summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-08-19 15:58:52 +0200
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-03-07 22:27:48 +0100
commitca0b74e0f52aef36b929a2059fab62c192c620f6 (patch)
tree14f0c461df4a3ec14a03187e8987be0f79215bcd /src
parent9d1c20860e8a5b8e7d5a4fb53c2ddb1c372bad7f (diff)
downloadmana-ca0b74e0f52aef36b929a2059fab62c192c620f6.tar.gz
mana-ca0b74e0f52aef36b929a2059fab62c192c620f6.tar.bz2
mana-ca0b74e0f52aef36b929a2059fab62c192c620f6.tar.xz
mana-ca0b74e0f52aef36b929a2059fab62c192c620f6.zip
Updated manaserv protocol to version 9
This extends the messages regarding abilities, replacing the specific "attack" messages. It also unifies attribute handling, with a generic system replacing specific variables for attributes like level, xp and skills. The inventory and equipment handling was adjusted such that equipped items stay in the inventory. Support for quest states was added. Added: * GPMSG_ABILITY_REMOVED (mana/manaserv@e3fcc1a47db312933a0f5b7e725c5779a1a45722) * GPMSG_ABILITY_COOLDOWN (mana/manaserv@c2f00b2f3ba920cb25333d19a1d37d251342caf8) * GPMSG_BEING_ABILITY_POINT * GPMSG_BEING_ABILITY_BEING (mana/manaserv@2f2393b6d190deb8958fcb806b58418508d25e28) * GPMSG_ATTRIBUTE_POINTS_STATUS (mana/manaserv@1e5a15c0a5e24fb4b358fff75a7082d65496e1f9) * PGMSG_USE_ABILITY_ON_DIRECTION (mana/manaserv@05fc955a3f8a03539088fa7569395434e29d90e8) * GPMSG_BEING_ABILITY_DIRECTION (mana/manaserv@54389afd7ba9fecf0761333185145e968e2453ae) * GPMSG_QUESTLOG_STATUS (mana/manaserv@66a98a3a0df795761328d62ef2ad07f81e383f9e) Removed: * PGMSG_ATTACK * GPMSG_BEING_ATTACK (mana/manaserv@f31277b327df701361391b1d4b8bd6f89f4e3109) * GPMSG_PLAYER_EXP_CHANGE * GPMSG_LEVELUP * GPMSG_LEVEL_PROGRESS (mana/manaserv@44ee071d7ece5a2023f79307f36e8a244c9e7b3a) Changed: * GPMSG_ABILITY_STATUS (mana/manaserv@ba573fcc38580a01985172b9bc864c97ce855af3) * GPMSG_BEING_LOOKS_CHANGE (mana/manaserv@8ddda85d923a528c7497a628d2fe10fc40b80a1f) * APMSG_CHAR_INFO (mana/manaserv@4f5053f463fd8da0de1615ca6b0f212f02f3d653) * APMSG_CHAR_CREATE_RESPONSE (mana/manaserv@1263c729d85df649c7ab59726bddad7c8cd7ae81) * GPMSG_NPC_BUYSELL_RESPONSE (mana/manaserv@336ce321a9b996e56a61a5364bb32124efa84dd9) Equipment changes (mana/manaserv@f712d68495dd8e040c32da3b1c85bcb7845543ec): * Changed GPMSG_INVENTORY_FULL, GPMSG_EQUIP * Removed PGMSG_MOVE_ITEM * Added GPMSG_EQUIP_RESPONSE, GPMSG_UNEQUIP_RESPONSE, GPMSG_UNEQUIP While this change deals with some of the protocol changes, there's still many changes required in the UI regarding using of abilities (including attacking), showing of certain attributes and quest log.
Diffstat (limited to 'src')
-rw-r--r--src/gui/abilitieswindow.cpp2
-rw-r--r--src/gui/inventorywindow.h2
-rw-r--r--src/item.h11
-rw-r--r--src/net/abilityhandler.h8
-rw-r--r--src/net/manaserv/abilityhandler.cpp11
-rw-r--r--src/net/manaserv/abilityhandler.h6
-rw-r--r--src/net/manaserv/beinghandler.cpp109
-rw-r--r--src/net/manaserv/beinghandler.h5
-rw-r--r--src/net/manaserv/charhandler.cpp82
-rw-r--r--src/net/manaserv/charhandler.h11
-rw-r--r--src/net/manaserv/gamehandler.cpp4
-rw-r--r--src/net/manaserv/generalhandler.cpp2
-rw-r--r--src/net/manaserv/inventoryhandler.cpp258
-rw-r--r--src/net/manaserv/inventoryhandler.h18
-rw-r--r--src/net/manaserv/loginhandler.cpp2
-rw-r--r--src/net/manaserv/manaserv_protocol.h208
-rw-r--r--src/net/manaserv/npchandler.cpp4
-rw-r--r--src/net/manaserv/playerhandler.cpp43
-rw-r--r--src/net/tmwa/abilityhandler.cpp6
-rw-r--r--src/net/tmwa/abilityhandler.h6
20 files changed, 373 insertions, 425 deletions
diff --git a/src/gui/abilitieswindow.cpp b/src/gui/abilitieswindow.cpp
index c6aefb32..10fed4ba 100644
--- a/src/gui/abilitieswindow.cpp
+++ b/src/gui/abilitieswindow.cpp
@@ -97,7 +97,7 @@ void AbilitiesWindow::action(const gcn::ActionEvent &event)
Being *target = local_player->getTarget();
if (target)
- Net::getAbilityHandler()->use(disp->mInfo->id, 1, target->getId());
+ Net::getAbilityHandler()->useOn(disp->mInfo->id, target->getId());
else
Net::getAbilityHandler()->use(disp->mInfo->id);
}
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index fec576d7..2bd6fe65 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -112,7 +112,7 @@ class InventoryWindow : public Window,
void slotsChanged(Inventory* inventory) override;
- bool isMainInventory() { return mInventory->isMainInventory(); }
+ bool isMainInventory() const { return mInventory->isMainInventory(); }
void event(Event::Channel channel, const Event &event) override;
diff --git a/src/item.h b/src/item.h
index e608bdd6..b08c2f5e 100644
--- a/src/item.h
+++ b/src/item.h
@@ -81,16 +81,6 @@ class Item
bool isEquipped() const { return mEquipped; }
/**
- * Sets whether this item is in equipment.
- */
- void setInEquipment(bool inEquipment) { mInEquipment = inEquipment; }
-
- /**
- * Returns whether this item is in equipment.
- */
- bool isInEquipment() const { return mInEquipment; }
-
- /**
* Returns whether this item is equippable.
*/
bool isEquippable() const;
@@ -119,6 +109,5 @@ class Item
ResourceRef<Image> mImage; /**< Item image. */
int mQuantity; /**< Number of items. */
bool mEquipped; /**< Item is equipped. */
- bool mInEquipment = false; /**< Item is in equipment */
int mInvIndex; /**< Inventory index. */
};
diff --git a/src/net/abilityhandler.h b/src/net/abilityhandler.h
index 6e3526bb..8e61d0c5 100644
--- a/src/net/abilityhandler.h
+++ b/src/net/abilityhandler.h
@@ -21,8 +21,6 @@
#pragma once
-#include <iosfwd>
-
namespace Net {
class AbilityHandler
@@ -32,11 +30,11 @@ class AbilityHandler
virtual void use(int id) = 0;
- virtual void use(int id, int level, int beingId) = 0;
+ virtual void useOn(int id, int beingId) = 0;
- virtual void use(int id, int level, int x, int y) = 0;
+ virtual void useAt(int id, int x, int y) = 0;
- virtual void use(int id, const std::string &map) = 0;
+ virtual void useInDirection(int id, int direction) = 0;
};
} // namespace Net
diff --git a/src/net/manaserv/abilityhandler.cpp b/src/net/manaserv/abilityhandler.cpp
index b5ce9d2e..a9ce8e37 100644
--- a/src/net/manaserv/abilityhandler.cpp
+++ b/src/net/manaserv/abilityhandler.cpp
@@ -50,7 +50,7 @@ void AbilityHandler::use(int id)
gameServerConnection->send(msg);
}
-void AbilityHandler::use(int id, int level, int beingId)
+void AbilityHandler::useOn(int id, int beingId)
{
MessageOut msg(PGMSG_USE_ABILITY_ON_BEING);
msg.writeInt8(id);
@@ -58,7 +58,7 @@ void AbilityHandler::use(int id, int level, int beingId)
gameServerConnection->send(msg);
}
-void AbilityHandler::use(int id, int level, int x, int y)
+void AbilityHandler::useAt(int id, int x, int y)
{
MessageOut msg(PGMSG_USE_ABILITY_ON_POINT);
msg.writeInt8(id);
@@ -67,9 +67,12 @@ void AbilityHandler::use(int id, int level, int x, int y)
gameServerConnection->send(msg);
}
-void AbilityHandler::use(int id, const std::string &map)
+void AbilityHandler::useInDirection(int id, int direction)
{
- // TODO
+ MessageOut msg(PGMSG_USE_ABILITY_ON_DIRECTION);
+ msg.writeInt8(id);
+ msg.writeInt8(direction);
+ gameServerConnection->send(msg);
}
} // namespace ManaServ
diff --git a/src/net/manaserv/abilityhandler.h b/src/net/manaserv/abilityhandler.h
index 69ab9c2b..e8263989 100644
--- a/src/net/manaserv/abilityhandler.h
+++ b/src/net/manaserv/abilityhandler.h
@@ -36,11 +36,11 @@ class AbilityHandler final : public MessageHandler, public Net::AbilityHandler
void use(int id) override;
- void use(int id, int level, int beingId) override;
+ void useOn(int id, int beingId) override;
- void use(int id, int level, int x, int y) override;
+ void useAt(int id, int x, int y) override;
- void use(int id, const std::string &map) override;
+ void useInDirection(int id, int direction) override;
};
} // namespace ManaServ
diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp
index 186239c1..d8f47297 100644
--- a/src/net/manaserv/beinghandler.cpp
+++ b/src/net/manaserv/beinghandler.cpp
@@ -23,6 +23,7 @@
#include "actorspritemanager.h"
#include "being.h"
+#include "effectmanager.h"
#include "localplayer.h"
#include "gui/okdialog.h"
@@ -34,6 +35,8 @@
#include "net/manaserv/playerhandler.h"
#include "net/manaserv/manaserv_protocol.h"
+#include "playerrelations.h"
+#include "resources/emotedb.h"
#include "resources/hairdb.h"
#include "utils/gettext.h"
@@ -45,10 +48,13 @@ namespace ManaServ {
BeingHandler::BeingHandler()
{
static const Uint16 _messages[] = {
- GPMSG_BEING_ATTACK,
GPMSG_BEING_ENTER,
GPMSG_BEING_LEAVE,
+ GPMSG_BEING_EMOTE,
GPMSG_BEINGS_MOVE,
+ GPMSG_BEING_ABILITY_POINT,
+ GPMSG_BEING_ABILITY_BEING,
+ GPMSG_BEING_ABILITY_DIRECTION,
GPMSG_BEINGS_DAMAGE,
GPMSG_BEING_ACTION_CHANGE,
GPMSG_BEING_LOOKS_CHANGE,
@@ -68,11 +74,20 @@ void BeingHandler::handleMessage(MessageIn &msg)
case GPMSG_BEING_LEAVE:
handleBeingLeaveMessage(msg);
break;
+ case GPMSG_BEING_EMOTE:
+ handleBeingEmoteMessage(msg);
+ break;
case GPMSG_BEINGS_MOVE:
handleBeingsMoveMessage(msg);
break;
- case GPMSG_BEING_ATTACK:
- handleBeingAttackMessage(msg);
+ case GPMSG_BEING_ABILITY_POINT:
+ handleBeingAbilityPointMessage(msg);
+ break;
+ case GPMSG_BEING_ABILITY_BEING:
+ handleBeingAbilityBeingMessage(msg);
+ break;
+ case GPMSG_BEING_ABILITY_DIRECTION:
+ handleBeingAbilityDirectionMessage(msg);
break;
case GPMSG_BEINGS_DAMAGE:
handleBeingsDamageMessage(msg);
@@ -91,11 +106,15 @@ void BeingHandler::handleMessage(MessageIn &msg)
static void handleLooks(Being *being, MessageIn &msg)
{
- int lookChanges = msg.readInt8();
+ const int hairStyle = msg.readInt8();
+ const int hairColor = msg.readInt8();
+ being->setSprite(SPRITE_LAYER_HAIR, hairStyle * -1,
+ hairDB.getHairColor(hairColor));
- if (lookChanges <= 0)
+ if (msg.getUnreadLength() < 1)
return;
+ int lookChanges = msg.readInt8();
while (lookChanges-- > 0)
{
unsigned int slotTypeId = msg.readInt8();
@@ -113,14 +132,19 @@ void BeingHandler::handleBeingEnterMessage(MessageIn &msg)
int px = msg.readInt16();
int py = msg.readInt16();
auto direction = (BeingDirection)msg.readInt8();
- Gender gender;
- int genderAsInt = msg.readInt8();
- if (genderAsInt == GENDER_FEMALE)
- gender = Gender::FEMALE;
- else if (genderAsInt == GENDER_MALE)
+
+ Gender gender = Gender::UNSPECIFIED;
+ switch (getGender(msg.readInt8())) {
+ case GENDER_MALE:
gender = Gender::MALE;
- else
- gender = Gender::UNSPECIFIED;
+ break;
+ case GENDER_FEMALE:
+ gender = Gender::FEMALE;
+ break;
+ case GENDER_UNSPECIFIED:
+ break;
+ }
+
Being *being;
switch (type)
@@ -139,9 +163,7 @@ void BeingHandler::handleBeingEnterMessage(MessageIn &msg)
ActorSprite::PLAYER, 0);
being->setName(name);
}
- int hs = msg.readInt8(), hc = msg.readInt8();
- being->setSprite(SPRITE_LAYER_HAIR, hs * -1,
- hairDB.getHairColor(hc));
+
handleLooks(being, msg);
} break;
@@ -152,7 +174,8 @@ void BeingHandler::handleBeingEnterMessage(MessageIn &msg)
being = actorSpriteManager->createBeing(id, type == OBJECT_MONSTER
? ActorSprite::MONSTER : ActorSprite::NPC, subtype);
std::string name = msg.readString();
- if (name.length() > 0) being->setName(name);
+ if (!name.empty())
+ being->setName(name);
} break;
default:
@@ -175,6 +198,19 @@ void BeingHandler::handleBeingLeaveMessage(MessageIn &msg)
actorSpriteManager->destroyActor(being);
}
+void BeingHandler::handleBeingEmoteMessage(MessageIn &msg)
+{
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
+ if (!being)
+ return;
+
+ if (player_relations.hasPermission(being, PlayerPermissions::EMOTE))
+ {
+ const int fx = EmoteDB::get(msg.readInt8() - 1).effectId;
+ effectManager->trigger(fx, being);
+ }
+}
+
void BeingHandler::handleBeingsMoveMessage(MessageIn &msg)
{
while (msg.getUnreadLength())
@@ -235,18 +271,41 @@ void BeingHandler::handleBeingsMoveMessage(MessageIn &msg)
}
}
-void BeingHandler::handleBeingAttackMessage(MessageIn &msg)
+void BeingHandler::handleBeingAbilityPointMessage(MessageIn &msg)
{
Being *being = actorSpriteManager->findBeing(msg.readInt16());
- const auto direction = (BeingDirection) msg.readInt8();
- const int attackId = msg.readInt8();
+ if (!being)
+ return;
+
+ const int abilityId = msg.readInt8();
+ const int x = msg.readInt16();
+ const int y = msg.readInt16();
+
+ std::cout << "GPMSG_BEING_ABILITY_POINT(" << abilityId << ", " << x << ", " << y << ")" << std::endl;
+}
+void BeingHandler::handleBeingAbilityBeingMessage(MessageIn &msg)
+{
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
if (!being)
return;
- being->setDirection(direction);
+ const int abilityId = msg.readInt8();
+ const int targetId = msg.readInt16();
+
+ std::cout << "GPMSG_BEING_ABILITY_BEING(" << abilityId << ", " << targetId << ")" << std::endl;
+}
+
+void BeingHandler::handleBeingAbilityDirectionMessage(MessageIn &msg)
+{
+ Being *being = actorSpriteManager->findBeing(msg.readInt16());
+ if (!being)
+ return;
+
+ const int abilityId = msg.readInt8();
+ const int direction = msg.readInt8();
- being->setAction(Being::ATTACK, attackId);
+ std::cout << "GPMSG_BEING_ABILITY_DIRECTION(" << abilityId << ", " << direction << ")" << std::endl;
}
void BeingHandler::handleBeingsDamageMessage(MessageIn &msg)
@@ -306,14 +365,8 @@ void BeingHandler::handleBeingLooksChangeMessage(MessageIn &msg)
Being *being = actorSpriteManager->findBeing(msg.readInt16());
if (!being || being->getType() != ActorSprite::PLAYER)
return;
+
handleLooks(being, msg);
- if (msg.getUnreadLength())
- {
- int style = msg.readInt16();
- int color = msg.readInt16();
- being->setSprite(SPRITE_LAYER_HAIR, style * -1,
- hairDB.getHairColor(color));
- }
}
void BeingHandler::handleBeingDirChangeMessage(MessageIn &msg)
diff --git a/src/net/manaserv/beinghandler.h b/src/net/manaserv/beinghandler.h
index b906aedd..9580c284 100644
--- a/src/net/manaserv/beinghandler.h
+++ b/src/net/manaserv/beinghandler.h
@@ -43,10 +43,13 @@ class BeingHandler final : public MessageHandler
void handleMessage(MessageIn &msg) override;
private:
- void handleBeingAttackMessage(MessageIn &msg);
void handleBeingEnterMessage(MessageIn &msg);
void handleBeingLeaveMessage(MessageIn &msg);
+ void handleBeingEmoteMessage(MessageIn &msg);
void handleBeingsMoveMessage(MessageIn &msg);
+ void handleBeingAbilityPointMessage(MessageIn &msg);
+ void handleBeingAbilityBeingMessage(MessageIn &msg);
+ void handleBeingAbilityDirectionMessage(MessageIn &msg);
void handleBeingsDamageMessage(MessageIn &msg);
void handleBeingActionChangeMessage(MessageIn &msg);
void handleBeingLooksChangeMessage(MessageIn &msg);
diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp
index 8a922e70..4d44aa93 100644
--- a/src/net/manaserv/charhandler.cpp
+++ b/src/net/manaserv/charhandler.cpp
@@ -99,28 +99,44 @@ void CharHandler::handleMessage(MessageIn &msg)
void CharHandler::handleCharacterInfo(MessageIn &msg)
{
- CachedCharacterInfo info;
- info.slot = msg.readInt8();
- info.name = msg.readString();
- info.gender = msg.readInt8() == ManaServ::GENDER_MALE ? Gender::MALE
- : Gender::FEMALE;
- info.hairStyle = msg.readInt8();
- info.hairColor = msg.readInt8();
- info.level = msg.readInt16();
- info.characterPoints = msg.readInt16();
- info.correctionPoints = msg.readInt16();
-
while (msg.getUnreadLength() > 0)
{
- int id = msg.readInt32();
- CachedAttrbiute attr;
- attr.base = msg.readInt32() / 256.0;
- attr.mod = msg.readInt32() / 256.0;
+ CachedCharacterInfo &info = mCachedCharacterInfos.emplace_back();
- info.attribute[id] = attr;
- }
+ info.slot = msg.readInt8();
+ info.name = msg.readString();
+ switch (getGender(msg.readInt8())) {
+ case GENDER_MALE:
+ info.gender = Gender::MALE;
+ break;
+ case GENDER_FEMALE:
+ info.gender = Gender::FEMALE;
+ break;
+ case GENDER_UNSPECIFIED:
+ info.gender = Gender::UNSPECIFIED;
+ break;
+ }
+ info.hairStyle = msg.readInt8();
+ info.hairColor = msg.readInt8();
+ info.characterPoints = msg.readInt16();
+ info.correctionPoints = msg.readInt16();
- mCachedCharacterInfos.push_back(info);
+ int equipmentCount = msg.readInt8();
+ while (equipmentCount--)
+ {
+ auto &slot = info.equipment.emplace_back();
+ slot.id = msg.readInt16();
+ slot.itemId = msg.readInt16();
+ }
+
+ int attributeCount = msg.readInt8();
+ while (attributeCount--)
+ {
+ CachedAttribute &attr = info.attributes[msg.readInt32()];
+ attr.base = msg.readInt32() / 256.0;
+ attr.mod = msg.readInt32() / 256.0;
+ }
+ }
updateCharacters();
}
@@ -182,6 +198,8 @@ void CharHandler::handleCharacterCreateResponse(MessageIn &msg)
}
else
{
+ handleCharacterInfo(msg);
+
// Close the character create dialog
if (mCharCreateDialog)
{
@@ -380,10 +398,8 @@ void CharHandler::updateCharacters()
return;
// Create new characters and initialize them from the cached infos
- for (unsigned i = 0; i < mCachedCharacterInfos.size(); ++i)
+ for (const auto &info : mCachedCharacterInfos)
{
- const CachedCharacterInfo &info = mCachedCharacterInfos.at(i);
-
auto *character = new Net::Character;
character->slot = info.slot;
LocalPlayer *player = character->dummy = new LocalPlayer;
@@ -391,14 +407,30 @@ void CharHandler::updateCharacters()
player->setGender(info.gender);
player->setSprite(SPRITE_LAYER_HAIR, info.hairStyle * -1,
hairDB.getHairColor(info.hairColor));
- character->data.mAttributes[LEVEL] = info.level;
+
+ for (auto &slot : info.equipment)
+ {
+ player->setSprite(slot.id + FIXED_SPRITE_LAYER_SIZE,
+ slot.itemId,
+ std::string(),
+ Net::getInventoryHandler()->isWeaponSlot(slot.id));
+ }
+
character->data.mAttributes[CHAR_POINTS] = info.characterPoints;
character->data.mAttributes[CORR_POINTS] = info.correctionPoints;
- for (const auto &it : info.attribute)
+ for (const auto &[id, attr] : info.attributes)
{
- character->data.mStats[i].base = it.second.base;
- character->data.mStats[i].mod = it.second.mod;
+ int playerInfoId = Attributes::getPlayerInfoIdFromAttrId(id);
+ if (playerInfoId > -1)
+ {
+ character->data.mAttributes[playerInfoId] = attr.mod;
+ }
+ else
+ {
+ character->data.mStats[id].base = attr.base;
+ character->data.mStats[id].mod = attr.mod;
+ }
}
mCharacters.push_back(character);
diff --git a/src/net/manaserv/charhandler.h b/src/net/manaserv/charhandler.h
index d83ce667..e962bdfa 100644
--- a/src/net/manaserv/charhandler.h
+++ b/src/net/manaserv/charhandler.h
@@ -88,12 +88,15 @@ class CharHandler final : public MessageHandler, public Net::CharHandler
* we have loaded the dynamic data, so we can't resolve load any
* sprites yet.
*/
- struct CachedAttrbiute {
+ struct CachedAttribute {
double base;
double mod;
};
- using CachedAttributes = std::map<int, CachedAttrbiute>;
+ struct EquipmentSlot {
+ int id;
+ int itemId;
+ };
struct CachedCharacterInfo {
int slot;
@@ -101,10 +104,10 @@ class CharHandler final : public MessageHandler, public Net::CharHandler
Gender gender;
int hairStyle;
int hairColor;
- int level;
int characterPoints;
int correctionPoints;
- CachedAttributes attribute;
+ std::vector<EquipmentSlot> equipment;
+ std::map<int, CachedAttribute> attributes;
};
void handleCharacterInfo(MessageIn &msg);
diff --git a/src/net/manaserv/gamehandler.cpp b/src/net/manaserv/gamehandler.cpp
index 1bf4d69f..3dae5640 100644
--- a/src/net/manaserv/gamehandler.cpp
+++ b/src/net/manaserv/gamehandler.cpp
@@ -44,6 +44,7 @@ extern ServerInfo chatServer;
GameHandler::GameHandler()
{
static const Uint16 _messages[] = {
+ GPMSG_CONNECT_RESPONSE,
GPMSG_DISCONNECT_RESPONSE,
0
};
@@ -55,6 +56,9 @@ void GameHandler::handleMessage(MessageIn &msg)
{
switch (msg.getId())
{
+ case GPMSG_CONNECT_RESPONSE:
+ break;
+
case GPMSG_DISCONNECT_RESPONSE:
{
int errMsg = msg.readInt8();
diff --git a/src/net/manaserv/generalhandler.cpp b/src/net/manaserv/generalhandler.cpp
index 1e443c66..b947cff4 100644
--- a/src/net/manaserv/generalhandler.cpp
+++ b/src/net/manaserv/generalhandler.cpp
@@ -182,7 +182,7 @@ void GeneralHandler::event(Event::Channel channel,
{
if (event.getType() == Event::GuiWindowsLoaded)
{
- inventoryWindow->setSplitAllowed(true);
+ inventoryWindow->setSplitAllowed(false);
skillDialog->loadSkills();
PlayerInfo::setAttribute(EXP_NEEDED, 100);
diff --git a/src/net/manaserv/inventoryhandler.cpp b/src/net/manaserv/inventoryhandler.cpp
index 9754beb0..0e822ca0 100644
--- a/src/net/manaserv/inventoryhandler.cpp
+++ b/src/net/manaserv/inventoryhandler.cpp
@@ -43,16 +43,6 @@ extern Net::InventoryHandler *inventoryHandler;
namespace ManaServ {
-struct EquipItemInfo
-{
-
- EquipItemInfo(int itemId, int slotTypeId, int amountUsed):
- mItemId(itemId), mSlotTypeId(slotTypeId), mAmountUsed(amountUsed)
- {}
-
- int mItemId, mSlotTypeId, mAmountUsed;
-};
-
extern Connection *gameServerConnection;
EquipBackend::EquipBackend()
@@ -69,7 +59,10 @@ EquipBackend::~EquipBackend()
Item *EquipBackend::getEquipment(int slotIndex) const
{
auto it = mSlots.find(slotIndex);
- return it == mSlots.end() ? nullptr : it->second.item;
+ if (it == mSlots.end())
+ return nullptr;
+
+ return PlayerInfo::getInventory()->getItem(it->second.inventorySlot);
}
std::string EquipBackend::getSlotName(int slotIndex) const
@@ -80,111 +73,54 @@ std::string EquipBackend::getSlotName(int slotIndex) const
void EquipBackend::triggerUnequip(int slotIndex) const
{
- // First get the itemInstance
- auto it = mSlots.find(slotIndex);
-
- if (it == mSlots.end() || it->second.itemInstance == 0 || !it->second.item)
+ auto item = getEquipment(slotIndex);
+ if (!item)
return;
Event event(Event::DoUnequip);
- event.setItem("item", it->second.item);
- event.setInt("itemInstance", it->second.itemInstance);
+ event.setItem("item", item);
event.trigger(Event::ItemChannel);
}
-
void EquipBackend::clear()
{
- for (auto &slot : mSlots)
- {
- if (slot.second.item)
- {
- delete slot.second.item;
- slot.second.item = nullptr;
- }
- }
mSlots.clear();
}
-void EquipBackend::equip(int itemId, int slotTypeId, int amountUsed,
- int itemInstance)
+void EquipBackend::equip(int inventorySlot, int equipmentSlot)
{
- if (itemInstance <= 0)
- {
- logger->log("ManaServ::EquipBackend: Equipment slot %i"
- " has an invalid item instance.", slotTypeId);
- return;
- }
-
- auto it = mSlots.begin();
- auto it_end = mSlots.end();
- bool slotTypeFound = false;
- for (; it != it_end; ++it)
- if (it->second.slotTypeId == (unsigned)slotTypeId)
- slotTypeFound = true;
-
- if (!slotTypeFound)
+ auto slotIt = mSlots.find(equipmentSlot);
+ if (slotIt == mSlots.end())
{
logger->log("ManaServ::EquipBackend: Equipment slot %i"
- " is not existing.", slotTypeId);
+ " is not existing.",
+ equipmentSlot);
return;
}
- if (!itemDb->exists(itemId))
- {
- logger->log("ManaServ::EquipBackend: No item with id %d",
- itemId);
- return;
- }
+ slotIt->second.inventorySlot = inventorySlot;
- // Place the item in the slots with corresponding id until
- // the capacity requested has been reached
- for (it = mSlots.begin(); it != it_end && amountUsed > 0; ++it)
- {
- // If we're on the right slot type and that its unit
- // isn't already equipped, we can equip there.
- // The slots are already sorted by id, and subId anyway.
- if (it->second.slotTypeId == (unsigned)slotTypeId
- && (!it->second.itemInstance) && (!it->second.item))
- {
- it->second.itemInstance = itemInstance;
- it->second.item = new Item(itemId, 1, true);
- --amountUsed;
- }
- }
+ if (auto item = PlayerInfo::getInventory()->getItem(inventorySlot))
+ item->setEquipped(true);
}
-void EquipBackend::unequip(int itemInstance)
+void EquipBackend::unequip(int inventorySlot)
{
- auto it = mSlots.begin();
- auto it_end = mSlots.end();
- bool itemInstanceFound = false;
- for (; it != it_end; ++it)
- if (it->second.itemInstance == (unsigned)itemInstance)
- itemInstanceFound = true;
-
- if (!itemInstanceFound)
+ for (auto &[_, slot] : mSlots)
{
- logger->log("ManaServ::EquipBackend: Equipment item instance %i"
- " is not existing. The item couldn't be unequipped!",
- itemInstance);
- return;
- }
+ if (slot.inventorySlot == inventorySlot)
+ {
+ slot.inventorySlot = -1;
- for (it = mSlots.begin(); it != it_end; ++it)
- {
- if (it->second.itemInstance != (unsigned)itemInstance)
- continue;
+ if (auto item = PlayerInfo::getInventory()->getItem(inventorySlot))
+ item->setEquipped(false);
- // We remove the item
- it->second.itemInstance = 0;
- // We also delete the item objects
- if (it->second.item)
- {
- delete it->second.item;
- it->second.item = nullptr;
+ return;
}
}
+
+ logger->log("ManaServ::EquipBackend: No equipped item found at inventory "
+ "slot %i!", inventorySlot);
}
void EquipBackend::event(Event::Channel, const Event &event)
@@ -245,7 +181,7 @@ void EquipBackend::readEquipFile()
}
slot.subId = i;
- mSlots.insert(std::make_pair(slotIndex, slot));
+ mSlots.insert(std::make_pair(slotIndex, std::move(slot)));
++slotIndex;
}
}
@@ -262,10 +198,10 @@ void EquipBackend::readBoxNode(XML::Node slotNode)
if (boxNode.name() != "box")
continue;
- int x = boxNode.getProperty("x" , 0);
- int y = boxNode.getProperty("y" , 0);
+ const int x = boxNode.getProperty("x" , 0);
+ const int y = boxNode.getProperty("y" , 0);
- mBoxesPositions.push_back(Position(x, y));
+ mBoxesPositions.emplace_back(x, y);
std::string backgroundFile =
boxNode.getProperty("background" , std::string());
@@ -313,6 +249,7 @@ InventoryHandler::InventoryHandler()
GPMSG_INVENTORY_FULL,
GPMSG_INVENTORY,
GPMSG_EQUIP,
+ GPMSG_UNEQUIP,
0
};
handledMessages = _messages;
@@ -331,43 +268,16 @@ void InventoryHandler::handleMessage(MessageIn &msg)
int count = msg.readInt16();
while (count--)
{
- int slot = msg.readInt16();
- int id = msg.readInt16();
- int amount = msg.readInt16();
- PlayerInfo::setInventoryItem(slot, id, amount);
- }
-
- // A map of { item instance, {slot type id, item id, amount used}}
- std::map<int, EquipItemInfo> equipItemsInfo;
- std::map<int, EquipItemInfo>::iterator it;
- while (msg.getUnreadLength())
- {
- int slotTypeId = msg.readInt16();
- int itemId = msg.readInt16();
- int itemInstance = msg.readInt16();
-
- // Turn the data received into a usable format
- it = equipItemsInfo.find(itemInstance);
- if (it == equipItemsInfo.end())
- {
- // Add a new entry
- equipItemsInfo.insert(std::make_pair(itemInstance,
- EquipItemInfo(itemId, slotTypeId, 1)));
- }
+ const int slot = msg.readInt16();
+ const int itemId = msg.readInt16();
+ const int amount = msg.readInt16();
+ const int equipmentSlot = msg.readInt16();
+ PlayerInfo::setInventoryItem(slot, itemId, amount);
+
+ if (equipmentSlot > 0)
+ mEquipBackend.equip(slot, equipmentSlot);
else
- {
- // Add amount to the existing entry
- it->second.mAmountUsed++;
- }
- }
-
- for (it = equipItemsInfo.begin(); it != equipItemsInfo.end();
- ++it)
- {
- mEquipBackend.equip(it->second.mItemId,
- it->second.mSlotTypeId,
- it->second.mAmountUsed,
- it->first);
+ mEquipBackend.unequip(slot);
}
}
break;
@@ -375,43 +285,24 @@ void InventoryHandler::handleMessage(MessageIn &msg)
case GPMSG_INVENTORY:
while (msg.getUnreadLength())
{
- unsigned int slot = msg.readInt16();
- int id = msg.readInt16();
- unsigned int amount = id ? msg.readInt16() : 0;
+ const unsigned int slot = msg.readInt16();
+ const int id = msg.readInt16();
+ const unsigned int amount = id ? msg.readInt16() : 0;
PlayerInfo::setInventoryItem(slot, id, amount);
}
break;
case GPMSG_EQUIP:
{
- int itemId = msg.readInt16();
- int equipSlotCount = msg.readInt16();
-
- if (equipSlotCount <= 0)
- break;
-
- // Otherwise equip the item in the given slots
- while (equipSlotCount--)
- {
- unsigned int parameter = msg.readInt16();
- unsigned int amountUsed = msg.readInt16();
-
- if (amountUsed == 0)
- {
- // No amount means to unequip this item
- // Note that in that case, the parameter is
- // in fact the itemInstanceId
- mEquipBackend.unequip(parameter);
- }
- else
- {
- int itemInstance = msg.readInt16();
- // The parameter is in that case the slot type id.
- mEquipBackend.equip(itemId, parameter,
- amountUsed, itemInstance);
- }
- }
+ const int inventorySlot = msg.readInt16();
+ const int equipmentSlot = msg.readInt16();
+ mEquipBackend.equip(inventorySlot, equipmentSlot);
+ }
+ case GPMSG_UNEQUIP:
+ {
+ const int inventorySlot = msg.readInt16();
+ mEquipBackend.unequip(inventorySlot);
}
break;
}
@@ -423,9 +314,7 @@ void InventoryHandler::event(Event::Channel channel,
if (channel == Event::ItemChannel)
{
Item *item = event.getItem("item");
- int itemInstance = event.getInt("itemInstance", 0);
-
- if (!item && itemInstance == 0)
+ if (!item)
return;
int index = item->getInvIndex();
@@ -439,7 +328,7 @@ void InventoryHandler::event(Event::Channel channel,
else if (event.getType() == Event::DoUnequip)
{
MessageOut msg(PGMSG_UNEQUIP);
- msg.writeInt16(itemInstance);
+ msg.writeInt16(index);
gameServerConnection->send(msg);
}
else if (event.getType() == Event::DoUse)
@@ -457,51 +346,12 @@ void InventoryHandler::event(Event::Channel channel,
msg.writeInt16(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.writeInt16(index);
- msg.writeInt16(newIndex);
- msg.writeInt16(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.writeInt16(index);
- msg.writeInt16(newIndex);
- msg.writeInt16(item->getQuantity());
- gameServerConnection->send(msg);
- }
- else
- {
- /*int source = event.getInt("source");
- int destination = event.getInt("destination");
- int amount = event.getInt("amount", 1);*/
-
- // TODO Support drag'n'drop to the map ground, or with other
- // windows.
- }
- }
}
}
bool InventoryHandler::canSplit(const Item *item)
{
- return item && item->getQuantity() > 1;
+ return false;
}
size_t InventoryHandler::getSize(int type) const
diff --git a/src/net/manaserv/inventoryhandler.h b/src/net/manaserv/inventoryhandler.h
index 98e02391..9402f349 100644
--- a/src/net/manaserv/inventoryhandler.h
+++ b/src/net/manaserv/inventoryhandler.h
@@ -27,6 +27,7 @@
#include "net/manaserv/messagehandler.h"
+#include <map>
#include <vector>
namespace ManaServ {
@@ -35,16 +36,14 @@ class EquipBackend final : public Equipment::Backend, public EventListener
{
public:
EquipBackend();
-
~EquipBackend() override;
Item *getEquipment(int slotIndex) const override;
std::string getSlotName(int slotIndex) const override;
void clear() override;
- void equip(int itemId, int slotTypeId, int amountUsed = 1,
- int itemInstance = 0);
- void unequip(int slotTypeId);
+ void equip(int inventorySlot, int equipmentSlot);
+ void unequip(int inventorySlot);
void event(Event::Channel channel, const Event &event) override;
@@ -72,9 +71,7 @@ class EquipBackend final : public Equipment::Backend, public EventListener
// Generic info
std::string name;
- // The Item reference, used for graphical representation
- // and info.
- Item *item = nullptr;
+ int inventorySlot = 0;
// Manaserv specific info
@@ -88,10 +85,6 @@ class EquipBackend final : public Equipment::Backend, public EventListener
// This is used to sort the multimap along with the slot id.
unsigned int subId = 0;
- // This is the (per character) unique item Id, used especially when
- // equipping the same item multiple times on the same slot type.
- unsigned int itemInstance = 0;
-
// Tell whether the slot is a weapon slot
bool weaponSlot = false;
@@ -102,8 +95,7 @@ class EquipBackend final : public Equipment::Backend, public EventListener
unsigned int mVisibleSlots;
// slot client index, slot info
- using Slots = std::map<unsigned int, Slot>;
- Slots mSlots;
+ std::map<unsigned int, Slot> mSlots;
std::vector<Position> mBoxesPositions;
std::vector<std::string> mBoxesBackgroundFile;
};
diff --git a/src/net/manaserv/loginhandler.cpp b/src/net/manaserv/loginhandler.cpp
index b9a56834..1c398990 100644
--- a/src/net/manaserv/loginhandler.cpp
+++ b/src/net/manaserv/loginhandler.cpp
@@ -399,8 +399,6 @@ void LoginHandler::loginAccount(LoginData *loginData)
mTmpPassword = loginData->password;
MessageOut msg(PAMSG_LOGIN_RNDTRGR);
- msg.writeString(mLoginData->username);
-
accountServerConnection->send(msg);
}
diff --git a/src/net/manaserv/manaserv_protocol.h b/src/net/manaserv/manaserv_protocol.h
index ab81846b..cb27d6f4 100644
--- a/src/net/manaserv/manaserv_protocol.h
+++ b/src/net/manaserv/manaserv_protocol.h
@@ -24,8 +24,9 @@
namespace ManaServ {
enum {
- PROTOCOL_VERSION = 3,
- SUPPORTED_DB_VERSION = 22
+ PROTOCOL_VERSION = 9,
+ MIN_PROTOCOL_VERSION = 9,
+ SUPPORTED_DB_VERSION = 27
};
/**
@@ -68,19 +69,22 @@ enum {
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, S Client data URL, B Character slots
+ APMSG_LOGIN_RESPONSE = 0x0012, // B error, S updatehost, S Client data URL, B Character slots, {content of APMSG_CHAR_CREATE_RESPONSE (without error code)}*
PAMSG_LOGOUT = 0x0013, // -
APMSG_LOGOUT_RESPONSE = 0x0014, // B error
- PAMSG_LOGIN_RNDTRGR = 0x0015, // S username
+ PAMSG_LOGIN_RNDTRGR = 0x0015, // -
APMSG_LOGIN_RNDTRGR_RESPONSE = 0x0016, // S random seed
+ PAMSG_STELLAR_LOGIN = 0x0017, // D version
+ APMSG_STELLAR_LOGIN_RESPONSE = 0x0018, // B error, S token, S url
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
+ APMSG_CHAR_CREATE_RESPONSE = 0x0021, // B error, on success: B slot, S name, B gender, B hair style, B hair color,
+ // W character points, W correction points, B amount of items equipped,
+ // { W slot, W itemId }*
+ // B attributeCount,
+ // {D attr id, D base value (in 1/256ths) D mod value (in 256ths) }*
PAMSG_CHAR_DELETE = 0x0022, // B slot
APMSG_CHAR_DELETE_RESPONSE = 0x0023, // B error
- // 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, // ^
+ APMSG_CHAR_INFO = 0x0024, // {content of APMSG_CHAR_CREATE_RESPONSE (without error code)}*
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
@@ -108,26 +112,28 @@ enum {
PGMSG_DROP = 0x0111, // W slot, W amount
PGMSG_EQUIP = 0x0112, // W inventory slot
PGMSG_UNEQUIP = 0x0113, // W item Instance id
- PGMSG_MOVE_ITEM = 0x0114, // W slot1, W slot2, W amount
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 }, { W equip slot, W item Id, W item Instance}*
- GPMSG_EQUIP = 0x0122, // W item Id, W equip slot type count //{ W equip slot, W capacity used}*//<- When equipping, //{ W item instance, W 0}*//<- When unequipping
+ GPMSG_INVENTORY_FULL = 0x0121, // W inventory slot count { W slot, W itemId, W amount, W equipmentSlot }
+ GPMSG_EQUIP = 0x0122, // W equipped inventory slot, W slot equipmentSlot
+ GPMSG_EQUIP_RESPONSE = 0x0123, // B error, W slot
+ GPMSG_UNEQUIP = 0x0124, // W equipped inventory slot
+ GPMSG_UNEQUIP_RESPONSE = 0x0125, // B error, W slot
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, W skill level }*
- GPMSG_LEVELUP = 0x0150, // W new level, W character points, W correction points
- GPMSG_LEVEL_PROGRESS = 0x0151, // B percent completed to next levelup
+ GPMSG_ATTRIBUTE_POINTS_STATUS = 0x0140, // W character points, W correction points
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, B direction, B gender
- // character: S name, B hair style, B hair color, B sprite layers changed, { B slot type, W item id }*
+ // character: S name, B hair style, B hair color [, B sprite layers changed, { B slot type, W item id }*]
// monster: W type id
// npc: W type id
GPMSG_BEING_LEAVE = 0x0201, // W being id
GPMSG_ITEM_APPEAR = 0x0202, // W item id, W*2 position
- GPMSG_BEING_LOOKS_CHANGE = 0x0210, // B sprite layers changed, { B slot type, W item id }*
+ GPMSG_BEING_LOOKS_CHANGE = 0x0210, // B hairstyle, B haircolor [, B sprite layers changed, { B slot type, W item id }*]
+ GPMSG_BEING_EMOTE = 0x0211, // W being id, W emote id
+ PGMSG_BEING_EMOTE = 0x0212, // W emoticon id
PGMSG_WALK = 0x0260, // W*2 destination
PGMSG_ACTION_CHANGE = 0x0270, // B Action
GPMSG_BEING_ACTION_CHANGE = 0x0271, // W being id, B action
@@ -136,46 +142,50 @@ enum {
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 attack Id
- PGMSG_USE_ABILITY_ON_BEING = 0x0292, // B abilityID, W being id
- GPMSG_ABILITY_STATUS = 0x0293, // { B abilityID, D current, D max, D recharge }
- PGMSG_USE_ABILITY_ON_POINT = 0x0294, // B abilityID, W*2 position
- GPMSG_ABILITY_REMOVED = 0x0295, // B abilityID
- PGMSG_SAY = 0x02A0, // S text
- GPMSG_SAY = 0x02A1, // W being id, S text
- GPMSG_NPC_CHOICE = 0x02B0, // W being id, { S text }*
- GPMSG_NPC_MESSAGE = 0x02B1, // W being id, B* text
- PGMSG_NPC_TALK = 0x02B2, // W being id
- PGMSG_NPC_TALK_NEXT = 0x02B3, // W being id
- PGMSG_NPC_SELECT = 0x02B4, // W being id, B choice
- GPMSG_NPC_BUY = 0x02B5, // W being id, { W item id, W amount, W cost }*
- GPMSG_NPC_SELL = 0x02B6, // W being id, { W item id, W amount, W cost }*
- PGMSG_NPC_BUYSELL = 0x02B7, // W item id, W amount
- GPMSG_NPC_ERROR = 0x02B8, // B error
- GPMSG_NPC_CLOSE = 0x02B9, // W being id
+ GPMSG_BEING_ABILITY_POINT = 0x0282, // W being id, B abilityId, W*2 point
+ GPMSG_BEING_ABILITY_BEING = 0x0283, // W being id, B abilityId, W target being id
+ GPMSG_BEING_ABILITY_DIRECTION = 0x0284, // W being id, B abilityId, B direction
+ PGMSG_USE_ABILITY_ON_BEING = 0x0290, // B abilityID, W being id
+ PGMSG_USE_ABILITY_ON_POINT = 0x0291, // B abilityID, W*2 position
+ PGMSG_USE_ABILITY_ON_DIRECTION = 0x0292, // B abilityID, B direction
+ GPMSG_ABILITY_STATUS = 0x02A0, // { B abilityID, D remainingTicks }
+ GPMSG_ABILITY_REMOVED = 0x02A1, // B abilityID
+ GPMSG_ABILITY_COOLDOWN = 0x02A2, // W ticks to wait
+ PGMSG_SAY = 0x02B0, // S text
+ GPMSG_SAY = 0x02B1, // W being id, S text
+ GPMSG_NPC_CHOICE = 0x02C0, // W being id, { S text }*
+ GPMSG_NPC_MESSAGE = 0x02C1, // W being id, B* text
+ PGMSG_NPC_TALK = 0x02C2, // W being id
+ PGMSG_NPC_TALK_NEXT = 0x02C3, // W being id
+ PGMSG_NPC_SELECT = 0x02C4, // W being id, B choice
+ GPMSG_NPC_BUY = 0x02C5, // W being id, { W item id, W amount, W cost }*
+ GPMSG_NPC_SELL = 0x02C6, // W being id, { W item id, W amount, W cost }*
+ PGMSG_NPC_BUYSELL = 0x02C7, // W item id, W amount
+ GPMSG_NPC_ERROR = 0x02C8, // B error
+ GPMSG_NPC_CLOSE = 0x02C9, // W being id
GPMSG_NPC_POST = 0x02D0, // W being id
PGMSG_NPC_POST_SEND = 0x02D1, // W being id, { S name, S text, W item id }
GPMSG_NPC_POST_GET = 0x02D2, // W being id, { S name, S text, W item id }
PGMSG_NPC_NUMBER = 0x02D3, // W being id, D number
PGMSG_NPC_STRING = 0x02D4, // W being id, S string
- GPMSG_NPC_NUMBER = 0x02D5, // W being id, D max, D min, D default
+ GPMSG_NPC_NUMBER = 0x02D5, // W being id, D min, D max, D default
GPMSG_NPC_STRING = 0x02D6, // W being id
- PGMSG_TRADE_REQUEST = 0x02C0, // W being id
- GPMSG_TRADE_REQUEST = 0x02C1, // W being id
- GPMSG_TRADE_START = 0x02C2, // -
- GPMSG_TRADE_COMPLETE = 0x02C3, // -
- PGMSG_TRADE_CANCEL = 0x02C4, // -
- GPMSG_TRADE_CANCEL = 0x02C5, // -
- PGMSG_TRADE_AGREED = 0x02C6, // -
- GPMSG_TRADE_AGREED = 0x02C7, // -
- PGMSG_TRADE_CONFIRM = 0x02C8, // -
- GPMSG_TRADE_CONFIRM = 0x02C9, // -
- PGMSG_TRADE_ADD_ITEM = 0x02CA, // B slot, B amount
- GPMSG_TRADE_ADD_ITEM = 0x02CB, // W item id, B amount
- PGMSG_TRADE_SET_MONEY = 0x02CC, // D amount
- GPMSG_TRADE_SET_MONEY = 0x02CD, // D amount
- GPMSG_TRADE_BOTH_CONFIRM = 0x02CE, // -
+ GPMSG_NPC_BUYSELL_RESPONSE = 0x02D7, // B error, W item id, W amount
+ PGMSG_TRADE_REQUEST = 0x02E0, // W being id
+ GPMSG_TRADE_REQUEST = 0x02E1, // W being id
+ GPMSG_TRADE_START = 0x02E2, // -
+ GPMSG_TRADE_COMPLETE = 0x02E3, // -
+ PGMSG_TRADE_CANCEL = 0x02E4, // -
+ GPMSG_TRADE_CANCEL = 0x02E5, // -
+ PGMSG_TRADE_AGREED = 0x02E6, // -
+ GPMSG_TRADE_AGREED = 0x02E7, // -
+ PGMSG_TRADE_CONFIRM = 0x02E8, // -
+ GPMSG_TRADE_CONFIRM = 0x02E9, // -
+ PGMSG_TRADE_ADD_ITEM = 0x02EA, // B slot, B amount
+ GPMSG_TRADE_ADD_ITEM = 0x02EB, // W item id, B amount
+ PGMSG_TRADE_SET_MONEY = 0x02EC, // D amount
+ GPMSG_TRADE_SET_MONEY = 0x02ED, // D amount
+ GPMSG_TRADE_BOTH_CONFIRM = 0x02EE, // -
PGMSG_USE_ITEM = 0x0300, // B slot
GPMSG_USE_RESPONSE = 0x0301, // B error
GPMSG_BEINGS_DAMAGE = 0x0310, // { W being id, W amount }*
@@ -243,8 +253,11 @@ enum {
PCMSG_USER_MODE = 0x0465, // W channel id, S name, B mode
PCMSG_KICK_USER = 0x0466, // W channel id, S name
+ // -- Questlog
+ GPMSG_QUESTLOG_STATUS = 0x0470, // {W quest id, B flags, [B status], [S questname], [S questdescription]}*
+
// Inter-server
- GAMSG_REGISTER = 0x0500, // S address, W port, S password, D items db revision, { W map id }*
+ GAMSG_REGISTER = 0x0500, // S address, W port, S password, D items db revision
AGMSG_REGISTER_RESPONSE = 0x0501, // W item version, W password response, { S globalvar_key, S globalvar_value }
AGMSG_ACTIVE_MAP = 0x0502, // W map id, W Number of mapvar_key mapvar_value sent, { S mapvar_key, S mapvar_value }, W Number of map items, { D item Id, W amount, W posX, W posY }
AGMSG_PLAYER_ENTER = 0x0510, // B*32 token, D id, S name, serialised character data
@@ -263,7 +276,6 @@ enum {
GAMSG_SET_VAR_WORLD = 0x0547, // S name, S value
AGMSG_SET_VAR_WORLD = 0x0548, // S name, S value
GAMSG_BAN_PLAYER = 0x0550, // D id, W duration
- GAMSG_CHANGE_PLAYER_LEVEL = 0x0555, // D id, W level
GAMSG_CHANGE_ACCOUNT_LEVEL = 0x0556, // D id, W level
GAMSG_STATISTICS = 0x0560, // { W map id, W entity nb, W monster nb, W player nb, { D character id }* }*
CGMSG_CHANGED_PARTY = 0x0590, // D character id, D party id
@@ -295,7 +307,8 @@ enum {
ERRMSG_TIME_OUT, // data failed to arrive in due time
ERRMSG_LIMIT_REACHED, // limit reached
ERRMSG_ADMINISTRATIVE_LOGOFF, // kicked by server administrator
- ERRMSG_ALREADY_MEMBER // is already member of guild/party
+ ERRMSG_ALREADY_MEMBER, // is already member of guild/party
+ ERRMSG_LOGIN_WAS_TAKEN_OVER // a different connection took over
};
// used in AGMSG_REGISTER_RESPONSE to show state of item db
@@ -314,7 +327,6 @@ enum {
enum {
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 0 = offline, 1 = online
};
@@ -358,21 +370,18 @@ enum AttribmodResponseCode {
enum EntityType
{
// A simple item.
- OBJECT_ITEM = 0,
- // An item that toggle map/quest actions (doors, switchs, ...)
- // and can speak (map panels).
- OBJECT_ACTOR,
+ OBJECT_ITEM = 0,
// Non-Playable-Character is an actor capable of movement and maybe actions.
- OBJECT_NPC,
+ OBJECT_NPC = 2,
// A monster (moving actor with AI. Should be able to toggle map/quest
// actions, too).
- OBJECT_MONSTER,
+ OBJECT_MONSTER = 3,
// A normal being.
- OBJECT_CHARACTER,
+ OBJECT_CHARACTER = 4,
// A effect to be shown.
- OBJECT_EFFECT,
+ OBJECT_EFFECT = 5,
// Server-only object.
- OBJECT_OTHER
+ OBJECT_OTHER = 6
};
// Moving object flags
@@ -406,6 +415,13 @@ enum {
GUILD_EVENT_OFFLINE_PLAYER
};
+enum {
+ QUESTLOG_UPDATE_STATE = 1,
+ QUESTLOG_UPDATE_TITLE = 2,
+ QUESTLOG_UPDATE_DESCRIPTION = 4,
+ QUESTLOG_SHOW_NOTIFICATION = 8
+};
+
/**
* Moves enum for beings and actors for others players vision.
* WARNING: Has to be in sync with the same enum in the Being class
@@ -415,27 +431,12 @@ enum BeingAction
{
STAND,
WALK,
- ATTACK,
SIT,
DEAD,
HURT
};
/**
- * 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!
@@ -458,6 +459,55 @@ enum BeingGender
GENDER_UNSPECIFIED
};
+// Helper functions for gender
+
+/**
+* Helper function for getting gender by int
+*/
+inline ManaServ::BeingGender getGender(int gender)
+{
+ switch (gender)
+ {
+ case 0:
+ return ManaServ::GENDER_MALE;
+ case 1:
+ return ManaServ::GENDER_FEMALE;
+ default:
+ return ManaServ::GENDER_UNSPECIFIED;
+ }
+}
+
+/**
+ * Quest states
+ */
+enum QuestStatus
+{
+ STATUS_OPEN = 0,
+ STATUS_STARTED,
+ STATUS_FINISHED,
+ STATUS_INVALID
+};
+
+/**
+ * Helper function for getting quest status by id
+ * @param status id of the status
+ * @return the status as enum value
+ */
+inline ManaServ::QuestStatus getQuestStatus(int status)
+{
+ switch (status)
+ {
+ case 0:
+ return ManaServ::STATUS_OPEN;
+ case 1:
+ return ManaServ::STATUS_STARTED;
+ case 2:
+ return ManaServ::STATUS_FINISHED;
+ default:
+ return ManaServ::STATUS_INVALID;
+ }
+}
+
/** The permited range to pick up an item */
const int PICKUP_RANGE = 32 + 16;
diff --git a/src/net/manaserv/npchandler.cpp b/src/net/manaserv/npchandler.cpp
index f19bf134..44729654 100644
--- a/src/net/manaserv/npchandler.cpp
+++ b/src/net/manaserv/npchandler.cpp
@@ -47,6 +47,7 @@ NpcHandler::NpcHandler()
GPMSG_NPC_CLOSE,
GPMSG_NPC_NUMBER,
GPMSG_NPC_STRING,
+ GPMSG_NPC_BUYSELL_RESPONSE,
0
};
handledMessages = _messages;
@@ -122,6 +123,9 @@ void NpcHandler::handleMessage(MessageIn &msg)
event->setInt("id", npcId);
event->trigger(Event::NpcChannel);
break;
+
+ case GPMSG_NPC_BUYSELL_RESPONSE:
+ break;
}
delete event;
diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp
index e0d4e783..02712214 100644
--- a/src/net/manaserv/playerhandler.cpp
+++ b/src/net/manaserv/playerhandler.cpp
@@ -70,9 +70,7 @@ PlayerHandler::PlayerHandler()
GPMSG_PLAYER_MAP_CHANGE,
GPMSG_PLAYER_SERVER_CHANGE,
GPMSG_PLAYER_ATTRIBUTE_CHANGE,
- GPMSG_PLAYER_EXP_CHANGE,
- GPMSG_LEVELUP,
- GPMSG_LEVEL_PROGRESS,
+ GPMSG_ATTRIBUTE_POINTS_STATUS,
GPMSG_RAISE_ATTRIBUTE_RESPONSE,
GPMSG_LOWER_ATTRIBUTE_RESPONSE,
GPMSG_ABILITY_STATUS,
@@ -130,39 +128,10 @@ void PlayerHandler::handleMessage(MessageIn &msg)
}
} break;
- case GPMSG_PLAYER_EXP_CHANGE:
- {
- logger->log("EXP Update");
- while (msg.getUnreadLength())
- {
- int skill = msg.readInt16();
- int current = msg.readInt32();
- int next = msg.readInt32();
- int level = msg.readInt16();
-
- PlayerInfo::setStatExperience(skill, current, next);
- PlayerInfo::setStatBase(skill, level);
- }
- } break;
-
- case GPMSG_LEVELUP:
- {
- PlayerInfo::setAttribute(LEVEL, msg.readInt16());
+ case GPMSG_ATTRIBUTE_POINTS_STATUS:
PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16());
PlayerInfo::setAttribute(CORR_POINTS, msg.readInt16());
- Particle* effect = particleEngine->addEffect(
- paths.getStringValue("particles")
- + paths.getStringValue("levelUpEffectFile")
- ,0, 0);
- local_player->controlParticle(effect);
- } break;
-
-
- case GPMSG_LEVEL_PROGRESS:
- {
- PlayerInfo::setAttribute(EXP, msg.readInt8());
- } break;
-
+ break;
case GPMSG_RAISE_ATTRIBUTE_RESPONSE:
{
@@ -321,9 +290,9 @@ void PlayerHandler::handleMapChangeMessage(MessageIn &msg)
void PlayerHandler::attack(int id)
{
- MessageOut msg(PGMSG_ATTACK);
- msg.writeInt16(id);
- gameServerConnection->send(msg);
+ // MessageOut msg(PGMSG_ATTACK);
+ // msg.writeInt16(id);
+ // gameServerConnection->send(msg);
}
void PlayerHandler::emote(int emoteId)
diff --git a/src/net/tmwa/abilityhandler.cpp b/src/net/tmwa/abilityhandler.cpp
index e221039c..e3e5d3bc 100644
--- a/src/net/tmwa/abilityhandler.cpp
+++ b/src/net/tmwa/abilityhandler.cpp
@@ -223,15 +223,15 @@ void AbilityHandler::use(int id)
{
}
-void AbilityHandler::use(int id, int level, int beingId)
+void AbilityHandler::useOn(int id, int beingId)
{
}
-void AbilityHandler::use(int id, int level, int x, int y)
+void AbilityHandler::useAt(int id, int x, int y)
{
}
-void AbilityHandler::use(int id, const std::string &map)
+void AbilityHandler::useInDirection(int id, int direction)
{
}
diff --git a/src/net/tmwa/abilityhandler.h b/src/net/tmwa/abilityhandler.h
index 822ed737..171f7d41 100644
--- a/src/net/tmwa/abilityhandler.h
+++ b/src/net/tmwa/abilityhandler.h
@@ -37,11 +37,11 @@ class AbilityHandler final : public MessageHandler, public Net::AbilityHandler
void use(int id) override;
- void use(int id, int level, int beingId) override;
+ void useOn(int id, int beingId) override;
- void use(int id, int level, int x, int y) override;
+ void useAt(int id, int x, int y) override;
- void use(int id, const std::string &map) override;
+ void useInDirection(int id, int direction) override;
};
} // namespace TmwAthena