diff options
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Loot/LootMgr.cpp | 30 | ||||
-rw-r--r-- | src/server/game/Loot/LootMgr.h | 3 |
4 files changed, 30 insertions, 11 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 93d4796f21a..220bc4378ae 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -289,6 +289,10 @@ bool Creature::InitEntry(uint32 Entry, uint32 /*team*/, const CreatureData* data --diff; } + // Initialize loot duplicate count depending on raid difficulty + if (GetMap()->IsRaid() && GetMap()->GetSpawnMode() & RAID_DIFFICULTY_MASK_25MAN) + loot.maxDuplicates = 3; + SetEntry(Entry); // normal entry always m_creatureInfo = cinfo; // map mode related always diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index bf0fbb4199d..61e7943453e 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -258,6 +258,10 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa LastUsedScriptID = GetGOInfo()->ScriptId; AIM_Initialize(); + // Initialize loot duplicate count depending on raid difficulty + if (map->IsRaid() && map->GetSpawnMode() & RAID_DIFFICULTY_MASK_25MAN) + loot.maxDuplicates = 3; + return true; } diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 128cf358557..56e72a10930 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -52,16 +52,27 @@ LootStore LootTemplates_Reference("reference_loot_template", "reference LootStore LootTemplates_Skinning("skinning_loot_template", "creature skinning id", true); LootStore LootTemplates_Spell("spell_loot_template", "spell id (random item creating)", false); -struct NotMatchingLootMode : public std::unary_function<LootStoreItem*, bool> +// Selects invalid loot items to be removed from group possible entries (before rolling) +struct LootGroupInvalidSelector : public std::unary_function<LootStoreItem*, bool> { - explicit NotMatchingLootMode(uint16 lootMode) : _lootMode(lootMode) { } + explicit LootGroupInvalidSelector(Loot const& loot, uint16 lootMode) : _loot(loot), _lootMode(lootMode) { } bool operator()(LootStoreItem* item) const { - return !(item->lootmode & _lootMode); + if (!(item->lootmode & _lootMode)) + return true; + + uint8 foundDuplicates = 0; + for (std::vector<LootItem>::const_iterator itr = _loot.items.begin(); itr != _loot.items.end(); ++itr) + if (itr->itemid == item->itemid) + if (++foundDuplicates == _loot.maxDuplicates) + return true; + + return false; } private: + Loot const& _loot; uint16 _lootMode; }; @@ -89,7 +100,7 @@ class LootTemplate::LootGroup // A set of loot def LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance - LootStoreItem const* Roll(uint16 lootMode) const; // Rolls an item from the group, returns NULL if all miss their chances + LootStoreItem const* Roll(Loot& loot, uint16 lootMode) const; // Rolls an item from the group, returns NULL if all miss their chances // This class must never be copied - storing pointers LootGroup(LootGroup const&); @@ -1076,10 +1087,10 @@ void LootTemplate::LootGroup::AddEntry(LootStoreItem* item) } // Rolls an item from the group, returns NULL if all miss their chances -LootStoreItem const* LootTemplate::LootGroup::Roll(uint16 lootMode) const +LootStoreItem const* LootTemplate::LootGroup::Roll(Loot& loot, uint16 lootMode) const { LootStoreItemList possibleLoot = ExplicitlyChanced; - possibleLoot.remove_if(NotMatchingLootMode(lootMode)); + possibleLoot.remove_if(LootGroupInvalidSelector(loot, lootMode)); if (!possibleLoot.empty()) // First explicitly chanced entries are checked { @@ -1098,7 +1109,7 @@ LootStoreItem const* LootTemplate::LootGroup::Roll(uint16 lootMode) const } possibleLoot = EqualChanced; - possibleLoot.remove_if(NotMatchingLootMode(lootMode)); + possibleLoot.remove_if(LootGroupInvalidSelector(loot, lootMode)); if (!possibleLoot.empty()) // If nothing selected yet - an item is taken from equal-chanced part return Trinity::Containers::SelectRandomContainerElement(possibleLoot); @@ -1145,7 +1156,7 @@ void LootTemplate::LootGroup::CopyConditions(ConditionList /*conditions*/) // Rolls an item from the group (if any takes its chance) and adds the item to the loot void LootTemplate::LootGroup::Process(Loot& loot, uint16 lootMode) const { - if (LootStoreItem const* item = Roll(lootMode)) + if (LootStoreItem const* item = Roll(loot, lootMode)) loot.AddItem(*item); } @@ -1285,7 +1296,7 @@ void LootTemplate::Process(Loot& loot, bool rate, uint16 lootMode, uint8 groupId for (LootStoreItemList::const_iterator i = Entries.begin(); i != Entries.end(); ++i) { LootStoreItem* item = *i; - if (item->lootmode &~ lootMode) // Do not add if mode mismatch + if (!(item->lootmode & lootMode)) // Do not add if mode mismatch continue; if (!item->Roll(rate)) @@ -1294,7 +1305,6 @@ void LootTemplate::Process(Loot& loot, bool rate, uint16 lootMode, uint8 groupId if (item->mincountOrRef < 0) // References processing { LootTemplate const* Referenced = LootTemplates_Reference.GetLootFor(-item->mincountOrRef); - if (!Referenced) continue; // Error message already printed at loading stage diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h index df2717ee36e..5c858a35242 100644 --- a/src/server/game/Loot/LootMgr.h +++ b/src/server/game/Loot/LootMgr.h @@ -298,12 +298,13 @@ struct Loot uint8 unlootedCount; uint64 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) // GUIDLow of container that holds this loot (item_instance.entry) // Only set for inventory items that can be right-click looted uint32 containerID; - Loot(uint32 _gold = 0) : gold(_gold), unlootedCount(0), loot_type(LOOT_CORPSE), containerID(0) {} + Loot(uint32 _gold = 0) : gold(_gold), unlootedCount(0), loot_type(LOOT_CORPSE), maxDuplicates(1), containerID(0) {} ~Loot() { clear(); } // For deleting items at loot removal since there is no backward interface to the Item() |