diff options
author | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2024-08-19 15:58:52 +0200 |
---|---|---|
committer | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2025-03-07 22:27:48 +0100 |
commit | ca0b74e0f52aef36b929a2059fab62c192c620f6 (patch) | |
tree | 14f0c461df4a3ec14a03187e8987be0f79215bcd /src | |
parent | 9d1c20860e8a5b8e7d5a4fb53c2ddb1c372bad7f (diff) | |
download | mana-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.cpp | 2 | ||||
-rw-r--r-- | src/gui/inventorywindow.h | 2 | ||||
-rw-r--r-- | src/item.h | 11 | ||||
-rw-r--r-- | src/net/abilityhandler.h | 8 | ||||
-rw-r--r-- | src/net/manaserv/abilityhandler.cpp | 11 | ||||
-rw-r--r-- | src/net/manaserv/abilityhandler.h | 6 | ||||
-rw-r--r-- | src/net/manaserv/beinghandler.cpp | 109 | ||||
-rw-r--r-- | src/net/manaserv/beinghandler.h | 5 | ||||
-rw-r--r-- | src/net/manaserv/charhandler.cpp | 82 | ||||
-rw-r--r-- | src/net/manaserv/charhandler.h | 11 | ||||
-rw-r--r-- | src/net/manaserv/gamehandler.cpp | 4 | ||||
-rw-r--r-- | src/net/manaserv/generalhandler.cpp | 2 | ||||
-rw-r--r-- | src/net/manaserv/inventoryhandler.cpp | 258 | ||||
-rw-r--r-- | src/net/manaserv/inventoryhandler.h | 18 | ||||
-rw-r--r-- | src/net/manaserv/loginhandler.cpp | 2 | ||||
-rw-r--r-- | src/net/manaserv/manaserv_protocol.h | 208 | ||||
-rw-r--r-- | src/net/manaserv/npchandler.cpp | 4 | ||||
-rw-r--r-- | src/net/manaserv/playerhandler.cpp | 43 | ||||
-rw-r--r-- | src/net/tmwa/abilityhandler.cpp | 6 | ||||
-rw-r--r-- | src/net/tmwa/abilityhandler.h | 6 |
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; @@ -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 |