diff options
-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 |