diff options
Diffstat (limited to 'src/net')
73 files changed, 1868 insertions, 1566 deletions
diff --git a/src/net/adminhandler.h b/src/net/adminhandler.h index 23e9abc0..3ed96dbd 100644 --- a/src/net/adminhandler.h +++ b/src/net/adminhandler.h @@ -29,6 +29,8 @@ namespace Net { class AdminHandler { public: + virtual ~AdminHandler() {} + virtual void announce(const std::string &text) = 0; virtual void localAnnounce(const std::string &text) = 0; @@ -49,8 +51,6 @@ class AdminHandler virtual void mute(int playerId, int type, int limit) = 0; - virtual ~AdminHandler() {} - // TODO }; diff --git a/src/net/charhandler.h b/src/net/charhandler.h index 4a813e21..0694e39e 100644 --- a/src/net/charhandler.h +++ b/src/net/charhandler.h @@ -23,14 +23,13 @@ #define CHARHANDLER_H #include "localplayer.h" -#include "logindata.h" +#include "playerinfo.h" #include <iosfwd> #include <vector> class CharCreateDialog; class CharSelectDialog; -class LocalPlayer; namespace Net { @@ -41,7 +40,7 @@ struct Character { Character() : slot(0), - dummy(new LocalPlayer) + dummy(0) { } @@ -52,6 +51,7 @@ struct Character int slot; /**< The index in the list of characters */ LocalPlayer *dummy; /**< A dummy representing this character */ + PlayerInfoBackend data; }; typedef std::list<Character*> Characters; @@ -59,6 +59,8 @@ typedef std::list<Character*> Characters; class CharHandler { public: + virtual ~CharHandler() {} + virtual void setCharSelectDialog(CharSelectDialog *window) = 0; virtual void setCharCreateDialog(CharCreateDialog *window) = 0; @@ -75,13 +77,11 @@ class CharHandler virtual void switchCharacter() = 0; - virtual int baseSprite() const = 0; + virtual unsigned int baseSprite() const = 0; - virtual int hairSprite() const = 0; + virtual unsigned int hairSprite() const = 0; - virtual int maxSprite() const = 0; - - virtual ~CharHandler() {} + virtual unsigned int maxSprite() const = 0; protected: CharHandler(): diff --git a/src/net/chathandler.h b/src/net/chathandler.h index d1449698..fbaa8dba 100644 --- a/src/net/chathandler.h +++ b/src/net/chathandler.h @@ -28,6 +28,8 @@ namespace Net { class ChatHandler { public: + virtual ~ChatHandler() {} + virtual void talk(const std::string &text) = 0; virtual void me(const std::string &text) = 0; @@ -53,8 +55,6 @@ class ChatHandler virtual void kickUser(int channelId, const std::string &name) = 0; virtual void who() = 0; - - virtual ~ChatHandler() {} }; } diff --git a/src/net/download.cpp b/src/net/download.cpp index a2cd4910..83ab180f 100644 --- a/src/net/download.cpp +++ b/src/net/download.cpp @@ -221,8 +221,8 @@ int Download::downloadThread(void *ptr) } curl_easy_setopt(d->mCurl, CURLOPT_USERAGENT, - strprintf(PACKAGE_EXTENDED_VERSION, branding - .getValue("appShort", "mana").c_str()).c_str()); + strprintf(PACKAGE_EXTENDED_VERSION, + branding.getStringValue("appShort").c_str()).c_str()); curl_easy_setopt(d->mCurl, CURLOPT_ERRORBUFFER, d->mError); curl_easy_setopt(d->mCurl, CURLOPT_URL, d->mUrl.c_str()); curl_easy_setopt(d->mCurl, CURLOPT_NOPROGRESS, 0); diff --git a/src/net/gamehandler.h b/src/net/gamehandler.h index 774de16c..0c5d889f 100644 --- a/src/net/gamehandler.h +++ b/src/net/gamehandler.h @@ -22,8 +22,6 @@ #ifndef MAPHANDLER_H #define MAPHANDLER_H -#include "logindata.h" - #include <iosfwd> namespace Net { @@ -31,16 +29,14 @@ namespace Net { class GameHandler { public: + virtual ~GameHandler() {} + virtual void connect() = 0; virtual bool isConnected() = 0; virtual void disconnect() = 0; - virtual void inGame() = 0; - - virtual void mapLoaded(const std::string &mapName) = 0; - virtual void who() = 0; virtual void quit() = 0; @@ -49,7 +45,10 @@ class GameHandler virtual bool removeDeadBeings() const = 0; - virtual ~GameHandler() {} + /** + * Tells whether the protocol is using the MP status bar + */ + virtual bool canUseMagicBar() const = 0; }; } // namespace Net diff --git a/src/net/generalhandler.h b/src/net/generalhandler.h index 222b430a..4b8474dd 100644 --- a/src/net/generalhandler.h +++ b/src/net/generalhandler.h @@ -19,9 +19,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "client.h" -#include "main.h" - #ifndef GENERALHANDLER_H #define GENERALHANDLER_H @@ -40,13 +37,7 @@ class GeneralHandler virtual void flushNetwork() = 0; - virtual void guiWindowsLoaded() = 0; - - virtual void guiWindowsUnloaded() = 0; - virtual void clearHandlers() = 0; - - virtual void stateChanged(State oldState, State newState) = 0; }; } // namespace Net diff --git a/src/net/guildhandler.h b/src/net/guildhandler.h index 1696b2d5..e4513cbb 100644 --- a/src/net/guildhandler.h +++ b/src/net/guildhandler.h @@ -23,10 +23,11 @@ #define GUILDHANDLER_H #include "guild.h" -#include "player.h" #include <iosfwd> +class Being; + namespace Net { class GuildHandler @@ -40,7 +41,7 @@ class GuildHandler virtual void invite(int guildId, const std::string &name) = 0; - virtual void invite(int guildId, Player *player) = 0; + virtual void invite(int guildId, Being *being) = 0; virtual void inviteResponse(int guildId, bool response) = 0; diff --git a/src/net/inventoryhandler.h b/src/net/inventoryhandler.h index e48043a7..93b56a40 100644 --- a/src/net/inventoryhandler.h +++ b/src/net/inventoryhandler.h @@ -32,33 +32,12 @@ namespace Net { class InventoryHandler { public: - virtual void equipItem(const Item *item) = 0; - - virtual void unequipItem(const Item *item) = 0; - - virtual void useItem(const Item *item) = 0; - - virtual void dropItem(const Item *item, int amount) = 0; + virtual ~InventoryHandler() {} virtual bool canSplit(const Item *item) = 0; - virtual void splitItem(const Item *item, int amount) = 0; - - virtual void moveItem(int oldIndex, int newIndex) = 0; - - virtual void openStorage(int type) = 0; - - virtual void closeStorage(int type) = 0; - - //void changeCart() = 0; - - virtual void moveItem(int source, int slot, int amount, - int destination) = 0; - // TODO: fix/remove me virtual size_t getSize(int type) const = 0; - - virtual ~InventoryHandler() {} }; } // namespace Net diff --git a/src/net/logindata.h b/src/net/logindata.h index 9bbeed4f..22675d5a 100644 --- a/src/net/logindata.h +++ b/src/net/logindata.h @@ -22,9 +22,7 @@ #ifndef LOGINDATA_H #define LOGINDATA_H -#include "player.h" - -#include "net/serverinfo.h" +#include "being.h" #include <string> diff --git a/src/net/manaserv/attributes.cpp b/src/net/manaserv/attributes.cpp new file mode 100644 index 00000000..a65dc01f --- /dev/null +++ b/src/net/manaserv/attributes.cpp @@ -0,0 +1,408 @@ +/* + * The Mana Client + * Copyright (C) 2010 The Mana Developers + * + * This file is part of The Mana Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "net/manaserv/attributes.h" + +#include "log.h" +#include "playerinfo.h" + +#include "gui/statuswindow.h" + +#include "resources/itemdb.h" + +#include "utils/gettext.h" +#include "utils/stringutils.h" +#include "utils/xml.h" + +#include <list> +#include <map> + +#define DEFAULT_ATTRIBUTESDB_FILE "attributes.xml" +#define DEFAULT_POINTS 60 +#define DEFAULT_MIN_PTS 1 +#define DEFAULT_MAX_PTS 20 + +namespace ManaServ { +namespace Attributes { + + typedef struct + { + unsigned int id; + std::string name; + std::string description; + /** Whether the attribute value can be modified by the player */ + bool modifiable; + /**< Attribute scope. */ + std::string scope; + /** The playerInfo core Id the attribute is linked with or -1 if not */ + int playerInfoId; + } Attribute; + + /** Map for attributes. */ + typedef std::map<unsigned int, Attribute> AttributeMap; + static AttributeMap attributes; + + /** tags = effects on attributes. */ + typedef std::map< std::string, std::string > TagMap; + static TagMap tags; + + /** List of modifiable attribute names used at character's creation. */ + static std::vector<std::string> attributeLabels; + + /** Characters creation points. */ + static unsigned int creationPoints = 0; + static unsigned int attributeMinimum = 0; + static unsigned int attributeMaximum = 0; + + unsigned int getCreationPoints() + { + return creationPoints; + } + + unsigned int getAttributeMinimum() + { + return attributeMinimum; + } + + unsigned int getAttributeMaximum() + { + return attributeMaximum; + } + + std::vector<std::string>& getLabels() + { + return attributeLabels; + } + + /** + * Fills the list of base attribute labels. + */ + static void fillLabels() + { + // Fill up the modifiable attribute label list. + attributeLabels.clear(); + AttributeMap::const_iterator it, it_end; + for (it = attributes.begin(), it_end = attributes.end(); it != it_end; + it++) + { + if (it->second.modifiable && + (it->second.scope == "character" || it->second.scope == "being")) + attributeLabels.push_back(it->second.name + ":"); + } + } + + /** + * Fills the list of base attribute labels. + */ + static int getPlayerInfoIdFromAttrType(std::string attrType) + { + toLower(attrType); + if (attrType == "level") + return ::LEVEL; + else if (attrType == "hp") + return ::HP; + else if (attrType == "max-hp") + return ::MAX_HP; + else if (attrType == "mp") + return ::MP; + else if (attrType == "max-mp") + return ::MAX_MP; + else if (attrType == "exp") + return ::EXP; + else if (attrType == "exp-needed") + return ::EXP_NEEDED; + else if (attrType == "money") + return ::MONEY; + else if (attrType == "total-weight") + return ::TOTAL_WEIGHT; + else if (attrType == "max-weight") + return ::MAX_WEIGHT; + else if (attrType == "skill-points") + return ::SKILL_POINTS; + else if (attrType == "char-points") + return ::CHAR_POINTS; + else if (attrType == "corr-points") + return ::CORR_POINTS; + else if (attrType == "none") + return -2; // Used to hide the attribute display. + + return -1; // Not linked to a playerinfo stat. + } + + int getPlayerInfoIdFromAttrId(int attrId) + { + AttributeMap::const_iterator it = attributes.find(attrId); + + if (it != attributes.end()) + { + return it->second.playerInfoId; + } + + return -1; + } + + static void loadBuiltins() + { + { + Attribute a; + a.id = 16; + a.name = _("Strength"); + a.description = ""; + a.modifiable = true; + a.scope = "character"; + a.playerInfoId = -1; + + attributes[a.id] = a; + tags.insert(std::make_pair("str", _("Strength %+.1f"))); + } + + { + Attribute a; + a.id = 17; + a.name = _("Agility"); + a.description = ""; + a.modifiable = true; + a.scope = "character"; + a.playerInfoId = -1; + + attributes[a.id] = a; + tags.insert(std::make_pair("agi", _("Agility %+.1f"))); + } + + { + Attribute a; + a.id = 18; + a.name = _("Dexterity"); + a.description = ""; + a.modifiable = true; + a.scope = "character"; + a.playerInfoId = -1; + + attributes[a.id] = a; + tags.insert(std::make_pair("dex", _("Dexterity %+.1f"))); + } + + { + Attribute a; + a.id = 19; + a.name = _("Vitality"); + a.description = ""; + a.modifiable = true; + a.scope = "character"; + a.playerInfoId = -1; + + attributes[a.id] = a; + tags.insert(std::make_pair("vit", _("Vitality %+.1f"))); + } + + { + Attribute a; + a.id = 20; + a.name = _("Intelligence"); + a.description = ""; + a.modifiable = true; + a.scope = "character"; + a.playerInfoId = -1; + + attributes[a.id] = a; + tags.insert(std::make_pair("int", _("Intelligence %+.1f"))); + } + + { + Attribute a; + a.id = 21; + a.name = _("Willpower"); + a.description = ""; + a.modifiable = true; + a.scope = "character"; + a.playerInfoId = -1; + + attributes[a.id] = a; + tags.insert(std::make_pair("wil", _("Willpower %+.1f"))); + } + } + + void load() + { + logger->log("Initializing attributes database..."); + + XML::Document doc(DEFAULT_ATTRIBUTESDB_FILE); + xmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "attributes")) + { + logger->log("Attributes: Error while loading " + DEFAULT_ATTRIBUTESDB_FILE ". Using Built-ins."); + loadBuiltins(); + fillLabels(); + return; + } + + for_each_xml_child_node(node, rootNode) + { + if (xmlStrEqual(node->name, BAD_CAST "attribute")) + { + int id = XML::getProperty(node, "id", 0); + + if (!id) + { + logger->log("Attributes: Invalid or missing stat ID in " + DEFAULT_ATTRIBUTESDB_FILE "!"); + continue; + } + else if (attributes.find(id) != attributes.end()) + { + logger->log("Attributes: Redefinition of stat ID %d", id); + } + + std::string name = XML::getProperty(node, "name", ""); + + if (name.empty()) + { + logger->log("Attributes: Invalid or missing stat name in " + DEFAULT_ATTRIBUTESDB_FILE "!"); + continue; + } + + // Create the attribute. + Attribute a; + a.id = id; + a.name = name; + a.description = XML::getProperty(node, "desc", ""); + a.modifiable = XML::getBoolProperty(node, "modifiable", false); + a.scope = XML::getProperty(node, "scope", "none"); + a.playerInfoId = getPlayerInfoIdFromAttrType( + XML::getProperty(node, "player-info", "")); + + attributes[id] = a; + + unsigned int count = 0; + for_each_xml_child_node(effectNode, node) + { + if (!xmlStrEqual(effectNode->name, BAD_CAST "modifier")) + continue; + ++count; + std::string tag = XML::getProperty(effectNode, "tag", ""); + if (tag.empty()) + { + if (name.empty()) + { + logger->log("Attribute modifier in attribute %u:%s: " + "Empty name definition " + "on empty tag definition, skipping.", + a.id, a.name.c_str()); + --count; + continue; + } + tag = name.substr(0, name.size() > 3 ? 3 : name.size()); + tag = toLower(tag) + toString(count); + } + + std::string effect = XML::getProperty(effectNode, "effect", ""); + if (effect.empty()) + { + if (name.empty()) + { + logger->log("Attribute modifier in attribute %u:%s: " + "Empty name definition " + "on empty effect definition, skipping.", + a.id, a.name.c_str()); + --count; + continue; + } + else + effect = name + " %+f"; + } + tags.insert(std::make_pair(tag, effect)); + } + logger->log("Found %d tags for attribute %d.", count, id); + + }// End attribute + else if (xmlStrEqual(node->name, BAD_CAST "points")) + { + creationPoints = XML::getProperty(node, "start",DEFAULT_POINTS); + attributeMinimum = XML::getProperty(node, "minimum", + DEFAULT_MIN_PTS); + attributeMaximum = XML::getProperty(node, "maximum", + DEFAULT_MAX_PTS); + logger->log("Loaded points: start: %i, min: %i, max: %i.", + creationPoints, attributeMinimum, attributeMaximum); + } + else + { + continue; + } + } + logger->log("Found %d tags for %d attributes.", int(tags.size()), + int(attributes.size())); + + fillLabels(); + + // Sanity checks on starting points + float modifiableAttributeCount = (float) attributeLabels.size(); + float averageValue = ((float) creationPoints) / modifiableAttributeCount; + if (averageValue > attributeMaximum || averageValue < attributeMinimum + || creationPoints < 1) + { + logger->log("Attributes: Character's point values make " + "the character's creation impossible. " + "Switch back to defaults."); + creationPoints = DEFAULT_POINTS; + attributeMinimum = DEFAULT_MIN_PTS; + attributeMaximum = DEFAULT_MAX_PTS; + } + } + + void unload() + { + attributes.clear(); + } + + void informItemDB() + { + std::list<ItemDB::Stat> dbStats; + + TagMap::const_iterator it, it_end; + for (it = tags.begin(), it_end = tags.end(); it != it_end; ++it) + dbStats.push_back(ItemDB::Stat(it->first, + it->second)); + + itemDb->setStatsList(dbStats); + } + + void informStatusWindow() + { + AttributeMap::const_iterator it, it_end; + for (it = attributes.begin(), it_end = attributes.end(); it != it_end; + it++) + { + if (it->second.playerInfoId == -1 && + (it->second.scope == "character" || it->second.scope == "being")) + { + statusWindow->addAttribute(it->second.id, + it->second.name, + it->second.modifiable, + it->second.description); + } + } + } + +} // namespace Attributes +} // namespace ManaServ diff --git a/src/net/manaserv/stats.h b/src/net/manaserv/attributes.h index 63349095..aced85ec 100644 --- a/src/net/manaserv/stats.h +++ b/src/net/manaserv/attributes.h @@ -18,14 +18,15 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_STATS_H -#define NET_MANASERV_STATS_H +#ifndef NET_MANASERV_ATTRIBUTES_H +#define NET_MANASERV_ATTRIBUTES_H #include <string> #include <vector> namespace ManaServ { -namespace Stats { +namespace Attributes { + void load(); void unload(); @@ -34,8 +35,36 @@ namespace Stats { void informStatusWindow(); - std::vector<std::string> getLabelVector(); -} // namespace Stats + /** + * Returns the list of base attribute labels. + */ + std::vector<std::string>& getLabels(); + + /** + * Give back the corresponding playerinfo Id from the attribute id + * defined in the xml file. + */ + int getPlayerInfoIdFromAttrId(int attrId); + + /** + * Give the attribute points given to a character + * at its creation. + */ + unsigned int getCreationPoints(); + + /** + * Give the minimum attribute point possible + * at character's creation. + */ + unsigned int getAttributeMinimum(); + + /** + * Give the maximum attribute point possible + * at character's creation. + */ + unsigned int getAttributeMaximum(); + +} // namespace Attributes } // namespace ManaServ -#endif // NET_MANASERV_STATS_H +#endif // NET_MANASERV_ATTRIBUTES_H diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp index 8df9a8ab..63c1e13f 100644 --- a/src/net/manaserv/beinghandler.cpp +++ b/src/net/manaserv/beinghandler.cpp @@ -21,13 +21,12 @@ #include "net/manaserv/beinghandler.h" +#include "actorspritemanager.h" #include "being.h" -#include "beingmanager.h" #include "client.h" #include "game.h" #include "localplayer.h" #include "log.h" -#include "npc.h" #include "particle.h" #include "gui/okdialog.h" @@ -121,7 +120,7 @@ Vector BeingHandler::giveSpeedInPixelsPerTicks(float speedInTilesPerSeconds) return speedInTicks; } -static void handleLooks(Player *being, Net::MessageIn &msg) +static void handleLooks(Being *being, Net::MessageIn &msg) { // Order of sent slots. Has to be in sync with the server code. static int const nb_slots = 4; @@ -145,7 +144,7 @@ static void handleLooks(Player *being, Net::MessageIn &msg) { if (!(mask & (1 << i))) continue; int id = msg.readInt16(); - being->setSprite(slots[i], id); + being->setSprite(slots[i], id,"", (slots[i] == SPRITE_WEAPON)); } } @@ -170,23 +169,23 @@ void BeingHandler::handleBeingEnterMessage(Net::MessageIn &msg) } else { - being = beingManager->createBeing(id, Being::PLAYER, 0); + being = actorSpriteManager->createBeing(id, + ActorSprite::PLAYER, 0); being->setName(name); } - Player *p = static_cast< Player * >(being); int hs = msg.readInt8(), hc = msg.readInt8(); - p->setSprite(SPRITE_HAIR, hs * -1, ColorDB::get(hc)); - p->setGender(msg.readInt8() == GENDER_MALE ? - GENDER_MALE : GENDER_FEMALE); - handleLooks(p, msg); + being->setSprite(SPRITE_HAIR, hs * -1, ColorDB::get(hc)); + being->setGender(msg.readInt8() == GENDER_MALE ? + GENDER_MALE : GENDER_FEMALE); + handleLooks(being, msg); } break; case OBJECT_MONSTER: case OBJECT_NPC: { int subtype = msg.readInt16(); - being = beingManager->createBeing(id, type == OBJECT_MONSTER ? - Being::MONSTER : Being::NPC, subtype); + being = actorSpriteManager->createBeing(id, type == OBJECT_MONSTER + ? ActorSprite::MONSTER : ActorSprite::NPC, subtype); std::string name = msg.readString(); if (name.length() > 0) being->setName(name); } break; @@ -202,11 +201,11 @@ void BeingHandler::handleBeingEnterMessage(Net::MessageIn &msg) void BeingHandler::handleBeingLeaveMessage(Net::MessageIn &msg) { - Being *being = beingManager->findBeing(msg.readInt16()); + Being *being = actorSpriteManager->findBeing(msg.readInt16()); if (!being) return; - beingManager->destroyBeing(being); + actorSpriteManager->destroy(being); } void BeingHandler::handleBeingsMoveMessage(Net::MessageIn &msg) @@ -215,7 +214,7 @@ void BeingHandler::handleBeingsMoveMessage(Net::MessageIn &msg) { int id = msg.readInt16(); int flags = msg.readInt8(); - Being *being = beingManager->findBeing(id); + Being *being = actorSpriteManager->findBeing(id); int sx = 0; int sy = 0; int speed = 0; @@ -257,7 +256,7 @@ void BeingHandler::handleBeingsMoveMessage(Net::MessageIn &msg) void BeingHandler::handleBeingAttackMessage(Net::MessageIn &msg) { - Being *being = beingManager->findBeing(msg.readInt16()); + Being *being = actorSpriteManager->findBeing(msg.readInt16()); const int direction = msg.readInt8(); const int attackType = msg.readInt8(); @@ -279,7 +278,7 @@ void BeingHandler::handleBeingsDamageMessage(Net::MessageIn &msg) { while (msg.getUnreadLength()) { - Being *being = beingManager->findBeing(msg.readInt16()); + Being *being = actorSpriteManager->findBeing(msg.readInt16()); int damage = msg.readInt16(); if (being) { @@ -290,7 +289,7 @@ void BeingHandler::handleBeingsDamageMessage(Net::MessageIn &msg) void BeingHandler::handleBeingActionChangeMessage(Net::MessageIn &msg) { - Being *being = beingManager->findBeing(msg.readInt16()); + Being *being = actorSpriteManager->findBeing(msg.readInt16()); Being::Action action = (Being::Action) msg.readInt8(); if (!being) return; @@ -329,22 +328,21 @@ void BeingHandler::handleBeingActionChangeMessage(Net::MessageIn &msg) void BeingHandler::handleBeingLooksChangeMessage(Net::MessageIn &msg) { - Being *being = beingManager->findBeing(msg.readInt16()); - if (!being || being->getType() != Being::PLAYER) + Being *being = actorSpriteManager->findBeing(msg.readInt16()); + if (!being || being->getType() != ActorSprite::PLAYER) return; - Player *player = static_cast<Player *>(being); - handleLooks(player, msg); + handleLooks(being, msg); if (msg.getUnreadLength()) { int style = msg.readInt16(); int color = msg.readInt16(); - player->setSprite(SPRITE_HAIR, style * -1, ColorDB::get(color)); + being->setSprite(SPRITE_HAIR, style * -1, ColorDB::get(color)); } } void BeingHandler::handleBeingDirChangeMessage(Net::MessageIn &msg) { - Being *being = beingManager->findBeing(msg.readInt16()); + Being *being = actorSpriteManager->findBeing(msg.readInt16()); if (!being) return; int data = msg.readInt8(); diff --git a/src/net/manaserv/buysellhandler.cpp b/src/net/manaserv/buysellhandler.cpp index a4ce6aa0..d4187db7 100644 --- a/src/net/manaserv/buysellhandler.cpp +++ b/src/net/manaserv/buysellhandler.cpp @@ -21,13 +21,11 @@ #include "net/manaserv/buysellhandler.h" -#include "beingmanager.h" +#include "actorspritemanager.h" #include "item.h" -#include "localplayer.h" -#include "npc.h" +#include "playerinfo.h" #include "gui/buy.h" -#include "gui/chat.h" #include "gui/sell.h" #include "net/messagein.h" @@ -49,8 +47,8 @@ BuySellHandler::BuySellHandler() void BuySellHandler::handleMessage(Net::MessageIn &msg) { - Being *being = beingManager->findBeing(msg.readInt16()); - if (!being || being->getType() != Being::NPC) + Being *being = actorSpriteManager->findBeing(msg.readInt16()); + if (!being || being->getType() != ActorSprite::NPC) { return; } @@ -64,7 +62,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) BuyDialog* dialog = new BuyDialog(npcId); dialog->reset(); - dialog->setMoney(player_node->getMoney()); + dialog->setMoney(PlayerInfo::getAttribute(MONEY)); while (msg.getUnreadLength()) { @@ -81,7 +79,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) SellDialog* dialog = new SellDialog(npcId); dialog->reset(); - dialog->setMoney(player_node->getMoney()); + dialog->setMoney(PlayerInfo::getAttribute(MONEY)); while (msg.getUnreadLength()) { diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp index e6723226..6f2b4377 100644 --- a/src/net/manaserv/charhandler.cpp +++ b/src/net/manaserv/charhandler.cpp @@ -37,7 +37,7 @@ #include "net/manaserv/messagein.h" #include "net/manaserv/messageout.h" #include "net/manaserv/protocol.h" -#include "net/manaserv/stats.h" +#include "net/manaserv/attributes.h" #include "resources/colordb.h" @@ -108,11 +108,15 @@ void CharHandler::handleCharacterInfo(Net::MessageIn &msg) info.level = msg.readInt16(); info.characterPoints = msg.readInt16(); info.correctionPoints = msg.readInt16(); - info.money = msg.readInt32(); - for (int i = 0; i < 7; i++) + while (msg.getUnreadLength() > 0) { - info.attribute[i] = msg.readInt8(); + int id = msg.readInt32(); + CachedAttrbiute attr; + attr.base = msg.readInt32() / 256.0; + attr.mod = msg.readInt32() / 256.0; + + info.attribute[id] = attr; } mCachedCharacterInfos.push_back(info); @@ -157,8 +161,11 @@ void CharHandler::handleCharacterCreateResponse(Net::MessageIn &msg) case CREATE_ATTRIBUTES_TOO_LOW: errorMessage = _("Character's stats are too low."); break; - case CREATE_ATTRIBUTES_EQUAL_TO_ZERO: - errorMessage = _("One stat is zero."); + case CREATE_ATTRIBUTES_OUT_OF_RANGE: + errorMessage = strprintf( _("At least one stat" + "is out of the permitted range: (%u - %u)."), + Attributes::getAttributeMinimum(), + Attributes::getAttributeMaximum()); break; default: errorMessage = _("Unknown error."); @@ -189,7 +196,6 @@ void CharHandler::handleCharacterDeleteResponse(Net::MessageIn &msg) delete mSelectedCharacter; mCharacters.remove(mSelectedCharacter); updateCharSelectDialog(); - unlockCharSelectDialog(); new OkDialog(_("Info"), _("Player deleted.")); } else @@ -210,6 +216,7 @@ void CharHandler::handleCharacterDeleteResponse(Net::MessageIn &msg) new OkDialog(_("Error"), errorMessage); } mSelectedCharacter = 0; + unlockCharSelectDialog(); } void CharHandler::handleCharacterSelectResponse(Net::MessageIn &msg) @@ -233,6 +240,7 @@ void CharHandler::handleCharacterSelectResponse(Net::MessageIn &msg) // Prevent the selected local player from being deleted player_node = mSelectedCharacter->dummy; + PlayerInfo::setBackend(mSelectedCharacter->data); mSelectedCharacter->dummy = 0; Client::setState(STATE_CONNECT_GAME); @@ -259,7 +267,10 @@ void CharHandler::setCharCreateDialog(CharCreateDialog *window) if (!mCharCreateDialog) return; - mCharCreateDialog->setAttributes(Stats::getLabelVector(), 60, 1, 20); + mCharCreateDialog->setAttributes(Attributes::getLabels(), + Attributes::getCreationPoints(), + Attributes::getAttributeMinimum(), + Attributes::getAttributeMaximum()); } void CharHandler::requestCharacters() @@ -319,17 +330,17 @@ void CharHandler::switchCharacter() gameHandler->quit(true); } -int CharHandler::baseSprite() const +unsigned int CharHandler::baseSprite() const { return SPRITE_BASE; } -int CharHandler::hairSprite() const +unsigned int CharHandler::hairSprite() const { return SPRITE_HAIR; } -int CharHandler::maxSprite() const +unsigned int CharHandler::maxSprite() const { return SPRITE_VECTOREND; } @@ -350,19 +361,20 @@ void CharHandler::updateCharacters() Net::Character *character = new Net::Character; character->slot = info.slot; - LocalPlayer *player = character->dummy; + LocalPlayer *player = character->dummy = new LocalPlayer; player->setName(info.name); player->setGender(info.gender); player->setSprite(SPRITE_HAIR, info.hairStyle * -1, ColorDB::get(info.hairColor)); - player->setLevel(info.level); - player->setCharacterPoints(info.characterPoints); - player->setCorrectionPoints(info.correctionPoints); - player->setMoney(info.money); + character->data.mAttributes[LEVEL] = info.level; + character->data.mAttributes[CHAR_POINTS] = info.characterPoints; + character->data.mAttributes[CORR_POINTS] = info.correctionPoints; - for (int i = 0; i < 7; i++) + for (CachedAttributes::const_iterator it = info.attribute.begin(), + it_end = info.attribute.end(); it != it_end; it++) { - player->setAttributeBase(i, info.attribute[i], false); + character->data.mStats[i].base = it->second.base; + character->data.mStats[i].mod = it->second.mod; } mCharacters.push_back(character); diff --git a/src/net/manaserv/charhandler.h b/src/net/manaserv/charhandler.h index 26a7bf4e..2f335688 100644 --- a/src/net/manaserv/charhandler.h +++ b/src/net/manaserv/charhandler.h @@ -28,6 +28,8 @@ #include "net/manaserv/messagehandler.h" +#include <map.h> + class LoginData; namespace ManaServ { @@ -65,11 +67,11 @@ class CharHandler : public MessageHandler, public Net::CharHandler void switchCharacter(); - int baseSprite() const; + unsigned int baseSprite() const; - int hairSprite() const; + unsigned int hairSprite() const; - int maxSprite() const; + unsigned int maxSprite() const; void clear(); @@ -79,6 +81,13 @@ class CharHandler : public MessageHandler, public Net::CharHandler * we have loaded the dynamic data, so we can't resolve load any * sprites yet. */ + struct CachedAttrbiute { + double base; + double mod; + }; + + typedef std::map<int, CachedAttrbiute> CachedAttributes; + struct CachedCharacterInfo { int slot; std::string name; @@ -88,8 +97,7 @@ class CharHandler : public MessageHandler, public Net::CharHandler int level; int characterPoints; int correctionPoints; - int money; - int attribute[7]; + CachedAttributes attribute; }; void handleCharacterInfo(Net::MessageIn &msg); diff --git a/src/net/manaserv/chathandler.cpp b/src/net/manaserv/chathandler.cpp index a452281f..db0e1084 100644 --- a/src/net/manaserv/chathandler.cpp +++ b/src/net/manaserv/chathandler.cpp @@ -21,13 +21,13 @@ #include "net/manaserv/chathandler.h" +#include "actorspritemanager.h" #include "being.h" -#include "beingmanager.h" #include "client.h" #include "channel.h" #include "channelmanager.h" - -#include "gui/chat.h" +#include "event.h" +#include "playerrelations.h" #include "gui/widgets/channeltab.h" @@ -149,22 +149,29 @@ void ChatHandler::handleGameChatMessage(Net::MessageIn &msg) if (id == 0) { - localChatTab->chatLog(chatMsg, BY_SERVER); + SERVER_NOTICE(chatMsg) return; } - Being *being = beingManager->findBeing(id); + Being *being = actorSpriteManager->findBeing(id); std::string mes; if (being) { mes = being->getName() + " : " + chatMsg; - being->setSpeech(chatMsg, SPEECH_TIME); } else mes = "Unknown : " + chatMsg; - localChatTab->chatLog(mes, being == player_node ? BY_PLAYER : BY_OTHER); + Mana::Event event(being == player_node ? EVENT_PLAYER : EVENT_BEING); + event.setString("message", mes); + event.setString("text", chatMsg); + event.setString("nick", being->getName()); + event.setInt("beingId", id); + event.setInt("permissions", player_relations + .checkPermissionSilently(being->getName(), + PlayerRelation::SPEECH_LOG | PlayerRelation::SPEECH_FLOAT)); + event.trigger(CHANNEL_CHAT); } void ChatHandler::handleEnterChannelResponse(Net::MessageIn &msg) @@ -198,13 +205,13 @@ void ChatHandler::handleEnterChannelResponse(Net::MessageIn &msg) } else { - localChatTab->chatLog(_("Error joining channel."), BY_SERVER); + SERVER_NOTICE(_("Error joining channel.")) } } void ChatHandler::handleListChannelsResponse(Net::MessageIn &msg) { - localChatTab->chatLog(_("Listing channels."), BY_SERVER); + SERVER_NOTICE(_("Listing channels.")) while (msg.getUnreadLength()) { std::string channelName = msg.readString(); @@ -214,9 +221,9 @@ void ChatHandler::handleListChannelsResponse(Net::MessageIn &msg) numUsers << msg.readInt16(); channelName += " - "; channelName += numUsers.str(); - localChatTab->chatLog(channelName, BY_SERVER); + SERVER_NOTICE(channelName) } - localChatTab->chatLog(_("End of channel list."), BY_SERVER); + SERVER_NOTICE(_("End of channel list.")) } void ChatHandler::handlePrivateMessage(Net::MessageIn &msg) @@ -224,13 +231,18 @@ void ChatHandler::handlePrivateMessage(Net::MessageIn &msg) std::string userNick = msg.readString(); std::string chatMsg = msg.readString(); - chatWindow->whisper(userNick, chatMsg); + Mana::Event event(EVENT_WHISPER); + event.setString("nick", userNick); + event.setString("message", chatMsg); + event.trigger(CHANNEL_CHAT); } void ChatHandler::handleAnnouncement(Net::MessageIn &msg) { std::string chatMsg = msg.readString(); - localChatTab->chatLog(chatMsg, BY_GM); + Mana::Event event(EVENT_ANNOUNCEMENT); + event.setString("message", chatMsg); + event.trigger(CHANNEL_CHAT); } void ChatHandler::handleChatMessage(Net::MessageIn &msg) @@ -341,7 +353,7 @@ void ChatHandler::handleWhoResponse(Net::MessageIn &msg) { break; } - localChatTab->chatLog(userNick, BY_SERVER); + SERVER_NOTICE(userNick) } } diff --git a/src/net/manaserv/connection.cpp b/src/net/manaserv/connection.cpp index fbd2ed22..b404191f 100644 --- a/src/net/manaserv/connection.cpp +++ b/src/net/manaserv/connection.cpp @@ -60,7 +60,7 @@ bool Connection::connect(const std::string &address, short port) enetAddress.port = port; // Initiate the connection, allocating channel 0. -#ifdef ENET_VERSION_MAJOR +#if defined(ENET_VERSION) && ENET_VERSION >= ENET_CUTOFF mConnection = enet_host_connect(mClient, &enetAddress, 1, 0); #else mConnection = enet_host_connect(mClient, &enetAddress, 1); diff --git a/src/net/manaserv/connection.h b/src/net/manaserv/connection.h index b39f8957..808a6d40 100644 --- a/src/net/manaserv/connection.h +++ b/src/net/manaserv/connection.h @@ -26,6 +26,12 @@ #include <iosfwd> +#ifdef ENET_VERSION_CREATE +#define ENET_CUTOFF ENET_VERSION_CREATE(1,3,0) +#else +#define ENET_CUTOFF 0xFFFFFFFF +#endif + namespace ManaServ { class MessageOut; diff --git a/src/net/manaserv/defines.h b/src/net/manaserv/defines.h new file mode 100644 index 00000000..e97866df --- /dev/null +++ b/src/net/manaserv/defines.h @@ -0,0 +1,76 @@ +/* + * The Mana Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * + * This file is part of The Mana Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef MANASERV_DEFINES_H +#define MANASERV_DEFINES_H + +/** + * Attributes used during combat. Available to all the beings. + */ +enum +{ +BASE_ATTR_BEGIN = 0, + BASE_ATTR_PHY_ATK_MIN = BASE_ATTR_BEGIN, + BASE_ATTR_PHY_ATK_DELTA, + /**< Physical attack power. */ + BASE_ATTR_MAG_ATK, /**< Magical attack power. */ + BASE_ATTR_PHY_RES, /**< Resistance to physical damage. */ + BASE_ATTR_MAG_RES, /**< Resistance to magical damage. */ + BASE_ATTR_EVADE, /**< Ability to avoid hits. */ + BASE_ATTR_HIT, /**< Ability to hit stuff. */ + BASE_ATTR_HP, /**< Hit Points (Base value: maximum, Modded value: current) */ + BASE_ATTR_HP_REGEN,/**< number of HP regenerated every 10 game ticks */ + BASE_ATTR_END, + BASE_ATTR_NB = BASE_ATTR_END - BASE_ATTR_BEGIN, + + BASE_ELEM_BEGIN = BASE_ATTR_END, + BASE_ELEM_NEUTRAL = BASE_ELEM_BEGIN, + BASE_ELEM_FIRE, + BASE_ELEM_WATER, + BASE_ELEM_EARTH, + BASE_ELEM_AIR, + BASE_ELEM_SACRED, + BASE_ELEM_DEATH, + BASE_ELEM_END, + BASE_ELEM_NB = BASE_ELEM_END - BASE_ELEM_BEGIN, + + NB_BEING_ATTRIBUTES = BASE_ELEM_END +}; + +/** + * Attributes of characters. Used to derive being attributes. + */ +enum +{ + CHAR_ATTR_BEGIN = NB_BEING_ATTRIBUTES, + CHAR_ATTR_STRENGTH = CHAR_ATTR_BEGIN, + CHAR_ATTR_AGILITY, + CHAR_ATTR_DEXTERITY, + CHAR_ATTR_VITALITY, + CHAR_ATTR_INTELLIGENCE, + CHAR_ATTR_WILLPOWER, + CHAR_ATTR_END, + CHAR_ATTR_NB = CHAR_ATTR_END - CHAR_ATTR_BEGIN, + + NB_CHARACTER_ATTRIBUTES = CHAR_ATTR_END +}; + +#endif // MANASERV_DEFINES_H diff --git a/src/net/manaserv/effecthandler.cpp b/src/net/manaserv/effecthandler.cpp index 27db9b59..c803b441 100644 --- a/src/net/manaserv/effecthandler.cpp +++ b/src/net/manaserv/effecthandler.cpp @@ -21,7 +21,7 @@ #include "net/manaserv/effecthandler.h" -#include "beingmanager.h" +#include "actorspritemanager.h" #include "effectmanager.h" #include "log.h" @@ -68,7 +68,7 @@ void EffectHandler::handleCreateEffectBeing(Net::MessageIn &msg) { int eid = msg.readInt16(); int bid = msg.readInt16(); - Being* b = beingManager->findBeing(bid); + Being* b = actorSpriteManager->findBeing(bid); if (b) effectManager->trigger(eid, b); else diff --git a/src/net/manaserv/gamehandler.cpp b/src/net/manaserv/gamehandler.cpp index 5e29a896..3cb9f0ea 100644 --- a/src/net/manaserv/gamehandler.cpp +++ b/src/net/manaserv/gamehandler.cpp @@ -115,16 +115,6 @@ void GameHandler::disconnect() chatHandler->disconnect(); } -void GameHandler::inGame() -{ - // TODO -} - -void GameHandler::mapLoaded(const std::string &mapName) -{ - // TODO -} - void GameHandler::who() { // TODO diff --git a/src/net/manaserv/gamehandler.h b/src/net/manaserv/gamehandler.h index dde1748f..2e9f37fe 100644 --- a/src/net/manaserv/gamehandler.h +++ b/src/net/manaserv/gamehandler.h @@ -42,10 +42,6 @@ class GameHandler : public MessageHandler, public Net::GameHandler void disconnect(); - void inGame(); - - void mapLoaded(const std::string &mapName); - void who(); void quit(bool reconnectAccount); @@ -53,12 +49,15 @@ class GameHandler : public MessageHandler, public Net::GameHandler void quit() { quit(false); } void ping(int tick); - + bool removeDeadBeings() const { return false; } void clear(); void gameLoading(); + + /** The ManaServ protocol doesn't use the MP status bar. */ + bool canUseMagicBar() const { return false; } }; } // namespace ManaServ diff --git a/src/net/manaserv/generalhandler.cpp b/src/net/manaserv/generalhandler.cpp index 0d3073f1..d2151307 100644 --- a/src/net/manaserv/generalhandler.cpp +++ b/src/net/manaserv/generalhandler.cpp @@ -46,7 +46,7 @@ #include "net/manaserv/partyhandler.h" #include "net/manaserv/playerhandler.h" #include "net/manaserv/specialhandler.h" -#include "net/manaserv/stats.h" +#include "net/manaserv/attributes.h" #include "net/manaserv/tradehandler.h" #include "utils/gettext.h" @@ -90,6 +90,9 @@ GeneralHandler::GeneralHandler(): chatServerConnection = getConnection(); generalHandler = this; + + listen(CHANNEL_CLIENT); + listen(CHANNEL_GAME); } void GeneralHandler::load() @@ -127,9 +130,9 @@ void GeneralHandler::reload() gameServer.clear(); chatServer.clear(); - Stats::unload(); - Stats::load(); - Stats::informItemDB(); + Attributes::unload(); + Attributes::load(); + Attributes::informItemDB(); } void GeneralHandler::unload() @@ -147,7 +150,7 @@ void GeneralHandler::unload() delete gameServerConnection; delete chatServerConnection; - Stats::unload(); + Attributes::unload(); finalize(); } @@ -163,38 +166,43 @@ void GeneralHandler::flushNetwork() } } -void GeneralHandler::guiWindowsLoaded() -{ - inventoryWindow->setSplitAllowed(true); - skillDialog->loadSkills("mana-skills.xml"); - specialsWindow->loadSpecials("specials.xml"); - - player_node->setExpNeeded(100); - - Stats::informStatusWindow(); -} - -void GeneralHandler::guiWindowsUnloaded() -{ - // TODO -} - void GeneralHandler::clearHandlers() { clearNetworkHandlers(); } -void GeneralHandler::stateChanged(State oldState, State newState) +void GeneralHandler::event(Channels channel, + const Mana::Event &event) { - if (newState == STATE_GAME) + if (channel == CHANNEL_CLIENT) { - GameHandler *game = static_cast<GameHandler*>(Net::getGameHandler()); - game->gameLoading(); + if (event.getName() == EVENT_STATECHANGE) + { + int newState = event.getInt("newState"); + + if (newState == STATE_GAME) + { + GameHandler *game = static_cast<GameHandler*>(Net::getGameHandler()); + game->gameLoading(); + } + } + else if (event.getName() == EVENT_DBSLOADING) + { + Attributes::load(); + Attributes::informItemDB(); + } } - else if (newState == STATE_LOAD_DATA) + else if (channel == CHANNEL_GAME) { - Stats::load(); - Stats::informItemDB(); + if (event.getName() == EVENT_GUIWINDOWSLOADED) + { + inventoryWindow->setSplitAllowed(true); + skillDialog->loadSkills("mana-skills.xml"); + + PlayerInfo::setAttribute(EXP_NEEDED, 100); + + Attributes::informStatusWindow(); + } } } diff --git a/src/net/manaserv/generalhandler.h b/src/net/manaserv/generalhandler.h index 58b95529..c8671ec1 100644 --- a/src/net/manaserv/generalhandler.h +++ b/src/net/manaserv/generalhandler.h @@ -22,6 +22,8 @@ #ifndef NET_MANASERV_GENERALHANDLER_H #define NET_MANASERV_GENERALHANDLER_H +#include "listener.h" + #include "net/generalhandler.h" #include "net/net.h" @@ -29,7 +31,7 @@ namespace ManaServ { -class GeneralHandler : public Net::GeneralHandler +class GeneralHandler : public Net::GeneralHandler, public Mana::Listener { public: GeneralHandler(); @@ -42,13 +44,9 @@ class GeneralHandler : public Net::GeneralHandler void flushNetwork(); - void guiWindowsLoaded(); - - void guiWindowsUnloaded(); - void clearHandlers(); - void stateChanged(State oldState, State newState); + void event(Channels channel, const Mana::Event &event); protected: MessageHandlerPtr mBeingHandler; diff --git a/src/net/manaserv/guildhandler.cpp b/src/net/manaserv/guildhandler.cpp index 253efb01..821d70bd 100644 --- a/src/net/manaserv/guildhandler.cpp +++ b/src/net/manaserv/guildhandler.cpp @@ -21,16 +21,17 @@ #include "net/manaserv/guildhandler.h" +#include "event.h" #include "guild.h" #include "log.h" #include "localplayer.h" #include "channel.h" #include "channelmanager.h" -#include "gui/widgets/channeltab.h" -#include "gui/chat.h" #include "gui/socialwindow.h" +#include "gui/widgets/channeltab.h" + #include "net/messagein.h" #include "net/net.h" @@ -78,12 +79,12 @@ void GuildHandler::handleMessage(Net::MessageIn &msg) if (msg.readInt8() == ERRMSG_OK) { // TODO - Acknowledge guild was created - localChatTab->chatLog(_("Guild created.")); + SERVER_NOTICE(_("Guild created.")) joinedGuild(msg); } else { - localChatTab->chatLog(_("Error creating guild.")); + SERVER_NOTICE(_("Error creating guild.")) } } break; @@ -93,7 +94,7 @@ void GuildHandler::handleMessage(Net::MessageIn &msg) if (msg.readInt8() == ERRMSG_OK) { // TODO - Acknowledge invite was sent - localChatTab->chatLog(_("Invite sent.")); + SERVER_NOTICE(_("Invite sent.")) } } break; @@ -200,12 +201,12 @@ void GuildHandler::handleMessage(Net::MessageIn &msg) if (msg.readInt8() == ERRMSG_OK) { // promotion succeeded - localChatTab->chatLog(_("Member was promoted successfully.")); + SERVER_NOTICE(_("Member was promoted successfully.")) } else { // promotion failed - localChatTab->chatLog(_("Failed to promote member.")); + SERVER_NOTICE(_("Failed to promote member.")) } } @@ -275,9 +276,9 @@ void GuildHandler::invite(int guildId, const std::string &name) chatServerConnection->send(msg); } -void GuildHandler::invite(int guildId, Player *player) +void GuildHandler::invite(int guildId, Being *being) { - invite(guildId, player->getName()); + invite(guildId, being->getName()); } void GuildHandler::inviteResponse(int guildId, bool response) diff --git a/src/net/manaserv/guildhandler.h b/src/net/manaserv/guildhandler.h index 9929d135..bde677fb 100644 --- a/src/net/manaserv/guildhandler.h +++ b/src/net/manaserv/guildhandler.h @@ -41,7 +41,7 @@ public: void invite(int guildId, const std::string &name); - void invite(int guidId, Player *player); + void invite(int guidId, Being *being); void inviteResponse(int guidId, bool response); diff --git a/src/net/manaserv/inventoryhandler.cpp b/src/net/manaserv/inventoryhandler.cpp index 76fca7ae..9d2fdfeb 100644 --- a/src/net/manaserv/inventoryhandler.cpp +++ b/src/net/manaserv/inventoryhandler.cpp @@ -26,8 +26,7 @@ #include "item.h" #include "itemshortcut.h" #include "localplayer.h" - -#include "gui/chat.h" +#include "playerinfo.h" #include "net/manaserv/connection.h" #include "net/manaserv/messagein.h" @@ -36,8 +35,6 @@ #include "resources/iteminfo.h" -#include "log.h" // <<< REMOVE ME! - extern Net::InventoryHandler *inventoryHandler; namespace ManaServ { @@ -49,10 +46,13 @@ InventoryHandler::InventoryHandler() static const Uint16 _messages[] = { GPMSG_INVENTORY_FULL, GPMSG_INVENTORY, + GPMSG_EQUIP, 0 }; handledMessages = _messages; inventoryHandler = this; + + listen(CHANNEL_ITEM); } void InventoryHandler::handleMessage(Net::MessageIn &msg) @@ -60,114 +60,142 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) switch (msg.getId()) { case GPMSG_INVENTORY_FULL: - player_node->clearInventory(); - player_node->mEquipment->setBackend(&mEquips); - // no break! - - case GPMSG_INVENTORY: - while (msg.getUnreadLength()) { - unsigned int slot = msg.readInt8(); - if (slot == 255) + PlayerInfo::clearInventory(); + PlayerInfo::getEquipment()->setBackend(&mEquips); + int count = msg.readInt16(); + while (count--) { - player_node->setMoney(msg.readInt32()); - continue; + unsigned int slot = msg.readInt16(); + int id = msg.readInt16(); + unsigned int amount = msg.readInt16(); + PlayerInfo::setInventoryItem(slot, id, amount); } - - int id = msg.readInt16(); - if (slot < EQUIPMENT_SIZE) - { - mEquips.setEquipment(slot, id); - } - else if (slot >= 32 && slot < 32 + getSize(Inventory::INVENTORY)) + while (msg.getUnreadLength()) { - int amount = id ? msg.readInt8() : 0; - player_node->setInvItem(slot - 32, id, amount); + unsigned int slot = msg.readInt8(); + unsigned int ref = msg.readInt16(); + + mEquips.addEquipment(slot, ref); } - }; + } break; - } -} -void InventoryHandler::equipItem(const Item *item) -{ - MessageOut msg(PGMSG_EQUIP); - msg.writeInt8(item->getInvIndex()); - gameServerConnection->send(msg); -} - -void InventoryHandler::unequipItem(const Item *item) -{ - MessageOut msg(PGMSG_UNEQUIP); - msg.writeInt8(item->getInvIndex()); - gameServerConnection->send(msg); - - // Tidy equipment directly to avoid weapon still shown bug, for instance - int equipSlot = item->getInvIndex(); - logger->log("Unequipping %d", equipSlot); - mEquips.setEquipment(equipSlot, 0); -} - -void InventoryHandler::useItem(const Item *item) -{ - MessageOut msg(PGMSG_USE_ITEM); - msg.writeInt8(item->getInvIndex()); - gameServerConnection->send(msg); -} - -void InventoryHandler::dropItem(const Item *item, int amount) -{ - MessageOut msg(PGMSG_DROP); - msg.writeInt8(item->getInvIndex()); - msg.writeInt8(amount); - gameServerConnection->send(msg); -} + case GPMSG_INVENTORY: + while (msg.getUnreadLength()) + { + unsigned int slot = msg.readInt16(); + int id = msg.readInt16(); + unsigned int amount = id ? msg.readInt16() : 0; + PlayerInfo::setInventoryItem(slot, id, amount); + } + break; -bool InventoryHandler::canSplit(const Item *item) -{ - return item && !item->isEquipment() && item->getQuantity() > 1; -} + case GPMSG_EQUIP: + while (msg.getUnreadLength()) + { + unsigned int ref = msg.readInt16(); + int count = msg.readInt8(); + while (count--) + { + unsigned int slot = msg.readInt8(); + unsigned int used = msg.readInt8(); -void InventoryHandler::splitItem(const Item *item, int amount) -{ - int newIndex = player_node->getInventory()->getFreeSlot(); - if (newIndex > Inventory::NO_SLOT_INDEX) - { - MessageOut msg(PGMSG_MOVE_ITEM); - msg.writeInt8(item->getInvIndex()); - msg.writeInt8(newIndex); - msg.writeInt8(amount); - gameServerConnection->send(msg); + mEquips.setEquipment(slot, used, ref); + } + } + break; } } -void InventoryHandler::moveItem(int oldIndex, int newIndex) -{ - if (oldIndex == newIndex) - return; - - MessageOut msg(PGMSG_MOVE_ITEM); - msg.writeInt8(oldIndex); - msg.writeInt8(newIndex); - msg.writeInt8(player_node->getInventory()->getItem(oldIndex) - ->getQuantity()); - gameServerConnection->send(msg); -} - -void InventoryHandler::openStorage(int type) +void InventoryHandler::event(Channels channel, + const Mana::Event &event) { - // TODO -} + if (channel == CHANNEL_ITEM) + { + Item *item = event.getItem("item"); + + if (!item) + return; + + int index = item->getInvIndex(); + + if (event.getName() == EVENT_DOEQUIP) + { + MessageOut msg(PGMSG_EQUIP); + msg.writeInt8(index); + gameServerConnection->send(msg); + } + else if (event.getName() == EVENT_DOUNEQUIP) + { + MessageOut msg(PGMSG_UNEQUIP); + msg.writeInt8(index); + gameServerConnection->send(msg); + + // Tidy equipment directly to avoid weapon still shown bug, + // for instance. + mEquips.setEquipment(index, 0, 0); + } + else if (event.getName() == EVENT_DOUSE) + { + MessageOut msg(PGMSG_USE_ITEM); + msg.writeInt8(index); + gameServerConnection->send(msg); + } + else if (event.getName() == EVENT_DODROP) + { + int amount = event.getInt("amount", 1); + + MessageOut msg(PGMSG_DROP); + msg.writeInt8(index); + msg.writeInt8(amount); + gameServerConnection->send(msg); + } + else if (event.getName() == EVENT_DOSPLIT) + { + int amount = event.getInt("amount", 1); + + int newIndex = PlayerInfo::getInventory()->getFreeSlot(); + if (newIndex > Inventory::NO_SLOT_INDEX) + { + MessageOut msg(PGMSG_MOVE_ITEM); + msg.writeInt8(index); + msg.writeInt8(newIndex); + msg.writeInt8(amount); + gameServerConnection->send(msg); + } + } + else if (event.getName() == EVENT_DOMOVE) + { + int newIndex = event.getInt("newIndex", -1); + + if (newIndex >= 0) + { + if (index == newIndex) + return; + + MessageOut msg(PGMSG_MOVE_ITEM); + msg.writeInt8(index); + msg.writeInt8(newIndex); + msg.writeInt8(item->getQuantity()); + gameServerConnection->send(msg); + } + else + { + /*int source = event.getInt("source"); + int destination = event.getInt("destination"); + int amount = event.getInt("amount", 1);*/ -void InventoryHandler::closeStorage(int type) -{ - // TODO + // TODO + } + } + } } -void InventoryHandler::moveItem(int source, int slot, int amount, - int destination) +bool InventoryHandler::canSplit(const Item *item) { - // TODO + return item && !item->getInfo().getEquippable() + && item->getQuantity() > 1; } size_t InventoryHandler::getSize(int type) const diff --git a/src/net/manaserv/inventoryhandler.h b/src/net/manaserv/inventoryhandler.h index fd08b95e..bb68ceeb 100644 --- a/src/net/manaserv/inventoryhandler.h +++ b/src/net/manaserv/inventoryhandler.h @@ -23,6 +23,7 @@ #define NET_MANASERV_INVENTORYHANDLER_H #include "equipment.h" +#include "listener.h" #include "net/inventoryhandler.h" @@ -37,64 +38,38 @@ class EquipBackend : public Equipment::Backend { memset(mEquipment, 0, sizeof(mEquipment)); } Item *getEquipment(int index) const - { return mEquipment[index]; } + { return 0; } void clear() { - for (int i = 0; i < EQUIPMENT_SIZE; ++i) - delete mEquipment[i]; + } - std::fill_n(mEquipment, EQUIPMENT_SIZE, (Item*) 0); + void setEquipment(unsigned int slot, unsigned int used, int reference) + { + printf("Equip: %d at %dx%d\n", reference, slot, used); } - void setEquipment(int index, int id, int quantity = 0) + void addEquipment(unsigned int slot, int reference) { - if (mEquipment[index] && mEquipment[index]->getId() == id) - return; - - delete mEquipment[index]; - mEquipment[index] = (id > 0) ? new Item(id, quantity) : 0; - - if (mEquipment[index]) - { - mEquipment[index]->setInvIndex(index); - mEquipment[index]->setEquipped(true); - mEquipment[index]->setInEquipment(true); - } + printf("Equip: %d at %d\n", reference, slot); } private: Item *mEquipment[EQUIPMENT_SIZE]; }; -class InventoryHandler : public MessageHandler, Net::InventoryHandler +class InventoryHandler : public MessageHandler, Net::InventoryHandler, + public Mana::Listener { public: InventoryHandler(); void handleMessage(Net::MessageIn &msg); - void equipItem(const Item *item); - - void unequipItem(const Item *item); - - void useItem(const Item *item); - - void dropItem(const Item *item, int amount); + void event(Channels channel, const Mana::Event &event); bool canSplit(const Item *item); - void splitItem(const Item *item, int amount); - - void moveItem(int oldIndex, int newIndex); - - void openStorage(int type); - - void closeStorage(int type); - - void moveItem(int source, int slot, int amount, - int destination); - size_t getSize(int type) const; private: diff --git a/src/net/manaserv/itemhandler.cpp b/src/net/manaserv/itemhandler.cpp index dc3b9f14..200e7fac 100644 --- a/src/net/manaserv/itemhandler.cpp +++ b/src/net/manaserv/itemhandler.cpp @@ -21,7 +21,7 @@ #include "net/manaserv/itemhandler.h" -#include "flooritemmanager.h" +#include "actorspritemanager.h" #include "net/manaserv/protocol.h" #include "net/manaserv/messagein.h" @@ -62,8 +62,7 @@ void ItemHandler::handleMessage(Net::MessageIn &msg) { if (Map *map = game->getCurrentMap()) { - floorItemManager->create(id, - itemId, + actorSpriteManager->createItem(id, itemId, x / map->getTileWidth(), y / map->getTileHeight()); } @@ -75,9 +74,9 @@ void ItemHandler::handleMessage(Net::MessageIn &msg) } } } - else if (FloorItem *item = floorItemManager->findById(id)) + else if (FloorItem *item = actorSpriteManager->findItem(id)) { - floorItemManager->destroy(item); + actorSpriteManager->destroy(item); } } } break; diff --git a/src/net/manaserv/loginhandler.cpp b/src/net/manaserv/loginhandler.cpp index 61671824..29418124 100644 --- a/src/net/manaserv/loginhandler.cpp +++ b/src/net/manaserv/loginhandler.cpp @@ -196,7 +196,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg) // Successful unregistration if (errMsg == ERRMSG_OK) { - Client::setState(STATE_UNREGISTER); + Client::setState(STATE_UNREGISTER_SUCCESS); } // Unregistration failed else diff --git a/src/net/manaserv/network.cpp b/src/net/manaserv/network.cpp index 636585c9..a5bf6186 100644 --- a/src/net/manaserv/network.cpp +++ b/src/net/manaserv/network.cpp @@ -53,7 +53,7 @@ void initialize() logger->error("Failed to initialize ENet."); } -#ifdef ENET_VERSION_MAJOR +#if defined(ENET_VERSION) && ENET_VERSION >= ENET_CUTOFF client = enet_host_create(NULL, 3, 0, 0, 0); #else client = enet_host_create(NULL, 3, 0, 0); diff --git a/src/net/manaserv/npchandler.cpp b/src/net/manaserv/npchandler.cpp index 392ec4fd..9620f7c1 100644 --- a/src/net/manaserv/npchandler.cpp +++ b/src/net/manaserv/npchandler.cpp @@ -21,17 +21,16 @@ #include "net/manaserv/npchandler.h" -#include "beingmanager.h" -#include "npc.h" - -#include "gui/npcdialog.h" -#include "gui/npcpostdialog.h" +#include "actorspritemanager.h" +#include "event.h" #include "net/manaserv/connection.h" #include "net/manaserv/messagein.h" #include "net/manaserv/messageout.h" #include "net/manaserv/protocol.h" +#include "utils/stringutils.h" + extern Net::NpcHandler *npcHandler; namespace ManaServ { @@ -56,76 +55,112 @@ NpcHandler::NpcHandler() void NpcHandler::handleMessage(Net::MessageIn &msg) { - Being *being = beingManager->findBeing(msg.readInt16()); - if (!being || being->getType() != Being::NPC) + Being *being = actorSpriteManager->findBeing(msg.readInt16()); + if (!being || being->getType() != ActorSprite::NPC) { return; } - int npcId = being->getId(); - NpcDialogs::iterator diag = mNpcDialogs.find(npcId); - NpcDialog *dialog; - - if (diag == mNpcDialogs.end()) - { - if (msg.getId() == GPMSG_NPC_ERROR || msg.getId() == GPMSG_NPC_CLOSE) - return; // Dialog is pointless in these cases - - dialog = new NpcDialog(npcId); - Wrapper wrap; - wrap.dialog = dialog; - mNpcDialogs[npcId] = wrap; - } - else - { - dialog = diag->second.dialog; - } + int npcId = being->getId(), count = 0; + Mana::Event *event = 0; switch (msg.getId()) { - case GPMSG_NPC_CHOICE: - dialog->choiceRequest(); - while (msg.getUnreadLength()) - { - dialog->addChoice(msg.readString()); - } - break; - - case GPMSG_NPC_NUMBER: + case GPMSG_NPC_CHOICE: + event = new Mana::Event(EVENT_MENU); + event->setInt("id", npcId); + while (msg.getUnreadLength()) { - int min_num = msg.readInt32(); - int max_num = msg.readInt32(); - dialog->integerRequest(msg.readInt32(), min_num, max_num); - break; + count++; + event->setString("choice" + toString(count), msg.readString()); } + event->setInt("choiceCount", count); + event->trigger(CHANNEL_NPC); + break; + + case GPMSG_NPC_NUMBER: + event = new Mana::Event(EVENT_INTEGERINPUT); + event->setInt("id", npcId); + event->setInt("min", msg.readInt32()); + event->setInt("max", msg.readInt32()); + event->setInt("default", msg.readInt32()); + event->trigger(CHANNEL_NPC); + break; + + case GPMSG_NPC_STRING: + event = new Mana::Event(EVENT_STRINGINPUT); + event->setInt("id", npcId); + event->trigger(CHANNEL_NPC); + break; + + case GPMSG_NPC_POST: + event = new Mana::Event(EVENT_POST); + event->setInt("id", npcId); + event->trigger(CHANNEL_NPC); + break; + + case GPMSG_NPC_ERROR: + event = new Mana::Event(EVENT_END); + event->setInt("id", npcId); + event->trigger(CHANNEL_NPC); + break; + + case GPMSG_NPC_MESSAGE: + event = new Mana::Event(EVENT_MESSAGE); + event->setInt("id", npcId); + event->setString("text", msg.readString(msg.getUnreadLength())); + event->trigger(CHANNEL_NPC); + delete event; + + event = new Mana::Event(EVENT_NEXT); + event->setInt("id", npcId); + event->trigger(CHANNEL_NPC); + break; + + case GPMSG_NPC_CLOSE: + event = new Mana::Event(EVENT_CLOSE); + event->setInt("id", npcId); + event->trigger(CHANNEL_NPC); + break; + } - case GPMSG_NPC_STRING: - dialog->textRequest(""); - break; + delete event; +} - case GPMSG_NPC_POST: - { - new NpcPostDialog(npcId); - break; - } +void NpcHandler::startShopping(int beingId) +{ + // TODO +} - case GPMSG_NPC_ERROR: - dialog->close(); - if (diag != mNpcDialogs.end()) - { - mNpcDialogs.erase(diag); - } - break; - - case GPMSG_NPC_MESSAGE: - dialog->addText(msg.readString(msg.getUnreadLength())); - dialog->showNextButton(); - break; - - case GPMSG_NPC_CLOSE: - dialog->showCloseButton(); - break; - } +void NpcHandler::buy(int beingId) +{ + // TODO +} + +void NpcHandler::sell(int beingId) +{ + // TODO +} + +void NpcHandler::buyItem(int beingId, int itemId, int amount) +{ + MessageOut msg(PGMSG_NPC_BUYSELL); + msg.writeInt16(itemId); + msg.writeInt16(amount); + gameServerConnection->send(msg); +} + +void NpcHandler::sellItem(int beingId, int itemId, int amount) +{ + MessageOut msg(PGMSG_NPC_BUYSELL); + msg.writeInt16(itemId); + msg.writeInt16(amount); + gameServerConnection->send(msg); +} + +void NpcHandler::endShopping(int beingId) +{ + // TODO } void NpcHandler::talk(int npcId) @@ -133,6 +168,10 @@ void NpcHandler::talk(int npcId) MessageOut msg(PGMSG_NPC_TALK); msg.writeInt16(npcId); gameServerConnection->send(msg); + + Mana::Event event(EVENT_TALKSENT); + event.setInt("npcId", npcId); + event.trigger(CHANNEL_NPC); } void NpcHandler::nextDialog(int npcId) @@ -140,6 +179,10 @@ void NpcHandler::nextDialog(int npcId) MessageOut msg(PGMSG_NPC_TALK_NEXT); msg.writeInt16(npcId); gameServerConnection->send(msg); + + Mana::Event event(EVENT_NEXTSENT); + event.setInt("npcId", npcId); + event.trigger(CHANNEL_NPC); } void NpcHandler::closeDialog(int npcId) @@ -148,20 +191,22 @@ void NpcHandler::closeDialog(int npcId) msg.writeInt16(npcId); gameServerConnection->send(msg); - NpcDialogs::iterator it = mNpcDialogs.find(npcId); - if (it != mNpcDialogs.end()) - { - (*it).second.dialog->close(); - mNpcDialogs.erase(it); - } + Mana::Event event(EVENT_CLOSESENT); + event.setInt("npcId", npcId); + event.trigger(CHANNEL_NPC); } -void NpcHandler::listInput(int npcId, int value) +void NpcHandler::menuSelect(int npcId, int choice) { MessageOut msg(PGMSG_NPC_SELECT); msg.writeInt16(npcId); - msg.writeInt8(value); + msg.writeInt8(choice); gameServerConnection->send(msg); + + Mana::Event event(EVENT_MENUSENT); + event.setInt("npcId", npcId); + event.setInt("choice", choice); + event.trigger(CHANNEL_NPC); } void NpcHandler::integerInput(int npcId, int value) @@ -170,6 +215,11 @@ void NpcHandler::integerInput(int npcId, int value) msg.writeInt16(npcId); msg.writeInt32(value); gameServerConnection->send(msg); + + Mana::Event event(EVENT_INTEGERINPUTSENT); + event.setInt("npcId", npcId); + event.setInt("value", value); + event.trigger(CHANNEL_NPC); } void NpcHandler::stringInput(int npcId, const std::string &value) @@ -178,56 +228,26 @@ void NpcHandler::stringInput(int npcId, const std::string &value) msg.writeInt16(npcId); msg.writeString(value); gameServerConnection->send(msg); + + Mana::Event event(EVENT_STRINGINPUTSENT); + event.setInt("npcId", npcId); + event.setString("value", value); + event.trigger(CHANNEL_NPC); } void NpcHandler::sendLetter(int npcId, const std::string &recipient, - const std::string &text) + const std::string &text) { MessageOut msg(PGMSG_NPC_POST_SEND); msg.writeString(recipient); msg.writeString(text); gameServerConnection->send(msg); -} - -void NpcHandler::startShopping(int beingId) -{ - // TODO -} - -void NpcHandler::buy(int beingId) -{ - // TODO -} - -void NpcHandler::sell(int beingId) -{ - // TODO -} -void NpcHandler::buyItem(int beingId, int itemId, int amount) -{ - MessageOut msg(PGMSG_NPC_BUYSELL); - msg.writeInt16(itemId); - msg.writeInt16(amount); - gameServerConnection->send(msg); -} - -void NpcHandler::sellItem(int beingId, int itemId, int amount) -{ - MessageOut msg(PGMSG_NPC_BUYSELL); - msg.writeInt16(itemId); - msg.writeInt16(amount); - gameServerConnection->send(msg); -} - -void NpcHandler::endShopping(int beingId) -{ - // TODO -} - -void NpcHandler::clearDialogs() -{ - mNpcDialogs.clear(); + Mana::Event event(EVENT_SENDLETTERSENT); + event.setInt("npcId", npcId); + event.setString("recipient", recipient); + event.setString("text", text); + event.trigger(CHANNEL_NPC); } } // namespace ManaServ diff --git a/src/net/manaserv/npchandler.h b/src/net/manaserv/npchandler.h index 689fdc1d..cb8fd67d 100644 --- a/src/net/manaserv/npchandler.h +++ b/src/net/manaserv/npchandler.h @@ -22,14 +22,14 @@ #ifndef NET_MANASERV_NPCHANDLER_H #define NET_MANASERV_NPCHANDLER_H +#include "listener.h" + #include "net/npchandler.h" #include "net/manaserv/messagehandler.h" #include <map> -class NpcDialog; - namespace ManaServ { class NpcHandler : public MessageHandler, public Net::NpcHandler @@ -39,21 +39,6 @@ class NpcHandler : public MessageHandler, public Net::NpcHandler void handleMessage(Net::MessageIn &msg); - void talk(int npcId); - - void nextDialog(int npcId); - - void closeDialog(int npcId); - - void listInput(int npcId, int value); - - void integerInput(int npcId, int value); - - void stringInput(int npcId, const std::string &value); - - void sendLetter(int npcId, const std::string &recipient, - const std::string &text); - void startShopping(int beingId); void buy(int beingId); @@ -66,14 +51,21 @@ class NpcHandler : public MessageHandler, public Net::NpcHandler void endShopping(int beingId); - void clearDialogs(); + void talk(int npcId); + + void nextDialog(int npcId); + + void closeDialog(int npcId); + + void menuSelect(int npcId, int choice); + + void integerInput(int npcId, int value); + + void stringInput(int npcId, const std::string &value); + + void sendLetter(int npcId, const std::string &recipient, + const std::string &text); - private: - typedef struct { - NpcDialog* dialog; - } Wrapper; - typedef std::map<int, Wrapper> NpcDialogs; - NpcDialogs mNpcDialogs; }; } // namespace ManaServ diff --git a/src/net/manaserv/partyhandler.cpp b/src/net/manaserv/partyhandler.cpp index ec153fa8..370d6496 100644 --- a/src/net/manaserv/partyhandler.cpp +++ b/src/net/manaserv/partyhandler.cpp @@ -21,13 +21,12 @@ #include "net/manaserv/partyhandler.h" +#include "event.h" #include "log.h" #include "localplayer.h" #include "gui/socialwindow.h" -#include "gui/widgets/chattab.h" - #include "net/manaserv/connection.h" #include "net/manaserv/messagein.h" #include "net/manaserv/messageout.h" @@ -85,7 +84,7 @@ void PartyHandler::handleMessage(Net::MessageIn &msg) if (msg.readInt8() == ERRMSG_OK) { // - localChatTab->chatLog(_("Joined party.")); + SERVER_NOTICE(_("Joined party.")); } } @@ -103,7 +102,7 @@ void PartyHandler::handleMessage(Net::MessageIn &msg) int id = msg.readInt16(); // being id std::string name = msg.readString(); - localChatTab->chatLog(strprintf(_("%s joined the party."), + SERVER_NOTICE(strprintf(_("%s joined the party."), name.c_str())); if (id == player_node->getId()) @@ -120,8 +119,8 @@ void PartyHandler::handleMessage(Net::MessageIn &msg) case CPMSG_PARTY_REJECTED: { std::string name = msg.readString(); - localChatTab->chatLog(strprintf(_("%s rejected your invite."), - name.c_str())); + SERVER_NOTICE(strprintf( + _("%s rejected your invite."), name.c_str())); } break; } } @@ -136,9 +135,9 @@ void PartyHandler::join(int partyId) // TODO } -void PartyHandler::invite(Player *player) +void PartyHandler::invite(Being *being) { - invite(player->getName()); + invite(being->getName()); } void PartyHandler::invite(const std::string &name) @@ -167,7 +166,7 @@ void PartyHandler::leave() chatServerConnection->send(msg); } -void PartyHandler::kick(Player *player) +void PartyHandler::kick(Being *being) { // TODO } diff --git a/src/net/manaserv/partyhandler.h b/src/net/manaserv/partyhandler.h index 0777b49e..29dc280d 100644 --- a/src/net/manaserv/partyhandler.h +++ b/src/net/manaserv/partyhandler.h @@ -43,7 +43,7 @@ public: void join(int partyId); - void invite(Player *player); + void invite(Being *being); void invite(const std::string &name); @@ -51,7 +51,7 @@ public: void leave(); - void kick(Player *player); + void kick(Being *being); void kick(const std::string &name); diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp index 33367927..be09ff69 100644 --- a/src/net/manaserv/playerhandler.cpp +++ b/src/net/manaserv/playerhandler.cpp @@ -24,14 +24,14 @@ #include "client.h" #include "effectmanager.h" +#include "event.h" #include "game.h" #include "localplayer.h" #include "log.h" #include "particle.h" -#include "npc.h" +#include "playerinfo.h" #include "configuration.h" -#include "gui/chat.h" #include "gui/gui.h" #include "gui/okdialog.h" #include "gui/viewport.h" @@ -39,10 +39,11 @@ #include "net/net.h" #include "net/manaserv/connection.h" +#include "net/manaserv/defines.h" #include "net/manaserv/messagein.h" #include "net/manaserv/messageout.h" -#include "net/manaserv/npchandler.h" #include "net/manaserv/protocol.h" +#include "net/manaserv/attributes.h" /** * Max. distance we are willing to scroll after a teleport; @@ -64,9 +65,7 @@ void RespawnRequestListener::action(const gcn::ActionEvent &event) { Net::getPlayerHandler()->respawn(); - ManaServ::NpcHandler *handler = - static_cast<ManaServ::NpcHandler*>(Net::getNpcHandler()); - handler->clearDialogs(); + Mana::Event::trigger(CHANNEL_NPC, EVENT_CLOSEALL); } PlayerHandler::PlayerHandler() @@ -112,23 +111,24 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) case GPMSG_PLAYER_ATTRIBUTE_CHANGE: { - logger->log("ATTRIBUTE UPDATE:"); while (msg.getUnreadLength()) { - int stat = msg.readInt16(); - int base = msg.readInt16(); - int value = msg.readInt16(); - logger->log("%d set to %d %d", stat, base, value); - - if (stat == BASE_ATTR_HP) + int attrId = msg.readInt16(); + double base = msg.readInt32() / 256.0; + double value = msg.readInt32() / 256.0; + + // Set the core player attribute the stat + // depending on attribute link. + int playerInfoId = + Attributes::getPlayerInfoIdFromAttrId(attrId); + if (playerInfoId > -1) { - player_node->setMaxHp(base); - player_node->setHp(value); + PlayerInfo::setAttribute(playerInfoId, value); } else { - player_node->setAttributeBase(stat, base); - player_node->setAttributeEffective(stat, value); + PlayerInfo::setStatBase(attrId, base); + PlayerInfo::setStatMod(attrId, value - base); } } } break; @@ -142,33 +142,33 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) int current = msg.readInt32(); int next = msg.readInt32(); - player_node->setExperience(skill, current, next); + PlayerInfo::setStatExperience(skill, current, next); } } break; case GPMSG_LEVELUP: { - player_node->setLevel(msg.readInt16()); - player_node->setCharacterPoints(msg.readInt16()); - player_node->setCorrectionPoints(msg.readInt16()); + PlayerInfo::setAttribute(LEVEL, msg.readInt16()); + PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16()); + PlayerInfo::setAttribute(CORR_POINTS, msg.readInt16()); Particle* effect = particleEngine->addEffect( - paths.getValue("particles", "graphics/particles/") - + paths.getValue("levelUpEffectFile", "levelup.particle.xml"), - 0, 0); + paths.getStringValue("particles") + + paths.getStringValue("levelUpEffectFile") + ,0, 0); player_node->controlParticle(effect); } break; case GPMSG_LEVEL_PROGRESS: { - player_node->setExp(msg.readInt8(), false); + PlayerInfo::setAttribute(EXP, msg.readInt8()); } break; case GPMSG_RAISE_ATTRIBUTE_RESPONSE: { int errCode = msg.readInt8(); - int attrNum = msg.readInt8() - CHAR_ATTR_BEGIN; + int attrNum = msg.readInt16(); switch (errCode) { case ATTRIBMOD_OK: @@ -185,18 +185,19 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) // has to be correct. The server is always right! // undo attribute change and set points to 0 logger->log("Warning: Server denied increase of attribute %d (no points left) ", attrNum); - int attrValue = player_node->getAttributeBase(attrNum) - 1; - player_node->setCharacterPoints(0); - player_node->setAttributeBase(attrNum, attrValue); + int attrValue = PlayerInfo::getStatBase(attrNum) - 1; + PlayerInfo::setAttribute(CHAR_POINTS, 0); + PlayerInfo::setStatBase(attrNum, attrValue); } break; case ATTRIBMOD_DENIED: { // undo attribute change logger->log("Warning: Server denied increase of attribute %d (reason unknown) ", attrNum); - int points = player_node->getCharacterPoints() - 1; - player_node->setCharacterPoints(points); - int attrValue = player_node->getAttributeBase(attrNum) - 1; - player_node->setAttributeBase(attrNum, attrValue); + int points = PlayerInfo::getAttribute(CHAR_POINTS) - 1; + PlayerInfo::setAttribute(CHAR_POINTS, points); + + int attrValue = PlayerInfo::getStatBase(attrNum) - 1; + PlayerInfo::setStatBase(attrNum, attrValue); } break; } } break; @@ -204,7 +205,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) case GPMSG_LOWER_ATTRIBUTE_RESPONSE: { int errCode = msg.readInt8(); - int attrNum = msg.readInt8() - CHAR_ATTR_BEGIN; + int attrNum = msg.readInt16(); switch (errCode) { case ATTRIBMOD_OK: @@ -221,21 +222,24 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) // has to be correct. The server is always right! // undo attribute change and set points to 0 logger->log("Warning: Server denied reduction of attribute %d (no points left) ", attrNum); - int attrValue = player_node->getAttributeBase(attrNum) + 1; - player_node->setCorrectionPoints(0); - player_node->setAttributeBase(attrNum, attrValue); - break; + int attrValue = PlayerInfo::getStatBase(attrNum) + 1; + // TODO are these right? + PlayerInfo::setAttribute(CHAR_POINTS, 0); + PlayerInfo::setAttribute(CORR_POINTS, 0); + PlayerInfo::setStatBase(attrNum, attrValue); } break; case ATTRIBMOD_DENIED: { // undo attribute change logger->log("Warning: Server denied reduction of attribute %d (reason unknown) ", attrNum); - int charaPoints = player_node->getCharacterPoints() - 1; - player_node->setCharacterPoints(charaPoints); - int correctPoints = player_node->getCorrectionPoints() + 1; - player_node->setCorrectionPoints(correctPoints); - int attrValue = player_node->getAttributeBase(attrNum) + 1; - player_node->setAttributeBase(attrNum, attrValue); + int charaPoints = PlayerInfo::getAttribute(CHAR_POINTS) - 1; + PlayerInfo::setAttribute(CHAR_POINTS, charaPoints); + + int correctPoints = PlayerInfo::getAttribute(CORR_POINTS) + 1; + PlayerInfo::setAttribute(CORR_POINTS, correctPoints); + + int attrValue = PlayerInfo::getStatBase(attrNum) + 1; + PlayerInfo::setStatBase(attrNum, attrValue); } break; } @@ -250,7 +254,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) int current = msg.readInt32(); int max = msg.readInt32(); int recharge = msg.readInt32(); - player_node->setSpecialStatus(id, current, max, recharge); + PlayerInfo::setSpecialStatus(id, current, max, recharge); } } break; /* @@ -325,14 +329,14 @@ void PlayerHandler::emote(int emoteId) void PlayerHandler::increaseAttribute(int attr) { MessageOut msg(PGMSG_RAISE_ATTRIBUTE); - msg.writeInt8(attr); + msg.writeInt16(attr); gameServerConnection->send(msg); } void PlayerHandler::decreaseAttribute(int attr) { MessageOut msg(PGMSG_LOWER_ATTRIBUTE); - msg.writeInt8(attr); + msg.writeInt16(attr); gameServerConnection->send(msg); } @@ -343,11 +347,14 @@ void PlayerHandler::increaseSkill(int skillId) void PlayerHandler::pickUp(FloorItem *floorItem) { - int id = floorItem->getId(); - MessageOut msg(PGMSG_PICKUP); - msg.writeInt16(id >> 16); - msg.writeInt16(id & 0xFFFF); - gameServerConnection->send(msg); + if (floorItem) + { + int id = floorItem->getId(); + MessageOut msg(PGMSG_PICKUP); + msg.writeInt16(id >> 16); + msg.writeInt16(id & 0xFFFF); + gameServerConnection->send(msg); + } } void PlayerHandler::setDirection(char direction) diff --git a/src/net/manaserv/protocol.h b/src/net/manaserv/protocol.h index 226a27a0..beb04b21 100644 --- a/src/net/manaserv/protocol.h +++ b/src/net/manaserv/protocol.h @@ -57,7 +57,10 @@ enum { APMSG_CHAR_CREATE_RESPONSE = 0x0021, // B error PAMSG_CHAR_DELETE = 0x0022, // B index APMSG_CHAR_DELETE_RESPONSE = 0x0023, // B error - APMSG_CHAR_INFO = 0x0024, // B index, S name, B gender, B hair style, B hair color, W level, W character points, W correction points, D money, W*6 stats + // B index, S name, B gender, B hair style, B hair color, W level, + // W character points, W correction points, + // {D attr id, D base value (in 1/256ths) D mod value (in 256ths) }* + APMSG_CHAR_INFO = 0x0024, // ^ PAMSG_CHAR_SELECT = 0x0026, // B index APMSG_CHAR_SELECT_RESPONSE = 0x0027, // B error, B*32 token, S game address, W game port, S chat address, W chat port PAMSG_EMAIL_CHANGE = 0x0030, // S email @@ -86,16 +89,17 @@ enum { PGMSG_EQUIP = 0x0112, // B slot PGMSG_UNEQUIP = 0x0113, // B slot PGMSG_MOVE_ITEM = 0x0114, // B slot1, B slot2, B amount - GPMSG_INVENTORY = 0x0120, // { B slot, W item id [, B amount] }* - GPMSG_INVENTORY_FULL = 0x0121, // { B slot, W item id [, B amount] }* - GPMSG_PLAYER_ATTRIBUTE_CHANGE = 0x0130, // { W attribute, W base value, W modified value }* + GPMSG_INVENTORY = 0x0120, // { W slot, W item id [, W amount] (if item id is nonzero) }* + GPMSG_INVENTORY_FULL = 0x0121, // W inventory slot count { W slot, W itemId, W amount } { B equip slot, W invy slot}* + GPMSG_EQUIP = 0x0122, // { W Invy slot, B equip slot type count { B equip slot, B number used} }* + GPMSG_PLAYER_ATTRIBUTE_CHANGE = 0x0130, // { W attribute, D base value (in 1/256ths), D modified value (in 1/256ths)}* GPMSG_PLAYER_EXP_CHANGE = 0x0140, // { W skill, D exp got, D exp needed }* GPMSG_LEVELUP = 0x0150, // W new level, W character points, W correction points GPMSG_LEVEL_PROGRESS = 0x0151, // B percent completed to next levelup - PGMSG_RAISE_ATTRIBUTE = 0x0160, // B attribute - GPMSG_RAISE_ATTRIBUTE_RESPONSE = 0x0161, // B error, B attribute - PGMSG_LOWER_ATTRIBUTE = 0x0170, // B attribute - GPMSG_LOWER_ATTRIBUTE_RESPONSE = 0x0171, // B error, B attribute + PGMSG_RAISE_ATTRIBUTE = 0x0160, // W attribute + GPMSG_RAISE_ATTRIBUTE_RESPONSE = 0x0161, // B error, W attribute + PGMSG_LOWER_ATTRIBUTE = 0x0170, // W attribute + GPMSG_LOWER_ATTRIBUTE_RESPONSE = 0x0171, // B error, W attribute PGMSG_RESPAWN = 0x0180, // - GPMSG_BEING_ENTER = 0x0200, // B type, W being id, B action, W*2 position // character: S name, B hair style, B hair color, B gender, B item bitmask, { W item id }* @@ -109,7 +113,7 @@ enum { GPMSG_BEING_ACTION_CHANGE = 0x0271, // W being id, B action PGMSG_DIRECTION_CHANGE = 0x0272, // B Direction GPMSG_BEING_DIR_CHANGE = 0x0273, // W being id, B direction - GPMSG_BEING_HEALTH_CHANGE = 0x0274, // W being id, W health + GPMSG_BEING_HEALTH_CHANGE = 0x0274, // W being id, W hp, W max hp GPMSG_BEINGS_MOVE = 0x0280, // { W being id, B flags [, W*2 position, B speed] }* GPMSG_ITEMS = 0x0281, // { W item id, W*2 position }* PGMSG_ATTACK = 0x0290, // W being id @@ -272,10 +276,11 @@ enum { // used to identify part of sync message enum { - SYNC_CHARACTER_POINTS = 0x01, // D charId, D charPoints, D corrPoints, B attribute id, D attribute value - SYNC_CHARACTER_SKILL = 0x02, // D charId, B skillId, D skill value - SYNC_ONLINE_STATUS = 0x03, // D charId, B 0x00 = offline, 0x01 = online - SYNC_END_OF_BUFFER = 0xFF // shows, that the buffer ends here. + SYNC_CHARACTER_POINTS = 0x01, // D charId, D charPoints, D corrPoints + SYNC_CHARACTER_ATTRIBUTE = 0x02, // D charId, D attrId, DF base, DF mod + SYNC_CHARACTER_SKILL = 0x03, // D charId, B skillId, D skill value + SYNC_ONLINE_STATUS = 0x04, // D charId, B 0x00 = offline, 0x01 = online + SYNC_END_OF_BUFFER = 0xFF // shows, that the buffer ends here. }; // Login specific return values @@ -300,7 +305,7 @@ enum { CREATE_INVALID_GENDER, CREATE_ATTRIBUTES_TOO_HIGH, CREATE_ATTRIBUTES_TOO_LOW, - CREATE_ATTRIBUTES_EQUAL_TO_ZERO, + CREATE_ATTRIBUTES_OUT_OF_RANGE, CREATE_EXISTS_NAME, CREATE_TOO_MUCH_CHARACTERS }; diff --git a/src/net/manaserv/stats.cpp b/src/net/manaserv/stats.cpp deleted file mode 100644 index ece0e72a..00000000 --- a/src/net/manaserv/stats.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * The Mana Client - * Copyright (C) 2010 The Mana Developers - * - * This file is part of The Mana Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "net/manaserv/stats.h" - -#include "log.h" - -#include "gui/statuswindow.h" - -#include "resources/itemdb.h" - -#include "utils/gettext.h" -#include "utils/xml.h" - -#include <list> -#include <map> - -#define DEFAULT_ATTRIBUTESDB_FILE "attributes.xml" - -namespace ManaServ { -namespace Stats { - typedef struct { - unsigned int id; - std::string name; - std::string tag; - std::string effect; - std::string description; - bool modifiable; - } Stat; - - typedef std::map<unsigned int, Stat> StatMap; - StatMap stats; - - static void loadBuiltins() - { - { - Stat s; - s.id = 16; - s.name = _("Strength"); - s.tag = "str"; - s.effect = _("Strength %+d"); - s.description = ""; - s.modifiable = true; - - stats[s.id] = s; - } - - { - Stat s; - s.id = 17; - s.name = _("Agility"); - s.tag = "agi"; - s.effect = _("Agility %+d"); - s.description = ""; - s.modifiable = true; - - stats[s.id] = s; - } - - { - Stat s; - s.id = 18; - s.name = _("Dexterity"); - s.tag = "dex"; - s.effect = _("Dexterity %+d"); - s.description = ""; - s.modifiable = true; - - stats[s.id] = s; - } - - { - Stat s; - s.id = 19; - s.name = _("Vitality"); - s.tag = "vit"; - s.effect = _("Vitality %+d"); - s.description = ""; - s.modifiable = true; - - stats[s.id] = s; - } - - { - Stat s; - s.id = 20; - s.name = _("Intelligence"); - s.tag = "int"; - s.effect = _("Intelligence %+d"); - s.description = ""; - s.modifiable = true; - - stats[s.id] = s; - } - - { - Stat s; - s.id = 21; - s.name = _("Willpower"); - s.tag = "will"; - s.effect = _("Willpower %+d"); - s.description = ""; - s.modifiable = true; - - stats[s.id] = s; - } - } - - void load() - { - XML::Document doc(DEFAULT_ATTRIBUTESDB_FILE); - xmlNodePtr rootNode = doc.rootNode(); - - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "stats")) - { - logger->log("Stats: Error while loading " - DEFAULT_ATTRIBUTESDB_FILE ". Using Built-ins."); - loadBuiltins(); - return; - } - - for_each_xml_child_node(node, rootNode) - { - if (!xmlStrEqual(node->name, BAD_CAST "stat")) - continue; - - int id = XML::getProperty(node, "id", 0); - - if (id == 0) - { - logger->log("Stats: Invalid or missing stat ID in " - DEFAULT_ATTRIBUTESDB_FILE "!"); - continue; - } - else if (stats.find(id) != stats.end()) - { - logger->log("Stats: Redefinition of stat ID %d", id); - } - - std::string name = XML::getProperty(node, "name", ""); - - if (name.empty()) - { - logger->log("Stats: Invalid or missing stat name in " - DEFAULT_ATTRIBUTESDB_FILE "!"); - continue; - } - - Stat s; - s.id = id; - s.name = name; - s.tag = XML::getProperty(node, "tag", ""); - s.effect = XML::getProperty(node, "effect", ""); - s.description = XML::getProperty(node, "desc", ""); - s.modifiable = XML::getProperty(node, "modifiable", "false") - == "true"; - - stats[id] = s; - } - } - - void unload() - { - stats.clear(); - } - - void informItemDB() - { - std::list<ItemDB::Stat> dbStats; - - StatMap::const_iterator it, it_end; - for (it = stats.begin(), it_end = stats.end(); it != it_end; it++) - if (!it->second.tag.empty()) - dbStats.push_back(ItemDB::Stat(it->second.tag, - it->second.effect)); - - ItemDB::setStatsList(dbStats); - } - - void informStatusWindow() - { - StatMap::const_iterator it, it_end; - for (it = stats.begin(), it_end = stats.end(); it != it_end; it++) - statusWindow->addAttribute(it->second.id, it->second.name, - it->second.modifiable, - it->second.description); - } - - std::vector<std::string> getLabelVector() - { - std::vector<std::string> attributes; - StatMap::const_iterator it, it_end; - for (it = stats.begin(), it_end = stats.end(); it != it_end; it++) - if (it->second.modifiable) - attributes.push_back(it->second.name + ":"); - - return attributes; - } -} // namespace Stats -} // namespace ManaServ diff --git a/src/net/manaserv/tradehandler.cpp b/src/net/manaserv/tradehandler.cpp index 234a18d6..30ff6890 100644 --- a/src/net/manaserv/tradehandler.cpp +++ b/src/net/manaserv/tradehandler.cpp @@ -21,15 +21,15 @@ #include "net/manaserv/tradehandler.h" -#include "beingmanager.h" +#include "actorspritemanager.h" +#include "event.h" #include "item.h" #include "localplayer.h" +#include "playerinfo.h" #include "gui/confirmdialog.h" #include "gui/trade.h" -#include "gui/widgets/chattab.h" - #include "net/net.h" #include "net/manaserv/connection.h" @@ -86,16 +86,15 @@ TradeHandler::TradeHandler(): }; handledMessages = _messages; tradeHandler = this; - } void TradeHandler::setAcceptTradeRequests(bool acceptTradeRequests) { mAcceptTradeRequests = acceptTradeRequests; if (mAcceptTradeRequests) - localChatTab->chatLog(_("Accepting incoming trade requests."), BY_SERVER); + SERVER_NOTICE(_("Accepting incoming trade requests.")) else - localChatTab->chatLog(_("Ignoring incoming trade requests."), BY_SERVER); + SERVER_NOTICE(_("Ignoring incoming trade requests.")) } void TradeHandler::handleMessage(Net::MessageIn &msg) @@ -104,13 +103,13 @@ void TradeHandler::handleMessage(Net::MessageIn &msg) { case GPMSG_TRADE_REQUEST: { - Being *being = beingManager->findBeing(msg.readInt16()); + Being *being = actorSpriteManager->findBeing(msg.readInt16()); if (!being || !mAcceptTradeRequests) { respond(false); break; } - player_node->setTrading(true); + PlayerInfo::setTrading(true); tradePartnerName = being->getName(); tradePartnerID = being->getId(); ConfirmDialog *dlg = new ConfirmDialog(_("Request for Trade"), @@ -144,19 +143,19 @@ void TradeHandler::handleMessage(Net::MessageIn &msg) case GPMSG_TRADE_AGREED: tradeWindow->receivedOk(false); break; - + case GPMSG_TRADE_CANCEL: - localChatTab->chatLog(_("Trade canceled."), BY_SERVER); + SERVER_NOTICE(_("Trade canceled.")) tradeWindow->setVisible(false); tradeWindow->reset(); - player_node->setTrading(false); + PlayerInfo::setTrading(false); break; case GPMSG_TRADE_COMPLETE: - localChatTab->chatLog(_("Trade completed."), BY_SERVER); + SERVER_NOTICE(_("Trade completed.")) tradeWindow->setVisible(false); tradeWindow->reset(); - player_node->setTrading(false); + PlayerInfo::setTrading(false); break; } } @@ -177,7 +176,7 @@ void TradeHandler::respond(bool accept) gameServerConnection->send(msg); if (!accept) - player_node->setTrading(false); + PlayerInfo::setTrading(false); } void TradeHandler::addItem(Item *item, int amount) diff --git a/src/net/net.cpp b/src/net/net.cpp index 25dcd981..09f245b0 100644 --- a/src/net/net.cpp +++ b/src/net/net.cpp @@ -133,17 +133,12 @@ void connectToServer(ServerInfo &server) { // TODO: Query the server about itself and choose the netcode based on // that - -#ifndef MANASERV_SUPPORT - server.type = ServerInfo::TMWATHENA; -#else if (server.port == 6901) server.type = ServerInfo::TMWATHENA; else if (server.port == 9601) server.type = ServerInfo::MANASERV; else logger->error(_("Unknown Server Type! Exiting.")); -#endif } if (networkType == server.type && getGeneralHandler() != NULL) diff --git a/src/net/npchandler.h b/src/net/npchandler.h index bba8dc31..35535c61 100644 --- a/src/net/npchandler.h +++ b/src/net/npchandler.h @@ -29,13 +29,27 @@ namespace Net { class NpcHandler { public: + virtual ~NpcHandler() {} + + virtual void startShopping(int beingId) = 0; + + virtual void buy(int beingId) = 0; + + virtual void sell(int beingId) = 0; + + virtual void buyItem(int beingId, int itemId, int amount) = 0; + + virtual void sellItem(int beingId, int itemId, int amount) = 0; + + virtual void endShopping(int beingId) = 0; + virtual void talk(int npcId) = 0; virtual void nextDialog(int npcId) = 0; virtual void closeDialog(int npcId) = 0; - virtual void listInput(int npcId, int value) = 0; + virtual void menuSelect(int npcId, int choice) = 0; virtual void integerInput(int npcId, int value) = 0; @@ -44,19 +58,6 @@ class NpcHandler virtual void sendLetter(int npcId, const std::string &recipient, const std::string &text) = 0; - virtual void startShopping(int beingId) = 0; - - virtual void buy(int beingId) = 0; - - virtual void sell(int beingId) = 0; - - virtual void buyItem(int beingId, int itemId, int amount) = 0; - - virtual void sellItem(int beingId, int itemId, int amount) = 0; - - virtual void endShopping(int beingId) = 0; - - virtual ~NpcHandler() {} }; } // namespace Net diff --git a/src/net/partyhandler.h b/src/net/partyhandler.h index dd1103fc..7ca13546 100644 --- a/src/net/partyhandler.h +++ b/src/net/partyhandler.h @@ -24,7 +24,7 @@ #include <string> -class Player; +class Being; enum PartyShare { PARTY_SHARE_UNKNOWN = -1, @@ -38,11 +38,13 @@ namespace Net { class PartyHandler { public: + virtual ~PartyHandler() {} + virtual void create(const std::string &name = "") = 0; virtual void join(int partyId) = 0; - virtual void invite(Player *player) = 0; + virtual void invite(Being *player) = 0; virtual void invite(const std::string &name) = 0; @@ -50,7 +52,7 @@ class PartyHandler virtual void leave() = 0; - virtual void kick(Player *player) = 0; + virtual void kick(Being *player) = 0; virtual void kick(const std::string &name) = 0; @@ -69,8 +71,6 @@ class PartyHandler // virtual void options() = 0; // virtual void message() = 0; - - virtual ~PartyHandler() {} }; } // namespace Net diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h index 399afb5e..d7676a92 100644 --- a/src/net/playerhandler.h +++ b/src/net/playerhandler.h @@ -24,13 +24,14 @@ #include "being.h" #include "flooritem.h" -#include "localplayer.h" namespace Net { class PlayerHandler { public: + virtual ~PlayerHandler() {} + virtual void attack(int id) = 0; virtual void emote(int emoteId) = 0; @@ -62,8 +63,6 @@ class PlayerHandler virtual int getJobLocation() = 0; virtual Vector getDefaultWalkSpeed() = 0; - - virtual ~PlayerHandler() {} }; } // namespace Net diff --git a/src/net/specialhandler.h b/src/net/specialhandler.h index 21e3a4b7..89fcdf7d 100644 --- a/src/net/specialhandler.h +++ b/src/net/specialhandler.h @@ -28,6 +28,8 @@ namespace Net { class SpecialHandler { public: + virtual ~SpecialHandler () {} + virtual void use(int id) = 0; virtual void use(int id, int level, int beingId) = 0; @@ -35,8 +37,6 @@ class SpecialHandler virtual void use(int id, int level, int x, int y) = 0; virtual void use(int id, const std::string &map) = 0; - - virtual ~SpecialHandler () {} }; } diff --git a/src/net/tmwa/adminhandler.cpp b/src/net/tmwa/adminhandler.cpp index c75ec217..2795df8a 100644 --- a/src/net/tmwa/adminhandler.cpp +++ b/src/net/tmwa/adminhandler.cpp @@ -21,14 +21,12 @@ #include "net/tmwa/adminhandler.h" +#include "actorspritemanager.h" #include "being.h" -#include "beingmanager.h" +#include "event.h" #include "game.h" -#include "player.h" #include "playerrelations.h" -#include "gui/widgets/chattab.h" - #include "net/chathandler.h" #include "net/net.h" @@ -45,7 +43,8 @@ namespace TmwAthena { AdminHandler::AdminHandler() { - static const Uint16 _messages[] = { + static const Uint16 _messages[] = + { SMSG_ADMIN_KICK_ACK, SMSG_ADMIN_IP, 0 @@ -62,14 +61,14 @@ void AdminHandler::handleMessage(Net::MessageIn &msg) case SMSG_ADMIN_KICK_ACK: id = msg.readInt32(); if (id == 0) - localChatTab->chatLog(_("Kick failed!"), BY_SERVER); + SERVER_NOTICE(_("Kick failed!")) else - localChatTab->chatLog(_("Kick succeeded!"), BY_SERVER); + SERVER_NOTICE(_("Kick succeeded!")) break; case SMSG_ADMIN_IP: id = msg.readInt32(); int ip = msg.readInt32(); - Player *player = (Player *)beingManager->findBeing(id); + Being *player = actorSpriteManager->findBeing(id); player->setIp(ip); player->updateName(); break; diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 2fe962c7..61491692 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -21,31 +21,30 @@ #include "net/tmwa/beinghandler.h" +#include "actorspritemanager.h" #include "being.h" -#include "beingmanager.h" #include "client.h" #include "effectmanager.h" #include "guild.h" #include "localplayer.h" #include "log.h" -#include "npc.h" #include "party.h" #include "playerrelations.h" #include "net/tmwa/protocol.h" #include "resources/colordb.h" +#include "resources/emotedb.h" #include <iostream> namespace TmwAthena { -const int EMOTION_TIME = 150; /**< Duration of emotion icon */ - BeingHandler::BeingHandler(bool enableSync): mSync(enableSync) { - static const Uint16 _messages[] = { + static const Uint16 _messages[] = + { SMSG_BEING_VISIBLE, SMSG_BEING_MOVE, SMSG_BEING_SPAWN, @@ -75,19 +74,19 @@ BeingHandler::BeingHandler(bool enableSync): Being *createBeing(int id, short job) { - Being::Type type = Being::UNKNOWN; + ActorSprite::Type type = ActorSprite::UNKNOWN; if (job <= 25 || (job >= 4001 && job <= 4049)) - type = Being::PLAYER; + type = ActorSprite::PLAYER; else if (job >= 46 && job <= 1000) - type = Being::NPC; + type = ActorSprite::NPC; else if (job > 1000 && job <= 2000) - type = Being::MONSTER; + type = ActorSprite::MONSTER; else if (job == 45) return NULL; // Skip portals - Being *being = beingManager->createBeing(id, type, job); + Being *being = actorSpriteManager->createBeing(id, type, job); - if (type == Being::PLAYER || type == Being::NPC) + if (type == ActorSprite::PLAYER || type == ActorSprite::NPC) { MessageOut outMsg(0x0094); outMsg.writeInt32(id);//readLong(2)); @@ -98,7 +97,7 @@ Being *createBeing(int id, short job) void BeingHandler::handleMessage(Net::MessageIn &msg) { - if (!beingManager) + if (!actorSpriteManager) return; int id; @@ -113,7 +112,6 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) int type, guild; Uint16 status; Being *srcBeing, *dstBeing; - Player *player = 0; int hairStyle, hairColor, flag; switch (msg.getId()) @@ -128,7 +126,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) statusEffects |= ((Uint32)msg.readInt16()) << 16; // option job = msg.readInt16(); // class - dstBeing = beingManager->findBeing(id); + dstBeing = actorSpriteManager->findBeing(id); if (!dstBeing) { @@ -145,14 +143,10 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) break; } - if (dstBeing->getType() == Being::PLAYER) - player = static_cast<Player*>(dstBeing); - - if (msg.getId() == 0x0078) + if (msg.getId() == SMSG_BEING_VISIBLE) { dstBeing->clearPath(); - dstBeing->setFrame(0); - dstBeing->setWalkTime(tick_time); + dstBeing->setActionTime(tick_time); dstBeing->setAction(Being::STAND); } @@ -178,16 +172,13 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) shoes = msg.readInt16(); // clothes color - "abused" as shoes gloves = msg.readInt16(); // head dir - "abused" as gloves guild = msg.readInt32(); // guild - if (player) + if (guild == 0) { - if (guild == 0) - { - player->clearGuilds(); - } - else - { - player->addGuild(Guild::getGuild(guild)); - } + dstBeing->clearGuilds(); + } + else + { + dstBeing->addGuild(Guild::getGuild(guild)); } msg.readInt16(); // guild emblem msg.readInt16(); // manner @@ -195,19 +186,19 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) msg.readInt8(); // karma gender = msg.readInt8(); - if (player) + if (dstBeing->getType() == ActorSprite::PLAYER) { - player->setGender((gender == 0) - ? GENDER_FEMALE : GENDER_MALE); + dstBeing->setGender((gender == 0) + ? GENDER_FEMALE : GENDER_MALE); // Set these after the gender, as the sprites may be gender-specific - player->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(hairColor)); - player->setSprite(SPRITE_BOTTOMCLOTHES, headBottom); - player->setSprite(SPRITE_TOPCLOTHES, headMid); - player->setSprite(SPRITE_HAT, headTop); - player->setSprite(SPRITE_SHOE, shoes); - player->setSprite(SPRITE_GLOVES, gloves); - player->setSprite(SPRITE_WEAPON, weapon, "", true); - player->setSprite(SPRITE_SHIELD, shield); + dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(hairColor)); + dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom); + dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid); + dstBeing->setSprite(SPRITE_HAT, headTop); + dstBeing->setSprite(SPRITE_SHOE, shoes); + dstBeing->setSprite(SPRITE_GLOVES, gloves); + dstBeing->setSprite(SPRITE_WEAPON, weapon, "", true); + dstBeing->setSprite(SPRITE_SHIELD, shield); } if (msg.getId() == SMSG_BEING_MOVE) @@ -249,11 +240,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) * later versions of eAthena for both mobs and * players */ - dstBeing = beingManager->findBeing(msg.readInt32()); - - Uint16 srcX, srcY, dstX, dstY; - msg.readCoordinatePair(srcX, srcY, dstX, dstY); - msg.readInt32(); // Server tick + dstBeing = actorSpriteManager->findBeing(msg.readInt32()); /* * This packet doesn't have enough info to actually @@ -261,21 +248,23 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) * we'll just pretend the packet didn't happen */ - if (dstBeing) - { - dstBeing->setAction(Being::STAND); - dstBeing->setTileCoords(srcX, srcY); - dstBeing->setDestination(dstX, dstY); - } + if (!dstBeing) + break; + + Uint16 srcX, srcY, dstX, dstY; + msg.readCoordinatePair(srcX, srcY, dstX, dstY); + msg.readInt32(); // Server tick + + dstBeing->setAction(Being::STAND); + dstBeing->setTileCoords(srcX, srcY); + dstBeing->setDestination(dstX, dstY); break; case SMSG_BEING_REMOVE: // A being should be removed or has died id = msg.readInt32(); - - dstBeing = beingManager->findBeing(id); - + dstBeing = actorSpriteManager->findBeing(id); if (!dstBeing) break; @@ -286,16 +275,14 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) if (msg.readInt8() == 1) dstBeing->setAction(Being::DEAD); else - beingManager->destroyBeing(dstBeing); + actorSpriteManager->destroy(dstBeing); break; case SMSG_BEING_RESURRECT: // A being changed mortality status id = msg.readInt32(); - - dstBeing = beingManager->findBeing(id); - + dstBeing = actorSpriteManager->findBeing(id); if (!dstBeing) break; @@ -310,8 +297,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) case SMSG_SKILL_DAMAGE: msg.readInt16(); // Skill Id - srcBeing = beingManager->findBeing(msg.readInt32()); - dstBeing = beingManager->findBeing(msg.readInt32()); + srcBeing = actorSpriteManager->findBeing(msg.readInt32()); + dstBeing = actorSpriteManager->findBeing(msg.readInt32()); msg.readInt32(); // Server tick msg.readInt32(); // src speed msg.readInt32(); // dst speed @@ -326,8 +313,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) break; case SMSG_BEING_ACTION: - srcBeing = beingManager->findBeing(msg.readInt32()); - dstBeing = beingManager->findBeing(msg.readInt32()); + srcBeing = actorSpriteManager->findBeing(msg.readInt32()); + dstBeing = actorSpriteManager->findBeing(msg.readInt32()); msg.readInt32(); // server tick msg.readInt32(); // src speed msg.readInt32(); // dst speed @@ -354,7 +341,6 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) case 0x02: // Sit if (srcBeing) { - srcBeing->setFrame(0); srcBeing->setAction(Being::SIT); } break; @@ -362,37 +348,36 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) case 0x03: // Stand up if (srcBeing) { - srcBeing->setFrame(0); srcBeing->setAction(Being::STAND); } break; } break; - case SMSG_BEING_SELFEFFECT: { + case SMSG_BEING_SELFEFFECT: + { id = (Uint32)msg.readInt32(); - if (!beingManager->findBeing(id)) + Being* being = actorSpriteManager->findBeing(id); + if (!being) break; int effectType = msg.readInt32(); - Being* being = beingManager->findBeing(id); effectManager->trigger(effectType, being); - break; } case SMSG_BEING_EMOTION: - if (!(dstBeing = beingManager->findBeing(msg.readInt32()))) + if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32()))) { break; } if (player_relations.hasPermission(dstBeing, PlayerRelation::EMOTE)) { - // only set emote if one doesnt already exist - if (!dstBeing->getEmotion()) - dstBeing->setEmote(msg.readInt8(), EMOTION_TIME); + const int fx = EmoteDB::get(msg.readInt8())->effect; + //TODO: figure out why the -1 is needed + effectManager->trigger(fx - 1, dstBeing); } break; @@ -412,14 +397,11 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) * 16 bit value will be 0. */ - if (!(dstBeing = beingManager->findBeing(msg.readInt32()))) + if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32()))) { break; } - if (dstBeing->getType() == Being::PLAYER) - player = static_cast<Player*>(dstBeing); - int type = msg.readInt8(); int id = 0; int id2 = 0; @@ -437,41 +419,41 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) switch (type) { case 1: // eAthena LOOK_HAIR - player->setSpriteID(SPRITE_HAIR, id *-1); + dstBeing->setSpriteID(SPRITE_HAIR, id *-1); break; case 2: // Weapon ID in id, Shield ID in id2 - player->setSprite(SPRITE_WEAPON, id, "", true); - player->setSprite(SPRITE_SHIELD, id2); + dstBeing->setSprite(SPRITE_WEAPON, id, "", true); + dstBeing->setSprite(SPRITE_SHIELD, id2); break; case 3: // Change lower headgear for eAthena, pants for us - player->setSprite(SPRITE_BOTTOMCLOTHES, id); + dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, id); break; case 4: // Change upper headgear for eAthena, hat for us - player->setSprite(SPRITE_HAT, id); + dstBeing->setSprite(SPRITE_HAT, id); break; case 5: // Change middle headgear for eathena, armor for us - player->setSprite(SPRITE_TOPCLOTHES, id); + dstBeing->setSprite(SPRITE_TOPCLOTHES, id); break; case 6: // eAthena LOOK_HAIR_COLOR - player->setSpriteColor(SPRITE_HAIR, ColorDB::get(id)); + dstBeing->setSpriteColor(SPRITE_HAIR, ColorDB::get(id)); break; case 8: // eAthena LOOK_SHIELD - player->setSprite(SPRITE_SHIELD, id); + dstBeing->setSprite(SPRITE_SHIELD, id); break; case 9: // eAthena LOOK_SHOES - player->setSprite(SPRITE_SHOE, id); + dstBeing->setSprite(SPRITE_SHOE, id); break; case 10: // LOOK_GLOVES - player->setSprite(SPRITE_GLOVES, id); + dstBeing->setSprite(SPRITE_GLOVES, id); break; case 11: // LOOK_CAPE - player->setSprite(SPRITE_CAPE, id); + dstBeing->setSprite(SPRITE_CAPE, id); break; case 12: - player->setSprite(SPRITE_MISC1, id); + dstBeing->setSprite(SPRITE_MISC1, id); break; case 13: - player->setSprite(SPRITE_MISC2, id); + dstBeing->setSprite(SPRITE_MISC2, id); break; default: logger->log("SMSG_BEING_CHANGE_LOOKS: unsupported type: " @@ -482,13 +464,13 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) break; case SMSG_BEING_NAME_RESPONSE: - if ((dstBeing = beingManager->findBeing(msg.readInt32()))) + if ((dstBeing = actorSpriteManager->findBeing(msg.readInt32()))) { dstBeing->setName(msg.readString(24)); } break; case SMSG_PLAYER_GUILD_PARTY_INFO: - if ((dstBeing = beingManager->findBeing(msg.readInt32()))) + if ((dstBeing = actorSpriteManager->findBeing(msg.readInt32()))) { dstBeing->setPartyName(msg.readString(24)); dstBeing->setGuildName(msg.readString(24)); @@ -497,7 +479,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) } break; case SMSG_BEING_CHANGE_DIRECTION: - if (!(dstBeing = beingManager->findBeing(msg.readInt32()))) + if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32()))) { break; } @@ -520,7 +502,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) << 16; // status.options; Aethyra uses this as misc2 job = msg.readInt16(); - dstBeing = beingManager->findBeing(id); + dstBeing = actorSpriteManager->findBeing(id); if (!dstBeing) { @@ -530,13 +512,10 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) break; } - if (dstBeing->getType() == Being::PLAYER) - player = static_cast<Player*>(dstBeing); - if (Party *party = player_node->getParty()){ if (party->isMember(id)) { - player->setParty(party); + dstBeing->setParty(party); } } @@ -562,21 +541,21 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) msg.readInt16(); // manner dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3 msg.readInt8(); // karma - player->setGender((msg.readInt8() == 0) + dstBeing->setGender((msg.readInt8() == 0) ? GENDER_FEMALE : GENDER_MALE); // Set these after the gender, as the sprites may be gender-specific - player->setSprite(SPRITE_WEAPON, weapon, "", true); - player->setSprite(SPRITE_SHIELD, shield); - //player->setSprite(SPRITE_SHOE, shoes); - player->setSprite(SPRITE_BOTTOMCLOTHES, headBottom); - player->setSprite(SPRITE_TOPCLOTHES, headMid); - player->setSprite(SPRITE_HAT, headTop); - //player->setSprite(SPRITE_GLOVES, gloves); - //player->setSprite(SPRITE_CAPE, cape); - //player->setSprite(SPRITE_MISC1, misc1); - //player->setSprite(SPRITE_MISC2, misc2); - player->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(hairColor)); + dstBeing->setSprite(SPRITE_WEAPON, weapon, "", true); + dstBeing->setSprite(SPRITE_SHIELD, shield); + //dstBeing->setSprite(SPRITE_SHOE, shoes); + dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom); + dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid); + dstBeing->setSprite(SPRITE_HAT, headTop); + //dstBeing->setSprite(SPRITE_GLOVES, gloves); + //dstBeing->setSprite(SPRITE_CAPE, cape); + //dstBeing->setSprite(SPRITE_MISC1, misc1); + //dstBeing->setSprite(SPRITE_MISC2, misc2); + dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(hairColor)); if (msg.getId() == SMSG_PLAYER_MOVE) { @@ -596,7 +575,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) gmstatus = msg.readInt16(); if (gmstatus & 0x80) - player->setGM(true); + dstBeing->setGM(true); if (msg.getId() == SMSG_PLAYER_UPDATE_1) { @@ -619,8 +598,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) msg.readInt8(); // Lv msg.readInt8(); // unknown - dstBeing->setWalkTime(tick_time); - dstBeing->setFrame(0); + dstBeing->setActionTime(tick_time); + dstBeing->reset(); dstBeing->setStunMode(stunMode); dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff); @@ -643,18 +622,15 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) id = msg.readInt32(); if (mSync || id != player_node->getId()) { - dstBeing = beingManager->findBeing(id); + dstBeing = actorSpriteManager->findBeing(id); if (dstBeing) { Uint16 x, y; x = msg.readInt16(); y = msg.readInt16(); dstBeing->setTileCoords(x, y); - if (dstBeing->getCurrentAction() == Being::WALK) - { - dstBeing->setFrame(0); + if (dstBeing->getCurrentAction() == Being::MOVE) dstBeing->setAction(Being::STAND); - } } } break; @@ -671,18 +647,18 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) case SMSG_PLAYER_STATUS_CHANGE: // Change in players' flags id = msg.readInt32(); - dstBeing = beingManager->findBeing(id); + dstBeing = actorSpriteManager->findBeing(id); + if (!dstBeing) + break; + stunMode = msg.readInt16(); statusEffects = msg.readInt16(); statusEffects |= ((Uint32) msg.readInt16()) << 16; - msg.readInt8(); + msg.readInt8(); // Unused? - if (dstBeing) - { - dstBeing->setStunMode(stunMode); - dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff); - dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff); - } + dstBeing->setStunMode(stunMode); + dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff); + dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff); break; case SMSG_BEING_STATUS_CHANGE: @@ -691,7 +667,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) id = msg.readInt32(); flag = msg.readInt8(); // 0: stop, 1: start - dstBeing = beingManager->findBeing(id); + dstBeing = actorSpriteManager->findBeing(id); if (dstBeing) dstBeing->setStatusEffect(status, flag); break; diff --git a/src/net/tmwa/buysellhandler.cpp b/src/net/tmwa/buysellhandler.cpp index 209f034d..5368ba9d 100644 --- a/src/net/tmwa/buysellhandler.cpp +++ b/src/net/tmwa/buysellhandler.cpp @@ -21,18 +21,17 @@ #include "net/tmwa/buysellhandler.h" -#include "beingmanager.h" +#include "actorspritemanager.h" +#include "event.h" #include "inventory.h" #include "item.h" #include "localplayer.h" -#include "npc.h" +#include "playerinfo.h" #include "gui/buy.h" #include "gui/buysell.h" #include "gui/sell.h" -#include "gui/widgets/chattab.h" - #include "net/messagein.h" #include "net/tmwa/protocol.h" @@ -62,7 +61,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) switch (msg.getId()) { case SMSG_NPC_BUY_SELL_CHOICE: - if (!BuySellDialog::isActive()) + if (PlayerInfo::getBuySellState() != BUYSELL_CHOOSING) { mNpcId = msg.readInt32(); new BuySellDialog(mNpcId); @@ -73,7 +72,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) msg.readInt16(); // length n_items = (msg.getLength() - 4) / 11; mBuyDialog = new BuyDialog(mNpcId); - mBuyDialog->setMoney(player_node->getMoney()); + mBuyDialog->setMoney(PlayerInfo::getAttribute(MONEY)); for (int k = 0; k < n_items; k++) { @@ -91,7 +90,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) if (n_items > 0) { SellDialog *dialog = new SellDialog(mNpcId); - dialog->setMoney(player_node->getMoney()); + dialog->setMoney(PlayerInfo::getAttribute(MONEY)); for (int k = 0; k < n_items; k++) { @@ -99,7 +98,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) int value = msg.readInt32(); msg.readInt32(); // OCvalue - Item *item = player_node->getInventory()->getItem(index); + Item *item = PlayerInfo::getInventory()->getItem(index); if (item && !(item->isEquipped())) dialog->addItem(item, value); @@ -107,29 +106,29 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg) } else { - localChatTab->chatLog(_("Nothing to sell."), BY_SERVER); + SERVER_NOTICE(_("Nothing to sell.")) } break; case SMSG_NPC_BUY_RESPONSE: if (msg.readInt8() == 0) { - localChatTab->chatLog(_("Thanks for buying."), BY_SERVER); + SERVER_NOTICE(_("Thanks for buying.")) } else { // Reset player money since buy dialog already assumed purchase // would go fine - mBuyDialog->setMoney(player_node->getMoney()); - localChatTab->chatLog(_("Unable to buy."), BY_SERVER); + mBuyDialog->setMoney(PlayerInfo::getAttribute(MONEY)); + SERVER_NOTICE(_("Unable to buy.")) } break; case SMSG_NPC_SELL_RESPONSE: if (msg.readInt8() == 0) - localChatTab->chatLog(_("Thanks for selling."), BY_SERVER); + SERVER_NOTICE(_("Thanks for selling.")) else - localChatTab->chatLog(_("Unable to sell."), BY_SERVER); + SERVER_NOTICE(_("Unable to sell.")) break; } diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index dc9b3108..1063ee39 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -86,12 +86,10 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg) for (int i = 0; i < count; ++i) { Net::Character *character = new Net::Character; - int slot; - character->dummy = readPlayerData(msg, &slot); - character->slot = slot; + readPlayerData(msg, character); mCharacters.push_back(character); logger->log("CharServer: Player: %s (%d)", - character->dummy->getName().c_str(), slot); + character->dummy->getName().c_str(), character->slot); } Client::setState(STATE_CHAR_SELECT); @@ -118,9 +116,7 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg) case SMSG_CHAR_CREATE_SUCCEEDED: { Net::Character *character = new Net::Character; - int slot; - character->dummy = readPlayerData(msg, &slot); - character->slot = slot; + readPlayerData(msg, character); mCharacters.push_back(character); updateCharSelectDialog(); @@ -165,6 +161,8 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg) // Prevent the selected local player from being deleted player_node = mSelectedCharacter->dummy; + PlayerInfo::setBackend(mSelectedCharacter->data); + mSelectedCharacter->dummy = 0; delete_all(mCharacters); @@ -194,7 +192,7 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg) } } -LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int *slot) +void CharServerHandler::readPlayerData(Net::MessageIn &msg, Net::Character *character) { const Token &token = static_cast<LoginHandler*>(Net::getLoginHandler())->getToken(); @@ -202,30 +200,37 @@ LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int *slot) LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0); tempPlayer->setGender(token.sex); - tempPlayer->setExp(msg.readInt32()); - tempPlayer->setMoney(msg.readInt32()); - tempPlayer->setExperience(JOB, msg.readInt32(), 1); + character->data.mAttributes[EXP] = msg.readInt32(); + character->data.mAttributes[MONEY] = msg.readInt32(); + character->data.mStats[JOB].exp = msg.readInt32(); + int temp = msg.readInt32(); - tempPlayer->setAttributeBase(JOB, temp, false); - tempPlayer->setAttributeEffective(JOB, temp); + character->data.mStats[JOB].base = temp; + character->data.mStats[JOB].mod = temp; + tempPlayer->setSprite(SPRITE_SHOE, msg.readInt16()); tempPlayer->setSprite(SPRITE_GLOVES, msg.readInt16()); tempPlayer->setSprite(SPRITE_CAPE, msg.readInt16()); tempPlayer->setSprite(SPRITE_MISC1, msg.readInt16()); + msg.readInt32(); // option msg.readInt32(); // karma msg.readInt32(); // manner msg.skip(2); // unknown - tempPlayer->setHp(msg.readInt16()); - tempPlayer->setMaxHp(msg.readInt16()); - tempPlayer->setMP(msg.readInt16()); - tempPlayer->setMaxMP(msg.readInt16()); + + character->data.mAttributes[HP] = msg.readInt16(); + character->data.mAttributes[MAX_HP] = msg.readInt16(); + character->data.mAttributes[MP] = msg.readInt16(); + character->data.mAttributes[MAX_MP] = msg.readInt16(); + msg.readInt16(); // speed tempPlayer->setSubtype(msg.readInt16()); // class (used for race) int hairStyle = msg.readInt16(); Uint16 weapon = msg.readInt16(); tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", true); - tempPlayer->setLevel(msg.readInt16()); + + character->data.mAttributes[LEVEL] = msg.readInt16(); + msg.readInt16(); // skill point tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, msg.readInt16()); // head bottom tempPlayer->setSprite(SPRITE_SHIELD, msg.readInt16()); @@ -234,12 +239,14 @@ LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int *slot) tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(msg.readInt16())); tempPlayer->setSprite(SPRITE_MISC2, msg.readInt16()); tempPlayer->setName(msg.readString(24)); + + character->dummy = tempPlayer; + for (int i = 0; i < 6; i++) - tempPlayer->setAttributeBase(i + STR, msg.readInt8(), false); - *slot = msg.readInt8(); // character slot - msg.readInt8(); // unknown + character->data.mStats[i + STR].base = msg.readInt8(); - return tempPlayer; + character->slot = msg.readInt8(); // character slot + msg.readInt8(); // unknown } void CharServerHandler::setCharSelectDialog(CharSelectDialog *window) @@ -315,17 +322,17 @@ void CharServerHandler::switchCharacter() outMsg.writeInt8(1); } -int CharServerHandler::baseSprite() const +unsigned int CharServerHandler::baseSprite() const { return SPRITE_BASE; } -int CharServerHandler::hairSprite() const +unsigned int CharServerHandler::hairSprite() const { return SPRITE_HAIR; } -int CharServerHandler::maxSprite() const +unsigned int CharServerHandler::maxSprite() const { return SPRITE_VECTOREND; } diff --git a/src/net/tmwa/charserverhandler.h b/src/net/tmwa/charserverhandler.h index e80d22c4..2076cbae 100644 --- a/src/net/tmwa/charserverhandler.h +++ b/src/net/tmwa/charserverhandler.h @@ -63,16 +63,16 @@ class CharServerHandler : public MessageHandler, public Net::CharHandler void switchCharacter(); - int baseSprite() const; + unsigned int baseSprite() const; - int hairSprite() const; + unsigned int hairSprite() const; - int maxSprite() const; + unsigned int maxSprite() const; void connect(); private: - LocalPlayer *readPlayerData(Net::MessageIn &msg, int *slot); + void readPlayerData(Net::MessageIn &msg, Net::Character *character); }; } // namespace TmwAthena diff --git a/src/net/tmwa/chathandler.cpp b/src/net/tmwa/chathandler.cpp index 00d29662..33826762 100644 --- a/src/net/tmwa/chathandler.cpp +++ b/src/net/tmwa/chathandler.cpp @@ -21,14 +21,13 @@ #include "net/tmwa/chathandler.h" +#include "actorspritemanager.h" #include "being.h" -#include "beingmanager.h" +#include "event.h" #include "game.h" #include "localplayer.h" #include "playerrelations.h" -#include "gui/widgets/chattab.h" - #include "net/messagein.h" #include "net/messageout.h" @@ -60,8 +59,6 @@ ChatHandler::ChatHandler() void ChatHandler::handleMessage(Net::MessageIn &msg) { - if (!localChatTab) return; - Being *being; std::string chatMsg; std::string nick; @@ -70,19 +67,36 @@ void ChatHandler::handleMessage(Net::MessageIn &msg) switch (msg.getId()) { case SMSG_WHISPER_RESPONSE: + if (mSentWhispers.empty()) + nick = "user"; + else + { + nick = mSentWhispers.front(); + mSentWhispers.pop(); + } + switch (msg.readInt8()) { case 0x00: - // comment out since we'll local echo in chat.cpp instead, then only report failures - //localChatTab->chatLog("Whisper sent", BY_SERVER); + // Success (don't need to report) break; case 0x01: - localChatTab->chatLog(_("Whisper could not be sent, user " - "is offline."), BY_SERVER); + { + Mana::Event event(EVENT_WHISPERERROR); + event.setString("nick", nick); + event.setString("error", strprintf(_("Whisper could " + "not be sent, %s is offline."), nick.c_str())); + event.trigger(CHANNEL_CHAT); + } break; case 0x02: - localChatTab->chatLog(_("Whisper could not be sent, " - "ignored by user."), BY_SERVER); + { + Mana::Event event(EVENT_WHISPERERROR); + event.setString("nick", nick); + event.setString("error", strprintf(_("Whisper could " + "not be sent, ignored by %s."), nick.c_str())); + event.Event::trigger(CHANNEL_CHAT); + } break; } break; @@ -100,11 +114,16 @@ void ChatHandler::handleMessage(Net::MessageIn &msg) if (nick != "Server") { if (player_relations.hasPermission(nick, PlayerRelation::WHISPER)) - chatWindow->whisper(nick, chatMsg); + { + Mana::Event event(EVENT_WHISPER); + event.setString("nick", nick); + event.setString("message", chatMsg); + event.trigger(CHANNEL_CHAT); + } } else { - localChatTab->chatLog(chatMsg, BY_SERVER); + SERVER_NOTICE(chatMsg) } break; @@ -113,7 +132,8 @@ void ChatHandler::handleMessage(Net::MessageIn &msg) case SMSG_BEING_CHAT: { chatMsgLength = msg.readInt16() - 8; - being = beingManager->findBeing(msg.readInt32()); + int beingId = msg.readInt32(); + being = actorSpriteManager->findBeing(beingId); if (!being || chatMsgLength <= 0) break; @@ -135,23 +155,33 @@ void ChatHandler::handleMessage(Net::MessageIn &msg) chatMsg.erase(0, pos + 3); } - trim(chatMsg); + int perms; - // We use getIgnorePlayer instead of ignoringPlayer here - // because ignorePlayer' side effects are triggered - // right below for Being::IGNORE_SPEECH_FLOAT. - if (player_relations.checkPermissionSilently(sender_name, - PlayerRelation::SPEECH_LOG) && chatWindow) + if (being->getType() == Being::PLAYER) { - localChatTab->chatLog(removeColors(sender_name) + " : " - + chatMsg, BY_OTHER); + perms = player_relations.checkPermissionSilently(sender_name, + PlayerRelation::SPEECH_LOG | PlayerRelation::SPEECH_FLOAT); } - - if (player_relations.hasPermission(sender_name, - PlayerRelation::SPEECH_FLOAT)) + else { - being->setSpeech(chatMsg, SPEECH_TIME); + perms = player_relations.getDefault() + & (PlayerRelation::SPEECH_LOG + | PlayerRelation::SPEECH_FLOAT); } + + trim(chatMsg); + + std::string reducedMessage = chatMsg; + chatMsg = removeColors(sender_name) + " : " + reducedMessage; + + Mana::Event event(EVENT_BEING); + event.setString("message", chatMsg); + event.setString("text", reducedMessage); + event.setString("nick", sender_name); + event.setInt("beingId", beingId); + event.setInt("permissions", perms); + event.trigger(CHANNEL_CHAT); + break; } @@ -164,22 +194,32 @@ void ChatHandler::handleMessage(Net::MessageIn &msg) break; chatMsg = msg.readString(chatMsgLength); - std::string::size_type pos = chatMsg.find(" : ", 0); if (msg.getId() == SMSG_PLAYER_CHAT) { - localChatTab->chatLog(chatMsg, BY_PLAYER); + std::string::size_type pos = chatMsg.find(" : ", 0); + std::string mes = chatMsg; if (pos != std::string::npos) chatMsg.erase(0, pos + 3); trim(chatMsg); - player_node->setSpeech(chatMsg, SPEECH_TIME); + Mana::Event event(EVENT_PLAYER); + event.setString("message", mes); + event.setString("text", chatMsg); + event.setString("nick", player_node->getName()); + event.setInt("beingId", player_node->getId()); + event.setInt("permissions", player_relations.getDefault() + & (PlayerRelation::SPEECH_LOG + | PlayerRelation::SPEECH_FLOAT)); + event.trigger(CHANNEL_CHAT); } else { - localChatTab->chatLog(chatMsg, BY_GM); + Mana::Event event(EVENT_ANNOUNCEMENT); + event.setString("message", chatMsg); + event.trigger(CHANNEL_CHAT); } break; } @@ -187,7 +227,7 @@ void ChatHandler::handleMessage(Net::MessageIn &msg) case SMSG_MVP: // Display MVP player msg.readInt32(); // id - localChatTab->chatLog(_("MVP player."), BY_SERVER); + SERVER_NOTICE(_("MVP player.")) break; } } @@ -216,47 +256,49 @@ void ChatHandler::privateMessage(const std::string &recipient, outMsg.writeInt16(text.length() + 28); outMsg.writeString(recipient, 24); outMsg.writeString(text, text.length()); + + mSentWhispers.push(recipient); } void ChatHandler::channelList() { - localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER); + SERVER_NOTICE(_("Channels are not supported!")) } void ChatHandler::enterChannel(const std::string &channel, const std::string &password) { - localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER); + SERVER_NOTICE(_("Channels are not supported!")) } void ChatHandler::quitChannel(int channelId) { - localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER); + SERVER_NOTICE(_("Channels are not supported!")) } void ChatHandler::sendToChannel(int channelId, const std::string &text) { - localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER); + SERVER_NOTICE(_("Channels are not supported!")) } void ChatHandler::userList(const std::string &channel) { - localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER); + SERVER_NOTICE(_("Channels are not supported!")) } void ChatHandler::setChannelTopic(int channelId, const std::string &text) { - localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER); + SERVER_NOTICE(_("Channels are not supported!")) } void ChatHandler::setUserMode(int channelId, const std::string &name, int mode) { - localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER); + SERVER_NOTICE(_("Channels are not supported!")) } void ChatHandler::kickUser(int channelId, const std::string &name) { - localChatTab->chatLog(_("Channels are not supported!"), BY_SERVER); + SERVER_NOTICE(_("Channels are not supported!")) } void ChatHandler::who() diff --git a/src/net/tmwa/chathandler.h b/src/net/tmwa/chathandler.h index 3e035f7e..6426a71e 100644 --- a/src/net/tmwa/chathandler.h +++ b/src/net/tmwa/chathandler.h @@ -27,6 +27,8 @@ #include "net/tmwa/messagehandler.h" +#include <queue> + namespace TmwAthena { class ChatHandler : public MessageHandler, public Net::ChatHandler @@ -61,6 +63,10 @@ class ChatHandler : public MessageHandler, public Net::ChatHandler void kickUser(int channelId, const std::string &name); void who(); + + private: + typedef std::queue<std::string> WhisperQueue; + WhisperQueue mSentWhispers; }; } // namespace TmwAthena diff --git a/src/net/tmwa/gamehandler.cpp b/src/net/tmwa/gamehandler.cpp index 435d5d30..63f5fcec 100644 --- a/src/net/tmwa/gamehandler.cpp +++ b/src/net/tmwa/gamehandler.cpp @@ -22,12 +22,11 @@ #include "net/tmwa/gamehandler.h" #include "client.h" +#include "event.h" #include "game.h" #include "localplayer.h" #include "log.h" -#include "gui/widgets/chattab.h" - #include "gui/okdialog.h" #include "net/messagein.h" @@ -58,6 +57,8 @@ GameHandler::GameHandler() }; handledMessages = _messages; gameHandler = this; + + listen(CHANNEL_GAME); } void GameHandler::handleMessage(Net::MessageIn &msg) @@ -84,8 +85,7 @@ void GameHandler::handleMessage(Net::MessageIn &msg) break; case SMSG_WHO_ANSWER: - localChatTab->chatLog(strprintf(_("Online users: %d"), - msg.readInt32()), BY_SERVER); + SERVER_NOTICE(strprintf(_("Online users: %d"), msg.readInt32())) break; case SMSG_CHAR_SWITCH_RESPONSE: @@ -105,6 +105,21 @@ void GameHandler::handleMessage(Net::MessageIn &msg) } } +void GameHandler::event(Channels channel, const Mana::Event &event) +{ + if (channel == CHANNEL_GAME) + { + if (event.getName() == EVENT_ENGINESINITALIZED) + { + Game::instance()->changeMap(mMap); + } + else if (event.getName() == EVENT_MAPLOADED) + { + MessageOut outMsg(CMSG_MAP_LOADED); + } + } +} + void GameHandler::connect() { mNetwork->connect(mapServer); @@ -142,16 +157,6 @@ void GameHandler::disconnect() mNetwork->disconnect(); } -void GameHandler::inGame() -{ - Game::instance()->changeMap(mMap); -} - -void GameHandler::mapLoaded(const std::string &mapName) -{ - MessageOut outMsg(CMSG_MAP_LOADED); -} - void GameHandler::who() { } diff --git a/src/net/tmwa/gamehandler.h b/src/net/tmwa/gamehandler.h index ca8d27e6..18317445 100644 --- a/src/net/tmwa/gamehandler.h +++ b/src/net/tmwa/gamehandler.h @@ -22,6 +22,8 @@ #ifndef NET_TA_MAPHANDLER_H #define NET_TA_MAPHANDLER_H +#include "listener.h" + #include "net/gamehandler.h" #include "net/net.h" #include "net/serverinfo.h" @@ -31,23 +33,22 @@ namespace TmwAthena { -class GameHandler : public MessageHandler, public Net::GameHandler +class GameHandler : public MessageHandler, public Net::GameHandler, + public Mana::Listener { public: GameHandler(); void handleMessage(Net::MessageIn &msg); + void event(Channels channel, const Mana::Event &event); + void connect(); bool isConnected(); void disconnect(); - void inGame(); - - void mapLoaded(const std::string &mapName); - void who(); void quit(); @@ -60,6 +61,9 @@ class GameHandler : public MessageHandler, public Net::GameHandler void setMap(const std::string map); + /** The tmwAthena protocol is making use of the MP status bar. */ + bool canUseMagicBar() const { return true; } + private: std::string mMap; int mCharID; /// < Saved for map-server switching diff --git a/src/net/tmwa/generalhandler.cpp b/src/net/tmwa/generalhandler.cpp index 14f48055..b4327d47 100644 --- a/src/net/tmwa/generalhandler.cpp +++ b/src/net/tmwa/generalhandler.cpp @@ -32,6 +32,10 @@ #include "gui/socialwindow.h" #include "gui/statuswindow.h" +#include "net/messagein.h" +#include "net/messageout.h" +#include "net/serverinfo.h" + #include "net/tmwa/adminhandler.h" #include "net/tmwa/beinghandler.h" #include "net/tmwa/buysellhandler.h" @@ -53,9 +57,6 @@ #include "net/tmwa/gui/guildtab.h" #include "net/tmwa/gui/partytab.h" -#include "net/messagein.h" -#include "net/messageout.h" - #include "resources/itemdb.h" #include "utils/gettext.h" @@ -75,7 +76,7 @@ extern Party *taParty; GeneralHandler::GeneralHandler(): mAdminHandler(new AdminHandler), - mBeingHandler(new BeingHandler(config.getValue("EnableSync", 0) == 1)), + mBeingHandler(new BeingHandler(config.getBoolValue("EnableSync"))), mBuySellHandler(new BuySellHandler), mCharHandler(new CharServerHandler), mChatHandler(new ChatHandler), @@ -105,7 +106,9 @@ GeneralHandler::GeneralHandler(): stats.push_back(ItemDB::Stat("dex", _("Dexterity %+d"))); stats.push_back(ItemDB::Stat("luck", _("Luck %+d"))); - ItemDB::setStatsList(stats); + itemDb->setStatsList(stats); + + listen(CHANNEL_GAME); } GeneralHandler::~GeneralHandler() @@ -209,47 +212,48 @@ void GeneralHandler::flushNetwork() } } -void GeneralHandler::guiWindowsLoaded() -{ - inventoryWindow->setSplitAllowed(false); - skillDialog->loadSkills("ea-skills.xml"); - - statusWindow->addAttribute(STR, _("Strength"), true, ""); - statusWindow->addAttribute(AGI, _("Agility"), true, ""); - statusWindow->addAttribute(VIT, _("Vitality"), true, ""); - statusWindow->addAttribute(INT, _("Intelligence"), true, ""); - statusWindow->addAttribute(DEX, _("Dexterity"), true, ""); - statusWindow->addAttribute(LUK, _("Luck"), true, ""); - - statusWindow->addAttribute(ATK, _("Attack"), false, ""); - statusWindow->addAttribute(DEF, _("Defense"), false, ""); - statusWindow->addAttribute(MATK, _("M.Attack"), false, ""); - statusWindow->addAttribute(MDEF, _("M.Defense"), false, ""); - statusWindow->addAttribute(HIT, _("% Accuracy"), false, ""); - statusWindow->addAttribute(FLEE, _("% Evade"), false, ""); - statusWindow->addAttribute(CRIT, _("% Critical"), false, ""); -} - -void GeneralHandler::guiWindowsUnloaded() -{ - socialWindow->removeTab(taGuild); - socialWindow->removeTab(taParty); - - delete guildTab; - guildTab = 0; - - delete partyTab; - partyTab = 0; -} - void GeneralHandler::clearHandlers() { mNetwork->clearHandlers(); } -void GeneralHandler::stateChanged(State oldState, State newState) +void GeneralHandler::event(Channels channel, + const Mana::Event &event) { - // + if (channel == CHANNEL_GAME) + { + if (event.getName() == EVENT_GUIWINDOWSLOADED) + { + inventoryWindow->setSplitAllowed(false); + skillDialog->loadSkills("ea-skills.xml"); + + statusWindow->addAttribute(STR, _("Strength"), true, ""); + statusWindow->addAttribute(AGI, _("Agility"), true, ""); + statusWindow->addAttribute(VIT, _("Vitality"), true, ""); + statusWindow->addAttribute(INT, _("Intelligence"), true, ""); + statusWindow->addAttribute(DEX, _("Dexterity"), true, ""); + statusWindow->addAttribute(LUK, _("Luck"), true, ""); + + statusWindow->addAttribute(ATK, _("Attack"), false, ""); + statusWindow->addAttribute(DEF, _("Defense"), false, ""); + statusWindow->addAttribute(MATK, _("M.Attack"), false, ""); + statusWindow->addAttribute(MDEF, _("M.Defense"), false, ""); + statusWindow->addAttribute(HIT, _("% Accuracy"), false, ""); + statusWindow->addAttribute(FLEE, _("% Evade"), false, ""); + statusWindow->addAttribute(CRIT, _("% Critical"), false, ""); + } + else if (event.getName() == EVENT_GUIWINDOWSUNLOADING) + { + socialWindow->removeTab(taGuild); + socialWindow->removeTab(taParty); + + delete guildTab; + guildTab = 0; + + delete partyTab; + partyTab = 0; + } + } } } // namespace TmwAthena diff --git a/src/net/tmwa/generalhandler.h b/src/net/tmwa/generalhandler.h index d680f215..722c3215 100644 --- a/src/net/tmwa/generalhandler.h +++ b/src/net/tmwa/generalhandler.h @@ -22,15 +22,17 @@ #ifndef NET_TMWA_GENERALHANDLER_H #define NET_TMWA_GENERALHANDLER_H +#include "listener.h" + #include "net/generalhandler.h" #include "net/net.h" -#include "net/serverinfo.h" #include "net/tmwa/messagehandler.h" namespace TmwAthena { -class GeneralHandler : public MessageHandler, public Net::GeneralHandler +class GeneralHandler : public MessageHandler, public Net::GeneralHandler, + public Mana::Listener { public: GeneralHandler(); @@ -47,13 +49,9 @@ class GeneralHandler : public MessageHandler, public Net::GeneralHandler void flushNetwork(); - void guiWindowsLoaded(); - - void guiWindowsUnloaded(); - void clearHandlers(); - void stateChanged(State oldState, State newState); + void event(Channels channel, const Mana::Event &event); protected: MessageHandlerPtr mAdminHandler; diff --git a/src/net/tmwa/gui/guildtab.cpp b/src/net/tmwa/gui/guildtab.cpp index 794ad5cc..ca922e55 100644 --- a/src/net/tmwa/gui/guildtab.cpp +++ b/src/net/tmwa/gui/guildtab.cpp @@ -21,17 +21,17 @@ #include "net/tmwa/gui/guildtab.h" +#include "chatlog.h" #include "commandhandler.h" #include "guild.h" #include "localplayer.h" -#include "gui/theme.h" - #include "net/net.h" #include "net/guildhandler.h" #include "resources/iteminfo.h" #include "resources/itemdb.h" +#include "resources/theme.h" #include "utils/dtor.h" #include "utils/gettext.h" @@ -114,4 +114,10 @@ void GuildTab::getAutoCompleteList(std::vector<std::string> &names) const taGuild->getNames(names); } +void GuildTab::saveToLogFile(std::string &msg) +{ + if (chatLogger) + chatLogger->log("#Guild", msg); +} + } // namespace TmwAthena diff --git a/src/net/tmwa/gui/guildtab.h b/src/net/tmwa/gui/guildtab.h index 031c81bf..12e15e16 100644 --- a/src/net/tmwa/gui/guildtab.h +++ b/src/net/tmwa/gui/guildtab.h @@ -39,6 +39,8 @@ class GuildTab : public ChatTab bool handleCommand(const std::string &type, const std::string &args); + void saveToLogFile(std::string &msg); + protected: void handleInput(const std::string &msg); diff --git a/src/net/tmwa/gui/partytab.cpp b/src/net/tmwa/gui/partytab.cpp index b541c498..6833831c 100644 --- a/src/net/tmwa/gui/partytab.cpp +++ b/src/net/tmwa/gui/partytab.cpp @@ -21,17 +21,17 @@ #include "net/tmwa/gui/partytab.h" +#include "chatlog.h" #include "commandhandler.h" #include "localplayer.h" #include "party.h" -#include "gui/theme.h" - #include "net/net.h" #include "net/partyhandler.h" #include "resources/iteminfo.h" #include "resources/itemdb.h" +#include "resources/theme.h" #include "utils/dtor.h" #include "utils/gettext.h" @@ -206,4 +206,10 @@ void PartyTab::getAutoCompleteList(std::vector<std::string> &names) const p->getNames(names); } +void PartyTab::saveToLogFile(std::string &msg) +{ + if (chatLogger) + chatLogger->log("#Party", msg); +} + } // namespace TmwAthena diff --git a/src/net/tmwa/gui/partytab.h b/src/net/tmwa/gui/partytab.h index 62027726..4c16ab46 100644 --- a/src/net/tmwa/gui/partytab.h +++ b/src/net/tmwa/gui/partytab.h @@ -39,6 +39,8 @@ class PartyTab : public ChatTab bool handleCommand(const std::string &type, const std::string &args); + void saveToLogFile(std::string &msg); + protected: void handleInput(const std::string &msg); diff --git a/src/net/tmwa/guildhandler.cpp b/src/net/tmwa/guildhandler.cpp index 93bc7807..1ff2f22a 100644 --- a/src/net/tmwa/guildhandler.cpp +++ b/src/net/tmwa/guildhandler.cpp @@ -21,6 +21,7 @@ #include "net/tmwa/guildhandler.h" #include "guild.h" +#include "event.h" #include "localplayer.h" #include "log.h" @@ -389,8 +390,7 @@ void GuildHandler::handleMessage(Net::MessageIn &msg) void GuildHandler::create(const std::string &name) { - localChatTab->chatLog(_("Guild creation isn't supported yet."), - BY_SERVER); + SERVER_NOTICE(_("Guild creation isn't supported yet.")) return; MessageOut msg(CMSG_GUILD_CREATE); @@ -403,10 +403,10 @@ void GuildHandler::invite(int guildId, const std::string &name) // TODO? } -void GuildHandler::invite(int guildId, Player *player) +void GuildHandler::invite(int guildId, Being *being) { MessageOut msg(CMSG_GUILD_INVITE); - msg.writeInt32(player->getId()); + msg.writeInt32(being->getId()); msg.writeInt32(0); // Unused msg.writeInt32(0); // Unused } diff --git a/src/net/tmwa/guildhandler.h b/src/net/tmwa/guildhandler.h index 39dbe486..8bde222f 100644 --- a/src/net/tmwa/guildhandler.h +++ b/src/net/tmwa/guildhandler.h @@ -40,7 +40,7 @@ class GuildHandler : public Net::GuildHandler, public MessageHandler void invite(int guildId, const std::string &name); - void invite(int guildId, Player *player); + void invite(int guildId, Being *being); void inviteResponse(int guildId, bool response); diff --git a/src/net/tmwa/inventoryhandler.cpp b/src/net/tmwa/inventoryhandler.cpp index 3809399d..3a0a93e3 100644 --- a/src/net/tmwa/inventoryhandler.cpp +++ b/src/net/tmwa/inventoryhandler.cpp @@ -23,6 +23,7 @@ #include "configuration.h" #include "equipment.h" +#include "event.h" #include "inventory.h" #include "item.h" #include "itemshortcut.h" @@ -108,6 +109,8 @@ InventoryHandler::InventoryHandler() mStorage = 0; mStorageWindow = 0; + + listen(CHANNEL_ITEM); } InventoryHandler::~InventoryHandler() @@ -126,8 +129,8 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) int number, flag; int index, amount, itemId, equipType, arrow; int identified, cards[4], itemType; - Inventory *inventory = player_node->getInventory(); - player_node->mEquipment->setBackend(&mEquips); + Inventory *inventory = PlayerInfo::getInventory(); + PlayerInfo::getEquipment()->setBackend(&mEquips); switch (msg.getId()) { @@ -170,17 +173,10 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) } if (msg.getId() == SMSG_PLAYER_INVENTORY) - { - // Trick because arrows are not considered equipment - bool isEquipment = arrow & 0x8000; - - inventory->setItem(index, itemId, amount, isEquipment); - } + inventory->setItem(index, itemId, amount); else - { mInventoryItems.push_back(InventoryItem(index, itemId, amount, false)); - } } break; @@ -224,11 +220,11 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) msg.readInt8(); // refine for (int i = 0; i < 4; i++) cards[i] = msg.readInt16(); - equipType = msg.readInt16(); + msg.readInt16(); // EquipType itemType = msg.readInt8(); { - const ItemInfo &itemInfo = ItemDB::get(itemId); + const ItemInfo &itemInfo = itemDb->get(itemId); if (msg.readInt8() > 0) { @@ -243,7 +239,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) if (item && item->getId() == itemId) amount += inventory->getItem(index)->getQuantity(); - inventory->setItem(index, itemId, amount, equipType != 0); + inventory->setItem(index, itemId, amount); } inventoryWindow->updateButtons(); @@ -286,7 +282,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) if (msg.readInt8() == 0) { - localChatTab->chatLog(_("Failed to use item."), BY_SERVER); + SERVER_NOTICE(_("Failed to use item.")) } else { @@ -318,8 +314,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) InventoryItems::iterator it = mInventoryItems.begin(); InventoryItems::iterator it_end = mInventoryItems.end(); for (; it != it_end; it++) - mStorage->setItem((*it).slot, (*it).id, (*it).quantity, - (*it).equip); + mStorage->setItem((*it).slot, (*it).id, (*it).quantity); mInventoryItems.clear(); if (!mStorageWindow) @@ -344,9 +339,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) item->increaseQuantity(amount); } else - { - mStorage->setItem(index, itemId, amount, false); - } + mStorage->setItem(index, itemId, amount); break; case SMSG_PLAYER_STORAGE_REMOVE: @@ -388,7 +381,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) msg.readInt8(); // refine msg.skip(8); // card - inventory->setItem(index, itemId, 1, true); + inventory->setItem(index, itemId, 1); if (equipType) { @@ -403,7 +396,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) flag = msg.readInt8(); if (!flag) - localChatTab->chatLog(_("Unable to equip."), BY_SERVER); + SERVER_NOTICE(_("Unable to equip.")) else mEquips.setEquipment(getSlot(equipType), index); break; @@ -414,7 +407,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) flag = msg.readInt8(); if (!flag) - localChatTab->chatLog(_("Unable to unequip."), BY_SERVER); + SERVER_NOTICE(_("Unable to unequip.")) else mEquips.setEquipment(getSlot(equipType), -1); break; @@ -437,41 +430,85 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) } } -void InventoryHandler::equipItem(const Item *item) +void InventoryHandler::event(Channels channel, + const Mana::Event &event) { - if (!item) - return; - - MessageOut outMsg(CMSG_PLAYER_EQUIP); - outMsg.writeInt16(item->getInvIndex() + INVENTORY_OFFSET); - outMsg.writeInt16(0); -} + if (channel == CHANNEL_ITEM) + { + if (event.getName() == EVENT_DOCLOSEINVENTORY) + { + // No need to worry about type + MessageOut outMsg(CMSG_CLOSE_STORAGE); + } + else + { + Item *item = event.getItem("item"); -void InventoryHandler::unequipItem(const Item *item) -{ - if (!item) - return; + if (!item) + return; - MessageOut outMsg(CMSG_PLAYER_UNEQUIP); - outMsg.writeInt16(item->getInvIndex() + INVENTORY_OFFSET); -} + int index = item->getInvIndex() + INVENTORY_OFFSET; -void InventoryHandler::useItem(const Item *item) -{ - if (!item) - return; + if (event.getName() == EVENT_DOEQUIP) + { + MessageOut outMsg(CMSG_PLAYER_EQUIP); + outMsg.writeInt16(index); + outMsg.writeInt16(0); + } + else if (event.getName() == EVENT_DOUNEQUIP) + { + MessageOut outMsg(CMSG_PLAYER_UNEQUIP); + outMsg.writeInt16(index); + } + else if (event.getName() == EVENT_DOUSE) + { + MessageOut outMsg(CMSG_PLAYER_INVENTORY_USE); + outMsg.writeInt16(index); + outMsg.writeInt32(item->getId()); // unused + } + else if (event.getName() == EVENT_DODROP) + { + int amount = event.getInt("amount", 1); - MessageOut outMsg(CMSG_PLAYER_INVENTORY_USE); - outMsg.writeInt16(item->getInvIndex() + INVENTORY_OFFSET); - outMsg.writeInt32(item->getId()); // unused -} + // TODO: Fix wrong coordinates of drops, serverside? + // (what's wrong here?) + MessageOut outMsg(CMSG_PLAYER_INVENTORY_DROP); + outMsg.writeInt16(index); + outMsg.writeInt16(amount); + } + else if (event.getName() == EVENT_DOMOVE) + { + int newIndex = event.getInt("newIndex", -1); -void InventoryHandler::dropItem(const Item *item, int amount) -{ - // TODO: Fix wrong coordinates of drops, serverside? (what's wrong here?) - MessageOut outMsg(CMSG_PLAYER_INVENTORY_DROP); - outMsg.writeInt16(item->getInvIndex() + INVENTORY_OFFSET); - outMsg.writeInt16(amount); + if (newIndex >= 0) + { + // Not implemented for tmwAthena (possible?) + } + else + { + int source = event.getInt("source"); + int destination = event.getInt("destination"); + int amount = event.getInt("amount", 1); + + if (source == Inventory::INVENTORY + && destination == Inventory::STORAGE) + { + MessageOut outMsg(CMSG_MOVE_TO_STORAGE); + outMsg.writeInt16(index); + outMsg.writeInt32(amount); + } + else if (source == Inventory::STORAGE + && destination == Inventory::INVENTORY) + { + MessageOut outMsg(CSMG_MOVE_FROM_STORAGE); + outMsg.writeInt16(index - INVENTORY_OFFSET + + STORAGE_OFFSET); + outMsg.writeInt32(amount); + } + } + } + } + } } bool InventoryHandler::canSplit(const Item *item) @@ -479,43 +516,6 @@ bool InventoryHandler::canSplit(const Item *item) return false; } -void InventoryHandler::splitItem(const Item *item, int amount) -{ - // Not implemented for eAthena (possible?) -} - -void InventoryHandler::moveItem(int oldIndex, int newIndex) -{ - // Not implemented for eAthena (possible?) -} - -void InventoryHandler::openStorage(int type) -{ - // Doesn't apply to eAthena, since opening happens through NPCs? -} - -void InventoryHandler::closeStorage(int type) -{ - MessageOut outMsg(CMSG_CLOSE_STORAGE); -} - -void InventoryHandler::moveItem(int source, int slot, int amount, - int destination) -{ - if (source == Inventory::INVENTORY && destination == Inventory::STORAGE) - { - MessageOut outMsg(CMSG_MOVE_TO_STORAGE); - outMsg.writeInt16(slot + INVENTORY_OFFSET); - outMsg.writeInt32(amount); - } - else if (source == Inventory::STORAGE && destination == Inventory::INVENTORY) - { - MessageOut outMsg(CSMG_MOVE_FROM_STORAGE); - outMsg.writeInt16(slot + STORAGE_OFFSET); - outMsg.writeInt32(amount); - } -} - size_t InventoryHandler::getSize(int type) const { switch (type) diff --git a/src/net/tmwa/inventoryhandler.h b/src/net/tmwa/inventoryhandler.h index 0c4ad092..dfbefaa8 100644 --- a/src/net/tmwa/inventoryhandler.h +++ b/src/net/tmwa/inventoryhandler.h @@ -24,7 +24,8 @@ #include "equipment.h" #include "inventory.h" -#include "localplayer.h" +#include "listener.h" +#include "playerinfo.h" #include "gui/inventorywindow.h" @@ -51,7 +52,7 @@ class EquipBackend : public Equipment::Backend { { return NULL; } - return player_node->getInventory()->getItem(invyIndex); + return PlayerInfo::getInventory()->getItem(invyIndex); } void clear() @@ -60,7 +61,7 @@ class EquipBackend : public Equipment::Backend { { if (mEquipment[i] != -1) { - Item* item = player_node->getInventory()->getItem(i); + Item* item = PlayerInfo::getInventory()->getItem(i); if (item) { item->setEquipped(false); @@ -74,7 +75,7 @@ class EquipBackend : public Equipment::Backend { void setEquipment(int index, int inventoryIndex) { // Unequip existing item - Item* item = player_node->getInventory()->getItem(mEquipment[index]); + Item* item = PlayerInfo::getInventory()->getItem(mEquipment[index]); if (item) { item->setEquipped(false); @@ -82,7 +83,7 @@ class EquipBackend : public Equipment::Backend { mEquipment[index] = inventoryIndex; - item = player_node->getInventory()->getItem(inventoryIndex); + item = PlayerInfo::getInventory()->getItem(inventoryIndex); if (item) { item->setEquipped(true); @@ -117,7 +118,8 @@ class InventoryItem typedef std::list<InventoryItem> InventoryItems; -class InventoryHandler : public MessageHandler, public Net::InventoryHandler +class InventoryHandler : public MessageHandler, public Net::InventoryHandler, + public Mana::Listener { public: enum { @@ -131,27 +133,10 @@ class InventoryHandler : public MessageHandler, public Net::InventoryHandler void handleMessage(Net::MessageIn &msg); - void equipItem(const Item *item); - - void unequipItem(const Item *item); - - void useItem(const Item *item); - - void dropItem(const Item *item, int amount); + void event(Channels channel, const Mana::Event &event); bool canSplit(const Item *item); - void splitItem(const Item *item, int amount); - - void moveItem(int oldIndex, int newIndex); - - void openStorage(int type); - - void closeStorage(int type); - - void moveItem(int source, int slot, int amount, - int destination); - size_t getSize(int type) const; private: diff --git a/src/net/tmwa/itemhandler.cpp b/src/net/tmwa/itemhandler.cpp index abc8103b..a8e98860 100644 --- a/src/net/tmwa/itemhandler.cpp +++ b/src/net/tmwa/itemhandler.cpp @@ -21,7 +21,7 @@ #include "net/tmwa/itemhandler.h" -#include "flooritemmanager.h" +#include "actorspritemanager.h" #include "net/messagein.h" @@ -54,13 +54,13 @@ void ItemHandler::handleMessage(Net::MessageIn &msg) int y = msg.readInt16(); msg.skip(4); // amount,subX,subY / subX,subY,amount - floorItemManager->create(id, itemId, x, y); + actorSpriteManager->createItem(id, itemId, x, y); } break; case SMSG_ITEM_REMOVE: - if (FloorItem *item = floorItemManager->findById(msg.readInt32())) - floorItemManager->destroy(item); + if (FloorItem *item = actorSpriteManager->findItem(msg.readInt32())) + actorSpriteManager->destroy(item); break; } } diff --git a/src/net/tmwa/npchandler.cpp b/src/net/tmwa/npchandler.cpp index 5888c679..337226a9 100644 --- a/src/net/tmwa/npchandler.cpp +++ b/src/net/tmwa/npchandler.cpp @@ -21,11 +21,9 @@ #include "net/tmwa/npchandler.h" -#include "beingmanager.h" +#include "actorspritemanager.h" +#include "event.h" #include "localplayer.h" -#include "npc.h" - -#include "gui/npcdialog.h" #include "net/messagein.h" #include "net/messageout.h" @@ -34,10 +32,27 @@ #include "net/tmwa/protocol.h" +#include "utils/stringutils.h" + #include <SDL_types.h> extern Net::NpcHandler *npcHandler; +static void parseMenu(Mana::Event *event, const std::string &options) +{ + std::istringstream iss(options); + + int count = 0; + std::string tmp; + while (getline(iss, tmp, ':')) + { + count++; + event->setString("choice" + toString(count), tmp); + } + + event->setInt("choiceCount", count); +} + namespace TmwAthena { NpcHandler::NpcHandler() @@ -63,82 +78,118 @@ void NpcHandler::handleMessage(Net::MessageIn &msg) } int npcId = msg.readInt32(); - NpcDialogs::iterator diag = mNpcDialogs.find(npcId); - NpcDialog *dialog = 0; - - if (diag == mNpcDialogs.end()) - { - // Empty dialogs don't help - if (msg.getId() == SMSG_NPC_CLOSE) - { - closeDialog(npcId); - return; - } - else if (msg.getId() == SMSG_NPC_NEXT) - { - nextDialog(npcId); - return; - } - else - { - dialog = new NpcDialog(npcId); - Wrapper wrap; - wrap.dialog = dialog; - mNpcDialogs[npcId] = wrap; - } - } - else - { - dialog = diag->second.dialog; - } + Mana::Event *event = 0; switch (msg.getId()) { - case SMSG_NPC_CHOICE: - dialog->choiceRequest(); - dialog->parseListItems(msg.readString(msg.getLength() - 8)); - break; - - case SMSG_NPC_MESSAGE: - dialog->addText(msg.readString(msg.getLength() - 8)); - break; - - case SMSG_NPC_CLOSE: - // Show the close button - dialog->showCloseButton(); - break; - - case SMSG_NPC_NEXT: - // Show the next button - dialog->showNextButton(); - break; - - case SMSG_NPC_INT_INPUT: - // Request for an integer - dialog->integerRequest(0); - break; - - case SMSG_NPC_STR_INPUT: - // Request for a string - dialog->textRequest(""); - break; + case SMSG_NPC_CHOICE: + event = new Mana::Event(EVENT_MENU); + event->setInt("id", npcId); + parseMenu(event, msg.readString(msg.getLength() - 8)); + event->trigger(CHANNEL_NPC); + break; + + case SMSG_NPC_MESSAGE: + event = new Mana::Event(EVENT_MESSAGE); + event->setInt("id", npcId); + event->setString("text", msg.readString(msg.getLength() - 8)); + event->trigger(CHANNEL_NPC); + break; + + case SMSG_NPC_CLOSE: + // Show the close button + event = new Mana::Event(EVENT_CLOSE); + event->setInt("id", npcId); + event->trigger(CHANNEL_NPC); + break; + + case SMSG_NPC_NEXT: + // Show the next button + event = new Mana::Event(EVENT_NEXT); + event->setInt("id", npcId); + event->trigger(CHANNEL_NPC); + break; + + case SMSG_NPC_INT_INPUT: + // Request for an integer + event = new Mana::Event(EVENT_INTEGERINPUT); + event->setInt("id", npcId); + event->trigger(CHANNEL_NPC); + break; + + case SMSG_NPC_STR_INPUT: + // Request for a string + event = new Mana::Event(EVENT_STRINGINPUT); + event->setInt("id", npcId); + event->trigger(CHANNEL_NPC); + break; } + delete event; + if (player_node->getCurrentAction() != Being::SIT) player_node->setAction(Being::STAND); } +void NpcHandler::startShopping(int beingId) +{ + // TODO +} + +void NpcHandler::buy(int beingId) +{ + MessageOut outMsg(CMSG_NPC_BUY_SELL_REQUEST); + outMsg.writeInt32(beingId); + outMsg.writeInt8(0); // Buy +} + +void NpcHandler::sell(int beingId) +{ + MessageOut outMsg(CMSG_NPC_BUY_SELL_REQUEST); + outMsg.writeInt32(beingId); + outMsg.writeInt8(1); // Sell +} + +void NpcHandler::buyItem(int beingId, int itemId, int amount) +{ + MessageOut outMsg(CMSG_NPC_BUY_REQUEST); + outMsg.writeInt16(8); // One item (length of packet) + outMsg.writeInt16(amount); + outMsg.writeInt16(itemId); +} + +void NpcHandler::sellItem(int beingId, int itemId, int amount) +{ + MessageOut outMsg(CMSG_NPC_SELL_REQUEST); + outMsg.writeInt16(8); // One item (length of packet) + outMsg.writeInt16(itemId + INVENTORY_OFFSET); + outMsg.writeInt16(amount); +} + +void NpcHandler::endShopping(int beingId) +{ + // TODO +} + void NpcHandler::talk(int npcId) { MessageOut outMsg(CMSG_NPC_TALK); outMsg.writeInt32(npcId); outMsg.writeInt8(0); // Unused + + Mana::Event event(EVENT_TALKSENT); + event.setInt("npcId", npcId); + event.trigger(CHANNEL_NPC); } void NpcHandler::nextDialog(int npcId) { MessageOut outMsg(CMSG_NPC_NEXT_REQUEST); outMsg.writeInt32(npcId); + + Mana::Event event(EVENT_NEXTSENT); + event.setInt("npcId", npcId); + event.trigger(CHANNEL_NPC); } void NpcHandler::closeDialog(int npcId) @@ -146,19 +197,21 @@ void NpcHandler::closeDialog(int npcId) MessageOut outMsg(CMSG_NPC_CLOSE); outMsg.writeInt32(npcId); - NpcDialogs::iterator it = mNpcDialogs.find(npcId); - if (it != mNpcDialogs.end()) - { - (*it).second.dialog->close(); - mNpcDialogs.erase(it); - } + Mana::Event event(EVENT_CLOSESENT); + event.setInt("npcId", npcId); + event.trigger(CHANNEL_NPC); } -void NpcHandler::listInput(int npcId, int value) +void NpcHandler::menuSelect(int npcId, int choice) { MessageOut outMsg(CMSG_NPC_LIST_CHOICE); outMsg.writeInt32(npcId); - outMsg.writeInt8(value); + outMsg.writeInt8(choice); + + Mana::Event event(EVENT_MENUSENT); + event.setInt("npcId", npcId); + event.setInt("choice", choice); + event.trigger(CHANNEL_NPC); } void NpcHandler::integerInput(int npcId, int value) @@ -166,6 +219,11 @@ void NpcHandler::integerInput(int npcId, int value) MessageOut outMsg(CMSG_NPC_INT_RESPONSE); outMsg.writeInt32(npcId); outMsg.writeInt32(value); + + Mana::Event event(EVENT_INTEGERINPUTSENT); + event.setInt("npcId", npcId); + event.setInt("value", value); + event.trigger(CHANNEL_NPC); } void NpcHandler::stringInput(int npcId, const std::string &value) @@ -175,57 +233,17 @@ void NpcHandler::stringInput(int npcId, const std::string &value) outMsg.writeInt32(npcId); outMsg.writeString(value, value.length()); outMsg.writeInt8(0); // Prevent problems with string reading -} -void NpcHandler::sendLetter(int npcId, const std::string &recipient, - const std::string &text) -{ - // TODO + Mana::Event event(EVENT_STRINGINPUTSENT); + event.setInt("npcId", npcId); + event.setString("value", value); + event.trigger(CHANNEL_NPC); } -void NpcHandler::startShopping(int beingId) -{ - // TODO -} - -void NpcHandler::buy(int beingId) -{ - MessageOut outMsg(CMSG_NPC_BUY_SELL_REQUEST); - outMsg.writeInt32(beingId); - outMsg.writeInt8(0); // Buy -} - -void NpcHandler::sell(int beingId) -{ - MessageOut outMsg(CMSG_NPC_BUY_SELL_REQUEST); - outMsg.writeInt32(beingId); - outMsg.writeInt8(1); // Sell -} - -void NpcHandler::buyItem(int beingId, int itemId, int amount) -{ - MessageOut outMsg(CMSG_NPC_BUY_REQUEST); - outMsg.writeInt16(8); // One item (length of packet) - outMsg.writeInt16(amount); - outMsg.writeInt16(itemId); -} - -void NpcHandler::sellItem(int beingId, int itemId, int amount) -{ - MessageOut outMsg(CMSG_NPC_SELL_REQUEST); - outMsg.writeInt16(8); // One item (length of packet) - outMsg.writeInt16(itemId + INVENTORY_OFFSET); - outMsg.writeInt16(amount); -} - -void NpcHandler::endShopping(int beingId) -{ - // TODO -} - -void NpcHandler::clearDialogs() +void NpcHandler::sendLetter(int npcId, const std::string &recipient, + const std::string &text) { - mNpcDialogs.clear(); + //NOTE: eA doesn't have letters } } // namespace TmwAthena diff --git a/src/net/tmwa/npchandler.h b/src/net/tmwa/npchandler.h index bd696bdd..1e933418 100644 --- a/src/net/tmwa/npchandler.h +++ b/src/net/tmwa/npchandler.h @@ -22,15 +22,14 @@ #ifndef NET_TA_NPCHANDLER_H #define NET_TA_NPCHANDLER_H -#include "net/net.h" +#include "listener.h" + #include "net/npchandler.h" #include "net/tmwa/messagehandler.h" #include <map> -class NpcDialog; - namespace TmwAthena { class NpcHandler : public MessageHandler, public Net::NpcHandler @@ -40,13 +39,25 @@ class NpcHandler : public MessageHandler, public Net::NpcHandler void handleMessage(Net::MessageIn &msg); + void startShopping(int beingId); + + void buy(int beingId); + + void sell(int beingId); + + void buyItem(int beingId, int itemId, int amount); + + void sellItem(int beingId, int itemId, int amount); + + void endShopping(int beingId); + void talk(int npcId); void nextDialog(int npcId); void closeDialog(int npcId); - void listInput(int npcId, int value); + void menuSelect(int npcId, int choice); void integerInput(int npcId, int value); @@ -55,26 +66,6 @@ class NpcHandler : public MessageHandler, public Net::NpcHandler void sendLetter(int npcId, const std::string &recipient, const std::string &text); - void startShopping(int beingId); - - void buy(int beingId); - - void sell(int beingId); - - void buyItem(int beingId, int itemId, int amount); - - void sellItem(int beingId, int itemId, int amount); - - void endShopping(int beingId); - - void clearDialogs(); - - private: - typedef struct { - NpcDialog* dialog; - } Wrapper; - typedef std::map<int, Wrapper> NpcDialogs; - NpcDialogs mNpcDialogs; }; } // namespace TmwAthena diff --git a/src/net/tmwa/partyhandler.cpp b/src/net/tmwa/partyhandler.cpp index 611fe3e6..00b1e621 100644 --- a/src/net/tmwa/partyhandler.cpp +++ b/src/net/tmwa/partyhandler.cpp @@ -20,7 +20,8 @@ #include "net/tmwa/partyhandler.h" -#include "beingmanager.h" +#include "actorspritemanager.h" +#include "event.h" #include "localplayer.h" #include "log.h" @@ -78,12 +79,9 @@ void PartyHandler::handleMessage(Net::MessageIn &msg) { case SMSG_PARTY_CREATE: if (msg.readInt8()) - localChatTab->chatLog(_("Could not create party."), BY_SERVER); + SERVER_NOTICE(_("Could not create party.")) else - { - localChatTab->chatLog(_("Party successfully created."), - BY_SERVER); - } + SERVER_NOTICE(_("Party successfully created.")) break; case SMSG_PARTY_INFO: { @@ -143,12 +141,9 @@ void PartyHandler::handleMessage(Net::MessageIn &msg) std::string nick = ""; Being *being; - if ((being = beingManager->findBeing(id))) + if ((being = actorSpriteManager->findBeing(id))) { - if (being->getType() == Being::PLAYER) - { - nick = being->getName(); - } + nick = being->getName(); } socialWindow->showPartyInvite(partyName, nick); @@ -238,8 +233,7 @@ void PartyHandler::handleMessage(Net::MessageIn &msg) { taParty->removeFromMembers(); taParty->clearMembers(); - localChatTab->chatLog(_("You have left the party."), - BY_SERVER); + SERVER_NOTICE(_("You have left the party.")) if (partyTab) { delete partyTab; @@ -252,9 +246,10 @@ void PartyHandler::handleMessage(Net::MessageIn &msg) partyTab->chatLog(strprintf(_("%s has left your party."), nick.c_str()), BY_SERVER); - Being *b = beingManager->findBeing(id); - if (b && b->getType() == Being::PLAYER) - static_cast<Player*>(b)->setParty(NULL); + if (Being *b = actorSpriteManager->findBeing(id)) + { + b->setParty(NULL); + } taParty->removeMember(id); } @@ -274,9 +269,9 @@ void PartyHandler::handleMessage(Net::MessageIn &msg) // The server only sends this when the member is in range, so // lets make sure they get the party hilight. - if (Being *b = beingManager->findBeing(id)) + if (Being *b = actorSpriteManager->findBeing(id)) { - static_cast<Player*>(b)->setParty(taParty); + b->setParty(taParty); } } break; @@ -319,19 +314,19 @@ void PartyHandler::join(int partyId) // TODO? } -void PartyHandler::invite(Player *player) +void PartyHandler::invite(Being *being) { MessageOut outMsg(CMSG_PARTY_INVITE); - outMsg.writeInt32(player->getId()); + outMsg.writeInt32(being->getId()); } void PartyHandler::invite(const std::string &name) { - Being *invitee = beingManager->findBeingByName(name, Being::PLAYER); + Being *invitee = actorSpriteManager->findBeingByName(name, Being::PLAYER); if (invitee) { - invite((Player *)invitee); + invite(invitee); partyTab->chatLog(strprintf(_("Invited user %s to party."), invitee->getName().c_str()), BY_SERVER); } @@ -342,8 +337,7 @@ void PartyHandler::invite(const std::string &name) } else { - localChatTab->chatLog(_("You can only inivte when you are in a party!"), - BY_SERVER); + SERVER_NOTICE(_("You can only inivte when you are in a party!")) } } @@ -359,10 +353,10 @@ void PartyHandler::leave() MessageOut outMsg(CMSG_PARTY_LEAVE); } -void PartyHandler::kick(Player *player) +void PartyHandler::kick(Being *being) { MessageOut outMsg(CMSG_PARTY_KICK); - outMsg.writeInt32(player->getId()); + outMsg.writeInt32(being->getId()); outMsg.writeString("", 24); //Unused } diff --git a/src/net/tmwa/partyhandler.h b/src/net/tmwa/partyhandler.h index fc8d741f..5afc8e53 100644 --- a/src/net/tmwa/partyhandler.h +++ b/src/net/tmwa/partyhandler.h @@ -43,7 +43,7 @@ class PartyHandler : public MessageHandler, public Net::PartyHandler void join(int partyId); - void invite(Player *player); + void invite(Being *being); void invite(const std::string &name); @@ -51,7 +51,7 @@ class PartyHandler : public MessageHandler, public Net::PartyHandler void leave(); - void kick(Player *player); + void kick(Being *being); void kick(const std::string &name); diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp index 48e7f4b3..b82968a3 100644 --- a/src/net/tmwa/playerhandler.cpp +++ b/src/net/tmwa/playerhandler.cpp @@ -21,28 +21,25 @@ #include "net/tmwa/playerhandler.h" +#include "event.h" #include "game.h" #include "localplayer.h" #include "log.h" -#include "npc.h" +#include "playerinfo.h" #include "units.h" #include "gui/buy.h" #include "gui/buysell.h" #include "gui/gui.h" -#include "gui/npcdialog.h" #include "gui/okdialog.h" #include "gui/sell.h" #include "gui/statuswindow.h" #include "gui/viewport.h" -#include "gui/widgets/chattab.h" - #include "net/messagein.h" #include "net/messageout.h" #include "net/tmwa/protocol.h" -#include "net/tmwa/npchandler.h" #include "utils/stringutils.h" #include "utils/gettext.h" @@ -54,9 +51,6 @@ extern OkDialog *deathNotice; // everything beyond will reset the port hard. static const int MAP_TELEPORT_SCROLL_DISTANCE = 8; -#define ATTR_BONUS(atr) \ -(player_node->getAttributeEffective(atr) - player_node->getAttributeBase(atr)) - // TODO Move somewhere else namespace { @@ -83,14 +77,11 @@ namespace { BuyDialog::closeAll(); BuySellDialog::closeAll(); - NpcDialog::closeAll(); SellDialog::closeAll(); viewport->closePopupMenu(); - TmwAthena::NpcHandler *handler = - static_cast<TmwAthena::NpcHandler*>(Net::getNpcHandler()); - handler->clearDialogs(); + Mana::Event::trigger(CHANNEL_NPC, EVENT_CLOSEALL); } } deathListener; @@ -220,7 +211,6 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) } player_node->setAction(Being::STAND); - player_node->setFrame(0); player_node->setTileCoords(x, y); logger->log("Adjust scrolling by %d:%d", (int) scrollOffsetX, @@ -241,17 +231,17 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) player_node->setWalkSpeed(Vector(value, value, 0)); break; case 0x0004: break; // manner - case 0x0005: player_node->setHp(value); break; - case 0x0006: player_node->setMaxHp(value); break; - case 0x0007: player_node->setMP(value); break; - case 0x0008: player_node->setMaxMP(value); break; - case 0x0009: player_node->setCharacterPoints(value); break; - case 0x000b: player_node->setLevel(value); break; - case 0x000c: player_node->setSkillPoints(value); break; + case 0x0005: PlayerInfo::setAttribute(HP, value); break; + case 0x0006: PlayerInfo::setAttribute(MAX_HP, value); break; + case 0x0007: PlayerInfo::setAttribute(MP, value); break; + case 0x0008: PlayerInfo::setAttribute(MAX_MP, value); break; + case 0x0009: PlayerInfo::setAttribute(CHAR_POINTS, value); break; + case 0x000b: PlayerInfo::setAttribute(LEVEL, value); break; + case 0x000c: PlayerInfo::setAttribute(SKILL_POINTS, value); break; case 0x0018: - if (value >= player_node->getMaxWeight() / 2 && - player_node->getTotalWeight() < - player_node->getMaxWeight() / 2) + if (value >= PlayerInfo::getAttribute(MAX_WEIGHT) / 2 && + PlayerInfo::getAttribute(TOTAL_WEIGHT) < + PlayerInfo::getAttribute(MAX_WEIGHT) / 2) { weightNotice = new OkDialog(_("Message"), _("You are carrying more than " @@ -260,59 +250,37 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) weightNotice->addActionListener( &weightListener); } - player_node->setTotalWeight(value); + PlayerInfo::setAttribute(TOTAL_WEIGHT, value); break; - case 0x0019: player_node->setMaxWeight(value); break; + case 0x0019: PlayerInfo::setAttribute(MAX_WEIGHT, value); break; - case 0x0029: player_node->setAttributeEffective(ATK, value - + ATTR_BONUS(ATK)); - player_node->setAttributeBase(ATK, value); - break; - case 0x002a: value += player_node->getAttributeBase(ATK); - player_node->setAttributeEffective(ATK, value); break; - - case 0x002b: player_node->setAttributeEffective(MATK, value - + ATTR_BONUS(MATK)); - player_node->setAttributeBase(MATK, value); - if (statusWindow) - statusWindow->update(StatusWindow::MP); - break; - case 0x002c: value += player_node->getAttributeBase(MATK); - player_node->setAttributeEffective(MATK, value); - if (statusWindow) - statusWindow->update(StatusWindow::MP); - break; - case 0x002d: player_node->setAttributeEffective(DEF, value - + ATTR_BONUS(DEF)); - player_node->setAttributeBase(DEF, value); break; - case 0x002e: value += player_node->getAttributeBase(DEF); - player_node->setAttributeEffective(DEF, value); break; - - case 0x002f: player_node->setAttributeEffective(MDEF, value - + ATTR_BONUS(MDEF)); - player_node->setAttributeBase(MDEF, value); break; - case 0x0030: value += player_node->getAttributeBase(MDEF); - player_node->setAttributeEffective(MDEF, value); break; - - case 0x0031: player_node->setAttributeBase(HIT, value); - player_node->setAttributeEffective(HIT, value); break; - - case 0x0032: player_node->setAttributeEffective(FLEE, value - + ATTR_BONUS(FLEE)); - player_node->setAttributeBase(FLEE, value); break; - case 0x0033: value += player_node->getAttributeBase(FLEE); - player_node->setAttributeEffective(FLEE, value); break; - - case 0x0034: player_node->setAttributeBase(CRIT, value); - player_node->setAttributeEffective(CRIT, value); break; + case 0x0029: PlayerInfo::setStatBase(ATK, value); break; + case 0x002a: PlayerInfo::setStatMod(ATK, value); break; + + case 0x002b: PlayerInfo::setStatBase(MATK, value); break; + case 0x002c: PlayerInfo::setStatMod(MATK, value); break; + + case 0x002d: PlayerInfo::setStatBase(DEF, value); break; + case 0x002e: PlayerInfo::setStatMod(DEF, value); break; + + case 0x002f: PlayerInfo::setStatBase(MDEF, value); break; + case 0x0030: PlayerInfo::setStatMod(MDEF, value); break; + + case 0x0031: PlayerInfo::setStatBase(HIT, value); break; + + case 0x0032: PlayerInfo::setStatBase(FLEE, value); break; + case 0x0033: PlayerInfo::setStatMod(FLEE, value); break; + + case 0x0034: PlayerInfo::setStatBase(CRIT, value); break; case 0x0035: player_node->setAttackSpeed(value); break; - case 0x0037: player_node->setAttributeBase(JOB, value); - player_node->setAttributeEffective(JOB, value); break; + + case 0x0037: PlayerInfo::setStatBase(JOB, value); break; + case 500: player_node->setGMLevel(value); break; } - if (player_node->getHp() == 0 && !deathNotice) + if (PlayerInfo::getAttribute(HP) == 0 && !deathNotice) { deathNotice = new OkDialog(_("Message"), randomDeathMessage(), @@ -331,29 +299,29 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) switch (msg.readInt16()) { case 0x0001: - player_node->setExp(msg.readInt32()); + PlayerInfo::setAttribute(EXP, msg.readInt32()); break; case 0x0002: - player_node->setExperience(JOB, msg.readInt32(), - player_node->getExperience(JOB).second); + PlayerInfo::setStatExperience(JOB, msg.readInt32(), + PlayerInfo::getStatExperience(JOB).second); break; case 0x0014: { - int curGp = player_node->getMoney(); - player_node->setMoney(msg.readInt32()); - if (player_node->getMoney() > curGp) - localChatTab->chatLog(strprintf(_("You picked up " - "%s."), - Units::formatCurrency(player_node->getMoney() - - curGp).c_str()), BY_SERVER); + int oldMoney = PlayerInfo::getAttribute(MONEY); + int newMoney = msg.readInt32(); + PlayerInfo::setAttribute(MONEY, newMoney); + if (newMoney > oldMoney) + SERVER_NOTICE(strprintf(_("You picked up %s."), + Units::formatCurrency(newMoney - + oldMoney).c_str())) } break; case 0x0016: - player_node->setExpNeeded(msg.readInt32()); + PlayerInfo::setAttribute(EXP_NEEDED, msg.readInt32()); break; case 0x0017: - player_node->setExperience(JOB, - player_node->getExperience(JOB).first, - msg.readInt32()); + PlayerInfo::setStatExperience(JOB, + PlayerInfo::getStatExperience(JOB).first, + msg.readInt32()); break; } break; @@ -364,8 +332,8 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) int base = msg.readInt32(); int bonus = msg.readInt32(); - player_node->setAttributeBase(type, base); - player_node->setAttributeEffective(type, base + bonus); + PlayerInfo::setStatBase(type, base, false); + PlayerInfo::setStatMod(type, bonus); } break; @@ -377,25 +345,20 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) if (ok != 1) { - localChatTab->chatLog(_("Cannot raise skill!"), - BY_SERVER); + SERVER_NOTICE(_("Cannot raise skill!")) } - int bonus = ATTR_BONUS(type); - - player_node->setAttributeBase(type, value); - player_node->setAttributeEffective(type, value + bonus); + PlayerInfo::setStatBase(type, value); } break; // Updates stats and status points case SMSG_PLAYER_STAT_UPDATE_5: - player_node->setCharacterPoints(msg.readInt16()); + PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16()); { int val = msg.readInt8(); - player_node->setAttributeEffective(STR, val + ATTR_BONUS(STR)); - player_node->setAttributeBase(STR, val); + PlayerInfo::setStatBase(STR, val); if (val >= 99) { statusWindow->setPointsNeeded(STR, 0); @@ -407,8 +370,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) } val = msg.readInt8(); - player_node->setAttributeEffective(AGI, val + ATTR_BONUS(AGI)); - player_node->setAttributeBase(AGI, val); + PlayerInfo::setStatBase(AGI, val); if (val >= 99) { statusWindow->setPointsNeeded(AGI, 0); @@ -420,8 +382,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) } val = msg.readInt8(); - player_node->setAttributeEffective(VIT, val + ATTR_BONUS(VIT)); - player_node->setAttributeBase(VIT, val); + PlayerInfo::setStatBase(VIT, val); if (val >= 99) { statusWindow->setPointsNeeded(VIT, 0); @@ -433,8 +394,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) } val = msg.readInt8(); - player_node->setAttributeEffective(INT, val + ATTR_BONUS(INT)); - player_node->setAttributeBase(INT, val); + PlayerInfo::setStatBase(INT, val); if (val >= 99) { statusWindow->setPointsNeeded(INT, 0); @@ -446,8 +406,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) } val = msg.readInt8(); - player_node->setAttributeEffective(DEX, val + ATTR_BONUS(DEX)); - player_node->setAttributeBase(DEX, val); + PlayerInfo::setStatBase(DEX, val); if (val >= 99) { statusWindow->setPointsNeeded(DEX, 0); @@ -459,8 +418,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) } val = msg.readInt8(); - player_node->setAttributeEffective(LUK, val + ATTR_BONUS(LUK)); - player_node->setAttributeBase(LUK, val); + PlayerInfo::setStatBase(LUK, val); if (val >= 99) { statusWindow->setPointsNeeded(LUK, 0); @@ -471,39 +429,25 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) statusWindow->setPointsNeeded(LUK, msg.readInt8()); } - val = msg.readInt16(); // ATK - player_node->setAttributeBase(ATK, val); - val += msg.readInt16(); // ATK bonus - player_node->setAttributeEffective(ATK, val); - - val = msg.readInt16(); // MATK - player_node->setAttributeBase(MATK, val); - val += msg.readInt16(); // MATK bonus - player_node->setAttributeEffective(MATK, val); - statusWindow->update(StatusWindow::MP); - - val = msg.readInt16(); // DEF - player_node->setAttributeBase(DEF, val); - val += msg.readInt16(); // DEF bonus - player_node->setAttributeEffective(DEF, val); - - val = msg.readInt16(); // MDEF - player_node->setAttributeBase(MDEF, val); - val += msg.readInt16(); // MDEF bonus - player_node->setAttributeEffective(MDEF, val); - - val = msg.readInt16(); // HIT - player_node->setAttributeBase(HIT, val); - player_node->setAttributeEffective(HIT, val); - - val = msg.readInt16(); // FLEE - player_node->setAttributeBase(FLEE, val); - val += msg.readInt16(); // FLEE bonus - player_node->setAttributeEffective(FLEE, val); - - val = msg.readInt16(); - player_node->setAttributeBase(CRIT, val); - player_node->setAttributeEffective(CRIT, val); + PlayerInfo::setStatBase(ATK, msg.readInt16(), false); + PlayerInfo::setStatMod(ATK, msg.readInt16()); + + PlayerInfo::setStatBase(MATK, msg.readInt16(), false); + PlayerInfo::setStatMod(MATK, msg.readInt16()); + + + PlayerInfo::setStatBase(DEF, msg.readInt16(), false); + PlayerInfo::setStatMod(DEF, msg.readInt16()); + + PlayerInfo::setStatBase(MDEF, msg.readInt16(), false); + PlayerInfo::setStatMod(MDEF, msg.readInt16()); + + PlayerInfo::setStatBase(HIT, msg.readInt16()); + + PlayerInfo::setStatBase(FLEE, msg.readInt16(), false); + PlayerInfo::setStatMod(FLEE, msg.readInt16()); + + PlayerInfo::setStatBase(CRIT, msg.readInt16()); } msg.readInt16(); // manner @@ -540,8 +484,9 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) switch (type) { case 0: - localChatTab->chatLog(_("Equip arrows first."), - BY_SERVER); + { + SERVER_NOTICE(_("Equip arrows first.")) + } break; default: logger->log("0x013b: Unhandled message %i", type); @@ -582,7 +527,7 @@ void PlayerHandler::decreaseAttribute(int attr) void PlayerHandler::increaseSkill(int skillId) { - if (player_node->getSkillPoints() <= 0) + if (PlayerInfo::getAttribute(SKILL_POINTS) <= 0) return; MessageOut outMsg(CMSG_SKILL_LEVELUP_REQUEST); @@ -591,8 +536,11 @@ void PlayerHandler::increaseSkill(int skillId) void PlayerHandler::pickUp(FloorItem *floorItem) { - MessageOut outMsg(CMSG_ITEM_PICKUP); - outMsg.writeInt32(floorItem->getId()); + if (floorItem) + { + MessageOut outMsg(CMSG_ITEM_PICKUP); + outMsg.writeInt32(floorItem->getId()); + } } void PlayerHandler::setDirection(char direction) @@ -641,7 +589,7 @@ void PlayerHandler::ignoreAll(bool ignore) bool PlayerHandler::canUseMagic() { - return player_node->getAttributeEffective(MATK) > 0; + return PlayerInfo::getStatEffective(MATK) > 0; } bool PlayerHandler::canCorrectAttributes() diff --git a/src/net/tmwa/specialhandler.cpp b/src/net/tmwa/specialhandler.cpp index c5f5d540..577bda7e 100644 --- a/src/net/tmwa/specialhandler.cpp +++ b/src/net/tmwa/specialhandler.cpp @@ -21,13 +21,12 @@ #include "net/tmwa/specialhandler.h" -#include "localplayer.h" +#include "event.h" #include "log.h" +#include "playerinfo.h" #include "gui/skilldialog.h" -#include "gui/widgets/chattab.h" - #include "net/messagein.h" #include "net/messageout.h" @@ -105,8 +104,7 @@ void SpecialHandler::handleMessage(Net::MessageIn &msg) msg.skip(24); // unused int up = msg.readInt8(); - player_node->setAttributeBase(skillId, level); - player_node->setAttributeEffective(skillId, level); + PlayerInfo::setStatBase(skillId, level); skillDialog->setModifiable(skillId, up); } break; @@ -119,8 +117,7 @@ void SpecialHandler::handleMessage(Net::MessageIn &msg) msg.readInt16(); // range int up = msg.readInt8(); - player_node->setAttributeBase(skillId, level); - player_node->setAttributeEffective(skillId, level); + PlayerInfo::setStatBase(skillId, level); skillDialog->setModifiable(skillId, up); } break; @@ -218,7 +215,7 @@ void SpecialHandler::handleMessage(Net::MessageIn &msg) } } - localChatTab->chatLog(msg); + SERVER_NOTICE(msg) break; } } diff --git a/src/net/tmwa/token.h b/src/net/tmwa/token.h index d2a21012..3e781cd8 100644 --- a/src/net/tmwa/token.h +++ b/src/net/tmwa/token.h @@ -19,7 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "player.h" +#include "being.h" #ifndef NET_TA_TOKEN_H #define NET_TA_TOKEN_H diff --git a/src/net/tmwa/tradehandler.cpp b/src/net/tmwa/tradehandler.cpp index 9089f8e6..034b959d 100644 --- a/src/net/tmwa/tradehandler.cpp +++ b/src/net/tmwa/tradehandler.cpp @@ -21,22 +21,24 @@ #include "net/tmwa/tradehandler.h" +#include "event.h" #include "inventory.h" #include "item.h" #include "localplayer.h" +#include "playerinfo.h" #include "playerrelations.h" #include "gui/confirmdialog.h" #include "gui/trade.h" -#include "gui/widgets/chattab.h" - #include "net/inventoryhandler.h" #include "net/messagein.h" #include "net/messageout.h" #include "net/tmwa/protocol.h" +#include "resources/iteminfo.h" + #include "utils/gettext.h" #include "utils/stringutils.h" @@ -96,14 +98,14 @@ void TradeHandler::handleMessage(Net::MessageIn &msg) if (player_relations.hasPermission(tradePartnerName, PlayerRelation::TRADE)) { - if (!player_node->tradeRequestOk() || confirmDlg) + if (PlayerInfo::isTrading() || confirmDlg) { Net::getTradeHandler()->respond(false); break; } tradePartnerName = tradePartnerNameTemp; - player_node->setTrading(true); + PlayerInfo::setTrading(true); confirmDlg = new ConfirmDialog(_("Request for Trade"), strprintf(_("%s wants to trade with you, do you " "accept?"), tradePartnerName.c_str())); @@ -121,16 +123,16 @@ void TradeHandler::handleMessage(Net::MessageIn &msg) switch (msg.readInt8()) { case 0: // Too far away - localChatTab->chatLog(_("Trading isn't possible. Trade " - "partner is too far away."), BY_SERVER); + SERVER_NOTICE(_("Trading isn't possible. Trade " + "partner is too far away.")) break; case 1: // Character doesn't exist - localChatTab->chatLog(_("Trading isn't possible. Character " - "doesn't exist."), BY_SERVER); + SERVER_NOTICE(_("Trading isn't possible. Character " + "doesn't exist.")) break; case 2: // Invite request check failed... - localChatTab->chatLog(_("Trade cancelled due to an unknown " - "reason."), BY_SERVER); + SERVER_NOTICE(_("Trade cancelled due to an unknown " + "reason.")) break; case 3: // Trade accepted tradeWindow->reset(); @@ -141,17 +143,15 @@ void TradeHandler::handleMessage(Net::MessageIn &msg) case 4: // Trade cancelled if (player_relations.hasPermission(tradePartnerName, PlayerRelation::SPEECH_LOG)) - localChatTab->chatLog(strprintf(_("Trade with %s " - "cancelled."), tradePartnerName.c_str()), - BY_SERVER); + SERVER_NOTICE(strprintf(_("Trade with %s cancelled."), + tradePartnerName.c_str())) // otherwise ignore silently tradeWindow->setVisible(false); - player_node->setTrading(false); + PlayerInfo::setTrading(false); break; default: // Shouldn't happen as well, but to be sure - localChatTab->chatLog(_("Unhandled trade cancel packet."), - BY_SERVER); + SERVER_NOTICE(_("Unhandled trade cancel packet.")) break; } break; @@ -169,7 +169,7 @@ void TradeHandler::handleMessage(Net::MessageIn &msg) if (type == 0) tradeWindow->setMoney(amount); else - tradeWindow->addItem(type, false, amount, false); + tradeWindow->addItem(type, false, amount); } break; @@ -177,7 +177,7 @@ void TradeHandler::handleMessage(Net::MessageIn &msg) // Trade: New Item add response (was 0x00ea, now 01b1) { const int index = msg.readInt16() - INVENTORY_OFFSET; - Item *item = player_node->getInventory()->getItem(index); + Item *item = PlayerInfo::getInventory()->getItem(index); if (!item) { tradeWindow->receivedOk(true); @@ -189,27 +189,27 @@ void TradeHandler::handleMessage(Net::MessageIn &msg) { case 0: // Successfully added item - if (item->isEquipment() && item->isEquipped()) + if (item->isEquippable() && item->isEquipped()) { - Net::getInventoryHandler()->unequipItem(item); + item->doEvent(EVENT_DOUNEQUIP); } - tradeWindow->addItem(item->getId(), true, quantity, - item->isEquipment()); + tradeWindow->addItem(item->getId(), true, quantity); + item->increaseQuantity(-quantity); break; case 1: // Add item failed - player overweighted - localChatTab->chatLog(_("Failed adding item. Trade " - "partner is over weighted."), BY_SERVER); + SERVER_NOTICE(_("Failed adding item. Trade " + "partner is over weighted.")) break; case 2: // Add item failed - player has no free slot - localChatTab->chatLog(_("Failed adding item. Trade " - "partner has no free slot."), BY_SERVER); + SERVER_NOTICE(_("Failed adding item. Trade " + "partner has no free slot.")) break; default: - localChatTab->chatLog(_("Failed adding item for " - "unknown reason."), BY_SERVER); + SERVER_NOTICE(_("Failed adding item for " + "unknown reason.")) break; } } @@ -221,17 +221,17 @@ void TradeHandler::handleMessage(Net::MessageIn &msg) break; case SMSG_TRADE_CANCEL: - localChatTab->chatLog(_("Trade canceled."), BY_SERVER); + SERVER_NOTICE(_("Trade canceled.")) tradeWindow->setVisible(false); tradeWindow->reset(); - player_node->setTrading(false); + PlayerInfo::setTrading(false); break; case SMSG_TRADE_COMPLETE: - localChatTab->chatLog(_("Trade completed."), BY_SERVER); + SERVER_NOTICE(_("Trade completed.")) tradeWindow->setVisible(false); tradeWindow->reset(); - player_node->setTrading(false); + PlayerInfo::setTrading(false); break; } } @@ -245,7 +245,7 @@ void TradeHandler::request(Being *being) void TradeHandler::respond(bool accept) { if (!accept) - player_node->setTrading(false); + PlayerInfo::setTrading(false); MessageOut outMsg(CMSG_TRADE_RESPONSE); outMsg.writeInt8(accept ? 3 : 4); diff --git a/src/net/tradehandler.h b/src/net/tradehandler.h index 30798c41..ea3c4550 100644 --- a/src/net/tradehandler.h +++ b/src/net/tradehandler.h @@ -30,6 +30,8 @@ namespace Net { class TradeHandler { public: + virtual ~TradeHandler() {} + virtual void request(Being *being) {} virtual void respond(bool accept) {} @@ -45,8 +47,6 @@ class TradeHandler virtual void finish() {} virtual void cancel() {} - - virtual ~TradeHandler() {} }; } |