diff --git a/conf/transmog.conf.dist b/conf/transmog.conf.dist index 90fecdcd..9aaa6be1 100644 --- a/conf/transmog.conf.dist +++ b/conf/transmog.conf.dist @@ -72,6 +72,11 @@ # Transmogrification.EnablePortable # Description: Enables / Disables the portable transmogrification NPC. # Default: 1 +# +# Transmogrification.EnableSortByQualityAndName +# Description: Enables / Disables the sorting of the items by quality and then by names +# Default: 1 +# Transmogrification.Enable = 1 Transmogrification.UseCollectionSystem = 1 @@ -90,6 +95,8 @@ Transmogrification.NotAllowed = "" Transmogrification.EnablePortable = 1 +Transmogrification.EnableSortByQualityAndName = 1 + # # COPPER COST # @@ -220,6 +227,7 @@ Transmogrification.TokenAmount = 1 # Description: Ignore stat count > 0 requirement for source items # Default: 0 + Transmogrification.AllowPoor = 0 Transmogrification.AllowCommon = 0 Transmogrification.AllowUncommon = 1 diff --git a/src/Transmogrification.cpp b/src/Transmogrification.cpp index dc4bc44c..5781480c 100644 --- a/src/Transmogrification.cpp +++ b/src/Transmogrification.cpp @@ -472,7 +472,11 @@ bool Transmogrification::AddCollectedAppearance(uint32 accountId, uint32 itemId) if (std::find(collectionCache[accountId].begin(), collectionCache[accountId].end(), itemId) == collectionCache[accountId].end()) { collectionCache[accountId].push_back(itemId); - std::sort(collectionCache[accountId].begin(), collectionCache[accountId].end()); + + if (!sConfigMgr->GetOption("Transmogrification.EnableSortByQualityAndName", true)) { + std::sort(collectionCache[accountId].begin(), collectionCache[accountId].end()); + } + return true; } return false; @@ -654,19 +658,19 @@ bool Transmogrification::CanTransmogrifyItemWithItem(Player* player, ItemTemplat bool Transmogrification::IsSubclassMismatchAllowed(Player *player, const ItemTemplate *source, const ItemTemplate *target) const { if (IsAllowed(source->ItemId)) return true; - + uint32 sourceType = source->InventoryType; uint32 targetType = target->InventoryType; uint32 sourceClass = source->Class; uint32 targetClass = target->Class; uint32 sourceSub = source->SubClass; uint32 targetSub = target->SubClass; - + if (targetClass == ITEM_CLASS_WEAPON) { if (IsRangedWeapon(sourceClass, sourceSub)) return true; - + if (AllowMixedWeaponTypes == MIXED_WEAPONS_MODERN) { switch (targetSub) @@ -674,8 +678,8 @@ bool Transmogrification::IsSubclassMismatchAllowed(Player *player, const ItemTem case ITEM_SUBCLASS_WEAPON_AXE: case ITEM_SUBCLASS_WEAPON_SWORD: case ITEM_SUBCLASS_WEAPON_MACE: - if (sourceSub == ITEM_SUBCLASS_WEAPON_AXE || - sourceSub == ITEM_SUBCLASS_WEAPON_SWORD || + if (sourceSub == ITEM_SUBCLASS_WEAPON_AXE || + sourceSub == ITEM_SUBCLASS_WEAPON_SWORD || sourceSub == ITEM_SUBCLASS_WEAPON_MACE ) return true; break; @@ -684,13 +688,13 @@ bool Transmogrification::IsSubclassMismatchAllowed(Player *player, const ItemTem case ITEM_SUBCLASS_WEAPON_MACE2: case ITEM_SUBCLASS_WEAPON_STAFF: case ITEM_SUBCLASS_WEAPON_POLEARM: - if (sourceSub == ITEM_SUBCLASS_WEAPON_AXE2 || - sourceSub == ITEM_SUBCLASS_WEAPON_SWORD2 || + if (sourceSub == ITEM_SUBCLASS_WEAPON_AXE2 || + sourceSub == ITEM_SUBCLASS_WEAPON_SWORD2 || sourceSub == ITEM_SUBCLASS_WEAPON_MACE2 || sourceSub == ITEM_SUBCLASS_WEAPON_STAFF || sourceSub == ITEM_SUBCLASS_WEAPON_POLEARM ) return true; - break; + break; } } else if (AllowMixedWeaponTypes == MIXED_WEAPONS_LOOSE) @@ -704,19 +708,19 @@ bool Transmogrification::IsSubclassMismatchAllowed(Player *player, const ItemTem { if (AllowMixedArmorTypes) return true; - if (AllowLowerTiers && IsTieredArmorSubclass(targetSub) && TierAvailable(player, 0, sourceSub)) + if (AllowLowerTiers && IsTieredArmorSubclass(targetSub) && TierAvailable(player, 0, sourceSub)) return true; if (AllowMixedOffhandArmorTypes && IsValidOffhandArmor(targetSub, targetType) && IsValidOffhandArmor(sourceSub, sourceType)) return true; if (sourceSub == ITEM_SUBCLASS_ARMOR_MISC) return sourceType == targetType; } - + return false; } bool Transmogrification::IsInvTypeMismatchAllowed(const ItemTemplate *source, const ItemTemplate *target) const -{ +{ uint32 sourceType = source->InventoryType; uint32 targetType = target->InventoryType; uint32 sourceClass = source->Class; @@ -728,7 +732,7 @@ bool Transmogrification::IsInvTypeMismatchAllowed(const ItemTemplate *source, co { if (IsRangedWeapon(sourceClass, sourceSub)) return true; - + // Main-hand to offhand restrictions - see https://wowpedia.fandom.com/wiki/Transmogrification if (AllowMixedWeaponTypes == MIXED_WEAPONS_LOOSE) return true; @@ -751,7 +755,7 @@ bool Transmogrification::IsInvTypeMismatchAllowed(const ItemTemplate *source, co if (targetType == INVTYPE_CHEST || targetType == INVTYPE_ROBE) return sourceType == INVTYPE_CHEST || sourceType == INVTYPE_ROBE; } - + return false; } diff --git a/src/transmog_scripts.cpp b/src/transmog_scripts.cpp index 4c360798..4ea413ce 100644 --- a/src/transmog_scripts.cpp +++ b/src/transmog_scripts.cpp @@ -364,7 +364,7 @@ bool ValidForTransmog (Player* player, Item* target, Item* source, bool hasSearc if (!target || !source || !player) return false; ItemTemplate const* targetTemplate = target->GetTemplate(); ItemTemplate const* sourceTemplate = source->GetTemplate(); - + if (!sT->CanTransmogrifyItemWithItem(player, targetTemplate, sourceTemplate)) return false; if (sT->GetFakeEntry(target->GetGUID()) == source->GetEntry()) @@ -374,17 +374,26 @@ bool ValidForTransmog (Player* player, Item* target, Item* source, bool hasSearc return true; } +bool CmpTmog (Item* i1, Item* i2) +{ + const ItemTemplate* i1t = i1->GetTemplate(); + const ItemTemplate* i2t = i2->GetTemplate(); + const int q1 = 7-i1t->Quality; + const int q2 = 7-i2t->Quality; + return std::tie(q1, i1t->Name1) < std::tie(q2, i2t->Name1); +} + std::vector GetValidTransmogs (Player* player, Item* target, bool hasSearch, std::string searchTerm) { std::vector allowedItems; if (!target) return allowedItems; - + if (sT->GetUseCollectionSystem()) { uint32 accountId = player->GetSession()->GetAccountId(); if (sT->collectionCache.find(accountId) == sT->collectionCache.end()) return allowedItems; - + for (uint32 itemId : sT->collectionCache[accountId]) { if (!sObjectMgr->GetItemTemplate(itemId)) @@ -415,6 +424,11 @@ std::vector GetValidTransmogs (Player* player, Item* target, bool hasSear } } } + + if (sConfigMgr->GetOption("Transmogrification.EnableSortByQualityAndName", true)) { + sort(allowedItems.begin(), allowedItems.end(), CmpTmog); + } + return allowedItems; } @@ -775,7 +789,7 @@ class npc_transmogrifier : public CreatureScript LocaleConstant locale = session->GetSessionDbLocaleIndex(); Item* oldItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); bool hasSearchString; - + uint16 pageNumber = 0; uint32 startValue = 0; uint32 endValue = MAX_OPTIONS - 4; @@ -786,7 +800,7 @@ class npc_transmogrifier : public CreatureScript startValue = (pageNumber * (MAX_OPTIONS - 2)); endValue = (pageNumber + 1) * (MAX_OPTIONS - 2) - 1; } - + if (oldItem) { uint32 price = GetTransmogPrice(oldItem->GetTemplate()); @@ -800,7 +814,7 @@ class npc_transmogrifier : public CreatureScript hasSearchString = !(searchStringIterator == sT->searchStringByPlayer.end()); std::string searchDisplayValue(hasSearchString ? searchStringIterator->second : GetLocaleText(locale, "search")); std::vector allowedItems = GetValidTransmogs(player, oldItem, hasSearchString, searchDisplayValue); - + if (allowedItems.size() > 0) { lastPage = false; @@ -872,7 +886,7 @@ class npc_transmogrifier : public CreatureScript AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|t" + GetLocaleText(locale, "back"), EQUIPMENT_SLOT_END + 1, 0); SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID()); } - + static std::vector GetSpoofedVendorItems (Item* target) { std::vector spoofedItems; @@ -913,7 +927,7 @@ class npc_transmogrifier : public CreatureScript return 0; } } - + static void EncodeItemToPacket (WorldPacket& data, ItemTemplate const* proto, uint8& slot, uint32 price) { data << uint32(slot + 1); @@ -926,7 +940,7 @@ class npc_transmogrifier : public CreatureScript data << uint32(0); slot++; } - + //The actual vendor options are handled in the player script below, OnBeforeBuyItemFromVendor static void ShowTransmogItemsInFakeVendor (Player* player, Creature* creature, uint8 slot) { @@ -938,26 +952,26 @@ class npc_transmogrifier : public CreatureScript return; } ItemTemplate const* targetTemplate = targetItem->GetTemplate(); - + std::vector itemList = GetValidTransmogs(player, targetItem, false, ""); std::vector spoofedItems = GetSpoofedVendorItems(targetItem); - + uint32 itemCount = itemList.size(); uint32 spoofCount = spoofedItems.size(); uint32 totalItems = itemCount + spoofCount; uint32 price = GetTransmogPrice(targetItem->GetTemplate()); - - WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + totalItems * 8 * 4); + + WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + totalItems * 8 * 4); data << uint64(creature->GetGUID().GetRawValue()); - + uint8 count = 0; size_t count_pos = data.wpos(); data << uint8(count); - + for (uint32 i = 0; i < spoofCount && count < MAX_VENDOR_ITEMS; ++i) { EncodeItemToPacket ( - data, spoofedItems[i], count, + data, spoofedItems[i], count, GetSpoofedItemPrice(spoofedItems[i]->ItemId, targetTemplate) ); } @@ -966,7 +980,7 @@ class npc_transmogrifier : public CreatureScript ItemTemplate const* _proto = itemList[i]->GetTemplate(); if (_proto) EncodeItemToPacket(data, _proto, count, price); } - + data.put(count_pos, count); player->GetSession()->SendPacket(&data); } @@ -1154,13 +1168,13 @@ class PS_Transmogrification : public PlayerScript sT->dataMap.erase(it->first); sT->entryMap.erase(pGUID); sT->selectionCache.erase(pGUID); - + #ifdef PRESETS if (sT->GetEnableSets()) sT->UnloadPlayerSets(pGUID); #endif } - + void OnBeforeBuyItemFromVendor(Player* player, ObjectGuid vendorguid, uint32 /*vendorslot*/, uint32& itemEntry, uint8 /*count*/, uint8 /*bag*/, uint8 /*slot*/) override { Creature* vendor = player->GetMap()->GetCreature(vendorguid);