diff options
Diffstat (limited to 'src/net/tmwa')
-rw-r--r-- | src/net/tmwa/abilityhandler.cpp | 2 | ||||
-rw-r--r-- | src/net/tmwa/beinghandler.cpp | 20 | ||||
-rw-r--r-- | src/net/tmwa/buysellhandler.cpp | 2 | ||||
-rw-r--r-- | src/net/tmwa/charserverhandler.cpp | 18 | ||||
-rw-r--r-- | src/net/tmwa/charserverhandler.h | 3 | ||||
-rw-r--r-- | src/net/tmwa/chathandler.cpp | 5 | ||||
-rw-r--r-- | src/net/tmwa/gamehandler.cpp | 6 | ||||
-rw-r--r-- | src/net/tmwa/generalhandler.cpp | 2 | ||||
-rw-r--r-- | src/net/tmwa/gui/partytab.cpp | 3 | ||||
-rw-r--r-- | src/net/tmwa/inventoryhandler.cpp | 22 | ||||
-rw-r--r-- | src/net/tmwa/inventoryhandler.h | 7 | ||||
-rw-r--r-- | src/net/tmwa/loginhandler.cpp | 18 | ||||
-rw-r--r-- | src/net/tmwa/messagein.cpp | 2 | ||||
-rw-r--r-- | src/net/tmwa/messageout.cpp | 5 | ||||
-rw-r--r-- | src/net/tmwa/network.cpp | 47 | ||||
-rw-r--r-- | src/net/tmwa/network.h | 2 | ||||
-rw-r--r-- | src/net/tmwa/partyhandler.cpp | 4 | ||||
-rw-r--r-- | src/net/tmwa/playerhandler.cpp | 116 | ||||
-rw-r--r-- | src/net/tmwa/playerhandler.h | 13 | ||||
-rw-r--r-- | src/net/tmwa/protocol.h | 20 | ||||
-rw-r--r-- | src/net/tmwa/token.h | 22 |
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 ¤tMapName = 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 |