summaryrefslogtreecommitdiff
path: root/src/net/manaserv
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/manaserv')
-rw-r--r--src/net/manaserv/adminhandler.cpp2
-rw-r--r--src/net/manaserv/attributes.cpp408
-rw-r--r--src/net/manaserv/attributes.h (renamed from src/net/manaserv/stats.h)41
-rw-r--r--src/net/manaserv/beinghandler.cpp141
-rw-r--r--src/net/manaserv/beinghandler.h8
-rw-r--r--src/net/manaserv/buysellhandler.cpp16
-rw-r--r--src/net/manaserv/charhandler.cpp79
-rw-r--r--src/net/manaserv/charhandler.h18
-rw-r--r--src/net/manaserv/chathandler.cpp55
-rw-r--r--src/net/manaserv/connection.cpp4
-rw-r--r--src/net/manaserv/defines.h76
-rw-r--r--src/net/manaserv/effecthandler.cpp44
-rw-r--r--src/net/manaserv/effecthandler.h1
-rw-r--r--src/net/manaserv/gamehandler.cpp15
-rw-r--r--src/net/manaserv/gamehandler.h9
-rw-r--r--src/net/manaserv/generalhandler.cpp64
-rw-r--r--src/net/manaserv/generalhandler.h10
-rw-r--r--src/net/manaserv/guildhandler.cpp21
-rw-r--r--src/net/manaserv/guildhandler.h2
-rw-r--r--src/net/manaserv/inventoryhandler.cpp220
-rw-r--r--src/net/manaserv/inventoryhandler.h47
-rw-r--r--src/net/manaserv/itemhandler.cpp27
-rw-r--r--src/net/manaserv/loginhandler.cpp21
-rw-r--r--src/net/manaserv/loginhandler.h2
-rw-r--r--src/net/manaserv/manaserv_protocol.h (renamed from src/net/manaserv/protocol.h)113
-rw-r--r--src/net/manaserv/messagein.h3
-rw-r--r--src/net/manaserv/messageout.h6
-rw-r--r--src/net/manaserv/network.cpp4
-rw-r--r--src/net/manaserv/npchandler.cpp246
-rw-r--r--src/net/manaserv/npchandler.h40
-rw-r--r--src/net/manaserv/partyhandler.cpp19
-rw-r--r--src/net/manaserv/partyhandler.h4
-rw-r--r--src/net/manaserv/playerhandler.cpp144
-rw-r--r--src/net/manaserv/playerhandler.h7
-rw-r--r--src/net/manaserv/specialhandler.cpp2
-rw-r--r--src/net/manaserv/stats.cpp217
-rw-r--r--src/net/manaserv/tradehandler.cpp29
37 files changed, 1296 insertions, 869 deletions
diff --git a/src/net/manaserv/adminhandler.cpp b/src/net/manaserv/adminhandler.cpp
index 8a30e01b..db6c22ed 100644
--- a/src/net/manaserv/adminhandler.cpp
+++ b/src/net/manaserv/adminhandler.cpp
@@ -23,7 +23,7 @@
#include "net/manaserv/connection.h"
#include "net/manaserv/messageout.h"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
extern Net::AdminHandler *adminHandler;
diff --git a/src/net/manaserv/attributes.cpp b/src/net/manaserv/attributes.cpp
new file mode 100644
index 00000000..e57c6278
--- /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<ItemStat> dbStats;
+
+ TagMap::const_iterator it, it_end;
+ for (it = tags.begin(), it_end = tags.end(); it != it_end; ++it)
+ dbStats.push_back(ItemStat(it->first,
+ it->second));
+
+ 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..4c91a36e 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"
@@ -35,12 +34,14 @@
#include "net/messagein.h"
#include "net/manaserv/playerhandler.h"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
#include "resources/colordb.h"
#include "utils/gettext.h"
+#define POSITION_DIFF_TOLERANCE 48
+
namespace ManaServ {
BeingHandler::BeingHandler()
@@ -90,38 +91,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
}
}
-Vector BeingHandler::giveSpeedInPixelsPerTicks(float speedInTilesPerSeconds)
-{
- Vector speedInTicks;
- Game *game = Game::instance();
- Map *map = 0;
- if (game)
- {
- map = game->getCurrentMap();
- if (map)
- {
- speedInTicks.x = speedInTilesPerSeconds
- * (float)map->getTileWidth()
- / 1000 * (float) MILLISECONDS_IN_A_TICK;
- speedInTicks.y = speedInTilesPerSeconds
- * (float)map->getTileHeight()
- / 1000 * (float) MILLISECONDS_IN_A_TICK;
- }
- }
-
- if (!game || !map)
- {
- speedInTicks.x = speedInTicks.y = 0;
- logger->log("Manaserv::BeingHandler: Speed wasn't given back"
- " because game/Map not initialized.");
- }
- // We don't use z for now.
- speedInTicks.z = 0;
-
- 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 +115,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));
}
}
@@ -156,6 +126,7 @@ void BeingHandler::handleBeingEnterMessage(Net::MessageIn &msg)
Being::Action action = (Being::Action)msg.readInt8();
int px = msg.readInt16();
int py = msg.readInt16();
+ BeingDirection direction = (BeingDirection)msg.readInt8();
Being *being;
switch (type)
@@ -170,23 +141,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;
@@ -197,16 +168,17 @@ void BeingHandler::handleBeingEnterMessage(Net::MessageIn &msg)
being->setPosition(px, py);
being->setDestination(px, py);
+ being->setDirection(direction);
being->setAction(action);
}
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,62 +187,69 @@ void BeingHandler::handleBeingsMoveMessage(Net::MessageIn &msg)
{
int id = msg.readInt16();
int flags = msg.readInt8();
- Being *being = beingManager->findBeing(id);
- int sx = 0;
- int sy = 0;
- int speed = 0;
+ Being *being = actorSpriteManager->findBeing(id);
+ int sx = 0, sy = 0, dx = 0, dy = 0, speed = 0;
+
+ if ((!flags & (MOVING_POSITION | MOVING_DESTINATION)))
+ continue;
if (flags & MOVING_POSITION)
{
sx = msg.readInt16();
sy = msg.readInt16();
- speed = msg.readInt8();
}
- if (!being || !(flags & (MOVING_POSITION | MOVING_DESTINATION)))
+
+ if (flags & MOVING_DESTINATION)
{
- continue;
+ dx = msg.readInt16();
+ dy = msg.readInt16();
+ speed = msg.readInt8();
}
+
+ if (!being)
+ continue;
+
if (speed)
{
/*
* The being's speed is transfered in tiles per second * 10
* to keep it transferable in a Byte.
* We set it back to tiles per second and in a float.
- * Then, we translate it in pixels per ticks, to correspond
- * with the Being::logic() function calls
- * @see MILLISECONDS_IN_A_TICK
*/
- being->setWalkSpeed(
- giveSpeedInPixelsPerTicks((float) speed / 10));
+ float speedTilesSeconds = (float) speed / 10;
+ being->setMoveSpeed(Vector(speedTilesSeconds, speedTilesSeconds,
+ 0));
}
// Ignore messages from the server for the local player
if (being == player_node)
continue;
+ // If the position differs too much from the actual one, we resync
+ // the being position
if (flags & MOVING_POSITION)
{
- being->setDestination(sx, sy);
+ Vector serverPos(sx, sy);
+ if (serverPos.length()
+ - being->getPosition().length() > POSITION_DIFF_TOLERANCE)
+ being->setPosition(serverPos);
}
+
+ if (flags & MOVING_DESTINATION)
+ being->setDestination(dx, dy);
}
}
void BeingHandler::handleBeingAttackMessage(Net::MessageIn &msg)
{
- Being *being = beingManager->findBeing(msg.readInt16());
- const int direction = msg.readInt8();
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
+ const BeingDirection direction = (BeingDirection) msg.readInt8();
const int attackType = msg.readInt8();
if (!being)
return;
- switch (direction)
- {
- case DIRECTION_UP: being->setDirection(Being::UP); break;
- case DIRECTION_DOWN: being->setDirection(Being::DOWN); break;
- case DIRECTION_LEFT: being->setDirection(Being::LEFT); break;
- case DIRECTION_RIGHT: being->setDirection(Being::RIGHT); break;
- }
+ being->setDirection(direction);
being->setAction(Being::ATTACK, attackType);
}
@@ -279,7 +258,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 +269,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,38 +308,28 @@ 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();
// The direction for the player's character is handled on client side.
if (being != player_node)
- {
- switch (data)
- {
- case DIRECTION_UP: being->setDirection(Being::UP); break;
- case DIRECTION_DOWN: being->setDirection(Being::DOWN); break;
- case DIRECTION_LEFT: being->setDirection(Being::LEFT); break;
- case DIRECTION_RIGHT: being->setDirection(Being::RIGHT); break;
- default: break;
- }
- }
+ being->setDirection((BeingDirection) data);
}
} // namespace ManaServ
diff --git a/src/net/manaserv/beinghandler.h b/src/net/manaserv/beinghandler.h
index 2e9eb333..04c766d9 100644
--- a/src/net/manaserv/beinghandler.h
+++ b/src/net/manaserv/beinghandler.h
@@ -35,14 +35,6 @@ class BeingHandler : public MessageHandler
void handleMessage(Net::MessageIn &msg);
- /**
- * Translate a given speed in tiles per seconds
- * into pixels per ticks.
- * Used to optimize Being::logic() calls.
- * @see MILLISECONDS_IN_A_TICKS
- */
- static Vector giveSpeedInPixelsPerTicks(float speedInTilesPerSeconds);
-
private:
void handleBeingAttackMessage(Net::MessageIn &msg);
void handleBeingEnterMessage(Net::MessageIn &msg);
diff --git a/src/net/manaserv/buysellhandler.cpp b/src/net/manaserv/buysellhandler.cpp
index a4ce6aa0..c375ed75 100644
--- a/src/net/manaserv/buysellhandler.cpp
+++ b/src/net/manaserv/buysellhandler.cpp
@@ -21,18 +21,16 @@
#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"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
namespace ManaServ {
@@ -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..79f3b35a 100644
--- a/src/net/manaserv/charhandler.cpp
+++ b/src/net/manaserv/charhandler.cpp
@@ -36,8 +36,8 @@
#include "net/manaserv/gamehandler.h"
#include "net/manaserv/messagein.h"
#include "net/manaserv/messageout.h"
-#include "net/manaserv/protocol.h"
-#include "net/manaserv/stats.h"
+#include "net/manaserv/manaserv_protocol.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,14 @@ 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;
+ case CREATE_INVALID_SLOT:
+ errorMessage = _("Invalid slot number.");
break;
default:
errorMessage = _("Unknown error.");
@@ -186,10 +196,17 @@ void CharHandler::handleCharacterDeleteResponse(Net::MessageIn &msg)
if (errMsg == ERRMSG_OK)
{
// Character deletion successful
+ for (unsigned i = 0; i < mCachedCharacterInfos.size(); ++i)
+ {
+ if (mCachedCharacterInfos[i].slot == mSelectedCharacter->slot)
+ {
+ mCachedCharacterInfos.erase(mCachedCharacterInfos.begin() + i);
+ break;
+ }
+ }
delete mSelectedCharacter;
mCharacters.remove(mSelectedCharacter);
updateCharSelectDialog();
- unlockCharSelectDialog();
new OkDialog(_("Info"), _("Player deleted."));
}
else
@@ -210,6 +227,7 @@ void CharHandler::handleCharacterDeleteResponse(Net::MessageIn &msg)
new OkDialog(_("Error"), errorMessage);
}
mSelectedCharacter = 0;
+ unlockCharSelectDialog();
}
void CharHandler::handleCharacterSelectResponse(Net::MessageIn &msg)
@@ -233,13 +251,25 @@ 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);
}
- else if (errMsg == ERRMSG_FAILURE)
+ else
{
- errorMessage = _("No gameservers are available.");
+ switch (errMsg)
+ {
+ case ERRMSG_FAILURE:
+ errorMessage = _("No gameservers are available.");
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("Invalid character slot selected.");
+ break;
+ default:
+ errorMessage = strprintf(_("Unhandled character select "
+ "error message %i."), errMsg);
+ }
delete_all(mCharacters);
mCharacters.clear();
Client::setState(STATE_ERROR);
@@ -259,7 +289,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()
@@ -285,7 +318,7 @@ void CharHandler::chooseCharacter(Net::Character *character)
}
void CharHandler::newCharacter(const std::string &name,
- int /* slot */,
+ int slot,
bool gender,
int hairstyle,
int hairColor,
@@ -297,6 +330,7 @@ void CharHandler::newCharacter(const std::string &name,
msg.writeInt8(hairstyle);
msg.writeInt8(hairColor);
msg.writeInt8(gender);
+ msg.writeInt8(slot);
std::vector<int>::const_iterator it, it_end;
for (it = stats.begin(), it_end = stats.end(); it != it_end; it++)
@@ -319,17 +353,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 +384,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..6c97fae3 100644
--- a/src/net/manaserv/chathandler.cpp
+++ b/src/net/manaserv/chathandler.cpp
@@ -21,20 +21,21 @@
#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 "log.h"
+#include "playerrelations.h"
#include "gui/widgets/channeltab.h"
#include "net/manaserv/connection.h"
#include "net/manaserv/messagein.h"
#include "net/manaserv/messageout.h"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
@@ -149,22 +150,31 @@ 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)
+ if (!being)
{
- mes = being->getName() + " : " + chatMsg;
- being->setSpeech(chatMsg, SPEECH_TIME);
+ logger->log("Warning: Received GPMSG_SAY for unknown being with id %i."
+ " (Message is: %s)", id, chatMsg.c_str());
+ return;
}
- else
- mes = "Unknown : " + chatMsg;
- localChatTab->chatLog(mes, being == player_node ? BY_PLAYER : BY_OTHER);
+ std::string mes = being->getName() + " : " + chatMsg;
+
+ 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(Event::ChatChannel);
}
void ChatHandler::handleEnterChannelResponse(Net::MessageIn &msg)
@@ -198,13 +208,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 +224,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 +234,18 @@ void ChatHandler::handlePrivateMessage(Net::MessageIn &msg)
std::string userNick = msg.readString();
std::string chatMsg = msg.readString();
- chatWindow->whisper(userNick, chatMsg);
+ Event event(Event::Whisper);
+ event.setString("nick", userNick);
+ event.setString("message", chatMsg);
+ event.trigger(Event::ChatChannel);
}
void ChatHandler::handleAnnouncement(Net::MessageIn &msg)
{
std::string chatMsg = msg.readString();
- localChatTab->chatLog(chatMsg, BY_GM);
+ Event event(Event::Announcement);
+ event.setString("message", chatMsg);
+ event.trigger(Event::ChatChannel);
}
void ChatHandler::handleChatMessage(Net::MessageIn &msg)
@@ -341,7 +356,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..4b421a04 100644
--- a/src/net/manaserv/connection.cpp
+++ b/src/net/manaserv/connection.cpp
@@ -60,11 +60,7 @@ bool Connection::connect(const std::string &address, short port)
enetAddress.port = port;
// Initiate the connection, allocating channel 0.
-#ifdef ENET_VERSION_MAJOR
mConnection = enet_host_connect(mClient, &enetAddress, 1, 0);
-#else
- mConnection = enet_host_connect(mClient, &enetAddress, 1);
-#endif
if (!mConnection)
{
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..7051bedd 100644
--- a/src/net/manaserv/effecthandler.cpp
+++ b/src/net/manaserv/effecthandler.cpp
@@ -21,13 +21,15 @@
#include "net/manaserv/effecthandler.h"
-#include "beingmanager.h"
+#include "actorspritemanager.h"
#include "effectmanager.h"
#include "log.h"
+#include "gui/viewport.h"
+
#include "net/messagein.h"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
namespace ManaServ {
@@ -36,6 +38,7 @@ EffectHandler::EffectHandler()
static const Uint16 _messages[] = {
GPMSG_CREATE_EFFECT_POS,
GPMSG_CREATE_EFFECT_BEING,
+ GPMSG_SHAKE,
0
};
handledMessages = _messages;
@@ -51,6 +54,9 @@ void EffectHandler::handleMessage(Net::MessageIn &msg)
case GPMSG_CREATE_EFFECT_BEING:
handleCreateEffectBeing(msg);
break;
+ case GPMSG_SHAKE:
+ handleShake(msg);
+ break;
default:
break;
}
@@ -68,11 +74,43 @@ 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
logger->log("Warning: CreateEffect called for unknown being #%d", bid);
}
+void EffectHandler::handleShake(Net::MessageIn &msg)
+{
+ int16_t intensityX = 0;
+ int16_t intensityY = 0;
+ float decay;
+ int duration;
+
+ switch (msg.getUnreadLength())
+ {
+ case 4:
+ intensityX = msg.readInt16();
+ intensityY = msg.readInt16();
+ viewport->shakeScreen(intensityX, intensityY);
+ break;
+ case 6:
+ intensityX = msg.readInt16();
+ intensityY = msg.readInt16();
+ decay = msg.readInt16() / 10000.0f;
+ viewport->shakeScreen(intensityX, intensityY, decay);
+ break;
+ case 8:
+ intensityX = msg.readInt16();
+ intensityY = msg.readInt16();
+ decay = msg.readInt16() / 10000.0f;
+ duration = msg.readInt16();
+ viewport->shakeScreen(intensityX, intensityY, decay, duration);
+ break;
+ default:
+ logger->log("Warning: Received GPMSG_SHAKE message with unexpected length of %d bytes", msg.getUnreadLength());
+ }
+}
+
} // namespace ManaServ
diff --git a/src/net/manaserv/effecthandler.h b/src/net/manaserv/effecthandler.h
index a0445aad..d31c3421 100644
--- a/src/net/manaserv/effecthandler.h
+++ b/src/net/manaserv/effecthandler.h
@@ -36,6 +36,7 @@ class EffectHandler : public MessageHandler
private:
void handleCreateEffectPos(Net::MessageIn &msg);
void handleCreateEffectBeing(Net::MessageIn &msg);
+ void handleShake(Net::MessageIn &msg);
};
} // namespace ManaServ
diff --git a/src/net/manaserv/gamehandler.cpp b/src/net/manaserv/gamehandler.cpp
index 5e29a896..63f84fd1 100644
--- a/src/net/manaserv/gamehandler.cpp
+++ b/src/net/manaserv/gamehandler.cpp
@@ -27,7 +27,7 @@
#include "net/manaserv/chathandler.h"
#include "net/manaserv/connection.h"
#include "net/manaserv/messageout.h"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
extern Net::GameHandler *gameHandler;
@@ -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
@@ -151,7 +141,8 @@ void GameHandler::gameLoading()
chatHandler->connect();
// Attack range from item DB
- player_node->setAttackRange(-1);
+ // TODO: Deharcode it through equipment handling
+ player_node->setAttackRange(48);
}
} // namespace ManaServ
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 4f6ade4e..a1ba746f 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(Event::ClientChannel);
+ listen(Event::GameChannel);
}
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();
- 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(Event::Channel channel,
+ const Event &event)
{
- if (newState == STATE_GAME)
+ if (channel == Event::ClientChannel)
{
- GameHandler *game = static_cast<GameHandler*>(Net::getGameHandler());
- game->gameLoading();
+ if (event.getType() == Event::StateChange)
+ {
+ int newState = event.getInt("newState");
+
+ if (newState == STATE_GAME)
+ {
+ GameHandler *game = static_cast<GameHandler*>(Net::getGameHandler());
+ game->gameLoading();
+ }
+ }
+ else if (event.getType() == Event::LoadingDatabases)
+ {
+ Attributes::load();
+ Attributes::informItemDB();
+ }
}
- else if (newState == STATE_LOAD_DATA)
+ else if (channel == Event::GameChannel)
{
- Stats::load();
- Stats::informItemDB();
+ if (event.getType() == Event::GuiWindowsLoaded)
+ {
+ inventoryWindow->setSplitAllowed(true);
+ skillDialog->loadSkills();
+
+ PlayerInfo::setAttribute(EXP_NEEDED, 100);
+
+ Attributes::informStatusWindow();
+ }
}
}
diff --git a/src/net/manaserv/generalhandler.h b/src/net/manaserv/generalhandler.h
index 58b95529..45ded011 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 "eventlistener.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 EventListener
{
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(Event::Channel channel, const Event &event);
protected:
MessageHandlerPtr mBeingHandler;
diff --git a/src/net/manaserv/guildhandler.cpp b/src/net/manaserv/guildhandler.cpp
index 253efb01..a2c571bc 100644
--- a/src/net/manaserv/guildhandler.cpp
+++ b/src/net/manaserv/guildhandler.cpp
@@ -21,23 +21,24 @@
#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"
#include "net/manaserv/connection.h"
#include "net/manaserv/messagein.h"
#include "net/manaserv/messageout.h"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
#include "utils/gettext.h"
#include "utils/stringutils.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..ff9b69e6 100644
--- a/src/net/manaserv/inventoryhandler.cpp
+++ b/src/net/manaserv/inventoryhandler.cpp
@@ -26,18 +26,15 @@
#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"
#include "net/manaserv/messageout.h"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
#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(Event::ItemChannel);
}
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(Event::Channel channel,
+ const Event &event)
{
- // TODO
-}
+ if (channel == Event::ItemChannel)
+ {
+ Item *item = event.getItem("item");
+
+ if (!item)
+ return;
+
+ int index = item->getInvIndex();
+
+ if (event.getType() == Event::DoEquip)
+ {
+ MessageOut msg(PGMSG_EQUIP);
+ msg.writeInt8(index);
+ gameServerConnection->send(msg);
+ }
+ else if (event.getType() == 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.getType() == Event::DoUse)
+ {
+ MessageOut msg(PGMSG_USE_ITEM);
+ msg.writeInt8(index);
+ gameServerConnection->send(msg);
+ }
+ else if (event.getType() == Event::DoDrop)
+ {
+ int amount = event.getInt("amount", 1);
+
+ MessageOut msg(PGMSG_DROP);
+ msg.writeInt8(index);
+ msg.writeInt8(amount);
+ gameServerConnection->send(msg);
+ }
+ else if (event.getType() == 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.getType() == 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..2733f3da 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 "eventlistener.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 EventListener
{
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(Event::Channel channel, const 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..d8365d79 100644
--- a/src/net/manaserv/itemhandler.cpp
+++ b/src/net/manaserv/itemhandler.cpp
@@ -21,13 +21,11 @@
#include "net/manaserv/itemhandler.h"
-#include "flooritemmanager.h"
+#include "actorspritemanager.h"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
#include "net/manaserv/messagein.h"
-#include "game.h"
-#include "map.h"
#include "log.h"
namespace ManaServ {
@@ -58,26 +56,11 @@ void ItemHandler::handleMessage(Net::MessageIn &msg)
if (itemId)
{
- if (Game *game = Game::instance())
- {
- if (Map *map = game->getCurrentMap())
- {
- floorItemManager->create(id,
- itemId,
- x / map->getTileWidth(),
- y / map->getTileHeight());
- }
- else
- {
- logger->log(
- "ItemHandler: An item wasn't created "
- "because of Game/Map not initialized...");
- }
- }
+ actorSpriteManager->createItem(id, itemId, Vector(x, y));
}
- 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..2f802e21 100644
--- a/src/net/manaserv/loginhandler.cpp
+++ b/src/net/manaserv/loginhandler.cpp
@@ -29,7 +29,7 @@
#include "net/manaserv/connection.h"
#include "net/manaserv/messagein.h"
#include "net/manaserv/messageout.h"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
#include "utils/gettext.h"
#include "utils/sha256.h"
@@ -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
@@ -251,7 +251,7 @@ void LoginHandler::handleLoginResponse(Net::MessageIn &msg)
if (errMsg == ERRMSG_OK)
{
- readUpdateHost(msg);
+ readServerInfo(msg);
// No worlds atm, but future use :-D
Client::setState(STATE_WORLD_SELECT);
}
@@ -289,7 +289,7 @@ void LoginHandler::handleRegisterResponse(Net::MessageIn &msg)
if (errMsg == ERRMSG_OK)
{
- readUpdateHost(msg);
+ readServerInfo(msg);
Client::setState(STATE_WORLD_SELECT);
}
else
@@ -320,7 +320,7 @@ void LoginHandler::handleRegisterResponse(Net::MessageIn &msg)
}
}
-void LoginHandler::readUpdateHost(Net::MessageIn &msg)
+void LoginHandler::readServerInfo(Net::MessageIn &msg)
{
// Safety check for outdated manaserv versions (remove me later)
if (msg.getUnreadLength() == 0)
@@ -332,6 +332,13 @@ void LoginHandler::readUpdateHost(Net::MessageIn &msg)
mLoginData->updateHost = updateHost;
else
logger->log("Warning: server does not have an update host set!");
+
+ // Read the client data folder for dynamic data loading.
+ // This is only used by the QT client.
+ msg.readString();
+
+ // Read the number of character slots
+ mLoginData->characterSlots = msg.readInt8();
}
void LoginHandler::connect()
@@ -381,7 +388,7 @@ void LoginHandler::loginAccount(LoginData *loginData)
MessageOut msg(PAMSG_LOGIN);
- msg.writeInt32(0); // client version
+ msg.writeInt32(PROTOCOL_VERSION); // client version
msg.writeString(loginData->username);
msg.writeString(sha256(loginData->username + loginData->password));
@@ -429,7 +436,7 @@ void LoginHandler::registerAccount(LoginData *loginData)
MessageOut msg(PAMSG_REGISTER);
- msg.writeInt32(0); // client version
+ msg.writeInt32(PROTOCOL_VERSION); // client version
msg.writeString(loginData->username);
// Use a hashed password for privacy reasons
msg.writeString(sha256(loginData->username + loginData->password));
diff --git a/src/net/manaserv/loginhandler.h b/src/net/manaserv/loginhandler.h
index d2ffbc3d..2062dcb5 100644
--- a/src/net/manaserv/loginhandler.h
+++ b/src/net/manaserv/loginhandler.h
@@ -80,7 +80,7 @@ class LoginHandler : public MessageHandler, public Net::LoginHandler
void handleLoginResponse(Net::MessageIn &msg);
void handleRegisterResponse(Net::MessageIn &msg);
- void readUpdateHost(Net::MessageIn &msg);
+ void readServerInfo(Net::MessageIn &msg);
LoginData *mLoginData;
unsigned int mMinUserNameLength;
diff --git a/src/net/manaserv/protocol.h b/src/net/manaserv/manaserv_protocol.h
index 226a27a0..b5023a42 100644
--- a/src/net/manaserv/protocol.h
+++ b/src/net/manaserv/manaserv_protocol.h
@@ -22,6 +22,10 @@
#ifndef MANASERV_PROTOCOL_H
#define MANASERV_PROTOCOL_H
+namespace ManaServ {
+
+enum { PROTOCOL_VERSION = 1 };
+
/**
* Enumerated type for communicated messages:
*
@@ -44,21 +48,24 @@
enum {
// Login/Register
PAMSG_REGISTER = 0x0000, // D version, S username, S password, S email, S captcha response
- APMSG_REGISTER_RESPONSE = 0x0002, // B error, [S updatehost]
+ APMSG_REGISTER_RESPONSE = 0x0002, // B error, S updatehost, S Client data URL, B Character slots
PAMSG_UNREGISTER = 0x0003, // S username, S password
APMSG_UNREGISTER_RESPONSE = 0x0004, // B error
PAMSG_REQUEST_REGISTER_INFO = 0x0005, //
APMSG_REGISTER_INFO_RESPONSE = 0x0006, // B byte registration Allowed, byte minNameLength, byte maxNameLength, string captchaURL, string captchaInstructions
PAMSG_LOGIN = 0x0010, // D version, S username, S password
- APMSG_LOGIN_RESPONSE = 0x0012, // B error, [S updatehost]
+ APMSG_LOGIN_RESPONSE = 0x0012, // B error, S updatehost, S Client data URL, B Character slots
PAMSG_LOGOUT = 0x0013, // -
APMSG_LOGOUT_RESPONSE = 0x0014, // B error
- PAMSG_CHAR_CREATE = 0x0020, // S name, B hair style, B hair color, B gender, W*6 stats
+ PAMSG_CHAR_CREATE = 0x0020, // S name, B hair style, B hair color, B gender, B slot, {W stats}*
APMSG_CHAR_CREATE_RESPONSE = 0x0021, // B error
- PAMSG_CHAR_DELETE = 0x0022, // B index
+ PAMSG_CHAR_DELETE = 0x0022, // B slot
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
- PAMSG_CHAR_SELECT = 0x0026, // B index
+ // B slot, 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 slot
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
APMSG_EMAIL_CHANGE_RESPONSE = 0x0031, // B error
@@ -86,18 +93,19 @@ 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
+ GPMSG_BEING_ENTER = 0x0200, // B type, W being id, B action, W*2 position, B direction
// character: S name, B hair style, B hair color, B gender, B item bitmask, { W item id }*
// monster: W type id
// npc: W type id
@@ -109,8 +117,8 @@ 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_BEINGS_MOVE = 0x0280, // { W being id, B flags [, W*2 position, B speed] }*
+ 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,] W*2 destination, B speed] }*
GPMSG_ITEMS = 0x0281, // { W item id, W*2 position }*
PGMSG_ATTACK = 0x0290, // W being id
GPMSG_BEING_ATTACK = 0x0291, // W being id, B direction, B attacktype
@@ -155,6 +163,7 @@ enum {
GPMSG_BEINGS_DAMAGE = 0x0310, // { W being id, W amount }*
GPMSG_CREATE_EFFECT_POS = 0x0320, // W effect id, W*2 position
GPMSG_CREATE_EFFECT_BEING = 0x0321, // W effect id, W BeingID
+ GPMSG_SHAKE = 0x0330, // W intensityX, W intensityY, [W decay_times_10000, [W duration]]
// Guild
PCMSG_GUILD_CREATE = 0x0350, // S name
@@ -255,7 +264,8 @@ enum {
ERRMSG_ALREADY_TAKEN, // name used was already taken
ERRMSG_SERVER_FULL, // the server is overloaded
ERRMSG_TIME_OUT, // data failed to arrive in due time
- ERRMSG_LIMIT_REACHED // limit reached
+ ERRMSG_LIMIT_REACHED, // limit reached
+ ERRMSG_ADMINISTRATIVE_LOGOFF // kicked by server administrator
};
// used in AGMSG_REGISTER_RESPONSE to show state of item db
@@ -272,10 +282,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,9 +311,10 @@ 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
+ CREATE_TOO_MUCH_CHARACTERS,
+ CREATE_INVALID_SLOT
};
// Character attribute modification specific return value
@@ -342,11 +354,6 @@ enum {
MOVING_DESTINATION = 2
};
-// Email change specific return values
-enum {
- EMAILCHG_EXISTS_EMAIL = 0x40
-};
-
// Chat errors return values
enum {
CHAT_USING_BAD_WORDS = 0x40,
@@ -370,8 +377,54 @@ enum {
GUILD_EVENT_OFFLINE_PLAYER
};
+/**
+ * Moves enum for beings and actors for others players vision.
+ * WARNING: Has to be in sync with the same enum in the Being class
+ * of the client!
+ */
+enum BeingAction
+{
+ STAND,
+ WALK,
+ ATTACK,
+ SIT,
+ DEAD,
+ HURT
+};
-enum
+/**
+ * Moves enum for beings and actors for others players attack types.
+ * WARNING: Has to be in sync with the same enum in the Being class
+ * of the client!
+ */
+enum AttackType
+{
+ HIT = 0x00,
+ CRITICAL = 0x0a,
+ MULTI = 0x08,
+ REFLECT = 0x04,
+ FLEE = 0x0b
+};
+
+/**
+ * Beings and actors directions
+ * WARNING: Has to be in sync with the same enum in the Being class
+ * of the client!
+ */
+enum BeingDirection
+{
+ DOWN = 1,
+ LEFT = 2,
+ UP = 4,
+ RIGHT = 8
+};
+
+/**
+ * enum for sprites layers.
+ * WARNING: Has to be in sync with the same enum in the Sprite class
+ * of the client!
+ */
+enum SpriteLayer
{
SPRITE_BASE = 0,
SPRITE_SHOE,
@@ -383,4 +436,6 @@ enum
SPRITE_VECTOREND
};
+}; // Namespace ManaServ
+
#endif // MANASERV_PROTOCOL_H
diff --git a/src/net/manaserv/messagein.h b/src/net/manaserv/messagein.h
index fe77c436..6d0a4035 100644
--- a/src/net/manaserv/messagein.h
+++ b/src/net/manaserv/messagein.h
@@ -34,9 +34,6 @@ namespace ManaServ {
class MessageIn : public Net::MessageIn
{
public:
- /**
- * Constructor.
- */
MessageIn(const char *data, unsigned int length);
int readInt16(); /**< Reads a short. */
diff --git a/src/net/manaserv/messageout.h b/src/net/manaserv/messageout.h
index 7c474cda..451bc0aa 100644
--- a/src/net/manaserv/messageout.h
+++ b/src/net/manaserv/messageout.h
@@ -29,14 +29,8 @@ namespace ManaServ {
class MessageOut : public Net::MessageOut
{
public:
- /**
- * Constructor.
- */
MessageOut(short id);
- /**
- * Destructor.
- */
~MessageOut();
void writeInt16(Sint16 value); /**< Writes a short. */
diff --git a/src/net/manaserv/network.cpp b/src/net/manaserv/network.cpp
index 636585c9..03bd7b28 100644
--- a/src/net/manaserv/network.cpp
+++ b/src/net/manaserv/network.cpp
@@ -53,11 +53,7 @@ void initialize()
logger->error("Failed to initialize ENet.");
}
-#ifdef ENET_VERSION_MAJOR
client = enet_host_create(NULL, 3, 0, 0, 0);
-#else
- client = enet_host_create(NULL, 3, 0, 0);
-#endif
if (!client)
{
diff --git a/src/net/manaserv/npchandler.cpp b/src/net/manaserv/npchandler.cpp
index 392ec4fd..1c89f39f 100644
--- a/src/net/manaserv/npchandler.cpp
+++ b/src/net/manaserv/npchandler.cpp
@@ -21,16 +21,15 @@
#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 "net/manaserv/manaserv_protocol.h"
+
+#include "utils/stringutils.h"
extern Net::NpcHandler *npcHandler;
@@ -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;
+ 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 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(Event::NpcChannel);
+ break;
+
+ case GPMSG_NPC_NUMBER:
+ event = new Event(Event::IntegerInput);
+ event->setInt("id", npcId);
+ event->setInt("min", msg.readInt32());
+ event->setInt("max", msg.readInt32());
+ event->setInt("default", msg.readInt32());
+ event->trigger(Event::NpcChannel);
+ break;
+
+ case GPMSG_NPC_STRING:
+ event = new Event(Event::StringInput);
+ event->setInt("id", npcId);
+ event->trigger(Event::NpcChannel);
+ break;
+
+ case GPMSG_NPC_POST:
+ event = new Event(Event::Post);
+ event->setInt("id", npcId);
+ event->trigger(Event::NpcChannel);
+ break;
+
+ case GPMSG_NPC_ERROR:
+ event = new Event(Event::End);
+ event->setInt("id", npcId);
+ event->trigger(Event::NpcChannel);
+ break;
+
+ case GPMSG_NPC_MESSAGE:
+ event = new Event(Event::Message);
+ event->setInt("id", npcId);
+ event->setString("text", msg.readString(msg.getUnreadLength()));
+ event->trigger(Event::NpcChannel);
+ delete event;
+
+ event = new Event(Event::Next);
+ event->setInt("id", npcId);
+ event->trigger(Event::NpcChannel);
+ break;
+
+ case GPMSG_NPC_CLOSE:
+ event = new Event(Event::Close);
+ event->setInt("id", npcId);
+ event->trigger(Event::NpcChannel);
+ 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);
+
+ Event event(Event::TalkSent);
+ event.setInt("npcId", npcId);
+ event.trigger(Event::NpcChannel);
}
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);
+
+ Event event(Event::NextSent);
+ event.setInt("npcId", npcId);
+ event.trigger(Event::NpcChannel);
}
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);
- }
+ Event event(Event::CloseSent);
+ event.setInt("npcId", npcId);
+ event.trigger(Event::NpcChannel);
}
-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);
+
+ Event event(Event::MenuSent);
+ event.setInt("npcId", npcId);
+ event.setInt("choice", choice);
+ event.trigger(Event::NpcChannel);
}
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);
+
+ Event event(Event::IntegerInputSent);
+ event.setInt("npcId", npcId);
+ event.setInt("value", value);
+ event.trigger(Event::NpcChannel);
}
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);
+
+ Event event(Event::StringInputSent);
+ event.setInt("npcId", npcId);
+ event.setString("value", value);
+ event.trigger(Event::NpcChannel);
}
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();
+ Event event(Event::SendLetterSent);
+ event.setInt("npcId", npcId);
+ event.setString("recipient", recipient);
+ event.setString("text", text);
+ event.trigger(Event::NpcChannel);
}
} // namespace ManaServ
diff --git a/src/net/manaserv/npchandler.h b/src/net/manaserv/npchandler.h
index 689fdc1d..bda4de31 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 "eventlistener.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..b30d5391 100644
--- a/src/net/manaserv/partyhandler.cpp
+++ b/src/net/manaserv/partyhandler.cpp
@@ -21,17 +21,16 @@
#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"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
#include "utils/gettext.h"
#include "utils/stringutils.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..4249bac8 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/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();
+ Event::trigger(Event::NpcChannel, 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)
@@ -405,10 +412,35 @@ int PlayerHandler::getJobLocation()
return -1;
}
-Vector PlayerHandler::getDefaultWalkSpeed()
+Vector PlayerHandler::getDefaultMoveSpeed() const
{
- // Return translation in pixels per ticks.
- return ManaServ::BeingHandler::giveSpeedInPixelsPerTicks(6.0f);
+ // Return default speed at 6 tiles per second.
+ return Vector(6.0f, 6.0f, 0.0f);
+}
+
+Vector PlayerHandler::getPixelsPerTickMoveSpeed(const Vector &speed, Map *map)
+{
+ Vector speedInTicks;
+
+ Game *game = Game::instance();
+ if (game && !map)
+ map = game->getCurrentMap();
+
+ if (!map)
+ {
+ logger->log("Manaserv::PlayerHandler: Speed wasn't given back"
+ " because Map not initialized.");
+ return speedInTicks;
+ }
+
+ speedInTicks.x = speed.x
+ * (float)map->getTileWidth()
+ / 1000 * (float) MILLISECONDS_IN_A_TICK;
+ speedInTicks.y = speed.y
+ * (float)map->getTileHeight()
+ / 1000 * (float) MILLISECONDS_IN_A_TICK;
+
+ return speedInTicks;
}
} // namespace ManaServ
diff --git a/src/net/manaserv/playerhandler.h b/src/net/manaserv/playerhandler.h
index 5796b0d3..3e3f8aad 100644
--- a/src/net/manaserv/playerhandler.h
+++ b/src/net/manaserv/playerhandler.h
@@ -65,7 +65,12 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler
int getJobLocation();
- Vector getDefaultWalkSpeed();
+ Vector getDefaultMoveSpeed() const;
+
+ Vector getPixelsPerTickMoveSpeed(const Vector &speed, Map *map = 0);
+
+ bool usePixelPrecision()
+ { return true; }
private:
void handleMapChangeMessage(Net::MessageIn &msg);
diff --git a/src/net/manaserv/specialhandler.cpp b/src/net/manaserv/specialhandler.cpp
index 144111c2..11d361c8 100644
--- a/src/net/manaserv/specialhandler.cpp
+++ b/src/net/manaserv/specialhandler.cpp
@@ -24,7 +24,7 @@
#include "net/manaserv/connection.h"
#include "net/manaserv/messagein.h"
#include "net/manaserv/messageout.h"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
extern Net::SpecialHandler *specialHandler;
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..6e205e24 100644
--- a/src/net/manaserv/tradehandler.cpp
+++ b/src/net/manaserv/tradehandler.cpp
@@ -21,21 +21,21 @@
#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"
#include "net/manaserv/messagein.h"
#include "net/manaserv/messageout.h"
-#include "net/manaserv/protocol.h"
+#include "net/manaserv/manaserv_protocol.h"
#include "utils/gettext.h"
#include "utils/stringutils.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)