aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOsmium Sorcerer <os@sof.beauty>2026-03-22 17:30:03 +0000
committerOsmium Sorcerer <os@sof.beauty>2026-03-29 22:22:25 +0000
commit3b8bc386d316b6e177c814920f21f5ab5d798ee6 (patch)
treea19d60b323d8211a4d71594c2616ecbe78f2cef5 /src
parent39372432b78b3d0980b004903739539e565c0948 (diff)
Support passworded characters in character list
This obscure feature has been present for years, from sending passwords to the server to showing `char_passworded` image over character icons. Servers could already exploit clients sending `PW` with a password every time they select a character to implement passworded characters. The clients had no way of knowing which ones were passworded, however, and couldn't filter them despite "Passworded" checkbox being here all along. The approach used by this commit is a hack. During loading, server sends SC which is a list of characters, each one having name, description, and evidence. In practice, only names were used. Descriptions were stored in memory but unused, and evidence was ignored altogether. By adding a magic value "P" in this "character evidence" field, server can mark passworded characters without breaking Vanilla compatibility.
Diffstat (limited to 'src')
-rw-r--r--src/aocharbutton.cpp19
-rw-r--r--src/aocharbutton.h4
-rw-r--r--src/charselect.cpp15
-rw-r--r--src/courtroom.cpp1
-rw-r--r--src/datatypes.h1
-rw-r--r--src/packet_distribution.cpp5
6 files changed, 39 insertions, 6 deletions
diff --git a/src/aocharbutton.cpp b/src/aocharbutton.cpp
index d446cca3..fe87041f 100644
--- a/src/aocharbutton.cpp
+++ b/src/aocharbutton.cpp
@@ -11,6 +11,12 @@ AOCharButton::AOCharButton(AOApplication *ao_app, QWidget *parent)
resize(size, size);
+ ui_passworded = new AOImage(ao_app, this);
+ ui_passworded->setAttribute(Qt::WA_TransparentForMouseEvents);
+ ui_passworded->resize(size, size);
+ ui_passworded->setImage("char_passworded");
+ ui_passworded->hide();
+
ui_taken = new AOImage(ao_app, this);
ui_taken->setAttribute(Qt::WA_TransparentForMouseEvents);
ui_taken->resize(size, size);
@@ -24,6 +30,19 @@ AOCharButton::AOCharButton(AOApplication *ao_app, QWidget *parent)
ui_selector->hide();
}
+void AOCharButton::setPassworded(bool enabled)
+{
+ if (enabled)
+ {
+ ui_passworded->move(0, 0);
+ ui_passworded->show();
+ }
+ else
+ {
+ ui_passworded->hide();
+ }
+}
+
void AOCharButton::setTaken(bool enabled)
{
if (enabled)
diff --git a/src/aocharbutton.h b/src/aocharbutton.h
index ba618976..64bea50a 100644
--- a/src/aocharbutton.h
+++ b/src/aocharbutton.h
@@ -18,6 +18,8 @@ public:
void setCharacter(QString character);
+ void setPassworded(bool enabled);
+
void setTaken(bool enabled);
protected:
@@ -30,7 +32,9 @@ protected:
private:
AOApplication *ao_app;
+ bool m_passworded = false;
bool m_taken = false;
+ AOImage *ui_passworded;
AOImage *ui_taken;
AOImage *ui_selector;
};
diff --git a/src/charselect.cpp b/src/charselect.cpp
index 040bfd0e..2443393f 100644
--- a/src/charselect.cpp
+++ b/src/charselect.cpp
@@ -62,8 +62,8 @@ void Courtroom::construct_char_select()
connect(ui_spectator, &AOButton::clicked, this, &Courtroom::on_spectator_clicked);
connect(ui_char_search, &QLineEdit::textEdited, this, &Courtroom::on_char_search_changed);
- connect(ui_char_passworded, &QCheckBox::stateChanged, this, &Courtroom::on_char_passworded_clicked);
- connect(ui_char_taken, &QCheckBox::stateChanged, this, &Courtroom::on_char_taken_clicked);
+ connect(ui_char_passworded, &QCheckBox::checkStateChanged, this, &Courtroom::on_char_passworded_clicked);
+ connect(ui_char_taken, &QCheckBox::checkStateChanged, this, &Courtroom::on_char_taken_clicked);
}
void Courtroom::set_char_select()
@@ -300,6 +300,7 @@ void Courtroom::character_loading_finished()
char_button->setContextMenuPolicy(Qt::CustomContextMenu);
char_button->hide();
char_button->setCharacter(character.name);
+ char_button->setPassworded(character.passworded);
char_button->setTaken(character.taken);
char_button->setToolTip(character.name);
ui_char_button_list.append(char_button);
@@ -354,10 +355,11 @@ void Courtroom::filter_character_list()
AOCharButton *current_char = ui_char_button_list.at(i);
QTreeWidgetItem *current_char_list_item = ui_char_list->findItems(QString::number(i), Qt::MatchExactly | Qt::MatchRecursive, 1).at(0);
- // It seems passwording characters is unimplemented yet?
- // Until then, this will stay here, I suppose.
- // if (ui_char_passworded->isChecked() && character_is_passworded??)
- // continue;
+ if (!ui_char_passworded->isChecked() && char_list.at(i).passworded)
+ {
+ current_char_list_item->setHidden(true);
+ continue;
+ }
if (!ui_char_taken->isChecked() && char_list.at(i).taken)
{
@@ -375,6 +377,7 @@ void Courtroom::filter_character_list()
// for the buttons that actually appear.
// You'd also update the passwordedness and etc. here later.
current_char_list_item->setHidden(false);
+ current_char->setPassworded(char_list.at(i).passworded);
current_char->setTaken(char_list.at(i).taken);
current_char_list_item->setText(0, char_list.at(i).name);
// reset disabled
diff --git a/src/courtroom.cpp b/src/courtroom.cpp
index 0edef949..82caddd2 100644
--- a/src/courtroom.cpp
+++ b/src/courtroom.cpp
@@ -1357,6 +1357,7 @@ void Courtroom::set_taken(int n_char, bool p_taken)
CharacterSlot f_char;
f_char.name = char_list.at(n_char).name;
f_char.description = char_list.at(n_char).description;
+ f_char.passworded = char_list.at(n_char).passworded;
f_char.taken = p_taken;
f_char.evidence_string = char_list.at(n_char).evidence_string;
diff --git a/src/datatypes.h b/src/datatypes.h
index 0bc6b20f..a6231c45 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -10,6 +10,7 @@ struct CharacterSlot
QString name;
QString description;
QString evidence_string;
+ bool passworded;
bool taken;
};
diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp
index 6aa50368..066fc6be 100644
--- a/src/packet_distribution.cpp
+++ b/src/packet_distribution.cpp
@@ -223,10 +223,15 @@ void AOApplication::server_packet_received(AOPacket packet)
CharacterSlot f_char;
f_char.name = sub_elements.at(0);
+ f_char.passworded = false;
if (sub_elements.size() >= 2)
{
f_char.description = sub_elements.at(1);
}
+ if (sub_elements.size() >= 3)
+ {
+ f_char.passworded = sub_elements.at(2) == "P";
+ }
// temporary. the CharsCheck packet sets this properly
f_char.taken = false;