aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md31
-rw-r--r--.github/ISSUE_TEMPLATE/feature_request.md20
-rw-r--r--.travis.yml1
-rw-r--r--Attorney_Online.pro6
-rw-r--r--include/aoapplication.h13
-rw-r--r--include/aoblipplayer.h3
-rw-r--r--include/aooptionsdialog.h2
-rw-r--r--include/aopacket.h7
-rw-r--r--include/aosfxplayer.h3
-rw-r--r--include/courtroom.h47
-rw-r--r--include/datatypes.h2
-rw-r--r--include/encryption_functions.h15
-rw-r--r--include/hex_functions.h16
-rw-r--r--include/lobby.h1
-rwxr-xr-xscripts/configure_ubuntu.sh3
-rw-r--r--src/aoblipplayer.cpp4
-rw-r--r--src/aocaseannouncerdialog.cpp2
-rw-r--r--src/aocharmovie.cpp13
-rw-r--r--src/aoemotebutton.cpp1
-rw-r--r--src/aoimage.cpp15
-rw-r--r--src/aomovie.cpp1
-rw-r--r--src/aomusicplayer.cpp22
-rw-r--r--src/aooptionsdialog.cpp33
-rw-r--r--src/aopacket.cpp72
-rw-r--r--src/aoscene.cpp1
-rw-r--r--src/aosfxplayer.cpp32
-rw-r--r--src/charselect.cpp13
-rw-r--r--src/courtroom.cpp707
-rw-r--r--src/debug_functions.cpp12
-rw-r--r--src/encryption_functions.cpp58
-rw-r--r--src/evidence.cpp9
-rw-r--r--src/hex_functions.cpp17
-rw-r--r--src/lobby.cpp27
-rw-r--r--src/main.cpp2
-rw-r--r--src/packet_distribution.cpp196
-rw-r--r--src/path_functions.cpp53
-rw-r--r--src/text_file_functions.cpp20
37 files changed, 862 insertions, 618 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 00000000..0e1e98c1
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,31 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Version:**
+ - OS: (e.g. Windows 10)
+ - Version or branch: (e.g. 2.8.5, master, ui-files, etc.)
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 00000000..bbcbbe7d
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.travis.yml b/.travis.yml
index 48bc2b56..802ace96 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,6 @@
language: cpp
os: osx
+osx_image: xcode12
addons:
homebrew:
update: true
diff --git a/Attorney_Online.pro b/Attorney_Online.pro
index d2c20624..5ee3f402 100644
--- a/Attorney_Online.pro
+++ b/Attorney_Online.pro
@@ -14,6 +14,10 @@ SOURCES += $$files($$PWD/src/*.cpp)
HEADERS += $$files($$PWD/include/*.h)
LIBS += -L$$PWD/lib
+QMAKE_LFLAGS += -Wl,-rpath,"'\$$ORIGIN/lib'"
+
+# Uncomment for verbose network logging
+# DEFINES += DEBUG_NETWORK
# Uncomment to enable Discord Rich Presence
# DEFINES += DISCORD
@@ -31,7 +35,7 @@ LIBS += -lbassopus
macx:LIBS += -framework CoreFoundation -framework Foundation -framework CoreServices
-CONFIG += c++14
+CONFIG += c++17
RESOURCES += resources.qrc
diff --git a/include/aoapplication.h b/include/aoapplication.h
index 458a8844..b17ac4a9 100644
--- a/include/aoapplication.h
+++ b/include/aoapplication.h
@@ -67,14 +67,10 @@ public:
/////////////////server metadata//////////////////
- unsigned int s_decryptor = 5;
- bool encryption_needed = true;
-
bool yellow_text_enabled = false;
bool prezoom_enabled = false;
bool flipping_enabled = false;
bool custom_objection_enabled = false;
- bool improved_loading_enabled = false;
bool desk_mod_enabled = false;
bool evidence_enabled = false;
bool cccc_ic_support_enabled = false;
@@ -84,6 +80,8 @@ public:
bool looping_sfx_support_enabled = false;
bool additive_enabled = false;
bool effects_enabled = false;
+ bool y_offset_enabled = false;
+ bool expanded_desk_mods_enabled = false;
///////////////loading info///////////////////
@@ -227,6 +225,9 @@ public:
// Returns whether the log should have a timestamp.
bool get_log_timestamp();
+ // Returns whether to log IC actions.
+ bool get_log_ic_actions();
+
// Returns the username the user may have set in config.ini.
QString get_default_username();
@@ -407,8 +408,8 @@ public:
// Returns the desk modifier for p_char's p_emote
int get_desk_mod(QString p_char, int p_emote);
- // Returns p_char's gender
- QString get_gender(QString p_char);
+ // Returns p_char's blips (previously called their "gender")
+ QString get_blips(QString p_char);
// ======
// These are all casing-related settings.
diff --git a/include/aoblipplayer.h b/include/aoblipplayer.h
index 4d3b5f14..a11e29db 100644
--- a/include/aoblipplayer.h
+++ b/include/aoblipplayer.h
@@ -22,12 +22,9 @@ public:
int m_cycle = 0;
private:
- const int max_blip_ms = 60;
-
QWidget *m_parent;
AOApplication *ao_app;
qreal m_volume;
- QElapsedTimer delay;
void set_volume_internal(qreal p_volume);
diff --git a/include/aooptionsdialog.h b/include/aooptionsdialog.h
index fe99626a..2e2d7b8a 100644
--- a/include/aooptionsdialog.h
+++ b/include/aooptionsdialog.h
@@ -52,6 +52,8 @@ private:
QSpinBox *ui_log_margin_spinbox;
QLabel *ui_log_timestamp_lbl;
QCheckBox *ui_log_timestamp_cb;
+ QLabel *ui_log_ic_actions_lbl;
+ QCheckBox *ui_log_ic_actions_cb;
QFrame *ui_log_names_divider;
QLineEdit *ui_username_textbox;
QLabel *ui_username_lbl;
diff --git a/include/aopacket.h b/include/aopacket.h
index 4097be86..6d1debad 100644
--- a/include/aopacket.h
+++ b/include/aopacket.h
@@ -8,21 +8,16 @@
class AOPacket {
public:
AOPacket(QString p_packet_string);
- AOPacket(QString header, QStringList &p_contents);
- ~AOPacket();
+ AOPacket(QString header, QStringList &p_contents) : m_header(header), m_contents(p_contents){}
QString get_header() { return m_header; }
QStringList &get_contents() { return m_contents; }
QString to_string();
- void encrypt_header(unsigned int p_key);
- void decrypt_header(unsigned int p_key);
-
void net_encode();
void net_decode();
private:
- bool encrypted = false;
QString m_header;
QStringList m_contents;
diff --git a/include/aosfxplayer.h b/include/aosfxplayer.h
index 0a5fffa8..75976368 100644
--- a/include/aosfxplayer.h
+++ b/include/aosfxplayer.h
@@ -16,8 +16,7 @@ public:
void clear();
void loop_clear();
- void play(QString p_sfx, QString p_char = "", QString shout = "",
- int channel = -1);
+ void play(QString p_sfx, QString p_char = "", QString shout = "");
void stop(int channel = -1);
void set_volume(qreal p_volume);
void set_looping(bool toggle, int channel = -1);
diff --git a/include/courtroom.h b/include/courtroom.h
index 72b4989c..e0db7195 100644
--- a/include/courtroom.h
+++ b/include/courtroom.h
@@ -59,6 +59,7 @@
#include <QTextCharFormat>
#include <QElapsedTimer>
+#include <algorithm>
#include <stack>
class AOApplication;
@@ -175,6 +176,9 @@ public:
// sets desk and bg based on pos in chatmessage
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
+ void set_self_offset(QString p_list);
+
// takes in serverD-formatted IP list as prints a converted version to server
// OOC admittedly poorly named
void set_ip_list(QString p_list);
@@ -226,14 +230,14 @@ public:
// selected
// or the user isn't already scrolled to the top
void append_ic_text(QString p_text, QString p_name = "", QString action = "",
- int color = 0);
+ int color = 0, QDateTime timestamp = QDateTime::currentDateTime());
// prints who played the song to IC chat and plays said song(if found on local
// filesystem) takes in a list where the first element is the song name and
// the second is the char id of who played it
void handle_song(QStringList *p_contents);
- void play_preanim(bool noninterrupting);
+ void play_preanim(bool immediate);
// plays the witness testimony or cross examination animation based on
// argument
@@ -259,6 +263,8 @@ public:
void set_clock_visibility(bool visible);
qint64 pong();
+ // Truncates text so it fits within theme-specified boundaries and sets the tooltip to the full string
+ void truncate_label_text(QWidget* p_widget, QString p_identifier);
~Courtroom();
private:
@@ -284,14 +290,17 @@ private:
bool message_is_centered = false;
int current_display_speed = 3;
- int message_display_speed[7] = {0, 10, 25, 40, 50, 70, 90};
+ int message_display_speed[7] = {5, 10, 25, 40, 50, 70, 90};
// The character ID of the character this user wants to appear alongside with.
int other_charid = -1;
- // The offset this user has given if they want to appear alongside someone.
+ // The horizontal offset this user has given if they want to appear alongside someone.
int char_offset = 0;
+ // The vertical offset this user has given.
+ int char_vert_offset = 0;
+
// 0 = in front, 1 = behind
int pair_order = 0;
@@ -325,7 +334,7 @@ private:
int real_tick_pos = 0;
// used to determine how often blips sound
int blip_ticker = 0;
- int blip_rate = 1;
+ int blip_rate = 2;
int rainbow_counter = 0;
bool rainbow_appended = false;
bool blank_blip = false;
@@ -342,6 +351,9 @@ private:
// True, if the log should display the message like name<br>text instead of name: text
bool log_newline = false;
+ // True, if the log should include RP actions like interjections, showing evidence, etc.
+ bool log_ic_actions = true;
+
// Margin in pixels between log entries for the IC log.
int log_margin = 0;
@@ -408,6 +420,11 @@ private:
int objection_state = 0;
QString objection_custom = "";
+ struct CustomObjection {
+ QString name;
+ QString filename;
+ };
+ QList<CustomObjection> custom_objections_list;
int realization_state = 0;
int screenshake_state = 0;
int text_color = 0;
@@ -422,6 +439,17 @@ private:
// List of associated RGB colors for this color index
QVector<QColor> color_rgb_list;
+ // Same as above but populated from misc/default's config
+ QVector<QColor> default_color_rgb_list;
+
+ // Get a color index from an arbitrary misc config
+ void gen_char_rgb_list(QString p_char);
+ QVector<QColor> char_color_rgb_list;
+
+ // Misc we used for the last message, and the one we're using now. Used to avoid loading assets when it's not needed
+ QString current_misc;
+ QString last_misc;
+
// List of markdown start characters, their index is tied to the color index
QStringList color_markdown_start_list;
@@ -438,8 +466,12 @@ private:
// List of all currently available pos
QStringList pos_dropdown_list;
+ // is the message we're about to send supposed to present evidence?
bool is_presenting_evidence = false;
+ // have we already presented evidence for this message?
+ bool evidence_presented = false;
+
QString effect = "";
// Music effect flags we want to send to server when we play music
@@ -536,6 +568,7 @@ private:
AOButton *ui_pair_button;
QListWidget *ui_pair_list;
QSpinBox *ui_pair_offset_spinbox;
+ QSpinBox *ui_pair_vert_offset_spinbox;
QComboBox *ui_pair_order_dropdown;
@@ -595,7 +628,7 @@ private:
QCheckBox *ui_guard;
QCheckBox *ui_casing;
- QCheckBox *ui_pre_non_interrupt;
+ QCheckBox *ui_immediate;
QCheckBox *ui_showname_enable;
AOButton *ui_custom_objection;
@@ -717,6 +750,7 @@ private slots:
void music_random();
void music_list_expand_all();
void music_list_collapse_all();
+ void music_stop();
void on_area_list_double_clicked(QTreeWidgetItem *p_item, int column);
void select_emote(int p_id);
@@ -790,6 +824,7 @@ private slots:
void on_log_limit_changed(int value);
void on_pair_offset_changed(int value);
+ void on_pair_vert_offset_changed(int value);
void on_ooc_toggle_clicked();
diff --git a/include/datatypes.h b/include/datatypes.h
index 21ade040..ebf2e380 100644
--- a/include/datatypes.h
+++ b/include/datatypes.h
@@ -91,7 +91,7 @@ enum CHAT_MESSAGE {
SELF_OFFSET,
OTHER_OFFSET,
OTHER_FLIP,
- NONINTERRUPTING_PRE,
+ IMMEDIATE,
LOOPING_SFX,
SCREENSHAKE,
FRAME_SCREENSHAKE,
diff --git a/include/encryption_functions.h b/include/encryption_functions.h
deleted file mode 100644
index b70e8e65..00000000
--- a/include/encryption_functions.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef ENCRYPTION_FUNCTIONS_H
-#define ENCRYPTION_FUNCTIONS_H
-
-#include <QString>
-
-#include <QVector>
-#include <cstddef>
-#include <iomanip>
-#include <sstream>
-#include <stdlib.h>
-
-QString fanta_encrypt(QString p_input, unsigned int key);
-QString fanta_decrypt(QString p_input, unsigned int key);
-
-#endif // ENCRYPTION_FUNCTIONS_H
diff --git a/include/hex_functions.h b/include/hex_functions.h
deleted file mode 100644
index d178ba1b..00000000
--- a/include/hex_functions.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef HEX_OPERATIONS_H
-#define HEX_OPERATIONS_H
-
-#include <algorithm>
-#include <bitset>
-#include <cstdint>
-#include <iomanip>
-#include <iostream>
-#include <sstream>
-#include <string>
-
-namespace omni {
-std::string int_to_hex(unsigned int input);
-}
-
-#endif // HEX_OPERATIONS_H
diff --git a/include/lobby.h b/include/lobby.h
index 42f52977..4278534c 100644
--- a/include/lobby.h
+++ b/include/lobby.h
@@ -46,6 +46,7 @@ public:
void set_loading_value(int p_value);
bool public_servers_selected = true;
+ bool doubleclicked = false;
~Lobby();
diff --git a/scripts/configure_ubuntu.sh b/scripts/configure_ubuntu.sh
index 280dfdf9..b010d36e 100755
--- a/scripts/configure_ubuntu.sh
+++ b/scripts/configure_ubuntu.sh
@@ -20,10 +20,13 @@ cd tmp
#get the bass prebuilt
curl http://www.un4seen.com/files/bass24-linux.zip -o bass_linux.zip
+curl http://www.un4seen.com/files/bassopus24-linux.zip -o bassopus_linux.zip
unzip bass_linux.zip
+unzip bassopus_linux.zip
cp x64/libbass.so ../../lib
+cp x64/libbassopus.so ../../lib
#get the discord-rpc prebuilt
curl -L https://github.com/discordapp/discord-rpc/releases/download/v3.4.0/discord-rpc-linux.zip -o discord_rpc_linux.zip
diff --git a/src/aoblipplayer.cpp b/src/aoblipplayer.cpp
index 5b4d625c..6607d463 100644
--- a/src/aoblipplayer.cpp
+++ b/src/aoblipplayer.cpp
@@ -26,10 +26,6 @@ void AOBlipPlayer::set_blips(QString p_sfx)
void AOBlipPlayer::blip_tick()
{
- if (delay.isValid() && delay.elapsed() < max_blip_ms)
- return;
-
- delay.start();
int f_cycle = m_cycle++;
if (m_cycle == 5)
diff --git a/src/aocaseannouncerdialog.cpp b/src/aocaseannouncerdialog.cpp
index d91433a6..aea6405d 100644
--- a/src/aocaseannouncerdialog.cpp
+++ b/src/aocaseannouncerdialog.cpp
@@ -3,7 +3,7 @@
AOCaseAnnouncerDialog::AOCaseAnnouncerDialog(QWidget *parent,
AOApplication *p_ao_app,
Courtroom *p_court)
- : QDialog(parent)
+ : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint)
{
ao_app = p_ao_app;
court = p_court;
diff --git a/src/aocharmovie.cpp b/src/aocharmovie.cpp
index 252aab5d..09a4b889 100644
--- a/src/aocharmovie.cpp
+++ b/src/aocharmovie.cpp
@@ -35,8 +35,8 @@ void AOCharMovie::load_image(QString p_char, QString p_emote,
ao_app->get_image_suffix(ao_app->get_character_path(
p_char, emote_prefix + "/" +
p_emote)), // Path check if it's categorized into a folder
- ao_app->get_character_path(
- p_char, p_emote + ".png"), // Non-animated path if emote_prefix fails
+ ao_app->get_image_suffix(ao_app->get_character_path(
+ p_char, p_emote)), // Just use the non-prefixed image, animated or not
ao_app->get_image_suffix(
ao_app->get_theme_path("placeholder")), // Theme placeholder path
ao_app->get_image_suffix(ao_app->get_default_theme_path(
@@ -61,6 +61,15 @@ void AOCharMovie::load_image(QString p_char, QString p_emote,
return;
m_reader->setFileName(emote_path);
+
+ // set format to apng if png supports animation
+ if (emote_path.endsWith("png")) {
+ m_reader->setFormat("apng");
+ if (!m_reader->supportsAnimation()) {
+ m_reader->setFormat("png");
+ }
+ }
+
QPixmap f_pixmap = this->get_pixmap(m_reader->read());
int f_delay = m_reader->nextImageDelay();
diff --git a/src/aoemotebutton.cpp b/src/aoemotebutton.cpp
index 90535607..652010d2 100644
--- a/src/aoemotebutton.cpp
+++ b/src/aoemotebutton.cpp
@@ -27,6 +27,7 @@ void AOEmoteButton::set_image(QString p_image, QString p_emote_comment)
}
else if (p_image.contains("_on") && file_exists(tmp_p_image.replace("_on", "_off"))) {
QImage tmpImage(tmp_p_image);
+ tmpImage = tmpImage.convertToFormat(QImage::Format_ARGB32);
QPoint p1, p2;
p2.setY(tmpImage.height());
diff --git a/src/aoimage.cpp b/src/aoimage.cpp
index 2663ba05..3977c979 100644
--- a/src/aoimage.cpp
+++ b/src/aoimage.cpp
@@ -2,6 +2,8 @@
#include "aoimage.h"
+#include <QBitmap>
+
AOImage::AOImage(QWidget *parent, AOApplication *p_ao_app) : QLabel(parent)
{
m_parent = parent;
@@ -29,9 +31,10 @@ bool AOImage::set_image(QString p_image)
}
QPixmap f_pixmap(final_image_path);
-
- this->setPixmap(
- f_pixmap.scaled(this->width(), this->height(), Qt::IgnoreAspectRatio));
+ f_pixmap =
+ f_pixmap.scaled(this->width(), this->height(), Qt::IgnoreAspectRatio);
+ this->setPixmap(f_pixmap);
+ this->setMask(f_pixmap.mask());
return true;
}
@@ -45,7 +48,9 @@ bool AOImage::set_chatbox(QString p_path)
QPixmap f_pixmap(p_path);
- this->setPixmap(
- f_pixmap.scaled(this->width(), this->height(), Qt::IgnoreAspectRatio));
+ f_pixmap =
+ f_pixmap.scaled(this->width(), this->height(), Qt::IgnoreAspectRatio);
+ this->setPixmap(f_pixmap);
+ this->setMask(f_pixmap.mask());
return true;
}
diff --git a/src/aomovie.cpp b/src/aomovie.cpp
index ac949219..196c1d3e 100644
--- a/src/aomovie.cpp
+++ b/src/aomovie.cpp
@@ -9,6 +9,7 @@ AOMovie::AOMovie(QWidget *p_parent, AOApplication *p_ao_app) : QLabel(p_parent)
ao_app = p_ao_app;
m_movie = new QMovie();
+ m_movie->setCacheMode(QMovie::CacheAll);
this->setMovie(m_movie);
diff --git a/src/aomusicplayer.cpp b/src/aomusicplayer.cpp
index 0c50d505..6219edfb 100644
--- a/src/aomusicplayer.cpp
+++ b/src/aomusicplayer.cpp
@@ -23,14 +23,26 @@ void AOMusicPlayer::play(QString p_song, int channel, bool loop,
unsigned int flags = BASS_STREAM_PRESCAN | BASS_STREAM_AUTOFREE |
BASS_UNICODE | BASS_ASYNCFILE;
- if (loop)
+ unsigned int streaming_flags = BASS_STREAM_AUTOFREE;
+ if (loop) {
flags |= BASS_SAMPLE_LOOP;
+ streaming_flags |= BASS_SAMPLE_LOOP;
+ }
DWORD newstream;
- if (f_path.endsWith(".opus"))
- newstream = BASS_OPUS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags);
- else
- newstream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags);
+ if (f_path.startsWith("http")) {
+ if (f_path.endsWith(".opus"))
+ newstream = BASS_OPUS_StreamCreateURL(f_path.toStdString().c_str(), 0, streaming_flags, nullptr, 0);
+ else
+ newstream = BASS_StreamCreateURL(f_path.toStdString().c_str(), 0, streaming_flags, nullptr, 0);
+
+ } else {
+ if (f_path.endsWith(".opus"))
+ newstream = BASS_OPUS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags);
+ else
+ newstream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags);
+ }
+
if (ao_app->get_audio_output_device() != "default")
BASS_ChannelSetDevice(m_stream_list[channel], BASS_GetDevice());
diff --git a/src/aooptionsdialog.cpp b/src/aooptionsdialog.cpp
index 6fc4d03e..314e9820 100644
--- a/src/aooptionsdialog.cpp
+++ b/src/aooptionsdialog.cpp
@@ -3,7 +3,7 @@
#include "bass.h"
AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
- : QDialog(parent)
+ : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint)
{
ao_app = p_ao_app;
@@ -41,7 +41,7 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
// Let's add the tabs one by one.
// First, we'll start with 'Gameplay'.
- ui_gameplay_tab = new QWidget();
+ ui_gameplay_tab = new QWidget(this);
ui_gameplay_tab->setSizePolicy(sizePolicy1);
ui_settings_tabs->addTab(ui_gameplay_tab, tr("Gameplay"));
ui_form_layout_widget = new QWidget(ui_gameplay_tab);
@@ -164,6 +164,19 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_log_timestamp_cb);
row += 1;
+ ui_log_ic_actions_lbl = new QLabel(ui_form_layout_widget);
+ ui_log_ic_actions_lbl->setText(tr("Log IC actions:"));
+ ui_log_ic_actions_lbl->setToolTip(
+ tr("If ticked, log will show IC actions such as shouting and presenting evidence."));
+
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_log_ic_actions_lbl);
+
+ ui_log_ic_actions_cb = new QCheckBox(ui_form_layout_widget);
+ ui_log_ic_actions_cb->setChecked(p_ao_app->get_log_ic_actions());
+
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_log_ic_actions_cb);
+
+ row += 1;
ui_log_names_divider = new QFrame(ui_form_layout_widget);
ui_log_names_divider->setFrameShape(QFrame::HLine);
ui_log_names_divider->setFrameShadow(QFrame::Sunken);
@@ -372,14 +385,14 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_customchat_cb);
- QScrollArea *scroll = new QScrollArea;
+ QScrollArea *scroll = new QScrollArea(this);
scroll->setWidget(ui_form_layout_widget);
ui_gameplay_tab->setLayout(new QVBoxLayout);
ui_gameplay_tab->layout()->addWidget(scroll);
ui_gameplay_tab->show();
// Here we start the callwords tab.
- ui_callwords_tab = new QWidget();
+ ui_callwords_tab = new QWidget(this);
ui_settings_tabs->addTab(ui_callwords_tab, tr("Callwords"));
ui_callwords_widget = new QWidget(ui_callwords_tab);
@@ -416,7 +429,7 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_callwords_layout->addWidget(ui_callwords_explain_lbl);
// The audio tab.
- ui_audio_tab = new QWidget();
+ ui_audio_tab = new QWidget(this);
ui_settings_tabs->addTab(ui_audio_tab, tr("Audio"));
ui_audio_widget = new QWidget(ui_audio_tab);
@@ -577,7 +590,7 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_audio_layout->setWidget(row, QFormLayout::FieldRole, ui_objectmusic_cb);
// The casing tab!
- ui_casing_tab = new QWidget();
+ ui_casing_tab = new QWidget(this);
ui_settings_tabs->addTab(ui_casing_tab, tr("Casing"));
ui_casing_widget = new QWidget(ui_casing_tab);
@@ -756,12 +769,16 @@ void AOOptionsDialog::save_pressed()
// Save everything into the config.ini.
QSettings *configini = ao_app->configini;
+ const bool audioChanged = ui_audio_device_combobox->currentText() !=
+ ao_app->get_audio_output_device();
+
configini->setValue("theme", ui_theme_combobox->currentText());
configini->setValue("log_goes_downwards", ui_downwards_cb->isChecked());
configini->setValue("log_maximum", ui_length_spinbox->value());
configini->setValue("log_newline", ui_log_newline_cb->isChecked());
configini->setValue("log_margin", ui_log_margin_spinbox->value());
configini->setValue("log_timestamp", ui_log_timestamp_cb->isChecked());
+ configini->setValue("log_ic_actions", ui_log_ic_actions_cb->isChecked());
configini->setValue("default_username", ui_username_textbox->text());
configini->setValue("show_custom_shownames", ui_showname_cb->isChecked());
configini->setValue("master", ui_ms_textbox->text());
@@ -806,7 +823,9 @@ void AOOptionsDialog::save_pressed()
configini->setValue("casing_can_host_cases",
ui_casing_cm_cases_textbox->text());
- ao_app->initBASS();
+ if (audioChanged)
+ ao_app->initBASS();
+
callwordsini->close();
done(0);
}
diff --git a/src/aopacket.cpp b/src/aopacket.cpp
index 6afd39e7..bb6ac73b 100644
--- a/src/aopacket.cpp
+++ b/src/aopacket.cpp
@@ -1,80 +1,30 @@
#include "aopacket.h"
-#include "encryption_functions.h"
-
AOPacket::AOPacket(QString p_packet_string)
{
QStringList packet_contents = p_packet_string.split("#");
- m_header = packet_contents.at(0);
-
- for (int n_string = 1; n_string < packet_contents.size() - 1; ++n_string) {
- m_contents.append(packet_contents.at(n_string));
- }
-}
-
-AOPacket::AOPacket(QString p_header, QStringList &p_contents)
-{
- m_header = p_header;
- m_contents = p_contents;
+ m_header = packet_contents.first();
+ m_contents = packet_contents.mid(1, packet_contents.size()-2); // trims %
}
-AOPacket::~AOPacket() {}
-
QString AOPacket::to_string()
{
- QString f_string = m_header;
-
- for (QString i_string : m_contents) {
- f_string += ("#" + i_string);
- }
-
- f_string += "#%";
-
- if (encrypted)
- return "#" + f_string;
- else
- return f_string;
-}
-
-void AOPacket::encrypt_header(unsigned int p_key)
-{
- m_header = fanta_encrypt(m_header, p_key);
-
- encrypted = true;
-}
-
-void AOPacket::decrypt_header(unsigned int p_key)
-{
- m_header = fanta_decrypt(m_header, p_key);
-
- encrypted = false;
+ return m_header + "#" + m_contents.join("#") + "#%";
}
void AOPacket::net_encode()
{
- for (int n_element = 0; n_element < m_contents.size(); ++n_element) {
- QString f_element = m_contents.at(n_element);
- f_element.replace("#", "<num>")
- .replace("%", "<percent>")
- .replace("$", "<dollar>")
- .replace("&", "<and>");
-
- m_contents.removeAt(n_element);
- m_contents.insert(n_element, f_element);
- }
+ m_contents.replaceInStrings("#", "<num>")
+ .replaceInStrings("%", "<percent>")
+ .replaceInStrings("$", "<dollar>")
+ .replaceInStrings("&", "<and>");
}
void AOPacket::net_decode()
{
- for (int n_element = 0; n_element < m_contents.size(); ++n_element) {
- QString f_element = m_contents.at(n_element);
- f_element.replace("<num>", "#")
- .replace("<percent>", "%")
- .replace("<dollar>", "$")
- .replace("<and>", "&");
-
- m_contents.removeAt(n_element);
- m_contents.insert(n_element, f_element);
- }
+ m_contents.replaceInStrings("<num>", "#")
+ .replaceInStrings("<percent>", "%")
+ .replaceInStrings("<dollar>", "$")
+ .replaceInStrings("<and>", "&");
}
diff --git a/src/aoscene.cpp b/src/aoscene.cpp
index 594013a1..78d69acd 100644
--- a/src/aoscene.cpp
+++ b/src/aoscene.cpp
@@ -7,6 +7,7 @@ AOScene::AOScene(QWidget *parent, AOApplication *p_ao_app) : QLabel(parent)
m_parent = parent;
ao_app = p_ao_app;
m_movie = new QMovie(this);
+ m_movie->setCacheMode(QMovie::CacheAll);
last_image = "";
}
diff --git a/src/aosfxplayer.cpp b/src/aosfxplayer.cpp
index 8c4f3c86..13de04fe 100644
--- a/src/aosfxplayer.cpp
+++ b/src/aosfxplayer.cpp
@@ -24,24 +24,30 @@ void AOSfxPlayer::loop_clear()
set_volume_internal(m_volume);
}
-void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout,
- int channel)
+void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout)
{
- if (channel == -1) {
- if (BASS_ChannelIsActive(m_stream_list[channel]) == BASS_ACTIVE_PLAYING)
- m_channel = (m_channel + 1) % m_channelmax;
- channel = m_channel;
+ for (int i = 0; i < m_channelmax; ++i) {
+ if (BASS_ChannelIsActive(m_stream_list[i]) == BASS_ACTIVE_PLAYING)
+ m_channel = (i + 1) % m_channelmax;
+ else {
+ m_channel = i;
+ break;
+ }
}
- BASS_ChannelStop(m_stream_list[channel]);
-
QString misc_path = "";
QString char_path = "";
+ QString theme_path = "";
QString sound_path = ao_app->get_sfx_suffix(ao_app->get_sounds_path(p_sfx));
- if (shout != "")
+ if (shout != "") {
misc_path = ao_app->get_sfx_suffix(ao_app->get_base_path() + "misc/" +
shout + "/" + p_sfx);
+ theme_path = ao_app->get_sfx_suffix(ao_app->get_theme_path(p_sfx));
+ if (!file_exists(theme_path))
+ theme_path =
+ ao_app->get_sfx_suffix(ao_app->get_default_theme_path(p_sfx));
+ }
if (p_char != "")
char_path =
ao_app->get_sfx_suffix(ao_app->get_character_path(p_char, p_sfx));
@@ -52,15 +58,17 @@ void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout,
f_path = char_path;
else if (file_exists(misc_path))
f_path = misc_path;
+ else if (shout != "" && file_exists(theme_path)) // only check here for shouts
+ f_path = theme_path;
else
f_path = sound_path;
if (f_path.endsWith(".opus"))
- m_stream_list[channel] = BASS_OPUS_StreamCreateFile(
+ m_stream_list[m_channel] = BASS_OPUS_StreamCreateFile(
FALSE, f_path.utf16(), 0, 0,
BASS_STREAM_AUTOFREE | BASS_UNICODE | BASS_ASYNCFILE);
else
- m_stream_list[channel] = BASS_StreamCreateFile(
+ m_stream_list[m_channel] = BASS_StreamCreateFile(
FALSE, f_path.utf16(), 0, 0,
BASS_STREAM_AUTOFREE | BASS_UNICODE | BASS_ASYNCFILE);
@@ -74,7 +82,7 @@ void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout,
}
BASS_ChannelPlay(m_stream_list[m_channel], false);
- BASS_ChannelSetSync(m_stream_list[channel], BASS_SYNC_DEV_FAIL, 0,
+ BASS_ChannelSetSync(m_stream_list[m_channel], BASS_SYNC_DEV_FAIL, 0,
ao_app->BASSreset, 0);
}
diff --git a/src/charselect.cpp b/src/charselect.cpp
index 8e0aab5e..33cc5176 100644
--- a/src/charselect.cpp
+++ b/src/charselect.cpp
@@ -7,6 +7,8 @@
void Courtroom::construct_char_select()
{
+ this->setWindowFlags( (this->windowFlags() | Qt::CustomizeWindowHint) & ~Qt::WindowMaximizeButtonHint);
+
ui_char_select_background = new AOImage(this, ao_app);
ui_char_buttons = new QWidget(ui_char_select_background);
@@ -60,6 +62,9 @@ void Courtroom::construct_char_select()
SLOT(on_char_passworded_clicked()));
connect(ui_char_taken, SIGNAL(stateChanged(int)), this,
SLOT(on_char_taken_clicked()));
+
+ truncate_label_text(ui_char_taken, "char_taken");
+ truncate_label_text(ui_char_passworded, "char_passworded");
}
void Courtroom::set_char_select()
@@ -72,10 +77,10 @@ void Courtroom::set_char_select()
if (f_charselect.width < 0 || f_charselect.height < 0) {
qDebug() << "W: did not find char_select width or height in "
"courtroom_design.ini!";
- this->resize(714, 668);
+ this->setFixedSize(714, 668);
}
else
- this->resize(f_charselect.width, f_charselect.height);
+ this->setFixedSize(f_charselect.width, f_charselect.height);
ui_char_select_background->resize(f_charselect.width, f_charselect.height);
ui_char_select_background->set_image("charselect_background");
@@ -131,7 +136,7 @@ void Courtroom::char_clicked(int n_char)
qDebug() << "char_ini_path" << char_ini_path;
if (!file_exists(char_ini_path)) {
- call_notice("Could not find " + char_ini_path);
+ call_error("Could not find " + char_ini_path);
return;
}
}
@@ -146,8 +151,6 @@ void Courtroom::char_clicked(int n_char)
else
update_character(n_char);
- enter_courtroom();
-
if (n_char != -1)
ui_ic_chat_name->setPlaceholderText(char_list.at(n_char).name);
}
diff --git a/src/courtroom.cpp b/src/courtroom.cpp
index c2fcf9b8..962c04f3 100644
--- a/src/courtroom.cpp
+++ b/src/courtroom.cpp
@@ -3,6 +3,10 @@
Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
{
ao_app = p_ao_app;
+
+ this->setWindowFlags((this->windowFlags() | Qt::CustomizeWindowHint) &
+ ~Qt::WindowMaximizeButtonHint);
+
ao_app->initBASS();
qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000));
@@ -210,9 +214,9 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
ui_showname_enable->setChecked(ao_app->get_showname_enabled_by_default());
ui_showname_enable->setText(tr("Shownames"));
- ui_pre_non_interrupt = new QCheckBox(this);
- ui_pre_non_interrupt->setText(tr("No Interrupt"));
- ui_pre_non_interrupt->hide();
+ ui_immediate = new QCheckBox(this);
+ ui_immediate->setText(tr("No Interrupt"));
+ ui_immediate->hide();
ui_custom_objection = new AOButton(this, ao_app);
ui_custom_objection->setContextMenuPolicy(Qt::CustomContextMenu);
@@ -246,7 +250,10 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
ui_pair_list = new QListWidget(this);
ui_pair_offset_spinbox = new QSpinBox(this);
ui_pair_offset_spinbox->setRange(-100, 100);
- ui_pair_offset_spinbox->setSuffix(tr("% offset"));
+ ui_pair_offset_spinbox->setSuffix(tr("% x offset"));
+ ui_pair_vert_offset_spinbox = new QSpinBox(this);
+ ui_pair_vert_offset_spinbox->setRange(-100, 100);
+ ui_pair_vert_offset_spinbox->setSuffix(tr("% y offset"));
ui_pair_order_dropdown = new QComboBox(this);
ui_pair_order_dropdown->addItem(tr("To front"));
@@ -390,6 +397,8 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
SLOT(on_pair_list_clicked(QModelIndex)));
connect(ui_pair_offset_spinbox, SIGNAL(valueChanged(int)), this,
SLOT(on_pair_offset_changed(int)));
+ connect(ui_pair_vert_offset_spinbox, SIGNAL(valueChanged(int)), this,
+ SLOT(on_pair_vert_offset_changed(int)));
connect(ui_pair_order_dropdown, SIGNAL(currentIndexChanged(int)), this,
SLOT(on_pair_order_dropdown_changed(int)));
@@ -450,13 +459,13 @@ void Courtroom::set_widgets()
if (f_courtroom.width < 0 || f_courtroom.height < 0) {
qDebug() << "W: did not find courtroom width or height in " << filename;
- this->resize(714, 668);
+ this->setFixedSize(714, 668);
}
else {
m_courtroom_width = f_courtroom.width;
m_courtroom_height = f_courtroom.height;
- this->resize(f_courtroom.width, f_courtroom.height);
+ this->setFixedSize(f_courtroom.width, f_courtroom.height);
}
set_fonts();
@@ -472,14 +481,14 @@ void Courtroom::set_widgets()
// if needed.
if (ao_app->cccc_ic_support_enabled) {
ui_pair_button->show();
- ui_pre_non_interrupt->show();
+ ui_immediate->show();
ui_showname_enable->show();
ui_ic_chat_name->show();
ui_ic_chat_name->setEnabled(true);
}
else {
ui_pair_button->hide();
- ui_pre_non_interrupt->hide();
+ ui_immediate->hide();
ui_showname_enable->hide();
ui_ic_chat_name->hide();
ui_ic_chat_name->setEnabled(false);
@@ -556,7 +565,11 @@ void Courtroom::set_widgets()
log_maximum_blocks = ao_app->get_max_log_size();
- bool regenerate = log_goes_downwards != ao_app->get_log_goes_downwards() || log_colors != ao_app->is_colorlog_enabled() || log_newline != ao_app->get_log_newline() || log_margin != ao_app->get_log_margin() || log_timestamp != ao_app->get_log_timestamp();
+ bool regenerate = log_goes_downwards != ao_app->get_log_goes_downwards() ||
+ log_colors != ao_app->is_colorlog_enabled() ||
+ log_newline != ao_app->get_log_newline() ||
+ log_margin != ao_app->get_log_margin() ||
+ log_timestamp != ao_app->get_log_timestamp();
log_goes_downwards = ao_app->get_log_goes_downwards();
log_colors = ao_app->is_colorlog_enabled();
log_newline = ao_app->get_log_newline();
@@ -567,7 +580,8 @@ void Courtroom::set_widgets()
set_size_and_pos(ui_ic_chatlog, "ic_chatlog");
ui_ic_chatlog->setFrameShape(QFrame::NoFrame);
- ui_ic_chatlog->setPlaceholderText(log_goes_downwards ? "▼ Log goes down ▼" : "▲ Log goes up ▲");
+ ui_ic_chatlog->setPlaceholderText(log_goes_downwards ? "▼ Log goes down ▼"
+ : "▲ Log goes up ▲");
set_size_and_pos(ui_ms_chatlog, "ms_chatlog");
ui_ms_chatlog->setFrameShape(QFrame::NoFrame);
@@ -585,12 +599,20 @@ void Courtroom::set_widgets()
set_size_and_pos(ui_pair_offset_spinbox, "pair_offset_spinbox");
ui_pair_offset_spinbox->hide();
ui_pair_offset_spinbox->setToolTip(
- tr("Change the percentage offset of your character's position from the "
+ tr("Change the horizontal percentage offset of your character's position "
+ "from the "
+ "center of the screen."));
+
+ set_size_and_pos(ui_pair_vert_offset_spinbox, "pair_vert_offset_spinbox");
+ ui_pair_vert_offset_spinbox->hide();
+ ui_pair_vert_offset_spinbox->setToolTip(
+ tr("Change the vertical percentage offset of your character's position "
+ "from the "
"center of the screen."));
ui_pair_order_dropdown->hide();
set_size_and_pos(ui_pair_order_dropdown, "pair_order_dropdown");
- ui_pair_offset_spinbox->setToolTip(
+ ui_pair_order_dropdown->setToolTip(
tr("Change the order of appearance for your character."));
set_size_and_pos(ui_pair_button, "pair_button");
@@ -684,7 +706,7 @@ void Courtroom::set_widgets()
tr("Set an 'iniswap', or an alternative character folder to refer to "
"from your current character.\n"
"Edit by typing and pressing Enter, [X] to remove. This saves to your "
- "base/characters/<charname>/iniswaps.ini"));
+ "base/iniswaps.ini"));
set_size_and_pos(ui_iniswap_remove, "iniswap_remove");
ui_iniswap_remove->setText("X");
@@ -706,11 +728,11 @@ void Courtroom::set_widgets()
set_size_and_pos(ui_sfx_remove, "sfx_remove");
ui_sfx_remove->setText("X");
ui_sfx_remove->set_image("evidencex");
- ui_sfx_remove->setToolTip(
- tr("Remove the currently selected iniswap from the list and return to "
- "the original character folder."));
+ ui_sfx_remove->setToolTip(tr("Remove the currently selected sound effect."));
ui_sfx_remove->hide();
+ set_iniswap_dropdown();
+
set_size_and_pos(ui_effects_dropdown, "effects_dropdown");
ui_effects_dropdown->setInsertPolicy(QComboBox::InsertAtBottom);
ui_effects_dropdown->setToolTip(
@@ -823,11 +845,23 @@ void Courtroom::set_widgets()
ui_pre->setToolTip(
tr("Play a single-shot animation as defined by the emote when checked."));
- set_size_and_pos(ui_pre_non_interrupt, "pre_no_interrupt");
- ui_pre_non_interrupt->setToolTip(
+ ui_immediate->setToolTip(
tr("If preanim is checked, display the input text immediately as the "
"animation plays concurrently."));
+ design_ini_result =
+ ao_app->get_element_dimensions("immediate", "courtroom_design.ini");
+ // If we don't have new-style naming, fall back to the old method
+ if (design_ini_result.width < 0 || design_ini_result.height < 0) {
+ set_size_and_pos(ui_immediate, "pre_no_interrupt");
+ truncate_label_text(ui_immediate, "pre_no_interrupt");
+ }
+ else {// Adopt the based new method instead
+ set_size_and_pos(ui_immediate, "immediate");
+ truncate_label_text(ui_immediate, "immediate");
+ }
+
+
set_size_and_pos(ui_flip, "flip");
ui_flip->setToolTip(tr("Mirror your character's emotes when checked."));
@@ -922,6 +956,17 @@ void Courtroom::set_widgets()
ui_spectator->setToolTip(tr("Become a spectator. You won't be able to "
"interact with the in-character screen."));
+ // QCheckBox
+ truncate_label_text(ui_guard, "guard");
+ truncate_label_text(ui_pre, "pre");
+ truncate_label_text(ui_flip, "flip");
+ truncate_label_text(ui_showname_enable, "showname_enable");
+
+ // QLabel
+ truncate_label_text(ui_music_label, "music_label");
+ truncate_label_text(ui_sfx_label, "sfx_label");
+ truncate_label_text(ui_blip_label, "blip_label");
+
free_brush =
QBrush(ao_app->get_color("area_free_color", "courtroom_design.ini"));
lfp_brush =
@@ -1133,14 +1178,18 @@ void Courtroom::set_background(QString p_background, bool display)
// Populate the dropdown list with all pos that exist on this bg
QStringList pos_list = {};
for (QString key : default_pos.keys()) {
- if (file_exists(
- ao_app->get_image_suffix(ao_app->get_background_path(key)))) {
+ if (file_exists(ao_app->get_image_suffix(
+ ao_app->get_background_path(default_pos[key]))) || // if we have 2.8-style positions, e.g. def.png, wit.webp, hld.apng
+ file_exists(
+ ao_app->get_image_suffix(ao_app->get_background_path(key)))) { // if we have pre-2.8-style positions, e.g. defenseempty.png
pos_list.append(default_pos[key]);
}
}
-
- // TODO: search through extra/custom pos and add them to the pos dropdown as
- // well
+ for (QString pos : ao_app->read_design_ini("positions", ao_app->get_background_path("design.ini")).split(",")) {
+ if (file_exists(ao_app->get_image_suffix(ao_app->get_background_path(pos)))) {
+ pos_list.append(pos);
+ }
+ }
set_pos_dropdown(pos_list);
@@ -1287,10 +1336,16 @@ void Courtroom::update_character(int p_cid)
if (ao_app->custom_objection_enabled) // if setting is enabled
{
custom_obj_menu->clear();
+ custom_objections_list.clear();
if (file_exists(ao_app->get_image_suffix(
ao_app->get_character_path(current_char, "custom")))) {
ui_custom_objection->show();
- QAction *action = custom_obj_menu->addAction("Default");
+ QString custom_name = ao_app->read_char_ini(f_char, "custom_name", "Shouts");
+ QAction *action;
+ if (custom_name != "")
+ action = custom_obj_menu->addAction(custom_name);
+ else
+ action = custom_obj_menu->addAction("Default");
custom_obj_menu->setDefaultAction(action);
objection_custom = "";
}
@@ -1305,11 +1360,23 @@ void Courtroom::update_character(int p_cid)
<< "*.webp",
QDir::Files);
for (const QString &filename : custom_obj) {
- QAction *action = custom_obj_menu->addAction(filename);
+ CustomObjection custom_objection;
+ custom_objection.filename = filename;
+ QString custom_name = ao_app->read_char_ini(f_char, filename.split(".")[0] + "_name", "Shouts");
+ QAction *action;
+ if (custom_name != "") {
+ custom_objection.name = custom_name;
+ action = custom_obj_menu->addAction(custom_name);
+ }
+ else {
+ custom_objection.name = filename.split(".")[0];
+ action = custom_obj_menu->addAction(filename.split(".")[0]);
+ }
if (custom_obj_menu->defaultAction() == nullptr) {
custom_obj_menu->setDefaultAction(action);
- objection_custom = action->text();
+ objection_custom = custom_objection.filename;
}
+ custom_objections_list.append(custom_objection);
}
}
}
@@ -1320,6 +1387,9 @@ void Courtroom::update_character(int p_cid)
ui_char_select_background->hide();
ui_ic_chat_message->setEnabled(m_cid != -1);
ui_ic_chat_message->setFocus();
+ // have to call these to make sure sfx and blips don't get accidentally muted forever when we change characters
+ sfx_player->set_volume(ui_sfx_slider->value());
+ blip_player->set_volume(ui_blip_slider->value());
}
void Courtroom::enter_courtroom()
@@ -1532,6 +1602,9 @@ void Courtroom::on_chat_return_pressed()
if ((anim_state < 3 || text_state < 2) && objection_state == 0)
return;
+ ui_ic_chat_message->blockSignals(true);
+ QTimer::singleShot(600, this,
+ [=] { ui_ic_chat_message->blockSignals(false); });
// MS#
// deskmod#
// pre-emote#
@@ -1554,7 +1627,7 @@ void Courtroom::on_chat_return_pressed()
// showname#
// other_charid#
// self_offset#
- // noninterrupting_preanim#%
+ // immediate_preanim#%
QStringList packet_contents;
@@ -1566,6 +1639,12 @@ void Courtroom::on_chat_return_pressed()
if (ao_app->desk_mod_enabled) {
f_desk_mod =
QString::number(ao_app->get_desk_mod(current_char, current_emote));
+ if (!ao_app->expanded_desk_mods_enabled) {
+ if (f_desk_mod == "2" || f_desk_mod == "4")
+ f_desk_mod = "0";
+ else if (f_desk_mod == "3" || f_desk_mod == "5")
+ f_desk_mod = "1";
+ }
if (f_desk_mod == "-1")
f_desk_mod = "chat";
}
@@ -1583,7 +1662,7 @@ void Courtroom::on_chat_return_pressed()
packet_contents.append(current_side);
packet_contents.append(get_char_sfx());
- if (ui_pre->isChecked() && !ao_app->is_stickysounds_enabled()) {
+ if (ui_pre->isChecked() && !ao_app->is_stickysounds_enabled() && ui_sfx_dropdown->currentIndex() > 1) {
ui_sfx_dropdown->blockSignals(true);
ui_sfx_dropdown->setCurrentIndex(0);
ui_sfx_dropdown->blockSignals(false);
@@ -1593,15 +1672,13 @@ void Courtroom::on_chat_return_pressed()
int f_emote_mod = ao_app->get_emote_mod(current_char, current_emote);
// needed or else legacy won't understand what we're saying
- if (objection_state > 0) {
- if (ui_pre->isChecked()) {
- if (f_emote_mod == 4 || f_emote_mod == 5)
- f_emote_mod = 6;
- else
- f_emote_mod = 2;
- }
+ if (objection_state > 0 && ui_pre->isChecked()) {
+ if (f_emote_mod == 4 || f_emote_mod == 5)
+ f_emote_mod = 6;
+ else
+ f_emote_mod = 2;
}
- else if (ui_pre->isChecked() && !ui_pre_non_interrupt->isChecked()) {
+ else if (ui_pre->isChecked() && !ui_immediate->isChecked()) {
if (f_emote_mod == 0)
f_emote_mod = 1;
else if (f_emote_mod == 5 && ao_app->prezoom_enabled)
@@ -1691,10 +1768,13 @@ void Courtroom::on_chat_return_pressed()
packet_contents.append("-1");
}
// Send the offset as it's gonna be used regardless
- packet_contents.append(QString::number(char_offset));
+ if(ao_app->y_offset_enabled)
+ packet_contents.append(QString::number(char_offset) + "&" + QString::number(char_vert_offset));
+ else
+ packet_contents.append(QString::number(char_offset));
// Finally, we send over if we want our pres to not interrupt.
- if (ui_pre_non_interrupt->isChecked() && ui_pre->isChecked()) {
+ if (ui_immediate->isChecked() && ui_pre->isChecked()) {
packet_contents.append("1");
}
else {
@@ -1759,6 +1839,7 @@ void Courtroom::reset_ic()
ui_vp_chat_arrow->stop();
text_state = 0;
anim_state = 0;
+ evidence_presented = false;
ui_vp_objection->stop();
chat_tick_timer->stop();
ui_vp_evidence_display->reset();
@@ -1792,6 +1873,7 @@ void Courtroom::handle_chatmessage(QStringList *p_contents)
if (p_contents->size() < MS_MINIMUM)
return;
+ int prev_char_id = m_chatmessage[CHAR_ID].toInt();
for (int n_string = 0; n_string < MS_MAXIMUM; ++n_string) {
// Note that we have added stuff that vanilla clients and servers simply
// won't send. So now, we have to check if the thing we want even exists
@@ -1859,34 +1941,36 @@ void Courtroom::handle_chatmessage(QStringList *p_contents)
{
m_chatmessage[MESSAGE] = ""; // Turn it into true blankpost
}
-
- if (!m_chatmessage[MESSAGE].isEmpty() || ic_chatlog_history.isEmpty() || ic_chatlog_history.last().get_message() != "")
- {
- log_ic_text(f_charname, f_displayname, m_chatmessage[MESSAGE], "",
- m_chatmessage[TEXT_COLOR].toInt());
- append_ic_text(m_chatmessage[MESSAGE], f_displayname, "",
- m_chatmessage[TEXT_COLOR].toInt());
- }
-
+
QString f_char = m_chatmessage[CHAR_NAME];
QString f_custom_theme = ao_app->get_char_shouts(f_char);
// if an objection is used
if (objection_mod <= 4 && objection_mod >= 1) {
+ QString shout_message;
switch (objection_mod) {
case 1:
ui_vp_objection->play("holdit_bubble", f_char, f_custom_theme, 724);
objection_player->play("holdit", f_char, f_custom_theme);
+ shout_message = ao_app->read_char_ini(f_char, "holdit_message", "Shouts");
+ if (shout_message == "")
+ shout_message = tr("HOLD IT!");
break;
case 2:
ui_vp_objection->play("objection_bubble", f_char, f_custom_theme, 724);
objection_player->play("objection", f_char, f_custom_theme);
+ shout_message = ao_app->read_char_ini(f_char, "objection_message", "Shouts");
+ if (shout_message == "")
+ shout_message = tr("OBJECTION!");
if (ao_app->objection_stop_music())
music_player->stop();
break;
case 3:
ui_vp_objection->play("takethat_bubble", f_char, f_custom_theme, 724);
objection_player->play("takethat", f_char, f_custom_theme);
+ shout_message = ao_app->read_char_ini(f_char, "takethat_message", "Shouts");
+ if (shout_message == "")
+ shout_message = tr("TAKE THAT!");
break;
// case 4 is AO2 only
case 4:
@@ -1896,19 +1980,36 @@ void Courtroom::handle_chatmessage(QStringList *p_contents)
objection_player->play("custom_objections/" +
custom_objection.split('.')[0],
f_char, f_custom_theme);
+ shout_message = ao_app->read_char_ini(f_char, custom_objection.split('.')[0] + "_message", "Shouts");
+ if (shout_message == "")
+ shout_message = custom_objection.split('.')[0];
}
else {
ui_vp_objection->play("custom", f_char, f_custom_theme,
shout_stay_time);
objection_player->play("custom", f_char, f_custom_theme);
+ shout_message = ao_app->read_char_ini(f_char, "custom_message", "Shouts");
+ if (shout_message == "")
+ shout_message = tr("CUSTOM OBJECTION!");
}
m_chatmessage[EMOTE_MOD] = 1;
break;
}
+ log_ic_text(f_char, f_displayname, shout_message,
+ tr("shouts"),2);
+ append_ic_text(shout_message, f_displayname, tr("shouts"));
sfx_player->clear(); // Objection played! Cut all sfx.
}
else
handle_chatmessage_2();
+
+ if (!m_chatmessage[MESSAGE].isEmpty() || ic_chatlog_history.isEmpty() ||
+ ic_chatlog_history.last().get_message() != "") {
+ log_ic_text(f_charname, f_displayname, m_chatmessage[MESSAGE], "",
+ m_chatmessage[TEXT_COLOR].toInt());
+ append_ic_text(m_chatmessage[MESSAGE], f_displayname, "",
+ m_chatmessage[TEXT_COLOR].toInt());
+ }
}
void Courtroom::objection_done() { handle_chatmessage_2(); }
@@ -2048,8 +2149,6 @@ void Courtroom::handle_chatmessage_2()
f_pointsize = chatsize;
set_font(ui_vp_message, "", "message", customchar, font_name, f_pointsize);
- set_scene(m_chatmessage[DESK_MOD], m_chatmessage[SIDE]);
-
int emote_mod = m_chatmessage[EMOTE_MOD].toInt();
// Deal with invalid emote modifiers
if (emote_mod != 0 && emote_mod != 1 && emote_mod != 2 && emote_mod != 5 &&
@@ -2081,10 +2180,20 @@ void Courtroom::handle_chatmessage_2()
if (got_other_charid > -1) {
// If there is, show them!
ui_vp_sideplayer_char->show();
-
- int other_offset = m_chatmessage[OTHER_OFFSET].toInt();
+ QStringList other_offsets = m_chatmessage[OTHER_OFFSET].split("&");
+ int other_offset;
+ int other_offset_v;
+ if (other_offsets.length() <= 1) {
+ other_offset = m_chatmessage[OTHER_OFFSET].toInt();
+ other_offset_v = 0;
+ }
+ else {
+ other_offset = other_offsets[0].toInt();
+ other_offset_v = other_offsets[1].toInt();
+ }
ui_vp_sideplayer_char->move(ui_viewport->width() * other_offset / 100,
- 0);
+ ui_viewport->height() * other_offset_v /
+ 100);
QStringList args = m_chatmessage[OTHER_CHARID].split("^");
if (args.size() >
@@ -2123,13 +2232,32 @@ void Courtroom::handle_chatmessage_2()
}
// Set ourselves according to SELF_OFFSET
- bool ok;
- int self_offset = m_chatmessage[SELF_OFFSET].toInt(&ok);
- if (ok)
- ui_vp_player_char->move(ui_viewport->width() * self_offset / 100, 0);
+ 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
- ui_vp_player_char->move(0, 0);
+ self_offset_v = self_offsets[1].toInt();
+ ui_vp_player_char->move(ui_viewport->width() * self_offset / 100,
+ ui_viewport->height() * self_offset_v / 100);
+ switch(m_chatmessage[DESK_MOD].toInt()) {
+ case 4:
+ ui_vp_sideplayer_char->hide();
+ ui_vp_player_char->move(0, 0);
+ [[fallthrough]];
+ case 2:
+ set_scene("0", m_chatmessage[SIDE]);
+ break;
+ case 5:
+ case 3:
+ set_scene("1", m_chatmessage[SIDE]);
+ break;
+ default:
+ set_scene(m_chatmessage[DESK_MOD], m_chatmessage[SIDE]);
+ break;
+ }
switch (emote_mod) {
case 1:
case 2:
@@ -2138,7 +2266,7 @@ void Courtroom::handle_chatmessage_2()
break;
case 0:
case 5:
- if (m_chatmessage[NONINTERRUPTING_PRE].toInt() == 0)
+ if (m_chatmessage[IMMEDIATE].toInt() == 0)
handle_chatmessage_3();
else
play_preanim(true);
@@ -2251,7 +2379,8 @@ void Courtroom::handle_chatmessage_3()
.isEmpty()) // Pure whitespace showname, get outta here.
f_showname = m_chatmessage[CHAR_NAME];
- if (f_evi_id > 0 && f_evi_id <= local_evidence_list.size()) {
+ if (f_evi_id > 0 && f_evi_id <= local_evidence_list.size() &&
+ !evidence_presented) {
// shifted by 1 because 0 is no evidence per legacy standards
QString f_image = local_evidence_list.at(f_evi_id - 1).image;
QString f_evi_name = local_evidence_list.at(f_evi_id - 1).name;
@@ -2260,16 +2389,38 @@ void Courtroom::handle_chatmessage_3()
f_side == "jud" || f_side == "jur");
ui_vp_evidence_display->show_evidence(f_image, is_left_side,
ui_sfx_slider->value());
-
- log_ic_text(m_chatmessage[CHAR_NAME], m_chatmessage[SHOWNAME], f_evi_name, tr("has presented evidence"),
- m_chatmessage[TEXT_COLOR].toInt());
- append_ic_text(f_evi_name, f_showname, tr("has presented evidence"));
+ if (log_ic_actions) {
+ log_ic_text(m_chatmessage[CHAR_NAME], m_chatmessage[SHOWNAME], f_evi_name,
+ tr("has presented evidence"),
+ m_chatmessage[TEXT_COLOR].toInt());
+ append_ic_text(f_evi_name, f_showname, tr("has presented evidence"));
+ }
+ evidence_presented = true; // we're done presenting evidence, and we
+ // don't want to do it twice
}
int emote_mod = m_chatmessage[EMOTE_MOD].toInt();
QString side = m_chatmessage[SIDE];
+ switch(m_chatmessage[DESK_MOD].toInt()) {
+ case 4:
+ set_self_offset(m_chatmessage[SELF_OFFSET]);
+ [[fallthrough]];
+ case 2:
+ set_scene("1", m_chatmessage[SIDE]);
+ break;
+ case 5:
+ ui_vp_sideplayer_char->hide();
+ ui_vp_player_char->move(0, 0);
+ [[fallthrough]];
+ case 3:
+ set_scene("0", m_chatmessage[SIDE]);
+ break;
+ default:
+ set_scene(m_chatmessage[DESK_MOD], m_chatmessage[SIDE]);
+ break;
+ }
if (emote_mod == 5 || emote_mod == 6) {
ui_vp_desk->hide();
ui_vp_legacy_desk->hide();
@@ -2358,9 +2509,7 @@ QString Courtroom::filter_ic_text(QString p_text, bool html, int target_pos,
// If html is enabled, prepare this text to be all ready for it.
if (html) {
ic_color_stack.push(default_color);
- QString appendage = "<font color=\"" +
- color_rgb_list.at(default_color).name(QColor::HexRgb) +
- "\">";
+ QString appendage = "<font color=\"$c" + QString::number(default_color) + "\">";
if (!align.isEmpty())
appendage.prepend("<div align=" + align + ">");
@@ -2479,8 +2628,7 @@ QString Courtroom::filter_ic_text(QString p_text, bool html, int target_pos,
if (!ic_color_stack.empty())
appendage +=
- "<font color=\"" +
- color_rgb_list.at(ic_color_stack.top()).name(QColor::HexRgb) +
+ "<font color=\"$c" + QString::number(ic_color_stack.top()) +
"\">";
if (is_end && !skip) {
@@ -2568,10 +2716,9 @@ QString Courtroom::filter_ic_text(QString p_text, bool html, int target_pos,
}
void Courtroom::log_ic_text(QString p_name, QString p_showname,
- QString p_message, QString p_action, int p_color)
+ QString p_message, QString p_action, int p_color)
{
- chatlogpiece log_entry(p_name, p_showname, p_message, p_action,
- p_color);
+ chatlogpiece log_entry(p_name, p_showname, p_message, p_action, p_color);
ic_chatlog_history.append(log_entry);
if (ao_app->get_auto_logging_enabled())
ao_app->append_to_file(log_entry.get_full(), ao_app->log_filename, true);
@@ -2583,7 +2730,7 @@ void Courtroom::log_ic_text(QString p_name, QString p_showname,
}
void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action,
- int color)
+ int color, QDateTime timestamp)
{
QTextCharFormat bold;
QTextCharFormat normal;
@@ -2596,9 +2743,12 @@ void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action,
const QTextCursor old_cursor = ui_ic_chatlog->textCursor();
const int old_scrollbar_value = ui_ic_chatlog->verticalScrollBar()->value();
const bool need_newline = !ui_ic_chatlog->document()->isEmpty();
- const int scrollbar_target_value = log_goes_downwards ? ui_ic_chatlog->verticalScrollBar()->maximum() : ui_ic_chatlog->verticalScrollBar()->minimum();
+ const int scrollbar_target_value =
+ log_goes_downwards ? ui_ic_chatlog->verticalScrollBar()->maximum()
+ : ui_ic_chatlog->verticalScrollBar()->minimum();
- ui_ic_chatlog->moveCursor(log_goes_downwards ? QTextCursor::End : QTextCursor::Start);
+ ui_ic_chatlog->moveCursor(log_goes_downwards ? QTextCursor::End
+ : QTextCursor::Start);
// Only prepend with newline if log goes downwards
if (log_goes_downwards && need_newline) {
@@ -2606,18 +2756,37 @@ void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action,
}
// Timestamp if we're doing that meme
- if (log_timestamp)
- ui_ic_chatlog->textCursor().insertText("[" + QDateTime::currentDateTime().toString("h:mm:ss AP") + "] ", normal);
+ if (log_timestamp) {
+ if (timestamp.isValid()) {
+ ui_ic_chatlog->textCursor().insertText(
+ "[" + timestamp.toString("h:mm:ss AP") + "] ", normal);
+ } else {
+ qDebug() << "could not insert invalid timestamp";
+ }
+ }
// Format the name of the actor
ui_ic_chatlog->textCursor().insertText(p_name, bold);
+ // Special case for stopping the music
+ if (p_action == tr("has stopped the music")) {
+ ui_ic_chatlog->textCursor().insertText(" " + p_action + ".", normal);
+ }
+ // Make shout text bold
+ else if (p_action == tr("shouts") && log_ic_actions) {
+ ui_ic_chatlog->textCursor().insertText(" " + p_action + " ", normal);
+ if (log_colors)
+ ui_ic_chatlog->textCursor().insertHtml("<b>" + filter_ic_text(p_text, true, -1, 0) + "</b>");
+ else
+ ui_ic_chatlog->textCursor().insertText(" " + p_text, italics);
+ }
// If action not blank:
- if (p_action != "") {
+ else if (p_action != "" && log_ic_actions) {
// Format the action in normal
ui_ic_chatlog->textCursor().insertText(" " + p_action, normal);
if (log_newline)
- // For some reason, we're forced to use <br> instead of the more sensible \n.
- // Why? Because \n is treated as a new Block instead of a soft newline within a paragraph!
+ // For some reason, we're forced to use <br> instead of the more sensible
+ // \n. Why? Because \n is treated as a new Block instead of a soft newline
+ // within a paragraph!
ui_ic_chatlog->textCursor().insertHtml("<br>");
else
ui_ic_chatlog->textCursor().insertText(": ", normal);
@@ -2626,14 +2795,21 @@ void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action,
}
else {
if (log_newline)
- // For some reason, we're forced to use <br> instead of the more sensible \n.
- // Why? Because \n is treated as a new Block instead of a soft newline within a paragraph!
+ // For some reason, we're forced to use <br> instead of the more sensible
+ // \n. Why? Because \n is treated as a new Block instead of a soft newline
+ // within a paragraph!
ui_ic_chatlog->textCursor().insertHtml("<br>");
else
ui_ic_chatlog->textCursor().insertText(": ", normal);
// Format the result according to html
- if (log_colors)
- ui_ic_chatlog->textCursor().insertHtml(filter_ic_text(p_text, true, -1, color));
+ if (log_colors) {
+ QString p_text_filtered = filter_ic_text(p_text, true, -1, color);
+ p_text_filtered = p_text_filtered.replace("$c0", ao_app->get_color("ic_chatlog_color", "courtroom_fonts.ini").name(QColor::HexRgb));
+ for (int c = 1; c < max_colors; ++c) {
+ p_text_filtered = p_text_filtered.replace("$c" + QString::number(c), default_color_rgb_list.at(c).name(QColor::HexRgb));
+ }
+ ui_ic_chatlog->textCursor().insertHtml(p_text_filtered);
+ }
else
ui_ic_chatlog->textCursor().insertText(filter_ic_text(p_text, false), normal);
}
@@ -2646,7 +2822,8 @@ void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action,
// If we got too many blocks in the current log, delete some.
while (ui_ic_chatlog->document()->blockCount() > log_maximum_blocks &&
log_maximum_blocks > 0) {
- ui_ic_chatlog->moveCursor(log_goes_downwards ? QTextCursor::Start : QTextCursor::End);
+ ui_ic_chatlog->moveCursor(log_goes_downwards ? QTextCursor::Start
+ : QTextCursor::End);
ui_ic_chatlog->textCursor().select(QTextCursor::BlockUnderCursor);
ui_ic_chatlog->textCursor().removeSelectedText();
if (log_goes_downwards)
@@ -2656,7 +2833,8 @@ void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action,
}
// Finally, scroll the scrollbar to the correct position.
- if (old_cursor.hasSelection() || old_scrollbar_value != scrollbar_target_value) {
+ if (old_cursor.hasSelection() ||
+ old_scrollbar_value != scrollbar_target_value) {
// The user has selected text or scrolled away from the bottom: maintain
// position.
ui_ic_chatlog->setTextCursor(old_cursor);
@@ -2665,13 +2843,14 @@ void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action,
else {
// The user hasn't selected any text and the scrollbar is at the bottom:
// scroll to the bottom.
- ui_ic_chatlog->moveCursor(log_goes_downwards ? QTextCursor::End : QTextCursor::Start);
+ ui_ic_chatlog->moveCursor(log_goes_downwards ? QTextCursor::End
+ : QTextCursor::Start);
ui_ic_chatlog->verticalScrollBar()->setValue(
- ui_ic_chatlog->verticalScrollBar()->maximum());
+ log_goes_downwards ? ui_ic_chatlog->verticalScrollBar()->maximum() : 0);
}
}
-void Courtroom::play_preanim(bool noninterrupting)
+void Courtroom::play_preanim(bool immediate)
{
QString f_char = m_chatmessage[CHAR_NAME];
QString f_preanim = m_chatmessage[PRE_EMOTE];
@@ -2693,7 +2872,7 @@ void Courtroom::play_preanim(bool noninterrupting)
QString anim_to_find =
ao_app->get_image_suffix(ao_app->get_character_path(f_char, f_preanim));
if (!file_exists(anim_to_find)) {
- if (noninterrupting)
+ if (immediate)
anim_state = 4;
else
anim_state = 1;
@@ -2704,7 +2883,7 @@ void Courtroom::play_preanim(bool noninterrupting)
ui_vp_player_char->play_pre(f_char, f_preanim, preanim_duration);
- if (noninterrupting)
+ if (immediate)
anim_state = 4;
else
anim_state = 1;
@@ -2712,7 +2891,7 @@ void Courtroom::play_preanim(bool noninterrupting)
if (text_delay >= 0)
text_delay_timer->start(text_delay);
- if (noninterrupting)
+ if (immediate)
handle_chatmessage_3();
}
@@ -2780,9 +2959,13 @@ void Courtroom::start_chat_ticking()
current_display_speed = 3;
chat_tick_timer->start(0); // Display the first char right away
- QString f_gender = ao_app->get_gender(m_chatmessage[CHAR_NAME]);
+ last_misc = current_misc;
+ current_misc = ao_app->get_char_shouts(m_chatmessage[CHAR_NAME]);
+ if (last_misc != current_misc)
+ gen_char_rgb_list(m_chatmessage[CHAR_NAME]);
- blip_player->set_blips(f_gender);
+ QString f_blips = ao_app->get_blips(m_chatmessage[CHAR_NAME]);
+ blip_player->set_blips(f_blips);
// means text is currently ticking
text_state = 1;
@@ -2814,9 +2997,11 @@ void Courtroom::chat_tick()
ui_vp_chat_arrow->play(
"chat_arrow", f_char,
f_custom_theme); // Chat stopped being processed, indicate that.
- additive_previous =
- additive_previous +
- filter_ic_text(f_message, true, -1, m_chatmessage[TEXT_COLOR].toInt());
+ QString f_message_filtered = filter_ic_text(f_message, true, -1, m_chatmessage[TEXT_COLOR].toInt());
+ for (int c = 0; c < max_colors; ++c) {
+ f_message_filtered = f_message_filtered.replace("$c" + QString::number(c), char_color_rgb_list.at(c).name(QColor::HexRgb));
+ }
+ additive_previous = additive_previous + f_message_filtered;
real_tick_pos = ui_vp_message->toPlainText().size();
return;
}
@@ -2929,9 +3114,11 @@ void Courtroom::chat_tick()
else {
int msg_delay = message_display_speed[current_display_speed];
// Do the colors, gradual showing, etc. in here
- ui_vp_message->setHtml(additive_previous +
- filter_ic_text(f_message, true, tick_pos,
- m_chatmessage[TEXT_COLOR].toInt()));
+ QString f_message_filtered = filter_ic_text(f_message, true, tick_pos, m_chatmessage[TEXT_COLOR].toInt());
+ for (int c = 0; c < max_colors; ++c) {
+ f_message_filtered = f_message_filtered.replace("$c" + QString::number(c), char_color_rgb_list.at(c).name(QColor::HexRgb));
+ }
+ ui_vp_message->setHtml(additive_previous + f_message_filtered);
// This should always be done AFTER setHtml. Scroll the chat window with the
// text.
@@ -2944,17 +3131,42 @@ void Courtroom::chat_tick()
ui_vp_message->ensureCursorVisible();
- // Blip player and real tick pos ticker
- if (!formatting_char && (f_character != ' ' || blank_blip)) {
- if (blip_ticker % blip_rate == 0) {
+ // We blip every "blip rate" letters.
+ // Here's an example with blank_blip being false and blip_rate being 2:
+ // I am you
+ // ! ! ! !
+ // where ! is the blip sound
+ int b_rate = blip_rate;
+ // Earrape prevention without using timers, this method is more consistent.
+ if (msg_delay != 0 && msg_delay <= 25) {
+ // The default blip speed is 40ms, and if current msg_delay is 25ms,
+ // the formula will result in the blip rate of:
+ // 40/25 = 1.6 = 2
+ // And if it's faster than that:
+ // 40/10 = 4
+ b_rate =
+ qMax(b_rate, qRound(static_cast<float>(message_display_speed[3]) /
+ msg_delay));
+ }
+ if (blip_ticker % b_rate == 0) {
+ // ignoring white space unless blank_blip is enabled.
+ if (!formatting_char && (f_character != ' ' || blank_blip)) {
blip_player->blip_tick();
+ ++blip_ticker;
}
+ }
+ else {
+ // Don't fully ignore whitespace still, keep ticking until
+ // we reached the need to play a blip sound - we also just
+ // need to wait for a letter to play it on.
++blip_ticker;
}
- // Punctuation delayer
- if (punctuation_chars.contains(f_character)) {
- msg_delay *= punctuation_modifier;
+ // Punctuation delayer, only kicks in on speed ticks less than }}
+ if (current_display_speed > 1 && punctuation_chars.contains(f_character)) {
+ // Making the user have to wait any longer than 150ms per letter is
+ // downright unreasonable
+ msg_delay = qMin(150, msg_delay * punctuation_modifier);
}
// If this color is talking
@@ -3001,8 +3213,16 @@ void Courtroom::play_sfx()
void Courtroom::set_scene(QString f_desk_mod, QString f_side)
{
// witness is default if pos is invalid
- QString f_background = "witnessempty";
- QString f_desk_image = "stand";
+ QString f_background;
+ QString f_desk_image;
+ if (file_exists(ao_app->get_image_suffix(ao_app->get_background_path("witnessempty")))) {
+ f_background = "witnessempty";
+ f_desk_image = "stand";
+ }
+ else {
+ f_background = "wit";
+ f_desk_image = "wit_overlay";
+ }
if (f_side == "def" && file_exists(ao_app->get_image_suffix(
ao_app->get_background_path("defenseempty")))) {
@@ -3067,6 +3287,17 @@ void Courtroom::set_scene(QString f_desk_mod, QString f_side)
}
}
+void Courtroom::set_self_offset(QString p_list) {
+ QStringList self_offsets = p_list.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();
+ ui_vp_player_char->move(ui_viewport->width() * self_offset / 100, ui_viewport->height() * self_offset_v / 100);
+}
+
void Courtroom::set_ip_list(QString p_list)
{
QString f_list = p_list.replace("|", ":").replace("*", "\n");
@@ -3141,14 +3372,19 @@ void Courtroom::handle_song(QStringList *p_contents)
{
effect_flags = p_contents->at(5).toInt();
}
-
music_player->play(f_song, channel, looping, effect_flags);
- if (channel == 0)
- ui_music_name->setText(f_song_clear);
+ if (f_song == "~stop.mp3")
+ ui_music_name->setText(tr("None"));
+ else if (channel == 0) {
+ if (file_exists(ao_app->get_sfx_suffix(ao_app->get_music_path(f_song))))
+ ui_music_name->setText(f_song_clear);
+ else
+ ui_music_name->setText(tr("[MISSING] %1").arg(f_song_clear));
+ }
}
else {
QString str_char = char_list.at(n_char).name;
- QString str_show = char_list.at(n_char).name;
+ QString str_show = ao_app->get_showname(str_char);
if (p_contents->length() > 2) {
if (p_contents->at(2) != "") {
@@ -3170,13 +3406,25 @@ void Courtroom::handle_song(QStringList *p_contents)
}
if (!mute_map.value(n_char)) {
- log_ic_text(str_char, str_show, f_song, tr("has played a song"),
- m_chatmessage[TEXT_COLOR].toInt());
- append_ic_text(f_song_clear, str_show, tr("has played a song"));
-
+ if (f_song == "~stop.mp3") {
+ log_ic_text(str_char, str_show, "", tr("has stopped the music"),
+ m_chatmessage[TEXT_COLOR].toInt());
+ append_ic_text("", str_show, tr("has stopped the music"));
+ }
+ else {
+ log_ic_text(str_char, str_show, f_song, tr("has played a song"),
+ m_chatmessage[TEXT_COLOR].toInt());
+ append_ic_text(f_song_clear, str_show, tr("has played a song"));
+ }
music_player->play(f_song, channel, looping, effect_flags);
- if (channel == 0)
- ui_music_name->setText(f_song_clear);
+ if (f_song == "~stop.mp3")
+ ui_music_name->setText(tr("None"));
+ else if (channel == 0) {
+ if (file_exists(ao_app->get_sfx_suffix(ao_app->get_music_path(f_song))))
+ ui_music_name->setText(f_song_clear);
+ else
+ ui_music_name->setText(tr("[MISSING] %1").arg(f_song_clear));
+ }
}
}
}
@@ -3334,9 +3582,8 @@ void Courtroom::on_ooc_return_pressed()
if (ok) {
if (off >= -100 && off <= 100) {
char_offset = off;
- QString msg = tr("You have set your offset to ");
- msg.append(QString::number(off));
- msg.append("%.");
+ QString msg =
+ tr("You have set your offset to %1%%.").arg(QString::number(off));
append_server_chatmessage("CLIENT", msg, "1");
}
else {
@@ -3350,6 +3597,31 @@ void Courtroom::on_ooc_return_pressed()
}
return;
}
+ else if (ooc_message.startsWith("/voffset")) {
+ ui_ooc_chat_message->clear();
+ ooc_message.remove(0, 8);
+
+ bool ok;
+ int off = ooc_message.toInt(&ok);
+ if (ok) {
+ if (off >= -100 && off <= 100) {
+ char_vert_offset = off;
+ QString msg = tr("You have set your vertical offset to %1%%.")
+ .arg(QString::number(off));
+ append_server_chatmessage("CLIENT", msg, "1");
+ }
+ else {
+ append_server_chatmessage(
+ "CLIENT",
+ tr("Your vertical offset must be between -100% and 100%!"), "1");
+ }
+ }
+ else {
+ append_server_chatmessage(
+ "CLIENT", tr("That vertical offset does not look like one."), "1");
+ }
+ return;
+ }
else if (ooc_message.startsWith("/switch_am")) {
append_server_chatmessage(
"CLIENT", tr("You switched your music and area list."), "1");
@@ -3371,13 +3643,13 @@ void Courtroom::on_ooc_return_pressed()
return;
}
else if (ooc_message.startsWith("/non_int_pre")) {
- if (ui_pre_non_interrupt->isChecked())
+ if (ui_immediate->isChecked())
append_server_chatmessage(
"CLIENT", tr("Your pre-animations interrupt again."), "1");
else
append_server_chatmessage(
"CLIENT", tr("Your pre-animations will not interrupt text."), "1");
- ui_pre_non_interrupt->setChecked(!ui_pre_non_interrupt->isChecked());
+ ui_immediate->setChecked(!ui_immediate->isChecked());
ui_ooc_chat_message->clear();
return;
}
@@ -3458,9 +3730,10 @@ void Courtroom::on_ooc_return_pressed()
if (!caseauth.isEmpty())
append_server_chatmessage(tr("CLIENT"),
tr("Case made by %1.").arg(caseauth), "1");
- if (!casedoc.isEmpty())
- ao_app->send_server_packet(new AOPacket("CT#" + ui_ooc_chat_name->text() +
- "#/doc " + casedoc + "#%"));
+ if (!casedoc.isEmpty()) {
+ QStringList f_contents = {ui_ooc_chat_name->text(), "/doc " + casedoc};
+ ao_app->send_server_packet(new AOPacket("CT", f_contents));
+ }
if (!casestatus.isEmpty())
ao_app->send_server_packet(new AOPacket("CT#" + ui_ooc_chat_name->text() +
"#/status " + casestatus + "#%"));
@@ -3473,7 +3746,15 @@ void Courtroom::on_ooc_return_pressed()
new AOPacket("DE#" + QString::number(i) + "#%"));
}
- foreach (QString evi, casefile.childGroups()) {
+ // sort the case_evidence numerically
+ QStringList case_evidence = casefile.childGroups();
+ std::sort(case_evidence.begin(), case_evidence.end(),
+ [] (const QString &a, const QString &b) {
+ return a.toInt() < b.toInt();
+ });
+
+ // load evidence
+ foreach (QString evi, case_evidence) {
if (evi == "General")
continue;
@@ -3648,7 +3929,7 @@ void Courtroom::on_music_search_return_pressed()
void Courtroom::on_pos_dropdown_changed(int p_index)
{
- if (p_index < 0 || p_index > 7)
+ if (p_index < 0)
return;
toggle_judge_buttons(false);
@@ -3676,7 +3957,8 @@ void Courtroom::set_iniswap_dropdown()
return;
}
QStringList iniswaps = ao_app->get_list_file(
- ao_app->get_character_path(char_list.at(m_cid).name, "iniswaps.ini"));
+ ao_app->get_character_path(char_list.at(m_cid).name, "iniswaps.ini")) + ao_app->get_list_file(ao_app->get_base_path() + "iniswaps.ini");
+ iniswaps.removeDuplicates();
iniswaps.prepend(char_list.at(m_cid).name);
if (iniswaps.size() <= 0) {
ui_iniswap_dropdown->hide();
@@ -3706,14 +3988,15 @@ void Courtroom::on_iniswap_dropdown_changed(int p_index)
ao_app->set_char_ini(char_list.at(m_cid).name, iniswap, "name", "Options");
QStringList swaplist;
+ QStringList defswaplist = ao_app->get_list_file(ao_app->get_character_path(char_list.at(m_cid).name, "iniswaps.ini"));
for (int i = 0; i < ui_iniswap_dropdown->count(); ++i) {
QString entry = ui_iniswap_dropdown->itemText(i);
- if (!swaplist.contains(entry) && entry != char_list.at(m_cid).name)
+ if (!swaplist.contains(entry) && entry != char_list.at(m_cid).name && !defswaplist.contains(entry))
swaplist.append(entry);
}
ao_app->write_to_file(
swaplist.join("\n"),
- ao_app->get_character_path(char_list.at(m_cid).name, "iniswaps.ini"));
+ ao_app->get_base_path() + "iniswaps.ini");
ui_iniswap_dropdown->blockSignals(true);
ui_iniswap_dropdown->setCurrentIndex(p_index);
ui_iniswap_dropdown->blockSignals(false);
@@ -3728,6 +4011,7 @@ void Courtroom::on_iniswap_context_menu_requested(const QPoint &pos)
{
QMenu *menu = ui_iniswap_dropdown->lineEdit()->createStandardContextMenu();
+ menu->setAttribute(Qt::WA_DeleteOnClose);
menu->addSeparator();
if (file_exists(ao_app->get_character_path(current_char, "char.ini")))
menu->addAction(QString("Edit " + current_char + "/char.ini"), this,
@@ -3787,6 +4071,7 @@ void Courtroom::set_sfx_dropdown()
ui_sfx_remove->hide();
return;
}
+ soundlist.prepend("Nothing");
soundlist.prepend("Default");
ui_sfx_dropdown->show();
@@ -3801,9 +4086,9 @@ void Courtroom::on_sfx_dropdown_changed(int p_index)
ui_ic_chat_message->setFocus();
QStringList soundlist;
- for (int i = 0; i < ui_sfx_dropdown->count(); ++i) {
+ for (int i = 2; i < ui_sfx_dropdown->count(); ++i) {
QString entry = ui_sfx_dropdown->itemText(i);
- if (!soundlist.contains(entry) && entry != "Default")
+ if (!soundlist.contains(entry))
soundlist.append(entry);
}
@@ -3825,7 +4110,7 @@ void Courtroom::on_sfx_dropdown_changed(int p_index)
ui_sfx_dropdown->blockSignals(true);
ui_sfx_dropdown->setCurrentIndex(p_index);
ui_sfx_dropdown->blockSignals(false);
- if (p_index != 0)
+ if (p_index > 1)
ui_sfx_remove->show();
else
ui_sfx_remove->hide();
@@ -3835,6 +4120,7 @@ void Courtroom::on_sfx_context_menu_requested(const QPoint &pos)
{
QMenu *menu = ui_sfx_dropdown->lineEdit()->createStandardContextMenu();
+ menu->setAttribute(Qt::WA_DeleteOnClose);
menu->addSeparator();
if (file_exists(ao_app->get_character_path(current_char, "soundlist.ini")))
menu->addAction(QString("Edit " + current_char + "/soundlist.ini"), this,
@@ -3842,7 +4128,7 @@ void Courtroom::on_sfx_context_menu_requested(const QPoint &pos)
else
menu->addAction(QString("Edit theme's character_soundlist.ini"), this,
SLOT(on_sfx_edit_requested()));
- if (ui_sfx_dropdown->currentIndex() != 0)
+ if (ui_sfx_dropdown->currentIndex() > 1)
menu->addAction(QString("Remove " + ui_sfx_dropdown->itemText(
ui_sfx_dropdown->currentIndex())),
this, SLOT(on_sfx_remove_clicked()));
@@ -3870,7 +4156,7 @@ void Courtroom::on_sfx_remove_clicked()
// client will crash
return;
}
- if (ui_sfx_dropdown->itemText(ui_sfx_dropdown->currentIndex()) != "Default") {
+ if (ui_sfx_dropdown->currentIndex() > 1) {
ui_sfx_dropdown->removeItem(ui_sfx_dropdown->currentIndex());
on_sfx_dropdown_changed(0); // Reset back to original
}
@@ -3891,7 +4177,7 @@ void Courtroom::set_effects_dropdown()
return;
}
- effectslist.prepend("None");
+ effectslist.prepend(tr("None"));
ui_effects_dropdown->show();
ui_effects_dropdown->addItems(effectslist);
@@ -3922,8 +4208,9 @@ void Courtroom::set_effects_dropdown()
void Courtroom::on_effects_context_menu_requested(const QPoint &pos)
{
- QMenu *menu = new QMenu();
+ QMenu *menu = new QMenu(this);
+ menu->setAttribute(Qt::WA_DeleteOnClose);
if (!ao_app->read_char_ini(current_char, "effects", "Options").isEmpty())
menu->addAction(
QString("Open misc/" +
@@ -3976,6 +4263,8 @@ bool Courtroom::effects_dropdown_find_and_set(QString effect)
QString Courtroom::get_char_sfx()
{
QString sfx = ui_sfx_dropdown->itemText(ui_sfx_dropdown->currentIndex());
+ if (sfx == "Nothing")
+ return "1";
if (sfx != "" && sfx != "Default")
return sfx;
return ao_app->get_sfx_name(current_char, current_emote);
@@ -4069,10 +4358,10 @@ void Courtroom::on_music_list_double_clicked(QTreeWidgetItem *p_item,
{
if (is_muted)
return;
-
+ if (p_item->parent() == nullptr) // i.e. we've clicked a category
+ return;
column = 1; // Column 1 is always the metadata (which we want)
QString p_song = p_item->text(column);
-
QStringList packet_contents;
packet_contents.append(p_song);
packet_contents.append(QString::number(m_cid));
@@ -4086,8 +4375,9 @@ void Courtroom::on_music_list_double_clicked(QTreeWidgetItem *p_item,
void Courtroom::on_music_list_context_menu_requested(const QPoint &pos)
{
- QMenu *menu = new QMenu();
-
+ QMenu *menu = new QMenu(this);
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->addAction(QString(tr("Stop Current Song")), this, SLOT(music_stop()));
menu->addAction(QString(tr("Play Random Song")), this, SLOT(music_random()));
menu->addSeparator();
menu->addAction(QString(tr("Expand All Categories")), this,
@@ -4148,11 +4438,14 @@ void Courtroom::music_random()
QTreeWidgetItemIterator::NotHidden |
QTreeWidgetItemIterator::NoChildren);
while (*it) {
- clist += (*it);
+ if ((*it)->parent()->isExpanded()) {
+ clist += (*it);
+ }
++it;
}
- int i = qrand() % clist.length();
- on_music_list_double_clicked(clist.at(i), 1);
+ if (clist.length() == 0)
+ return;
+ on_music_list_double_clicked(clist.at(qrand() % clist.length()), 1);
}
void Courtroom::music_list_expand_all() { ui_music_list->expandAll(); }
@@ -4165,6 +4458,22 @@ void Courtroom::music_list_collapse_all()
ui_music_list->setCurrentItem(current);
}
+void Courtroom::music_stop()
+{ // send a fake music packet with a nonexistent song
+ if (is_muted) // this requires a special exception for "~stop.mp3" in
+ return; // tsuserver3, as it will otherwise reject songs not on
+ QStringList packet_contents; // its music list
+ packet_contents.append(
+ "~stop.mp3"); // this is our fake song, playing it triggers special code
+ packet_contents.append(QString::number(m_cid));
+ if ((!ui_ic_chat_name->text().isEmpty() && ao_app->cccc_ic_support_enabled) ||
+ ao_app->effects_enabled)
+ packet_contents.append(ui_ic_chat_name->text());
+ if (ao_app->effects_enabled)
+ packet_contents.append(QString::number(music_flags));
+ ao_app->send_server_packet(new AOPacket("MC", packet_contents), false);
+}
+
void Courtroom::on_area_list_double_clicked(QTreeWidgetItem *p_item, int column)
{
column = 0; // The metadata
@@ -4258,10 +4567,16 @@ void Courtroom::show_custom_objection_menu(const QPoint &pos)
ui_take_that->set_image("takethat");
ui_hold_it->set_image("holdit");
ui_custom_objection->set_image("custom_selected");
- if (selecteditem->text() == "Default")
+ if (selecteditem->text() == ao_app->read_char_ini(current_char, "custom_name", "Shouts") || selecteditem->text() == "Default")
objection_custom = "";
- else
- objection_custom = selecteditem->text();
+ else {
+ foreach (CustomObjection custom_objection, custom_objections_list) {
+ if (custom_objection.name == selecteditem->text()) {
+ objection_custom = custom_objection.filename;
+ break;
+ }
+ }
+ }
objection_state = 4;
custom_obj_menu->setDefaultAction(selecteditem);
}
@@ -4306,6 +4621,7 @@ void Courtroom::on_mute_clicked()
ui_mute_list->show();
ui_pair_list->hide();
ui_pair_offset_spinbox->hide();
+ ui_pair_vert_offset_spinbox->hide();
ui_pair_order_dropdown->hide();
ui_pair_button->set_image("pair_button");
ui_mute->set_image("mute_pressed");
@@ -4321,6 +4637,8 @@ void Courtroom::on_pair_clicked()
if (ui_pair_list->isHidden()) {
ui_pair_list->show();
ui_pair_offset_spinbox->show();
+ if(ao_app->y_offset_enabled)
+ ui_pair_vert_offset_spinbox->show();
ui_pair_order_dropdown->show();
ui_mute_list->hide();
ui_mute->set_image("mute");
@@ -4329,6 +4647,7 @@ void Courtroom::on_pair_clicked()
else {
ui_pair_list->hide();
ui_pair_offset_spinbox->hide();
+ ui_pair_vert_offset_spinbox->hide();
ui_pair_order_dropdown->hide();
ui_pair_button->set_image("pair_button");
}
@@ -4383,6 +4702,7 @@ void Courtroom::set_text_color_dropdown()
// Clear the stored optimization information
color_rgb_list.clear();
+ default_color_rgb_list.clear();
color_markdown_start_list.clear();
color_markdown_end_list.clear();
color_markdown_remove_list.clear();
@@ -4419,6 +4739,18 @@ void Courtroom::set_text_color_dropdown()
ui_text_color->setItemIcon(ui_text_color->count() - 1, QIcon(pixmap));
color_row_to_number.append(c);
}
+ for (int c = 0; c < max_colors; ++c) {
+ QColor color = ao_app->get_chat_color("c" + QString::number(c), "default");
+ default_color_rgb_list.append(color);
+ }
+}
+
+void Courtroom::gen_char_rgb_list(QString p_char) {
+ char_color_rgb_list.clear();
+ for (int c = 0; c < max_colors; ++c) {
+ QColor color = ao_app->get_chat_color("c" + QString::number(c), p_char);
+ char_color_rgb_list.append(color);
+ }
}
void Courtroom::on_text_color_changed(int p_color)
@@ -4485,6 +4817,11 @@ void Courtroom::on_log_limit_changed(int value) { log_maximum_blocks = value; }
void Courtroom::on_pair_offset_changed(int value) { char_offset = value; }
+void Courtroom::on_pair_vert_offset_changed(int value)
+{
+ char_vert_offset = value;
+}
+
void Courtroom::on_witness_testimony_clicked()
{
if (is_muted)
@@ -4640,8 +4977,11 @@ void Courtroom::regenerate_ic_chatlog()
{
ui_ic_chatlog->clear();
foreach (chatlogpiece item, ic_chatlog_history) {
- append_ic_text(item.get_message(), ui_showname_enable->isChecked() ? item.get_showname() : item.get_name(),
- item.get_action(), item.get_chat_color());
+ append_ic_text(item.get_message(),
+ ui_showname_enable->isChecked() ? item.get_showname()
+ : item.get_name(),
+ item.get_action(), item.get_chat_color(),
+ item.get_datetime().toLocalTime());
}
}
@@ -4756,6 +5096,75 @@ void Courtroom::set_clock_visibility(bool visible)
ui_clock->setVisible(visible);
}
+void Courtroom::truncate_label_text(QWidget *p_widget, QString p_identifier)
+{
+ QString filename = "courtroom_design.ini";
+ pos_size_type design_ini_result =
+ ao_app->get_element_dimensions(p_identifier, filename);
+ // Get the width of the element as defined by the current theme
+
+ // Cast to make sure we're working with one of the two supported widget types
+ QLabel *p_label = qobject_cast<QLabel *>(p_widget);
+ QCheckBox *p_checkbox = qobject_cast<QCheckBox *>(p_widget);
+
+ if (p_checkbox == nullptr &&
+ p_label ==
+ nullptr) { // i.e. the given p_widget isn't a QLabel or a QCheckBox
+ qWarning() << "W: Tried to truncate an unsupported widget:" << p_identifier;
+ return;
+ }
+ // translate the text for the widget we're working with so we truncate the right string
+ QString label_text_tr =
+ QCoreApplication::translate(p_widget->metaObject()->className(), "%1")
+ .arg((p_label != nullptr ? p_label->text() : p_checkbox->text()));
+ int label_theme_width =
+ (p_label != nullptr
+ ? design_ini_result.width
+ : design_ini_result.width -
+ 18); // 18 is the width of a checkbox on win10 + 5px of
+ // padding, TODO: fetch the actual size
+ int label_px_width =
+ p_widget->fontMetrics().boundingRect(label_text_tr).width(); // pixel width of our translated text
+ p_widget->setToolTip(label_text_tr + "\n" + p_widget->toolTip());
+ // qInfo() << "I: Width of label text: " << label_px_width << "px. Theme's
+ // width: " << label_theme_width << "px.";
+
+ // we can't do much with a 0-width widget, and there's no need to truncate if
+ // the theme gives us enough space
+ if (label_theme_width <= 0 || label_px_width < label_theme_width) {
+ qInfo() << "I: Truncation aborted for label text " << label_text_tr
+ << ", either theme width <= 0 or label width < theme width.";
+ return;
+ }
+
+ QString truncated_label = label_text_tr;
+ int truncated_px_width = label_px_width;
+ while (truncated_px_width > label_theme_width && truncated_label != "…") {
+ truncated_label.chop(2);
+ truncated_label.append("…");
+ // qInfo() << "I: Attempted to truncate label to string: " <<
+ // truncated_label;
+ truncated_px_width =
+ p_widget->fontMetrics().boundingRect(truncated_label).width();
+ }
+ if (truncated_label == "…") {
+ // Safeguard against edge case where label text is shorter in px than '…',
+ // causing an infinite loop. Additionally, having just an ellipse for a
+ // label looks strange, so we don't set the new label.
+ qWarning() << "W: Potential infinite loop prevented: Label text "
+ << label_text_tr
+ << "truncated to '…', so truncation was aborted.";
+ return;
+ }
+ if (p_label != nullptr)
+ p_label->setText(truncated_label);
+ else if (p_checkbox != nullptr)
+ p_checkbox->setText(truncated_label);
+ qInfo() << "I: Truncated label text from " << label_text_tr << " ("
+ << label_px_width << "px ) to " << truncated_label << " ("
+ << truncated_px_width << "px )";
+}
+
Courtroom::~Courtroom()
{
delete music_player;
diff --git a/src/debug_functions.cpp b/src/debug_functions.cpp
index b8321640..1613a7d1 100644
--- a/src/debug_functions.cpp
+++ b/src/debug_functions.cpp
@@ -1,5 +1,7 @@
#include <QCoreApplication>
#include <QMessageBox>
+#include <QTimer>
+#include <functional>
#include "debug_functions.h"
@@ -7,6 +9,7 @@ void call_error(QString p_message)
{
QMessageBox *msgBox = new QMessageBox;
+ msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setText(QCoreApplication::translate("debug_functions", "Error: %1")
.arg(p_message));
msgBox->setWindowTitle(
@@ -20,10 +23,15 @@ void call_notice(QString p_message)
{
QMessageBox *msgBox = new QMessageBox;
+ msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setText(p_message);
msgBox->setWindowTitle(
QCoreApplication::translate("debug_functions", "Notice"));
- // msgBox->setWindowModality(Qt::NonModal);
- msgBox->exec();
+ msgBox->setStandardButtons(QMessageBox::NoButton);
+
+ QTimer::singleShot(3000, msgBox, std::bind(&QMessageBox::setStandardButtons,msgBox,QMessageBox::Ok));
+
+ msgBox->exec();
+
}
diff --git a/src/encryption_functions.cpp b/src/encryption_functions.cpp
deleted file mode 100644
index 6669fe15..00000000
--- a/src/encryption_functions.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#include "encryption_functions.h"
-
-#include "hex_functions.h"
-
-QString fanta_encrypt(QString temp_input, unsigned int p_key)
-{
- // using standard stdlib types is actually easier here because of implicit
- // char<->int conversion which in turn makes encryption arithmetic easier
-
- unsigned int key = p_key;
- unsigned int C1 = 53761;
- unsigned int C2 = 32618;
-
- QVector<uint_fast8_t> temp_result;
- std::string input = temp_input.toUtf8().constData();
-
- for (unsigned int pos = 0; pos < input.size(); ++pos) {
- uint_fast8_t output = input.at(pos) ^ (key >> 8) % 256;
- temp_result.append(output);
- key = (temp_result.at(pos) + key) * C1 + C2;
- }
-
- std::string result = "";
-
- for (uint_fast8_t i_int : temp_result) {
- result += omni::int_to_hex(i_int);
- }
-
- QString final_result = QString::fromStdString(result);
-
- return final_result;
-}
-
-QString fanta_decrypt(QString temp_input, unsigned int key)
-{
- std::string input = temp_input.toUtf8().constData();
-
- QVector<unsigned int> unhexed_vector;
-
- for (unsigned int i = 0; i < input.length(); i += 2) {
- std::string byte = input.substr(i, 2);
- unsigned int hex_int = strtoul(byte.c_str(), nullptr, 16);
- unhexed_vector.append(hex_int);
- }
-
- unsigned int C1 = 53761;
- unsigned int C2 = 32618;
-
- std::string result = "";
-
- for (int pos = 0; pos < unhexed_vector.size(); ++pos) {
- unsigned char output = unhexed_vector.at(pos) ^ (key >> 8) % 256;
- result += output;
- key = (unhexed_vector.at(pos) + key) * C1 + C2;
- }
-
- return QString::fromStdString(result);
-}
diff --git a/src/evidence.cpp b/src/evidence.cpp
index a8f59135..b97607ba 100644
--- a/src/evidence.cpp
+++ b/src/evidence.cpp
@@ -258,8 +258,9 @@ void Courtroom::set_evidence_list(QVector<evi_type> &p_evi_list)
else if (compare_evidence_changed(
old_list.at(current_evidence),
local_evidence_list.at(current_evidence))) {
- QMessageBox *msgBox = new QMessageBox;
+ QMessageBox *msgBox = new QMessageBox(this);
+ msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setText(tr("The piece of evidence you've been editing has changed."));
msgBox->setInformativeText(tr("Do you wish to keep your changes?"));
msgBox->setDetailedText(tr(
@@ -552,7 +553,8 @@ void Courtroom::on_evidence_x_clicked()
evidence_close();
return;
}
- QMessageBox *msgBox = new QMessageBox;
+ QMessageBox *msgBox = new QMessageBox(this);
+ msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setText(tr("Evidence has been modified."));
msgBox->setInformativeText(tr("Do you want to save your changes?"));
msgBox->setStandardButtons(QMessageBox::Save | QMessageBox::Discard |
@@ -655,7 +657,8 @@ void Courtroom::on_evidence_transfer_clicked()
private_evidence_list.append(f_evi);
}
- QMessageBox *msgBox = new QMessageBox;
+ QMessageBox *msgBox = new QMessageBox(this);
+ msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setText(tr("\"%1\" has been transferred.").arg(name));
msgBox->setStandardButtons(QMessageBox::Ok);
msgBox->setDefaultButton(QMessageBox::Ok);
diff --git a/src/hex_functions.cpp b/src/hex_functions.cpp
deleted file mode 100644
index 1e35718f..00000000
--- a/src/hex_functions.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "hex_functions.h"
-
-namespace omni {
-std::string int_to_hex(unsigned int input)
-{
- if (input > 255)
- return "FF";
-
- std::stringstream stream;
- stream << std::setfill('0') << std::setw(sizeof(char) * 2) << std::hex
- << input;
- std::string result(stream.str());
- std::transform(result.begin(), result.end(), result.begin(), ::toupper);
-
- return result;
-}
-} // namespace omni
diff --git a/src/lobby.cpp b/src/lobby.cpp
index 093b0f7d..954c30a8 100644
--- a/src/lobby.cpp
+++ b/src/lobby.cpp
@@ -13,6 +13,7 @@ Lobby::Lobby(AOApplication *p_ao_app) : QMainWindow()
this->setWindowTitle(tr("Attorney Online 2"));
this->setWindowIcon(QIcon(":/logo.png"));
+ this->setWindowFlags( (this->windowFlags() | Qt::CustomizeWindowHint) & ~Qt::WindowMaximizeButtonHint);
ui_background = new AOImage(this, ao_app);
ui_public_servers = new AOButton(this, ao_app);
@@ -97,10 +98,10 @@ void Lobby::set_widgets()
"Did you download all resources correctly from tiny.cc/getao, "
"including the large 'base' folder?"));
- this->resize(517, 666);
+ this->setFixedSize(517, 666);
}
else {
- this->resize(f_lobby.width, f_lobby.height);
+ this->setFixedSize(f_lobby.width, f_lobby.height);
}
set_size_and_pos(ui_background, "lobby");
@@ -282,7 +283,10 @@ QString Lobby::get_chatlog()
int Lobby::get_selected_server()
{
- return ui_server_list->currentItem()->text(0).toInt();
+ if (auto item = ui_server_list->currentItem()) {
+ return item->text(0).toInt();
+ }
+ return -1;
}
void Lobby::set_loading_value(int p_value)
@@ -332,12 +336,12 @@ void Lobby::on_add_to_fav_pressed()
void Lobby::on_add_to_fav_released()
{
ui_add_to_fav->set_image("addtofav");
-
- // you cant add favorites from favorites m8
- if (!public_servers_selected)
- return;
-
- ao_app->add_favorite_server(get_selected_server());
+ if (public_servers_selected) {
+ int selection = get_selected_server();
+ if (selection > -1) {
+ ao_app->add_favorite_server(selection);
+ }
+ }
}
void Lobby::on_connect_pressed() { ui_connect->set_image("connect_pressed"); }
@@ -355,7 +359,7 @@ void Lobby::on_connect_released()
void Lobby::on_about_clicked()
{
- const bool hasApng = QImageReader::supportedImageFormats().contains("APNG");
+ const bool hasApng = QImageReader::supportedImageFormats().contains("apng");
QString msg =
tr("<h2>Attorney Online %1</h2>"
@@ -441,8 +445,9 @@ void Lobby::on_server_list_clicked(QTreeWidgetItem *p_item, int column)
// doubleclicked on an item in the serverlist so we'll connect right away
void Lobby::on_server_list_doubleclicked(QTreeWidgetItem *p_item, int column)
{
+ doubleclicked = true;
on_server_list_clicked(p_item, column);
- on_connect_released();
+ //on_connect_released();
}
void Lobby::on_server_search_edited(QString p_text)
diff --git a/src/main.cpp b/src/main.cpp
index 364377b5..ce8b1dde 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -21,6 +21,8 @@ int main(int argc, char *argv[])
AOApplication main_app(argc, argv);
+ AOApplication::addLibraryPath(AOApplication::applicationDirPath() + "/lib");
+
QSettings *configini = main_app.configini;
QPluginLoader apngPlugin("qapng");
diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp
index 17e57bf7..0bc38141 100644
--- a/src/packet_distribution.cpp
+++ b/src/packet_distribution.cpp
@@ -2,7 +2,6 @@
#include "courtroom.h"
#include "debug_functions.h"
-#include "encryption_functions.h"
#include "hardware_functions.h"
#include "lobby.h"
#include "networkmanager.h"
@@ -120,16 +119,11 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
if (f_contents.size() == 0)
goto end;
- // you may ask where 322 comes from. that would be a good question.
- s_decryptor = fanta_decrypt(f_contents.at(0), 322).toUInt();
-
// default(legacy) values
- encryption_needed = true;
yellow_text_enabled = false;
prezoom_enabled = false;
flipping_enabled = false;
custom_objection_enabled = false;
- improved_loading_enabled = false;
desk_mod_enabled = false;
evidence_enabled = false;
cccc_ic_support_enabled = false;
@@ -139,10 +133,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
looping_sfx_support_enabled = false;
additive_enabled = false;
effects_enabled = false;
-
- // workaround for tsuserver4
- if (f_contents.at(0) == "NOENCRYPT")
- encryption_needed = false;
+ y_offset_enabled = false;
QString f_hdid;
f_hdid = get_hdid();
@@ -176,12 +167,10 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
}
}
else if (header == "FL") {
- // encryption_needed = true;
yellow_text_enabled = false;
prezoom_enabled = false;
flipping_enabled = false;
custom_objection_enabled = false;
- improved_loading_enabled = false;
desk_mod_enabled = false;
evidence_enabled = false;
cccc_ic_support_enabled = false;
@@ -191,6 +180,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
looping_sfx_support_enabled = false;
additive_enabled = false;
effects_enabled = false;
+ expanded_desk_mods_enabled = false;
if (f_packet.contains("yellowtext", Qt::CaseInsensitive))
yellow_text_enabled = true;
if (f_packet.contains("prezoom", Qt::CaseInsensitive))
@@ -199,10 +189,6 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
flipping_enabled = true;
if (f_packet.contains("customobjections", Qt::CaseInsensitive))
custom_objection_enabled = true;
- if (f_packet.contains("fastloading", Qt::CaseInsensitive))
- improved_loading_enabled = true;
- if (f_packet.contains("noencryption", Qt::CaseInsensitive))
- encryption_needed = false;
if (f_packet.contains("deskmod", Qt::CaseInsensitive))
desk_mod_enabled = true;
if (f_packet.contains("evidence", Qt::CaseInsensitive))
@@ -221,6 +207,10 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
additive_enabled = true;
if (f_packet.contains("effects", Qt::CaseInsensitive))
effects_enabled = true;
+ if (f_packet.contains("y_offset", Qt::CaseInsensitive))
+ y_offset_enabled = true;
+ if (f_packet.contains("expanded_desk_mods", Qt::CaseInsensitive))
+ expanded_desk_mods_enabled = true;
}
else if (header == "PN") {
if (f_contents.size() < 2)
@@ -228,6 +218,11 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
w_lobby->set_player_count(f_contents.at(0).toInt(),
f_contents.at(1).toInt());
+
+ if (w_lobby->doubleclicked) {
+ send_server_packet(new AOPacket("askchaa#%"));
+ w_lobby->doubleclicked = false;
+ }
}
else if (header == "SI") {
if (f_contents.size() != 3)
@@ -283,11 +278,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
AOPacket *f_packet;
- if (improved_loading_enabled)
- f_packet = new AOPacket("RC#%");
- else
- f_packet = new AOPacket("askchar2#%");
-
+ f_packet = new AOPacket("RC#%");
send_server_packet(f_packet);
// Remove any characters not accepted in folder names for the server_name
@@ -308,152 +299,6 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
discord->state_server(server_name.toStdString(),
hash.result().toBase64().toStdString());
}
- else if (header == "CI") {
- if (!courtroom_constructed)
- goto end;
-
- for (int n_element = 0; n_element < f_contents.size(); n_element += 2) {
- if (f_contents.at(n_element).toInt() != loaded_chars)
- break;
-
- // this means we are on the last element and checking n + 1 element will
- // be game over so
- if (n_element == f_contents.size() - 1)
- break;
-
- QStringList sub_elements = f_contents.at(n_element + 1).split("&");
- if (sub_elements.size() < 2)
- break;
-
- char_type f_char;
- f_char.name = sub_elements.at(0);
- f_char.description = sub_elements.at(1);
- f_char.evidence_string = sub_elements.at(3);
- // temporary. the CharsCheck packet sets this properly
- f_char.taken = false;
-
- ++loaded_chars;
-
- w_lobby->set_loading_text(tr("Loading chars:\n%1/%2")
- .arg(QString::number(loaded_chars))
- .arg(QString::number(char_list_size)));
-
- w_courtroom->append_char(f_char);
-
- int total_loading_size =
- char_list_size * 2 + evidence_list_size + music_list_size;
- int loading_value = int(
- ((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
- static_cast<double>(total_loading_size)) *
- 100);
- w_lobby->set_loading_value(loading_value);
- }
-
- if (improved_loading_enabled)
- send_server_packet(new AOPacket("RE#%"));
- else {
- QString next_packet_number =
- QString::number(((loaded_chars - 1) / 10) + 1);
- send_server_packet(new AOPacket("AN#" + next_packet_number + "#%"));
- }
- }
- else if (header == "EI") {
- if (!courtroom_constructed)
- goto end;
-
- // +1 because evidence starts at 1 rather than 0 for whatever reason
- // enjoy fanta
- if (f_contents.at(0).toInt() != loaded_evidence + 1)
- goto end;
-
- if (f_contents.size() < 2)
- goto end;
-
- QStringList sub_elements = f_contents.at(1).split("&");
- if (sub_elements.size() < 4)
- goto end;
-
- evi_type f_evi;
- f_evi.name = sub_elements.at(0);
- f_evi.description = sub_elements.at(1);
- // no idea what the number at position 2 is. probably an identifier?
- f_evi.image = sub_elements.at(3);
-
- ++loaded_evidence;
-
- w_lobby->set_loading_text(tr("Loading evidence:\n%1/%2")
- .arg(QString::number(loaded_evidence))
- .arg(QString::number(evidence_list_size)));
-
- w_courtroom->append_evidence(f_evi);
-
- int total_loading_size =
- char_list_size * 2 + evidence_list_size + music_list_size;
- int loading_value =
- int(((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
- static_cast<double>(total_loading_size)) *
- 100);
- w_lobby->set_loading_value(loading_value);
-
- QString next_packet_number = QString::number(loaded_evidence);
- send_server_packet(new AOPacket("AE#" + next_packet_number + "#%"));
- }
- else if (header == "EM") {
- if (!courtroom_constructed)
- goto end;
-
- bool musics_time = false;
- int areas = 0;
-
- for (int n_element = 0; n_element < f_contents.size(); n_element += 2) {
- if (f_contents.at(n_element).toInt() != loaded_music)
- break;
-
- if (n_element == f_contents.size() - 1)
- break;
-
- QString f_music = f_contents.at(n_element + 1);
-
- ++loaded_music;
-
- w_lobby->set_loading_text(tr("Loading music:\n%1/%2")
- .arg(QString::number(loaded_music))
- .arg(QString::number(music_list_size)));
-
- if (musics_time) {
- w_courtroom->append_music(f_music);
- }
- else {
- if (f_music.endsWith(".wav") || f_music.endsWith(".mp3") ||
- f_music.endsWith(".mp4") || f_music.endsWith(".ogg") ||
- f_music.endsWith(".opus")) {
- musics_time = true;
- areas--;
- w_courtroom->fix_last_area();
- w_courtroom->append_music(f_music);
- }
- else {
- w_courtroom->append_area(f_music);
- areas++;
- }
- }
-
- for (int area_n = 0; area_n < areas; area_n++) {
- w_courtroom->arup_append(0, "Unknown", "Unknown", "Unknown");
- }
-
- int total_loading_size =
- char_list_size * 2 + evidence_list_size + music_list_size;
- int loading_value = int(
- ((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
- static_cast<double>(total_loading_size)) *
- 100);
- w_lobby->set_loading_value(loading_value);
- }
-
- QString next_packet_number = QString::number(((loaded_music - 1) / 10) + 1);
- send_server_packet(new AOPacket("AM#" + next_packet_number + "#%"));
- }
else if (header == "CharsCheck") {
if (!courtroom_constructed)
goto end;
@@ -621,6 +466,8 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
if (f_contents.size() < 3)
goto end;
+ w_courtroom->enter_courtroom();
+
if (courtroom_constructed)
w_courtroom->update_character(f_contents.at(2).toInt());
}
@@ -691,6 +538,11 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
if (courtroom_constructed && f_contents.size() > 0)
w_courtroom->set_mute(false, f_contents.at(0).toInt());
}
+ else if (header == "BB") {
+ if (courtroom_constructed && f_contents.size() >= 1) {
+ call_notice(f_contents.at(0));
+ }
+ }
else if (header == "KK") {
if (courtroom_constructed && f_contents.size() >= 1) {
call_notice(tr("You have been kicked from the server.\nReason: %1")
@@ -803,19 +655,9 @@ void AOApplication::send_server_packet(AOPacket *p_packet, bool encoded)
QString f_packet = p_packet->to_string();
- if (encryption_needed) {
-#ifdef DEBUG_NETWORK
- qDebug() << "S(e):" << f_packet;
-#endif
-
- p_packet->encrypt_header(s_decryptor);
- f_packet = p_packet->to_string();
- }
- else {
#ifdef DEBUG_NETWORK
qDebug() << "S:" << f_packet;
#endif
- }
net_manager->ship_server_packet(f_packet);
diff --git a/src/path_functions.cpp b/src/path_functions.cpp
index 10c8ae53..c6c73a8b 100644
--- a/src/path_functions.cpp
+++ b/src/path_functions.cpp
@@ -44,61 +44,40 @@ QString AOApplication::get_data_path() { return get_base_path() + "data/"; }
QString AOApplication::get_default_theme_path(QString p_file)
{
QString path = get_base_path() + "themes/default/" + p_file;
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return path;
-#else
return get_case_sensitive_path(path);
-#endif
}
QString AOApplication::get_custom_theme_path(QString p_theme, QString p_file)
{
QString path = get_base_path() + "themes/" + p_theme + "/" + p_file;
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return path;
-#else
return get_case_sensitive_path(path);
-#endif
}
QString AOApplication::get_theme_path(QString p_file)
{
QString path = get_base_path() + "themes/" + current_theme + "/" + p_file;
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return path;
-#else
return get_case_sensitive_path(path);
-#endif
}
QString AOApplication::get_character_path(QString p_char, QString p_file)
{
QString path = get_base_path() + "characters/" + p_char + "/" + p_file;
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return path;
-#else
return get_case_sensitive_path(path);
-#endif
}
QString AOApplication::get_sounds_path(QString p_file)
{
QString path = get_base_path() + "sounds/general/" + p_file;
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return path;
-#else
return get_case_sensitive_path(path);
-#endif
}
QString AOApplication::get_music_path(QString p_song)
{
+ if (p_song.startsWith("http")) {
+ return p_song; // url
+ }
QString path = get_base_path() + "sounds/music/" + p_song;
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return path;
-#else
return get_case_sensitive_path(path);
-#endif
}
QString AOApplication::get_background_path(QString p_file)
@@ -106,11 +85,7 @@ QString AOApplication::get_background_path(QString p_file)
QString path = get_base_path() + "background/" +
w_courtroom->get_current_background() + "/" + p_file;
if (courtroom_constructed) {
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return path;
-#else
return get_case_sensitive_path(path);
-#endif
}
return get_default_background_path(p_file);
}
@@ -118,33 +93,30 @@ QString AOApplication::get_background_path(QString p_file)
QString AOApplication::get_default_background_path(QString p_file)
{
QString path = get_base_path() + "background/default/" + p_file;
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return path;
-#else
return get_case_sensitive_path(path);
-#endif
}
QString AOApplication::get_evidence_path(QString p_file)
{
QString path = get_base_path() + "evidence/" + p_file;
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return path;
-#else
return get_case_sensitive_path(path);
-#endif
}
QString AOApplication::get_case_sensitive_path(QString p_file)
{
+ QFileInfo file(p_file);
+ QString file_basename = file.fileName();
+
+ // no path traversal above base folder
+ if (!(file.absolutePath().startsWith(get_base_path())))
+ return get_base_path() + file_basename;
+
+ #ifdef CASE_SENSITIVE_FILESYSTEM
// first, check to see if it's actually there (also serves as base case for
// recursion)
if (exists(p_file))
return p_file;
- QFileInfo file(p_file);
-
- QString file_basename = file.fileName();
QString file_parent_dir = get_case_sensitive_path(file.absolutePath());
// second, does it exist in the new parent dir?
@@ -163,4 +135,7 @@ QString AOApplication::get_case_sensitive_path(QString p_file)
// if nothing is found, let the caller handle the missing file
return file_parent_dir + "/" + file_basename;
+#else
+ return p_file;
+#endif
}
diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp
index 8247fd86..3524d87e 100644
--- a/src/text_file_functions.cpp
+++ b/src/text_file_functions.cpp
@@ -73,6 +73,13 @@ bool AOApplication::get_log_timestamp()
return result.startsWith("true");
}
+bool AOApplication::get_log_ic_actions()
+{
+ QString result =
+ configini->value("log_ic_actions", "true").value<QString>();
+ return result.startsWith("true");
+}
+
bool AOApplication::get_showname_enabled_by_default()
{
QString result =
@@ -618,12 +625,15 @@ QString AOApplication::get_char_side(QString p_char)
return f_result;
}
-QString AOApplication::get_gender(QString p_char)
+QString AOApplication::get_blips(QString p_char)
{
- QString f_result = read_char_ini(p_char, "gender", "Options");
+ QString f_result = read_char_ini(p_char, "blips", "Options");
- if (f_result == "")
- f_result = "male";
+ if (f_result == "") {
+ f_result = read_char_ini(p_char, "gender", "Options"); // not very PC, FanatSors
+ if (f_result == "")
+ f_result = "male";
+ }
if (!file_exists(get_sfx_suffix(get_sounds_path(f_result)))) {
if (file_exists(get_sfx_suffix(get_sounds_path("../blips/" + f_result))))
@@ -636,6 +646,8 @@ QString AOApplication::get_gender(QString p_char)
QString AOApplication::get_chat(QString p_char)
{
+ if (p_char == "default")
+ return "default";
QString f_result = read_char_ini(p_char, "chat", "Options");
// handling the correct order of chat is a bit complicated, we let the caller