diff options
author | Shauren <shauren.trinity@gmail.com> | 2016-11-08 00:04:19 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-11-08 00:04:19 +0100 |
commit | fcbb4397ea5c803b5b46bda770606ae7a79e565f (patch) | |
tree | 07bbcd1f1f45c27503617301e7bc36c68b185f43 /src | |
parent | 0abb9873ec3798b6476400c8d283a6410d9418fe (diff) |
Core/Quests: Implemented handling all QuestPackageItem types
Closes #18209
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/DataStores/DB2Stores.cpp | 18 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Stores.h | 3 | ||||
-rw-r--r-- | src/server/game/Entities/Item/ItemTemplate.cpp | 14 | ||||
-rw-r--r-- | src/server/game/Entities/Item/ItemTemplate.h | 4 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 98 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 1 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Handlers/QuestHandler.cpp | 25 |
8 files changed, 136 insertions, 34 deletions
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index e6b5290b752..d249097273f 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -794,7 +794,12 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale) } for (QuestPackageItemEntry const* questPackageItem : sQuestPackageItemStore) - _questPackages[questPackageItem->QuestPackageID].push_back(questPackageItem); + { + if (questPackageItem->FilterType != QUEST_PACKAGE_FILTER_UNMATCHED) + _questPackages[questPackageItem->QuestPackageID].first.push_back(questPackageItem); + else + _questPackages[questPackageItem->QuestPackageID].second.push_back(questPackageItem); + } for (RulesetItemUpgradeEntry const* rulesetItemUpgrade : sRulesetItemUpgradeStore) _rulesetItemUpgrade[rulesetItemUpgrade->ItemID] = rulesetItemUpgrade->ItemUpgradeID; @@ -1625,7 +1630,16 @@ std::vector<QuestPackageItemEntry const*> const* DB2Manager::GetQuestPackageItem { auto itr = _questPackages.find(questPackageID); if (itr != _questPackages.end()) - return &itr->second; + return &itr->second.first; + + return nullptr; +} + +std::vector<QuestPackageItemEntry const*> const* DB2Manager::GetQuestPackageItemsFallback(uint32 questPackageID) const +{ + auto itr = _questPackages.find(questPackageID); + if (itr != _questPackages.end()) + return &itr->second.second; return nullptr; } diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 2a4e42b27ed..334081bab27 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -261,7 +261,7 @@ public: typedef std::array<std::vector<std::wregex>, TOTAL_LOCALES + 1> NameValidationRegexContainer; typedef std::unordered_map<uint32, std::set<uint32>> PhaseGroupContainer; typedef std::array<PowerTypeEntry const*, MAX_POWERS> PowerTypesContainer; - typedef std::unordered_map<uint32, std::vector<QuestPackageItemEntry const*>> QuestPackageItemContainer; + typedef std::unordered_map<uint32, std::pair<std::vector<QuestPackageItemEntry const*>, std::vector<QuestPackageItemEntry const*>>> QuestPackageItemContainer; typedef std::unordered_map<uint32, uint32> RulesetItemUpgradeContainer; typedef std::unordered_multimap<uint32, SkillRaceClassInfoEntry const*> SkillRaceClassInfoContainer; typedef std::unordered_map<uint32, std::vector<SpecializationSpellsEntry const*>> SpecializationSpellsContainer; @@ -330,6 +330,7 @@ public: static PvpDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 level); static PvpDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundBracketId id); std::vector<QuestPackageItemEntry const*> const* GetQuestPackageItems(uint32 questPackageID) const; + std::vector<QuestPackageItemEntry const*> const* GetQuestPackageItemsFallback(uint32 questPackageID) const; uint32 GetQuestUniqueBitFlag(uint32 questId); uint32 GetRulesetItemUpgrade(uint32 itemId) const; SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_); diff --git a/src/server/game/Entities/Item/ItemTemplate.cpp b/src/server/game/Entities/Item/ItemTemplate.cpp index 77848112014..d76985b269d 100644 --- a/src/server/game/Entities/Item/ItemTemplate.cpp +++ b/src/server/game/Entities/Item/ItemTemplate.cpp @@ -212,9 +212,11 @@ void ItemTemplate::GetDamage(uint32 itemLevel, float& minDamage, float& maxDamag maxDamage = floor(float(avgDamage * (GetStatScalingFactor() * 0.5f + 1.0f) + 0.5f)); } -bool ItemTemplate::IsUsableBySpecialization(Player const* player) const +bool ItemTemplate::IsUsableByLootSpecialization(Player const* player) const { - uint32 spec = player->GetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID); + uint32 spec = player->GetUInt32Value(PLAYER_FIELD_LOOT_SPEC_ID); + if (!spec) + spec = player->GetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID); if (!spec) spec = player->GetDefaultSpecId(); @@ -222,7 +224,13 @@ bool ItemTemplate::IsUsableBySpecialization(Player const* player) const if (!chrSpecialization) return false; - return Specializations[player->getLevel() > 40].test(CalculateItemSpecBit(chrSpecialization)); + std::size_t levelIndex = 0; + if (player->getLevel() >= 110) + levelIndex = 2; + else if (player->getLevel() > 40) + levelIndex = 1; + + return Specializations[levelIndex].test(CalculateItemSpecBit(chrSpecialization)); } std::size_t ItemTemplate::CalculateItemSpecBit(ChrSpecializationEntry const* spec) diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h index fb08248e4d3..5b997200758 100644 --- a/src/server/game/Entities/Item/ItemTemplate.h +++ b/src/server/game/Entities/Item/ItemTemplate.h @@ -776,7 +776,7 @@ struct TC_GAME_API ItemTemplate uint32 MaxMoneyLoot; uint32 FlagsCu; float SpellPPMRate; - std::bitset<MAX_CLASSES * MAX_SPECIALIZATIONS> Specializations[2]; // one set for 1-40 level range and another for 41-100 + std::bitset<MAX_CLASSES * MAX_SPECIALIZATIONS> Specializations[3]; // one set for 1-40 level range and another for 41-109 and one for 110 uint32 ItemSpecClassMask; // helpers @@ -807,7 +807,7 @@ struct TC_GAME_API ItemTemplate char const* GetDefaultLocaleName() const; uint32 GetArmor(uint32 itemLevel) const; void GetDamage(uint32 itemLevel, float& minDamage, float& maxDamage) const; - bool IsUsableBySpecialization(Player const* player) const; + bool IsUsableByLootSpecialization(Player const* player) const; static std::size_t CalculateItemSpecBit(ChrSpecializationEntry const* spec); }; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index aacc602d3d6..a8d57558db5 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -14699,6 +14699,7 @@ bool Player::CanRewardQuest(Quest const* quest, uint32 reward, bool msg) // QuestPackageItem.db2 if (quest->GetQuestPackageID()) { + bool hasFilteredQuestPackageReward = false; if (std::vector<QuestPackageItemEntry const*> const* questPackageItems = sDB2Manager.GetQuestPackageItems(quest->GetQuestPackageID())) { for (QuestPackageItemEntry const* questPackageItem : *questPackageItems) @@ -14706,16 +14707,33 @@ bool Player::CanRewardQuest(Quest const* quest, uint32 reward, bool msg) if (questPackageItem->ItemID != reward) continue; - if (ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate(questPackageItem->ItemID)) + if (CanSelectQuestPackageItem(questPackageItem)) { - if (rewardProto->IsUsableBySpecialization(this)) + hasFilteredQuestPackageReward = true; + InventoryResult res = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, questPackageItem->ItemID, questPackageItem->ItemCount); + if (res != EQUIP_ERR_OK) { - InventoryResult res = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, questPackageItem->ItemID, questPackageItem->ItemCount); - if (res != EQUIP_ERR_OK) - { - SendEquipError(res, nullptr, nullptr, questPackageItem->ItemID); - return false; - } + SendEquipError(res, nullptr, nullptr, questPackageItem->ItemID); + return false; + } + } + } + } + + if (!hasFilteredQuestPackageReward) + { + if (std::vector<QuestPackageItemEntry const*> const* questPackageItems = sDB2Manager.GetQuestPackageItemsFallback(quest->GetQuestPackageID())) + { + for (QuestPackageItemEntry const* questPackageItem : *questPackageItems) + { + if (questPackageItem->ItemID != reward) + continue; + + InventoryResult res = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, questPackageItem->ItemID, questPackageItem->ItemCount); + if (res != EQUIP_ERR_OK) + { + SendEquipError(res, nullptr, nullptr, questPackageItem->ItemID); + return false; } } } @@ -14865,6 +14883,31 @@ uint32 Player::GetQuestXPReward(Quest const* quest) return XP; } +bool Player::CanSelectQuestPackageItem(QuestPackageItemEntry const* questPackageItem) const +{ + ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate(questPackageItem->ItemID); + if (!rewardProto) + return false; + + if ((rewardProto->GetFlags2() & ITEM_FLAG2_FACTION_ALLIANCE && GetTeam() != ALLIANCE) || + (rewardProto->GetFlags2() & ITEM_FLAG2_FACTION_HORDE && GetTeam() != HORDE)) + return false; + + switch (questPackageItem->FilterType) + { + case QUEST_PACKAGE_FILTER_LOOT_SPECIALIZATION: + return rewardProto->IsUsableByLootSpecialization(this); + case QUEST_PACKAGE_FILTER_CLASS: + return (rewardProto->ItemSpecClassMask & getClassMask()) != 0; + case QUEST_PACKAGE_FILTER_EVERYONE: + return true; + default: + break; + } + + return false; +} + void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, bool announce) { //this THING should be here to protect code from quest, which cast on player far teleport as a reward @@ -14901,7 +14944,8 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, RemoveTimedQuest(quest_id); - if (quest->GetRewChoiceItemsCount() > 0) + ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate(reward); + if (rewardProto && quest->GetRewChoiceItemsCount()) { for (uint32 i = 0; i < quest->GetRewChoiceItemsCount(); ++i) { @@ -14918,8 +14962,9 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, } // QuestPackageItem.db2 - if (quest->GetQuestPackageID()) + if (rewardProto && quest->GetQuestPackageID()) { + bool hasFilteredQuestPackageReward = false; if (std::vector<QuestPackageItemEntry const*> const* questPackageItems = sDB2Manager.GetQuestPackageItems(quest->GetQuestPackageID())) { for (QuestPackageItemEntry const* questPackageItem : *questPackageItems) @@ -14927,16 +14972,33 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, if (questPackageItem->ItemID != reward) continue; - if (ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate(questPackageItem->ItemID)) + if (CanSelectQuestPackageItem(questPackageItem)) { - if (rewardProto->IsUsableBySpecialization(this)) + hasFilteredQuestPackageReward = true; + ItemPosCountVec dest; + if (CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, questPackageItem->ItemID, questPackageItem->ItemCount) == EQUIP_ERR_OK) { - ItemPosCountVec dest; - if (CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, questPackageItem->ItemID, questPackageItem->ItemCount) == EQUIP_ERR_OK) - { - Item* item = StoreNewItem(dest, questPackageItem->ItemID, true, Item::GenerateItemRandomPropertyId(questPackageItem->ItemID)); - SendNewItem(item, questPackageItem->ItemCount, true, false); - } + Item* item = StoreNewItem(dest, questPackageItem->ItemID, true, Item::GenerateItemRandomPropertyId(questPackageItem->ItemID)); + SendNewItem(item, questPackageItem->ItemCount, true, false); + } + } + } + } + + if (!hasFilteredQuestPackageReward) + { + if (std::vector<QuestPackageItemEntry const*> const* questPackageItems = sDB2Manager.GetQuestPackageItemsFallback(quest->GetQuestPackageID())) + { + for (QuestPackageItemEntry const* questPackageItem : *questPackageItems) + { + if (questPackageItem->ItemID != reward) + continue; + + ItemPosCountVec dest; + if (CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, questPackageItem->ItemID, questPackageItem->ItemCount) == EQUIP_ERR_OK) + { + Item* item = StoreNewItem(dest, questPackageItem->ItemID, true, Item::GenerateItemRandomPropertyId(questPackageItem->ItemID)); + SendNewItem(item, questPackageItem->ItemCount, true, false); } } } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 97fe7df32c1..d39c9d3e314 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1529,6 +1529,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void IncompleteQuest(uint32 quest_id); uint32 GetQuestMoneyReward(Quest const* quest) const; uint32 GetQuestXPReward(Quest const* quest); + bool CanSelectQuestPackageItem(QuestPackageItemEntry const* questPackageItem) const; void RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, bool announce = true); void FailQuest(uint32 quest_id); bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 005985b4d1d..9d026296724 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2781,7 +2781,12 @@ void ObjectMgr::LoadItemTemplates() if ((1 << (specialization->ClassID - 1)) & sparse->AllowableClass) { itemTemplate.ItemSpecClassMask |= 1 << (specialization->ClassID - 1); - itemTemplate.Specializations[itemSpec->MaxLevel > 40].set(ItemTemplate::CalculateItemSpecBit(specialization)); + std::size_t specBit = ItemTemplate::CalculateItemSpecBit(specialization); + itemTemplate.Specializations[0].set(specBit); + if (itemSpec->MaxLevel > 40) + itemTemplate.Specializations[1].set(specBit); + if (itemSpec->MaxLevel >= 110) + itemTemplate.Specializations[2].set(specBit); } } } diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index 89ebbaffbc0..2d293e84284 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -282,14 +282,25 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest if (questPackageItem->ItemID != uint32(packet.ItemChoiceID)) continue; - rewardProto = sObjectMgr->GetItemTemplate(questPackageItem->ItemID); - if (rewardProto) + if (_player->CanSelectQuestPackageItem(questPackageItem)) { - if (rewardProto->IsUsableBySpecialization(_player)) - { - itemValid = true; - break; - } + itemValid = true; + break; + } + } + } + + if (!itemValid) + { + if (std::vector<QuestPackageItemEntry const*> const* questPackageItems = sDB2Manager.GetQuestPackageItemsFallback(quest->GetQuestPackageID())) + { + for (QuestPackageItemEntry const* questPackageItem : *questPackageItems) + { + if (questPackageItem->ItemID != uint32(packet.ItemChoiceID)) + continue; + + itemValid = true; + break; } } } |