74 return AllowedForPlayer(player, loot, itemid, needs_quest, follow_loot_rules,
false, conditions);
119 if (strictUsabilityCheck)
153 auto ffaItemItr = std::find_if(ffaItems->get()->begin(), ffaItems->get()->end(), [&](
NotNormalLootItem const& ffaItem)
155 return ffaItem.LootListId == LootListId;
157 if (ffaItemItr != ffaItems->get()->end() && !ffaItemItr->is_looted)
235 startLootRoll.
ValidRolls &= ~ROLL_FLAG_TYPE_NEED;
262 lootAllPassed.
Write();
282 lootRoll.
Player = targetGuid;
283 lootRoll.
Roll = rollNumber;
296 if (playerGuid == rollWinner)
312 player->SendDirectMessage(lootRoll.
Write());
332 SendRoll(playerGuid, roll.RollNumber, roll.Vote, targetGuid);
339 lootRollWon.
Winner = targetGuid;
340 lootRollWon.
Roll = rollNumber;
353 if (playerGuid == targetGuid)
367 player->SendDirectMessage(lootRollWon.
Write());
403 if (lootListId >= loot.
items.size())
458 RollVoteMap::iterator voterItr =
m_rollVoteMap.find(playerGuid);
462 voterItr->second.Vote = vote;
465 voterItr->second.RollNumber =
urand(1, 100);
524 bool isSomeoneNeed =
false;
529 switch (itr->second.Vote)
532 if (!isSomeoneNeed || winnerItr ==
m_rollVoteMap.end() || itr->second.RollNumber > winnerItr->second.RollNumber)
534 isSomeoneNeed =
true;
542 if (winnerItr ==
m_rollVoteMap.end() || itr->second.RollNumber > winnerItr->second.RollNumber)
557 return notVoted == 0;
587 SendLootRollWon(winnerItr->first, winnerItr->second.RollNumber, winnerItr->second.Vote);
607 player->SendItemRetrievalMail(disenchantLoot->itemid, disenchantLoot->count, disenchantLoot->context);
626 _lootMaster(group ? group->GetMasterLooterGuid() :
ObjectGuid::
Empty), _wasOpened(false), _changed(false), _dungeonEncounterId(0)
635 player->GetSession()->DoLootRelease(
this);
655 allowedLooter->SendDirectMessage(lootList.
GetRawPacket());
688 player->SendNotifyLootMoneyRemoved(
GetGUID());
705 uint16 maxEnchantingSkill = 0;
708 maxEnchantingSkill = std::max(maxEnchantingSkill, allowedLooter->GetSkillValue(
SKILL_ENCHANTING));
710 for (
uint32 lootListId = 0; lootListId <
items.size(); ++lootListId)
716 auto&& [itr, inserted] =
_rolls.try_emplace(lootListId);
717 if (!itr->second.TryToStart(map, *
this, lootListId, maxEnchantingSkill))
733 lootMaster->SendDirectMessage(masterLootCandidateList.
Write());
749 if (maxAmount <= minAmount)
751 else if ((maxAmount - minAmount) < 32700)
770 TC_LOG_ERROR(
"sql.sql",
"Table '{}' loot id #{} used but it doesn't have records.", store.
GetName(), lootId);
782 if (!personal && group)
788 if (
Player const* player = itr->GetSource())
789 if (player->IsAtGroupRewardDistance(lootOwner))
794 if (!item.follow_loot_rules || item.freeforall)
800 item.is_underthreshold =
true;
809 item.is_blocked =
true;
844 items.push_back(generatedLoot);
851 bool allLooted =
true;
911 if (lootListId <
items.size())
912 return &
items[lootListId];
919 if (lootListId >=
items.size())
932 if (notNormalLootItem.
LootListId == lootListId)
936 *ffaItem = ¬NormalLootItem;
959 if (!item.is_looted && item.follow_loot_rules && !item.freeforall && item.conditions.IsEmpty())
969 if (!lootItem.is_looted && !lootItem.follow_loot_rules && lootItem.GetAllowedLooters().find(player->
GetGUID()) != lootItem.GetAllowedLooters().end())
974 bool hasFfaItem = std::any_of(ffaItems->get()->begin(), ffaItems->get()->end(), [&](
NotNormalLootItem const& ffaItem)
976 return !ffaItem.is_looted;
990 if (!
items[i].is_looted && !
items[i].is_underthreshold && !
items[i].freeforall)
1009 lootItem.
UIType = *uiType;
1019 if (itr->second.UpdateRoll())
1031 std::unique_ptr<NotNormalLootItemList> ffaItems = std::make_unique<NotNormalLootItemList>();
1035 if (!item.AllowedForPlayer(player,
this))
1038 item.AddAllowedLooter(player);
1040 if (item.freeforall)
1042 ffaItems->emplace_back(item.LootListId);
1045 else if (!item.is_counted)
1047 item.is_counted =
true;
1052 if (!ffaItems->empty())
1062 auto itr =
_byItem.find(item);
1064 _byOrder[itr->second].count += count;
1070 value.
count = count;
#define ASSERT_NOTNULL(pointer)
ItemRandomBonusListId GenerateItemRandomBonusListId(uint32 item_id)
@ ITEM_FLAG2_FACTION_HORDE
@ ITEM_FLAG2_FACTION_ALLIANCE
@ ITEM_FLAG2_CAN_ONLY_ROLL_GREED
@ ITEM_SPELLTRIGGER_ON_LEARN
@ ITEM_FLAG_HIDE_UNUSABLE_RECIPE
@ ITEM_FLAGS_CU_FOLLOW_LOOT_RULES
@ ITEM_FLAGS_CU_IGNORE_QUEST_STATUS
#define TC_LOG_ERROR(filterType__,...)
LootStore LootTemplates_Disenchant("disenchant_loot_template", "item disenchant id", true)
@ ROLL_FLAG_TYPE_DISENCHANT
@ LOOT_SLOT_TYPE_ROLL_ONGOING
@ LOOT_SLOT_TYPE_ALLOW_LOOT
#define MAX_NR_LOOT_ITEMS
constexpr Minutes LOOT_ROLL_TIMEOUT
std::set< ObjectGuid > GuidSet
std::optional< T > Optional
Optional helper class to wrap optional values within.
std::vector< ItemPosCount > ItemPosCountVec
uint32 urand(uint32 min, uint32 max)
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
std::unordered_map< Item *, OrderedStorage::size_type > _byItem
OrderedStorage::const_iterator end() const
OrderedStorage::const_iterator begin() const
void Add(Item *item, uint8 count, LootType lootType, uint32 dungeonEncounterId)
ItemQualities GetLootThreshold() const
GroupReference * GetFirstMember()
ItemDisenchantLootEntry const * GetDisenchantLoot(Player const *owner) const
uint32 GetItemLevel(Player const *owner) const
bool PlayerVote(Player *player, RollVote vote)
void Finish(RollVoteMap::const_iterator winnerItr)
bool AllPlayerVoted(RollVoteMap::const_iterator &winnerItr)
Check if all player have voted and return true in that case. Also return current winner.
bool TryToStart(Map *map, Loot &loot, uint32 lootListId, uint16 enchantingSkill)
ItemDisenchantLootEntry const * GetItemDisenchantLoot() const
bool IsLootItem(ObjectGuid const &lootObject, uint32 lootListId) const
RollVoteMap m_rollVoteMap
void SendLootRollWon(ObjectGuid const &targetGuid, int32 rollNumber, RollVote rollType)
void SendRoll(ObjectGuid const &targetGuid, int32 rollNumber, RollVote rollType, Optional< ObjectGuid > const &rollWinner)
void FillPacket(WorldPackets::Loot::LootItemData &lootItem) const
LootTemplate const * GetLootFor(uint32 loot_id) const
bool IsRatesAllowed() const
char const * GetName() const
void Process(Loot &loot, bool rate, uint16 lootMode, uint8 groupId, Player const *personalLooter=nullptr) const
static ObjectGuid const Empty
static ObjectGuid GetGUID(Object const *o)
void SendEquipError(InventoryResult msg, Item const *item1=nullptr, Item const *item2=nullptr, uint32 itemId=0) const
Item * StoreNewItem(ItemPosCountVec const &pos, uint32 itemId, bool update, ItemRandomBonusListId randomBonusListId=0, GuidSet const &allowedLooters=GuidSet(), ItemContext context=ItemContext::NONE, std::vector< int32 > const *bonusListIDs=nullptr, bool addToCollection=true)
void ApplyItemLootedSpell(Item *item, bool apply)
InventoryResult CanRollNeedForItem(ItemTemplate const *item, Map const *map, bool restrictOnlyLfg) const
void SendDirectMessage(WorldPacket const *data) const
bool HasQuestForItem(uint32 itemId) const
bool HasSkill(uint32 skill) const
void UpdateCriteria(CriteriaType type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, WorldObject *ref=nullptr)
void AddLootRoll(LootRoll *roll)
QuestStatus GetQuestStatus(uint32 quest_id) const
bool GetPassOnGroupLoot() const
bool HasSpell(uint32 spell) const override
Group * GetGroup(Optional< uint8 > partyIndex)
void RemoveLootRoll(LootRoll *roll)
InventoryResult CanStoreNewItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, uint32 item, uint32 count, uint32 *no_space_count=nullptr) const
void SendNewItem(Item *item, uint32 quantity, bool received, bool created, bool broadcast=false, uint32 dungeonEncounterId=0)
WorldPacket const * Write() override
Optional< ObjectGuid > Master
WorldPacket const * Write() override
Optional< ObjectGuid > RoundRobinWinner
std::vector< LootItemData > Items
WorldPacket const * Write() override
int32 Roll
Roll value can be negative, it means that it is an "offspec" roll but only during roll selection broa...
bool Autopassed
Triggers message |HlootHistory:d|h[Loot]|h: You automatically passed on: s because you cannot loot th...
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
Duration< Milliseconds, uint32 > RollTime
WorldPacket const * GetRawPacket() const
TC_GAME_API uint32 GetId(std::string_view username)
TimePoint Now()
Current chrono steady_clock time point.
std::vector< int32 > GetBonusListsForItem(uint32 itemId, ItemBonusGenerationParams const ¶ms)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
std::unique_ptr< VignetteData > Create(VignetteEntry const *vignetteData, WorldObject const *owner)
uint32 dungeonEncounterId
void Initialize(ItemTemplate const *proto)
bool Meets(WorldObject const *object) const
uint32 GetMaxStackSize() const
uint32 GetStartQuest() const
std::vector< ItemEffectEntry const * > Effects
bool HasFlag(ItemFlags flag) const
bool IsUsableByLootSpecialization(Player const *player, bool alwaysAllowBoundToAccount) const
uint32 GetRequiredSkill() const
bool HasAllowedLooter(ObjectGuid const &looter) const
std::vector< int32 > BonusListIDs
Optional< LootSlotType > GetUiTypeForPlayer(Player const *player, Loot const &loot) const
void AddAllowedLooter(Player const *player)
ObjectGuid rollWinnerGUID
bool AllowedForPlayer(Player const *player, Loot const *loot) const
ItemRandomBonusListId randomBonusListId
ConditionsReference conditions
GuidSet const & GetAllowedLooters() const
ConditionsReference conditions
void AddLooter(ObjectGuid GUID)
void NotifyLootList(Map const *map) const
bool AutoStore(Player *player, uint8 bag, uint8 slot, bool broadcast=false, bool createdByPlayer=false)
GuidUnorderedSet _allowedLooters
void OnLootOpened(Map *map, ObjectGuid looter)
bool hasOverThresholdItem() const
NotNormalLootItemMap PlayerFFAItems
void BuildLootResponse(WorldPackets::Loot::LootResponse &packet, Player const *viewer) const
void NotifyMoneyRemoved(Map const *map)
void NotifyItemRemoved(uint8 lootListId, Map const *map)
Loot(Map *map, ObjectGuid owner, LootType type, Group const *group)
void AddItem(LootStoreItem const &item)
LootItem const * GetItemInSlot(uint32 lootListId) const
ObjectGuid roundRobinPlayer
ObjectGuid const & GetOwnerGUID() const
void generateMoneyLoot(uint32 minAmount, uint32 maxAmount)
bool hasItemFor(Player const *player) const
bool hasItemForAll() const
LootItem * LootItemInSlot(uint32 lootListId, Player const *player, NotNormalLootItem **ffaItem=nullptr)
ObjectGuid const & GetGUID() const
std::vector< LootItem > items
std::unordered_map< uint32, LootRoll > _rolls
NotNormalLootItemMap const & GetPlayerFFAItems() const
bool FillLoot(uint32 lootId, LootStore const &store, Player *lootOwner, bool personal, bool noEmptyError=false, uint16 lootMode=LOOT_MODE_DEFAULT, ItemContext context=ItemContext::NONE)
uint32 GetDungeonEncounterId() const
ObjectGuid const & GetLootMasterGUID() const
LootMethod GetLootMethod() const
void FillNotNormalLootFor(Player const *player)
bool HasAllowedLooter(ObjectGuid const &looter) const
void Initialize(::Item const *item)
WorldPackets::Item::ItemInstance Loot