TrinityCore
Loading...
Searching...
No Matches
CollectionMgr.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 "CollectionMgr.h"
19#include "CollectionPackets.h"
20#include "DatabaseEnv.h"
21#include "DB2Stores.h"
22#include "Item.h"
23#include "Log.h"
24#include "MapUtils.h"
25#include "MiscPackets.h"
26#include "ObjectMgr.h"
27#include "Player.h"
28#include "Timer.h"
29#include "TransmogMgr.h"
31#include "WorldSession.h"
32#include <boost/dynamic_bitset.hpp>
33
34namespace
35{
36 MountDefinitionMap FactionSpecificMounts;
37 std::vector<uint32> DefaultWarbandScenes;
38}
39
41{
42 uint32 oldMSTime = getMSTime();
43
44 QueryResult result = WorldDatabase.Query("SELECT spellId, otherFactionSpellId FROM mount_definitions");
45
46 if (!result)
47 {
48 TC_LOG_INFO("server.loading", ">> Loaded 0 mount definitions. DB table `mount_definitions` is empty.");
49 return;
50 }
51
52 do
53 {
54 Field* fields = result->Fetch();
55
56 uint32 spellId = fields[0].GetUInt32();
57 uint32 otherFactionSpellId = fields[1].GetUInt32();
58
59 if (!sDB2Manager.GetMount(spellId))
60 {
61 TC_LOG_ERROR("sql.sql", "Mount spell {} defined in `mount_definitions` does not exist in Mount.db2, skipped", spellId);
62 continue;
63 }
64
65 if (otherFactionSpellId && !sDB2Manager.GetMount(otherFactionSpellId))
66 {
67 TC_LOG_ERROR("sql.sql", "otherFactionSpellId {} defined in `mount_definitions` for spell {} does not exist in Mount.db2, skipped", otherFactionSpellId, spellId);
68 continue;
69 }
70
71 FactionSpecificMounts[spellId] = otherFactionSpellId;
72 } while (result->NextRow());
73
74 TC_LOG_INFO("server.loading", ">> Loaded {} mount definitions in {} ms", FactionSpecificMounts.size(), GetMSTimeDiffToNow(oldMSTime));
75}
76
78{
79 for (WarbandSceneEntry const* warbandScene : sWarbandSceneStore)
80 if (warbandScene->GetFlags().HasFlag(WarbandSceneFlags::AwardedAutomatically))
81 DefaultWarbandScenes.push_back(warbandScene->ID);
82}
83
84namespace
85{
86 EnumFlag<ToyFlags> GetToyFlags(bool isFavourite, bool hasFanfare)
87 {
89 if (isFavourite)
91
92 if (hasFanfare)
94
95 return flags;
96 }
97}
98
100 _appearances(std::make_unique<boost::dynamic_bitset<uint32>>()),
101 _transmogIllusions(std::make_unique<boost::dynamic_bitset<uint32>>())
102{
103}
104
106
117
128
130{
131 for (auto const& [itemId, flags] : _toys)
132 _owner->GetPlayer()->AddToy(itemId, flags.AsUnderlyingType());
133}
134
135bool CollectionMgr::AddToy(uint32 itemId, bool isFavourite, bool hasFanfare)
136{
137 if (UpdateAccountToys(itemId, isFavourite, hasFanfare))
138 {
139 _owner->GetPlayer()->AddToy(itemId, GetToyFlags(isFavourite, hasFanfare).AsUnderlyingType());
140 return true;
141 }
142
143 return false;
144}
145
147{
148 if (!result)
149 return;
150
151 do
152 {
153 Field* fields = result->Fetch();
154 uint32 itemId = fields[0].GetUInt32();
155 _toys.emplace(itemId, GetToyFlags(fields[1].GetBool(), fields[2].GetBool()));
156 } while (result->NextRow());
157}
158
160{
161 LoginDatabasePreparedStatement* stmt = nullptr;
162 for (auto const& toy : _toys)
163 {
164 stmt = LoginDatabase.GetPreparedStatement(LOGIN_REP_ACCOUNT_TOYS);
166 stmt->setUInt32(1, toy.first);
167 stmt->setBool(2, toy.second.HasFlag(ToyFlags::Favorite));
168 stmt->setBool(3, toy.second.HasFlag(ToyFlags::HasFanfare));
169 trans->Append(stmt);
170 }
171}
172
173bool CollectionMgr::UpdateAccountToys(uint32 itemId, bool isFavourite, bool hasFanfare)
174{
175 return _toys.insert(ToyBoxContainer::value_type(itemId, GetToyFlags(isFavourite, hasFanfare))).second;
176}
177
178void CollectionMgr::ToySetFavorite(uint32 itemId, bool favorite)
179{
180 ToyBoxContainer::iterator itr = _toys.find(itemId);
181 if (itr == _toys.end())
182 return;
183
184 if (favorite)
185 itr->second |= ToyFlags::Favorite;
186 else
187 itr->second &= ~ToyFlags::Favorite;
188}
189
191{
192 auto itr = _toys.find(itemId);
193 if (itr == _toys.end())
194 return;
195
196 itr->second &= ~ ToyFlags::HasFanfare;
197}
198
200{
201 if (sDB2Manager.GetHeirloomByItemId(item->GetEntry()))
202 AddHeirloom(item->GetEntry(), 0);
203
204 AddItemAppearance(item);
205}
206
208{
209 if (!result)
210 return;
211
212 do
213 {
214 Field* fields = result->Fetch();
215 uint32 itemId = fields[0].GetUInt32();
216 uint32 flags = fields[1].GetUInt32();
217
218 HeirloomEntry const* heirloom = sDB2Manager.GetHeirloomByItemId(itemId);
219 if (!heirloom)
220 continue;
221
222 uint32 bonusId = 0;
223
224 for (int32 upgradeLevel = std::size(heirloom->UpgradeItemID) - 1; upgradeLevel >= 0; --upgradeLevel)
225 {
226 if (flags & (1 << upgradeLevel))
227 {
228 bonusId = heirloom->UpgradeItemBonusListID[upgradeLevel];
229 break;
230 }
231 }
232
233 _heirlooms[itemId] = HeirloomData(flags, bonusId);
234 } while (result->NextRow());
235}
236
238{
239 LoginDatabasePreparedStatement* stmt = nullptr;
240 for (auto const& heirloom : _heirlooms)
241 {
242 stmt = LoginDatabase.GetPreparedStatement(LOGIN_REP_ACCOUNT_HEIRLOOMS);
244 stmt->setUInt32(1, heirloom.first);
245 stmt->setUInt32(2, heirloom.second.flags);
246 trans->Append(stmt);
247 }
248}
249
251{
252 return _heirlooms.insert(HeirloomContainer::value_type(itemId, HeirloomData(flags, 0))).second;
253}
254
256{
257 HeirloomContainer::const_iterator itr = _heirlooms.find(itemId);
258 if (itr != _heirlooms.end())
259 return itr->second.bonusId;
260
261 return 0;
262}
263
265{
266 for (auto const& item : _heirlooms)
267 _owner->GetPlayer()->AddHeirloom(item.first, item.second.flags);
268}
269
279
281{
282 Player* player = _owner->GetPlayer();
283 if (!player)
284 return;
285
286 HeirloomEntry const* heirloom = sDB2Manager.GetHeirloomByItemId(itemId);
287 if (!heirloom)
288 return;
289
290 HeirloomContainer::iterator itr = _heirlooms.find(itemId);
291 if (itr == _heirlooms.end())
292 return;
293
294 uint32 flags = itr->second.flags;
295 uint32 bonusId = 0;
296
297 for (size_t upgradeLevel = 0; upgradeLevel < std::size(heirloom->UpgradeItemID); ++upgradeLevel)
298 {
299 if (heirloom->UpgradeItemID[upgradeLevel] == castItem)
300 {
301 flags |= 1 << upgradeLevel;
302 bonusId = heirloom->UpgradeItemBonusListID[upgradeLevel];
303 }
304 }
305
306 for (Item* item : player->GetItemListByEntry(itemId, true))
307 item->AddBonuses(bonusId);
308
309 // Get heirloom offset to update only one part of dynamic field
310 auto const& heirlooms = player->m_activePlayerData->Heirlooms;
311 uint32 offset = uint32(std::ranges::distance(heirlooms.begin(), std::ranges::find(heirlooms, int32(itemId))));
312
313 player->SetHeirloomFlags(offset, flags);
314 itr->second.flags = flags;
315 itr->second.bonusId = bonusId;
316}
317
319{
320 Player* player = _owner->GetPlayer();
321 if (!player)
322 return;
323
324 // Check already owned heirloom for upgrade kits
325 if (HeirloomEntry const* heirloom = sDB2Manager.GetHeirloomByItemId(item->GetEntry()))
326 {
327 HeirloomContainer::iterator itr = _heirlooms.find(item->GetEntry());
328 if (itr == _heirlooms.end())
329 return;
330
331 // Check for heirloom pairs (normal - heroic, heroic - mythic)
332 uint32 heirloomItemId = heirloom->StaticUpgradedItemID;
333 uint32 newItemId = 0;
334 while (HeirloomEntry const* heirloomDiff = sDB2Manager.GetHeirloomByItemId(heirloomItemId))
335 {
336 if (player->GetItemByEntry(heirloomDiff->ItemID))
337 newItemId = heirloomDiff->ItemID;
338
339 if (HeirloomEntry const* heirloomSub = sDB2Manager.GetHeirloomByItemId(heirloomDiff->StaticUpgradedItemID))
340 {
341 heirloomItemId = heirloomSub->ItemID;
342 continue;
343 }
344
345 break;
346 }
347
348 if (newItemId)
349 {
350 auto const& heirlooms = player->m_activePlayerData->Heirlooms;
351 uint32 offset = uint32(std::ranges::distance(heirlooms.begin(), std::ranges::find(heirlooms, int32(itr->first))));
352
353 player->SetHeirloom(offset, newItemId);
354 player->SetHeirloomFlags(offset, 0);
355
356 _heirlooms.erase(itr);
357 _heirlooms[newItemId] = 0;
358
359 return;
360 }
361
362 std::vector<int32> const& bonusListIDs = item->GetBonusListIDs();
363
364 for (uint32 bonusId : bonusListIDs)
365 {
366 if (bonusId != itr->second.bonusId)
367 {
368 item->ClearBonuses();
369 break;
370 }
371 }
372
373 if (!advstd::ranges::contains(bonusListIDs, int32(itr->second.bonusId)))
374 item->AddBonuses(itr->second.bonusId);
375 }
376}
377
379{
380 for (auto const& m : _mounts)
381 AddMount(m.first, m.second, false, false);
382}
383
385{
386 if (!result)
387 return;
388
389 do
390 {
391 Field* fields = result->Fetch();
392 uint32 mountSpellId = fields[0].GetUInt32();
393 MountStatusFlags flags = MountStatusFlags(fields[1].GetUInt8());
394
395 if (!sDB2Manager.GetMount(mountSpellId))
396 continue;
397
398 _mounts[mountSpellId] = flags;
399 } while (result->NextRow());
400}
401
403{
404 for (auto const& mount : _mounts)
405 {
408 stmt->setUInt32(1, mount.first);
409 stmt->setUInt8(2, mount.second);
410 trans->Append(stmt);
411 }
412}
413
414bool CollectionMgr::AddMount(uint32 spellId, MountStatusFlags flags, bool factionMount /*= false*/, bool learned /*= false*/)
415{
416 Player* player = _owner->GetPlayer();
417 if (!player)
418 return false;
419
420 MountEntry const* mount = sDB2Manager.GetMount(spellId);
421 if (!mount)
422 return false;
423
424 MountDefinitionMap::const_iterator itr = FactionSpecificMounts.find(spellId);
425 if (itr != FactionSpecificMounts.end() && !factionMount)
426 AddMount(itr->second, flags, true, learned);
427
428 _mounts.insert(MountContainer::value_type(spellId, flags));
429
430 // Mount condition only applies to using it, should still learn it.
432 return false;
433
434 if (!learned)
435 {
436 if (!factionMount)
437 SendSingleMountUpdate(std::make_pair(spellId, flags));
438 if (!player->HasSpell(spellId))
439 player->LearnSpell(spellId, true);
440 }
441
442 return true;
443}
444
445void CollectionMgr::MountSetFavorite(uint32 spellId, bool favorite)
446{
447 auto itr = _mounts.find(spellId);
448 if (itr == _mounts.end())
449 return;
450
451 if (favorite)
452 itr->second = MountStatusFlags(itr->second | MOUNT_IS_FAVORITE);
453 else
454 itr->second = MountStatusFlags(itr->second & ~MOUNT_IS_FAVORITE);
455
457}
458
459void CollectionMgr::SendSingleMountUpdate(std::pair<uint32, MountStatusFlags> mount)
460{
461 Player* player = _owner->GetPlayer();
462 if (!player)
463 return;
464
465 // Temporary container, just need to store only selected mount
466 MountContainer tempMounts;
467 tempMounts.insert(mount);
468
470 mountUpdate.IsFullUpdate = false;
471 mountUpdate.Mounts = &tempMounts;
472 player->SendDirectMessage(mountUpdate.Write());
473}
474
475template <std::invocable<uint32> OutputAction>
477{
478 using iterator_category = std::output_iterator_tag;
479 using value_type = void;
480 using difference_type = void;
481 using pointer = void;
482 using reference = void;
483
484 explicit DynamicBitsetBlockOutputIterator(OutputAction const& action) : _action(&action) { }
485
487 {
488 std::invoke(*_action, value);
489 return *this;
490 }
491
495
496private:
497 OutputAction const* _action;
498};
499
501{
502 Player* owner = _owner->GetPlayer();
503 boost::to_block_range(*_appearances, DynamicBitsetBlockOutputIterator([owner](uint32 blockValue)
504 {
505 owner->AddTransmogBlock(blockValue);
506 }));
507
508 for (auto const& [itemModifiedAppearanceId, _] : _temporaryAppearances)
509 owner->AddConditionalTransmog(itemModifiedAppearanceId);
510}
511
513{
514 if (knownAppearances)
515 {
516 std::vector<uint32> blocks;
517 do
518 {
519 Field* fields = knownAppearances->Fetch();
520 uint16 blobIndex = fields[0].GetUInt16();
521 if (blobIndex >= blocks.size())
522 blocks.resize(blobIndex + 1);
523
524 blocks[blobIndex] = fields[1].GetUInt32();
525
526 } while (knownAppearances->NextRow());
527
528 _appearances->resize(blocks.size() * 32);
529 boost::from_block_range(blocks.begin(), blocks.end(), *_appearances);
530 }
531
532 if (favoriteAppearances)
533 {
534 do
535 {
536 _favoriteAppearances[favoriteAppearances->Fetch()[0].GetUInt32()] = CollectionItemState::Unchanged;
537 } while (favoriteAppearances->NextRow());
538 }
539
540 // Static item appearances known by every player
541 static uint32 constexpr hiddenAppearanceItems[] =
542 {
543 134110, // Hidden Helm
544 134111, // Hidden Cloak
545 134112, // Hidden Shoulder
546 168659, // Hidden Chestpiece
547 142503, // Hidden Shirt
548 142504, // Hidden Tabard
549 168665, // Hidden Bracers
550 158329, // Hidden Gloves
551 143539, // Hidden Belt
552 168664 // Hidden Boots
553 };
554
555 for (uint32 hiddenItem : hiddenAppearanceItems)
556 {
558 ASSERT(hiddenAppearance);
559 if (_appearances->size() <= hiddenAppearance->ID)
560 _appearances->resize(hiddenAppearance->ID + 1);
561
562 _appearances->set(hiddenAppearance->ID);
563 }
564}
565
567{
568 uint16 blockIndex = 0;
569 boost::to_block_range(*_appearances, DynamicBitsetBlockOutputIterator([this, &blockIndex, trans = trans.get()](uint32 blockValue)
570 {
571 if (blockValue) // this table is only appended/bits are set (never cleared) so don't save empty blocks
572 {
573 LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_ITEM_APPEARANCES);
574 stmt->setUInt32(0, _owner->GetBattlenetAccountId());
575 stmt->setUInt16(1, blockIndex);
576 stmt->setUInt32(2, blockValue);
577 trans->Append(stmt);
578 }
579
580 ++blockIndex;
581 }));
582
584 for (auto itr = _favoriteAppearances.begin(); itr != _favoriteAppearances.end();)
585 {
586 switch (itr->second)
587 {
589 stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_ITEM_FAVORITE_APPEARANCE);
590 stmt->setUInt32(0, _owner->GetBattlenetAccountId());
591 stmt->setUInt32(1, itr->first);
592 trans->Append(stmt);
593 itr->second = CollectionItemState::Unchanged;
594 ++itr;
595 break;
597 stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_BNET_ITEM_FAVORITE_APPEARANCE);
598 stmt->setUInt32(0, _owner->GetBattlenetAccountId());
599 stmt->setUInt32(1, itr->first);
600 trans->Append(stmt);
601 itr = _favoriteAppearances.erase(itr);
602 break;
605 ++itr;
606 break;
607 }
608 }
609}
610
612{
613 if (!item->IsSoulBound())
614 return;
615
616 ItemModifiedAppearanceEntry const* itemModifiedAppearance = item->GetItemModifiedAppearance();
617 if (!CanAddAppearance(itemModifiedAppearance))
618 return;
619
620 if (item->IsBOPTradeable() || item->IsRefundable())
621 {
622 AddTemporaryAppearance(item->GetGUID(), itemModifiedAppearance);
623 return;
624 }
625
626 AddItemAppearance(itemModifiedAppearance);
627}
628
629void CollectionMgr::AddItemAppearance(uint32 itemId, uint32 appearanceModId /*= 0*/)
630{
631 ItemModifiedAppearanceEntry const* itemModifiedAppearance = TransmogMgr::GetItemModifiedAppearance(itemId, appearanceModId);
632 if (!CanAddAppearance(itemModifiedAppearance))
633 return;
634
635 AddItemAppearance(itemModifiedAppearance);
636}
637
639{
640 for (TransmogSetItemEntry const* item : TransmogMgr::GetTransmogSetItems(transmogSetId))
641 {
642 ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(item->ItemModifiedAppearanceID);
643 if (!itemModifiedAppearance)
644 continue;
645
646 AddItemAppearance(itemModifiedAppearance);
647 }
648}
649
650bool CollectionMgr::IsSetCompleted(uint32 transmogSetId) const
651{
652 std::span<TransmogSetItemEntry const* const> transmogSetItems = TransmogMgr::GetTransmogSetItems(transmogSetId);
653 if (transmogSetItems.empty())
654 return false;
655
656 std::array<int8, EQUIPMENT_SLOT_END> knownPieces;
657 knownPieces.fill(-1);
658 for (TransmogSetItemEntry const* transmogSetItem : transmogSetItems)
659 {
660 ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(transmogSetItem->ItemModifiedAppearanceID);
661 if (!itemModifiedAppearance)
662 continue;
663
664 ItemEntry const* item = sItemStore.LookupEntry(itemModifiedAppearance->ItemID);
665 if (!item)
666 continue;
667
668 int32 transmogSlot = ItemTransmogrificationSlots[item->InventoryType];
669 if (transmogSlot < 0 || knownPieces[transmogSlot] == 1)
670 continue;
671
672 auto [hasAppearance, isTemporary] = HasItemAppearance(transmogSetItem->ItemModifiedAppearanceID);
673
674 knownPieces[transmogSlot] = (hasAppearance && !isTemporary) ? 1 : 0;
675 }
676
677 return !advstd::ranges::contains(knownPieces, 0);
678}
679
680bool CollectionMgr::CanAddAppearance(ItemModifiedAppearanceEntry const* itemModifiedAppearance) const
681{
682 if (!itemModifiedAppearance)
683 return false;
684
685 if (itemModifiedAppearance->TransmogSourceTypeEnum == 6 || itemModifiedAppearance->TransmogSourceTypeEnum == 9)
686 return false;
687
688 if (!sItemSearchNameStore.LookupEntry(itemModifiedAppearance->ItemID))
689 return false;
690
691 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemModifiedAppearance->ItemID);
692 if (!itemTemplate)
693 return false;
694
695 if (itemTemplate->HasFlag(ITEM_FLAG2_NO_SOURCE_FOR_ITEM_VISUAL) || itemTemplate->GetQuality() == ITEM_QUALITY_ARTIFACT)
696 return false;
697
698 switch (itemTemplate->GetClass())
699 {
701 {
702 if (itemTemplate->GetSubClass() == ITEM_SUBCLASS_WEAPON_EXOTIC ||
703 itemTemplate->GetSubClass() == ITEM_SUBCLASS_WEAPON_EXOTIC2 ||
705 itemTemplate->GetSubClass() == ITEM_SUBCLASS_WEAPON_THROWN ||
706 itemTemplate->GetSubClass() == ITEM_SUBCLASS_WEAPON_SPEAR ||
708 return false;
709 break;
710 }
711 case ITEM_CLASS_ARMOR:
712 {
713 switch (itemTemplate->GetInventoryType())
714 {
715 case INVTYPE_BODY:
716 case INVTYPE_SHIELD:
717 case INVTYPE_CLOAK:
718 case INVTYPE_TABARD:
719 case INVTYPE_HOLDABLE:
720 break;
721 case INVTYPE_HEAD:
723 case INVTYPE_CHEST:
724 case INVTYPE_WAIST:
725 case INVTYPE_LEGS:
726 case INVTYPE_FEET:
727 case INVTYPE_WRISTS:
728 case INVTYPE_HANDS:
729 case INVTYPE_ROBE:
730 if (itemTemplate->GetSubClass() == ITEM_SUBCLASS_ARMOR_MISCELLANEOUS)
731 return false;
732 break;
733 default:
734 return false;
735 }
736 break;
737 }
738 default:
739 return false;
740 }
741
742 if (itemModifiedAppearance->ID < _appearances->size() && _appearances->test(itemModifiedAppearance->ID))
743 return false;
744
745 return true;
746}
747
749{
750 Player* owner = _owner->GetPlayer();
751 if (_appearances->size() <= itemModifiedAppearance->ID)
752 {
753 std::size_t numBlocks = _appearances->num_blocks();
754 _appearances->resize(itemModifiedAppearance->ID + 1);
755 numBlocks = _appearances->num_blocks() - numBlocks;
756 while (numBlocks--)
757 owner->AddTransmogBlock(0);
758 }
759
760 _appearances->set(itemModifiedAppearance->ID);
761 uint32 blockIndex = itemModifiedAppearance->ID / 32;
762 uint32 bitIndex = itemModifiedAppearance->ID % 32;
763 owner->AddTransmogFlag(blockIndex, 1 << bitIndex);
764 auto temporaryAppearance = _temporaryAppearances.find(itemModifiedAppearance->ID);
765 if (temporaryAppearance != _temporaryAppearances.end())
766 {
767 owner->RemoveConditionalTransmog(itemModifiedAppearance->ID);
768 _temporaryAppearances.erase(temporaryAppearance);
769 }
770
772
773 if (ItemEntry const* item = sItemStore.LookupEntry(itemModifiedAppearance->ItemID))
774 {
775 int32 transmogSlot = ItemTransmogrificationSlots[item->InventoryType];
776 if (transmogSlot >= 0)
777 owner->UpdateCriteria(CriteriaType::LearnAnyTransmogInSlot, transmogSlot, itemModifiedAppearance->ID);
778 }
779
780 for (TransmogSetEntry const* set : TransmogMgr::GetTransmogSetsForItemModifiedAppearance(itemModifiedAppearance->ID))
781 {
782 if (IsSetCompleted(set->ID))
783 {
784 if (Quest const* quest = sObjectMgr->GetQuestTemplate(set->TrackingQuestID))
785 owner->RewardQuest(quest, LootItemType::Item, 0, owner, false);
786
787 owner->UpdateCriteria(CriteriaType::CollectTransmogSetFromGroup, set->TransmogSetGroupID);
788 }
789 }
790}
791
792void CollectionMgr::AddTemporaryAppearance(ObjectGuid const& itemGuid, ItemModifiedAppearanceEntry const* itemModifiedAppearance)
793{
794 std::unordered_set<ObjectGuid>& itemsWithAppearance = _temporaryAppearances[itemModifiedAppearance->ID];
795 if (itemsWithAppearance.empty())
796 _owner->GetPlayer()->AddConditionalTransmog(itemModifiedAppearance->ID);
797
798 itemsWithAppearance.insert(itemGuid);
799}
800
802{
803 ItemModifiedAppearanceEntry const* itemModifiedAppearance = item->GetItemModifiedAppearance();
804 if (!itemModifiedAppearance)
805 return;
806
807 auto itr = _temporaryAppearances.find(itemModifiedAppearance->ID);
808 if (itr == _temporaryAppearances.end())
809 return;
810
811 itr->second.erase(item->GetGUID());
812 if (itr->second.empty())
813 {
814 _owner->GetPlayer()->RemoveConditionalTransmog(itemModifiedAppearance->ID);
815 _temporaryAppearances.erase(itr);
816 }
817}
818
819std::pair<bool, bool> CollectionMgr::HasItemAppearance(uint32 itemModifiedAppearanceId) const
820{
821 if (itemModifiedAppearanceId < _appearances->size() && _appearances->test(itemModifiedAppearanceId))
822 return { true, false };
823
824 if (_temporaryAppearances.contains(itemModifiedAppearanceId))
825 return { true, true };
826
827 return { false, false };
828}
829
830std::unordered_set<ObjectGuid> CollectionMgr::GetItemsProvidingTemporaryAppearance(uint32 itemModifiedAppearanceId) const
831{
832 auto temporaryAppearance = _temporaryAppearances.find(itemModifiedAppearanceId);
833 if (temporaryAppearance != _temporaryAppearances.end())
834 return temporaryAppearance->second;
835
836 return std::unordered_set<ObjectGuid>();
837}
838
839std::unordered_set<uint32> CollectionMgr::GetAppearanceIds() const
840{
841 std::unordered_set<uint32> appearances;
842 std::size_t id = _appearances->find_first();
843 while (id != boost::dynamic_bitset<uint32>::npos)
844 {
845 appearances.insert(sItemModifiedAppearanceStore.AssertEntry(id)->ItemAppearanceID);
846 id = _appearances->find_next(id);
847 }
848
849 return appearances;
850}
851
852void CollectionMgr::SetAppearanceIsFavorite(uint32 itemModifiedAppearanceId, bool apply)
853{
854 auto itr = _favoriteAppearances.find(itemModifiedAppearanceId);
855 if (apply)
856 {
857 if (itr == _favoriteAppearances.end())
858 _favoriteAppearances[itemModifiedAppearanceId] = CollectionItemState::New;
859 else if (itr->second == CollectionItemState::Removed)
860 itr->second = CollectionItemState::Unchanged;
861 else
862 return;
863 }
864 else if (itr != _favoriteAppearances.end())
865 {
866 if (itr->second == CollectionItemState::New)
867 _favoriteAppearances.erase(itemModifiedAppearanceId);
868 else
869 itr->second = CollectionItemState::Removed;
870 }
871 else
872 return;
873
875 accountTransmogUpdate.IsFullUpdate = false;
876 accountTransmogUpdate.IsSetFavorite = apply;
877 accountTransmogUpdate.FavoriteAppearances.push_back(itemModifiedAppearanceId);
878
879 _owner->SendPacket(accountTransmogUpdate.Write());
880}
881
883{
885 accountTransmogUpdate.IsFullUpdate = true;
886 accountTransmogUpdate.FavoriteAppearances.reserve(_favoriteAppearances.size());
887 for (auto [itemModifiedAppearanceId, state] : _favoriteAppearances)
888 if (state != CollectionItemState::Removed)
889 accountTransmogUpdate.FavoriteAppearances.push_back(itemModifiedAppearanceId);
890
891 _owner->SendPacket(accountTransmogUpdate.Write());
892}
893
895{
896 Player* owner = _owner->GetPlayer();
897 boost::to_block_range(*_transmogIllusions, DynamicBitsetBlockOutputIterator([owner](uint32 blockValue)
898 {
899 owner->AddIllusionBlock(blockValue);
900 }));
901}
902
904{
905 if (knownTransmogIllusions)
906 {
907 std::vector<uint32> blocks;
908 do
909 {
910 Field* fields = knownTransmogIllusions->Fetch();
911 uint16 blobIndex = fields[0].GetUInt16();
912 if (blobIndex >= blocks.size())
913 blocks.resize(blobIndex + 1);
914
915 blocks[blobIndex] = fields[1].GetUInt32();
916
917 } while (knownTransmogIllusions->NextRow());
918
919 _transmogIllusions->resize(blocks.size() * 32);
920 boost::from_block_range(blocks.begin(), blocks.end(), *_transmogIllusions);
921 }
922
923 // Static illusions known by every player
924 static uint16 constexpr defaultIllusions[] =
925 {
926 3, // Lifestealing
927 13, // Crusader
928 22, // Striking
929 23, // Agility
930 34, // Hide Weapon Enchant
931 43, // Beastslayer
932 44, // Titanguard
933 };
934
935 for (uint16 illusionId : defaultIllusions)
936 {
937 if (_transmogIllusions->size() <= illusionId)
938 _transmogIllusions->resize(illusionId + 1);
939
940 _transmogIllusions->set(illusionId);
941 }
942}
943
945{
946 uint16 blockIndex = 0;
947
948 boost::to_block_range(*_transmogIllusions, DynamicBitsetBlockOutputIterator([this, &blockIndex, trans = trans.get()](uint32 blockValue)
949 {
950 if (blockValue) // this table is only appended/bits are set (never cleared) so don't save empty blocks
951 {
952 LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_TRANSMOG_ILLUSIONS);
953 stmt->setUInt32(0, _owner->GetBattlenetAccountId());
954 stmt->setUInt16(1, blockIndex);
955 stmt->setUInt32(2, blockValue);
956 trans->Append(stmt);
957 }
958 ++blockIndex;
959 }));
960}
961
963{
964 Player* owner = _owner->GetPlayer();
965 if (_transmogIllusions->size() <= transmogIllusionId)
966 {
967 std::size_t numBlocks = _transmogIllusions->num_blocks();
968 _transmogIllusions->resize(transmogIllusionId + 1);
969 numBlocks = _transmogIllusions->num_blocks() - numBlocks;
970 while (numBlocks--)
971 owner->AddIllusionBlock(0);
972 }
973
974 _transmogIllusions->set(transmogIllusionId);
975 uint32 blockIndex = transmogIllusionId / 32;
976 uint32 bitIndex = transmogIllusionId % 32;
977
978 owner->AddIllusionFlag(blockIndex, 1 << bitIndex);
979}
980
981bool CollectionMgr::HasTransmogIllusion(uint32 transmogIllusionId) const
982{
983 return transmogIllusionId < _transmogIllusions->size() && _transmogIllusions->test(transmogIllusionId);
984}
985
990
992{
993 if (unlockedTransmogOutfits)
994 {
995 do
996 {
997 Field* fields = unlockedTransmogOutfits->Fetch();
998
999 int32 transmogOutfitId = fields[0].GetInt32();
1000
1001 if (!sTransmogOutfitEntryStore.HasRecord(transmogOutfitId))
1002 continue;
1003
1004 _transmogOutfits.insert(transmogOutfitId);
1005
1006 } while (unlockedTransmogOutfits->NextRow());
1007 }
1008
1010 _transmogOutfits.insert(transmogOutfitEntry->ID);
1011}
1012
1014{
1015 for (int32 transmogOutfitId : _transmogOutfits)
1016 {
1019 stmt->setInt32(1, transmogOutfitId);
1020 trans->Append(stmt);
1021 }
1022}
1023
1025{
1026 if (_transmogOutfits.insert(transmogOutfitId).second)
1027 _owner->GetPlayer()->AddUnlockedTransmogOutfit(transmogOutfitId);
1028}
1029
1030bool CollectionMgr::HasTransmogOutfit(int32 transmogOutfitId) const
1031{
1032 return _transmogOutfits.contains(transmogOutfitId);
1033}
1034
1036{
1037 Player* owner = _owner->GetPlayer();
1038 for (auto const& [warbandSceneId, _] : _warbandScenes)
1039 owner->AddWarbandScenesFlag(warbandSceneId / 32, 1 << warbandSceneId % 32);
1040}
1041
1043{
1044 if (knownWarbandScenes)
1045 {
1046 do
1047 {
1048 Field* fields = knownWarbandScenes->Fetch();
1049 uint32 warbandSceneId = fields[0].GetUInt32();
1050 if (!sWarbandSceneStore.HasRecord(warbandSceneId))
1051 {
1052 _warbandScenes[warbandSceneId].State = CollectionItemState::Removed;
1053 continue;
1054 }
1055
1056 bool isFavorite = fields[1].GetBool();
1057 bool hasFanfare = fields[2].GetBool();
1058
1059 WarbandSceneCollectionItem& warbandScene = _warbandScenes.try_emplace(warbandSceneId).first->second;
1060 if (isFavorite)
1062
1063 if (hasFanfare)
1065
1066 } while (knownWarbandScenes->NextRow());
1067 }
1068
1069 for (uint32 warbandSceneId : DefaultWarbandScenes)
1070 if (auto [itr, isNew] = _warbandScenes.try_emplace(warbandSceneId); isNew)
1071 itr->second.State = CollectionItemState::New;
1072}
1073
1075{
1077 for (auto itr = _warbandScenes.begin(); itr != _warbandScenes.end(); )
1078 {
1079 auto& [warbandSceneId, data] = *itr;
1080 switch (data.State)
1081 {
1083 stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_WARBAND_SCENE);
1085 stmt->setUInt32(1, warbandSceneId);
1086 stmt->setBool(2, data.Flags.HasFlag(WarbandSceneCollectionFlags::Favorite));
1087 stmt->setBool(3, data.Flags.HasFlag(WarbandSceneCollectionFlags::HasFanfare));
1088 trans->Append(stmt);
1089 data.State = CollectionItemState::Unchanged;
1090 ++itr;
1091 break;
1093 stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_WARBAND_SCENE);
1094 stmt->setBool(0, data.Flags.HasFlag(WarbandSceneCollectionFlags::Favorite));
1095 stmt->setBool(1, data.Flags.HasFlag(WarbandSceneCollectionFlags::HasFanfare));
1097 stmt->setUInt32(3, warbandSceneId);
1098 trans->Append(stmt);
1099 data.State = CollectionItemState::Unchanged;
1100 ++itr;
1101 break;
1103 stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_BNET_WARBAND_SCENE);
1105 stmt->setUInt32(1, warbandSceneId);
1106 trans->Append(stmt);
1107 itr = _warbandScenes.erase(itr);
1108 break;
1109 default:
1110 ++itr;
1111 break;
1112 }
1113 }
1114}
1115
1117{
1118 if (!sWarbandSceneStore.HasRecord(warbandSceneId))
1119 return;
1120
1121 WarbandSceneCollectionItem& warbandScene = _warbandScenes.try_emplace(warbandSceneId).first->second;
1122 warbandScene.State = CollectionItemState::New;
1123
1124 uint32 blockIndex = warbandSceneId / 32;
1125 uint32 bitIndex = warbandSceneId % 32;
1126 _owner->GetPlayer()->AddWarbandScenesFlag(blockIndex, 1 << bitIndex);
1127}
1128
1129bool CollectionMgr::HasWarbandScene(uint32 warbandSceneId) const
1130{
1131 return _warbandScenes.contains(warbandSceneId);
1132}
1133
1134void CollectionMgr::SetWarbandSceneIsFavorite(uint32 warbandSceneId, bool apply)
1135{
1137 if (!warbandScene)
1138 return;
1139
1140 if (apply)
1142 else
1144
1145 if (warbandScene->State == CollectionItemState::Unchanged)
1146 warbandScene->State = CollectionItemState::Changed;
1147}
1148
1150{
1152 accountItemCollection.Type = ItemCollectionType::WarbandScene;
1153
1154 for (auto const& [warbandSceneId, data] : _warbandScenes)
1155 {
1156 if (data.State == CollectionItemState::Removed)
1157 continue;
1158
1159 WorldPackets::Collections::ItemCollectionItemData& item = accountItemCollection.Items.emplace_back();
1160 item.ID = warbandSceneId;
1162 item.Flags = data.Flags.AsUnderlyingType();
1163 }
1164
1165 _owner->SendPacket(accountItemCollection.Write());
1166}
ToyFlags
MountStatusFlags
@ MOUNT_IS_FAVORITE
std::map< uint32, MountStatusFlags > MountContainer
std::unordered_map< uint32, uint32 > MountDefinitionMap
WarbandSceneCollectionFlags
DB2Storage< ItemEntry > sItemStore("Item.db2", &ItemLoadInfo::Instance)
DB2Storage< ItemSearchNameEntry > sItemSearchNameStore("ItemSearchName.db2", &ItemSearchNameLoadInfo::Instance)
DB2Storage< TransmogOutfitEntryEntry > sTransmogOutfitEntryStore("TransmogOutfitEntry.db2", &TransmogOutfitEntryLoadInfo::Instance)
DB2Storage< ItemModifiedAppearanceEntry > sItemModifiedAppearanceStore("ItemModifiedAppearance.db2", &ItemModifiedAppearanceLoadInfo::Instance)
DB2Storage< WarbandSceneEntry > sWarbandSceneStore("WarbandScene.db2", &WarbandSceneLoadInfo::Instance)
#define sDB2Manager
Definition DB2Stores.h:569
@ LearnAnyTransmogInSlot
@ CollectTransmogSetFromGroup
SQLTransaction< LoginDatabaseConnection > LoginDatabaseTransaction
std::shared_ptr< ResultSet > QueryResult
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< LoginDatabaseConnection > LoginDatabase
Accessor to the realm/login database.
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
int32_t int32
Definition Define.h:150
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
uint16 flags
#define ASSERT
Definition Errors.h:80
@ ITEM_CLASS_ARMOR
@ ITEM_CLASS_WEAPON
@ ITEM_FLAG2_NO_SOURCE_FOR_ITEM_VISUAL
@ ITEM_SUBCLASS_WEAPON_MISCELLANEOUS
@ ITEM_SUBCLASS_WEAPON_SPEAR
@ ITEM_SUBCLASS_WEAPON_EXOTIC2
@ ITEM_SUBCLASS_WEAPON_FISHING_POLE
@ ITEM_SUBCLASS_WEAPON_EXOTIC
@ ITEM_SUBCLASS_WEAPON_THROWN
@ ITEM_SUBCLASS_ARMOR_MISCELLANEOUS
@ INVTYPE_BODY
@ INVTYPE_HEAD
@ INVTYPE_CLOAK
@ INVTYPE_ROBE
@ INVTYPE_HOLDABLE
@ INVTYPE_WAIST
@ INVTYPE_WRISTS
@ INVTYPE_SHOULDERS
@ INVTYPE_FEET
@ INVTYPE_SHIELD
@ INVTYPE_TABARD
@ INVTYPE_LEGS
@ INVTYPE_CHEST
@ INVTYPE_HANDS
int32 const ItemTransmogrificationSlots[MAX_INVTYPE]
Definition Item.cpp:2014
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define TC_LOG_INFO(filterType__, message__,...)
Definition Log.h:184
@ LOGIN_UPD_BNET_WARBAND_SCENE
@ LOGIN_INS_BNET_TRANSMOG_OUTFITS
@ LOGIN_DEL_BNET_WARBAND_SCENE
@ LOGIN_REP_ACCOUNT_MOUNTS
@ LOGIN_REP_ACCOUNT_HEIRLOOMS
@ LOGIN_INS_BNET_ITEM_FAVORITE_APPEARANCE
@ LOGIN_INS_BNET_WARBAND_SCENE
@ LOGIN_REP_ACCOUNT_TOYS
@ LOGIN_DEL_BNET_ITEM_FAVORITE_APPEARANCE
#define sObjectMgr
Definition ObjectMgr.h:1885
@ ITEM_QUALITY_ARTIFACT
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:57
uint32 getMSTime()
Definition Timer.h:33
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:565
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
void AddTemporaryAppearance(ObjectGuid const &itemGuid, ItemModifiedAppearanceEntry const *itemModifiedAppearance)
bool UpdateAccountToys(uint32 itemId, bool isFavourite, bool hasFanfare)
void RemoveTemporaryAppearance(Item *item)
void LoadAccountTransmogOutfits(PreparedQueryResult unlockedTransmogOutfits)
void AddItemAppearance(Item *item)
void LoadAccountMounts(PreparedQueryResult result)
void MountSetFavorite(uint32 spellId, bool favorite)
void LoadTransmogOutfits()
void SetWarbandSceneIsFavorite(uint32 warbandSceneId, bool apply)
void SendWarbandSceneCollectionData() const
bool IsSetCompleted(uint32 transmogSetId) const
void SaveAccountToys(LoginDatabaseTransaction trans)
bool UpdateAccountHeirlooms(uint32 itemId, uint32 flags)
void LoadAccountWarbandScenes(PreparedQueryResult knownWarbandScenes)
void ToyClearFanfare(uint32 itemId)
void AddTransmogSet(uint32 transmogSetId)
WorldSession * _owner
void OnItemAdded(Item *item)
HeirloomContainer _heirlooms
void SendSingleMountUpdate(std::pair< uint32, MountStatusFlags > mount)
void SaveAccountTransmogIllusions(LoginDatabaseTransaction trans)
void AddTransmogOutfit(int32 transmogOutfitId)
std::unordered_map< uint32, std::unordered_set< ObjectGuid > > _temporaryAppearances
uint32 GetHeirloomBonus(uint32 itemId) const
MountContainer _mounts
void SaveAccountMounts(LoginDatabaseTransaction trans)
void ToySetFavorite(uint32 itemId, bool favorite)
bool HasTransmogIllusion(uint32 transmogIllusionId) const
void SaveAccountHeirlooms(LoginDatabaseTransaction trans)
std::unordered_map< uint32, CollectionItemState > _favoriteAppearances
bool AddMount(uint32 spellId, MountStatusFlags flags, bool factionMount=false, bool learned=false)
std::unique_ptr< boost::dynamic_bitset< uint32 > > _appearances
void LoadTransmogIllusions()
std::unordered_set< ObjectGuid > GetItemsProvidingTemporaryAppearance(uint32 itemModifiedAppearanceId) const
void UpgradeHeirloom(uint32 itemId, int32 castItem)
static void LoadWarbandSceneDefinitions()
bool HasWarbandScene(uint32 warbandSceneId) const
void LoadAccountHeirlooms(PreparedQueryResult result)
std::unordered_set< uint32 > GetAppearanceIds() const
std::unique_ptr< boost::dynamic_bitset< uint32 > > _transmogIllusions
void LoadAccountTransmogIllusions(PreparedQueryResult knownTransmogIllusions)
CollectionMgr(WorldSession *owner)
bool AddToy(uint32 itemId, bool isFavourite, bool hasFanfare)
void SaveAccountWarbandScenes(LoginDatabaseTransaction trans)
void AddHeirloom(uint32 itemId, uint32 flags)
void CheckHeirloomUpgrades(Item *item)
void LoadAccountItemAppearances(PreparedQueryResult knownAppearances, PreparedQueryResult favoriteAppearances)
std::pair< bool, bool > HasItemAppearance(uint32 itemModifiedAppearanceId) const
void SaveAccountTransmogOutfits(LoginDatabaseTransaction trans)
bool CanAddAppearance(ItemModifiedAppearanceEntry const *itemModifiedAppearance) const
void AddWarbandScene(uint32 warbandSceneId)
void SetAppearanceIsFavorite(uint32 itemModifiedAppearanceId, bool apply)
static void LoadMountDefinitions()
void SendFavoriteAppearances() const
void SaveAccountItemAppearances(LoginDatabaseTransaction trans)
void AddTransmogIllusion(uint32 transmogIllusionId)
WarbandSceneCollectionContainer _warbandScenes
void LoadAccountToys(PreparedQueryResult result)
void LoadItemAppearances()
Trinity::Containers::FlatSet< int32 > _transmogOutfits
bool HasTransmogOutfit(int32 transmogOutfitId) const
ToyBoxContainer _toys
void SaveToDB(LoginDatabaseTransaction trans)
static bool IsPlayerMeetingCondition(Player const *player, uint32 conditionId)
Class used to access individual fields of database query result.
Definition Field.h:94
bool GetBool() const noexcept
Definition Field.h:102
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
uint16 GetUInt16() const noexcept
Definition Field.cpp:43
int32 GetInt32() const noexcept
Definition Field.cpp:64
Definition Item.h:179
void AddBonuses(uint32 bonusListID)
Definition Item.cpp:2581
void ClearBonuses()
Definition Item.cpp:2609
std::vector< int32 > const & GetBonusListIDs() const
Definition Item.h:239
bool IsBOPTradeable() const
Definition Item.h:259
bool IsSoulBound() const
Definition Item.h:227
bool IsRefundable() const
Definition Item.h:258
ItemModifiedAppearanceEntry const * GetItemModifiedAppearance() const
Definition Item.cpp:2465
uint32 GetEntry() const
Definition Object.h:89
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6283
UF::UpdateField< UF::ActivePlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_ACTIVE_PLAYER > m_activePlayerData
Definition Player.h:3062
Item * GetItemByEntry(uint32 entry, ItemSearchLocation where=ItemSearchLocation::Default) const
Definition Player.cpp:12475
void AddTransmogFlag(uint32 slot, uint32 flag)
Definition Player.h:2970
void LearnSpell(uint32 spell_id, bool dependent, int32 fromSkill=0, bool suppressMessaging=false, Optional< PlayerSpellTrait > trait={})
Definition Player.cpp:3178
void UpdateCriteria(CriteriaType type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, WorldObject *ref=nullptr)
Definition Player.cpp:27588
void AddConditionalTransmog(uint32 itemModifiedAppearanceId)
Definition Player.h:2972
void AddUnlockedTransmogOutfit(int32 transmogOutfitIds)
Definition Player.h:3049
void AddIllusionBlock(uint32 blockValue)
Definition Player.h:2980
void RemoveConditionalTransmog(uint32 itemModifiedAppearanceId)
Definition Player.h:2973
void AddIllusionFlag(uint32 slot, uint32 flag)
Definition Player.h:2981
void AddWarbandScenesFlag(uint32 slot, uint32 flag)
Definition Player.h:2984
void SetHeirloom(uint32 slot, int32 itemId)
Definition Player.h:2960
void AddUnlockedTransmogOutfits(std::span< int32 const > transmogOutfitIds)
Definition Player.cpp:31124
bool HasSpell(uint32 spell) const override
Definition Player.cpp:3735
void AddToy(int32 itemId, uint32 flags)
Definition Player.h:2963
std::vector< Item * > GetItemListByEntry(uint32 entry, bool inBankAlso=false) const
Definition Player.cpp:12491
void AddHeirloom(int32 itemId, uint32 flags)
Definition Player.h:2955
void RewardQuest(Quest const *quest, LootItemType rewardType, uint32 rewardId, Object *questGiver, bool announce=true)
Definition Player.cpp:15061
void AddTransmogBlock(uint32 blockValue)
Definition Player.h:2969
void SetHeirloomFlags(uint32 slot, uint32 flags)
Definition Player.h:2961
void setUInt32(uint8 index, uint32 value)
void setBool(uint8 index, bool value)
void setInt32(uint8 index, int32 value)
void setUInt8(uint8 index, uint8 value)
bool contains(Key const &value) const
Definition FlatSet.h:42
std::pair< iterator, bool > insert(Key const &key)
Definition FlatSet.h:82
std::vector< ItemCollectionItemData > Items
WorldPacket const * Write() override
Player session in the World.
Player * GetPlayer() const
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
uint32 GetBattlenetAccountId() const
std::span< TransmogSetItemEntry const *const > GetTransmogSetItems(uint32 transmogSetId)
ItemModifiedAppearanceEntry const * GetDefaultItemModifiedAppearance(uint32 itemId)
std::span< TransmogSetEntry const *const > GetTransmogSetsForItemModifiedAppearance(uint32 itemModifiedAppearanceId)
ItemModifiedAppearanceEntry const * GetItemModifiedAppearance(uint32 itemId, uint32 appearanceModId)
std::span< TransmogOutfitEntryEntry const *const > GetAutomaticallyUnlockedOutfits()
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition MapUtils.h:37
struct advstd::ranges::Contains contains
STL namespace.
DynamicBitsetBlockOutputIterator & operator++()
DynamicBitsetBlockOutputIterator(OutputAction const &action)
DynamicBitsetBlockOutputIterator & operator=(uint32 value)
DynamicBitsetBlockOutputIterator & operator*()
std::output_iterator_tag iterator_category
DynamicBitsetBlockOutputIterator operator++(int)
std::array< uint16, 6 > UpgradeItemBonusListID
std::array< int32, 6 > UpgradeItemID
int8 InventoryType
uint32 GetQuality() const
InventoryType GetInventoryType() const
bool HasFlag(ItemFlags flag) const
uint32 GetSubClass() const
uint32 GetClass() const
uint32 PlayerConditionID
CollectionItemState State
EnumFlag< WarbandSceneCollectionFlags > Flags