TrinityCore
Loading...
Searching...
No Matches
Loot.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Loot.h"
19#include "Group.h"
20#include "ItemEnchantmentMgr.h"
21#include "ItemTemplate.h"
22#include "Log.h"
23#include "LootMgr.h"
24#include "ObjectAccessor.h"
25#include "ObjectMgr.h"
26#include "Player.h"
27#include "Random.h"
28#include "World.h"
29
30 //
31 // --------- LootItem ---------
32 //
33
34 // Constructor, copies most fields from LootStoreItem and generates random count
56
57bool LootItem::AllowedForPlayer(Player const* player, ObjectGuid ownerGuid) const
58{
59 return AllowedForPlayer(player, false, ownerGuid);
60}
61
62bool LootItem::AllowedForPlayer(Player const* player, bool isGivenByMasterLooter) const
63{
64 return AllowedForPlayer(player, isGivenByMasterLooter, ObjectGuid::Empty);
65}
66
67// Basic checks for player/item compatibility - if false no chance to see the item in the loot
68bool LootItem::AllowedForPlayer(Player const* player, bool isGivenByMasterLooter, ObjectGuid ownerGuid) const
69{
70 // DB conditions check
71 if (!sConditionMgr->IsObjectMeetToConditions(const_cast<Player*>(player), conditions))
72 return false;
73
74 ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid);
75 if (!pProto)
76 return false;
77
78 // not show loot for not own team
79 if (pProto->HasFlag(ITEM_FLAG2_FACTION_HORDE) && player->GetTeam() != HORDE)
80 return false;
81
82 if (pProto->HasFlag(ITEM_FLAG2_FACTION_ALLIANCE) && player->GetTeam() != ALLIANCE)
83 return false;
84
85 // Master looter can see all items even if the character can't loot them
86 if (!isGivenByMasterLooter && player->GetGroup() && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID())
87 {
88 return true;
89 }
90
91 // Don't allow loot for players without profession or those who already know the recipe
93 {
94 if (!player->HasSkill(pProto->RequiredSkill))
95 return false;
96
97 for (ItemEffect const& itemEffect : pProto->Effects)
98 {
99 if (itemEffect.TriggerType != ITEM_SPELLTRIGGER_LEARN_SPELL_ID)
100 continue;
101
102 if (player->HasSpell(itemEffect.SpellID))
103 return false;
104 }
105 }
106
107 // Don't allow to loot soulbound recipes that the player has already learned
108 if (pProto->Class == ITEM_CLASS_RECIPE && pProto->Bonding == BIND_WHEN_PICKED_UP)
109 {
110 for (ItemEffect const& itemEffect : pProto->Effects)
111 {
112 if (itemEffect.TriggerType != ITEM_SPELLTRIGGER_LEARN_SPELL_ID)
113 continue;
114
115 if (player->HasSpell(itemEffect.SpellID))
116 return false;
117 }
118 }
119
120 if (needs_quest && !freeforall && player->GetGroup() && (player->GetGroup()->GetLootMethod() == GROUP_LOOT || player->GetGroup()->GetLootMethod() == ROUND_ROBIN) && !ownerGuid.IsEmpty() && ownerGuid != player->GetGUID())
121 return false;
122
123 // check quest requirements
124 if (!pProto->HasFlag(ITEM_FLAGS_CU_IGNORE_QUEST_STATUS) && ((needs_quest || (pProto->StartQuest && player->GetQuestStatus(pProto->StartQuest) != QUEST_STATUS_NONE)) && !player->HasQuestForItem(itemid)))
125 return false;
126
127 return true;
128}
129
131{
132 allowedGUIDs.insert(player->GetGUID());
133}
134
135//
136// --------- Loot ---------
137//
138
139Loot::Loot(uint32 _gold /*= 0*/) : gold(_gold), unlootedCount(0), roundRobinPlayer(), loot_type(LOOT_NONE), maxDuplicates(1), containerID(0)
140{
141}
142
144{
145 clear();
146}
147
149{
150 for (NotNormalLootItemMap::const_iterator itr = PlayerQuestItems.begin(); itr != PlayerQuestItems.end(); ++itr)
151 delete itr->second;
152 PlayerQuestItems.clear();
153
154 for (NotNormalLootItemMap::const_iterator itr = PlayerFFAItems.begin(); itr != PlayerFFAItems.end(); ++itr)
155 delete itr->second;
156 PlayerFFAItems.clear();
157
158 for (NotNormalLootItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.begin(); itr != PlayerNonQuestNonFFAConditionalItems.end(); ++itr)
159 delete itr->second;
161
162 PlayersLooting.clear();
163 items.clear();
164 quest_items.clear();
165 gold = 0;
166 unlootedCount = 0;
170}
171
172// Inserts the item into the loot (called by LootTemplate processors)
174{
175 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item.itemid);
176 if (!proto)
177 return;
178
179 uint32 count = urand(item.mincount, item.maxcount);
180 uint32 stacks = count / proto->GetMaxStackSize() + ((count % proto->GetMaxStackSize()) ? 1 : 0);
181
182 std::vector<LootItem>& lootItems = item.needs_quest ? quest_items : items;
184
185 for (uint32 i = 0; i < stacks && lootItems.size() < limit; ++i)
186 {
187 LootItem generatedLoot(item);
188 generatedLoot.count = std::min(count, proto->GetMaxStackSize());
189 generatedLoot.itemIndex = lootItems.size();
190 lootItems.push_back(generatedLoot);
191 count -= proto->GetMaxStackSize();
192
193 // In some cases, a dropped item should be visible/lootable only for some players in group
194 bool canSeeItemInLootWindow = false;
196 {
197 if (Group* group = player->GetGroup())
198 {
199 for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
200 if (Player* member = itr->GetSource())
201 if (generatedLoot.AllowedForPlayer(member, lootOwnerGUID))
202 canSeeItemInLootWindow = true;
203 }
204 else if (generatedLoot.AllowedForPlayer(player, lootOwnerGUID))
205 canSeeItemInLootWindow = true;
206 }
207
208 if (!canSeeItemInLootWindow)
209 continue;
210
211 // non-conditional one-player only items are counted here,
212 // free for all items are counted in FillFFALoot(),
213 // non-ffa conditionals are counted in FillNonQuestNonFFAConditionalLoot()
214 if (!item.needs_quest && item.conditions.empty() && !proto->HasFlag(ITEM_FLAG_MULTI_DROP))
216 }
217}
218
219// Calls processor of corresponding LootTemplate (which handles everything including references)
220bool Loot::FillLoot(uint32 lootId, LootStore const& store, Player* lootOwner, bool personal, bool noEmptyError, uint16 lootMode /*= LOOT_MODE_DEFAULT*/)
221{
222 // Must be provided
223 if (!lootOwner)
224 return false;
225
226 lootOwnerGUID = lootOwner->GetGUID();
227
228 LootTemplate const* tab = store.GetLootFor(lootId);
229
230 if (!tab)
231 {
232 if (!noEmptyError)
233 TC_LOG_ERROR("sql.sql", "Table '{}' loot id #{} used but it doesn't have records.", store.GetName(), lootId);
234 return false;
235 }
236
237 items.reserve(MAX_NR_LOOT_ITEMS);
239
240 tab->Process(*this, store.IsRatesAllowed(), lootMode); // Processing is done there, callback via Loot::AddItem()
241
242 // Setting access rights for group loot case
243 Group* group = lootOwner->GetGroup();
244 if (!personal && group)
245 {
246 roundRobinPlayer = lootOwner->GetGUID();
247
248 for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
249 if (Player* player = itr->GetSource()) // should actually be looted object instead of lootOwner but looter has to be really close so doesnt really matter
250 if (player->IsInMap(lootOwner))
251 FillNotNormalLootFor(player, player->IsAtGroupRewardDistance(lootOwner));
252
253 for (uint8 i = 0; i < items.size(); ++i)
254 {
255 if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(items[i].itemid))
256 if (proto->Quality < uint32(group->GetLootThreshold()))
257 items[i].is_underthreshold = true;
258 }
259 }
260 // ... for personal loot
261 else
262 FillNotNormalLootFor(lootOwner, true);
263
264 return true;
265}
266
267void Loot::FillNotNormalLootFor(Player* player, bool presentAtLooting)
268{
269 ObjectGuid plguid = player->GetGUID();
270
271 NotNormalLootItemMap::const_iterator qmapitr = PlayerQuestItems.find(plguid);
272 if (qmapitr == PlayerQuestItems.end())
273 FillQuestLoot(player);
274
275 qmapitr = PlayerFFAItems.find(plguid);
276 if (qmapitr == PlayerFFAItems.end())
277 FillFFALoot(player);
278
279 qmapitr = PlayerNonQuestNonFFAConditionalItems.find(plguid);
280 if (qmapitr == PlayerNonQuestNonFFAConditionalItems.end())
281 FillNonQuestNonFFAConditionalLoot(player, presentAtLooting);
282
283 // if not auto-processed player will have to come and pick it up manually
284 if (!presentAtLooting)
285 return;
286
287 // Process currency items
288 uint32 max_slot = GetMaxSlotInLootFor(player);
289 LootItem const* item = nullptr;
290 uint32 itemsSize = uint32(items.size());
291 for (uint32 i = 0; i < max_slot; ++i)
292 {
293 if (i < items.size())
294 item = &items[i];
295 else
296 item = &quest_items[i - itemsSize];
297
298 if (!item->is_looted && item->freeforall && item->AllowedForPlayer(player, lootOwnerGUID))
299 if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item->itemid))
300 if (proto->IsCurrencyToken())
301 player->StoreLootItem(i, this);
302 }
303}
304
306{
308
309 for (uint8 i = 0; i < items.size(); ++i)
310 {
311 LootItem &item = items[i];
312 if (!item.is_looted && item.freeforall && item.AllowedForPlayer(player, lootOwnerGUID))
313 {
314 ql->push_back(NotNormalLootItem(i));
316 }
317 }
318 if (ql->empty())
319 {
320 delete ql;
321 return nullptr;
322 }
323
324 PlayerFFAItems[player->GetGUID()] = ql;
325 return ql;
326}
327
329{
330 if (items.size() == MAX_NR_LOOT_ITEMS)
331 return nullptr;
332
334
335 for (uint8 i = 0; i < quest_items.size(); ++i)
336 {
337 LootItem &item = quest_items[i];
338
339 if (!item.is_looted && (item.AllowedForPlayer(player, lootOwnerGUID) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT))))
340 {
341 ql->push_back(NotNormalLootItem(i));
342
343 // quest items get blocked when they first appear in a
344 // player's quest vector
345 //
346 // increase once if one looter only, looter-times if free for all
347 if (item.freeforall || !item.is_blocked)
349 if (!player->GetGroup() || (player->GetGroup()->GetLootMethod() != GROUP_LOOT && player->GetGroup()->GetLootMethod() != ROUND_ROBIN))
350 item.is_blocked = true;
351
352 if (items.size() + ql->size() == MAX_NR_LOOT_ITEMS)
353 break;
354 }
355 }
356 if (ql->empty())
357 {
358 delete ql;
359 return nullptr;
360 }
361
362 PlayerQuestItems[player->GetGUID()] = ql;
363 return ql;
364}
365
367{
369
370 for (uint8 i = 0; i < items.size(); ++i)
371 {
372 LootItem &item = items[i];
373 if (!item.is_looted && !item.freeforall && (item.AllowedForPlayer(player, lootOwnerGUID)))
374 {
375 if (presentAtLooting)
376 item.AddAllowedLooter(player);
377 if (!item.conditions.empty())
378 {
379 ql->push_back(NotNormalLootItem(i));
380 if (!item.is_counted)
381 {
383 item.is_counted = true;
384 }
385 }
386 }
387 }
388 if (ql->empty())
389 {
390 delete ql;
391 return nullptr;
392 }
393
395 return ql;
396}
397
398//===================================================
399
401{
402 // notify all players that are looting this that the item was removed
403 // convert the index to the slot the player sees
404 GuidSet::iterator i_next;
405 for (GuidSet::iterator i = PlayersLooting.begin(); i != PlayersLooting.end(); i = i_next)
406 {
407 i_next = i;
408 ++i_next;
409 if (Player* player = ObjectAccessor::FindPlayer(*i))
410 player->SendNotifyLootItemRemoved(lootIndex);
411 else
412 PlayersLooting.erase(i);
413 }
414}
415
417{
418 // notify all players that are looting this that the money was removed
419 GuidSet::iterator i_next;
420 for (GuidSet::iterator i = PlayersLooting.begin(); i != PlayersLooting.end(); i = i_next)
421 {
422 i_next = i;
423 ++i_next;
424 if (Player* player = ObjectAccessor::FindPlayer(*i))
425 player->SendNotifyLootMoneyRemoved();
426 else
427 PlayersLooting.erase(i);
428 }
429}
430
432{
433 // when a free for all questitem is looted
434 // all players will get notified of it being removed
435 // (other questitems can be looted by each group member)
436 // bit inefficient but isn't called often
437
438 GuidSet::iterator i_next;
439 for (GuidSet::iterator i = PlayersLooting.begin(); i != PlayersLooting.end(); i = i_next)
440 {
441 i_next = i;
442 ++i_next;
443 if (Player* player = ObjectAccessor::FindPlayer(*i))
444 {
445 NotNormalLootItemMap::const_iterator pq = PlayerQuestItems.find(player->GetGUID());
446 if (pq != PlayerQuestItems.end() && pq->second)
447 {
448 // find where/if the player has the given item in it's vector
449 NotNormalLootItemList& pql = *pq->second;
450
451 uint8 j;
452 for (j = 0; j < pql.size(); ++j)
453 if (pql[j].index == questIndex)
454 break;
455
456 if (j < pql.size())
457 player->SendNotifyLootItemRemoved(items.size() + j);
458 }
459 }
460 else
461 PlayersLooting.erase(i);
462 }
463}
464
465void Loot::generateMoneyLoot(uint32 minAmount, uint32 maxAmount)
466{
467 if (maxAmount > 0)
468 {
469 if (maxAmount <= minAmount)
470 gold = uint32(maxAmount * sWorld->getRate(RATE_DROP_MONEY));
471 else if ((maxAmount - minAmount) < 32700)
472 gold = uint32(urand(minAmount, maxAmount) * sWorld->getRate(RATE_DROP_MONEY));
473 else
474 gold = uint32(urand(minAmount >> 8, maxAmount >> 8) * sWorld->getRate(RATE_DROP_MONEY)) << 8;
475 }
476}
477
479{
480 LootItem* item = nullptr;
481 bool is_looted = true;
482 if (lootSlot >= items.size())
483 {
484 uint32 questSlot = lootSlot - items.size();
485 NotNormalLootItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUID());
486 if (itr != PlayerQuestItems.end() && questSlot < itr->second->size())
487 {
488 NotNormalLootItem* qitem2 = &itr->second->at(questSlot);
489 if (qitem)
490 *qitem = qitem2;
491 item = &quest_items[qitem2->index];
492 is_looted = qitem2->is_looted;
493 }
494 }
495 else
496 {
497 item = &items[lootSlot];
498 is_looted = item->is_looted;
499 if (item->freeforall)
500 {
501 NotNormalLootItemMap::const_iterator itr = PlayerFFAItems.find(player->GetGUID());
502 if (itr != PlayerFFAItems.end())
503 {
504 for (NotNormalLootItemList::const_iterator iter = itr->second->begin(); iter != itr->second->end(); ++iter)
505 if (iter->index == lootSlot)
506 {
507 NotNormalLootItem* ffaitem2 = (NotNormalLootItem*)&(*iter);
508 if (ffaitem)
509 *ffaitem = ffaitem2;
510 is_looted = ffaitem2->is_looted;
511 break;
512 }
513 }
514 }
515 else if (!item->conditions.empty())
516 {
517 NotNormalLootItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.find(player->GetGUID());
519 {
520 for (NotNormalLootItemList::const_iterator iter = itr->second->begin(); iter != itr->second->end(); ++iter)
521 {
522 if (iter->index == lootSlot)
523 {
524 NotNormalLootItem* conditem2 = (NotNormalLootItem*)&(*iter);
525 if (conditem)
526 *conditem = conditem2;
527 is_looted = conditem2->is_looted;
528 break;
529 }
530 }
531 }
532 }
533 }
534
535 if (is_looted)
536 return nullptr;
537
538 return item;
539}
540
542{
543 NotNormalLootItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUID());
544 return items.size() + (itr != PlayerQuestItems.end() ? itr->second->size() : 0);
545}
546
547// return true if there is any item that is lootable for any player (not quest item, FFA or conditional)
549{
550 // Gold is always lootable
551 if (gold)
552 return true;
553
554 for (LootItem const& item : items)
555 if (!item.is_looted && !item.freeforall && item.conditions.empty())
556 return true;
557 return false;
558}
559
560// return true if there is any FFA, quest or conditional item for the player.
561bool Loot::hasItemFor(Player const* player) const
562{
563 NotNormalLootItemMap const& lootPlayerQuestItems = GetPlayerQuestItems();
564 NotNormalLootItemMap::const_iterator q_itr = lootPlayerQuestItems.find(player->GetGUID());
565 if (q_itr != lootPlayerQuestItems.end())
566 {
567 NotNormalLootItemList* q_list = q_itr->second;
568 for (NotNormalLootItemList::const_iterator qi = q_list->begin(); qi != q_list->end(); ++qi)
569 {
570 LootItem const& item = quest_items[qi->index];
571 if (!qi->is_looted && !item.is_looted)
572 return true;
573 }
574 }
575
576 NotNormalLootItemMap const& lootPlayerFFAItems = GetPlayerFFAItems();
577 NotNormalLootItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(player->GetGUID());
578 if (ffa_itr != lootPlayerFFAItems.end())
579 {
580 NotNormalLootItemList* ffa_list = ffa_itr->second;
581 for (NotNormalLootItemList::const_iterator fi = ffa_list->begin(); fi != ffa_list->end(); ++fi)
582 {
583 LootItem const& item = items[fi->index];
584 if (!fi->is_looted && !item.is_looted)
585 return true;
586 }
587 }
588
589 NotNormalLootItemMap const& lootPlayerNonQuestNonFFAConditionalItems = GetPlayerNonQuestNonFFAConditionalItems();
590 NotNormalLootItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(player->GetGUID());
591 if (nn_itr != lootPlayerNonQuestNonFFAConditionalItems.end())
592 {
593 NotNormalLootItemList* conditional_list = nn_itr->second;
594 for (NotNormalLootItemList::const_iterator ci = conditional_list->begin(); ci != conditional_list->end(); ++ci)
595 {
596 LootItem const& item = items[ci->index];
597 if (!ci->is_looted && !item.is_looted)
598 return true;
599 }
600 }
601
602 return false;
603}
604
605// return true if there is any item over the group threshold (i.e. not underthreshold).
607{
608 for (uint8 i = 0; i < items.size(); ++i)
609 {
610 if (!items[i].is_looted && !items[i].is_underthreshold && !items[i].freeforall)
611 return true;
612 }
613
614 return false;
615}
616
618{
619 b << uint32(li.itemid);
620 b << uint32(li.count); // nr of items of this type
621 b << uint32(ASSERT_NOTNULL(sObjectMgr->GetItemTemplate(li.itemid))->DisplayInfoID);
622 b << uint32(li.randomSuffix);
623 b << uint32(li.randomPropertyId);
624 //b << uint8(0); // slot type - will send after this function call
625 return b;
626}
627
629{
630 if (lv.permission == NONE_PERMISSION)
631 {
632 b << uint32(0); // gold
633 b << uint8(0); // item count
634 return b;
635 }
636
637 Loot &l = lv.loot;
638
639 uint8 itemsShown = 0;
640
641 b << uint32(l.gold); //gold
642
643 size_t count_pos = b.wpos(); // pos of item count byte
644 b << uint8(0); // item count placeholder
645
646 switch (lv.permission)
647 {
648 case GROUP_PERMISSION:
651 {
652 // if you are not the round-robin group looter, you can only see
653 // blocked rolled items and quest items, and !ffa items
654 for (uint8 i = 0; i < l.items.size(); ++i)
655 {
656 if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer, l.roundRobinPlayer))
657 {
658 uint8 slot_type;
659
660 if (l.items[i].is_blocked) // for ML & restricted is_blocked = !is_underthreshold
661 {
662 switch (lv.permission)
663 {
664 case GROUP_PERMISSION:
665 slot_type = LOOT_SLOT_TYPE_ROLL_ONGOING;
666 break;
668 {
669 if (lv.viewer->GetGroup() && lv.viewer->GetGroup()->GetMasterLooterGuid() == lv.viewer->GetGUID())
670 slot_type = LOOT_SLOT_TYPE_MASTER;
671 else
672 slot_type = LOOT_SLOT_TYPE_LOCKED;
673 break;
674 }
676 slot_type = LOOT_SLOT_TYPE_LOCKED;
677 break;
678 default:
679 continue;
680 }
681 }
682 else if (!l.items[i].rollWinnerGUID.IsEmpty())
683 {
684 if (l.items[i].rollWinnerGUID == lv.viewer->GetGUID())
685 slot_type = LOOT_SLOT_TYPE_OWNER;
686 else
687 continue;
688 }
689 else if (l.roundRobinPlayer.IsEmpty() || lv.viewer->GetGUID() == l.roundRobinPlayer || !l.items[i].is_underthreshold)
690 {
691 // no round robin owner or he has released the loot
692 // or it IS the round robin group owner
693 // => item is lootable
694 slot_type = LOOT_SLOT_TYPE_ALLOW_LOOT;
695 }
696 else
697 // item shall not be displayed.
698 continue;
699
700 b << uint8(i) << l.items[i];
701 b << uint8(slot_type);
702 ++itemsShown;
703 }
704 }
705 break;
706 }
708 {
709 for (uint8 i = 0; i < l.items.size(); ++i)
710 {
711 if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer, l.roundRobinPlayer))
712 {
714 // item shall not be displayed.
715 continue;
716
717 b << uint8(i) << l.items[i];
719 ++itemsShown;
720 }
721 }
722 break;
723 }
724 case ALL_PERMISSION:
725 case OWNER_PERMISSION:
726 {
728 for (uint8 i = 0; i < l.items.size(); ++i)
729 {
730 if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer, l.roundRobinPlayer))
731 {
732 b << uint8(i) << l.items[i];
733 b << uint8(slot_type);
734 ++itemsShown;
735 }
736 }
737 break;
738 }
739 default:
740 return b;
741 }
742
744 NotNormalLootItemMap const& lootPlayerQuestItems = l.GetPlayerQuestItems();
745 NotNormalLootItemMap::const_iterator q_itr = lootPlayerQuestItems.find(lv.viewer->GetGUID());
746 if (q_itr != lootPlayerQuestItems.end())
747 {
748 NotNormalLootItemList* q_list = q_itr->second;
749 for (NotNormalLootItemList::const_iterator qi = q_list->begin(); qi != q_list->end(); ++qi)
750 {
751 LootItem &item = l.quest_items[qi->index];
752 if (!qi->is_looted && !item.is_looted)
753 {
754 b << uint8(l.items.size() + (qi - q_list->begin()));
755 b << item;
756 if (item.follow_loot_rules)
757 {
758 switch (lv.permission)
759 {
762 break;
764 b << (item.is_blocked ? uint8(LOOT_SLOT_TYPE_LOCKED) : uint8(slotType));
765 break;
766 case GROUP_PERMISSION:
768 if (!item.is_blocked)
770 else
772 break;
773 default:
774 b << uint8(slotType);
775 break;
776 }
777 }
778 else
779 b << uint8(slotType);
780 ++itemsShown;
781 }
782 }
783 }
784
785 NotNormalLootItemMap const& lootPlayerFFAItems = l.GetPlayerFFAItems();
786 NotNormalLootItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(lv.viewer->GetGUID());
787 if (ffa_itr != lootPlayerFFAItems.end())
788 {
789 NotNormalLootItemList* ffa_list = ffa_itr->second;
790 for (NotNormalLootItemList::const_iterator fi = ffa_list->begin(); fi != ffa_list->end(); ++fi)
791 {
792 LootItem &item = l.items[fi->index];
793 if (!fi->is_looted && !item.is_looted)
794 {
795 b << uint8(fi->index);
796 b << item;
797 b << uint8(slotType);
798 ++itemsShown;
799 }
800 }
801 }
802
803 NotNormalLootItemMap const& lootPlayerNonQuestNonFFAConditionalItems = l.GetPlayerNonQuestNonFFAConditionalItems();
804 NotNormalLootItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(lv.viewer->GetGUID());
805 if (nn_itr != lootPlayerNonQuestNonFFAConditionalItems.end())
806 {
807 NotNormalLootItemList* conditional_list = nn_itr->second;
808 for (NotNormalLootItemList::const_iterator ci = conditional_list->begin(); ci != conditional_list->end(); ++ci)
809 {
810 LootItem &item = l.items[ci->index];
811 if (!ci->is_looted && !item.is_looted)
812 {
813 b << uint8(ci->index);
814 b << item;
815 switch (lv.permission)
816 {
819 break;
821 b << (item.is_blocked ? uint8(LOOT_SLOT_TYPE_LOCKED) : uint8(slotType));
822 break;
823 case GROUP_PERMISSION:
825 if (!item.is_blocked)
827 else
829 break;
830 default:
831 b << uint8(slotType);
832 break;
833 }
834 ++itemsShown;
835 }
836 }
837 }
838
839 //update number of items shown
840 b.put<uint8>(count_pos, itemsShown);
841
842 return b;
843}
#define sConditionMgr
uint8_t uint8
Definition Define.h:135
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:84
uint32 GenerateEnchSuffixFactor(uint32 item_id)
int32 GenerateItemRandomPropertyId(uint32 item_id)
@ ITEM_CLASS_RECIPE
@ ITEM_FLAG2_FACTION_HORDE
@ ITEM_FLAG2_FACTION_ALLIANCE
@ ITEM_SPELLTRIGGER_LEARN_SPELL_ID
@ ITEM_FLAG_HIDE_UNUSABLE_RECIPE
@ ITEM_FLAG_MULTI_DROP
@ BIND_WHEN_PICKED_UP
@ ITEM_FLAGS_CU_FOLLOW_LOOT_RULES
@ ITEM_FLAGS_CU_IGNORE_QUEST_STATUS
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
ByteBuffer & operator<<(ByteBuffer &b, LootItem const &li)
Definition Loot.cpp:617
@ LOOT_NONE
Definition Loot.h:82
@ OWNER_PERMISSION
Definition Loot.h:76
@ ALL_PERMISSION
Definition Loot.h:71
@ RESTRICTED_PERMISSION
Definition Loot.h:74
@ NONE_PERMISSION
Definition Loot.h:77
@ ROUND_ROBIN_PERMISSION
Definition Loot.h:75
@ MASTER_PERMISSION
Definition Loot.h:73
@ GROUP_PERMISSION
Definition Loot.h:72
@ GROUP_LOOT
Definition Loot.h:65
@ MASTER_LOOT
Definition Loot.h:64
@ ROUND_ROBIN
Definition Loot.h:63
#define MAX_NR_QUEST_ITEMS
Definition Loot.h:57
LootSlotType
Definition Loot.h:117
@ LOOT_SLOT_TYPE_MASTER
Definition Loot.h:120
@ LOOT_SLOT_TYPE_ROLL_ONGOING
Definition Loot.h:119
@ LOOT_SLOT_TYPE_ALLOW_LOOT
Definition Loot.h:118
@ LOOT_SLOT_TYPE_OWNER
Definition Loot.h:122
@ LOOT_SLOT_TYPE_LOCKED
Definition Loot.h:121
std::unordered_map< ObjectGuid, NotNormalLootItemList * > NotNormalLootItemMap
Definition Loot.h:177
std::vector< NotNormalLootItem > NotNormalLootItemList
Definition Loot.h:175
#define MAX_NR_LOOT_ITEMS
Definition Loot.h:55
#define sObjectMgr
Definition ObjectMgr.h:1721
@ QUEST_STATUS_NONE
Definition QuestDef.h:104
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
@ ALLIANCE
@ HORDE
size_t wpos() const
Definition ByteBuffer.h:321
void put(std::size_t pos, T value)
Definition ByteBuffer.h:137
Definition Group.h:165
ObjectGuid GetMasterLooterGuid() const
Definition Group.cpp:2495
ItemQualities GetLootThreshold() const
Definition Group.cpp:2500
LootMethod GetLootMethod() const
Definition Group.cpp:2483
GroupReference * GetFirstMember()
Definition Group.h:247
LootTemplate const * GetLootFor(uint32 loot_id) const
Definition LootMgr.cpp:227
bool IsRatesAllowed() const
Definition LootMgr.h:88
char const * GetName() const
Definition LootMgr.h:86
void Process(Loot &loot, bool rate, uint16 lootMode, uint8 groupId=0) const
Definition LootMgr.cpp:562
static ObjectGuid const Empty
Definition ObjectGuid.h:140
bool IsEmpty() const
Definition ObjectGuid.h:172
void Clear()
Definition ObjectGuid.h:150
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
uint32 GetTeam() const
Definition Player.h:1832
bool HasQuestForItem(uint32 itemId, uint32 excludeQuestId=0, bool turnIn=false) const
Definition Player.cpp:16449
bool HasSkill(uint32 skill) const
Definition Player.cpp:5871
Group * GetGroup()
Definition Player.h:2171
void StoreLootItem(uint8 lootSlot, Loot *loot)
Definition Player.cpp:24556
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition Player.cpp:15642
bool HasSpell(uint32 spell) const override
Definition Player.cpp:3853
void clearReferences()
Definition RefManager.h:47
#define sWorld
Definition World.h:900
@ RATE_DROP_MONEY
Definition World.h:428
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
std::array< ItemEffect, MAX_ITEM_PROTO_SPELLS > Effects
uint32 RequiredSkill
uint32 GetMaxStackSize() const
bool IsCurrencyToken() const
bool HasFlag(ItemFlags flag) const
uint32 StartQuest
uint32 itemid
Definition Loot.h:127
bool is_blocked
Definition Loot.h:136
void AddAllowedLooter(Player const *player)
Definition Loot.cpp:130
ObjectGuid rollWinnerGUID
Definition Loot.h:133
bool needs_quest
Definition Loot.h:140
bool follow_loot_rules
Definition Loot.h:141
bool is_underthreshold
Definition Loot.h:138
GuidSet allowedGUIDs
Definition Loot.h:132
int32 randomPropertyId
Definition Loot.h:130
uint32 itemIndex
Definition Loot.h:128
uint8 count
Definition Loot.h:134
bool is_looted
Definition Loot.h:135
LootItem()
Definition Loot.h:148
ConditionContainer conditions
Definition Loot.h:131
bool AllowedForPlayer(Player const *player, bool isGivenByMasterLooter, ObjectGuid ownerGuid) const
Definition Loot.cpp:68
bool freeforall
Definition Loot.h:137
uint32 randomSuffix
Definition Loot.h:129
bool is_counted
Definition Loot.h:139
ConditionContainer conditions
Definition LootMgr.h:44
bool needs_quest
Definition LootMgr.h:40
uint32 itemid
Definition LootMgr.h:36
uint8 maxcount
Definition LootMgr.h:43
uint8 mincount
Definition LootMgr.h:42
PermissionTypes permission
Definition Loot.h:278
Loot & loot
Definition Loot.h:276
Player * viewer
Definition Loot.h:277
Definition Loot.h:207
uint32 GetMaxSlotInLootFor(Player *player) const
Definition Loot.cpp:541
Loot(uint32 _gold=0)
Definition Loot.cpp:139
NotNormalLootItemMap const & GetPlayerQuestItems() const
Definition Loot.h:210
NotNormalLootItemList * FillQuestLoot(Player *player)
Definition Loot.cpp:328
void clear()
Definition Loot.cpp:148
bool hasOverThresholdItem() const
Definition Loot.cpp:606
void NotifyMoneyRemoved()
Definition Loot.cpp:416
bool FillLoot(uint32 lootId, LootStore const &store, Player *lootOwner, bool personal, bool noEmptyError=false, uint16 lootMode=LOOT_MODE_DEFAULT)
Definition Loot.cpp:220
NotNormalLootItemMap PlayerFFAItems
Definition Loot.h:267
NotNormalLootItemList * FillFFALoot(Player *player)
Definition Loot.cpp:305
uint8 unlootedCount
Definition Loot.h:217
void AddItem(LootStoreItem const &item)
Definition Loot.cpp:173
ObjectGuid roundRobinPlayer
Definition Loot.h:218
ObjectGuid lootOwnerGUID
Definition Loot.h:219
NotNormalLootItemMap PlayerNonQuestNonFFAConditionalItems
Definition Loot.h:268
GuidSet PlayersLooting
Definition Loot.h:265
NotNormalLootItemMap const & GetPlayerNonQuestNonFFAConditionalItems() const
Definition Loot.h:212
void generateMoneyLoot(uint32 minAmount, uint32 maxAmount)
Definition Loot.cpp:465
NotNormalLootItemList * FillNonQuestNonFFAConditionalLoot(Player *player, bool presentAtLooting)
Definition Loot.cpp:366
bool hasItemFor(Player const *player) const
Definition Loot.cpp:561
uint32 gold
Definition Loot.h:216
bool hasItemForAll() const
Definition Loot.cpp:548
void NotifyQuestItemRemoved(uint8 questIndex)
Definition Loot.cpp:431
LootItem * LootItemInSlot(uint32 lootslot, Player *player, NotNormalLootItem **qitem=nullptr, NotNormalLootItem **ffaitem=nullptr, NotNormalLootItem **conditem=nullptr)
Definition Loot.cpp:478
~Loot()
Definition Loot.cpp:143
std::vector< LootItem > items
Definition Loot.h:214
NotNormalLootItemMap PlayerQuestItems
Definition Loot.h:266
NotNormalLootItemMap const & GetPlayerFFAItems() const
Definition Loot.h:211
void NotifyItemRemoved(uint8 lootIndex)
Definition Loot.cpp:400
LootType loot_type
Definition Loot.h:220
void FillNotNormalLootFor(Player *player, bool presentAtLooting)
Definition Loot.cpp:267
std::vector< LootItem > quest_items
Definition Loot.h:215
LootValidatorRefManager i_LootValidatorRefManager
Definition Loot.h:271