summaryrefslogtreecommitdiff
path: root/src/net/tmwa
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/tmwa')
-rw-r--r--src/net/tmwa/abilityhandler.cpp2
-rw-r--r--src/net/tmwa/beinghandler.cpp20
-rw-r--r--src/net/tmwa/buysellhandler.cpp2
-rw-r--r--src/net/tmwa/charserverhandler.cpp18
-rw-r--r--src/net/tmwa/charserverhandler.h3
-rw-r--r--src/net/tmwa/chathandler.cpp5
-rw-r--r--src/net/tmwa/gamehandler.cpp6
-rw-r--r--src/net/tmwa/generalhandler.cpp2
-rw-r--r--src/net/tmwa/gui/partytab.cpp3
-rw-r--r--src/net/tmwa/inventoryhandler.cpp22
-rw-r--r--src/net/tmwa/inventoryhandler.h7
-rw-r--r--src/net/tmwa/loginhandler.cpp18
-rw-r--r--src/net/tmwa/messagein.cpp2
-rw-r--r--src/net/tmwa/messageout.cpp5
-rw-r--r--src/net/tmwa/network.cpp47
-rw-r--r--src/net/tmwa/network.h2
-rw-r--r--src/net/tmwa/partyhandler.cpp4
-rw-r--r--src/net/tmwa/playerhandler.cpp116
-rw-r--r--src/net/tmwa/playerhandler.h13
-rw-r--r--src/net/tmwa/protocol.h20
-rw-r--r--src/net/tmwa/token.h22
21 files changed, 246 insertions, 93 deletions
diff --git a/src/net/tmwa/abilityhandler.cpp b/src/net/tmwa/abilityhandler.cpp
index ab891b40..fea492ef 100644
--- a/src/net/tmwa/abilityhandler.cpp
+++ b/src/net/tmwa/abilityhandler.cpp
@@ -129,7 +129,7 @@ void AbilityHandler::handleMessage(MessageIn &msg)
auto type = msg.readInt8();
if (btype == BSKILL_EMOTE)
{
- logger->log("Action: %d", btype);
+ Log::info("Action: %d", btype);
}
std::string msg;
diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp
index c5979e9f..d2fd4695 100644
--- a/src/net/tmwa/beinghandler.cpp
+++ b/src/net/tmwa/beinghandler.cpp
@@ -33,9 +33,9 @@
#include "playerrelations.h"
#include "net/net.h"
-#include "net/playerhandler.h"
#include "net/tmwa/messagein.h"
#include "net/tmwa/messageout.h"
+#include "net/tmwa/playerhandler.h"
#include "net/tmwa/protocol.h"
#include "resources/emotedb.h"
@@ -107,6 +107,12 @@ static Being *createBeing(int id, short job)
outMsg.writeInt32(id);
}
+ if (type == ActorSprite::NPC)
+ {
+ auto playerHandler = static_cast<TmwAthena::PlayerHandler*>(Net::getPlayerHandler());
+ playerHandler->applyQuestStatusEffects(being);
+ }
+
return being;
}
@@ -211,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;
@@ -299,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));
@@ -525,8 +531,8 @@ void BeingHandler::handleMessage(MessageIn &msg)
dstBeing->setSprite(SPRITE_MISC2, id);
break;
default:
- logger->log("SMSG_BEING_CHANGE_LOOKS2: unsupported type: "
- "%d, id: %d", static_cast<int>(type), id);
+ Log::info("SMSG_BEING_CHANGE_LOOKS2: unsupported type: "
+ "%d, id: %d", static_cast<int>(type), id);
break;
}
}
diff --git a/src/net/tmwa/buysellhandler.cpp b/src/net/tmwa/buysellhandler.cpp
index 1fdf1ffe..d7acd674 100644
--- a/src/net/tmwa/buysellhandler.cpp
+++ b/src/net/tmwa/buysellhandler.cpp
@@ -99,7 +99,7 @@ void BuySellHandler::handleMessage(MessageIn &msg)
Item *item = PlayerInfo::getInventory()->getItem(index);
- if (item && !(item->isEquipped()))
+ if (item && !item->isEquipped())
dialog->addItem(item, value);
}
}
diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp
index 0ecbb135..f248388b 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"
@@ -89,8 +90,8 @@ void CharServerHandler::handleMessage(MessageIn &msg)
auto *character = new Net::Character;
readPlayerData(msg, character);
mCharacters.push_back(character);
- logger->log("CharServer: Player: %s (%d)",
- character->dummy->getName().c_str(), character->slot);
+ Log::info("CharServer: Player: %s (%d)",
+ character->dummy->getName().c_str(), character->slot);
}
Client::setState(STATE_CHAR_SELECT);
@@ -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,7 @@ 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);
+ tempPlayer->setGender(sexToGender(static_cast<SEX>(msg.readInt8())));
}
void CharServerHandler::setCharSelectDialog(CharSelectDialog *window)
@@ -306,7 +306,9 @@ void CharServerHandler::setCharCreateDialog(CharCreateDialog *window)
sumStat = Attributes::getCreationPoints();
mCharCreateDialog->setAttributes(attributes, sumStat, minStat, maxStat);
- mCharCreateDialog->setDefaultGender(token.sex);
+
+ if (token.sex != SEX::UNSPECIFIED)
+ mCharCreateDialog->setDefaultGender(sexToGender(token.sex));
}
void CharServerHandler::requestCharacters()
@@ -324,7 +326,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 +402,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/chathandler.cpp b/src/net/tmwa/chathandler.cpp
index f9061f63..cce5a41d 100644
--- a/src/net/tmwa/chathandler.cpp
+++ b/src/net/tmwa/chathandler.cpp
@@ -193,7 +193,10 @@ void ChatHandler::handleMessage(MessageIn &msg)
trim(chatMsg);
std::string reducedMessage = chatMsg;
- chatMsg = removeColors(sender_name) + " : " + reducedMessage;
+ chatMsg = sender_name;
+ removeColors(chatMsg);
+ chatMsg += " : ";
+ chatMsg += reducedMessage;
Event event(Event::Being);
event.setString("message", chatMsg);
diff --git a/src/net/tmwa/gamehandler.cpp b/src/net/tmwa/gamehandler.cpp
index 0a3bb9d9..f16a133b 100644
--- a/src/net/tmwa/gamehandler.cpp
+++ b/src/net/tmwa/gamehandler.cpp
@@ -68,8 +68,8 @@ void GameHandler::handleMessage(MessageIn &msg)
msg.readInt32(); // server tick
msg.readCoordinates(x, y, direction);
msg.skip(2); // unknown
- logger->log("Protocol: Player start position: (%d, %d), Direction: %d",
- x, y, direction);
+ Log::info("Protocol: Player start position: (%d, %d), Direction: %d",
+ x, y, direction);
// Switch now or we'll have problems
Client::setState(STATE_GAME);
// Stores the position until the map is loaded.
@@ -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/generalhandler.cpp b/src/net/tmwa/generalhandler.cpp
index d6eb3b34..1f52c3db 100644
--- a/src/net/tmwa/generalhandler.cpp
+++ b/src/net/tmwa/generalhandler.cpp
@@ -117,7 +117,7 @@ void GeneralHandler::handleMessage(MessageIn &msg)
{
case SMSG_CONNECTION_PROBLEM:
code = msg.readInt8();
- logger->log("Connection problem: %i", code);
+ Log::info("Connection problem: %i", code);
switch (code)
{
diff --git a/src/net/tmwa/gui/partytab.cpp b/src/net/tmwa/gui/partytab.cpp
index 418e0843..ee29757a 100644
--- a/src/net/tmwa/gui/partytab.cpp
+++ b/src/net/tmwa/gui/partytab.cpp
@@ -32,14 +32,13 @@
#include "resources/theme.h"
#include "utils/gettext.h"
-#include "utils/stringutils.h"
namespace TmwAthena {
PartyTab::PartyTab() :
ChatTab(_("Party"))
{
- setTabColor(&Theme::getThemeColor(Theme::PARTY_CHAT_TAB));
+ setTabColor(&Theme::getThemeColor(Theme::PARTY_TAB));
}
void PartyTab::handleInput(const std::string &msg)
diff --git a/src/net/tmwa/inventoryhandler.cpp b/src/net/tmwa/inventoryhandler.cpp
index 0d8e3005..73d967a6 100644
--- a/src/net/tmwa/inventoryhandler.cpp
+++ b/src/net/tmwa/inventoryhandler.cpp
@@ -157,10 +157,10 @@ void InventoryHandler::handleMessage(MessageIn &msg)
if (debugInventory)
{
- logger->log("Index: %d, ID: %d, Type: %d, Identified: %d, "
- "Qty: %d, Cards: %d, %d, %d, %d",
- index, itemId, itemType, identified, amount,
- cards[0], cards[1], cards[2], cards[3]);
+ Log::info("Index: %d, ID: %d, Type: %d, Identified: %d, "
+ "Qty: %d, Cards: %d, %d, %d, %d",
+ index, itemId, itemType, identified, amount,
+ cards[0], cards[1], cards[2], cards[3]);
}
if (msg.getId() == SMSG_PLAYER_INVENTORY)
@@ -191,10 +191,10 @@ void InventoryHandler::handleMessage(MessageIn &msg)
if (debugInventory)
{
- logger->log("Index: %d, ID: %d, Type: %d, Identified: %d, "
- "Qty: %d, Cards: %d, %d, %d, %d",
- index, itemId, itemType, identified, amount,
- cards[0], cards[1], cards[2], cards[3]);
+ Log::info("Index: %d, ID: %d, Type: %d, Identified: %d, "
+ "Qty: %d, Cards: %d, %d, %d, %d",
+ index, itemId, itemType, identified, amount,
+ cards[0], cards[1], cards[2], cards[3]);
}
mInventoryItems.push_back(
@@ -419,8 +419,8 @@ void InventoryHandler::handleMessage(MessageIn &msg)
}
else
{
- logger->log("Couldn't set attacke range due to the lack"
- "of an initialized map.");
+ Log::info("Couldn't set attacke range due to the lack"
+ "of an initialized map.");
local_player->setAttackRange(-1);
}
}
@@ -434,7 +434,7 @@ void InventoryHandler::handleMessage(MessageIn &msg)
index -= INVENTORY_OFFSET;
- logger->log("Arrows equipped: %i", index);
+ Log::info("Arrows equipped: %i", index);
mEquips.setEquipment(EQUIP_PROJECTILE_SLOT, index);
break;
}
diff --git a/src/net/tmwa/inventoryhandler.h b/src/net/tmwa/inventoryhandler.h
index 47226bea..cde1235b 100644
--- a/src/net/tmwa/inventoryhandler.h
+++ b/src/net/tmwa/inventoryhandler.h
@@ -23,6 +23,7 @@
#include "eventlistener.h"
#include "inventory.h"
+#include "item.h"
#include "log.h"
#include "playerinfo.h"
@@ -107,9 +108,9 @@ class EquipBackend final : public Equipment::Backend
if (!newItem && inventoryIndex >= 0)
{
- logger->log("EquipBackend: Warning, trying to equip "
- "non-existing item from inventory index %i at "
- "equipment slot %i.", inventoryIndex, index);
+ Log::info("EquipBackend: Warning, trying to equip "
+ "non-existing item from inventory index %i at "
+ "equipment slot %i.", inventoryIndex, index);
return;
}
diff --git a/src/net/tmwa/loginhandler.cpp b/src/net/tmwa/loginhandler.cpp
index a7162ee6..fba8c9f8 100644
--- a/src/net/tmwa/loginhandler.cpp
+++ b/src/net/tmwa/loginhandler.cpp
@@ -108,7 +108,7 @@ void LoginHandler::handleMessage(MessageIn &msg)
mUpdateHost = msg.readString(len);
loginData.updateHost = mUpdateHost;
- logger->log("Received update host \"%s\" from login server.",
+ Log::info("Received update host \"%s\" from login server.",
mUpdateHost.c_str());
break;
}
@@ -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++)
{
@@ -138,10 +138,10 @@ void LoginHandler::handleMessage(MessageIn &msg)
msg.readInt16(); // maintenance
msg.readInt16(); // is_new
- logger->log("Network: Server: %s (%s:%d)",
- world->name.c_str(),
- ipToString(world->address),
- world->port);
+ Log::info("Network: Server: %s (%s:%d)",
+ world->name.c_str(),
+ ipToString(world->address),
+ world->port);
mWorlds.push_back(world);
}
@@ -150,7 +150,7 @@ void LoginHandler::handleMessage(MessageIn &msg)
case SMSG_LOGIN_ERROR:
code = msg.readInt8();
- logger->log("Login::error code: %i", code);
+ Log::info("Login::error code: %i", code);
switch (code)
{
@@ -212,9 +212,9 @@ void LoginHandler::handleMessage(MessageIn &msg)
mServerVersion = 0;
if (mServerVersion > 0)
- logger->log("TMW server version: x%06x", mServerVersion);
+ Log::info("TMW server version: x%06x", mServerVersion);
else
- logger->log("Server without version");
+ Log::info("Server without version");
mRegistrationEnabled = (options & FLAG_REGISTRATION);
diff --git a/src/net/tmwa/messagein.cpp b/src/net/tmwa/messagein.cpp
index c0db0fca..2630c511 100644
--- a/src/net/tmwa/messagein.cpp
+++ b/src/net/tmwa/messagein.cpp
@@ -26,9 +26,11 @@
#include <SDL_endian.h>
+#ifndef MAKEWORD
#define MAKEWORD(low,high) \
((unsigned short)(((unsigned char)(low)) | \
((unsigned short)((unsigned char)(high))) << 8))
+#endif
namespace TmwAthena {
diff --git a/src/net/tmwa/messageout.cpp b/src/net/tmwa/messageout.cpp
index 12c9419a..7758e306 100644
--- a/src/net/tmwa/messageout.cpp
+++ b/src/net/tmwa/messageout.cpp
@@ -23,6 +23,8 @@
#include "net/tmwa/network.h"
+#include "log.h"
+
#include <SDL_endian.h>
#include <cstring>
@@ -31,6 +33,9 @@ namespace TmwAthena {
MessageOut::MessageOut(uint16_t id)
{
+#ifdef DEBUG
+ Log::info("Sending %s (0x%x)", Network::mInstance->messageName(id), id);
+#endif
writeInt16(id);
}
diff --git a/src/net/tmwa/network.cpp b/src/net/tmwa/network.cpp
index 353495da..9e010f7c 100644
--- a/src/net/tmwa/network.cpp
+++ b/src/net/tmwa/network.cpp
@@ -45,9 +45,9 @@ struct PacketInfo
};
// indicator for a variable-length packet
-const uint16_t VAR = 1;
+constexpr uint16_t VAR = 1;
-static const PacketInfo packet_infos[] = {
+static constexpr PacketInfo packet_infos[] = {
// login server messages
{ SMSG_UPDATE_HOST, VAR, "SMSG_UPDATE_HOST" },
{ CMSG_LOGIN_REGISTER, 55, "CMSG_LOGIN_REGISTER" },
@@ -279,7 +279,7 @@ bool Network::connect(const ServerInfo &server)
{
if (mState != IDLE && mState != NET_ERROR)
{
- logger->log("Tried to connect an already connected socket!");
+ Log::info("Tried to connect an already connected socket!");
assert(false);
return false;
}
@@ -290,8 +290,8 @@ bool Network::connect(const ServerInfo &server)
return false;
}
- logger->log("Network::Connecting to %s:%i", server.hostname.c_str(),
- server.port);
+ Log::info("Network::Connecting to %s:%i", server.hostname.c_str(),
+ server.port);
mServer.hostname = server.hostname;
mServer.port = server.port;
@@ -353,6 +353,15 @@ void Network::clearHandlers()
mMessageHandlers.clear();
}
+const char *Network::messageName(uint16_t id) const
+{
+ auto packetInfoIt = mPacketInfo.find(id);
+ if (packetInfoIt != mPacketInfo.end())
+ return packetInfoIt->second->name;
+
+ return "Unknown";
+}
+
void Network::dispatchMessages()
{
MutexLocker lock(&mMutex);
@@ -367,8 +376,7 @@ void Network::dispatchMessages()
auto packetInfoIt = mPacketInfo.find(msgId);
if (packetInfoIt == mPacketInfo.end())
{
- auto error = strprintf("Unknown packet 0x%x received.", msgId);
- logger->error(error);
+ Log::critical(strprintf("Unknown packet 0x%x received.", msgId));
break;
}
@@ -386,9 +394,8 @@ void Network::dispatchMessages()
if (len < 4)
{
- auto error = strprintf("Variable length packet 0x%x has invalid length %d.",
- msgId, len);
- logger->error(error);
+ Log::critical(strprintf("Variable length packet 0x%x has invalid length %d.",
+ msgId, len));
break;
}
}
@@ -404,14 +411,14 @@ void Network::dispatchMessages()
if (iter != mMessageHandlers.end())
{
#ifdef DEBUG
- logger->log("Handling %s (0x%x) of length %d", packetInfo->name, msgId, len);
+ Log::info("Handling %s (0x%x) of length %d", packetInfo->name, msgId, len);
#endif
iter->second->handleMessage(message);
}
else
{
- logger->log("Unhandled %s (0x%x) of length %d", packetInfo->name, msgId, len);
+ Log::info("Unhandled %s (0x%x) of length %d", packetInfo->name, msgId, len);
}
skip(len);
@@ -465,7 +472,7 @@ bool Network::realConnect()
std::string errorMessage = strprintf(_("Unable to resolve host \"%s\""),
mServer.hostname.c_str());
setError(errorMessage);
- logger->log("SDLNet_ResolveHost: %s", errorMessage.c_str());
+ Log::info("SDLNet_ResolveHost: %s", errorMessage.c_str());
return false;
}
@@ -474,13 +481,13 @@ bool Network::realConnect()
mSocket = SDLNet_TCP_Open(&ipAddress);
if (!mSocket)
{
- logger->log("Error in SDLNet_TCP_Open(): %s", SDLNet_GetError());
+ Log::info("Error in SDLNet_TCP_Open(): %s", SDLNet_GetError());
setError(SDLNet_GetError());
return false;
}
- logger->log("Network::Started session with %s:%i",
- ipToString(ipAddress.host), ipAddress.port);
+ Log::info("Network::Started session with %s:%i",
+ ipToString(ipAddress.host), ipAddress.port);
mState = CONNECTED;
@@ -513,7 +520,7 @@ void Network::receive()
switch (numReady)
{
case -1:
- logger->log("Error: SDLNet_CheckSockets");
+ Log::error("SDLNet_CheckSockets");
// FALLTHROUGH
case 0:
break;
@@ -528,7 +535,7 @@ void Network::receive()
{
// We got disconnected
mState = IDLE;
- logger->log("Disconnected.");
+ Log::info("Disconnected.");
}
else if (ret < 0)
{
@@ -569,7 +576,7 @@ void Network::receive()
if (SDLNet_TCP_DelSocket(set, mSocket) == -1)
{
- logger->log("Error in SDLNet_DelSocket(): %s", SDLNet_GetError());
+ Log::info("Error in SDLNet_DelSocket(): %s", SDLNet_GetError());
}
SDLNet_FreeSocketSet(set);
@@ -577,7 +584,7 @@ void Network::receive()
void Network::setError(const std::string &error)
{
- logger->log("Network error: %s", error.c_str());
+ Log::info("Network error: %s", error.c_str());
mError = error;
mState = NET_ERROR;
}
diff --git a/src/net/tmwa/network.h b/src/net/tmwa/network.h
index 53f15761..b27d1eda 100644
--- a/src/net/tmwa/network.h
+++ b/src/net/tmwa/network.h
@@ -66,6 +66,8 @@ class Network
void clearHandlers();
+ const char *messageName(uint16_t id) const;
+
int getState() const { return mState; }
const std::string &getError() const { return mError; }
diff --git a/src/net/tmwa/partyhandler.cpp b/src/net/tmwa/partyhandler.cpp
index 2b256cd5..78dfd7a0 100644
--- a/src/net/tmwa/partyhandler.cpp
+++ b/src/net/tmwa/partyhandler.cpp
@@ -184,7 +184,7 @@ void PartyHandler::handleMessage(MessageIn &msg)
partyTab->chatLog(_("Experience sharing not possible."), BY_SERVER);
break;
default:
- logger->log("Unknown party exp option: %d", exp);
+ Log::info("Unknown party exp option: %d", exp);
}
switch (item)
@@ -208,7 +208,7 @@ void PartyHandler::handleMessage(MessageIn &msg)
partyTab->chatLog(_("Item sharing not possible."), BY_SERVER);
break;
default:
- logger->log("Unknown party item option: %d", exp);
+ Log::info("Unknown party item option: %d", exp);
}
break;
}
diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp
index f6f6ef41..44b0efd3 100644
--- a/src/net/tmwa/playerhandler.cpp
+++ b/src/net/tmwa/playerhandler.cpp
@@ -21,8 +21,11 @@
#include "net/tmwa/playerhandler.h"
+#include "actorspritemanager.h"
+#include "being.h"
#include "client.h"
#include "configuration.h"
+#include "effectmanager.h"
#include "game.h"
#include "localplayer.h"
#include "log.h"
@@ -55,7 +58,7 @@ const int MAP_TELEPORT_SCROLL_DISTANCE = 8;
namespace {
/**
- * Listener used for handling the overweigth message.
+ * Listener used for handling the overweight message.
*/
struct WeightListener : public gcn::ActionListener
{
@@ -126,7 +129,7 @@ static const char *randomDeathMessage()
N_("You're off the twig."),
N_("You've kicked the bucket."),
N_("You've shuffled off your mortal coil, run down the "
- "curtain and joined the bleedin' choir invisibile."),
+ "curtain and joined the bleedin' choir invisible."),
N_("You are an ex-player."),
N_("You're pining for the fjords.")
};
@@ -152,10 +155,14 @@ PlayerHandler::PlayerHandler()
SMSG_PLAYER_STAT_UPDATE_6,
SMSG_PLAYER_ARROW_MESSAGE,
SMSG_MAP_MASK,
+ SMSG_QUEST_SET_VAR,
+ SMSG_QUEST_PLAYER_VARS,
0
};
handledMessages = _messages;
playerHandler = this;
+
+ listen(Event::GameChannel);
}
void PlayerHandler::handleMessage(MessageIn &msg)
@@ -179,7 +186,7 @@ void PlayerHandler::handleMessage(MessageIn &msg)
int x = msg.readInt16();
int y = msg.readInt16();
- logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y);
+ Log::info("Warping to %s (%d, %d)", mapPath.c_str(), x, y);
/*
* We must clear the local player's target *before* the call
@@ -217,8 +224,8 @@ void PlayerHandler::handleMessage(MessageIn &msg)
// Stop movement
local_player->setDestination(pos.x, pos.y);
- logger->log("Adjust scrolling by %d:%d", (int) scrollOffsetX,
- (int) scrollOffsetY);
+ Log::info("Adjust scrolling by %d:%d", (int) scrollOffsetX,
+ (int) scrollOffsetY);
viewport->scrollBy(scrollOffsetX, scrollOffsetY);
}
@@ -499,7 +506,7 @@ void PlayerHandler::handleMessage(MessageIn &msg)
serverNotice(_("Equip arrows first."));
break;
default:
- logger->log("0x013b: Unhandled message %i", type);
+ Log::info("0x013b: Unhandled message %i", type);
break;
}
}
@@ -514,6 +521,49 @@ void PlayerHandler::handleMessage(MessageIn &msg)
map->setMask(mask);
}
break;
+
+ case SMSG_QUEST_SET_VAR:
+ {
+ int variable = msg.readInt16();
+ int value = msg.readInt32();
+ int oldValue = mQuestVars.get(variable);
+
+ mQuestVars.set(variable, value);
+ updateQuestStatusEffects();
+ Event::trigger(Event::QuestsChannel, Event::QuestVarsChanged);
+
+ if (effectManager && local_player)
+ {
+ switch (QuestDB::questChange(variable, oldValue, value))
+ {
+ case QuestChange::None:
+ break;
+ case QuestChange::New:
+ effectManager->trigger(paths.getIntValue("newQuestEffectId"), local_player);
+ break;
+ case QuestChange::Completed:
+ effectManager->trigger(paths.getIntValue("completeQuestEffectId"), local_player);
+ break;
+ }
+ }
+ break;
+ }
+
+ case SMSG_QUEST_PLAYER_VARS:
+ {
+ msg.readInt16(); // length
+ mQuestVars.clear();
+ unsigned int count = (msg.getLength() - 4) / 6;
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ int variable = msg.readInt16();
+ int value = msg.readInt32();
+ mQuestVars.set(variable, value);
+ }
+ updateQuestStatusEffects();
+ Event::trigger(Event::QuestsChannel, Event::QuestVarsChanged);
+ break;
+ }
}
}
@@ -649,8 +699,8 @@ Vector PlayerHandler::getPixelsPerSecondMoveSpeed(const Vector &speed, Map *map)
if (!map || speed.x == 0 || speed.y == 0)
{
- logger->log("TmwAthena::PlayerHandler: Speed set to default: "
- "Map not yet initialized or invalid speed.");
+ Log::info("TmwAthena::PlayerHandler: Speed set to default: "
+ "Map not yet initialized or invalid speed.");
return getDefaultMoveSpeed();
}
@@ -664,4 +714,54 @@ Vector PlayerHandler::getPixelsPerSecondMoveSpeed(const Vector &speed, Map *map)
return pixelsPerSecond;
}
+void PlayerHandler::event(Event::Channel channel, const Event &event)
+{
+ if (channel == Event::GameChannel)
+ {
+ if (event.getType() == Event::MapLoaded)
+ {
+ updateQuestStatusEffects();
+ }
+ }
+}
+
+void PlayerHandler::applyQuestStatusEffects(Being *npc)
+{
+ const auto npcId = npc->getSubType();
+ const auto effect = mActiveQuestEffects.get(npcId);
+ if (effect != 0)
+ npc->setStatusEffect(effect, true);
+}
+
+void PlayerHandler::updateQuestStatusEffects()
+{
+ auto game = Game::instance();
+ if (!game)
+ return;
+
+ const auto &currentMapName = game->getCurrentMapName();
+ auto updatedQuestEffects = QuestDB::getActiveEffects(mQuestVars, currentMapName);
+
+ // Loop over all NPCs, disabling no longer active effects and enabling new ones
+ for (auto actor : actorSpriteManager->getAll()) {
+ if (actor->getType() != ActorSprite::NPC)
+ continue;
+
+ auto *npc = static_cast<Being *>(actor);
+ const auto npcId = npc->getSubType();
+ const auto oldEffect = mActiveQuestEffects.get(npcId);
+ const auto newEffect = updatedQuestEffects.get(npcId);
+
+ if (oldEffect != newEffect)
+ {
+ if (oldEffect != 0)
+ npc->setStatusEffect(oldEffect, false);
+ if (newEffect != 0)
+ npc->setStatusEffect(newEffect, true);
+ }
+ }
+
+ std::swap(mActiveQuestEffects, updatedQuestEffects);
+}
+
} // namespace TmwAthena
diff --git a/src/net/tmwa/playerhandler.h b/src/net/tmwa/playerhandler.h
index f1a67e94..49990d85 100644
--- a/src/net/tmwa/playerhandler.h
+++ b/src/net/tmwa/playerhandler.h
@@ -28,7 +28,8 @@
namespace TmwAthena {
-class PlayerHandler final : public MessageHandler, public Net::PlayerHandler
+class PlayerHandler final : public MessageHandler, public Net::PlayerHandler,
+ public EventListener
{
public:
PlayerHandler();
@@ -63,6 +64,16 @@ class PlayerHandler final : public MessageHandler, public Net::PlayerHandler
bool usePixelPrecision() override
{ return false; }
+
+ // EventListener
+ void event(Event::Channel channel, const Event &event) override;
+
+ void applyQuestStatusEffects(Being *npc);
+
+ private:
+ void updateQuestStatusEffects();
+
+ QuestEffectMap mActiveQuestEffects;
};
} // namespace TmwAthena
diff --git a/src/net/tmwa/protocol.h b/src/net/tmwa/protocol.h
index 532ac90e..b93c81e1 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,24 @@ 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;
+ default: return Gender::Neutral;
+ }
+}
+
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