diff options
author | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2007-01-03 17:10:43 +0000 |
---|---|---|
committer | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2007-01-03 17:10:43 +0000 |
commit | 1673de8b5553f6dcd4898c84b8d44ba8b30740f1 (patch) | |
tree | 3dcc47461a6b4914c4e81492e7be885c3a1502ea /src/game-server/inventory.cpp | |
parent | 6b7441516002d6e7cca424416bb67c6bc7d7c9d2 (diff) | |
download | manaserv-1673de8b5553f6dcd4898c84b8d44ba8b30740f1.tar.gz manaserv-1673de8b5553f6dcd4898c84b8d44ba8b30740f1.tar.bz2 manaserv-1673de8b5553f6dcd4898c84b8d44ba8b30740f1.tar.xz manaserv-1673de8b5553f6dcd4898c84b8d44ba8b30740f1.zip |
Split persistent player data from game server data. Enabled inventory code back.
Diffstat (limited to 'src/game-server/inventory.cpp')
-rw-r--r-- | src/game-server/inventory.cpp | 419 |
1 files changed, 419 insertions, 0 deletions
diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp new file mode 100644 index 00000000..b3b8a254 --- /dev/null +++ b/src/game-server/inventory.cpp @@ -0,0 +1,419 @@ +/* + * The Mana World Server + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include "game-server/inventory.hpp" +#include "game-server/itemmanager.hpp" + +// --------- +// Items +// --------- +unsigned char +Inventory::getInventoryFreeSlot() +{ + for (int a = 0; a < MAX_ITEMS_IN_INVENTORY; a++) + { + if (itemList.at(a).amount == 0) + return a; + } + return INVENTORY_FULL; +} + +unsigned char +Inventory::getSlotFromId(const unsigned int itemId) +{ + for (int a = 0; a < MAX_ITEMS_IN_INVENTORY; a++) + { + if (itemList.at(a).itemId == itemId) + return a; + } + return INVENTORY_FULL; +} + +bool +Inventory::hasItem(unsigned int itemId, + bool searchInInventory, + bool searchInEquipment) +{ + bool hasItem = false; + // Search in inventory + if (searchInInventory) + { + std::vector<StoredItem>::iterator iter = itemList.begin(); + for (iter = itemList.begin(); iter != itemList.end(); ++iter) + { + if (iter->itemId == itemId) + hasItem = true; + } + } + // Search in equipment + if (searchInEquipment) + { + std::vector<EquippedItem>::iterator equipIter = equippedItemList.begin(); + for (equipIter = equippedItemList.begin(); + equipIter != equippedItemList.end(); + ++equipIter) + { + if (equipIter->itemId == itemId) + hasItem = true; + } + if (equippedProjectiles.itemId == itemId) + hasItem = true; + } + return hasItem; +} + +short +Inventory::addItem(unsigned int itemId, unsigned char amount) +{ + // We get the max number of item we can have in the same slot + // for the given item. + unsigned char maxPerSlot = itemManager->getMaxPerSlot(itemId); + // We'll add items in slots with the item type and in free slots + // until it's all done or until the inventory will be all parsed. + // Searching for items with the same Id in the inventory, before + // seeking a free slot. + unsigned char amountToAdd = amount; + + // Parsing inventory + unsigned char currentAmountInSlot = 0; + std::vector<StoredItem>::iterator iter = itemList.begin(); + for (iter = itemList.begin(); iter != itemList.end(); ++iter) + { + currentAmountInSlot = iter->amount; + // If a slot has got place for some more of such an item. + if (iter->itemId == itemId && currentAmountInSlot < maxPerSlot) + { + // If there isn't enough space to put every item in the slot. + // We add the difference. + if ((maxPerSlot - currentAmountInSlot) < amountToAdd) + { + iter->amount += (maxPerSlot - currentAmountInSlot); + amountToAdd -= (maxPerSlot - currentAmountInSlot); + } + else // there is enough to add everything. + { + iter->amount += amountToAdd; + amountToAdd = 0; // Ok! + } + } + // Or if there is an empty slot. + else if (iter->amount == 0) + { + // We add the item in the new slot (setting also the Id.) + if (maxPerSlot < amountToAdd) + { + iter->amount = maxPerSlot; + amountToAdd -= maxPerSlot; + } + else + { + iter->amount += amountToAdd; + amountToAdd = 0; // Ok! + } + iter->itemId = itemId; + } + } + + return (short)(amount - amountToAdd); +} + +short +Inventory::removeItem(unsigned int itemId, unsigned char amount) +{ + // We'll remove items in slots with the item type + // until it's all done or until the inventory will be all parsed. + // Searching for items with the same Id in the inventory + unsigned char amountToRemove = amount; + + // Parsing inventory + unsigned char currentAmountInSlot = 0; + std::vector<StoredItem>::iterator iter = itemList.begin(); + for (iter = itemList.begin(); iter != itemList.end(); ++iter) + { + currentAmountInSlot = iter->amount; + // If a slot has got such an item, remove it + if (iter->itemId == itemId && currentAmountInSlot > 0) + { + // If there isn't enough to finish, we remove the difference + // Emptying the slot, so we clean also the itemId. + if (currentAmountInSlot <= amountToRemove) + { + amountToRemove -= currentAmountInSlot; + iter->amount = 0; + iter->itemId = 0; + } + else // there is enough to remove everything. + { + iter->amount -= amountToRemove; + amountToRemove = 0; // Ok! + } + } + } + return (short)(amount - amountToRemove); +} + +short +Inventory::removeItem(unsigned char slot, unsigned char amount) +{ + if (itemList.at(slot).amount < amount) + { + unsigned char value = itemList.at(slot).amount; + itemList.at(slot).amount = 0; + return (short)value; + } + else + { + itemList.at(slot).amount -= amount; + return amount; + } +} + +bool +Inventory::use(unsigned char slot, BeingPtr itemUser) +{ + return false; // TODO +} + +bool +Inventory::use(unsigned int itemId, BeingPtr itemUser) +{ + return false; // TODO +} + +// --------- +// Equipment +// --------- +unsigned char +Inventory::equipItem(unsigned int itemId) +{ + // First, we look for the item in the player's inventory. + if (!hasItem(itemId, true, false)) + return false; + + unsigned char availableSlots = 0, firstSlot = 0, secondSlot = 0; + + unsigned short itemType = itemManager->getItemType(itemId); + switch (itemType) + { + case ITEM_EQUIPMENT_TWO_HANDS_WEAPON: + // Special case 1, the two one-handed weapons are to be placed back + // in the inventory, if there are any. + if (equippedItemList.at(EQUIP_FIGHT1_SLOT).itemId > 0) + { // Slot 1 full + // old two-handed weapon case: + if (equippedItemList.at(EQUIP_FIGHT1_SLOT).itemType + == ITEM_EQUIPMENT_TWO_HANDS_WEAPON) + { + equippedItemList.at(EQUIP_FIGHT2_SLOT).itemId = 0; + equippedItemList.at(EQUIP_FIGHT2_SLOT).itemType = 0; + } + + if (unequipItem_(equippedItemList.at(EQUIP_FIGHT1_SLOT).itemId, + EQUIP_FIGHT1_SLOT) == INVENTORY_FULL) + return INVENTORY_FULL; + } + if (equippedItemList.at(EQUIP_FIGHT2_SLOT).itemId > 0) + { // Slot 2 full + if (unequipItem_(equippedItemList.at(EQUIP_FIGHT2_SLOT).itemId, + EQUIP_FIGHT2_SLOT) == INVENTORY_FULL) + return INVENTORY_FULL; + } + // Only the slot 1 needs to be updated. + return equipItem_(itemId, itemType, EQUIP_FIGHT1_SLOT); + break; + + case ITEM_EQUIPMENT_PROJECTILE: + // Special case 2: the projectile is a Stored Item structure, + // but is still considered as part of the equipment. + // Case 1: Reloading + if (equippedProjectiles.itemId == itemId) + { + equippedProjectiles.amount += removeItem(itemId, + (255 - equippedProjectiles.amount)); + return EQUIP_PROJECTILES_SLOT; + } + else // Case 2: Changing projectiles. + { + short added; + added = addItem(equippedProjectiles.itemId, + equippedProjectiles.amount); + if (added == equippedProjectiles.amount) + { // Ok, we can equip + equippedProjectiles.itemId = itemId; + equippedProjectiles.amount = removeItem(itemId, 255); + return EQUIP_PROJECTILES_SLOT; + } + else // Some were unequipped. + { + equippedProjectiles.amount -= added; + return INVENTORY_FULL; + } + } + break; + + case ITEM_EQUIPMENT_ONE_HAND_WEAPON: + case ITEM_EQUIPMENT_SHIELD: + availableSlots = 2; + firstSlot = EQUIP_FIGHT1_SLOT; + secondSlot = EQUIP_FIGHT2_SLOT; + break; + case ITEM_EQUIPMENT_RING: + availableSlots = 2; + firstSlot = EQUIP_RING1_SLOT; + secondSlot = EQUIP_RING2_SLOT; + break; + case ITEM_EQUIPMENT_BREST: + availableSlots = 1; + firstSlot = EQUIP_BREST_SLOT; + break; + case ITEM_EQUIPMENT_ARMS: + availableSlots = 1; + firstSlot = EQUIP_ARMS_SLOT; + break; + case ITEM_EQUIPMENT_HEAD: + availableSlots = 1; + firstSlot = EQUIP_HEAD_SLOT; + break; + case ITEM_EQUIPMENT_LEGS: + availableSlots = 1; + firstSlot = EQUIP_LEGS_SLOT; + break; + case ITEM_EQUIPMENT_NECKLACE: + availableSlots = 1; + firstSlot = EQUIP_NECKLACE_SLOT; + break; + case ITEM_EQUIPMENT_FEET: + availableSlots = 1; + firstSlot = EQUIP_FEET_SLOT; + break; + + case ITEM_UNUSABLE: + case ITEM_USABLE: + default: + return NOT_EQUIPPABLE; + } + + switch (availableSlots) + { + case 1: + if (equippedItemList.at(firstSlot).itemId > 0) + { + if (unequipItem_(equippedItemList.at(firstSlot).itemId, + firstSlot) != INVENTORY_FULL) + return equipItem_(itemId, itemType, firstSlot); + else + return INVENTORY_FULL; + } + else // slot empty, we can equip. + { + return equipItem_(itemId, itemType, firstSlot); + } + break; + + case 2: + if (equippedItemList.at(firstSlot).itemId > 0) + { + // If old weapon is two-handed one, we can unequip + // the first slot only, and clean the second. + if (equippedItemList.at(firstSlot).itemId == + ITEM_EQUIPMENT_TWO_HANDS_WEAPON) + { + if (unequipItem_(equippedItemList.at(firstSlot).itemId, + firstSlot) != INVENTORY_FULL) + return equipItem_(itemId, itemType, firstSlot); + else + return INVENTORY_FULL; + } + + if (equippedItemList.at(secondSlot).itemId > 0) + { // Both slots are full, + // we remove the first one to equip + if (unequipItem_(equippedItemList.at(firstSlot).itemId, + firstSlot) != INVENTORY_FULL) + return equipItem_(itemId, itemType, firstSlot); + else + return INVENTORY_FULL; + } + else // Second slot empty, we can equip. + { + return equipItem_(itemId, itemType, secondSlot); + } + } + else // first slot empty, we can equip. + { + return equipItem_(itemId, itemType, firstSlot); + } + break; + + default: + return NOT_EQUIPPABLE; + } +} + +bool +Inventory::equipItem(unsigned char inventorySlot, unsigned char equipmentSlot) +{ + return false; // TODO +} + +bool +Inventory::unequipItem(unsigned int itemId) +{ + return false; // TODO +} + +bool +Inventory::unequipItem(unsigned char inventorySlot, + unsigned char equipmentSlot) +{ + return false; // TODO +} + +unsigned char +Inventory::equipItem_(unsigned int itemId, + unsigned int itemType, + unsigned char equipmentSlot) +{ + if (removeItem(itemId, 1) == 1) + { + equippedItemList.at(equipmentSlot).itemId = itemId; + equippedItemList.at(equipmentSlot).itemType = itemType; + return equipmentSlot; + } + else + return NO_ITEM_TO_EQUIP; +} + +unsigned char +Inventory::unequipItem_(unsigned int itemId, + unsigned char equipmentSlot) +{ + if (addItem(itemId, 1) == 1) + { + equippedItemList.at(equipmentSlot).itemId = 0; + equippedItemList.at(equipmentSlot).itemType = 0; + return equipmentSlot; + } + else + return INVENTORY_FULL; +} |