diff options
author | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2025-07-17 15:09:11 +0200 |
---|---|---|
committer | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2025-08-04 20:51:09 +0200 |
commit | bc29cbb38913abf66c794a134afe62ab8acf70b4 (patch) | |
tree | c38bc839b42865ace4d1cda5ba2a67d5078d2cac | |
parent | e6dceba196e5bc8e305101c63add0c76a3912ff0 (diff) | |
download | mana-bc29cbb38913abf66c794a134afe62ab8acf70b4.tar.gz mana-bc29cbb38913abf66c794a134afe62ab8acf70b4.tar.bz2 mana-bc29cbb38913abf66c794a134afe62ab8acf70b4.tar.xz mana-bc29cbb38913abf66c794a134afe62ab8acf70b4.zip |
Added support for the hidden/neutral gender
TMWA supports a "neutral" gender, which in Mana client maps to "hidden". In
The Mana World, it means a player character is not displayed as clearly male
or female, using a dedicated base sprite with more underwear.
It is not possible to choose the neutral gender on account registration or
character creation. In TMW, these choices are not actually relevant anyway
and could probably be removed.
Fixes #114
-rw-r--r-- | src/gui/charcreatedialog.cpp | 4 | ||||
-rw-r--r-- | src/net/charhandler.h | 2 | ||||
-rw-r--r-- | src/net/manaserv/charhandler.cpp | 4 | ||||
-rw-r--r-- | src/net/manaserv/charhandler.h | 2 | ||||
-rw-r--r-- | src/net/tmwa/beinghandler.cpp | 8 | ||||
-rw-r--r-- | src/net/tmwa/charserverhandler.cpp | 17 | ||||
-rw-r--r-- | src/net/tmwa/charserverhandler.h | 3 | ||||
-rw-r--r-- | src/net/tmwa/gamehandler.cpp | 2 | ||||
-rw-r--r-- | src/net/tmwa/loginhandler.cpp | 2 | ||||
-rw-r--r-- | src/net/tmwa/protocol.h | 22 | ||||
-rw-r--r-- | src/net/tmwa/token.h | 22 |
11 files changed, 56 insertions, 32 deletions
diff --git a/src/gui/charcreatedialog.cpp b/src/gui/charcreatedialog.cpp index cff7d822..6b46d2ac 100644 --- a/src/gui/charcreatedialog.cpp +++ b/src/gui/charcreatedialog.cpp @@ -191,8 +191,10 @@ void CharCreateDialog::action(const gcn::ActionEvent &event) 0 : mHairStylesIds.at(mHairStyleId); int hairColor = mHairColorsIds.empty() ? 0 : mHairColorsIds.at(mHairColorId); + + Gender gender = mFemale->isSelected() ? Gender::Female : Gender::Male; Net::getCharHandler()->newCharacter(getName(), characterSlot, - mFemale->isSelected(), + gender, hairStyle, hairColor, mAttributes); } diff --git a/src/net/charhandler.h b/src/net/charhandler.h index 3f0c096f..c04cf81e 100644 --- a/src/net/charhandler.h +++ b/src/net/charhandler.h @@ -62,7 +62,7 @@ class CharHandler virtual void chooseCharacter(Net::Character *character) = 0; virtual void newCharacter(const std::string &name, int slot, - bool gender, int hairstyle, int hairColor, + Gender gender, int hairstyle, int hairColor, const std::vector<int> &stats) = 0; virtual void deleteCharacter(Net::Character *character) = 0; diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp index cc0ea17e..8d7c5511 100644 --- a/src/net/manaserv/charhandler.cpp +++ b/src/net/manaserv/charhandler.cpp @@ -339,7 +339,7 @@ void CharHandler::chooseCharacter(Net::Character *character) void CharHandler::newCharacter(const std::string &name, int slot, - bool gender, + Gender gender, int hairstyle, int hairColor, const std::vector<int> &stats) @@ -349,7 +349,7 @@ void CharHandler::newCharacter(const std::string &name, msg.writeString(name); msg.writeInt8(hairstyle); msg.writeInt8(hairColor); - msg.writeInt8(gender); + msg.writeInt8(gender == Gender::Female); msg.writeInt8(slot); for (int stat : stats) diff --git a/src/net/manaserv/charhandler.h b/src/net/manaserv/charhandler.h index e962bdfa..c26194ee 100644 --- a/src/net/manaserv/charhandler.h +++ b/src/net/manaserv/charhandler.h @@ -59,7 +59,7 @@ class CharHandler final : public MessageHandler, public Net::CharHandler void chooseCharacter(Net::Character *character) override; void newCharacter(const std::string &name, int slot, - bool gender, int hairstyle, int hairColor, + Gender gender, int hairstyle, int hairColor, const std::vector<int> &stats) override; void deleteCharacter(Net::Character *character) override; diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 690b0d87..d2fd4695 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -217,7 +217,8 @@ void BeingHandler::handleMessage(MessageIn &msg) return; int id; - short job, gender; + short job; + SEX sex; float speed; Uint16 headTop, headMid, headBottom; Uint16 shoes, gloves; @@ -305,12 +306,11 @@ void BeingHandler::handleMessage(MessageIn &msg) msg.readInt16(); // manner opt3 = msg.readInt16(); msg.readInt8(); // karma - gender = msg.readInt8(); + sex = static_cast<SEX>(msg.readInt8()); if (dstBeing->getType() == ActorSprite::PLAYER) { - dstBeing->setGender(gender == 0 ? Gender::Female - : Gender::Male); + dstBeing->setGender(sexToGender(sex)); // Set these after the gender, as the sprites may be gender-specific dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, hairDB.getHairColor(hairColor)); diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index fcd47b74..e8562bf9 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -36,6 +36,7 @@ #include "net/tmwa/messageout.h" #include "net/tmwa/network.h" #include "net/tmwa/protocol.h" +#include "net/tmwa/token.h" #include "resources/attributes.h" #include "resources/chardb.h" @@ -241,7 +242,7 @@ void CharServerHandler::readPlayerData(MessageIn &msg, Net::Character *character const uint16_t weapon = msg.readInt16(); auto *tempPlayer = new LocalPlayer(id, race); - tempPlayer->setGender(token.sex); + tempPlayer->setGender(sexToGender(token.sex)); tempPlayer->setSprite(SPRITE_SHOE, shoe); tempPlayer->setSprite(SPRITE_GLOVES, gloves); @@ -267,8 +268,9 @@ void CharServerHandler::readPlayerData(MessageIn &msg, Net::Character *character character->data.mStats[i + STRENGTH].base = msg.readInt8(); character->slot = msg.readInt8(); // character slot - const uint8_t sex = msg.readInt8(); - tempPlayer->setGender(sex ? Gender::Male : Gender::Female); + const Gender gender = sexToGender(static_cast<SEX>(msg.readInt8())); + if (gender != Gender::Unspecified) + tempPlayer->setGender(gender); } void CharServerHandler::setCharSelectDialog(CharSelectDialog *window) @@ -306,7 +308,10 @@ void CharServerHandler::setCharCreateDialog(CharCreateDialog *window) sumStat = Attributes::getCreationPoints(); mCharCreateDialog->setAttributes(attributes, sumStat, minStat, maxStat); - mCharCreateDialog->setDefaultGender(token.sex); + + const Gender gender = sexToGender(token.sex); + if (gender != Gender::Unspecified) + mCharCreateDialog->setDefaultGender(gender); } void CharServerHandler::requestCharacters() @@ -324,7 +329,7 @@ void CharServerHandler::chooseCharacter(Net::Character *character) } void CharServerHandler::newCharacter(const std::string &name, int slot, - bool gender, int hairstyle, int hairColor, + Gender /*gender*/, int hairstyle, int hairColor, const std::vector<int> &stats) { MessageOut outMsg(CMSG_CHAR_CREATE); @@ -400,7 +405,7 @@ void CharServerHandler::connect() // [Fate] The next word is unused by the old char server, so we squeeze in // mana client version information outMsg.writeInt16(CLIENT_PROTOCOL_VERSION); - outMsg.writeInt8(token.sex == Gender::Male ? 1 : 0); + outMsg.writeInt8(static_cast<uint8_t>(token.sex)); // We get 4 useless bytes before the real answer comes in (what are these?) mNetwork->skip(4); diff --git a/src/net/tmwa/charserverhandler.h b/src/net/tmwa/charserverhandler.h index b0d3e970..cb79f969 100644 --- a/src/net/tmwa/charserverhandler.h +++ b/src/net/tmwa/charserverhandler.h @@ -24,7 +24,6 @@ #include "net/charhandler.h" #include "net/tmwa/messagehandler.h" -#include "net/tmwa/token.h" class LoginData; @@ -53,7 +52,7 @@ class CharServerHandler final : public MessageHandler, public Net::CharHandler void chooseCharacter(Net::Character *character) override; - void newCharacter(const std::string &name, int slot, bool gender, + void newCharacter(const std::string &name, int slot, Gender gender, int hairstyle, int hairColor, const std::vector<int> &stats) override; diff --git a/src/net/tmwa/gamehandler.cpp b/src/net/tmwa/gamehandler.cpp index a88e377e..f16a133b 100644 --- a/src/net/tmwa/gamehandler.cpp +++ b/src/net/tmwa/gamehandler.cpp @@ -140,7 +140,7 @@ void GameHandler::connect() outMsg.writeInt32(mCharID); outMsg.writeInt32(token.session_ID1); outMsg.writeInt32(token.session_ID2); - outMsg.writeInt8(token.sex == Gender::Male ? 1 : 0); + outMsg.writeInt8(static_cast<uint8_t>(token.sex)); // We get 4 useless bytes before the real answer comes in (what are these?) mNetwork->skip(4); diff --git a/src/net/tmwa/loginhandler.cpp b/src/net/tmwa/loginhandler.cpp index b6e3d518..fba8c9f8 100644 --- a/src/net/tmwa/loginhandler.cpp +++ b/src/net/tmwa/loginhandler.cpp @@ -124,7 +124,7 @@ void LoginHandler::handleMessage(MessageIn &msg) mToken.account_ID = msg.readInt32(); mToken.session_ID2 = msg.readInt32(); msg.skip(30); // unused - mToken.sex = msg.readInt8() ? Gender::Male : Gender::Female; + mToken.sex = static_cast<SEX>(msg.readInt8()); for (int i = 0; i < worldCount; i++) { diff --git a/src/net/tmwa/protocol.h b/src/net/tmwa/protocol.h index 532ac90e..1f91616f 100644 --- a/src/net/tmwa/protocol.h +++ b/src/net/tmwa/protocol.h @@ -21,6 +21,8 @@ #pragma once +#include "being.h" + #include <cstdint> namespace TmwAthena { @@ -93,6 +95,26 @@ enum class DIR : uint8_t COUNT, }; +enum class SEX : uint8_t +{ + FEMALE = 0, + MALE = 1, + UNSPECIFIED = 2, + NEUTRAL = 3, +}; + +inline Gender sexToGender(SEX sex) +{ + switch (sex) + { + case SEX::FEMALE: return Gender::Female; + case SEX::MALE: return Gender::Male; + case SEX::UNSPECIFIED: return Gender::Unspecified; + case SEX::NEUTRAL: return Gender::Hidden; + } + return Gender::Unspecified; +} + enum NpcCommand { NPC_REQUEST_LANG = 0, diff --git a/src/net/tmwa/token.h b/src/net/tmwa/token.h index b563bf65..c24fbebb 100644 --- a/src/net/tmwa/token.h +++ b/src/net/tmwa/token.h @@ -19,22 +19,18 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "being.h" +#include "net/tmwa/protocol.h" #pragma once +namespace TmwAthena { + struct Token { - int account_ID; - int session_ID1; - int session_ID2; - Gender sex; - - void clear() - { - account_ID = 0; - session_ID1 = 0; - session_ID2 = 0; - sex = Gender::Unspecified; - } + int account_ID = 0; + int session_ID1 = 0; + int session_ID2 = 0; + SEX sex = SEX::UNSPECIFIED; }; + +} // namespace TmwAthena |