From 3ceed0edfbb9faf243c756ed202d9f4322f639ae Mon Sep 17 00:00:00 2001 From: Yaki Khadafi Date: Wed, 22 Aug 2012 20:08:58 +0300 Subject: [PATCH] [0159] Update quest system. TODO: - implement currency requirements/rewards - skill rewards - skill learned requirements. - not show quests with RewSkill to players which do not have that skill Signed-off-by: Yaki Khadafi --- .../0159_xxxxx_01_mangos_quest_template.sql | 37 + src/game/DBCEnums.h | 8 + src/game/DBCStores.cpp | 3 +- src/game/DBCStores.h | 1 + src/game/DBCStructure.h | 30 +- src/game/DBCfmt.h | 1 + src/game/GossipDef.cpp | 217 ++- src/game/ObjectMgr.cpp | 149 +- src/game/Opcodes.cpp | 64 +- src/game/Opcodes.h | 62 +- src/game/Player.cpp | 1460 +++++++++-------- src/game/QuestDef.cpp | 33 + src/game/QuestDef.h | 32 +- src/game/QuestHandler.cpp | 14 +- src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 2 +- 16 files changed, 1273 insertions(+), 842 deletions(-) create mode 100644 sql/updates/0159_xxxxx_01_mangos_quest_template.sql diff --git a/sql/updates/0159_xxxxx_01_mangos_quest_template.sql b/sql/updates/0159_xxxxx_01_mangos_quest_template.sql new file mode 100644 index 000000000..bd7eaca1a --- /dev/null +++ b/sql/updates/0159_xxxxx_01_mangos_quest_template.sql @@ -0,0 +1,37 @@ +ALTER TABLE db_version CHANGE COLUMN required_0157_xxxxx_01_player_levelstats required_0159_xxxxx_01_mangos_quest_template bit; + +ALTER TABLE `quest_template` MODIFY COLUMN `RequiredRaces` int(7) unsigned NOT NULL DEFAULT '0'; + +ALTER TABLE `quest_template` ADD COLUMN `ReqSpellLearned` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `ReqSpellCast4`; + +ALTER TABLE `quest_template` ADD COLUMN `PortraitGiver` mediumint(9) NOT NULL DEFAULT '0' AFTER `BonusTalents`; +ALTER TABLE `quest_template` ADD COLUMN `PortraitTurnIn` mediumint(9) NOT NULL DEFAULT '0' AFTER `PortraitGiver`; + +ALTER TABLE `quest_template` ADD COLUMN `PortraitGiverText` text AFTER `CompletedText`; +ALTER TABLE `quest_template` ADD COLUMN `PortraitGiverName` text AFTER `PortraitGiverText`; +ALTER TABLE `quest_template` ADD COLUMN `PortraitTurnInText` text AFTER `PortraitGiverName`; +ALTER TABLE `quest_template` ADD COLUMN `PortraitTurnInName` text AFTER `PortraitTurnInText`; + +ALTER TABLE `quest_template` ADD COLUMN `ReqCurrencyId1` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `ReqCreatureOrGOCount4`; +ALTER TABLE `quest_template` ADD COLUMN `ReqCurrencyId2` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `ReqCurrencyId1`; +ALTER TABLE `quest_template` ADD COLUMN `ReqCurrencyId3` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `ReqCurrencyId2`; +ALTER TABLE `quest_template` ADD COLUMN `ReqCurrencyId4` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `ReqCurrencyId3`; +ALTER TABLE `quest_template` ADD COLUMN `ReqCurrencyCount1` mediumint(9) NOT NULL DEFAULT '0' AFTER `ReqCurrencyId4`; +ALTER TABLE `quest_template` ADD COLUMN `ReqCurrencyCount2` mediumint(9) NOT NULL DEFAULT '0' AFTER `ReqCurrencyCount1`; +ALTER TABLE `quest_template` ADD COLUMN `ReqCurrencyCount3` mediumint(9) NOT NULL DEFAULT '0' AFTER `ReqCurrencyCount2`; +ALTER TABLE `quest_template` ADD COLUMN `ReqCurrencyCount4` mediumint(9) NOT NULL DEFAULT '0' AFTER `ReqCurrencyCount3`; + +ALTER TABLE `quest_template` ADD COLUMN `RewCurrencyId1` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `RewItemCount4`; +ALTER TABLE `quest_template` ADD COLUMN `RewCurrencyId2` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `RewCurrencyId1`; +ALTER TABLE `quest_template` ADD COLUMN `RewCurrencyId3` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `RewCurrencyId2`; +ALTER TABLE `quest_template` ADD COLUMN `RewCurrencyId4` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `RewCurrencyId3`; +ALTER TABLE `quest_template` ADD COLUMN `RewCurrencyCount1` mediumint(9) NOT NULL DEFAULT '0' AFTER `RewCurrencyId4`; +ALTER TABLE `quest_template` ADD COLUMN `RewCurrencyCount2` mediumint(9) NOT NULL DEFAULT '0' AFTER `RewCurrencyCount1`; +ALTER TABLE `quest_template` ADD COLUMN `RewCurrencyCount3` mediumint(9) NOT NULL DEFAULT '0' AFTER `RewCurrencyCount2`; +ALTER TABLE `quest_template` ADD COLUMN `RewCurrencyCount4` mediumint(9) NOT NULL DEFAULT '0' AFTER `RewCurrencyCount3`; + +ALTER TABLE `quest_template` ADD COLUMN `RewSkill` smallint(5) unsigned NOT NULL DEFAULT '0' AFTER `RewCurrencyCount4`; +ALTER TABLE `quest_template` ADD COLUMN `RewSkillValue` smallint(5) unsigned NOT NULL DEFAULT '0' AFTER `RewSkill`; + +ALTER TABLE `quest_template` ADD COLUMN `SoundAccept` smallint(5) unsigned NOT NULL DEFAULT '0' AFTER `OfferRewardEmoteDelay4`; +ALTER TABLE `quest_template` ADD COLUMN `SoundTurnIn` smallint(5) unsigned NOT NULL DEFAULT '0' AFTER `SoundAccept`; diff --git a/src/game/DBCEnums.h b/src/game/DBCEnums.h index 693595f1f..76fdcf5da 100644 --- a/src/game/DBCEnums.h +++ b/src/game/DBCEnums.h @@ -378,6 +378,14 @@ enum AbilitySkillFlags ABILITY_SKILL_NONTRAINABLE = 0x100 }; +#define CURRENCY_PRECISION 100.0f + +enum CurrencyFlags +{ + CURRENCY_FLAG_HAS_PRECISION = 0x08, + CURRENCY_FLAG_HAS_SEASON_COUNT = 0x80, // guessed +}; + enum ItemEnchantmentType { ITEM_ENCHANTMENT_TYPE_NONE = 0, diff --git a/src/game/DBCStores.cpp b/src/game/DBCStores.cpp index 4bc287a06..529d3c18c 100644 --- a/src/game/DBCStores.cpp +++ b/src/game/DBCStores.cpp @@ -81,7 +81,7 @@ DBCStorage sCreatureDisplayInfoExtraStore(Creatu DBCStorage sCreatureFamilyStore(CreatureFamilyfmt); DBCStorage sCreatureSpellDataStore(CreatureSpellDatafmt); DBCStorage sCreatureTypeStore(CreatureTypefmt); -//DBCStorage sCurrencyTypesStore(CurrencyTypesfmt); +DBCStorage sCurrencyTypesStore(CurrencyTypesfmt); DBCStorage sDungeonEncounterStore(DungeonEncounterfmt); DBCStorage sDurabilityQualityStore(DurabilityQualityfmt); @@ -479,6 +479,7 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureFamilyStore, dbcPath,"CreatureFamily.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureSpellDataStore, dbcPath,"CreatureSpellData.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureTypeStore, dbcPath,"CreatureType.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCurrencyTypesStore, dbcPath,"CurrencyTypes.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDungeonEncounterStore, dbcPath,"DungeonEncounter.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityCostsStore, dbcPath,"DurabilityCosts.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityQualityStore, dbcPath,"DurabilityQuality.dbc"); diff --git a/src/game/DBCStores.h b/src/game/DBCStores.h index 299d33728..fa758266b 100644 --- a/src/game/DBCStores.h +++ b/src/game/DBCStores.h @@ -121,6 +121,7 @@ extern DBCStorage sCreatureDisplayInfoExtraStore; extern DBCStorage sCreatureFamilyStore; extern DBCStorage sCreatureSpellDataStore; extern DBCStorage sCreatureTypeStore; +extern DBCStorage sCurrencyTypesStore; extern DBCStorage sDungeonEncounterStore; extern DBCStorage sDurabilityCostsStore; extern DBCStorage sDurabilityQualityStore; diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 5ea95fd88..30329ec73 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -807,20 +807,24 @@ struct CreatureTypeEntry char* Name; // 2 m_name_lang };*/ -/*struct CurrencyTypesEntry +struct CurrencyTypesEntry { - //uint32 ID; // 0 m_ID - //uint32 Category; // 1 m_categoryID - //char *name; // 2 - //char *iconName; // 3 - //uint32 // 4 - //uint32 // 5 - //uint32 // 6 - //uint32 // 7 - //uint32 // 8 - //uint32 // 9 - //char* description; // 10 -};*/ + uint32 ID; // 0 + //uint32 Category; // 1 + //char* name; // 2 + //char* iconName; // 3 + //uint32 unk4; // 4 + //uint32 unk5; // 5 + //uint32 unk6; // 6 + uint32 TotalCount; // 7 + uint32 WeekCount; // 8 + uint32 Flags; // 9 + //char* description; // 10 + + bool HasPrecision() const { return Flags & CURRENCY_FLAG_HAS_PRECISION; } + bool HasSeasonCount() const { return Flags & CURRENCY_FLAG_HAS_SEASON_COUNT; } + float GetPrecision() const { return HasPrecision() ? CURRENCY_PRECISION : 1.0f; } +}; struct DungeonEncounterEntry { diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h index 12ad3218f..95bc175dc 100644 --- a/src/game/DBCfmt.h +++ b/src/game/DBCfmt.h @@ -43,6 +43,7 @@ const char CreatureFamilyfmt[]="nfifiiiiixsx"; const char CreatureSpellDatafmt[]="niiiixxxx"; const char DungeonEncounterfmt[]="niiiisxx"; const char CreatureTypefmt[]="nxx"; +const char CurrencyTypesfmt[]="nxxxxxxiiix"; const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; const char DurabilityQualityfmt[]="nf"; const char EmotesEntryfmt[]="nxxiiixx"; diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp index 985c302cc..225c8b9f4 100644 --- a/src/game/GossipDef.cpp +++ b/src/game/GossipDef.cpp @@ -426,6 +426,10 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* pQuest, ObjectGuid guid std::string Title = pQuest->GetTitle(); std::string Details = pQuest->GetDetails(); std::string Objectives = pQuest->GetObjectives(); + std::string PortraitGiverText = pQuest->GetPortraitGiverText(); + std::string PortraitGiverName = pQuest->GetPortraitGiverName(); + std::string PortraitTurnInText = pQuest->GetPortraitTurnInText(); + std::string PortraitTurnInName = pQuest->GetPortraitTurnInName(); int loc_idx = GetMenuSession()->GetSessionDbLocaleIndex(); if (loc_idx >= 0) @@ -438,6 +442,7 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* pQuest, ObjectGuid guid Details = ql->Details[loc_idx]; if (ql->Objectives.size() > (size_t)loc_idx && !ql->Objectives[loc_idx].empty()) Objectives = ql->Objectives[loc_idx]; + // TODO: locales for PortraitGiver and PortraitTurnIn } } @@ -448,57 +453,52 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* pQuest, ObjectGuid guid data << Title; data << Details; data << Objectives; + data << PortraitGiverText; + data << PortraitGiverName; + data << PortraitTurnInText; + data << PortraitTurnInName; + data << uint32(pQuest->GetPortraitGiver()); + data << uint32(pQuest->GetPortraitTurnIn()); data << uint8(ActivateAccept ? 1 : 0); // auto finish data << uint32(pQuest->GetQuestFlags()); // 3.3.3 questFlags data << uint32(pQuest->GetSuggestedPlayers()); data << uint8(0); // IsFinished? value is sent back to server in quest accept packet + data << uint8(0); // is areatrigger quest + data << uint32(pQuest->GetReqSpellLearned()); - if (pQuest->HasQuestFlag(QUEST_FLAGS_HIDDEN_REWARDS)) + // unused 4.x.x? + /*if (pQuest->HasQuestFlag(QUEST_FLAGS_HIDDEN_REWARDS)) { data << uint32(0); // Rewarded chosen items hidden data << uint32(0); // Rewarded items hidden data << uint32(0); // Rewarded money hidden data << uint32(0); // Rewarded XP hidden } - else + else*/ { - ItemPrototype const* IProto; - data << uint32(pQuest->GetRewChoiceItemsCount()); for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) - { - if (!pQuest->RewChoiceItemId[i]) - continue; - data << uint32(pQuest->RewChoiceItemId[i]); + for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) data << uint32(pQuest->RewChoiceItemCount[i]); - - IProto = ObjectMgr::GetItemPrototype(pQuest->RewChoiceItemId[i]); - - if (IProto) + for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) + if (ItemPrototype const* IProto = ObjectMgr::GetItemPrototype(pQuest->RewChoiceItemId[i])) data << uint32(IProto->DisplayInfoID); else - data << uint32(0x00); - } + data << uint32(0); data << uint32(pQuest->GetRewItemsCount()); for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i) - { - if (!pQuest->RewItemId[i]) - continue; - data << uint32(pQuest->RewItemId[i]); + for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i) data << uint32(pQuest->RewItemCount[i]); - - IProto = ObjectMgr::GetItemPrototype(pQuest->RewItemId[i]); - - if (IProto) + for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i) + if (ItemPrototype const* IProto = ObjectMgr::GetItemPrototype(pQuest->RewItemId[i])) data << uint32(IProto->DisplayInfoID); else data << uint32(0); - } // send rewMoneyMaxLevel explicit for max player level, else send RewOrReqMoney if (GetMenuSession()->GetPlayer()->getLevel() >= sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL)) @@ -509,17 +509,14 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* pQuest, ObjectGuid guid data << uint32(pQuest->XPValue(GetMenuSession()->GetPlayer())); } - // TODO: fixme. rewarded honor points - data << uint32(pQuest->GetRewHonorAddition()); - data << float(pQuest->GetRewHonorMultiplier()); // new 3.3.0 - - data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0) - data << uint32(pQuest->GetRewSpellCast()); // casted spell data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles) + data << uint32(0); // unk, unused 10 * GetRewHonorAddition ? + data << float(0); // unk, unused GetRewHonorMultiplier ? data << uint32(pQuest->GetBonusTalents()); // bonus talents - data << uint32(0); // bonus arena points + data << uint32(0); // unk, unused bonus arena points? data << uint32(0); // rep reward show mask? + for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward factions ids data << uint32(pQuest->RewRepFaction[i]); @@ -530,6 +527,18 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* pQuest, ObjectGuid guid data << int32(0); // data << int32(pQuest->RewRepValue[i]); // current field for store of rep value, can be reused to implement "override value" + data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0) + data << uint32(pQuest->GetRewSpellCast()); // casted spell + + for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + data << uint32(pQuest->RewCurrencyId[i]); + + for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + data << uint32(pQuest->RewCurrencyCount[i]); + + data << uint32(pQuest->GetRewSkill()); + data << uint32(pQuest->GetRewSkillValue()); + data << uint32(QUEST_EMOTE_COUNT); for (uint32 i = 0; i < QUEST_EMOTE_COUNT; ++i) @@ -547,12 +556,18 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* pQuest, ObjectGuid guid void PlayerMenu::SendQuestQueryResponse(Quest const* pQuest) { std::string Title, Details, Objectives, EndText, CompletedText; + std::string PortraitGiverText, PortraitGiverName; + std::string PortraitTurnInText, PortraitTurnInName; std::string ObjectiveText[QUEST_OBJECTIVES_COUNT]; Title = pQuest->GetTitle(); Details = pQuest->GetDetails(); Objectives = pQuest->GetObjectives(); EndText = pQuest->GetEndText(); CompletedText = pQuest->GetCompletedText(); + PortraitGiverText = pQuest->GetPortraitGiverText(); + PortraitGiverName = pQuest->GetPortraitGiverName(); + PortraitTurnInText = pQuest->GetPortraitTurnInText(); + PortraitTurnInName = pQuest->GetPortraitTurnInName(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) ObjectiveText[i] = pQuest->ObjectiveText[i]; @@ -572,6 +587,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* pQuest) EndText = ql->EndText[loc_idx]; if (ql->CompletedText.size() > (size_t)loc_idx && !ql->CompletedText[loc_idx].empty()) CompletedText = ql->CompletedText[loc_idx]; + // TODO: locales for PortraitGiver and PortraitTurnIn for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) if (ql->ObjectiveText[i].size() > (size_t)loc_idx && !ql->ObjectiveText[i][loc_idx].empty()) @@ -593,15 +609,16 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* pQuest) data << uint32(pQuest->GetRepObjectiveFaction()); // shown in quest log as part of quest objective data << uint32(pQuest->GetRepObjectiveValue()); // shown in quest log as part of quest objective - data << uint32(0); // RequiredOpositeRepFaction - data << uint32(0); // RequiredOpositeRepValue, required faction value with another (oposite) faction (objective) + data << uint32(0); // RequiredOppositeRepFaction + data << uint32(0); // RequiredOppositeRepValue, required faction value with another (oposite) faction (objective) data << uint32(pQuest->GetNextQuestInChain()); // client will request this quest from NPC, if not 0 data << uint32(pQuest->GetRewXPId()); // column index in QuestXP.dbc (row based on quest level) - if (pQuest->HasQuestFlag(QUEST_FLAGS_HIDDEN_REWARDS)) + // unused 4.x.x ? + /*if (pQuest->HasQuestFlag(QUEST_FLAGS_HIDDEN_REWARDS)) data << uint32(0); // Hide money rewarded - else + else*/ data << uint32(pQuest->GetRewOrReqMoney()); // reward money (below max lvl) data << uint32(pQuest->GetRewMoneyMaxLevel()); // used in XP calculation at client @@ -609,27 +626,36 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* pQuest) data << uint32(pQuest->GetRewSpellCast()); // casted spell // rewarded honor points - data << uint32(pQuest->GetRewHonorAddition()); - data << float(pQuest->GetRewHonorMultiplier()); // new reward honor (multiplied by ~62 at client side) + data << uint32(pQuest->GetRewHonorAddition()); // unused 4.x.x ? + data << float(pQuest->GetRewHonorMultiplier()); // unused 4.x.x ? new reward honor (multiplied by ~62 at client side) data << uint32(pQuest->GetSrcItemId()); // source item id data << uint32(pQuest->GetQuestFlags()); // quest flags + + data << uint32(0); // MinimapTargetMark + data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles) data << uint32(pQuest->GetPlayersSlain()); // players slain data << uint32(pQuest->GetBonusTalents()); // bonus talents - data << uint32(0); // bonus arena points + + data << uint32(0); // unused 4.x.x ? bonus arena points + data << uint32(pQuest->GetRewSkill()); // Rewarded skill id + data << uint32(pQuest->GetRewSkillValue()); // Rewarded skill bonus points data << uint32(0); // rew rep show mask? + data << uint32(pQuest->GetPortraitGiver()); + data << uint32(pQuest->GetPortraitTurnIn()); int iI; - if (pQuest->HasQuestFlag(QUEST_FLAGS_HIDDEN_REWARDS)) + // unused 4.?.? + /*if (pQuest->HasQuestFlag(QUEST_FLAGS_HIDDEN_REWARDS)) { for (iI = 0; iI < QUEST_REWARDS_COUNT; ++iI) data << uint32(0) << uint32(0); for (iI = 0; iI < QUEST_REWARD_CHOICES_COUNT; ++iI) data << uint32(0) << uint32(0); } - else + else*/ { for (iI = 0; iI < QUEST_REWARDS_COUNT; ++iI) { @@ -677,7 +703,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* pQuest) } data << uint32(pQuest->ReqCreatureOrGOCount[iI]); data << uint32(pQuest->ReqSourceId[iI]); - data << uint32(0); // req source count? + data << uint32(pQuest->ReqSourceCount[iI]); } for (iI = 0; iI < QUEST_ITEM_OBJECTIVES_COUNT; ++iI) @@ -686,32 +712,32 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* pQuest) data << uint32(pQuest->ReqItemCount[iI]); } - data << uint32(0); // unk1 4.3.4 + data << uint32(pQuest->GetReqSpellLearned()); for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; ++iI) data << ObjectiveText[iI]; - for(iI = 0; iI < 4; ++iI) // 4.0.0 currency reward id and count + for(iI = 0; iI < QUEST_REWARD_CURRENCY_COUNT; ++iI) { - data << uint32(0); - data << uint32(0); + data << uint32(pQuest->RewCurrencyId[iI]); + data << uint32(pQuest->RewCurrencyCount[iI]); } - for(iI = 0; iI < 4; ++iI) // 4.0.0 currency required id and count + for(iI = 0; iI < QUEST_REQUIRED_CURRENCY_COUNT; ++iI) { - data << uint32(0); - data << uint32(0); + data << uint32(pQuest->ReqCurrencyId[iI]); + data << uint32(pQuest->ReqCurrencyCount[iI]); } - data << ""; // 4.3.4 4 strings sent, unk - data << ""; - data << ""; - data << ""; + data << PortraitGiverText; + data << PortraitGiverName; + data << PortraitTurnInText; + data << PortraitTurnInName; - data << uint32(0); - data << uint32(0); + data << uint32(pQuest->GetSoundAcceptId()); + data << uint32(pQuest->GetSoundTurnInId()); - GetMenuSession()->SendPacket( &data ); + GetMenuSession()->SendPacket(&data); DEBUG_LOG("WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u", pQuest->GetQuestId()); } @@ -719,6 +745,10 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* pQuest, ObjectGuid npcGU { std::string Title = pQuest->GetTitle(); std::string OfferRewardText = pQuest->GetOfferRewardText(); + std::string PortraitGiverText = pQuest->GetPortraitGiverText(); + std::string PortraitGiverName = pQuest->GetPortraitGiverName(); + std::string PortraitTurnInText = pQuest->GetPortraitTurnInText(); + std::string PortraitTurnInName = pQuest->GetPortraitTurnInName(); int loc_idx = GetMenuSession()->GetSessionDbLocaleIndex(); if (loc_idx >= 0) @@ -729,6 +759,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* pQuest, ObjectGuid npcGU Title = ql->Title[loc_idx]; if (ql->OfferRewardText.size() > (size_t)loc_idx && !ql->OfferRewardText[loc_idx].empty()) OfferRewardText = ql->OfferRewardText[loc_idx]; + // TODO: locales for PortraitGiver and PortraitTurnIn } } @@ -739,6 +770,13 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* pQuest, ObjectGuid npcGU data << Title; data << OfferRewardText; + data << PortraitGiverText; + data << PortraitGiverName; + data << PortraitTurnInText; + data << PortraitTurnInName; + data << uint32(pQuest->GetPortraitGiver()); + data << uint32(pQuest->GetPortraitTurnIn()); + data << uint8(EnableNext ? 1 : 0); // Auto Finish data << uint32(pQuest->GetQuestFlags()); // 3.3.3 questFlags data << uint32(pQuest->GetSuggestedPlayers()); // SuggestedGroupNum @@ -758,34 +796,27 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* pQuest, ObjectGuid npcGU data << uint32(pQuest->OfferRewardEmote[i]); } - ItemPrototype const* pItem; - data << uint32(pQuest->GetRewChoiceItemsCount()); - for (uint32 i = 0; i < pQuest->GetRewChoiceItemsCount(); ++i) - { - pItem = ObjectMgr::GetItemPrototype(pQuest->RewChoiceItemId[i]); - + for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) data << uint32(pQuest->RewChoiceItemId[i]); + for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) data << uint32(pQuest->RewChoiceItemCount[i]); - - if (pItem) + for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) + if (ItemPrototype const* pItem = ObjectMgr::GetItemPrototype(pQuest->RewChoiceItemId[i])) data << uint32(pItem->DisplayInfoID); else data << uint32(0); - } data << uint32(pQuest->GetRewItemsCount()); - for (uint32 i = 0; i < pQuest->GetRewItemsCount(); ++i) - { - pItem = ObjectMgr::GetItemPrototype(pQuest->RewItemId[i]); + for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i) data << uint32(pQuest->RewItemId[i]); + for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i) data << uint32(pQuest->RewItemCount[i]); - - if (pItem) + for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i) + if (ItemPrototype const* pItem = ObjectMgr::GetItemPrototype(pQuest->RewItemId[i])) data << uint32(pItem->DisplayInfoID); else data << uint32(0); - } // send rewMoneyMaxLevel explicit for max player level, else send RewOrReqMoney if (GetMenuSession()->GetPlayer()->getLevel() >= sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL)) @@ -796,27 +827,34 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* pQuest, ObjectGuid npcGU // xp data << uint32(pQuest->XPValue(GetMenuSession()->GetPlayer())); - // TODO: fixme. rewarded honor points. Multiply with 10 to satisfy client - data << uint32(10 * MaNGOS::Honor::hk_honor_at_level(GetMenuSession()->GetPlayer()->getLevel(), pQuest->GetRewHonorAddition())); - data << float(pQuest->GetRewHonorMultiplier()); + data << uint32(pQuest->GetCharTitleId()); // character title + data << uint32(0); // unk, unused 10 * GetRewHonorAddition ? + data << float(0); // unk, unused GetRewHonorMultiplier ? + data << uint32(pQuest->GetBonusTalents()); // bonus talents + data << uint32(0); // unk, unused bonus arena points? + data << uint32(0); // rep reward show mask? - data << uint32(0x08); // unused by client? - data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0) - data << uint32(pQuest->GetRewSpellCast()); // casted spell - data << uint32(pQuest->GetCharTitleId()); // character title - data << uint32(pQuest->GetBonusTalents()); // bonus talents - data << uint32(0); // bonus arena points - data << uint32(0); // rew rep show mask? - - for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward factions ids + for(int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward factions ids data << uint32(pQuest->RewRepFaction[i]); - for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // columnid in QuestFactionReward.dbc (if negative, from second row) + for(int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // columnid in QuestFactionReward.dbc (if negative, from second row) data << int32(pQuest->RewRepValueId[i]); - for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward reputation override. No diplomacy bonus is expected given, reward also does not display in chat window + for(int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward reputation override. No diplomacy bonus is expected given, reward also does not display in chat window data << int32(0); - // data << int32(pQuest->RewRepValue[i]); + //data << int32(pQuest->RewRepValue[i]); + + data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0) + data << uint32(pQuest->GetRewSpellCast()); // casted spell + + for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + data << uint32(pQuest->RewCurrencyId[i]); + + for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + data << uint32(pQuest->RewCurrencyCount[i]); + + data << uint32(pQuest->GetRewSkill()); + data << uint32(pQuest->GetRewSkillValue()); GetMenuSession()->SendPacket(&data); DEBUG_LOG("WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid = %s, questid = %u", npcGUID.GetString().c_str(), pQuest->GetQuestId()); @@ -889,6 +927,16 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* pQuest, ObjectGuid npcG data << uint32(0); } + data << uint32(pQuest->GetReqCurrencyCount()); + for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) + { + if (!pQuest->ReqCurrencyId[i]) + continue; + + data << uint32(pQuest->ReqCurrencyId[i]); + data << uint32(pQuest->ReqCurrencyCount[i]); + } + if (!Completable) // Completable = flags1 && flags2 && flags3 && flags4 data << uint32(0x00); // flags1 else @@ -897,6 +945,7 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* pQuest, ObjectGuid npcG data << uint32(0x04); // flags2 data << uint32(0x08); // flags3 data << uint32(0x10); // flags4 + data << uint32(0x40); // flags5 GetMenuSession()->SendPacket(&data); DEBUG_LOG("WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid = %s, questid = %u", npcGUID.GetString().c_str(), pQuest->GetQuestId()); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index a28188822..acea0f93c 100755 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -3616,7 +3616,15 @@ void ObjectMgr::LoadQuests() // 135 136 137 138 "OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4," // 139 140 - "StartScript, CompleteScript" + "StartScript, CompleteScript, " + // 141 142 143 144 145 146 147 + "ReqSpellLearned, PortraitGiver, PortraitTurnIn, PortraitGiverText, PortraitGiverName, PortraitTurnInText, PortraitTurnInName, " + // 148 149 150 151 152 153 154 155 + "ReqCurrencyId1, ReqCurrencyId2, ReqCurrencyId3, ReqCurrencyId4, ReqCurrencyCount1, ReqCurrencyCount2, ReqCurrencyCount3, ReqCurrencyCount4, " + // 156 157 158 159 160 161 162 163 + "RewCurrencyId1, RewCurrencyId2, RewCurrencyId3, RewCurrencyId4, RewCurrencyCount1, RewCurrencyCount2, RewCurrencyCount3, RewCurrencyCount4, " + // 164 165 166 167 + "RewSkill, RewSkillValue, SoundAccept, SoundTurnIn " " FROM quest_template"); if (!result) { @@ -4209,6 +4217,145 @@ void ObjectMgr::LoadQuests() } } + if (qinfo->RewSkill) + { + if (!sSkillLineStore.LookupEntry(qinfo->RewSkill)) + { + sLog.outErrorDb("Quest %u has `RewSkill` = %u but this skill does not exist", + qinfo->GetQuestId(), qinfo->RewSkill); + qinfo->RewSkill = 0; + qinfo->RewSkillValue = 0; + } + } + + if (qinfo->RewSkillValue) + { + if (qinfo->RewSkillValue > sWorld.GetConfigMaxSkillValue()) + { + sLog.outErrorDb("Quest %u has `RewSkillValue` = %u which is more than max possible skill value %u.", + qinfo->GetQuestId(), qinfo->RewSkillValue, sWorld.GetConfigMaxSkillValue()); + } + } + else + { + if (qinfo->RewSkill) + { + sLog.outErrorDb("Quest %u has `RewSkillValue` = %u, but `RewSkill` exists and is %u.", + qinfo->GetQuestId(), qinfo->RewSkillValue, qinfo->RewSkill); + qinfo->RewSkill = 0; + } + } + + if (qinfo->ReqSpellLearned) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(qinfo->ReqSpellLearned); + + if (!spellInfo) + { + sLog.outErrorDb("Quest %u has `ReqSpellLearned` = %u but spell %u does not exist, quest will not have a spell requirement.", + qinfo->GetQuestId(), qinfo->ReqSpellLearned, qinfo->ReqSpellLearned); + qinfo->ReqSpellLearned = 0; + } + else if (!SpellMgr::IsSpellValid(spellInfo)) + { + sLog.outErrorDb("Quest %u has `ReqSpellLearned` = %u but spell %u is broken, quest will not have a spell requirement.", + qinfo->GetQuestId(), qinfo->ReqSpellLearned, qinfo->ReqSpellLearned); + qinfo->ReqSpellLearned = 0; + } + } + + for (int j = 0; j < QUEST_REQUIRED_CURRENCY_COUNT; ++j) + { + if (qinfo->ReqCurrencyId[j]) + { + CurrencyTypesEntry const * currencyEntry = sCurrencyTypesStore.LookupEntry(qinfo->ReqCurrencyId[j]); + if (!currencyEntry) + { + sLog.outErrorDb("Quest %u has `ReqCurrencyId%d` = %u but currency with entry %u does not exist, quest can not be completed.", + qinfo->GetQuestId(), j + 1, qinfo->ReqCurrencyId[j], qinfo->ReqCurrencyId[j]); + qinfo->ReqCurrencyId[j] = 0; + qinfo->ReqCurrencyCount[j] = 0; + } + else + { + if (!qinfo->ReqCurrencyCount[j]) + { + sLog.outErrorDb("Quest %u has `ReqCurrencyId%d` = %u but `ReqCurrencyCount%d` = %u.", + qinfo->GetQuestId(), j + 1, qinfo->ReqCurrencyId[j], j + 1, qinfo->ReqCurrencyCount[j]); + qinfo->ReqCurrencyId[j] = 0; + } + else if (currencyEntry->TotalCount && uint32(qinfo->ReqCurrencyCount[j] * currencyEntry->GetPrecision()) > currencyEntry->TotalCount) + { + sLog.outErrorDb("Quest %u has `ReqCurrencyCount%d` = %u but currency %u has max count %u / %u (precision).", + qinfo->GetQuestId(), j + 1, qinfo->ReqCurrencyCount[j], qinfo->ReqCurrencyId[j], currencyEntry->TotalCount, uint32(currencyEntry->GetPrecision())); + qinfo->ReqCurrencyCount[j] = currencyEntry->TotalCount; + } + } + + } + else if (qinfo->ReqCurrencyCount[j]) + { + if (!qinfo->ReqCurrencyId[j]) + { + sLog.outErrorDb("Quest %u has `ReqCurrencyId%d` = 0 but `ReqCurrencyCount%d` = %u.", + qinfo->GetQuestId(), j + 1, j + 1, qinfo->ReqCurrencyCount[j]); + qinfo->ReqCurrencyCount[j] = 0; + } + } + } + + for (int j = 0; j < QUEST_REWARD_CURRENCY_COUNT; ++j) + { + if (qinfo->RewCurrencyId[j]) + { + CurrencyTypesEntry const * currencyEntry = sCurrencyTypesStore.LookupEntry(qinfo->RewCurrencyId[j]); + if (!currencyEntry) + { + sLog.outErrorDb("Quest %u has `RewCurrencyId%d` = %u but currency with entry %u does not exist, quest will not reward that currency.", + qinfo->GetQuestId(), j + 1, qinfo->RewCurrencyId[j], qinfo->RewCurrencyId[j]); + qinfo->RewCurrencyId[j] = 0; + qinfo->RewCurrencyCount[j] = 0; + } + else if (!qinfo->RewCurrencyCount[j]) + { + sLog.outErrorDb("Quest %u has `RewCurrencyId%d` = %u but `RewCurrencyCount%d` = %u.", + qinfo->GetQuestId(), j + 1, qinfo->RewCurrencyId[j], j + 1, qinfo->RewCurrencyCount[j]); + qinfo->RewCurrencyId[j] = 0; + } + } + else if (qinfo->RewCurrencyCount[j]) + { + if (!qinfo->RewCurrencyId[j]) + { + sLog.outErrorDb("Quest %u has `RewCurrencyId%d` = 0 but `RewCurrencyCount%d` = %u.", + qinfo->GetQuestId(), j + 1, j + 1, qinfo->RewCurrencyCount[j]); + qinfo->RewCurrencyCount[j] = 0; + } + } + } + + if (qinfo->SoundAcceptId) + { + SoundEntriesEntry const * soundEntry = sSoundEntriesStore.LookupEntry(qinfo->SoundAcceptId); + if (!soundEntry) + { + sLog.outErrorDb("Quest %u has `SoundAcceptId` = %u but sound with that entry does not exists.", + qinfo->GetQuestId(), qinfo->SoundAcceptId); + qinfo->SoundAcceptId = 0; + } + } + + if (qinfo->SoundTurnInId) + { + SoundEntriesEntry const * soundEntry = sSoundEntriesStore.LookupEntry(qinfo->SoundTurnInId); + if (!soundEntry) + { + sLog.outErrorDb("Quest %u has `SoundTurnInId` = %u but sound with that entry does not exists.", + qinfo->GetQuestId(), qinfo->SoundTurnInId); + qinfo->SoundTurnInId = 0; + } + } + if (qinfo->ExclusiveGroup) m_ExclusiveQuestGroups.insert(ExclusiveQuestGroupsMap::value_type(qinfo->ExclusiveGroup, qinfo->GetQuestId())); diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index d1b80d7d4..f3962ebcd 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -458,30 +458,30 @@ void InitializeOpcodes() OPCODE(SMSG_QUESTGIVER_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(CMSG_QUESTGIVER_HELLO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverHelloOpcode ); OPCODE(SMSG_QUESTGIVER_QUEST_LIST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(CMSG_QUESTGIVER_QUERY_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverQueryQuestOpcode); + OPCODE(CMSG_QUESTGIVER_QUERY_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverQueryQuestOpcode); //OPCODE(CMSG_QUESTGIVER_QUEST_AUTOLAUNCH, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverQuestAutoLaunch ); - //OPCODE(SMSG_QUESTGIVER_QUEST_DETAILS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(CMSG_QUESTGIVER_ACCEPT_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverAcceptQuestOpcode); - //OPCODE(CMSG_QUESTGIVER_COMPLETE_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverCompleteQuest ); - //OPCODE(SMSG_QUESTGIVER_REQUEST_ITEMS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(CMSG_QUESTGIVER_REQUEST_REWARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverRequestRewardOpcode); - //OPCODE(SMSG_QUESTGIVER_OFFER_REWARD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(CMSG_QUESTGIVER_CHOOSE_REWARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverChooseRewardOpcode); - //OPCODE(SMSG_QUESTGIVER_QUEST_INVALID, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_QUESTGIVER_QUEST_DETAILS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); // + + OPCODE(CMSG_QUESTGIVER_ACCEPT_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverAcceptQuestOpcode); + OPCODE(CMSG_QUESTGIVER_COMPLETE_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverCompleteQuest ); + OPCODE(SMSG_QUESTGIVER_REQUEST_ITEMS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(CMSG_QUESTGIVER_REQUEST_REWARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverRequestRewardOpcode); + OPCODE(SMSG_QUESTGIVER_OFFER_REWARD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(CMSG_QUESTGIVER_CHOOSE_REWARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverChooseRewardOpcode); + OPCODE(SMSG_QUESTGIVER_QUEST_INVALID, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_QUESTGIVER_CANCEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverCancel ); - //OPCODE(SMSG_QUESTGIVER_QUEST_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(SMSG_QUESTGIVER_QUEST_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_QUESTGIVER_QUEST_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_QUESTGIVER_QUEST_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_QUESTLOG_SWAP_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestLogSwapQuest ); - //OPCODE(CMSG_QUESTLOG_REMOVE_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestLogRemoveQuest ); - //OPCODE(SMSG_QUESTLOG_FULL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(SMSG_QUESTUPDATE_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(SMSG_QUESTUPDATE_FAILEDTIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(SMSG_QUESTUPDATE_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(SMSG_QUESTUPDATE_ADD_KILL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(CMSG_QUESTLOG_REMOVE_QUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestLogRemoveQuest ); + OPCODE(SMSG_QUESTLOG_FULL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_QUESTUPDATE_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_QUESTUPDATE_FAILEDTIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_QUESTUPDATE_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_QUESTUPDATE_ADD_KILL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_QUESTUPDATE_ADD_ITEM_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(CMSG_QUEST_CONFIRM_ACCEPT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestConfirmAccept ); - //OPCODE(SMSG_QUEST_CONFIRM_ACCEPT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(CMSG_PUSHQUESTTOPARTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePushQuestToParty ); + OPCODE(CMSG_QUEST_CONFIRM_ACCEPT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestConfirmAccept ); + OPCODE(SMSG_QUEST_CONFIRM_ACCEPT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(CMSG_PUSHQUESTTOPARTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePushQuestToParty ); OPCODE(CMSG_LIST_INVENTORY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleListInventoryOpcode ); OPCODE(SMSG_LIST_INVENTORY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(CMSG_SELL_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSellItemOpcode ); @@ -550,8 +550,8 @@ void InitializeOpcodes() //OPCODE(CMSG_SETSHEATHED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleSetSheathedOpcode ); //OPCODE(SMSG_COOLDOWN_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_SPELL_DELAYED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(CMSG_QUEST_POI_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPOIQueryOpcode ); - //OPCODE(SMSG_QUEST_POI_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(CMSG_QUEST_POI_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPOIQueryOpcode ); + OPCODE(SMSG_QUEST_POI_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_GHOST, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(CMSG_GM_INVIS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(SMSG_INVALID_PROMOTION_CODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -585,8 +585,8 @@ void InitializeOpcodes() OPCODE(CMSG_GMTICKET_UPDATETEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketUpdateTextOpcode ); OPCODE(SMSG_GMTICKET_UPDATETEXT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_ACCOUNT_DATA_TIMES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(CMSG_REQUEST_ACCOUNT_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestAccountData ); - OPCODE(CMSG_UPDATE_ACCOUNT_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateAccountData); + OPCODE(CMSG_REQUEST_ACCOUNT_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestAccountData ); + OPCODE(CMSG_UPDATE_ACCOUNT_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateAccountData ); OPCODE(SMSG_UPDATE_ACCOUNT_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_CHANGEPLAYER_DIFFICULTY_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -596,7 +596,7 @@ void InitializeOpcodes() OPCODE(SMSG_GMTICKET_GETTICKET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_UNLEARN_TALENTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(SMSG_INSTANCE_ENCOUNTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(SMSG_GAMEOBJECT_DESPAWN_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_GAMEOBJECT_DESPAWN_ANIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(MSG_CORPSE_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseQueryOpcode ); OPCODE(CMSG_GMTICKET_DELETETICKET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGMTicketDeleteTicketOpcode); OPCODE(SMSG_GMTICKET_DELETETICKET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -693,7 +693,7 @@ void InitializeOpcodes() //OPCODE(SMSG_STABLE_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_STABLE_REVIVE_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStableRevivePet ); //OPCODE(CMSG_STABLE_SWAP_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStableSwapPet ); - //OPCODE(MSG_QUEST_PUSH_RESULT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPushResult ); + OPCODE(MSG_QUEST_PUSH_RESULT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPushResult ); //OPCODE(SMSG_PLAY_MUSIC, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_PLAY_OBJECT_SOUND, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_REQUEST_PET_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPetInfoOpcode ); @@ -766,7 +766,7 @@ void InitializeOpcodes() //OPCODE(SMSG_PLAYER_SKINNED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_DURABILITY_DAMAGE_DEATH, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_SET_EXPLORATION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //OPCODE(CMSG_SET_ACTIONBAR_TOGGLES, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActionBarTogglesOpcode ); + OPCODE(CMSG_SET_ACTIONBAR_TOGGLES, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActionBarTogglesOpcode ); //OPCODE(UMSG_DELETE_GUILD_CHARTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(MSG_PETITION_RENAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetitionRenameOpcode ); OPCODE(SMSG_INIT_WORLD_STATES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -1108,8 +1108,8 @@ void InitializeOpcodes() OPCODE(CMSG_TOTEM_DESTROYED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTotemDestroyed ); //OPCODE(CMSG_EXPIRE_RAID_INSTANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(CMSG_NO_SPELL_VARIANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //OPCODE(CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverStatusMultipleQuery); - //OPCODE(SMSG_QUESTGIVER_STATUS_MULTIPLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestgiverStatusMultipleQuery); + OPCODE(SMSG_QUESTGIVER_STATUS_MULTIPLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(CMSG_SET_PLAYER_DECLINED_NAMES, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetPlayerDeclinedNamesOpcode); OPCODE(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_QUERY_SERVER_BUCK_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -1196,7 +1196,7 @@ void InitializeOpcodes() OPCODE(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_DISMISS_CONTROLLED_VEHICLE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissControlledVehicle ); //OPCODE(CMSG_COMPLETE_ACHIEVEMENT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //OPCODE(SMSG_QUESTUPDATE_ADD_PVP_KILL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_QUESTUPDATE_ADD_PVP_KILL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_SET_CRITERIA_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(SMSG_CALENDAR_RAID_LOCKOUT_UPDATED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_UNITANIMTIER_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -1331,8 +1331,8 @@ void InitializeOpcodes() //OPCODE(CMSG_GM_CREATE_TICKET_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(CMSG_SERVERINFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(SMSG_SERVERINFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //OPCODE(CMSG_UI_TIME_REQUEST, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleUITimeRequestOpcode ); - //OPCODE(SMSG_UI_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(CMSG_UI_TIME_REQUEST, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleUITimeRequestOpcode ); + OPCODE(SMSG_UI_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_CHAR_RACE_CHANGE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(MSG_VIEW_PHASE_SHIFT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(SMSG_TALENTS_INVOLUNTARILY_RESET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index eaa881e35..7a9124673 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -443,30 +443,30 @@ enum Opcodes SMSG_QUESTGIVER_STATUS = 0x2115, // 4.3.4 15595 CMSG_QUESTGIVER_HELLO = 0x0D17, // 4.3.4 15595 SMSG_QUESTGIVER_QUEST_LIST = 0x0134, // 4.3.4 15595 - CMSG_QUESTGIVER_QUERY_QUEST = 0x1187, + CMSG_QUESTGIVER_QUERY_QUEST = 0x2F14, // 4.3.4 15595 CMSG_QUESTGIVER_QUEST_AUTOLAUNCH = 0x1188, - SMSG_QUESTGIVER_QUEST_DETAILS = 0x1189, - CMSG_QUESTGIVER_ACCEPT_QUEST = 0x118A, - CMSG_QUESTGIVER_COMPLETE_QUEST = 0x118B, - SMSG_QUESTGIVER_REQUEST_ITEMS = 0x118C, - CMSG_QUESTGIVER_REQUEST_REWARD = 0x118D, - SMSG_QUESTGIVER_OFFER_REWARD = 0x118E, - CMSG_QUESTGIVER_CHOOSE_REWARD = 0x118F, - SMSG_QUESTGIVER_QUEST_INVALID = 0x1190, + SMSG_QUESTGIVER_QUEST_DETAILS = 0x2425, // 4.3.4 15595 + CMSG_QUESTGIVER_ACCEPT_QUEST = 0x6B37, // 4.3.4 15595 + CMSG_QUESTGIVER_COMPLETE_QUEST = 0x0114, // 4.3.4 15595 + SMSG_QUESTGIVER_REQUEST_ITEMS = 0x6236, // 4.3.4 15595 + CMSG_QUESTGIVER_REQUEST_REWARD = 0x2534, // 4.3.4 15595 + SMSG_QUESTGIVER_OFFER_REWARD = 0x2427, // 4.3.4 15595 + CMSG_QUESTGIVER_CHOOSE_REWARD = 0x2125, // 4.3.4 15595 + SMSG_QUESTGIVER_QUEST_INVALID = 0x4016, // 4.3.4 15595 CMSG_QUESTGIVER_CANCEL = 0x1191, - SMSG_QUESTGIVER_QUEST_COMPLETE = 0x1192, - SMSG_QUESTGIVER_QUEST_FAILED = 0x1193, + SMSG_QUESTGIVER_QUEST_COMPLETE = 0x55A4, // 4.3.4 15595 + SMSG_QUESTGIVER_QUEST_FAILED = 0x4236, // 4.3.4 15595 CMSG_QUESTLOG_SWAP_QUEST = 0x1194, - CMSG_QUESTLOG_REMOVE_QUEST = 0x1195, - SMSG_QUESTLOG_FULL = 0x1196, - SMSG_QUESTUPDATE_FAILED = 0x1197, - SMSG_QUESTUPDATE_FAILEDTIMER = 0x1198, - SMSG_QUESTUPDATE_COMPLETE = 0x1199, - SMSG_QUESTUPDATE_ADD_KILL = 0x119A, + CMSG_QUESTLOG_REMOVE_QUEST = 0x0D16, // 4.3.4 15595 + SMSG_QUESTLOG_FULL = 0x0E36, // 4.3.4 15595 + SMSG_QUESTUPDATE_FAILED = 0x6324, // 4.3.4 15595 + SMSG_QUESTUPDATE_FAILEDTIMER = 0x6427, // 4.3.4 15595 + SMSG_QUESTUPDATE_COMPLETE = 0x2937, // 4.3.4 15595 + SMSG_QUESTUPDATE_ADD_KILL = 0x0D27, // 4.3.4 15595 SMSG_QUESTUPDATE_ADD_ITEM_OBSOLETE = 0x119B, - CMSG_QUEST_CONFIRM_ACCEPT = 0x119C, - SMSG_QUEST_CONFIRM_ACCEPT = 0x119D, - CMSG_PUSHQUESTTOPARTY = 0x119E, + CMSG_QUEST_CONFIRM_ACCEPT = 0x0D15, // 4.3.4 15595 + SMSG_QUEST_CONFIRM_ACCEPT = 0x6F07, // 4.3.4 15595 + CMSG_PUSHQUESTTOPARTY = 0x4B14, // 4.3.4 15595 CMSG_LIST_INVENTORY = 0x2806, // 4.3.4 15595 SMSG_LIST_INVENTORY = 0x7CB0, // 4.3.4 15595 CMSG_SELL_ITEM = 0x4E15, // 4.3.4 15595 @@ -535,8 +535,8 @@ enum Opcodes CMSG_SETSHEATHED = 0x11E1, SMSG_COOLDOWN_CHEAT = 0x11E2, SMSG_SPELL_DELAYED = 0x0715, // 4.3.4 15595 - CMSG_QUEST_POI_QUERY = 0x11E4, - SMSG_QUEST_POI_QUERY_RESPONSE = 0x11E5, + CMSG_QUEST_POI_QUERY = 0x4037, // 4.3.4 15595 + SMSG_QUEST_POI_QUERY_RESPONSE = 0x6304, // 4.3.4 15595 CMSG_GHOST = 0x11E6, CMSG_GM_INVIS = 0x11E7, SMSG_INVALID_PROMOTION_CODE = 0x11E8, @@ -570,7 +570,7 @@ enum Opcodes CMSG_GMTICKET_UPDATETEXT = 0x0636, // 4.3.4 15595 SMSG_GMTICKET_UPDATETEXT = 0x6535, // 4.3.4 15595 SMSG_ACCOUNT_DATA_TIMES = 0x4B05, // 4.3.4 15595 - CMSG_REQUEST_ACCOUNT_DATA = 0x120B, + CMSG_REQUEST_ACCOUNT_DATA = 0x6505, // 4.3.4 15595 CMSG_UPDATE_ACCOUNT_DATA = 0x4736, // 4.3.4 15595 SMSG_UPDATE_ACCOUNT_DATA = 0x6837, // 4.3.4 15595 SMSG_CLEAR_FAR_SIGHT_IMMEDIATE = 0x120E, @@ -581,7 +581,7 @@ enum Opcodes SMSG_GMTICKET_GETTICKET = 0x2C15, // 4.3.4 15595 CMSG_UNLEARN_TALENTS = 0x1214, SMSG_INSTANCE_ENCOUNTER = 0x1215, - SMSG_GAMEOBJECT_DESPAWN_ANIM = 0x1216, + SMSG_GAMEOBJECT_DESPAWN_ANIM = 0x6735, // 4.3.4 15595 MSG_CORPSE_QUERY = 0x4336, // 4.3.4 15595 CMSG_GMTICKET_DELETETICKET = 0x6B14, // 4.3.4 15595 SMSG_GMTICKET_DELETETICKET = 0x6D17, // 4.3.4 15595 @@ -678,7 +678,7 @@ enum Opcodes SMSG_STABLE_RESULT = 0x1274, CMSG_STABLE_REVIVE_PET = 0x1275, CMSG_STABLE_SWAP_PET = 0x1276, - MSG_QUEST_PUSH_RESULT = 0x1277, + MSG_QUEST_PUSH_RESULT = 0x4515, // 4.3.4 15595 SMSG_PLAY_MUSIC = 0x1278, SMSG_PLAY_OBJECT_SOUND = 0x1279, CMSG_REQUEST_PET_INFO = 0x127A, @@ -751,7 +751,7 @@ enum Opcodes SMSG_PLAYER_SKINNED = 0x12BD, SMSG_DURABILITY_DAMAGE_DEATH = 0x12BE, CMSG_SET_EXPLORATION = 0x12BF, - CMSG_SET_ACTIONBAR_TOGGLES = 0x12C0, + CMSG_SET_ACTIONBAR_TOGGLES = 0x2506, // 4.3.4 15595 UMSG_DELETE_GUILD_CHARTER = 0x12C1, MSG_PETITION_RENAME = 0x12C2, SMSG_INIT_WORLD_STATES = 0x4C15, // 4.3.4 15595 @@ -1093,8 +1093,8 @@ enum Opcodes CMSG_TOTEM_DESTROYED = 0x4207, // 4.3.4 15595 CMSG_EXPIRE_RAID_INSTANCE = 0x1416, CMSG_NO_SPELL_VARIANCE = 0x1417, - CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x1418, - SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x1419, + CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x6305, // 4.3.4 15595 + SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x4F25, // 4.3.4 15595 CMSG_SET_PLAYER_DECLINED_NAMES = 0x6316, // 4.3.4 15595 SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x2B25, // 4.3.4 15595 CMSG_QUERY_SERVER_BUCK_DATA = 0x141C, @@ -1181,7 +1181,7 @@ enum Opcodes SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0x15B0, // 4.3.4 15595 CMSG_DISMISS_CONTROLLED_VEHICLE = 0x146E, CMSG_COMPLETE_ACHIEVEMENT_CHEAT = 0x146F, - SMSG_QUESTUPDATE_ADD_PVP_KILL = 0x1470, + SMSG_QUESTUPDATE_ADD_PVP_KILL = 0x4416, // 4.3.4 15595 CMSG_SET_CRITERIA_CHEAT = 0x1471, SMSG_CALENDAR_RAID_LOCKOUT_UPDATED = 0x1472, CMSG_UNITANIMTIER_CHEAT = 0x1473, @@ -1316,8 +1316,8 @@ enum Opcodes CMSG_GM_CREATE_TICKET_RESPONSE = 0x14F4, CMSG_SERVERINFO = 0x14F5, SMSG_SERVERINFO = 0x14F6, - CMSG_UI_TIME_REQUEST = 0x14F7, - SMSG_UI_TIME = 0x14F8, + CMSG_UI_TIME_REQUEST = 0x4605, // 4.3.4 15595 + SMSG_UI_TIME = 0x4A14, // 4.3.4 15595 CMSG_CHAR_RACE_CHANGE = 0x14F9, MSG_VIEW_PHASE_SHIFT = 0x14FA, SMSG_TALENTS_INVOLUNTARILY_RESET = 0x14FB, diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 62ba442ae..30d799295 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -63,24 +63,13 @@ #include "Mail.h" #include "SpellAuras.h" #include "DBCStores.h" +#include "DB2Stores.h" #include "SQLStorages.h" #include #define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS) -#define PLAYER_SKILL_INDEX(x) (PLAYER_SKILL_INFO_1_1 + ((x)*3)) -#define PLAYER_SKILL_VALUE_INDEX(x) (PLAYER_SKILL_INDEX(x)+1) -#define PLAYER_SKILL_BONUS_INDEX(x) (PLAYER_SKILL_INDEX(x)+2) - -#define SKILL_VALUE(x) PAIR32_LOPART(x) -#define SKILL_MAX(x) PAIR32_HIPART(x) -#define MAKE_SKILL_VALUE(v, m) MAKE_PAIR32(v,m) - -#define SKILL_TEMP_BONUS(x) int16(PAIR32_LOPART(x)) -#define SKILL_PERM_BONUS(x) int16(PAIR32_HIPART(x)) -#define MAKE_SKILL_BONUS(t, p) MAKE_PAIR32(t,p) - enum CharacterFlags { CHARACTER_FLAG_NONE = 0x00000000, @@ -275,6 +264,26 @@ std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi) ss << taxi.m_taximask[i] << " "; return ss; } + +SpellModifier::SpellModifier( SpellModOp _op, SpellModType _type, int32 _value, SpellEntry const* spellEntry, SpellEffectIndex eff, int16 _charges /*= 0*/ ) : op(_op), type(_type), charges(_charges), value(_value), spellId(spellEntry->Id), lastAffected(NULL) +{ + mask = spellEntry->GetEffectSpellClassMask(eff); +} + +SpellModifier::SpellModifier( SpellModOp _op, SpellModType _type, int32 _value, Aura const* aura, int16 _charges /*= 0*/ ) : op(_op), type(_type), charges(_charges), value(_value), spellId(aura->GetId()), lastAffected(NULL) +{ + mask = aura->GetAuraSpellClassMask(); +} + +bool SpellModifier::isAffectedOnSpell( SpellEntry const *spell ) const +{ + SpellEntry const *affect_spell = sSpellStore.LookupEntry(spellId); + // False if affect_spell == NULL or spellFamily not equal + if (!affect_spell || affect_spell->GetSpellFamilyName() != spell->GetSpellFamilyName()) + return false; + return spell->IsFitToFamilyMask(mask); +} + //== TradeData ================================================= TradeData* TradeData::GetTraderData() const @@ -426,6 +435,7 @@ Player::Player(WorldSession* session): Unit(), m_mover(this), m_camera(this), m_ memset(m_items, 0, sizeof(Item*)*PLAYER_SLOTS_COUNT); m_social = NULL; + m_guildId = 0; // group is initialized in the reference constructor SetGroupInvite(NULL); @@ -542,6 +552,8 @@ Player::Player(WorldSession* session): Unit(), m_mover(this), m_camera(this), m_ // Honor System m_lastHonorUpdateTime = time(NULL); + m_honorPoints = 0; + m_arenaPoints = 0; // Player summoning m_summon_expire = 0; @@ -559,6 +571,8 @@ Player::Player(WorldSession* session): Unit(), m_mover(this), m_camera(this), m_ m_lastFallZ = 0; m_cachedGS = 0; + + m_slot = 255; } Player::~Player() @@ -682,18 +696,16 @@ bool Player::Create(uint32 guidlow, const std::string& name, uint8 race, uint8 c SetUInt16Value(PLAYER_BYTES_3, 0, gender); // only GENDER_MALE/GENDER_FEMALE (1 bit) allowed, drunk state = 0 SetByteValue(PLAYER_BYTES_3, 3, 0); // BattlefieldArenaFaction (0 or 1) - SetUInt32Value(PLAYER_GUILDID, 0); - SetUInt32Value(PLAYER_GUILDRANK, 0); - SetUInt32Value(PLAYER_GUILD_TIMESTAMP, 0); + SetInGuild( 0 ); + SetUInt32Value( PLAYER_GUILDRANK, 0 ); + SetUInt32Value( PLAYER_GUILD_TIMESTAMP, 0 ); for (int i = 0; i < KNOWN_TITLES_SIZE; ++i) SetUInt64Value(PLAYER__FIELD_KNOWN_TITLES + i, 0); // 0=disabled SetUInt32Value(PLAYER_CHOSEN_TITLE, 0); - SetUInt32Value(PLAYER_FIELD_KILLS, 0); - SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0); - SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); - SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); + SetUInt32Value( PLAYER_FIELD_KILLS, 0 ); + SetUInt32Value( PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0 ); // set starting level uint32 start_level = getClass() != CLASS_DEATH_KNIGHT @@ -841,6 +853,9 @@ bool Player::Create(uint32 guidlow, const std::string& name, uint8 race, uint8 c } // all item positions resolved + if (info->phaseMap != 0) + CharacterDatabase.PExecute("REPLACE INTO `character_phase_data` (`guid`, `map`) VALUES (%u, %u)", guidlow, info->phaseMap); + return true; } @@ -1444,18 +1459,17 @@ void Player::SetDeathState(DeathState s) } } -bool Player::BuildEnumData(QueryResult* result, WorldPacket* p_data) +bool Player::BuildEnumData(QueryResult* result, ByteBuffer* data, ByteBuffer* buffer) { // 0 1 2 3 4 5 6 7 // "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " // 8 9 10 11 12 13 14 // "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " - // 15 16 17 18 19 20 - // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, character_declinedname.genitive " + // 15 16 17 18 19 20 21 + // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, characters.slot, character_declinedname.genitive " Field* fields = result->Fetch(); - - uint32 guid = fields[0].GetUInt32(); + ObjectGuid guid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()); uint8 pRace = fields[2].GetUInt8(); uint8 pClass = fields[3].GetUInt8(); @@ -1466,126 +1480,143 @@ bool Player::BuildEnumData(QueryResult* result, WorldPacket* p_data) return false; } - *p_data << ObjectGuid(HIGHGUID_PLAYER, guid); - *p_data << fields[1].GetString(); // name - *p_data << uint8(pRace); // race - *p_data << uint8(pClass); // class - *p_data << uint8(fields[4].GetUInt8()); // gender - + // FIXME + //ObjectGuid guildGuid = ObjectGuid(HIGHGUID_GUILD, fields[13].GetUInt32()); + ObjectGuid guildGuid = ObjectGuid(uint64(fields[13].GetUInt32())); + std::string name = fields[1].GetCppString(); + uint8 gender = fields[4].GetUInt8(); uint32 playerBytes = fields[5].GetUInt32(); - *p_data << uint8(playerBytes); // skin - *p_data << uint8(playerBytes >> 8); // face - *p_data << uint8(playerBytes >> 16); // hair style - *p_data << uint8(playerBytes >> 24); // hair color - - uint32 playerBytes2 = fields[6].GetUInt32(); - *p_data << uint8(playerBytes2 & 0xFF); // facial hair - - *p_data << uint8(fields[7].GetUInt8()); // level - *p_data << uint32(fields[8].GetUInt32()); // zone - *p_data << uint32(fields[9].GetUInt32()); // map - - *p_data << fields[10].GetFloat(); // x - *p_data << fields[11].GetFloat(); // y - *p_data << fields[12].GetFloat(); // z - - *p_data << uint32(fields[13].GetUInt32()); // guild id - - uint32 char_flags = 0; + uint8 level = fields[7].GetUInt8(); uint32 playerFlags = fields[14].GetUInt32(); uint32 atLoginFlags = fields[15].GetUInt32(); - if (playerFlags & PLAYER_FLAGS_HIDE_HELM) - char_flags |= CHARACTER_FLAG_HIDE_HELM; - if (playerFlags & PLAYER_FLAGS_HIDE_CLOAK) - char_flags |= CHARACTER_FLAG_HIDE_CLOAK; - if (playerFlags & PLAYER_FLAGS_GHOST) - char_flags |= CHARACTER_FLAG_GHOST; - if (atLoginFlags & AT_LOGIN_RENAME) - char_flags |= CHARACTER_FLAG_RENAME; - if (sWorld.getConfig(CONFIG_BOOL_DECLINED_NAMES_USED)) + uint32 zone = fields[8].GetUInt32(); + uint32 petDisplayId = 0; + uint32 petLevel = 0; + uint32 petFamily = 0; + uint32 char_flags = 0; + + data->WriteGuidMask<3>(guid); + data->WriteGuidMask<1, 7, 2>(guildGuid); + data->WriteBits(name.length(), 7); + data->WriteGuidMask<4, 7>(guid); + data->WriteGuidMask<3>(guildGuid); + data->WriteGuidMask<5>(guid); + data->WriteGuidMask<6>(guildGuid); + data->WriteGuidMask<1>(guid); + data->WriteGuidMask<5, 4>(guildGuid); + data->WriteBit(atLoginFlags & AT_LOGIN_FIRST); + data->WriteGuidMask<0, 2, 6>(guid); + data->WriteGuidMask<0>(guildGuid); + + // show pet at selection character in character list only for non-ghost character + if (result && !(playerFlags & PLAYER_FLAGS_GHOST) && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER || pClass == CLASS_DEATH_KNIGHT)) { - if (!fields[20].GetCppString().empty()) + uint32 entry = fields[16].GetUInt32(); + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(entry); + if(cInfo) + { + petDisplayId = fields[17].GetUInt32(); + petLevel = fields[18].GetUInt32(); + petFamily = cInfo->family; + } + } + + if(playerFlags & PLAYER_FLAGS_HIDE_HELM) + char_flags |= CHARACTER_FLAG_HIDE_HELM; + if(playerFlags & PLAYER_FLAGS_HIDE_CLOAK) + char_flags |= CHARACTER_FLAG_HIDE_CLOAK; + if(playerFlags & PLAYER_FLAGS_GHOST) + char_flags |= CHARACTER_FLAG_GHOST; + if(atLoginFlags & AT_LOGIN_RENAME) + char_flags |= CHARACTER_FLAG_RENAME; + if(sWorld.getConfig(CONFIG_BOOL_DECLINED_NAMES_USED)) + { + if(!fields[21].GetCppString().empty()) char_flags |= CHARACTER_FLAG_DECLINED; } else char_flags |= CHARACTER_FLAG_DECLINED; - *p_data << uint32(char_flags); // character flags - // character customize flags - *p_data << uint32(atLoginFlags & AT_LOGIN_CUSTOMIZE ? CHAR_CUSTOMIZE_FLAG_CUSTOMIZE : CHAR_CUSTOMIZE_FLAG_NONE); - // First login - *p_data << uint8(atLoginFlags & AT_LOGIN_FIRST ? 1 : 0); + *buffer << uint8(pClass); // class - // Pets info - { - uint32 petDisplayId = 0; - uint32 petLevel = 0; - uint32 petFamily = 0; - - // show pet at selection character in character list only for non-ghost character - if (result && !(playerFlags & PLAYER_FLAGS_GHOST) && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER || pClass == CLASS_DEATH_KNIGHT)) - { - uint32 entry = fields[16].GetUInt32(); - CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(entry); - if (cInfo) - { - petDisplayId = fields[17].GetUInt32(); - petLevel = fields[18].GetUInt32(); - petFamily = cInfo->family; - } - } - - *p_data << uint32(petDisplayId); - *p_data << uint32(petLevel); - *p_data << uint32(petFamily); - } - - - Tokens data = StrSplit(fields[19].GetCppString(), " "); + Tokens tdata = StrSplit(fields[19].GetCppString(), " "); for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot) { uint32 visualbase = slot * 2; - uint32 item_id = GetUInt32ValueFromArray(data, visualbase); - const ItemPrototype* proto = ObjectMgr::GetItemPrototype(item_id); - if (!proto) + uint32 item_id = GetUInt32ValueFromArray(tdata, visualbase); + const ItemPrototype * proto = ObjectMgr::GetItemPrototype(item_id); + if(!proto) { - *p_data << uint32(0); - *p_data << uint8(0); - *p_data << uint32(0); + *buffer << uint8(0); + *buffer << uint32(0); + *buffer << uint32(0); continue; } - SpellItemEnchantmentEntry const* enchant = NULL; + SpellItemEnchantmentEntry const *enchant = NULL; - uint32 enchants = GetUInt32ValueFromArray(data, visualbase + 1); - for (uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot) + uint32 enchants = GetUInt32ValueFromArray(tdata, visualbase + 1); + for(uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot) { // values stored in 2 uint16 - uint32 enchantId = 0x0000FFFF & (enchants >> enchantSlot * 16); - if (!enchantId) + uint32 enchantId = 0x0000FFFF & (enchants >> enchantSlot*16); + if(!enchantId) continue; if ((enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId))) break; } - *p_data << uint32(proto->DisplayInfoID); - *p_data << uint8(proto->InventoryType); - *p_data << uint32(enchant ? enchant->aura_id : 0); + *buffer << uint8(proto->InventoryType); + *buffer << uint32(proto->DisplayInfoID); + *buffer << uint32(enchant ? enchant->aura_id : 0); } - *p_data << uint32(0); // bag 1 display id - *p_data << uint8(0); // bag 1 inventory type - *p_data << uint32(0); // enchant? - *p_data << uint32(0); // bag 2 display id - *p_data << uint8(0); // bag 2 inventory type - *p_data << uint32(0); // enchant? - *p_data << uint32(0); // bag 3 display id - *p_data << uint8(0); // bag 3 inventory type - *p_data << uint32(0); // enchant? - *p_data << uint32(0); // bag 4 display id - *p_data << uint8(0); // bag 4 inventory type - *p_data << uint32(0); // enchant? + for (int32 i = 0; i < 4; i++) + { + *buffer << uint8(0); + *buffer << uint32(0); + *buffer << uint32(0); + } + + *buffer << uint32(petFamily); // Pet DisplayID + buffer->WriteGuidBytes<2>(guildGuid); + *buffer << uint8(fields[20].GetUInt8()); // char order id + *buffer << uint8((playerBytes >> 16) & 0xFF); // Hair style + buffer->WriteGuidBytes<3>(guildGuid); + *buffer << uint32(petDisplayId); // Pet DisplayID + *buffer << uint32(char_flags); // character flags + *buffer << uint8((playerBytes >> 24) & 0xFF); // Hair color + buffer->WriteGuidBytes<4>(guid); + *buffer << uint32(fields[9].GetUInt32()); // map + buffer->WriteGuidBytes<5>(guildGuid); + *buffer << fields[12].GetFloat(); // z + buffer->WriteGuidBytes<6>(guildGuid); + *buffer << uint32(petLevel); // pet level + buffer->WriteGuidBytes<3>(guid); + *buffer << fields[11].GetFloat(); // y + // character customize flags + *buffer << uint32(atLoginFlags & AT_LOGIN_CUSTOMIZE ? CHAR_CUSTOMIZE_FLAG_CUSTOMIZE : CHAR_CUSTOMIZE_FLAG_NONE); + + uint32 playerBytes2 = fields[6].GetUInt32(); + *buffer << uint8(playerBytes2 & 0xFF); // facial hair + buffer->WriteGuidBytes<7>(guid); + *buffer << uint8(gender); // Gender + buffer->append(name.c_str(), name.length()); + *buffer << uint8((playerBytes >> 8) & 0xFF); // face + + buffer->WriteGuidBytes<0, 2>(guid); + buffer->WriteGuidBytes<1, 7>(guildGuid); + + *buffer << fields[10].GetFloat(); // x + *buffer << uint8(playerBytes & 0xFF); // skin + *buffer << uint8(pRace); // Race + *buffer << uint8(level); // Level + buffer->WriteGuidBytes<6>(guid); + buffer->WriteGuidBytes<4, 0>(guildGuid); + buffer->WriteGuidBytes<5, 1>(guid); + + *buffer << uint32(zone); // Zone id return true; } @@ -1622,8 +1653,42 @@ uint8 Player::GetChatTag() const return tag; } +void Player::SendTeleportPacket(float oldX, float oldY, float oldZ, float oldO) +{ + ObjectGuid guid = GetObjectGuid(); + ObjectGuid transportGuid = m_movementInfo.GetTransportGuid(); + + WorldPacket data(SMSG_MOVE_TELEPORT, 38); + data.WriteGuidMask<6, 0, 3, 2>(guid); + data.WriteBit(0); // unknown + data.WriteBit(!transportGuid.IsEmpty()); + data.WriteGuidMask<1>(guid); + if (transportGuid) + data.WriteGuidMask<1, 3, 2, 5, 0, 7, 6, 4>(transportGuid); + + data.WriteGuidMask<4, 7, 5>(guid); + + if (transportGuid) + data.WriteGuidBytes<5, 6, 1, 7, 0, 2, 4, 3>(transportGuid); + + data << uint32(0); // counter + data.WriteGuidBytes<1, 2, 3, 5>(guid); + data << float(GetPositionX()); + data.WriteGuidBytes<4>(guid); + data << float(GetOrientation()); + data.WriteGuidBytes<7>(guid); + data << float(GetPositionZ()); + data.WriteGuidBytes<0, 6>(guid); + data << float(GetPositionY()); + + Relocate(oldX, oldY, oldZ, oldO); + SendDirectMessage(&data); +} + bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options) { + orientation = NormalizeOrientation(orientation); + if (!MapManager::IsValidMapCoord(mapid, x, y, z, orientation)) { sLog.outError("TeleportTo: invalid map %d or absent instance template.", mapid); @@ -1710,14 +1775,16 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati SetFallInformation(0, z); // code for finish transfer called in WorldSession::HandleMovementOpcodes() - // at client packet MSG_MOVE_TELEPORT_ACK + // at client packet CMSG_MOVE_TELEPORT_ACK SetSemaphoreTeleportNear(true); - // near teleport, triggering send MSG_MOVE_TELEPORT_ACK from client at landing + // near teleport, triggering send CMSG_MOVE_TELEPORT_ACK from client at landing if (!GetSession()->PlayerLogout()) { - WorldPacket data; - BuildTeleportAckMsg(data, x, y, z, orientation); - GetSession()->SendPacket(&data); + float oldX, oldY, oldZ; + float oldO = GetOrientation(); + GetPosition(oldX, oldY, oldZ);; + Relocate(x, y, z, orientation); + SendTeleportPacket(oldX, oldY, oldZ, oldO); } } else @@ -1787,12 +1854,17 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati { // send transfer packet to display load screen WorldPacket data(SMSG_TRANSFER_PENDING, (4 + 4 + 4)); - data << uint32(mapid); + data.WriteBit(0); // unknown if (m_transport) { - data << uint32(m_transport->GetEntry()); + data.WriteBit(1); // has transport data << uint32(GetMapId()); + data << uint32(m_transport->GetEntry()); } + else + data.WriteBit(0); // has transport + + data << uint32(mapid); GetSession()->SendPacket(&data); } @@ -1826,23 +1898,27 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if (!GetSession()->PlayerLogout()) { // transfer finished, inform client to start load - WorldPacket data(SMSG_NEW_WORLD, (20)); - data << uint32(mapid); + WorldPacket data(SMSG_NEW_WORLD, 20); if (m_transport) { data << float(m_movementInfo.GetTransportPos()->x); - data << float(m_movementInfo.GetTransportPos()->y); - data << float(m_movementInfo.GetTransportPos()->z); data << float(m_movementInfo.GetTransportPos()->o); + data << float(m_movementInfo.GetTransportPos()->z); } else { data << float(final_x); - data << float(final_y); - data << float(final_z); data << float(final_o); + data << float(final_z); } + data << uint32(mapid); + + if (m_transport) + data << float(m_movementInfo.GetTransportPos()->y); + else + data << float(final_y); + GetSession()->SendPacket(&data); SendSavedInstances(); } @@ -2000,14 +2076,24 @@ void Player::RegenerateAll(uint32 diff) if (getClass() == CLASS_DEATH_KNIGHT) Regenerate(POWER_RUNE, diff); + if (getClass() == CLASS_HUNTER) + Regenerate(POWER_FOCUS, diff); + m_regenTimer = REGEN_TIME_FULL; } // diff contains the time in milliseconds since last regen. void Player::Regenerate(Powers power, uint32 diff) { - uint32 curValue = GetPower(power); - uint32 maxValue = GetMaxPower(power); + uint32 powerIndex = GetPowerIndex(power); + if (powerIndex == INVALID_POWER_INDEX) + return; + + uint32 maxValue = GetMaxPowerByIndex(powerIndex); + if (!maxValue) + return; + + uint32 curValue = GetPowerByIndex(powerIndex); float addvalue = 0.0f; @@ -2034,6 +2120,9 @@ void Player::Regenerate(Powers power, uint32 diff) float RageDecreaseRate = sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_RAGE_LOSS); addvalue = 20 * RageDecreaseRate; // 2 rage by tick (= 2 seconds => 1 rage/sec) } break; + case POWER_FOCUS: + addvalue = 12; + break; case POWER_ENERGY: // Regenerate energy (rogue) { float EnergyRate = sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_ENERGY); @@ -2064,8 +2153,6 @@ void Player::Regenerate(Powers power, uint32 diff) } } } break; - case POWER_FOCUS: - case POWER_HAPPINESS: case POWER_HEALTH: break; } @@ -2474,17 +2561,15 @@ void Player::GiveLevel(uint32 level) PlayerLevelInfo info; sObjectMgr.GetPlayerLevelInfo(getRace(), getClass(), level, &info); - PlayerClassLevelInfo classInfo; - sObjectMgr.GetPlayerClassLevelInfo(getClass(), level, &classInfo); + uint32 basehp = 0, basemana = 0; + sObjectMgr.GetPlayerClassLevelInfo(getClass(), level, basehp, basemana); // send levelup info to client - WorldPacket data(SMSG_LEVELUP_INFO, (4 + 4 + MAX_POWERS * 4 + MAX_STATS * 4)); + WorldPacket data(SMSG_LEVELUP_INFO, (4 + 4 + MAX_STORED_POWERS * 4 + MAX_STATS * 4)); data << uint32(level); - data << uint32(int32(classInfo.basehealth) - int32(GetCreateHealth())); - // for(int i = 0; i < MAX_POWERS; ++i) // Powers loop (0-6) - data << uint32(int32(classInfo.basemana) - int32(GetCreateMana())); - data << uint32(0); - data << uint32(0); + data << uint32(int32(basehp) - int32(GetCreateHealth())); + // for(int i = 0; i < MAX_POWERS; ++i) // Powers loop (0-4) + data << uint32(int32(basemana) - int32(GetCreateMana())); data << uint32(0); data << uint32(0); data << uint32(0); @@ -2510,8 +2595,8 @@ void Player::GiveLevel(uint32 level) for (int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetCreateStat(Stats(i), info.stats[i]); - SetCreateHealth(classInfo.basehealth); - SetCreateMana(classInfo.basemana); + SetCreateHealth(basehp); + SetCreateMana(basemana); InitTalentForLevel(); InitTaxiNodesForLevel(); @@ -2527,7 +2612,6 @@ void Player::GiveLevel(uint32 level) if (GetPower(POWER_RAGE) > GetMaxPower(POWER_RAGE)) SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE)); SetPower(POWER_FOCUS, 0); - SetPower(POWER_HAPPINESS, 0); _ApplyAllLevelScaleItemMods(true); @@ -2586,8 +2670,8 @@ void Player::InitStatsForLevel(bool reapplyMods) if (reapplyMods) // reapply stats values only on .reset stats (level) command _RemoveAllStatBonuses(); - PlayerClassLevelInfo classInfo; - sObjectMgr.GetPlayerClassLevelInfo(getClass(), getLevel(), &classInfo); + uint32 basehp = 0, basemana = 0; + sObjectMgr.GetPlayerClassLevelInfo(getClass(), getLevel(), basehp, basemana); PlayerLevelInfo info; sObjectMgr.GetPlayerLevelInfo(getRace(), getClass(), getLevel(), &info); @@ -2610,10 +2694,10 @@ void Player::InitStatsForLevel(bool reapplyMods) for (int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetStat(Stats(i), info.stats[i]); - SetCreateHealth(classInfo.basehealth); + SetCreateHealth(basehp); // set create powers - SetCreateMana(classInfo.basemana); + SetCreateMana(basemana); SetArmor(int32(m_createStats[STAT_AGILITY] * 2)); @@ -2643,12 +2727,14 @@ void Player::InitStatsForLevel(bool reapplyMods) SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, 0.0f); SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, 0.0f); - SetInt32Value(UNIT_FIELD_ATTACK_POWER, 0); - SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, 0); - SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, 0.0f); - SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER, 0); - SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MODS, 0); - SetFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER, 0.0f); + SetInt32Value(UNIT_FIELD_ATTACK_POWER, 0 ); + SetInt32Value(UNIT_FIELD_ATTACK_POWER_MOD_POS, 0 ); + SetInt32Value(UNIT_FIELD_ATTACK_POWER_MOD_NEG, 0 ); + SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER,0.0f); + SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER, 0 ); + SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS,0 ); + SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MOD_NEG,0 ); + SetFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER,0.0f); // Base crit values (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset SetFloatValue(PLAYER_CRIT_PERCENTAGE, 0.0f); @@ -2693,9 +2779,9 @@ void Player::InitStatsForLevel(bool reapplyMods) // save new stats for (int i = POWER_MANA; i < MAX_POWERS; ++i) - SetMaxPower(Powers(i), GetCreatePowers(Powers(i))); + SetMaxPower(Powers(i), GetCreatePowers(Powers(i))); - SetMaxHealth(classInfo.basehealth); // stamina bonus will applied later + SetMaxHealth(basehp); // stamina bonus will applied later // cleanup mounted state (it will set correctly at aura loading if player saved at mount. SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0); @@ -2731,7 +2817,6 @@ void Player::InitStatsForLevel(bool reapplyMods) if (GetPower(POWER_RAGE) > GetMaxPower(POWER_RAGE)) SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE)); SetPower(POWER_FOCUS, 0); - SetPower(POWER_HAPPINESS, 0); SetPower(POWER_RUNIC_POWER, 0); // update level to hunter/summon pet @@ -2779,7 +2864,7 @@ void Player::SendInitialSpells() data << uint32(itr->first); data << uint16(itr->second.itemid); // cast item id - data << uint16(sEntry->Category); // spell category + data << uint16(sEntry->GetCategory()); // spell category // send infinity cooldown in special format if (itr->second.end >= infTime) @@ -2791,7 +2876,7 @@ void Player::SendInitialSpells() time_t cooldown = itr->second.end > curTime ? (itr->second.end - curTime) * IN_MILLISECONDS : 0; - if (sEntry->Category) // may be wrong, but anyway better than nothing... + if(sEntry->GetCategory()) // may be wrong, but anyway better than nothing... { data << uint32(0); // cooldown data << uint32(cooldown); // category cooldown @@ -3208,13 +3293,13 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen switch (GetSkillRangeType(pSkill, _spell_idx->second->racemask != 0)) { case SKILL_RANGE_LANGUAGE: - SetSkill(pSkill->id, 300, 300); + SetSkill(pSkill->id, 300, 300, GetSkillStep(pSkill->id)); break; case SKILL_RANGE_LEVEL: - SetSkill(pSkill->id, 1, GetMaxSkillValueForLevel()); + SetSkill(pSkill->id, 1, GetMaxSkillValueForLevel(), GetSkillStep(pSkill->id)); break; case SKILL_RANGE_MONO: - SetSkill(pSkill->id, 1, 1); + SetSkill(pSkill->id, 1, 1, GetSkillStep(pSkill->id)); break; default: break; @@ -3265,10 +3350,12 @@ bool Player::IsNeedCastPassiveLikeSpellAtLearn(SpellEntry const* spellInfo) cons // note: form passives activated with shapeshift spells be implemented by HandleShapeshiftBoosts instead of spell_learn_spell // talent dependent passives activated at form apply have proper stance data - bool need_cast = !spellInfo->Stances || (!form && spellInfo->HasAttribute(SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT)); + SpellShapeshiftEntry const* shapeShift = spellInfo->GetSpellShapeshift(); + bool need_cast = (!shapeShift || !shapeShift->Stances || (!form && spellInfo->HasAttribute(SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT))); // Check CasterAuraStates - return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState))); + SpellAuraRestrictionsEntry const* auraRestrictions = spellInfo->GetSpellAuraRestrictions(); + return need_cast && (auraRestrictions && (!auraRestrictions->CasterAuraState || HasAuraState(AuraState(auraRestrictions->CasterAuraState)))); } void Player::learnSpell(uint32 spell_id, bool dependent) @@ -3285,7 +3372,7 @@ void Player::learnSpell(uint32 spell_id, bool dependent) { WorldPacket data(SMSG_LEARNED_SPELL, 6); data << uint32(spell_id); - data << uint16(0); // 3.3.3 unk + data << uint32(0); // 3.3.3 unk GetSession()->SendPacket(&data); } @@ -3439,7 +3526,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank, bo (IsProfessionSkill(pSkill->id) || _spell_idx->second->racemask != 0)) continue; - SetSkill(pSkill->id, 0, 0); + SetSkill(pSkill->id, 0, 0, GetSkillStep(pSkill->id)); } } } @@ -3558,9 +3645,9 @@ void Player::RemoveArenaSpellCooldowns() ++next; SpellEntry const* entry = sSpellStore.LookupEntry(itr->first); // check if spellentry is present and if the cooldown is less than 15 mins - if (entry && - entry->RecoveryTime <= 15 * MINUTE * IN_MILLISECONDS && - entry->CategoryRecoveryTime <= 15 * MINUTE * IN_MILLISECONDS) + if( entry && + entry->GetRecoveryTime() <= 15 * MINUTE * IN_MILLISECONDS && + entry->GetCategoryRecoveryTime() <= 15 * MINUTE * IN_MILLISECONDS ) { // remove & notify RemoveSpellCooldown(itr->first, true); @@ -3572,8 +3659,21 @@ void Player::RemoveAllSpellCooldown() { if (!m_spellCooldowns.empty()) { + ObjectGuid guid = GetObjectGuid(); + + WorldPacket data(SMSG_CLEAR_COOLDOWNS, 1 + 8 + m_spellCooldowns.size() * 4); + data.WriteGuidMask<1, 3, 6>(guid); + data.WriteBits(m_spellCooldowns.size(), 24); // cooldown count + data.WriteGuidMask<7, 5, 2, 4, 0>(guid); + + data.WriteGuidBytes<7, 2, 4, 5, 1, 3>(guid); + for (SpellCooldowns::const_iterator itr = m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); ++itr) - SendClearCooldown(itr->first, this); + data << uint32(itr->first); + + data.WriteGuidBytes<0, 6>(guid); + + SendDirectMessage(&data); m_spellCooldowns.clear(); } @@ -3840,6 +3940,8 @@ void Player::InitVisibleBits() updateVisualBits.SetBit(OBJECT_FIELD_GUID); updateVisualBits.SetBit(OBJECT_FIELD_TYPE); updateVisualBits.SetBit(OBJECT_FIELD_ENTRY); + updateVisualBits.SetBit(OBJECT_FIELD_DATA + 0); + updateVisualBits.SetBit(OBJECT_FIELD_DATA + 1); updateVisualBits.SetBit(OBJECT_FIELD_SCALE_X); updateVisualBits.SetBit(UNIT_FIELD_CHARM + 0); updateVisualBits.SetBit(UNIT_FIELD_CHARM + 1); @@ -3858,16 +3960,12 @@ void Player::InitVisibleBits() updateVisualBits.SetBit(UNIT_FIELD_POWER3); updateVisualBits.SetBit(UNIT_FIELD_POWER4); updateVisualBits.SetBit(UNIT_FIELD_POWER5); - updateVisualBits.SetBit(UNIT_FIELD_POWER6); - updateVisualBits.SetBit(UNIT_FIELD_POWER7); updateVisualBits.SetBit(UNIT_FIELD_MAXHEALTH); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER1); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER2); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER3); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER4); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER5); - updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER6); - updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER7); updateVisualBits.SetBit(UNIT_FIELD_LEVEL); updateVisualBits.SetBit(UNIT_FIELD_FACTIONTEMPLATE); updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_ID + 0); @@ -3896,13 +3994,15 @@ void Player::InitVisibleBits() updateVisualBits.SetBit(PLAYER_DUEL_ARBITER + 0); updateVisualBits.SetBit(PLAYER_DUEL_ARBITER + 1); updateVisualBits.SetBit(PLAYER_FLAGS); - updateVisualBits.SetBit(PLAYER_GUILDID); + //updateVisualBits.SetBit(PLAYER_GUILDID); updateVisualBits.SetBit(PLAYER_GUILDRANK); + updateVisualBits.SetBit(PLAYER_GUILDLEVEL); updateVisualBits.SetBit(PLAYER_BYTES); updateVisualBits.SetBit(PLAYER_BYTES_2); updateVisualBits.SetBit(PLAYER_BYTES_3); updateVisualBits.SetBit(PLAYER_DUEL_TEAM); updateVisualBits.SetBit(PLAYER_GUILD_TIMESTAMP); + updateVisualBits.SetBit(UNIT_NPC_FLAGS); // PLAYER_QUEST_LOG_x also visible bit on official (but only on party/raid)... for (uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i += MAX_QUEST_OFFSET) @@ -3949,9 +4049,27 @@ void Player::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c } } + SetPhaseAndMap(target); Unit::BuildCreateUpdateBlockForPlayer(data, target); } +void Player::SetPhaseAndMap(Player* target) const +{ + QueryResult *result = CharacterDatabase.PQuery("SELECT map, phase FROM character_phase_data WHERE guid = '%u'", target->GetGUIDLow()); + + if (result) + { + Field *fields = result->Fetch(); + + uint16 mapId = fields[0].GetUInt16(); + uint32 phase = fields[1].GetUInt32(); + + target->GetSession()->SendSetPhaseShift(phase, mapId); + + delete result; + } +} + void Player::DestroyForPlayer(Player* target, bool anim) const { Unit::DestroyForPlayer(target, anim); @@ -4040,9 +4158,10 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->learnedSpell); // secondary prof. or not prof. spell - uint32 skill = spell->EffectMiscValue[1]; + SpellEffectEntry const* spellEffect = spell->GetSpellEffect(EFFECT_INDEX_1); + uint32 skill = spellEffect ? spellEffect->EffectMiscValue : 0; - if (spell->Effect[1] != SPELL_EFFECT_SKILL || !IsPrimaryProfessionSkill(skill)) + if(spellEffect && (spellEffect->Effect != SPELL_EFFECT_SKILL || !IsPrimaryProfessionSkill(skill))) return TRAINER_SPELL_GREEN; // check primary prof. limit @@ -4328,19 +4447,28 @@ void Player::DeleteOldCharacters(uint32 keepDays) } } -void Player::SetRoot(bool enable) +void Player::SetMovement(PlayerMovementType pType) { - WorldPacket data(enable ? SMSG_FORCE_MOVE_ROOT : SMSG_FORCE_MOVE_UNROOT, GetPackGUID().size() + 4); - data << GetPackGUID(); - data << uint32(0); - GetSession()->SendPacket(&data); -} + WorldPacket data; + switch (pType) + { + case MOVE_ROOT: + case MOVE_UNROOT: + { + BuildForceMoveRootPacket(&data, pType == MOVE_ROOT, 0); + break; + } + case MOVE_WATER_WALK: + case MOVE_LAND_WALK: + { + BuildMoveWaterWalkPacket(&data, pType == MOVE_WATER_WALK, 0); + break; + } + default: + sLog.outError("Player::SetMovement: Unsupported move type (%d), data not sent to client.", pType); + return; + } -void Player::SetWaterWalk(bool enable) -{ - WorldPacket data(enable ? SMSG_MOVE_WATER_WALK : SMSG_MOVE_LAND_WALK, GetPackGUID().size() + 4); - data << GetPackGUID(); - data << uint32(0); GetSession()->SendPacket(&data); } @@ -4381,9 +4509,9 @@ void Player::BuildPlayerRepop() // convert player body to ghost SetHealth(1); - SetWaterWalk(true); + SetMovement(MOVE_WATER_WALK); if (!GetSession()->isLogingOut()) - SetRoot(false); + SetMovement(MOVE_UNROOT); // BG - remove insignia related RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); @@ -4419,8 +4547,8 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) RemoveAurasDueToSpell(20584); // speed bonuses RemoveAurasDueToSpell(8326); // SPELL_AURA_GHOST - SetWaterWalk(false); - SetRoot(false); + SetMovement(MOVE_LAND_WALK); + SetMovement(MOVE_UNROOT); m_deathTimer = 0; @@ -4473,7 +4601,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) void Player::KillPlayer() { - SetRoot(true); + SetMovement(MOVE_ROOT); StopMirrorTimers(); // disable timers(bars) @@ -4534,8 +4662,6 @@ Corpse* Player::CreateCorpse() corpse->SetUInt32Value(CORPSE_FIELD_DISPLAY_ID, GetNativeDisplayId()); - corpse->SetUInt32Value(CORPSE_FIELD_GUILD, GetGuildId()); - uint32 iDisplayID; uint32 iIventoryType; uint32 _cfi; @@ -5118,23 +5244,23 @@ float Player::GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const float Player::OCTRegenHPPerSpirit() { - uint32 level = getLevel(); - uint32 pclass = getClass(); + //uint32 level = getLevel(); + //uint32 pclass = getClass(); - if (level > GT_MAX_LEVEL) level = GT_MAX_LEVEL; + //if (level>GT_MAX_LEVEL) level = GT_MAX_LEVEL; - GtOCTRegenHPEntry const* baseRatio = sGtOCTRegenHPStore.LookupEntry((pclass - 1) * GT_MAX_LEVEL + level - 1); - GtRegenHPPerSptEntry const* moreRatio = sGtRegenHPPerSptStore.LookupEntry((pclass - 1) * GT_MAX_LEVEL + level - 1); - if (baseRatio == NULL || moreRatio == NULL) + //GtOCTRegenHPEntry const *baseRatio = sGtOCTRegenHPStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1); + //GtRegenHPPerSptEntry const *moreRatio = sGtRegenHPPerSptStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1); + //if (baseRatio==NULL || moreRatio==NULL) return 0.0f; // Formula from PaperDollFrame script - float spirit = GetStat(STAT_SPIRIT); - float baseSpirit = spirit; - if (baseSpirit > 50) baseSpirit = 50; - float moreSpirit = spirit - baseSpirit; - float regen = baseSpirit * baseRatio->ratio + moreSpirit * moreRatio->ratio; - return regen; + //float spirit = GetStat(STAT_SPIRIT); + //float baseSpirit = spirit; + //if (baseSpirit>50) baseSpirit = 50; + //float moreSpirit = spirit - baseSpirit; + //float regen = baseSpirit * baseRatio->ratio + moreSpirit * moreRatio->ratio; + //return regen; } float Player::OCTRegenMPPerSpirit() @@ -5242,24 +5368,12 @@ void Player::UpdateRating(CombatRating cr) if (affectStats) UpdateAllSpellCritChances(); break; - case CR_HIT_TAKEN_MELEE: // Implemented in Unit::MeleeMissChanceCalc - case CR_HIT_TAKEN_RANGED: - break; - case CR_HIT_TAKEN_SPELL: // Implemented in Unit::MagicSpellHitResult - break; - case CR_CRIT_TAKEN_MELEE: // Implemented in Unit::RollMeleeOutcomeAgainst (only for chance to crit) - case CR_CRIT_TAKEN_RANGED: - break; - case CR_CRIT_TAKEN_SPELL: // Implemented in Unit::SpellCriticalBonus (only for chance to crit) + case CR_RESILIENCE_DAMAGE_TAKEN: break; case CR_HASTE_MELEE: // Implemented in Player::ApplyRatingMod case CR_HASTE_RANGED: case CR_HASTE_SPELL: break; - case CR_WEAPON_SKILL_MAINHAND: // Implemented in Unit::RollMeleeOutcomeAgainst - case CR_WEAPON_SKILL_OFFHAND: - case CR_WEAPON_SKILL_RANGED: - break; case CR_EXPERTISE: if (affectStats) { @@ -5271,6 +5385,16 @@ void Player::UpdateRating(CombatRating cr) if (affectStats) UpdateArmorPenetration(); break; + // deprecated + case CR_HIT_TAKEN_MELEE: + case CR_HIT_TAKEN_RANGED: + case CR_HIT_TAKEN_SPELL: + case CR_CRIT_TAKEN_SPELL: + case CR_CRIT_TAKEN_MELEE: + case CR_WEAPON_SKILL_MAINHAND: + case CR_WEAPON_SKILL_OFFHAND: + case CR_WEAPON_SKILL_RANGED: + break; } } @@ -5302,14 +5426,18 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) if (!skill_id) return false; + if (skill_id == SKILL_FIST_WEAPONS) + skill_id = SKILL_UNARMED; + SkillStatusMap::iterator itr = mSkillStatus.find(skill_id); if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return false; - uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); - uint32 data = GetUInt32Value(valueIndex); - uint32 value = SKILL_VALUE(data); - uint32 max = SKILL_MAX(data); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 + + uint16 value = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); + uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); if ((!max) || (!value) || (value >= max)) return false; @@ -5320,7 +5448,7 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) if (new_value > max) new_value = max; - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, max)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, new_value); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id); @@ -5355,7 +5483,7 @@ bool Player::UpdateCraftSkill(uint32 spellid) // Alchemy Discoveries here SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellid); - if (spellEntry && spellEntry->Mechanic == MECHANIC_DISCOVERY) + if (spellEntry && spellEntry->GetMechanic() == MECHANIC_DISCOVERY) { if (uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->skillId, spellid, this)) learnSpell(discoveredSpell, false); @@ -5435,11 +5563,11 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return false; - uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 - uint32 data = GetUInt32Value(valueIndex); - uint16 SkillValue = SKILL_VALUE(data); - uint16 MaxValue = SKILL_MAX(data); + uint16 SkillValue = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); + uint16 MaxValue = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); if (!MaxValue || !SkillValue || SkillValue >= MaxValue) return false; @@ -5448,16 +5576,16 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) if (Roll <= Chance) { - uint32 new_value = SkillValue + step; + uint16 new_value = SkillValue + step; if (new_value > MaxValue) new_value = MaxValue; - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, MaxValue)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, new_value); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; for (uint32* bsl = &bonusSkillLevels[0]; *bsl; ++bsl) { - if ((SkillValue < *bsl && new_value >= *bsl)) + if (SkillValue < *bsl && new_value >= *bsl) { learnSkillRewardedSpells(SkillId, new_value); break; @@ -5541,16 +5669,12 @@ void Player::ModifySkillBonus(uint32 skillid, int32 val, bool talent) if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return; - uint32 bonusIndex = PLAYER_SKILL_BONUS_INDEX(itr->second.pos); + uint16 field = itr->second.pos / 2 + (talent ? PLAYER_SKILL_TALENT_0 : PLAYER_SKILL_MODIFIER_0); + uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 - uint32 bonus_val = GetUInt32Value(bonusIndex); - int16 temp_bonus = SKILL_TEMP_BONUS(bonus_val); - int16 perm_bonus = SKILL_PERM_BONUS(bonus_val); + uint16 bonus = GetUInt16Value(field, offset); - if (talent) // permanent bonus stored in high part - SetUInt32Value(bonusIndex, MAKE_SKILL_BONUS(temp_bonus, perm_bonus + val)); - else // temporary/item bonus stored in low part - SetUInt32Value(bonusIndex, MAKE_SKILL_BONUS(temp_bonus + val, perm_bonus)); + SetUInt16Value(field, offset, bonus + val); } void Player::UpdateSkillsForLevel() @@ -5574,10 +5698,11 @@ void Player::UpdateSkillsForLevel() if (GetSkillRangeType(pSkill, false) != SKILL_RANGE_LEVEL) continue; - uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); - uint32 data = GetUInt32Value(valueIndex); - uint32 max = SKILL_MAX(data); - uint32 val = SKILL_VALUE(data); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 + + uint16 val = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); + uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); /// update only level dependent max skill values if (max != 1) @@ -5585,14 +5710,16 @@ void Player::UpdateSkillsForLevel() /// maximize skill always if (alwaysMaxSkill) { - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(maxSkill, maxSkill)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, maxSkill); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxSkill); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, pskill); } else if (max != maxconfskill) /// update max skill value if current max skill not maximized { - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(val, maxSkill)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, val); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxSkill); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; } @@ -5610,14 +5737,14 @@ void Player::UpdateSkillsToMaxSkillsForLevel() uint32 pskill = itr->first; if (IsProfessionOrRidingSkill(pskill)) continue; - uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); - uint32 data = GetUInt32Value(valueIndex); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 - uint32 max = SKILL_MAX(data); + uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); if (max > 1) { - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(max, max)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, max); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, pskill); @@ -5635,29 +5762,36 @@ void Player::SetSkill(uint16 id, uint16 currVal, uint16 maxVal, uint16 step /*=0 if (!id) return; + uint16 oldVal; SkillStatusMap::iterator itr = mSkillStatus.find(id); // has skill if (itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED) { + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 + oldVal = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); if (currVal) { - if (step) // need update step - SetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos), MAKE_PAIR32(id, step)); + SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step); // update value - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos), MAKE_SKILL_VALUE(currVal, maxVal)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, currVal); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxVal); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; - learnSkillRewardedSpells(id, currVal); + learnSkillRewardedSpells(id, oldVal); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id); } else // remove { // clear skill fields - SetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos), 0); - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos), 0); - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos), 0); + SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0); // mark as deleted or simply remove from map if not saved yet if (itr->second.uState != SKILL_NEW) @@ -5676,7 +5810,10 @@ void Player::SetSkill(uint16 id, uint16 currVal, uint16 maxVal, uint16 step /*=0 { for (int i = 0; i < PLAYER_MAX_SKILLS; ++i) { - if (!GetUInt32Value(PLAYER_SKILL_INDEX(i))) + uint16 field = i / 2; + uint8 offset = i & 1; // i % 2 + + if (!GetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset)) { SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(id); if (!pSkill) @@ -5685,8 +5822,10 @@ void Player::SetSkill(uint16 id, uint16 currVal, uint16 maxVal, uint16 step /*=0 return; } - SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id, step)); - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i), MAKE_SKILL_VALUE(currVal, maxVal)); + SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, id); + SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, currVal); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxVal); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id); @@ -5700,7 +5839,8 @@ void Player::SetSkill(uint16 id, uint16 currVal, uint16 maxVal, uint16 step /*=0 mSkillStatus.insert(SkillStatusMap::value_type(id, SkillStatusData(i, SKILL_NEW))); // apply skill bonuses - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i), 0); + SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0); // temporary bonuses AuraList const& mModSkill = GetAurasByType(SPELL_AURA_MOD_SKILL); @@ -5731,6 +5871,18 @@ bool Player::HasSkill(uint32 skill) const return (itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED); } +uint16 Player::GetSkillStep(uint16 skill) const +{ + if (!skill) + return 0; + + SkillStatusMap::const_iterator itr = mSkillStatus.find(skill); + if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) + return 0; + + return GetUInt16Value(PLAYER_SKILL_STEP_0 + itr->second.pos / 2, itr->second.pos & 1); +} + uint16 Player::GetSkillValue(uint32 skill) const { if (!skill) @@ -5740,11 +5892,12 @@ uint16 Player::GetSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; - int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); - result += SKILL_TEMP_BONUS(bonus); - result += SKILL_PERM_BONUS(bonus); + int32 result = int32(GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset)); + result += int32(GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset)); + result += int32(GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset)); return result < 0 ? 0 : result; } @@ -5757,11 +5910,12 @@ uint16 Player::GetMaxSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; - int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); - result += SKILL_TEMP_BONUS(bonus); - result += SKILL_PERM_BONUS(bonus); + int32 result = int32(GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset)); + result += int32(GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset)); + result += int32(GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset)); return result < 0 ? 0 : result; } @@ -5774,7 +5928,10 @@ uint16 Player::GetPureMaxSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; + + return GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); } uint16 Player::GetBaseSkillValue(uint32 skill) const @@ -5786,8 +5943,11 @@ uint16 Player::GetBaseSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); - result += SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos))); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; + + int32 result = int32(GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset)); + result += int32(GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset)); return result < 0 ? 0 : result; } @@ -5800,7 +5960,10 @@ uint16 Player::GetPureSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; + + return GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); } int16 Player::GetSkillPermBonusValue(uint32 skill) const @@ -5812,7 +5975,10 @@ int16 Player::GetSkillPermBonusValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos))); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; + + return GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset); } int16 Player::GetSkillTempBonusValue(uint32 skill) const @@ -5824,7 +5990,10 @@ int16 Player::GetSkillTempBonusValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - return SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos))); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; + + return GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset); } void Player::SendInitialActionButtons() const @@ -5832,7 +6001,6 @@ void Player::SendInitialActionButtons() const DETAIL_LOG("Initializing Action Buttons for '%u' spec '%u'", GetGUIDLow(), m_activeSpec); WorldPacket data(SMSG_ACTION_BUTTONS, 1 + (MAX_ACTION_BUTTONS * 4)); - data << uint8(1); // talent spec amount (in packet) ActionButtonList const& currentActionButtonList = m_actionButtons[m_activeSpec]; for (uint8 button = 0; button < MAX_ACTION_BUTTONS; ++button) { @@ -5842,7 +6010,7 @@ void Player::SendInitialActionButtons() const else data << uint32(0); } - + data << uint8(1); // talent spec amount (in packet) GetSession()->SendPacket(&data); DETAIL_LOG("Action Buttons for '%u' spec '%u' Initialized", GetGUIDLow(), m_activeSpec); } @@ -6397,16 +6565,14 @@ void Player::UpdateHonorFields() // update yesterday's contribution if (m_lastHonorUpdateTime >= yesterday) { - SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); + //SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); // this is the first update today, reset today's contribution - SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); - SetUInt32Value(PLAYER_FIELD_KILLS, MAKE_PAIR32(0, kills_today)); + SetUInt32Value(PLAYER_FIELD_KILLS, MAKE_PAIR32(0,kills_today)); } else { // no honor/kills yesterday or today, reset - SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); SetUInt32Value(PLAYER_FIELD_KILLS, 0); } } @@ -6540,7 +6706,7 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, float honor) // add honor points ModifyHonorPoints(int32(honor)); - ApplyModUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, uint32(honor), true); + // FIXME 4x ApplyModUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, uint32(honor), true); return true; } @@ -6549,7 +6715,9 @@ void Player::SetHonorPoints(uint32 value) if (value > sWorld.getConfig(CONFIG_UINT32_MAX_HONOR_POINTS)) value = sWorld.getConfig(CONFIG_UINT32_MAX_HONOR_POINTS); - SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, value); + // FIXME 4x SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, value); + // must be recalculated to new honor points items and removed + m_honorPoints = value; } void Player::SetArenaPoints(uint32 value) @@ -6557,7 +6725,9 @@ void Player::SetArenaPoints(uint32 value) if (value > sWorld.getConfig(CONFIG_UINT32_MAX_ARENA_POINTS)) value = sWorld.getConfig(CONFIG_UINT32_MAX_ARENA_POINTS); - SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, value); + // FIXME 4x SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, value); + // must be recalculated to new honor points items and removed + m_arenaPoints = value; } void Player::ModifyHonorPoints(int32 value) @@ -6972,7 +7142,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl if (ssd && ssd_level > ssd->MaxLevel) ssd_level = ssd->MaxLevel; - ScalingStatValuesEntry const* ssv = proto->ScalingStatValue ? sScalingStatValuesStore.LookupEntry(ssd_level) : NULL; + ScalingStatValuesEntry const* ssv = proto->StatScalingFactor ? sScalingStatValuesStore.LookupEntry(ssd_level) : NULL; if (only_level_scale && !ssv) return; @@ -6986,12 +7156,10 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl if (ssd->StatMod[i] < 0) continue; statType = ssd->StatMod[i]; - val = (ssv->getssdMultiplier(proto->ScalingStatValue) * ssd->Modifier[i]) / 10000; + val = (ssv->getssdMultiplier(proto->StatScalingFactor) * ssd->Modifier[i]) / 10000; } else { - if (i >= proto->StatsCount) - continue; statType = proto->ItemStat[i].ItemStatType; val = proto->ItemStat[i].ItemStatValue; } @@ -7001,12 +7169,9 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl switch (statType) { - case ITEM_MOD_MANA: + /*case ITEM_MOD_MANA: HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply); - break; - case ITEM_MOD_HEALTH: // modify HP - HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply); - break; + break;*/ case ITEM_MOD_AGILITY: // modify agility HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); ApplyStatBuffMod(STAT_AGILITY, float(val), apply); @@ -7027,63 +7192,15 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl HandleStatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply); ApplyStatBuffMod(STAT_STAMINA, float(val), apply); break; - case ITEM_MOD_DEFENSE_SKILL_RATING: - ApplyRatingMod(CR_DEFENSE_SKILL, int32(val), apply); - break; case ITEM_MOD_DODGE_RATING: ApplyRatingMod(CR_DODGE, int32(val), apply); break; case ITEM_MOD_PARRY_RATING: ApplyRatingMod(CR_PARRY, int32(val), apply); break; - case ITEM_MOD_BLOCK_RATING: - ApplyRatingMod(CR_BLOCK, int32(val), apply); - break; - case ITEM_MOD_HIT_MELEE_RATING: - ApplyRatingMod(CR_HIT_MELEE, int32(val), apply); - break; - case ITEM_MOD_HIT_RANGED_RATING: - ApplyRatingMod(CR_HIT_RANGED, int32(val), apply); - break; - case ITEM_MOD_HIT_SPELL_RATING: - ApplyRatingMod(CR_HIT_SPELL, int32(val), apply); - break; - case ITEM_MOD_CRIT_MELEE_RATING: - ApplyRatingMod(CR_CRIT_MELEE, int32(val), apply); - break; case ITEM_MOD_CRIT_RANGED_RATING: ApplyRatingMod(CR_CRIT_RANGED, int32(val), apply); break; - case ITEM_MOD_CRIT_SPELL_RATING: - ApplyRatingMod(CR_CRIT_SPELL, int32(val), apply); - break; - case ITEM_MOD_HIT_TAKEN_MELEE_RATING: - ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply); - break; - case ITEM_MOD_HIT_TAKEN_RANGED_RATING: - ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply); - break; - case ITEM_MOD_HIT_TAKEN_SPELL_RATING: - ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply); - break; - case ITEM_MOD_CRIT_TAKEN_MELEE_RATING: - ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply); - break; - case ITEM_MOD_CRIT_TAKEN_RANGED_RATING: - ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply); - break; - case ITEM_MOD_CRIT_TAKEN_SPELL_RATING: - ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply); - break; - case ITEM_MOD_HASTE_MELEE_RATING: - ApplyRatingMod(CR_HASTE_MELEE, int32(val), apply); - break; - case ITEM_MOD_HASTE_RANGED_RATING: - ApplyRatingMod(CR_HASTE_RANGED, int32(val), apply); - break; - case ITEM_MOD_HASTE_SPELL_RATING: - ApplyRatingMod(CR_HASTE_SPELL, int32(val), apply); - break; case ITEM_MOD_HIT_RATING: ApplyRatingMod(CR_HIT_MELEE, int32(val), apply); ApplyRatingMod(CR_HIT_RANGED, int32(val), apply); @@ -7094,20 +7211,8 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl ApplyRatingMod(CR_CRIT_RANGED, int32(val), apply); ApplyRatingMod(CR_CRIT_SPELL, int32(val), apply); break; - case ITEM_MOD_HIT_TAKEN_RATING: - ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply); - ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply); - ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply); - break; - case ITEM_MOD_CRIT_TAKEN_RATING: - ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply); - ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply); - ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply); - break; case ITEM_MOD_RESILIENCE_RATING: - ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply); - ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply); - ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply); + ApplyRatingMod(CR_RESILIENCE_DAMAGE_TAKEN, int32(val), apply); break; case ITEM_MOD_HASTE_RATING: ApplyRatingMod(CR_HASTE_MELEE, int32(val), apply); @@ -7124,12 +7229,6 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl case ITEM_MOD_RANGED_ATTACK_POWER: HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); break; - case ITEM_MOD_MANA_REGENERATION: - ApplyManaRegenBonus(int32(val), apply); - break; - case ITEM_MOD_ARMOR_PENETRATION_RATING: - ApplyRatingMod(CR_ARMOR_PENETRATION, int32(val), apply); - break; case ITEM_MOD_SPELL_POWER: ApplySpellPowerBonus(int32(val), apply); break; @@ -7137,13 +7236,35 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -int32(val), apply); m_spellPenetrationItemMod += apply ? val : -val; break; - case ITEM_MOD_BLOCK_VALUE: - HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(val), apply); + case ITEM_MOD_MASTERY_RATING: + ApplyRatingMod(CR_MASTERY, int32(val), apply); break; - // deprecated item mods + // deprecated item mods + case ITEM_MOD_HEALTH: + case ITEM_MOD_DEFENSE_SKILL_RATING: + case ITEM_MOD_BLOCK_RATING: + case ITEM_MOD_HIT_MELEE_RATING: + case ITEM_MOD_HIT_RANGED_RATING: + case ITEM_MOD_HIT_SPELL_RATING: + case ITEM_MOD_CRIT_MELEE_RATING: + case ITEM_MOD_CRIT_SPELL_RATING: + case ITEM_MOD_HIT_TAKEN_MELEE_RATING: + case ITEM_MOD_HIT_TAKEN_RANGED_RATING: + case ITEM_MOD_HIT_TAKEN_SPELL_RATING: + case ITEM_MOD_CRIT_TAKEN_MELEE_RATING: + case ITEM_MOD_CRIT_TAKEN_RANGED_RATING: + case ITEM_MOD_CRIT_TAKEN_SPELL_RATING: + case ITEM_MOD_HASTE_MELEE_RATING: + case ITEM_MOD_HASTE_RANGED_RATING: + case ITEM_MOD_HASTE_SPELL_RATING: + case ITEM_MOD_HIT_TAKEN_RATING: + case ITEM_MOD_CRIT_TAKEN_RATING: case ITEM_MOD_FERAL_ATTACK_POWER: case ITEM_MOD_SPELL_HEALING_DONE: case ITEM_MOD_SPELL_DAMAGE_DONE: + case ITEM_MOD_MANA_REGENERATION: + case ITEM_MOD_ARMOR_PENETRATION_RATING: + case ITEM_MOD_BLOCK_VALUE: break; } } @@ -7151,15 +7272,15 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl // Apply Spell Power from ScalingStatValue if set if (ssv) { - if (int32 spellbonus = ssv->getSpellBonus(proto->ScalingStatValue)) + if (int32 spellbonus = ssv->getSpellBonus(proto->StatScalingFactor)) ApplySpellPowerBonus(spellbonus, apply); } // If set ScalingStatValue armor get it or use item armor - uint32 armor = proto->Armor; + uint32 armor = proto->GetArmor(); if (ssv) { - if (uint32 ssvarmor = ssv->getArmorMod(proto->ScalingStatValue)) + if (uint32 ssvarmor = ssv->getArmorMod(proto->StatScalingFactor)) armor = ssvarmor; } // Add armor bonus from ArmorDamageModifier if > 0 @@ -7182,27 +7303,6 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl } } - if (proto->Block) - HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply); - - if (proto->HolyRes) - HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(proto->HolyRes), apply); - - if (proto->FireRes) - HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(proto->FireRes), apply); - - if (proto->NatureRes) - HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(proto->NatureRes), apply); - - if (proto->FrostRes) - HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(proto->FrostRes), apply); - - if (proto->ShadowRes) - HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(proto->ShadowRes), apply); - - if (proto->ArcaneRes) - HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply); - WeaponAttackType attType = BASE_ATTACK; float damage = 0.0f; @@ -7217,13 +7317,13 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl attType = OFF_ATTACK; } - float minDamage = proto->Damage[0].DamageMin; - float maxDamage = proto->Damage[0].DamageMax; + float minDamage = proto->GetMinDamage(); + float maxDamage = proto->GetMaxDamage(); int32 extraDPS = 0; // If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage if (ssv) { - if ((extraDPS = ssv->getDPSMod(proto->ScalingStatValue))) + if ((extraDPS = ssv->getDPSMod(proto->StatScalingFactor))) { float average = extraDPS * proto->Delay / 1000.0f; minDamage = 0.7f * average; @@ -7246,7 +7346,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl // Apply feral bonus from ScalingStatValue if set if (ssv) { - if (int32 feral_bonus = ssv->getFeralBonus(proto->ScalingStatValue)) + if (int32 feral_bonus = ssv->getFeralBonus(proto->StatScalingFactor)) ApplyFeralAPBonus(feral_bonus, apply); } // Druids get feral AP bonus from weapon dps (also use DPS from ScalingStatValue) @@ -7292,7 +7392,7 @@ void Player::_ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackTy void Player::_ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, Aura* aura, bool apply) { // generic not weapon specific case processes in aura code - if (aura->GetSpellProto()->EquippedItemClass == -1) + if(aura->GetSpellProto()->GetEquippedItemClass() == -1) return; BaseModGroup mod = BASEMOD_END; @@ -7318,7 +7418,7 @@ void Player::_ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType att return; // generic not weapon specific case processes in aura code - if (aura->GetSpellProto()->EquippedItemClass == -1) + if(aura->GetSpellProto()->GetEquippedItemClass() == -1) return; UnitMods unitMod = UNIT_MOD_END; @@ -7549,7 +7649,7 @@ void Player::_HandleDeadlyPoison(Unit* Target, WeaponAttackType attType, SpellEn break; } } - if (dPoison && dPoison->GetStackAmount() == spellInfo->StackAmount) + if (dPoison && dPoison->GetStackAmount() == spellInfo->GetStackAmount()) { Item* otherWeapon = GetWeaponForAttack(attType == BASE_ATTACK ? OFF_ATTACK : BASE_ATTACK); if (!otherWeapon) @@ -7569,9 +7669,9 @@ void Player::_HandleDeadlyPoison(Unit* Target, WeaponAttackType attType, SpellEn if (pSecondEnchant->type[s] != ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL) continue; - SpellEntry const* combatEntry = sSpellStore.LookupEntry(pSecondEnchant->spellid[s]); - if (combatEntry && combatEntry->Dispel == DISPEL_POISON) - CastSpell(Target, combatEntry, true, otherWeapon); + if (SpellEntry const* combatEntry = sSpellStore.LookupEntry(pSecondEnchant->spellid[s])) + if (combatEntry->GetDispel() == DISPEL_POISON) + CastSpell(Target, combatEntry, true, otherWeapon); } } } @@ -7612,7 +7712,7 @@ void Player::CastItemCombatSpell(Unit* Target, WeaponAttackType attType) if (m_extraAttacks && IsSpellHaveEffect(spellInfo, SPELL_EFFECT_ADD_EXTRA_ATTACKS)) return; - float chance = (float)spellInfo->procChance; + float chance = (float)spellInfo->GetProcChance(); if (spellData.SpellPPMRate) { @@ -7665,7 +7765,7 @@ void Player::CastItemCombatSpell(Unit* Target, WeaponAttackType attType) else { // Deadly Poison, unique effect needs to be handled before casting triggered spell - if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & UI64LIT(0x10000)) + if (spellInfo->IsFitToFamily(SPELLFAMILY_ROGUE, UI64LIT(0x0000000000010000))) _HandleDeadlyPoison(Target, attType, spellInfo); CastSpell(Target, spellInfo->Id, true, item); @@ -7880,26 +7980,26 @@ void Player::_ApplyAllLevelScaleItemMods(bool apply) void Player::_ApplyAmmoBonuses() { - // check ammo - uint32 ammo_id = GetUInt32Value(PLAYER_AMMO_ID); - if (!ammo_id) - return; + //// check ammo + //uint32 ammo_id = GetUInt32Value(PLAYER_AMMO_ID); + //if(!ammo_id) + // return; - float currentAmmoDPS; + //float currentAmmoDPS; - ItemPrototype const* ammo_proto = ObjectMgr::GetItemPrototype(ammo_id); - if (!ammo_proto || ammo_proto->Class != ITEM_CLASS_PROJECTILE || !CheckAmmoCompatibility(ammo_proto)) - currentAmmoDPS = 0.0f; - else - currentAmmoDPS = ammo_proto->Damage[0].DamageMin; + //ItemPrototype const *ammo_proto = ObjectMgr::GetItemPrototype( ammo_id ); + //if( !ammo_proto || ammo_proto->Class!=ITEM_CLASS_PROJECTILE || !CheckAmmoCompatibility(ammo_proto)) + // currentAmmoDPS = 0.0f; + //else + // currentAmmoDPS = ammo_proto->Damage[0].DamageMin; - if (currentAmmoDPS == GetAmmoDPS()) - return; + //if(currentAmmoDPS == GetAmmoDPS()) + // return; - m_ammoDPS = currentAmmoDPS; + //m_ammoDPS = currentAmmoDPS; - if (CanModifyStats()) - UpdateDamagePhysical(RANGED_ATTACK); + //if(CanModifyStats()) + // UpdateDamagePhysical(RANGED_ATTACK); } bool Player::CheckAmmoCompatibility(const ItemPrototype* ammo_proto) const @@ -11141,37 +11241,37 @@ InventoryResult Player::CanUseAmmo(uint32 item) const void Player::SetAmmo(uint32 item) { - if (!item) - return; + //if(!item) + // return; - // already set - if (GetUInt32Value(PLAYER_AMMO_ID) == item) - return; + //// already set + //if( GetUInt32Value(PLAYER_AMMO_ID) == item ) + // return; - // check ammo - if (item) - { - InventoryResult msg = CanUseAmmo(item); - if (msg != EQUIP_ERR_OK) - { - SendEquipError(msg, NULL, NULL, item); - return; - } - } + //// check ammo + //if (item) + //{ + // InventoryResult msg = CanUseAmmo( item ); + // if (msg != EQUIP_ERR_OK) + // { + // SendEquipError(msg, NULL, NULL, item); + // return; + // } + //} - SetUInt32Value(PLAYER_AMMO_ID, item); + //SetUInt32Value(PLAYER_AMMO_ID, item); - _ApplyAmmoBonuses(); + //_ApplyAmmoBonuses(); } void Player::RemoveAmmo() { - SetUInt32Value(PLAYER_AMMO_ID, 0); + //SetUInt32Value(PLAYER_AMMO_ID, 0); - m_ammoDPS = 0.0f; + //m_ammoDPS = 0.0f; - if (CanModifyStats()) - UpdateDamagePhysical(RANGED_ATTACK); + //if (CanModifyStats()) + // UpdateDamagePhysical(RANGED_ATTACK); } // Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case. @@ -11376,7 +11476,7 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update) sLog.outError("Weapon switch cooldown spell %u couldn't be found in Spell.dbc", cooldownSpell); else { - m_weaponChangeTimer = spellProto->StartRecoveryTime; + m_weaponChangeTimer = spellProto->GetStartRecoveryTime(); WorldPacket data(SMSG_SPELL_COOLDOWN, 8 + 1 + 4); data << GetObjectGuid(); @@ -12830,10 +12930,10 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool DEBUG_LOG("Adding %u to stat nb %u", enchant_amount, enchant_spell_id); switch (enchant_spell_id) { - case ITEM_MOD_MANA: + /*case ITEM_MOD_MANA: DEBUG_LOG("+ %u MANA", enchant_amount); HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply); - break; + break;*/ case ITEM_MOD_HEALTH: DEBUG_LOG("+ %u HEALTH", enchant_amount); HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply); @@ -12863,10 +12963,6 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply); ApplyStatBuffMod(STAT_STAMINA, float(enchant_amount), apply); break; - case ITEM_MOD_DEFENSE_SKILL_RATING: - ApplyRatingMod(CR_DEFENSE_SKILL, enchant_amount, apply); - DEBUG_LOG("+ %u DEFENCE", enchant_amount); - break; case ITEM_MOD_DODGE_RATING: ApplyRatingMod(CR_DODGE, enchant_amount, apply); DEBUG_LOG("+ %u DODGE", enchant_amount); @@ -12875,63 +12971,10 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool ApplyRatingMod(CR_PARRY, enchant_amount, apply); DEBUG_LOG("+ %u PARRY", enchant_amount); break; - case ITEM_MOD_BLOCK_RATING: - ApplyRatingMod(CR_BLOCK, enchant_amount, apply); - DEBUG_LOG("+ %u SHIELD_BLOCK", enchant_amount); - break; - case ITEM_MOD_HIT_MELEE_RATING: - ApplyRatingMod(CR_HIT_MELEE, enchant_amount, apply); - DEBUG_LOG("+ %u MELEE_HIT", enchant_amount); - break; - case ITEM_MOD_HIT_RANGED_RATING: - ApplyRatingMod(CR_HIT_RANGED, enchant_amount, apply); - DEBUG_LOG("+ %u RANGED_HIT", enchant_amount); - break; - case ITEM_MOD_HIT_SPELL_RATING: - ApplyRatingMod(CR_HIT_SPELL, enchant_amount, apply); - DEBUG_LOG("+ %u SPELL_HIT", enchant_amount); - break; - case ITEM_MOD_CRIT_MELEE_RATING: - ApplyRatingMod(CR_CRIT_MELEE, enchant_amount, apply); - DEBUG_LOG("+ %u MELEE_CRIT", enchant_amount); - break; case ITEM_MOD_CRIT_RANGED_RATING: ApplyRatingMod(CR_CRIT_RANGED, enchant_amount, apply); DEBUG_LOG("+ %u RANGED_CRIT", enchant_amount); break; - case ITEM_MOD_CRIT_SPELL_RATING: - ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply); - DEBUG_LOG("+ %u SPELL_CRIT", enchant_amount); - break; -// Values from ITEM_STAT_MELEE_HA_RATING to ITEM_MOD_HASTE_RANGED_RATING are never used -// in Enchantments -// case ITEM_MOD_HIT_TAKEN_MELEE_RATING: -// ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply); -// break; -// case ITEM_MOD_HIT_TAKEN_RANGED_RATING: -// ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply); -// break; -// case ITEM_MOD_HIT_TAKEN_SPELL_RATING: -// ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply); -// break; -// case ITEM_MOD_CRIT_TAKEN_MELEE_RATING: -// ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); -// break; -// case ITEM_MOD_CRIT_TAKEN_RANGED_RATING: -// ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); -// break; -// case ITEM_MOD_CRIT_TAKEN_SPELL_RATING: -// ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); -// break; -// case ITEM_MOD_HASTE_MELEE_RATING: -// ApplyRatingMod(CR_HASTE_MELEE, enchant_amount, apply); -// break; -// case ITEM_MOD_HASTE_RANGED_RATING: -// ApplyRatingMod(CR_HASTE_RANGED, enchant_amount, apply); -// break; - case ITEM_MOD_HASTE_SPELL_RATING: - ApplyRatingMod(CR_HASTE_SPELL, enchant_amount, apply); - break; case ITEM_MOD_HIT_RATING: ApplyRatingMod(CR_HIT_MELEE, enchant_amount, apply); ApplyRatingMod(CR_HIT_RANGED, enchant_amount, apply); @@ -12944,21 +12987,8 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply); DEBUG_LOG("+ %u CRITICAL", enchant_amount); break; -// Values ITEM_MOD_HIT_TAKEN_RATING and ITEM_MOD_CRIT_TAKEN_RATING are never used in Enchantment -// case ITEM_MOD_HIT_TAKEN_RATING: -// ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply); -// ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply); -// ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply); -// break; -// case ITEM_MOD_CRIT_TAKEN_RATING: -// ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); -// ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); -// ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); -// break; case ITEM_MOD_RESILIENCE_RATING: - ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); - ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); - ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); + ApplyRatingMod(CR_RESILIENCE_DAMAGE_TAKEN, enchant_amount, apply); DEBUG_LOG("+ %u RESILIENCE", enchant_amount); break; case ITEM_MOD_HASTE_RATING: @@ -12980,24 +13010,44 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); DEBUG_LOG("+ %u RANGED_ATTACK_POWER", enchant_amount); break; - case ITEM_MOD_MANA_REGENERATION: - ApplyManaRegenBonus(enchant_amount, apply); - DEBUG_LOG("+ %u MANA_REGENERATION", enchant_amount); - break; - case ITEM_MOD_ARMOR_PENETRATION_RATING: - ApplyRatingMod(CR_ARMOR_PENETRATION, enchant_amount, apply); - DEBUG_LOG("+ %u ARMOR PENETRATION", enchant_amount); - break; case ITEM_MOD_SPELL_POWER: ApplySpellPowerBonus(enchant_amount, apply); DEBUG_LOG("+ %u SPELL_POWER", enchant_amount); break; - case ITEM_MOD_BLOCK_VALUE: - HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(enchant_amount), apply); + case ITEM_MOD_SPELL_PENETRATION: + ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -int32(enchant_amount), apply); + m_spellPenetrationItemMod += apply ? enchant_amount : -int32(enchant_amount); + DEBUG_LOG("+ %u SPELL_PENETRATION", -int32(enchant_amount)); break; + case ITEM_MOD_MASTERY_RATING: + ApplyRatingMod(CR_MASTERY, enchant_amount, apply); + DEBUG_LOG("+ %u MASTERY_RATING", enchant_amount); + break; + // deprecated + case ITEM_MOD_DEFENSE_SKILL_RATING: + case ITEM_MOD_BLOCK_RATING: + case ITEM_MOD_HIT_MELEE_RATING: + case ITEM_MOD_HIT_RANGED_RATING: + case ITEM_MOD_HIT_SPELL_RATING: + case ITEM_MOD_CRIT_MELEE_RATING: + case ITEM_MOD_CRIT_SPELL_RATING: + case ITEM_MOD_HIT_TAKEN_MELEE_RATING: + case ITEM_MOD_HIT_TAKEN_RANGED_RATING: + case ITEM_MOD_HIT_TAKEN_SPELL_RATING: + case ITEM_MOD_CRIT_TAKEN_MELEE_RATING: + case ITEM_MOD_CRIT_TAKEN_RANGED_RATING: + case ITEM_MOD_CRIT_TAKEN_SPELL_RATING: + case ITEM_MOD_HASTE_MELEE_RATING: + case ITEM_MOD_HASTE_RANGED_RATING: + case ITEM_MOD_HASTE_SPELL_RATING: + case ITEM_MOD_HIT_TAKEN_RATING: + case ITEM_MOD_CRIT_TAKEN_RATING: case ITEM_MOD_FERAL_ATTACK_POWER: - case ITEM_MOD_SPELL_HEALING_DONE: // deprecated - case ITEM_MOD_SPELL_DAMAGE_DONE: // deprecated + case ITEM_MOD_SPELL_HEALING_DONE: + case ITEM_MOD_SPELL_DAMAGE_DONE: + case ITEM_MOD_MANA_REGENERATION: + case ITEM_MOD_ARMOR_PENETRATION_RATING: + case ITEM_MOD_BLOCK_VALUE: default: break; } @@ -13857,6 +13907,8 @@ bool Player::CanCompleteQuest(uint32 quest_id) const if (repFacId && GetReputationMgr().GetReputation(repFacId) < qInfo->GetRepObjectiveValue()) return false; + // FIXME: check req currencies + return true; } @@ -13913,6 +13965,8 @@ bool Player::CanRewardQuest(Quest const* pQuest, bool msg) const if (pQuest->GetRewOrReqMoney() < 0 && GetMoney() < uint32(-pQuest->GetRewOrReqMoney())) return false; + // FIXME: check currencies max count ? + return true; } @@ -14128,6 +14182,8 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver, } } + // FIXME: take currency + RemoveTimedQuest(quest_id); if (BattleGround* bg = GetBattleGround()) @@ -14202,9 +14258,7 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver, if (pQuest->GetRewOrReqMoney() < 0) ModifyMoney(pQuest->GetRewOrReqMoney()); - // honor reward - if (uint32 honor = pQuest->CalculateRewardHonor(getLevel())) - RewardHonor(NULL, 0, honor); + // FIXME: reward currency // title reward if (pQuest->GetCharTitleId()) @@ -15316,23 +15370,36 @@ void Player::SendQuestReward(Quest const* pQuest, uint32 XP, Object* questGiver) uint32 questid = pQuest->GetQuestId(); DEBUG_LOG("WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", questid); WorldPacket data(SMSG_QUESTGIVER_QUEST_COMPLETE, (4 + 4 + 4 + 4 + 4)); - data << uint32(questid); + data << uint32(pQuest->GetBonusTalents()); + data << uint32(pQuest->GetRewSkillValue()); if (getLevel() < sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL)) { - data << uint32(XP); data << uint32(pQuest->GetRewOrReqMoney()); + data << uint32(XP); } else { - data << uint32(0); data << uint32(pQuest->GetRewOrReqMoney() + int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_MONEY))); + data << uint32(0); } - data << uint32(10 * MaNGOS::Honor::hk_honor_at_level(getLevel(), pQuest->GetRewHonorAddition())); - data << uint32(pQuest->GetBonusTalents()); // bonus talents - data << uint32(0); // arena points + data << uint32(questid); + data << uint32(pQuest->GetRewSkill()); + + data.WriteBit(0); // unk + data.WriteBit(1); // unk + GetSession()->SendPacket(&data); + + if (QuestPhaseMapsVector const* QuestPhaseVector = sObjectMgr.GetQuestPhaseMapVector(questid)) + { + for (QuestPhaseMapsVector::const_iterator itr = QuestPhaseVector->begin(); itr != QuestPhaseVector->end(); ++itr) + { + GetSession()->SendSetPhaseShift(itr->PhaseMask, itr->MapId); + CharacterDatabase.PExecute("REPLACE INTO character_phase_data` (`guid`, `map`, `phase`) VALUES (%u, %u, %u)", GetSession()->GetPlayer()->GetGUIDLow(), itr->MapId, itr->PhaseMask); + } + } } void Player::SendQuestFailed(uint32 quest_id, InventoryResult reason) @@ -15579,9 +15646,9 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) //"resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty," // 39 40 41 42 43 44 45 46 47 48 49 //"arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk," - // 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 - //"health, power1, power2, power3, power4, power5, power6, power7, specCount, activeSpec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); - QueryResult* result = holder->GetResult(PLAYER_LOGIN_QUERY_LOADFROM); + // 50 51 52 53 54 55 56 57 58 59 60 61 62 + //"health, power1, power2, power3, power4, power5, specCount, activeSpec, exploredZones, equipmentCache, knownTitles, actionBars, slot FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); + QueryResult *result = holder->GetResult(PLAYER_LOGIN_QUERY_LOADFROM); if (!result) { @@ -15630,8 +15697,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8()); SetUInt32Value(PLAYER_XP, fields[7].GetUInt32()); - _LoadIntoDataField(fields[60].GetString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE); - _LoadIntoDataField(fields[63].GetString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE * 2); + _LoadIntoDataField(fields[58].GetString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE); + _LoadIntoDataField(fields[60].GetString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE*2); InitDisplayIds(); // model, scale and model data @@ -15656,12 +15723,12 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) SetUInt32Value(PLAYER_FLAGS, fields[11].GetUInt32()); SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fields[48].GetInt32()); - SetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES, fields[47].GetUInt64()); - - SetUInt32Value(PLAYER_AMMO_ID, fields[62].GetUInt32()); + //SetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES, fields[47].GetUInt64()); // Action bars state - SetByteValue(PLAYER_FIELD_BYTES, 2, fields[64].GetUInt8()); + SetByteValue(PLAYER_FIELD_BYTES, 2, fields[61].GetUInt8()); + + m_slot = fields[62].GetUInt8(); // cleanup inventory related item value fields (its will be filled correctly in _LoadInventory) for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) @@ -15724,8 +15791,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) SetHonorPoints(fields[40].GetUInt32()); - SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, fields[41].GetUInt32()); - SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, fields[42].GetUInt32()); + //SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, fields[41].GetUInt32()); + //SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, fields[42].GetUInt32()); SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, fields[43].GetUInt32()); SetUInt16Value(PLAYER_FIELD_KILLS, 0, fields[44].GetUInt16()); SetUInt16Value(PLAYER_FIELD_KILLS, 1, fields[45].GetUInt16()); @@ -15996,8 +16063,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) _LoadMailedItems(holder->GetResult(PLAYER_LOGIN_QUERY_LOADMAILEDITEMS)); UpdateNextMailTimeAndUnreads(); - m_specsCount = fields[58].GetUInt8(); - m_activeSpec = fields[59].GetUInt8(); + m_specsCount = fields[56].GetUInt8(); + m_activeSpec = fields[57].GetUInt8(); _LoadGlyphs(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGLYPHS)); @@ -16107,10 +16174,12 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) // restore remembered power/health values (but not more max values) uint32 savedhealth = fields[50].GetUInt32(); SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth); - for (uint32 i = 0; i < MAX_POWERS; ++i) + + static_assert(MAX_STORED_POWERS == 5, "Query not updated."); + for (uint32 i = 0; i < MAX_STORED_POWERS; ++i) { uint32 savedpower = fields[51 + i].GetUInt32(); - SetPower(Powers(i), savedpower > GetMaxPower(Powers(i)) ? GetMaxPower(Powers(i)) : savedpower); + SetPowerByIndex(i, std::min(savedpower, GetMaxPowerByIndex(i))); } DEBUG_FILTER_LOG(LOG_FILTER_PLAYER_STATS, "The value of player %s after load item and aura is: ", m_name.c_str()); @@ -16292,13 +16361,19 @@ void Player::_LoadAuras(QueryResult* result, uint32 timediff) } // prevent wrong values of remaincharges - if (spellproto->procCharges == 0) + if (uint32 procCharges = spellproto->GetProcCharges()) + { + if (remaincharges <= 0 || remaincharges > procCharges) + remaincharges = procCharges; + } + else remaincharges = 0; - if (!spellproto->StackAmount) + uint32 defstackamount = spellproto->GetStackAmount(); + if (!defstackamount) stackcount = 1; - else if (spellproto->StackAmount < stackcount) - stackcount = spellproto->StackAmount; + else if (defstackamount < stackcount) + stackcount = defstackamount; else if (!stackcount) stackcount = 1; @@ -17421,21 +17496,21 @@ void Player::SaveToDB() stmt.PExecute(GetGUIDLow()); SqlStatement uberInsert = CharacterDatabase.CreateStatement(insChar, "INSERT INTO characters (guid,account,name,race,class,gender,level,xp,money,playerBytes,playerBytes2,playerFlags," - "map, dungeon_difficulty, position_x, position_y, position_z, orientation, " - "taximask, online, cinematic, " - "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, " - "trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, " - "death_expire_time, taxi_path, arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, " - "todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, health, power1, power2, power3, " - "power4, power5, power6, power7, specCount, activeSpec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars) " - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " - "?, ?, ?, ?, ?, ?, " - "?, ?, ?, " - "?, ?, ?, ?, ?, ?, ?, " - "?, ?, ?, ?, ?, ?, ?, ?, ?, " - "?, ?, ?, ?, ?, ?, ?, " - "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " - "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "); + "map, dungeon_difficulty, position_x, position_y, position_z, orientation, " + "taximask, online, cinematic, " + "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, " + "trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, " + "death_expire_time, taxi_path, arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, " + "todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, health, power1, power2, power3, " + "power4, power5, specCount, activeSpec, exploredZones, equipmentCache, knownTitles, actionBars, slot) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, " + "?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, ?, ?) "); uberInsert.addUInt32(GetGUIDLow()); uberInsert.addUInt32(GetSession()->GetAccountId()); @@ -17514,9 +17589,9 @@ void Player::SaveToDB() uberInsert.addUInt32(GetHonorPoints()); - uberInsert.addUInt32(GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); + uberInsert.addUInt32(0); // FIXME 4x GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION) - uberInsert.addUInt32(GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION)); + uberInsert.addUInt32(0); // FIXME 4x GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION) uberInsert.addUInt32(GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS)); @@ -17526,7 +17601,7 @@ void Player::SaveToDB() uberInsert.addUInt32(GetUInt32Value(PLAYER_CHOSEN_TITLE)); - uberInsert.addUInt64(GetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES)); + uberInsert.addUInt64(0); // FIXME 4x GetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES) // FIXME: at this moment send to DB as unsigned, including unit32(-1) uberInsert.addUInt32(GetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX)); @@ -17535,8 +17610,9 @@ void Player::SaveToDB() uberInsert.addUInt32(GetHealth()); - for (uint32 i = 0; i < MAX_POWERS; ++i) - uberInsert.addUInt32(GetPower(Powers(i))); + static_assert(MAX_STORED_POWERS == 5, "Query not updated."); + for (uint32 i = 0; i < MAX_STORED_POWERS; ++i) + uberInsert.addUInt32(GetPowerByIndex(i)); uberInsert.addUInt32(uint32(m_specsCount)); uberInsert.addUInt32(uint32(m_activeSpec)); @@ -17553,9 +17629,7 @@ void Player::SaveToDB() } uberInsert.addString(ss); - uberInsert.addUInt32(GetUInt32Value(PLAYER_AMMO_ID)); - - for (uint32 i = 0; i < KNOWN_TITLES_SIZE * 2; ++i) // string + for(uint32 i = 0; i < KNOWN_TITLES_SIZE*2; ++i ) //string { ss << GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES + i) << " "; } @@ -17563,6 +17637,8 @@ void Player::SaveToDB() uberInsert.addUInt32(uint32(GetByteValue(PLAYER_FIELD_BYTES, 2))); + uberInsert.addUInt8(m_slot); + uberInsert.Execute(); if (m_mailsUpdated) // save mails only when needed @@ -18097,9 +18173,11 @@ void Player::_SaveSkills() continue; } - uint32 valueData = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)); - uint16 value = SKILL_VALUE(valueData); - uint16 max = SKILL_MAX(valueData); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; + + uint16 value = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); + uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); switch (itr->second.uState) { @@ -18203,15 +18281,16 @@ void Player::_SaveStats() SqlStatement stmt = CharacterDatabase.CreateStatement(delStats, "DELETE FROM character_stats WHERE guid = ?"); stmt.PExecute(GetGUIDLow()); - stmt = CharacterDatabase.CreateStatement(insertStats, "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5, maxpower6, maxpower7, " - "strength, agility, stamina, intellect, spirit, armor, resHoly, resFire, resNature, resFrost, resShadow, resArcane, " - "blockPct, dodgePct, parryPct, critPct, rangedCritPct, spellCritPct, attackPower, rangedAttackPower, spellPower) " - "VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + stmt = CharacterDatabase.CreateStatement(insertStats, "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5" + "strength, agility, stamina, intellect, spirit, armor, resHoly, resFire, resNature, resFrost, resShadow, resArcane, " + "blockPct, dodgePct, parryPct, critPct, rangedCritPct, spellCritPct, attackPower, rangedAttackPower, spellPower) " + "VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); stmt.addUInt32(GetGUIDLow()); stmt.addUInt32(GetMaxHealth()); - for (int i = 0; i < MAX_POWERS; ++i) - stmt.addUInt32(GetMaxPower(Powers(i))); + static_assert(MAX_STORED_POWERS == 5, "Query not updated."); + for (uint32 i = 0; i < MAX_STORED_POWERS; ++i) + stmt.addUInt32(GetMaxPowerByIndex(i)); for (int i = 0; i < MAX_STATS; ++i) stmt.addFloat(GetStat(Stats(i))); // armor + school resistances @@ -18522,13 +18601,16 @@ void Player::RemovePet(PetSaveMode mode) pet->Unsummon(mode, this); } -void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language) const +void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language, const char* addonPrefix) const { *data << uint8(msgtype); *data << uint32(language); - *data << ObjectGuid(GetObjectGuid()); - *data << uint32(0); // 2.1.0 - *data << ObjectGuid(GetObjectGuid()); + *data << GetObjectGuid(); + *data << uint32(0); // constant unknown time 4.3.4 + if (addonPrefix) + *data << addonPrefix; + else + *data << GetObjectGuid(); *data << uint32(text.length() + 1); *data << text; *data << uint8(GetChatTag()); @@ -18557,22 +18639,15 @@ void Player::TextEmote(const std::string& text) void Player::Whisper(const std::string& text, uint32 language, ObjectGuid receiver) { - if (language != LANG_ADDON) // if not addon data - language = LANG_UNIVERSAL; // whispers should always be readable - Player* rPlayer = sObjectMgr.GetPlayer(receiver); WorldPacket data(SMSG_MESSAGECHAT, 200); BuildPlayerChat(&data, CHAT_MSG_WHISPER, text, language); rPlayer->GetSession()->SendPacket(&data); - // not send confirmation for addon messages - if (language != LANG_ADDON) - { - data.Initialize(SMSG_MESSAGECHAT, 200); - rPlayer->BuildPlayerChat(&data, CHAT_MSG_WHISPER_INFORM, text, language); - GetSession()->SendPacket(&data); - } + data.Initialize(SMSG_MESSAGECHAT, 200); + rPlayer->BuildPlayerChat(&data, CHAT_MSG_WHISPER_INFORM, text, language); + GetSession()->SendPacket(&data); if (!isAcceptWhispers()) { @@ -18587,6 +18662,17 @@ void Player::Whisper(const std::string& text, uint32 language, ObjectGuid receiv ChatHandler(this).PSendSysMessage(LANG_PLAYER_DND, rPlayer->GetName(), rPlayer->autoReplyMsg.c_str()); } +void Player::WhisperAddon(const std::string& text, const std::string& prefix, ObjectGuid receiver) +{ + Player* rPlayer = sObjectMgr.GetPlayer(receiver); + + std::string _text(text); + + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildPlayerChat(&data, CHAT_MSG_WHISPER, _text, LANG_UNIVERSAL, prefix.c_str()); + rPlayer->GetSession()->SendPacket(&data); +} + void Player::PetSpellInitialize() { Pet* pet = GetPet(); @@ -18787,9 +18873,11 @@ void Player::AddSpellMod(Aura* aura, bool apply) val += (*itr)->GetModifier()->m_amount; } val += apply ? mod->m_amount : -(mod->m_amount); - WorldPacket data(Opcode, (1 + 1 + 4)); - data << uint8(eff); + WorldPacket data(Opcode, 4 + 4 + 1 + 1 + 4); + data << uint32(1); + data << uint32(1); data << uint8(mod->m_miscvalue); + data << uint8(eff); data << int32(val); SendDirectMessage(&data); } @@ -19231,7 +19319,7 @@ void Player::ContinueTaxiFlight() void Player::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) { - // last check 2.0.10 + // last check 4.3.4 WorldPacket data(SMSG_SPELL_COOLDOWN, 8 + 1 + m_spells.size() * 8); data << GetObjectGuid(); data << uint8(0x0); // flags (0x1, 0x2) @@ -19438,7 +19526,7 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorGuid, uint32 vendorslot, uin if (uint32 extendedCostId = crItem->ExtendedCost) { - ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(extendedCostId); + ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(extendedCostId); if (!iece) { sLog.outError("Item %u have wrong ExtendedCost field value %u", pProto->ItemId, extendedCostId); @@ -19642,7 +19730,6 @@ void Player::AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 it // some special item spells without correct cooldown in SpellInfo // cooldown information stored in item prototype - // This used in same way in WorldSession::HandleItemQuerySingleOpcode data sending to client. if (itemId) { @@ -19664,9 +19751,9 @@ void Player::AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 it // if no cooldown found above then base at DBC data if (rec < 0 && catrec < 0) { - cat = spellInfo->Category; - rec = spellInfo->RecoveryTime; - catrec = spellInfo->CategoryRecoveryTime; + cat = spellInfo->GetCategory(); + rec = spellInfo->GetRecoveryTime(); + catrec = spellInfo->GetCategoryRecoveryTime(); } time_t curTime = time(NULL); @@ -20396,14 +20483,13 @@ void Player::SendInitialPacketsAfterAddToMap() } if (HasAuraType(SPELL_AURA_MOD_STUN)) - SetRoot(true); + SetMovement(MOVE_ROOT); // manual send package (have code in ApplyModifier(true,true); that don't must be re-applied. if (HasAuraType(SPELL_AURA_MOD_ROOT)) { - WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 10); - data2 << GetPackGUID(); - data2 << (uint32)2; + WorldPacket data2; + BuildForceMoveRootPacket(&data2, true, 2); SendMessageToSet(&data2, true); } @@ -20430,14 +20516,8 @@ void Player::SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg) WorldPacket data(SMSG_TRANSFER_ABORTED, 4 + 2); data << uint32(mapid); data << uint8(reason); // transfer abort reason - switch (reason) - { - case TRANSFER_ABORT_INSUF_EXPAN_LVL: - case TRANSFER_ABORT_DIFFICULTY: - case TRANSFER_ABORT_UNIQUE_MESSAGE: - data << uint8(arg); - break; - } + data << uint8(arg); + GetSession()->SendPacket(&data); } @@ -20487,7 +20567,7 @@ void Player::ApplyEquipCooldown(Item* pItem) AddSpellCooldown(spellData.SpellId, pItem->GetEntry(), time(NULL) + 30); WorldPacket data(SMSG_ITEM_COOLDOWN, 12); - data << ObjectGuid(pItem->GetObjectGuid()); + data << pItem->GetObjectGuid(); data << uint32(spellData.SpellId); GetSession()->SendPacket(&data); } @@ -20541,10 +20621,13 @@ void Player::learnQuestRewardedSpells(Quest const* quest) bool found = false; for (int i = 0; i < MAX_EFFECT_INDEX; ++i) { - if (spellInfo->Effect[i] == SPELL_EFFECT_LEARN_SPELL && !HasSpell(spellInfo->EffectTriggerSpell[i])) + if(SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(SpellEffectIndex(i))) { - found = true; - break; + if(spellEffect->Effect == SPELL_EFFECT_LEARN_SPELL && !HasSpell(spellEffect->EffectTriggerSpell)) + { + found = true; + break; + } } } @@ -20553,8 +20636,10 @@ void Player::learnQuestRewardedSpells(Quest const* quest) return; // prevent learn non first rank unknown profession and second specialization for same profession) - uint32 learned_0 = spellInfo->EffectTriggerSpell[EFFECT_INDEX_0]; - if (sSpellMgr.GetSpellRank(learned_0) > 1 && !HasSpell(learned_0)) + SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(EFFECT_INDEX_0); + uint32 learned_0 = spellEffect ? spellEffect->EffectTriggerSpell : 0; + + if( sSpellMgr.GetSpellRank(learned_0) > 1 && !HasSpell(learned_0) ) { // not have first rank learned (unlearned prof?) uint32 first_spell = sSpellMgr.GetFirstSpellInChain(learned_0); @@ -20566,7 +20651,9 @@ void Player::learnQuestRewardedSpells(Quest const* quest) return; // specialization - if (learnedInfo->Effect[EFFECT_INDEX_0] == SPELL_EFFECT_TRADE_SKILL && learnedInfo->Effect[EFFECT_INDEX_1] == 0) + SpellEffectEntry const* learnedSpellEffect0 = learnedInfo->GetSpellEffect(EFFECT_INDEX_0); + SpellEffectEntry const* learnedSpellEffect1 = learnedInfo->GetSpellEffect(EFFECT_INDEX_1); + if (learnedSpellEffect0 && learnedSpellEffect0->Effect == SPELL_EFFECT_TRADE_SKILL && learnedSpellEffect1 && learnedSpellEffect1->Effect == 0) { // search other specialization for same prof for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) @@ -20579,7 +20666,9 @@ void Player::learnQuestRewardedSpells(Quest const* quest) return; // compare only specializations - if (itrInfo->Effect[EFFECT_INDEX_0] != SPELL_EFFECT_TRADE_SKILL || itrInfo->Effect[EFFECT_INDEX_1] != 0) + SpellEffectEntry const* itrSpellEffect0 = learnedInfo->GetSpellEffect(EFFECT_INDEX_0); + SpellEffectEntry const* itrSpellEffect1 = learnedInfo->GetSpellEffect(EFFECT_INDEX_1); + if ((itrSpellEffect0 && itrSpellEffect0->Effect != SPELL_EFFECT_TRADE_SKILL) || (itrSpellEffect1 && itrSpellEffect1->Effect != 0)) continue; // compare same chain spells @@ -20862,7 +20951,7 @@ void Player::UpdateForQuestWorldObjects() if (m_clientGUIDs.empty()) return; - UpdateData udata; + UpdateData udata(GetMapId()); WorldPacket packet; for (GuidSet::const_iterator itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr) { @@ -20981,12 +21070,13 @@ void Player::AutoUnequipOffhandIfNeed() bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem) { - if (spellInfo->EquippedItemClass < 0) + int32 itemClass = spellInfo->GetEquippedItemClass(); + if(itemClass < 0) return true; // scan other equipped items for same requirements (mostly 2 daggers/etc) // for optimize check 2 used cases only - switch (spellInfo->EquippedItemClass) + switch(itemClass) { case ITEM_CLASS_WEAPON: { @@ -21017,7 +21107,7 @@ bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item cons break; } default: - sLog.outError("HasItemFitToSpellReqirements: Not handled spell requirement for item class %u", spellInfo->EquippedItemClass); + sLog.outError("HasItemFitToSpellReqirements: Not handled spell requirement for item class %u", itemClass); break; } @@ -21953,6 +22043,7 @@ void Player::_LoadSkills(QueryResult* result) // SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid)); uint32 count = 0; + uint8 professionCount = 0; if (result) { do @@ -21990,9 +22081,28 @@ void Player::_LoadSkills(QueryResult* result) continue; } - SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, 0)); - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), MAKE_SKILL_VALUE(value, max)); - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0); + uint16 field = count / 2; + uint8 offset = count & 1; + + SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, skill); + uint16 step = 0; + + if (pSkill->categoryId == SKILL_CATEGORY_SECONDARY) + step = max / 75; + + if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION) + { + step = max / 75; + + if (professionCount < 2) + SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + professionCount++, skill); + } + + SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, value); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, max); + SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0); mSkillStatus.insert(SkillStatusMap::value_type(skill, SkillStatusData(count, SKILL_UNCHANGED))); @@ -22012,9 +22122,15 @@ void Player::_LoadSkills(QueryResult* result) for (; count < PLAYER_MAX_SKILLS; ++count) { - SetUInt32Value(PLAYER_SKILL_INDEX(count), 0); - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), 0); - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0); + uint16 field = count / 2; + uint8 offset = count & 1; + + SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0); } // special settings @@ -22241,7 +22357,7 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank) return; // Check if it requires another talent - if (talentInfo->DependsOn > 0) + /*if (talentInfo->DependsOn > 0) { if (TalentEntry const* depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn)) { @@ -22257,7 +22373,7 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank) if (!hasEnoughRank) return; } - } + }*/ // Find out how many points we have in this field uint32 spentPoints = 0; @@ -22355,7 +22471,7 @@ void Player::LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRa return; // Check if it requires another talent - if (talentInfo->DependsOn > 0) + /*if (talentInfo->DependsOn > 0) { if (TalentEntry const* depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn)) { @@ -22369,7 +22485,7 @@ void Player::LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRa if (!hasEnoughRank) return; } - } + }*/ // Find out how many points we have in this field uint32 spentPoints = 0; @@ -22424,18 +22540,18 @@ void Player::LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRa void Player::UpdateKnownCurrencies(uint32 itemId, bool apply) { - if (CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemId)) - { - if (apply) - SetFlag64(PLAYER_FIELD_KNOWN_CURRENCIES, (UI64LIT(1) << (ctEntry->BitIndex - 1))); - else - RemoveFlag64(PLAYER_FIELD_KNOWN_CURRENCIES, (UI64LIT(1) << (ctEntry->BitIndex - 1))); - } + //if(CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemId)) + //{ + // if(apply) + // SetFlag64(PLAYER_FIELD_KNOWN_CURRENCIES, (UI64LIT(1) << (ctEntry->BitIndex - 1))); + // else + // RemoveFlag64(PLAYER_FIELD_KNOWN_CURRENCIES, (UI64LIT(1) << (ctEntry->BitIndex - 1))); + //} } void Player::UpdateFallInformationIfNeed(MovementInfo const& minfo, uint16 opcode) { - if (m_lastFallTime >= minfo.GetFallTime() || m_lastFallZ <= minfo.GetPos()->z || opcode == MSG_MOVE_FALL_LAND) + if (m_lastFallTime >= minfo.GetFallTime() || m_lastFallZ <= minfo.GetPos()->z || opcode == CMSG_MOVE_FALL_LAND) SetFallInformation(minfo.GetFallTime(), minfo.GetPos()->z); } @@ -23025,23 +23141,20 @@ void Player::RemoveAtLoginFlag(AtLoginFlags f, bool in_db_also /*= false*/) void Player::SendClearCooldown(uint32 spell_id, Unit* target) { - WorldPacket data(SMSG_CLEAR_COOLDOWN, 4 + 8); + ObjectGuid guid = target->GetObjectGuid(); + + WorldPacket data(SMSG_CLEAR_COOLDOWNS, 1 + 8 + 4); + data.WriteGuidMask<1, 3, 6>(guid); + data.WriteBits(1, 24); // cooldown count + data.WriteGuidMask<7, 5, 2, 4, 0>(guid); + + data.WriteGuidBytes<7, 2, 4, 5, 1, 3>(guid); data << uint32(spell_id); - data << target->GetObjectGuid(); + data.WriteGuidBytes<0, 6>(guid); + SendDirectMessage(&data); } -void Player::BuildTeleportAckMsg(WorldPacket& data, float x, float y, float z, float ang) const -{ - MovementInfo mi = m_movementInfo; - mi.ChangePosition(x, y, z, ang); - - data.Initialize(MSG_MOVE_TELEPORT_ACK, 64); - data << GetPackGUID(); - data << uint32(0); // this value increments every time - data << mi; -} - bool Player::HasMovementFlag(MovementFlags f) const { return m_movementInfo.HasMovementFlag(f); @@ -23075,20 +23188,25 @@ void Player::SendDuelCountdown(uint32 counter) bool Player::IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index) const { - switch (spellInfo->Effect[index]) + SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(index); + if(spellEffect) { - case SPELL_EFFECT_ATTACK_ME: - return true; - default: - break; - } - switch (spellInfo->EffectApplyAuraName[index]) - { - case SPELL_AURA_MOD_TAUNT: - return true; - default: - break; + switch(spellEffect->Effect) + { + case SPELL_EFFECT_ATTACK_ME: + return true; + default: + break; + } + switch(spellEffect->EffectApplyAuraName) + { + case SPELL_AURA_MOD_TAUNT: + return true; + default: + break; + } } + return Unit::IsImmuneToSpellEffect(spellInfo, index); } diff --git a/src/game/QuestDef.cpp b/src/game/QuestDef.cpp index e16c2153c..ae7bc85ba 100644 --- a/src/game/QuestDef.cpp +++ b/src/game/QuestDef.cpp @@ -138,12 +138,38 @@ Quest::Quest(Field* questRecord) QuestStartScript = questRecord[139].GetUInt32(); QuestCompleteScript = questRecord[140].GetUInt32(); + ReqSpellLearned = questRecord[141].GetUInt32(); + PortraitGiver = questRecord[142].GetUInt32(); + PortraitTurnIn = questRecord[143].GetUInt32(); + + PortraitGiverText = questRecord[144].GetCppString(); + PortraitGiverName = questRecord[145].GetCppString(); + PortraitTurnInText = questRecord[146].GetCppString(); + PortraitTurnInName = questRecord[147].GetCppString(); + + for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) + ReqCurrencyId[i] = questRecord[148 + i].GetUInt32(); + for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) + ReqCurrencyCount[i] = questRecord[152 + i].GetUInt32(); + + for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + RewCurrencyId[i] = questRecord[156 + i].GetUInt32(); + for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + RewCurrencyCount[i] = questRecord[160 + i].GetUInt32(); + + RewSkill = questRecord[164].GetUInt32(); + RewSkillValue = questRecord[165].GetUInt32(); + + SoundAcceptId = questRecord[166].GetUInt32(); + SoundTurnInId = questRecord[167].GetUInt32(); + m_isActive = true; m_reqitemscount = 0; m_reqCreatureOrGOcount = 0; m_rewitemscount = 0; m_rewchoiceitemscount = 0; + m_reqCurrencyCount = 0; for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) { @@ -168,6 +194,12 @@ Quest::Quest(Field* questRecord) if (RewChoiceItemId[i]) ++m_rewchoiceitemscount; } + + for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + { + if (RewCurrencyId[i]) + ++m_reqCurrencyCount; + } } uint32 Quest::XPValue(Player* pPlayer) const @@ -294,3 +326,4 @@ uint32 Quest::CalculateRewardHonor(uint32 level) const return honor; } + diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h index fa382dbd2..cc24cda6a 100644 --- a/src/game/QuestDef.h +++ b/src/game/QuestDef.h @@ -31,6 +31,8 @@ class ObjectMgr; #define MAX_QUEST_LOG_SIZE 25 +#define QUEST_REQUIRED_CURRENCY_COUNT 4 +#define QUEST_REWARD_CURRENCY_COUNT 4 #define QUEST_OBJECTIVES_COUNT 4 #define QUEST_ITEM_OBJECTIVES_COUNT 6 #define QUEST_SOURCE_ITEM_IDS_COUNT 4 @@ -147,7 +149,7 @@ enum QuestFlags QUEST_FLAGS_RAID = 0x00000040, // Not used currently QUEST_FLAGS_TBC = 0x00000080, // Not used currently: Available if TBC expansion enabled only QUEST_FLAGS_UNK2 = 0x00000100, // Not used currently: _DELIVER_MORE Quest needs more than normal _q-item_ drops from mobs - QUEST_FLAGS_HIDDEN_REWARDS = 0x00000200, // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE)) + QUEST_FLAGS_HIDDEN_REWARDS = 0x00000200, // unused 4.x.x ? Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE)) QUEST_FLAGS_AUTO_REWARDED = 0x00000400, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side. QUEST_FLAGS_TBC_RACES = 0x00000800, // Not used currently: Blood elf/Draenei starting zone quests QUEST_FLAGS_DAILY = 0x00001000, // Daily quest. Can be done once a day. Quests reset at regular intervals for all players. @@ -223,6 +225,7 @@ class Quest uint32 GetRequiredMaxRepFaction() const { return RequiredMaxRepFaction; } int32 GetRequiredMaxRepValue() const { return RequiredMaxRepValue; } uint32 GetSuggestedPlayers() const { return SuggestedPlayers; } + uint32 GetReqSpellLearned() const { return ReqSpellLearned; } uint32 GetLimitTime() const { return LimitTime; } int32 GetPrevQuestId() const { return PrevQuestId; } int32 GetNextQuestId() const { return NextQuestId; } @@ -232,6 +235,8 @@ class Quest uint32 GetCharTitleId() const { return CharTitleId; } uint32 GetPlayersSlain() const { return PlayersSlain; } uint32 GetBonusTalents() const { return BonusTalents; } + uint32 GetPortraitGiver() const { return PortraitGiver; } + uint32 GetPortraitTurnIn() const { return PortraitTurnIn; } uint32 GetSrcItemId() const { return SrcItemId; } uint32 GetSrcItemCount() const { return SrcItemCount; } uint32 GetSrcSpell() const { return SrcSpell; } @@ -242,11 +247,17 @@ class Quest std::string GetRequestItemsText() const { return RequestItemsText; } std::string GetEndText() const { return EndText; } std::string GetCompletedText() const { return CompletedText; } + std::string GetPortraitGiverText() const { return PortraitGiverText; } + std::string GetPortraitGiverName() const { return PortraitGiverName; } + std::string GetPortraitTurnInText() const { return PortraitTurnInText; } + std::string GetPortraitTurnInName() const { return PortraitTurnInName; } int32 GetRewOrReqMoney() const; uint32 GetRewHonorAddition() const { return RewHonorAddition; } float GetRewHonorMultiplier() const { return RewHonorMultiplier; } uint32 GetRewMoneyMaxLevel() const { return RewMoneyMaxLevel; } // use in XP calculation at client + uint32 GetRewSkill() const { return RewSkill; } + uint32 GetRewSkillValue() const { return RewSkillValue; } uint32 GetRewSpell() const { return RewSpell; } uint32 GetRewSpellCast() const { return RewSpellCast; } uint32 GetRewMailTemplateId() const { return RewMailTemplateId; } @@ -259,6 +270,8 @@ class Quest uint32 GetCompleteEmote() const { return CompleteEmote; } uint32 GetQuestStartScript() const { return QuestStartScript; } uint32 GetQuestCompleteScript() const { return QuestCompleteScript; } + uint32 GetSoundAcceptId() const { return SoundAcceptId; } + uint32 GetSoundTurnInId() const { return SoundTurnInId; } bool IsRepeatable() const { return m_SpecialFlags & QUEST_SPECIAL_FLAG_REPEATABLE; } bool IsAutoComplete() const { return QuestMethod ? false : true; } @@ -295,9 +308,14 @@ class Quest uint32 DetailsEmoteDelay[QUEST_EMOTE_COUNT]; uint32 OfferRewardEmote[QUEST_EMOTE_COUNT]; uint32 OfferRewardEmoteDelay[QUEST_EMOTE_COUNT]; + uint32 RewCurrencyId[QUEST_REWARD_CURRENCY_COUNT]; + uint32 RewCurrencyCount[QUEST_REWARD_CURRENCY_COUNT]; + uint32 ReqCurrencyId[QUEST_REQUIRED_CURRENCY_COUNT]; + uint32 ReqCurrencyCount[QUEST_REQUIRED_CURRENCY_COUNT]; uint32 GetReqItemsCount() const { return m_reqitemscount; } uint32 GetReqCreatureOrGOcount() const { return m_reqCreatureOrGOcount; } + uint32 GetReqCurrencyCount() const { return m_reqCurrencyCount; } uint32 GetRewChoiceItemsCount() const { return m_rewchoiceitemscount; } uint32 GetRewItemsCount() const { return m_rewitemscount; } @@ -310,6 +328,7 @@ class Quest private: uint32 m_reqitemscount; uint32 m_reqCreatureOrGOcount; + uint32 m_reqCurrencyCount; uint32 m_rewchoiceitemscount; uint32 m_rewitemscount; @@ -333,6 +352,7 @@ class Quest int32 RequiredMinRepValue; uint32 RequiredMaxRepFaction; int32 RequiredMaxRepValue; + uint32 ReqSpellLearned; uint32 SuggestedPlayers; uint32 LimitTime; uint32 m_QuestFlags; @@ -340,6 +360,8 @@ class Quest uint32 CharTitleId; uint32 PlayersSlain; uint32 BonusTalents; + uint32 PortraitGiver; + uint32 PortraitTurnIn; int32 PrevQuestId; int32 NextQuestId; int32 ExclusiveGroup; @@ -355,10 +377,16 @@ class Quest std::string RequestItemsText; std::string EndText; std::string CompletedText; + std::string PortraitGiverText; + std::string PortraitGiverName; + std::string PortraitTurnInText; + std::string PortraitTurnInName; uint32 RewHonorAddition; float RewHonorMultiplier; int32 RewOrReqMoney; uint32 RewMoneyMaxLevel; + uint32 RewSkill; + uint32 RewSkillValue; uint32 RewSpell; uint32 RewSpellCast; uint32 RewMailTemplateId; @@ -371,6 +399,8 @@ class Quest uint32 CompleteEmote; uint32 QuestStartScript; uint32 QuestCompleteScript; + uint32 SoundAcceptId; + uint32 SoundTurnInId; }; enum QuestUpdateState diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index 82f2e18d5..25e4f9024 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -393,13 +393,14 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recv_data) { uint32 quest; ObjectGuid guid; - recv_data >> guid >> quest; + uint8 unk; + recv_data >> guid >> quest >> unk; if (!CanInteractWithQuestGiver(guid, "CMSG_QUESTGIVER_COMPLETE_QUEST")) return; // All ok, continue - DEBUG_LOG("WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST - for %s to %s, quest = %u", _player->GetGuidStr().c_str(), guid.GetString().c_str(), quest); + DEBUG_LOG("WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST - for %s to %s, quest = %u, unk = %u", _player->GetGuidStr().c_str(), guid.GetString().c_str(), quest, unk); if (Quest const* pQuest = sObjectMgr.GetQuestTemplate(quest)) { @@ -485,8 +486,9 @@ void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket) void WorldSession::HandleQuestPushResult(WorldPacket& recvPacket) { ObjectGuid guid; + uint32 quest; uint8 msg; - recvPacket >> guid >> msg; + recvPacket >> guid >> quest >> msg; DEBUG_LOG("WORLD: Received MSG_QUEST_PUSH_RESULT"); @@ -607,7 +609,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket for (GuidSet::const_iterator itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr) { - uint8 dialogStatus = DIALOG_STATUS_NONE; + uint32 dialogStatus = DIALOG_STATUS_NONE; if (itr->IsAnyTypeCreature()) { @@ -626,7 +628,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket dialogStatus = getDialogStatus(_player, questgiver, DIALOG_STATUS_NONE); data << questgiver->GetObjectGuid(); - data << uint8(dialogStatus); + data << uint32(dialogStatus); ++count; } else if (itr->IsGameObject()) @@ -645,7 +647,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket dialogStatus = getDialogStatus(_player, questgiver, DIALOG_STATUS_NONE); data << questgiver->GetObjectGuid(); - data << uint8(dialogStatus); + data << uint32(dialogStatus); ++count; } } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index fb2e9ac62..9a0552ea8 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ -#define REVISION_NR "0158" +#define REVISION_NR "0159" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index c7ae95d2a..9e1b05439 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ #define REVISION_DB_CHARACTERS "required_0099_xxxxx_01_characters_character_phase_data" - #define REVISION_DB_MANGOS "required_0157_xxxxx_01_player_levelstats" + #define REVISION_DB_MANGOS "required_0159_xxxxx_01_mangos_quest_template" #define REVISION_DB_REALMD "required_0014_xxxxx_01_realmd_account_access" #endif // __REVISION_SQL_H__