aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2015-04-14 01:12:20 +0200
committerShauren <shauren.trinity@gmail.com>2015-04-14 01:12:20 +0200
commitd9e941dde3cc6105d5cd68ae3da55e4a7efcb244 (patch)
tree0143efd544e61725a7f37acb13a5b4db29c75d81
parente5675412735a33f05f9c3215fb0cc7327a800c6c (diff)
Core/Quests: Added research results about last field in QuestPackageItem.db2
-rw-r--r--sql/updates/hotfixes/2015_04_14_00_hotfixes.sql1
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp21
-rw-r--r--src/server/game/DataStores/DB2Stores.h4
-rw-r--r--src/server/game/DataStores/DB2Structure.h6
-rw-r--r--src/server/game/DataStores/DBCEnums.h8
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.cpp8
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.h3
-rw-r--r--src/server/game/Entities/Player/Player.cpp32
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp23
-rw-r--r--src/server/shared/Database/Implementation/HotfixDatabase.cpp2
10 files changed, 72 insertions, 36 deletions
diff --git a/sql/updates/hotfixes/2015_04_14_00_hotfixes.sql b/sql/updates/hotfixes/2015_04_14_00_hotfixes.sql
new file mode 100644
index 00000000000..642ee3aaf20
--- /dev/null
+++ b/sql/updates/hotfixes/2015_04_14_00_hotfixes.sql
@@ -0,0 +1 @@
+ALTER TABLE `quest_package_item` CHANGE `Unk` `FilterType` int(10) unsigned NOT NULL DEFAULT '0';
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index 71090011c64..bed2cc793f4 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -66,7 +66,6 @@ TaxiMask sAllianceTaxiNodesMask;
TaxiMask sDeathKnightTaxiNodesMask;
TaxiPathSetBySource sTaxiPathSetBySource;
TaxiPathNodesByPath sTaxiPathNodesByPath;
-QuestPackageItemMap sQuestPackageItemStoreMap;
typedef std::list<std::string> DB2StoreProblemList;
@@ -202,6 +201,9 @@ void DB2Manager::LoadStores(std::string const& dataPath)
if (PhaseEntry const* phase = sPhaseStore.LookupEntry(group->PhaseID))
_phasesByGroup[group->PhaseGroupID].insert(phase->ID);
+ for (QuestPackageItemEntry const* questPackageItem : sQuestPackageItemStore)
+ _questPackages[questPackageItem->QuestPackageID].push_back(questPackageItem);
+
for (SpellPowerEntry const* power : sSpellPowerStore)
{
if (SpellPowerDifficultyEntry const* powerDifficulty = sSpellPowerDifficultyStore.LookupEntry(power->ID))
@@ -305,14 +307,6 @@ void DB2Manager::LoadStores(std::string const& dataPath)
}
}
- for (uint32 i = 0; i < sQuestPackageItemStore.GetNumRows(); ++i)
- {
- if (QuestPackageItemEntry const* pack = sQuestPackageItemStore.LookupEntry(i))
- {
- sQuestPackageItemStoreMap[pack->QuestPackageID].push_back(pack);
- }
- }
-
// error checks
if (bad_db2_files.size() >= DB2FilesCount)
{
@@ -499,6 +493,15 @@ MountEntry const* DB2Manager::GetMount(uint32 spellId) const
return nullptr;
}
+std::vector<QuestPackageItemEntry const*> const* DB2Manager::GetQuestPackageItems(uint32 questPackageID) const
+{
+ auto itr = _questPackages.find(questPackageID);
+ if (itr != _questPackages.end())
+ return &itr->second;
+
+ return nullptr;
+}
+
std::set<uint32> DB2Manager::GetPhasesForGroup(uint32 group) const
{
auto itr = _phasesByGroup.find(group);
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 29dc68a451c..ece71c7413e 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -51,7 +51,6 @@ extern TaxiMask sAllianceTaxiNodesMask;
extern TaxiMask sDeathKnightTaxiNodesMask;
extern TaxiPathSetBySource sTaxiPathSetBySource;
extern TaxiPathNodesByPath sTaxiPathNodesByPath;
-extern QuestPackageItemMap sQuestPackageItemStoreMap;
struct HotfixNotify
{
@@ -75,6 +74,7 @@ public:
typedef std::unordered_map<uint32, std::set<ItemBonusTreeNodeEntry const*>> ItemBonusTreeContainer;
typedef std::unordered_map<uint32, MountEntry const*> MountContainer;
typedef std::unordered_map<uint32, std::set<uint32>> PhaseGroupContainer;
+ typedef std::unordered_map<uint32, std::vector<QuestPackageItemEntry const*>> QuestPackageItemContainer;
typedef std::unordered_map<uint32, std::vector<SpellPowerEntry const*>> SpellPowerContainer;
typedef std::unordered_map<uint32, std::unordered_map<uint32, std::vector<SpellPowerEntry const*>>> SpellPowerDifficultyContainer;
@@ -98,6 +98,7 @@ public:
std::set<uint32> GetItemBonusTree(uint32 itemId, uint32 itemBonusTreeMod) const;
uint32 GetItemDisplayId(uint32 itemId, uint32 appearanceModId) const;
MountEntry const* GetMount(uint32 spellId) const;
+ std::vector<QuestPackageItemEntry const*> const* GetQuestPackageItems(uint32 questPackageID) const;
std::set<uint32> GetPhasesForGroup(uint32 group) const;
std::vector<SpellPowerEntry const*> GetSpellPowers(uint32 spellId, Difficulty difficulty = DIFFICULTY_NONE, bool* hasDifficultyPowers = nullptr) const;
@@ -113,6 +114,7 @@ private:
ItemToBonusTreeContainer _itemToBonusTree;
MountContainer _mountsBySpellId;
PhaseGroupContainer _phasesByGroup;
+ QuestPackageItemContainer _questPackages;
SpellPowerContainer _spellPowers;
SpellPowerDifficultyContainer _spellPowerDifficulties;
};
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index ee6f4fdcc85..912ae5d60d5 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -296,19 +296,15 @@ struct PhaseXPhaseGroupEntry
uint32 PhaseGroupID;
};
-// QuestPackageItem.db2
struct QuestPackageItemEntry
{
uint32 ID; // 0
uint32 QuestPackageID; // 1
uint32 ItemID; // 2
uint32 ItemCount; // 3
- uint32 Unk; // 4
+ uint32 FilterType; // 4
};
-typedef std::vector<QuestPackageItemEntry const*> QuestPackageItemList;
-typedef std::unordered_map<uint32, QuestPackageItemList> QuestPackageItemMap;
-
struct SoundEntriesEntry
{
uint32 ID; // 0
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 30bd11af8c5..aca745c52a3 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -491,6 +491,14 @@ enum MountFlags
MOUNT_FLAG_HIDE_IF_UNKNOWN = 0x40
};
+enum QuestPackageFilter
+{
+ QUEST_PACKAGE_FILTER_LOOT_SPECIALIZATION = 0, // Players can select this quest reward if it matches their selected loot specialization
+ QUEST_PACKAGE_FILTER_CLASS = 1, // Players can select this quest reward if it matches their class
+ QUEST_PACKAGE_FILTER_UNMATCHED = 2, // Players can select this quest reward if no class/loot_spec rewards are available
+ QUEST_PACKAGE_FILTER_EVERYONE = 3 // Players can always select this quest reward
+};
+
enum SkillRaceClassInfoFlags
{
SKILL_FLAG_NO_SKILLUP_MESSAGE = 0x2,
diff --git a/src/server/game/Entities/Item/ItemTemplate.cpp b/src/server/game/Entities/Item/ItemTemplate.cpp
index e0e577f1d38..10d8272fca8 100644
--- a/src/server/game/Entities/Item/ItemTemplate.cpp
+++ b/src/server/game/Entities/Item/ItemTemplate.cpp
@@ -138,18 +138,18 @@ void ItemTemplate::GetDamage(uint32 itemLevel, float& minDamage, float& maxDamag
maxDamage = floor(float(avgDamage * (GetStatScalingFactor() * 0.5f + 1.0f) + 0.5f));
}
-bool ItemTemplate::CanWinForPlayer(Player* plr) const
+bool ItemTemplate::CanWinForPlayer(Player const* player) const
{
if (!Specializations.size())
return true;
- uint32 spec = plr->GetSpecId(plr->GetActiveTalentGroup());
+ uint32 spec = player->GetSpecId(player->GetActiveTalentGroup());
if (!spec)
- spec = plr->GetDefaultSpecId();
+ spec = player->GetDefaultSpecId();
if (!spec)
return false;
-
+
UsableTalentSpecs::const_iterator itr = Specializations.find(spec);
return itr != Specializations.end();
}
diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h
index 3272de6ac5a..9ab04727ced 100644
--- a/src/server/game/Entities/Item/ItemTemplate.h
+++ b/src/server/game/Entities/Item/ItemTemplate.h
@@ -584,6 +584,7 @@ const uint32 MaxItemSubclassValues[MAX_ITEM_CLASS] =
#define MIN_ITEM_LEVEL 1
#define MAX_ITEM_LEVEL 1000
+class Player;
typedef std::set<uint32> UsableTalentSpecs;
struct ItemTemplate
@@ -704,7 +705,7 @@ struct ItemTemplate
char const* GetDefaultLocaleName() const;
uint32 GetArmor(uint32 itemLevel) const;
void GetDamage(uint32 itemLevel, float& minDamage, float& maxDamage) const;
- bool CanWinForPlayer(Player* plr) const;
+ bool CanWinForPlayer(Player const* player) const;
};
// Benchmarked: Faster than std::map (insert/find)
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 8305949b352..a720f7ed529 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -14442,23 +14442,25 @@ bool Player::CanRewardQuest(Quest const* quest, uint32 reward, bool msg)
}
}
}
-
+
// QuestPackageItem.db2
if (quest->GetQuestPackageID())
{
- if (sQuestPackageItemStoreMap.find(quest->GetQuestPackageID()) != sQuestPackageItemStoreMap.end())
+ if (std::vector<QuestPackageItemEntry const*> const* questPackageItems = sDB2Manager.GetQuestPackageItems(quest->GetQuestPackageID()))
{
- QuestPackageItemList itemList = sQuestPackageItemStoreMap[quest->GetQuestPackageID()];
- for (QuestPackageItemList::const_iterator itr = itemList.begin(); itr != itemList.end(); ++itr)
+ for (QuestPackageItemEntry const* questPackageItem : *questPackageItems)
{
- if (ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate((*itr)->ItemID))
+ if (questPackageItem->ItemID != reward)
+ continue;
+
+ if (ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate(questPackageItem->ItemID))
{
if (rewardProto->CanWinForPlayer(this))
{
- InventoryResult res = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, (*itr)->ItemID, (*itr)->ItemCount);
+ InventoryResult res = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, questPackageItem->ItemID, questPackageItem->ItemCount);
if (res != EQUIP_ERR_OK)
{
- SendEquipError(res, NULL, NULL, (*itr)->ItemID);
+ SendEquipError(res, NULL, NULL, questPackageItem->ItemID);
return false;
}
}
@@ -14660,20 +14662,22 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
// QuestPackageItem.db2
if (quest->GetQuestPackageID())
{
- if (sQuestPackageItemStoreMap.find(quest->GetQuestPackageID()) != sQuestPackageItemStoreMap.end())
+ if (std::vector<QuestPackageItemEntry const*> const* questPackageItems = sDB2Manager.GetQuestPackageItems(quest->GetQuestPackageID()))
{
- QuestPackageItemList itemList = sQuestPackageItemStoreMap[quest->GetQuestPackageID()];
- for (QuestPackageItemList::const_iterator itr = itemList.begin(); itr != itemList.end(); ++itr)
+ for (QuestPackageItemEntry const* questPackageItem : *questPackageItems)
{
- if (ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate((*itr)->ItemID))
+ if (questPackageItem->ItemID != reward)
+ continue;
+
+ if (ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate(questPackageItem->ItemID))
{
if (rewardProto->CanWinForPlayer(this))
{
ItemPosCountVec dest;
- if (CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, (*itr)->ItemID, (*itr)->ItemCount) == EQUIP_ERR_OK)
+ if (CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, questPackageItem->ItemID, questPackageItem->ItemCount) == EQUIP_ERR_OK)
{
- Item* item = StoreNewItem(dest, (*itr)->ItemID, true, Item::GenerateItemRandomPropertyId((*itr)->ItemID));
- SendNewItem(item, (*itr)->ItemCount, true, false);
+ Item* item = StoreNewItem(dest, questPackageItem->ItemID, true, Item::GenerateItemRandomPropertyId(questPackageItem->ItemID));
+ SendNewItem(item, questPackageItem->ItemCount, true, false);
}
}
}
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 5e73fb71ae8..d7ad9c71956 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -242,7 +242,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest
Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID);
if (!quest)
return;
-
+
// This is Real Item Entry, not slot id as pre 5.x
if (packet.ItemChoiceID)
{
@@ -263,6 +263,27 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest
}
}
+ if (quest->GetQuestPackageID())
+ {
+ if (std::vector<QuestPackageItemEntry const*> const* questPackageItems = sDB2Manager.GetQuestPackageItems(quest->GetQuestPackageID()))
+ {
+ for (QuestPackageItemEntry const* questPackageItem : *questPackageItems)
+ {
+ if (questPackageItem->ItemID != packet.ItemChoiceID)
+ continue;
+
+ if (ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate(questPackageItem->ItemID))
+ {
+ if (rewardProto->CanWinForPlayer(_player))
+ {
+ itemValid = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
if (!itemValid)
{
TC_LOG_ERROR("network", "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player %s (%s) tried to get reward item (Item Entry: %u) wich is not a reward for quest %u (possible packet-hacking detected)", _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), packet.ItemChoiceID, packet.QuestID);
diff --git a/src/server/shared/Database/Implementation/HotfixDatabase.cpp b/src/server/shared/Database/Implementation/HotfixDatabase.cpp
index 73441855483..e13863d9326 100644
--- a/src/server/shared/Database/Implementation/HotfixDatabase.cpp
+++ b/src/server/shared/Database/Implementation/HotfixDatabase.cpp
@@ -119,7 +119,7 @@ void HotfixDatabaseConnection::DoPrepareStatements()
PrepareStatement(HOTFIX_SEL_PHASE_GROUP, "SELECT ID, PhaseID, PhaseGroupID FROM phase_group ORDER BY ID DESC", CONNECTION_SYNCH);
// QuestPackageItem.db2
- PrepareStatement(HOTFIX_SEL_QUEST_PACKAGE_ITEM, "SELECT ID, QuestPackageID, ItemID, ItemCount, Unk FROM quest_package_item ORDER BY ID DESC", CONNECTION_SYNCH);
+ PrepareStatement(HOTFIX_SEL_QUEST_PACKAGE_ITEM, "SELECT ID, QuestPackageID, ItemID, ItemCount, FilterType FROM quest_package_item ORDER BY ID DESC", CONNECTION_SYNCH);
// SoundEntries.db2
PrepareStatement(HOTFIX_SEL_SOUND_ENTRIES, "SELECT ID, SoundType, Name, FileDataID1, FileDataID2, FileDataID3, FileDataID4, FileDataID5, "