diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/game/DataStores/DB2Stores.cpp | 11 | ||||
| -rw-r--r-- | src/server/game/DataStores/DB2Stores.h | 1 | ||||
| -rw-r--r-- | src/server/game/DataStores/DB2Structure.h | 13 | ||||
| -rw-r--r-- | src/server/game/DataStores/DB2fmt.h | 1 | ||||
| -rw-r--r-- | src/server/game/DataStores/DBCStores.cpp | 9 | ||||
| -rw-r--r-- | src/server/game/DataStores/DBCStores.h | 3 | ||||
| -rw-r--r-- | src/server/game/DataStores/DBCStructure.h | 23 | ||||
| -rw-r--r-- | src/server/game/DataStores/DBCfmt.h | 4 | ||||
| -rw-r--r-- | src/server/game/Entities/Item/ItemTemplate.cpp | 17 | ||||
| -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 | 26 | ||||
| -rw-r--r-- | src/server/game/Handlers/QuestHandler.cpp | 35 | ||||
| -rw-r--r-- | src/server/game/Quests/QuestDef.h | 27 | ||||
| -rw-r--r-- | src/server/shared/Database/Implementation/HotfixDatabase.cpp | 3 | ||||
| -rw-r--r-- | src/server/shared/Database/Implementation/HotfixDatabase.h | 2 |
17 files changed, 253 insertions, 25 deletions
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 26f2d8b36c9..71090011c64 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -43,6 +43,7 @@ DB2Storage<KeyChainEntry> sKeyChainStore("KeyChain.db2", KeyCh DB2Storage<MountEntry> sMountStore("Mount.db2", MountFormat, HOTFIX_SEL_MOUNT); DB2Storage<OverrideSpellDataEntry> sOverrideSpellDataStore("OverrideSpellData.db2", OverrideSpellDataFormat, HOTFIX_SEL_OVERRIDE_SPELL_DATA); DB2Storage<PhaseXPhaseGroupEntry> sPhaseXPhaseGroupStore("PhaseXPhaseGroup.db2", PhaseXPhaseGroupFormat, HOTFIX_SEL_PHASE_GROUP); +DB2Storage<QuestPackageItemEntry> sQuestPackageItemStore("QuestPackageItem.db2", QuestPackageItemfmt, HOTFIX_SEL_QUEST_PACKAGE_ITEM); DB2Storage<SoundEntriesEntry> sSoundEntriesStore("SoundEntries.db2", SoundEntriesFormat, HOTFIX_SEL_SOUND_ENTRIES); DB2Storage<SpellAuraRestrictionsEntry> sSpellAuraRestrictionsStore("SpellAuraRestrictions.db2", SpellAuraRestrictionsFormat, HOTFIX_SEL_SPELL_AURA_RESTRICTIONS); DB2Storage<SpellCastingRequirementsEntry> sSpellCastingRequirementsStore("SpellCastingRequirements.db2", SpellCastingRequirementsFormat, HOTFIX_SEL_SPELL_CASTING_REQUIREMENTS); @@ -65,6 +66,7 @@ TaxiMask sAllianceTaxiNodesMask; TaxiMask sDeathKnightTaxiNodesMask; TaxiPathSetBySource sTaxiPathSetBySource; TaxiPathNodesByPath sTaxiPathNodesByPath; +QuestPackageItemMap sQuestPackageItemStoreMap; typedef std::list<std::string> DB2StoreProblemList; @@ -144,6 +146,7 @@ void DB2Manager::LoadStores(std::string const& dataPath) LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sMountStore, db2Path); LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sOverrideSpellDataStore, db2Path); LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sPhaseXPhaseGroupStore, db2Path); + LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sQuestPackageItemStore, db2Path); LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSoundEntriesStore, db2Path); LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellAuraRestrictionsStore, db2Path); LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellCastingRequirementsStore, db2Path); @@ -302,6 +305,14 @@ 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) { diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 8fdf23ec58c..29dc68a451c 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -51,6 +51,7 @@ extern TaxiMask sAllianceTaxiNodesMask; extern TaxiMask sDeathKnightTaxiNodesMask; extern TaxiPathSetBySource sTaxiPathSetBySource; extern TaxiPathNodesByPath sTaxiPathNodesByPath; +extern QuestPackageItemMap sQuestPackageItemStoreMap; struct HotfixNotify { diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index 9aab120cc63..ee6f4fdcc85 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -296,6 +296,19 @@ struct PhaseXPhaseGroupEntry uint32 PhaseGroupID; }; +// QuestPackageItem.db2 +struct QuestPackageItemEntry +{ + uint32 ID; // 0 + uint32 QuestPackageID; // 1 + uint32 ItemID; // 2 + uint32 ItemCount; // 3 + uint32 Unk; // 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/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h index baab3cf9302..f59c7b56f56 100644 --- a/src/server/game/DataStores/DB2fmt.h +++ b/src/server/game/DataStores/DB2fmt.h @@ -38,6 +38,7 @@ char const KeyChainFormat[] = "nbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; char const MountFormat[] = "niiisssiii"; char const OverrideSpellDataFormat[] = "niiiiiiiiiiii"; char const PhaseXPhaseGroupFormat[] = "nii"; +char const QuestPackageItemfmt[] = "niiii"; char const SoundEntriesFormat[] = "nisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiififfiifffffii"; char const SpellAuraRestrictionsFormat[] = "niiiiiiii"; char const SpellCastingRequirementsFormat[] = "niiiiii"; diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 919c952f136..805885df51c 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -158,6 +158,9 @@ DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffi DBCStorage <ItemSetEntry> sItemSetStore(ItemSetEntryfmt); DBCStorage <ItemSetSpellEntry> sItemSetSpellStore(ItemSetSpellEntryfmt); ItemSetSpellsStore sItemSetSpellsStore; +DBCStorage <ItemSpecOverrideEntry> sItemSpecOverrideStore(ItemSpecOverrideEntryfmt); +ItemSpecOverridesStore sItemSpecOverridesStore; +DBCStorage <ItemSpecEntry> sItemSpecStore(ItemSpecEntryfmt); DBCStorage <LFGDungeonEntry> sLFGDungeonStore(LFGDungeonEntryfmt); DBCStorage <LightEntry> sLightStore(LightEntryfmt); @@ -477,6 +480,12 @@ void LoadDBCStores(const std::string& dataPath) if (ItemSetSpellEntry const* entry = sItemSetSpellStore.LookupEntry(i)) sItemSetSpellsStore[entry->ItemSetID].push_back(entry); + LoadDBC(availableDbcLocales, bad_dbc_files, sItemSpecStore, dbcPath, "ItemSpec.dbc");//19116 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemSpecOverrideStore, dbcPath, "ItemSpecOverride.dbc");//19116 + for (uint32 i = 0; i < sItemSpecOverrideStore.GetNumRows(); ++i) + if (ItemSpecOverrideEntry const* entry = sItemSpecOverrideStore.LookupEntry(i)) + sItemSpecOverridesStore[entry->ItemID].push_back(entry); + LoadDBC(availableDbcLocales, bad_dbc_files, sItemArmorQualityStore, dbcPath, "ItemArmorQuality.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sItemArmorShieldStore, dbcPath, "ItemArmorShield.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sItemArmorTotalStore, dbcPath, "ItemArmorTotal.dbc");//19116 diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index f16b56609dd..781b981c4c1 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -211,6 +211,9 @@ extern DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore; extern DBCStorage <ItemSetEntry> sItemSetStore; extern DBCStorage <ItemSetSpellEntry> sItemSetSpellStore; extern ItemSetSpellsStore sItemSetSpellsStore; +extern DBCStorage <ItemSpecOverrideEntry> sItemSpecOverrideStore; +extern ItemSpecOverridesStore sItemSpecOverridesStore; +extern DBCStorage <ItemSpecEntry> sItemSpecStore; extern DBCStorage <LFGDungeonEntry> sLFGDungeonStore; extern DBCStorage <LiquidTypeEntry> sLiquidTypeStore; extern DBCStorage <LockEntry> sLockStore; diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index 0d4ada1ab39..ae6722b7932 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -261,7 +261,7 @@ struct ChrClassesEntry uint32 AttackPowerPerStrength; // 10 Attack Power bonus per point of strength uint32 AttackPowerPerAgility; // 11 Attack Power bonus per point of agility uint32 RangedAttackPowerPerAgility; // 12 Ranged Attack Power bonus per point of agility - //uint32 DefaultSpec; // 13 + uint32 DefaultSpec; // 13 //uint32 CreateScreenFileDataID; // 14 //uint32 SelectScreenFileDataID; // 15 //uint32 LowResScreenFileDataID; // 16 @@ -1108,6 +1108,27 @@ struct ItemSetSpellEntry typedef std::vector<ItemSetSpellEntry const*> ItemSetSpells; typedef std::unordered_map<uint32, ItemSetSpells> ItemSetSpellsStore; +struct ItemSpecEntry +{ + uint32 ID; // 0 + uint32 MinLevel; // 1 + uint32 MaxLevel; // 2 + uint32 ItemType; // 3 + uint32 PrimaryStat; // 4 + uint32 SecondaryStat; // 5 + uint32 SpecID; // 6 +}; + +struct ItemSpecOverrideEntry +{ + uint32 ID; // 0 + uint32 ItemID; // 1 + uint32 SpecID; // 2 +}; + +typedef std::vector<ItemSpecOverrideEntry const*> ItemSpecOverrides; +typedef std::unordered_map<uint32, ItemSpecOverrides> ItemSpecOverridesStore; + struct LFGDungeonEntry { uint32 ID; // 0 diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 98677746c3c..271aca1c43f 100644 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -37,7 +37,7 @@ char const CharStartOutfitEntryfmt[] = "dbbbXiiiiiiiiiiiiiiiiiiiiiiiiii"; char const CharSectionsEntryfmt[] = "diiixxxiii"; char const CharTitlesEntryfmt[] = "nxssix"; char const ChatChannelsEntryfmt[] = "nixsx"; -char const ChrClassesEntryfmt[] = "nixsxxxixiiiixxxxxx"; +char const ChrClassesEntryfmt[] = "nixsxxxixiiiiixxxxx"; char const ChrRacesEntryfmt[] = "niixiixxxxxxiisxxxxxxxxxxxxxxxxxxxxxxxxx"; char const ChrClassesXPowerTypesfmt[] = "nii"; char const ChrSpecializationEntryfmt[] = "nxiiiiiiiiixxxii"; @@ -105,6 +105,8 @@ char const ItemRandomPropertiesfmt[] = "nxiiiiis"; char const ItemRandomSuffixfmt[] = "nsxiiiiiiiiii"; char const ItemSetEntryfmt[] = "nsiiiiiiiiiiiiiiiiiii"; char const ItemSetSpellEntryfmt[] = "niiii"; +char const ItemSpecEntryfmt[] = "niiiiii"; +char const ItemSpecOverrideEntryfmt[] = "nii"; char const LFGDungeonEntryfmt[] = "nsiiixxiiiixxixixxxxxxxxxxxxx"; char const LightEntryfmt[] = "nifffxxxxxxxxxx"; char const LiquidTypefmt[] = "nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; diff --git a/src/server/game/Entities/Item/ItemTemplate.cpp b/src/server/game/Entities/Item/ItemTemplate.cpp index 983a263f725..e0e577f1d38 100644 --- a/src/server/game/Entities/Item/ItemTemplate.cpp +++ b/src/server/game/Entities/Item/ItemTemplate.cpp @@ -20,6 +20,7 @@ #include "DB2Stores.h" #include "World.h" #include "ItemTemplate.h" +#include "Player.h" char const* ItemTemplate::GetName(LocaleConstant locale) const { @@ -136,3 +137,19 @@ void ItemTemplate::GetDamage(uint32 itemLevel, float& minDamage, float& maxDamag minDamage = (GetStatScalingFactor() * -0.5f + 1.0f) * avgDamage; maxDamage = floor(float(avgDamage * (GetStatScalingFactor() * 0.5f + 1.0f) + 0.5f)); } + +bool ItemTemplate::CanWinForPlayer(Player* plr) const +{ + if (!Specializations.size()) + return true; + + uint32 spec = plr->GetSpecId(plr->GetActiveTalentGroup()); + if (!spec) + spec = plr->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 eb5fbc2e022..3272de6ac5a 100644 --- a/src/server/game/Entities/Item/ItemTemplate.h +++ b/src/server/game/Entities/Item/ItemTemplate.h @@ -584,6 +584,8 @@ const uint32 MaxItemSubclassValues[MAX_ITEM_CLASS] = #define MIN_ITEM_LEVEL 1 #define MAX_ITEM_LEVEL 1000 +typedef std::set<uint32> UsableTalentSpecs; + struct ItemTemplate { ItemEntry const* BasicData; @@ -655,6 +657,7 @@ struct ItemTemplate uint32 MaxMoneyLoot; uint32 FlagsCu; float SpellPPMRate; + UsableTalentSpecs Specializations; // helpers bool CanChangeEquipStateInCombat() const @@ -701,6 +704,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; }; // 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 2ef3380a5eb..8305949b352 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -14413,13 +14413,16 @@ bool Player::CanRewardQuest(Quest const* quest, uint32 reward, bool msg) ItemPosCountVec dest; if (quest->GetRewChoiceItemsCount() > 0) { - if (quest->RewardChoiceItemId[reward]) + for (uint32 i = 0; i < quest->GetRewChoiceItemsCount(); ++i) { - InventoryResult res = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, quest->RewardChoiceItemId[reward], quest->RewardChoiceItemCount[reward]); - if (res != EQUIP_ERR_OK) + if (quest->RewardChoiceItemId[i] && quest->RewardChoiceItemId[i] == reward) { - SendEquipError(res, NULL, NULL, quest->RewardChoiceItemId[reward]); - return false; + InventoryResult res = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, quest->RewardChoiceItemId[i], quest->RewardChoiceItemCount[i]); + if (res != EQUIP_ERR_OK) + { + SendEquipError(res, NULL, NULL, quest->RewardChoiceItemId[i]); + return false; + } } } } @@ -14439,6 +14442,30 @@ bool Player::CanRewardQuest(Quest const* quest, uint32 reward, bool msg) } } } + + // QuestPackageItem.db2 + if (quest->GetQuestPackageID()) + { + if (sQuestPackageItemStoreMap.find(quest->GetQuestPackageID()) != sQuestPackageItemStoreMap.end()) + { + QuestPackageItemList itemList = sQuestPackageItemStoreMap[quest->GetQuestPackageID()]; + for (QuestPackageItemList::const_iterator itr = itemList.begin(); itr != itemList.end(); ++itr) + { + if (ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate((*itr)->ItemID)) + { + if (rewardProto->CanWinForPlayer(this)) + { + InventoryResult res = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, (*itr)->ItemID, (*itr)->ItemCount); + if (res != EQUIP_ERR_OK) + { + SendEquipError(res, NULL, NULL, (*itr)->ItemID); + return false; + } + } + } + } + } + } return true; } @@ -14591,7 +14618,8 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, switch (obj.Type) { case QUEST_OBJECTIVE_ITEM: - DestroyItemCount(obj.ObjectID, obj.Amount, true); + if (!(quest->GetFlagsEx() & QUEST_FLAGS_EX_KEEP_ADDITIONAL_ITEMS)) + DestroyItemCount(obj.ObjectID, obj.Amount, true); break; case QUEST_OBJECTIVE_CURRENCY: ModifyCurrency(obj.ObjectID, -int32(obj.Amount)); @@ -14599,12 +14627,15 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, } } - for (uint8 i = 0; i < QUEST_ITEM_DROP_COUNT; ++i) + if (!(quest->GetFlagsEx() & QUEST_FLAGS_EX_KEEP_ADDITIONAL_ITEMS)) { - if (quest->ItemDrop[i]) + for (uint8 i = 0; i < QUEST_ITEM_DROP_COUNT; ++i) { - uint32 count = quest->ItemDropQuantity[i]; - DestroyItemCount(quest->ItemDrop[i], count ? count : 9999, true); + if (quest->ItemDrop[i]) + { + uint32 count = quest->ItemDropQuantity[i]; + DestroyItemCount(quest->ItemDrop[i], count ? count : 9999, true); + } } } @@ -14612,13 +14643,40 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, if (quest->GetRewChoiceItemsCount() > 0) { - if (uint32 itemId = quest->RewardChoiceItemId[reward]) + for (uint32 i = 0; i < quest->GetRewChoiceItemsCount(); ++i) { - ItemPosCountVec dest; - if (CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, quest->RewardChoiceItemCount[reward]) == EQUIP_ERR_OK) + if (quest->RewardChoiceItemId[i] && quest->RewardChoiceItemId[i] == reward) { - Item* item = StoreNewItem(dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId)); - SendNewItem(item, quest->RewardChoiceItemCount[reward], true, false); + ItemPosCountVec dest; + if (CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, reward, quest->RewardChoiceItemCount[i]) == EQUIP_ERR_OK) + { + Item* item = StoreNewItem(dest, reward, true, Item::GenerateItemRandomPropertyId(reward)); + SendNewItem(item, quest->RewardChoiceItemCount[i], true, false); + } + } + } + } + + // QuestPackageItem.db2 + if (quest->GetQuestPackageID()) + { + if (sQuestPackageItemStoreMap.find(quest->GetQuestPackageID()) != sQuestPackageItemStoreMap.end()) + { + QuestPackageItemList itemList = sQuestPackageItemStoreMap[quest->GetQuestPackageID()]; + for (QuestPackageItemList::const_iterator itr = itemList.begin(); itr != itemList.end(); ++itr) + { + if (ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate((*itr)->ItemID)) + { + if (rewardProto->CanWinForPlayer(this)) + { + ItemPosCountVec dest; + if (CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, (*itr)->ItemID, (*itr)->ItemCount) == EQUIP_ERR_OK) + { + Item* item = StoreNewItem(dest, (*itr)->ItemID, true, Item::GenerateItemRandomPropertyId((*itr)->ItemID)); + SendNewItem(item, (*itr)->ItemCount, true, false); + } + } + } } } } @@ -26563,4 +26621,12 @@ bool Player::ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 ha return false; return true; -}
\ No newline at end of file +} + +uint32 Player::GetDefaultSpecId() const +{ + ChrClassesEntry const* entry = sChrClassesStore.LookupEntry(getClass()); + if (entry) + return entry->DefaultSpec; + return 0; +} diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 7698cee5a70..9ddcf6ed92d 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1892,6 +1892,7 @@ class Player : public Unit, public GridObject<Player> void SetActiveTalentGroup(uint8 group){ _talentMgr->ActiveGroup = group; } uint8 GetTalentGroupsCount() const { return _talentMgr->GroupsCount; } void SetTalentGroupsCount(uint8 count) { _talentMgr->GroupsCount = count; } + uint32 GetDefaultSpecId() const; bool ResetTalents(bool noCost = false); uint32 GetNextResetTalentsCost() const; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index eec09b6f7d1..43371c5aff8 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2439,6 +2439,32 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.MaxMoneyLoot = 0; itemTemplate.FlagsCu = 0; itemTemplate.SpellPPMRate = 0.0f; + + /*for (uint32 i = 0; i < sItemSpecStore.GetNumRows(); ++i) + { + if (ItemSpecEntry const* spec = sItemSpecStore.LookupEntry(i)) + { + if (itemTemplate.GetBaseItemLevel() >= spec->MinLevel && itemTemplate.GetBaseItemLevel() <= spec->MaxLevel) + { + // have to research what are these! + if (spec->PrimaryStat && spec->SecondaryStat && spec->ItemType) + { + itemTemplate.Specializations.insert(spec->SpecID); + } + } + } + }*/ + + ItemSpecOverridesStore::const_iterator spec = sItemSpecOverridesStore.find(itemTemplate.GetId()); + if (spec != sItemSpecOverridesStore.end()) + { + itemTemplate.Specializations.clear(); + for (ItemSpecOverrideEntry const* over : (*spec).second) + { + itemTemplate.Specializations.insert(over->SpecID); + } + } + ++sparseCount; } diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index ee3ccea9460..5e73fb71ae8 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -237,17 +237,38 @@ void WorldSession::HandleQuestQueryOpcode(WorldPackets::Quest::QueryQuestInfo& p void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::QuestGiverChooseReward& packet) { - if (packet.ItemChoiceID >= QUEST_REWARD_CHOICES_COUNT) - { - TC_LOG_ERROR("network", "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player %s (%s) tried to get invalid reward (%u) (possible packet-hacking detected)", _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), packet.ItemChoiceID); - return; - } - TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_CHOOSE_REWARD npc = %s, quest = %u, reward = %u", packet.QuestGiverGUID.ToString().c_str(), packet.QuestID, packet.ItemChoiceID); 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) + { + ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate(packet.ItemChoiceID); + if (!rewardProto) + { + TC_LOG_ERROR("network", "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player %s (%s) tried to get invalid reward item (Item Entry: %u) for quest %u (possible packet-hacking detected)", _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), packet.ItemChoiceID, packet.QuestID); + return; + } + + bool itemValid = false; + for (uint32 i = 0; i < quest->GetRewChoiceItemsCount(); ++i) + { + if (quest->RewardChoiceItemId[i] && quest->RewardChoiceItemId[i] == packet.ItemChoiceID) + { + 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); + return; + } + } Object* object = _player; @@ -643,4 +664,4 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPackets::Quest::Ques } SendPacket(response.Write()); -}
\ No newline at end of file +} diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 3e62348a5c3..8433a549c60 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -163,6 +163,33 @@ enum QuestFlags // ... 4.x added flags up to 0x80000000 - all unknown for now }; +// last checked in 19802 +enum QuestFlagsEx +{ + QUEST_FLAGS_EX_NONE = 0X000000, + QUEST_FLAGS_EX_KEEP_ADDITIONAL_ITEMS = 0X000001, + QUEST_FLAGS_EX_SUPPRESS_GOSSIP_COMPLETE = 0X000002, + QUEST_FLAGS_EX_SUPPRESS_GOSSIP_ACCEPT = 0X000004, + QUEST_FLAGS_EX_DISALLOW_PLAYER_AS_QUESTGIVER = 0X000008, + QUEST_FLAGS_EX_DISPLAY_CLASS_CHOICE_REWARDS = 0X000010, + QUEST_FLAGS_EX_DISPLAY_SPEC_CHOICE_REWARDS = 0X000020, + QUEST_FLAGS_EX_REMOVE_FROM_LOG_ON_PERIDOIC_RESET = 0X000040, + QUEST_FLAGS_EX_ACCOUNT_LEVEL_QUEST = 0X000080, + QUEST_FLAGS_EX_LEGENDARY_QUEST = 0X000100, + QUEST_FLAGS_EX_NO_GUILD_XP = 0X000200, + QUEST_FLAGS_EX_RESET_CACHE_ON_ACCEPT = 0X000400, + QUEST_FLAGS_EX_NO_ABANDON_ONCE_ANY_OBJECTIVE_COMPLETE = 0X000800, + QUEST_FLAGS_EX_RECAST_ACCEPT_SPELL_ON_LOGIN = 0X001000, + QUEST_FLAGS_EX_UPDATE_ZONE_AURAS = 0X002000, + QUEST_FLAGS_EX_NO_CREDIT_FOR_PROXY = 0X004000, + QUEST_FLAGS_EX_DISPLAY_AS_DAILY_QUEST = 0X008000, + QUEST_FLAGS_EX_PART_OF_QUEST_LINE = 0X010000, + QUEST_FLAGS_EX_QUEST_FOR_INTERNAL_BUILDS_ONLY = 0X020000, + QUEST_FLAGS_EX_SUPPRESS_SPELL_LEARN_TEXT_LINE = 0X040000, + QUEST_FLAGS_EX_DISPLAY_HEADER_AS_OBJECTIVE_FOR_TASKS = 0X080000, + QUEST_FLAGS_EX_GARRISON_NON_OWNERS_ALLOWED = 0X100000 +}; + enum QuestSpecialFlags { QUEST_SPECIAL_FLAGS_NONE = 0x000, diff --git a/src/server/shared/Database/Implementation/HotfixDatabase.cpp b/src/server/shared/Database/Implementation/HotfixDatabase.cpp index 7f148f95e00..73441855483 100644 --- a/src/server/shared/Database/Implementation/HotfixDatabase.cpp +++ b/src/server/shared/Database/Implementation/HotfixDatabase.cpp @@ -118,6 +118,9 @@ void HotfixDatabaseConnection::DoPrepareStatements() // PhaseGroup.db2 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); + // SoundEntries.db2 PrepareStatement(HOTFIX_SEL_SOUND_ENTRIES, "SELECT ID, SoundType, Name, FileDataID1, FileDataID2, FileDataID3, FileDataID4, FileDataID5, " "FileDataID6, FileDataID7, FileDataID8, FileDataID9, FileDataID10, FileDataID11, FileDataID12, FileDataID13, FileDataID14, FileDataID15, " diff --git a/src/server/shared/Database/Implementation/HotfixDatabase.h b/src/server/shared/Database/Implementation/HotfixDatabase.h index 70472537510..3d8e528cd98 100644 --- a/src/server/shared/Database/Implementation/HotfixDatabase.h +++ b/src/server/shared/Database/Implementation/HotfixDatabase.h @@ -86,6 +86,8 @@ enum HotfixDatabaseStatements HOTFIX_SEL_OVERRIDE_SPELL_DATA, HOTFIX_SEL_PHASE_GROUP, + + HOTFIX_SEL_QUEST_PACKAGE_ITEM, HOTFIX_SEL_SOUND_ENTRIES, HOTFIX_SEL_SOUND_ENTRIES_LOCALE, |
