/*
* Copyright (C) 2008-2018 TrinityCore
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#ifndef Loot_h__
#define Loot_h__
#include "Define.h"
#include "ConditionMgr.h"
#include "ItemEnchantmentMgr.h"
#include "ObjectGuid.h"
#include "RefManager.h"
#include "SharedDefines.h"
#include
#include
class Item;
class LootStore;
class Player;
struct Loot;
struct LootStoreItem;
namespace WorldPackets
{
namespace Loot
{
class LootResponse;
}
}
enum RollType
{
ROLL_PASS = 0,
ROLL_NEED = 1,
ROLL_GREED = 2,
ROLL_DISENCHANT = 3,
MAX_ROLL_TYPE = 4
};
enum RollMask
{
ROLL_FLAG_TYPE_PASS = 0x01,
ROLL_FLAG_TYPE_NEED = 0x02,
ROLL_FLAG_TYPE_GREED = 0x04,
ROLL_FLAG_TYPE_DISENCHANT = 0x08,
ROLL_ALL_TYPE_NO_DISENCHANT = 0x07,
ROLL_ALL_TYPE_MASK = 0x0F
};
#define MAX_NR_LOOT_ITEMS 16
// note: the client cannot show more than 16 items total
#define MAX_NR_QUEST_ITEMS 32
// unrelated to the number of quest items shown, just for reserve
enum LootMethod : uint8
{
FREE_FOR_ALL = 0,
MASTER_LOOT = 2,
GROUP_LOOT = 3,
PERSONAL_LOOT = 5
};
enum PermissionTypes
{
ALL_PERMISSION = 0,
GROUP_PERMISSION = 1,
MASTER_PERMISSION = 2,
RESTRICTED_PERMISSION = 3,
OWNER_PERMISSION = 5,
NONE_PERMISSION = 6
};
enum LootType : uint8
{
LOOT_NONE = 0,
LOOT_CORPSE = 1,
LOOT_PICKPOCKETING = 2,
LOOT_FISHING = 3,
LOOT_DISENCHANTING = 4,
// ignored always by client
LOOT_SKINNING = 6,
LOOT_PROSPECTING = 7,
LOOT_MILLING = 8,
LOOT_FISHINGHOLE = 20, // unsupported by client, sending LOOT_FISHING instead
LOOT_INSIGNIA = 21, // unsupported by client, sending LOOT_CORPSE instead
LOOT_FISHING_JUNK = 22 // unsupported by client, sending LOOT_FISHING instead
};
enum LootError : uint8
{
LOOT_ERROR_DIDNT_KILL = 0, // You don't have permission to loot that corpse.
LOOT_ERROR_TOO_FAR = 4, // You are too far away to loot that corpse.
LOOT_ERROR_BAD_FACING = 5, // You must be facing the corpse to loot it.
LOOT_ERROR_LOCKED = 6, // Someone is already looting that corpse.
LOOT_ERROR_NOTSTANDING = 8, // You need to be standing up to loot something!
LOOT_ERROR_STUNNED = 9, // You can't loot anything while stunned!
LOOT_ERROR_PLAYER_NOT_FOUND = 10, // Player not found
LOOT_ERROR_PLAY_TIME_EXCEEDED = 11, // Maximum play time exceeded
LOOT_ERROR_MASTER_INV_FULL = 12, // That player's inventory is full
LOOT_ERROR_MASTER_UNIQUE_ITEM = 13, // Player has too many of that item already
LOOT_ERROR_MASTER_OTHER = 14, // Can't assign item to that player
LOOT_ERROR_ALREADY_PICKPOCKETED = 15, // Your target has already had its pockets picked
LOOT_ERROR_NOT_WHILE_SHAPESHIFTED = 16, // You can't do that while shapeshifted.
LOOT_ERROR_NO_LOOT = 17 // There is no loot.
};
// type of Loot Item in Loot View
enum LootSlotType
{
LOOT_SLOT_TYPE_ALLOW_LOOT = 0, // player can loot the item.
LOOT_SLOT_TYPE_ROLL_ONGOING = 1, // roll is ongoing. player cannot loot.
LOOT_SLOT_TYPE_MASTER = 3, // item can only be distributed by group loot master.
LOOT_SLOT_TYPE_LOCKED = 2, // item is shown in red. player cannot loot.
LOOT_SLOT_TYPE_OWNER = 4 // ignore binding confirmation and etc, for single player looting
};
struct TC_GAME_API LootItem
{
uint32 itemid;
uint32 randomSuffix;
ItemRandomEnchantmentId randomPropertyId;
int32 upgradeId;
std::vector BonusListIDs;
uint8 context;
ConditionContainer conditions; // additional loot condition
GuidSet allowedGUIDs;
ObjectGuid rollWinnerGUID; // Stores the guid of person who won loot, if his bags are full only he can see the item in loot list!
uint8 count : 8;
bool is_looted : 1;
bool is_blocked : 1;
bool freeforall : 1; // free for all
bool is_underthreshold : 1;
bool is_counted : 1;
bool needs_quest : 1; // quest drop
bool follow_loot_rules : 1;
bool canSave;
// Constructor, copies most fields from LootStoreItem, generates random count and random suffixes/properties
// Should be called for non-reference LootStoreItem entries only (reference = 0)
explicit LootItem(LootStoreItem const& li);
// Empty constructor for creating an empty LootItem to be filled in with DB data
LootItem() : itemid(0), randomSuffix(0), randomPropertyId(), upgradeId(0), context(0), count(0), is_looted(false), is_blocked(false),
freeforall(false), is_underthreshold(false), is_counted(false), needs_quest(false), follow_loot_rules(false),
canSave(true){ };
// Basic checks for player/item compatibility - if false no chance to see the item in the loot
bool AllowedForPlayer(Player const* player) const;
void AddAllowedLooter(Player const* player);
GuidSet const& GetAllowedLooters() const { return allowedGUIDs; }
};
struct NotNormalLootItem
{
uint8 index; // position in quest_items or items;
bool is_looted;
NotNormalLootItem()
: index(0), is_looted(false) { }
NotNormalLootItem(uint8 _index, bool _islooted = false)
: index(_index), is_looted(_islooted) { }
};
typedef std::vector NotNormalLootItemList;
typedef std::vector LootItemList;
typedef std::unordered_map NotNormalLootItemMap;
//=====================================================
class LootValidatorRef : public Reference
{
public:
LootValidatorRef() { }
void targetObjectDestroyLink() override { }
void sourceObjectDestroyLink() override { }
};
//=====================================================
class LootValidatorRefManager : public RefManager
{
public:
typedef LinkedListHead::Iterator iterator;
LootValidatorRef* getFirst() { return (LootValidatorRef*)RefManager::getFirst(); }
iterator begin() { return iterator(getFirst()); }
iterator end() { return iterator(nullptr); }
};
//=====================================================
struct TC_GAME_API Loot
{
NotNormalLootItemMap const& GetPlayerQuestItems() const { return PlayerQuestItems; }
NotNormalLootItemMap const& GetPlayerFFAItems() const { return PlayerFFAItems; }
NotNormalLootItemMap const& GetPlayerNonQuestNonFFAConditionalItems() const { return PlayerNonQuestNonFFAConditionalItems; }
std::vector items;
std::vector quest_items;
uint32 gold;
uint8 unlootedCount;
ObjectGuid roundRobinPlayer; // GUID of the player having the Round-Robin ownership for the loot. If 0, round robin owner has released.
LootType loot_type; // required for achievement system
uint8 maxDuplicates; // Max amount of items with the same entry that can drop (default is 1; on 25 man raid mode 3)
// GUID of container that holds this loot (item_instance.entry)
// Only set for inventory items that can be right-click looted
ObjectGuid containerID;
Loot(uint32 _gold = 0);
~Loot();
ObjectGuid const& GetGUID() const { return _GUID; }
void SetGUID(ObjectGuid const& guid) { _GUID = guid; }
// For deleting items at loot removal since there is no backward interface to the Item()
void DeleteLootItemFromContainerItemDB(uint32 itemID);
void DeleteLootMoneyFromContainerItemDB();
// if loot becomes invalid this reference is used to inform the listener
void addLootValidatorRef(LootValidatorRef* pLootValidatorRef)
{
i_LootValidatorRefManager.insertFirst(pLootValidatorRef);
}
void clear();
bool empty() const { return items.empty() && gold == 0; }
bool isLooted() const { return gold == 0 && unlootedCount == 0; }
void NotifyItemRemoved(uint8 lootIndex);
void NotifyQuestItemRemoved(uint8 questIndex);
void NotifyMoneyRemoved();
void AddLooter(ObjectGuid GUID) { PlayersLooting.insert(GUID); }
void RemoveLooter(ObjectGuid GUID) { PlayersLooting.erase(GUID); }
void generateMoneyLoot(uint32 minAmount, uint32 maxAmount);
bool FillLoot(uint32 lootId, LootStore const& store, Player* lootOwner, bool personal, bool noEmptyError = false, uint16 lootMode = LOOT_MODE_DEFAULT);
// Inserts the item into the loot (called by LootTemplate processors)
void AddItem(LootStoreItem const & item);
LootItem const* GetItemInSlot(uint32 lootSlot) const;
LootItem* LootItemInSlot(uint32 lootslot, Player* player, NotNormalLootItem** qitem = NULL, NotNormalLootItem** ffaitem = NULL, NotNormalLootItem** conditem = NULL);
uint32 GetMaxSlotInLootFor(Player* player) const;
bool hasItemForAll() const;
bool hasItemFor(Player* player) const;
bool hasOverThresholdItem() const;
// Builds data for SMSG_LOOT_RESPONSE
void BuildLootResponse(WorldPackets::Loot::LootResponse& packet, Player* viewer, PermissionTypes permission = ALL_PERMISSION) const;
private:
void FillNotNormalLootFor(Player* player, bool presentAtLooting);
NotNormalLootItemList* FillFFALoot(Player* player);
NotNormalLootItemList* FillQuestLoot(Player* player);
NotNormalLootItemList* FillNonQuestNonFFAConditionalLoot(Player* player, bool presentAtLooting);
GuidSet PlayersLooting;
NotNormalLootItemMap PlayerQuestItems;
NotNormalLootItemMap PlayerFFAItems;
NotNormalLootItemMap PlayerNonQuestNonFFAConditionalItems;
// All rolls are registered here. They need to know, when the loot is not valid anymore
LootValidatorRefManager i_LootValidatorRefManager;
// Loot GUID
ObjectGuid _GUID;
uint8 _itemContext;
};
class TC_GAME_API AELootResult
{
public:
struct ResultValue
{
Item* item;
uint8 count;
LootType lootType;
};
typedef std::vector OrderedStorage;
void Add(Item* item, uint8 count, LootType lootType);
OrderedStorage::const_iterator begin() const;
OrderedStorage::const_iterator end() const;
OrderedStorage _byOrder;
std::unordered_map- _byItem;
};
#endif // Loot_h__