diff options
author | linencloth <none@none> | 2010-12-26 04:16:18 +0100 |
---|---|---|
committer | linencloth <none@none> | 2010-12-26 04:16:18 +0100 |
commit | b150172521636fa5646489688e53d03f0773b9be (patch) | |
tree | b078947617c1deead6699123567e8beabdb2477b | |
parent | 8fdbe7c4e69f5b0a8eb907aa76cc2afd2b297cd3 (diff) |
Core/QuestStatus:
- Separate rewarded quests from active quests, and store them in a new table to reduce database size
- Drop the no longer needed `rewarded` column from character_queststatus for smaller table size
- Prevent filling the database with dropped quests
- Delete useless records
- Implement queststatus save "queues" instead of states
- Minor optimizations
WARNING: Backup your database!
--HG--
branch : trunk
-rw-r--r-- | sql/base/characters_database.sql | 9 | ||||
-rw-r--r-- | sql/updates/10828_characters_character_queststatus.sql | 13 | ||||
-rwxr-xr-x | src/server/game/Achievements/AchievementMgr.cpp | 12 | ||||
-rwxr-xr-x | src/server/game/Entities/Player/Player.cpp | 348 | ||||
-rwxr-xr-x | src/server/game/Entities/Player/Player.h | 18 | ||||
-rwxr-xr-x | src/server/game/Quests/QuestDef.h | 20 | ||||
-rwxr-xr-x | src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp | 8 | ||||
-rwxr-xr-x | src/server/game/Server/Protocol/Handlers/QuestHandler.cpp | 20 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellEffects.cpp | 7 | ||||
-rwxr-xr-x | src/server/game/Tools/PlayerDump.cpp | 3 | ||||
-rwxr-xr-x | src/server/game/Tools/PlayerDump.h | 4 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_quest.cpp | 6 | ||||
-rw-r--r-- | src/server/scripts/Kalimdor/silithus.cpp | 1 | ||||
-rw-r--r-- | src/server/scripts/Outland/shadowmoon_valley.cpp | 2 | ||||
-rwxr-xr-x | src/server/shared/Database/Implementation/CharacterDatabase.cpp | 5 | ||||
-rwxr-xr-x | src/server/shared/Database/Implementation/CharacterDatabase.h | 1 |
16 files changed, 250 insertions, 227 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql index 85b87c1af05..bfbed7ea722 100644 --- a/sql/base/characters_database.sql +++ b/sql/base/characters_database.sql @@ -857,7 +857,6 @@ CREATE TABLE `character_queststatus` ( `guid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier', `quest` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Quest Identifier', `status` tinyint(1) unsigned NOT NULL DEFAULT '0', - `rewarded` tinyint(1) unsigned NOT NULL DEFAULT '0', `explored` tinyint(1) unsigned NOT NULL DEFAULT '0', `timer` bigint(20) unsigned NOT NULL DEFAULT '0', `mobcount1` smallint(3) unsigned NOT NULL DEFAULT '0', @@ -906,6 +905,14 @@ LOCK TABLES `character_queststatus_daily` WRITE; /*!40000 ALTER TABLE `character_queststatus_daily` ENABLE KEYS */; UNLOCK TABLES; +DROP TABLE IF EXISTS `character_queststatus_rewarded`; +CREATE TABLE `character_queststatus_rewarded` ( + `guid` int(10) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `quest` int(10) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + PRIMARY KEY (`guid`,`quest`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System'; + + -- -- Table structure for table `character_queststatus_weekly` -- diff --git a/sql/updates/10828_characters_character_queststatus.sql b/sql/updates/10828_characters_character_queststatus.sql new file mode 100644 index 00000000000..88681714a86 --- /dev/null +++ b/sql/updates/10828_characters_character_queststatus.sql @@ -0,0 +1,13 @@ +DELETE FROM character_queststatus WHERE `status` = 0; + +DROP TABLE IF EXISTS `character_queststatus_rewarded`; +CREATE TABLE `character_queststatus_rewarded` ( + `guid` int(10) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `quest` int(10) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + PRIMARY KEY (`guid`,`quest`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System'; + +INSERT INTO character_queststatus_rewarded SELECT guid, quest FROM character_queststatus WHERE rewarded = 1; +DELETE FROM character_queststatus WHERE rewarded = 1; + +ALTER TABLE character_queststatus DROP COLUMN rewarded; diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 5e54fce96a1..777aed237e0 100755 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -848,11 +848,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT: { - uint32 counter =0; - for (QuestStatusMap::const_iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr != GetPlayer()->getQuestStatusMap().end(); itr++) - if (itr->second.m_rewarded) - counter++; - SetCriteriaProgress(achievementCriteria, counter); + SetCriteriaProgress(achievementCriteria, GetPlayer()->getRewardedQuests().size()); break; } case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY: @@ -892,10 +888,10 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; uint32 counter =0; - for (QuestStatusMap::const_iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr != GetPlayer()->getQuestStatusMap().end(); itr++) + for (RewardedQuestSet::const_iterator itr = GetPlayer()->getRewardedQuests().begin(); itr != GetPlayer()->getRewardedQuests().end(); itr++) { - Quest const* quest = sObjectMgr->GetQuestTemplate(itr->first); - if (itr->second.m_rewarded && quest && quest->GetZoneOrSort() >= 0 && uint32(quest->GetZoneOrSort()) == achievementCriteria->complete_quests_in_zone.zoneID) + Quest const* quest = sObjectMgr->GetQuestTemplate(*itr); + if (quest && quest->GetZoneOrSort() >= 0 && uint32(quest->GetZoneOrSort()) == achievementCriteria->complete_quests_in_zone.zoneID) counter++; } SetCriteriaProgress(achievementCriteria, counter); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index ae1f8dcde09..ce787a11cce 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1311,7 +1311,7 @@ void Player::Update(uint32 p_time) QuestSet::iterator iter = m_timedquests.begin(); while (iter != m_timedquests.end()) { - QuestStatusData& q_status = mQuestStatus[*iter]; + QuestStatusData& q_status = m_QuestStatus[*iter]; if (q_status.m_timer <= p_time) { uint32 quest_id = *iter; @@ -1321,8 +1321,7 @@ void Player::Update(uint32 p_time) else { q_status.m_timer -= p_time; - if (q_status.uState != QUEST_NEW) - q_status.uState = QUEST_CHANGED; + m_QuestStatusSave[*iter] = true; ++iter; } } @@ -4616,6 +4615,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC trans->PAppend("DELETE FROM character_instance WHERE guid = '%u'",guid); trans->PAppend("DELETE FROM character_inventory WHERE guid = '%u'",guid); trans->PAppend("DELETE FROM character_queststatus WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_queststatus_rewarded WHERE guid = '%u'",guid); trans->PAppend("DELETE FROM character_reputation WHERE guid = '%u'",guid); trans->PAppend("DELETE FROM character_spell WHERE guid = '%u'",guid); trans->PAppend("DELETE FROM character_spell_cooldown WHERE guid = '%u'",guid); @@ -14039,13 +14039,15 @@ void Player::PrepareQuestMenu(uint64 guid) { uint32 quest_id = i->second; Quest const* pQuest = sObjectMgr->GetQuestTemplate(quest_id); - if (!pQuest) continue; + if (!pQuest) + continue; - QuestStatus status = GetQuestStatus(quest_id); + if (!CanTakeQuest(pQuest, false)) + continue; - if (pQuest->IsAutoComplete() && CanTakeQuest(pQuest, false)) + if (pQuest->IsAutoComplete()) qm.AddMenuItem(quest_id, 4); - else if (status == QUEST_STATUS_NONE && CanTakeQuest(pQuest, false)) + else if (GetQuestStatus(quest_id) == QUEST_STATUS_NONE) qm.AddMenuItem(quest_id, 2); } } @@ -14148,9 +14150,7 @@ void Player::SendPreparedQuest(uint64 guid) bool Player::IsActiveQuest(uint32 quest_id) const { - QuestStatusMap::const_iterator itr = mQuestStatus.find(quest_id); - - return itr != mQuestStatus.end() && itr->second.m_status != QUEST_STATUS_NONE; + return m_QuestStatus.find(quest_id) != m_QuestStatus.end(); } Quest const * Player::GetNextQuest(uint64 guid, Quest const *pQuest) @@ -14237,8 +14237,8 @@ bool Player::CanCompleteQuest(uint32 quest_id) { if (quest_id) { - QuestStatusData& q_status = mQuestStatus[quest_id]; - if (q_status.m_status == QUEST_STATUS_COMPLETE) + RewardedQuestSet::iterator rewItr = m_RewardedQuests.find(quest_id); + if (rewItr != m_RewardedQuests.end()) return false; // not allow re-complete quest Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id); @@ -14250,6 +14250,12 @@ bool Player::CanCompleteQuest(uint32 quest_id) if ((qInfo->IsAutoComplete() || qInfo->GetFlags() & QUEST_FLAGS_AUTOCOMPLETE) && CanTakeQuest(qInfo, false)) return true; + QuestStatusMap::iterator itr = m_QuestStatus.find(quest_id); + if (itr == m_QuestStatus.end()) + return false; + + QuestStatusData &q_status = itr->second; + if (q_status.m_status == QUEST_STATUS_INCOMPLETE) { @@ -14403,7 +14409,7 @@ void Player::AddQuest(Quest const *pQuest, Object *questGiver) uint32 quest_id = pQuest->GetQuestId(); // if not exist then created with set uState == NEW and rewarded=false - QuestStatusData& questStatusData = mQuestStatus[quest_id]; + QuestStatusData& questStatusData = m_QuestStatus[quest_id]; // check for repeatable quests status reset questStatusData.m_status = QUEST_STATUS_INCOMPLETE; @@ -14450,8 +14456,7 @@ void Player::AddQuest(Quest const *pQuest, Object *questGiver) SetQuestSlot(log_slot, quest_id, qtime); - if (questStatusData.uState != QUEST_NEW) - questStatusData.uState = QUEST_CHANGED; + m_QuestStatusSave[quest_id] = true; GetAchievementMgr().StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, quest_id); @@ -14565,10 +14570,11 @@ void Player::RewardQuest(Quest const *pQuest, uint32 reward, Object* questGiver, if (log_slot < MAX_QUEST_LOG_SIZE) SetQuestSlot(log_slot, 0); - QuestStatusData& q_status = mQuestStatus[quest_id]; + RewardedQuestSet::const_iterator rewItr = m_RewardedQuests.find(quest_id); + bool rewarded = (rewItr != m_RewardedQuests.end()); // Not give XP in case already completed once repeatable quest - uint32 XP = q_status.m_rewarded ? 0 : uint32(pQuest->XPValue(this)*sWorld->getRate(RATE_XP_QUEST)); + uint32 XP = rewarded ? 0 : uint32(pQuest->XPValue(this)*sWorld->getRate(RATE_XP_QUEST)); // handle SPELL_AURA_MOD_XP_QUEST_PCT auras Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT); @@ -14635,14 +14641,10 @@ void Player::RewardQuest(Quest const *pQuest, uint32 reward, Object* questGiver, } else if (pQuest->IsWeekly()) SetWeeklyQuestStatus(quest_id); - if (!pQuest->IsRepeatable()) - SetQuestStatus(quest_id, QUEST_STATUS_COMPLETE); - else - SetQuestStatus(quest_id, QUEST_STATUS_NONE); + RemoveQuest(quest_id); - q_status.m_rewarded = true; - if (q_status.uState != QUEST_NEW) - q_status.uState = QUEST_CHANGED; + m_RewardedQuests.insert(quest_id); + m_RewardedQuestsSave[quest_id] = true; if (announce) SendQuestReward(pQuest, XP, questGiver); @@ -14705,7 +14707,7 @@ void Player::FailQuest(uint32 questId) if (pQuest->HasFlag(QUEST_TRINITY_FLAGS_TIMED)) { - QuestStatusData& q_status = mQuestStatus[questId]; + QuestStatusData& q_status = m_QuestStatus[questId]; RemoveTimedQuest(questId); q_status.m_timer = 0; @@ -14815,13 +14817,12 @@ bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) { uint32 prevId = abs(*iter); - QuestStatusMap::iterator i_prevstatus = mQuestStatus.find(prevId); Quest const* qPrevInfo = sObjectMgr->GetQuestTemplate(prevId); - if (qPrevInfo && i_prevstatus != mQuestStatus.end()) + if (qPrevInfo) { // If any of the positive previous quests completed, return true - if (*iter > 0 && i_prevstatus->second.m_rewarded) + if (*iter > 0 && m_RewardedQuests.find(prevId) != m_RewardedQuests.end()) { // skip one-from-all exclusive group if (qPrevInfo->GetExclusiveGroup() >= 0) @@ -14842,10 +14843,8 @@ bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) if (exclude_Id == prevId) continue; - QuestStatusMap::iterator i_exstatus = mQuestStatus.find(exclude_Id); - // alternative quest from group also must be completed and rewarded(reported) - if (i_exstatus == mQuestStatus.end() || !i_exstatus->second.m_rewarded) + if (m_RewardedQuests.find(exclude_Id) == m_RewardedQuests.end()) { if (msg) SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ); @@ -14854,9 +14853,10 @@ bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) } return true; } + + // If any of the negative previous quests active, return true - if (*iter < 0 && (i_prevstatus->second.m_status == QUEST_STATUS_INCOMPLETE - || (i_prevstatus->second.m_status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus(prevId)))) + if (*iter < 0 && m_QuestStatus.find(prevId) != m_QuestStatus.end()) { // skip one-from-all exclusive group if (qPrevInfo->GetExclusiveGroup() >= 0) @@ -14877,12 +14877,10 @@ bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) if (exclude_Id == prevId) continue; - QuestStatusMap::iterator i_exstatus = mQuestStatus.find(exclude_Id); + QuestStatusMap::iterator i_exstatus = m_QuestStatus.find(exclude_Id); // alternative quest from group also must be active - if (i_exstatus == mQuestStatus.end() || - (i_exstatus->second.m_status != QUEST_STATUS_INCOMPLETE && - (i_prevstatus->second.m_status != QUEST_STATUS_COMPLETE || GetQuestRewardStatus(prevId)))) + if (m_QuestStatus.find(exclude_Id) != m_QuestStatus.end()) { if (msg) SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ); @@ -14939,8 +14937,7 @@ bool Player::SatisfyQuestReputation(Quest const* qInfo, bool msg) bool Player::SatisfyQuestStatus(Quest const* qInfo, bool msg) { - QuestStatusMap::iterator itr = mQuestStatus.find(qInfo->GetQuestId()); - if (itr != mQuestStatus.end() && itr->second.m_status != QUEST_STATUS_NONE) + if (GetQuestStatus(qInfo->GetQuestId()) != QUEST_STATUS_NONE) { if (msg) SendCanTakeQuestResponse(INVALIDREASON_QUEST_ALREADY_ON); @@ -15002,11 +14999,8 @@ bool Player::SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg) return false; } - QuestStatusMap::iterator i_exstatus = mQuestStatus.find(exclude_Id); - // alternative quest already started or completed - if (i_exstatus != mQuestStatus.end() - && (i_exstatus->second.m_status == QUEST_STATUS_COMPLETE || i_exstatus->second.m_status == QUEST_STATUS_INCOMPLETE)) + if (m_QuestStatus.find(exclude_Id) != m_QuestStatus.end() || m_RewardedQuests.find(exclude_Id) != m_RewardedQuests.end()) { if (msg) SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ); @@ -15018,13 +15012,12 @@ bool Player::SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg) bool Player::SatisfyQuestNextChain(Quest const* qInfo, bool msg) { - if (!qInfo->GetNextQuestInChain()) + uint32 nextQuest = qInfo->GetNextQuestInChain(); + if (!nextQuest) return true; // next quest in chain already started or completed - QuestStatusMap::iterator itr = mQuestStatus.find(qInfo->GetNextQuestInChain()); - if (itr != mQuestStatus.end() - && (itr->second.m_status == QUEST_STATUS_COMPLETE || itr->second.m_status == QUEST_STATUS_INCOMPLETE)) + if (m_QuestStatus.find(nextQuest) != m_QuestStatus.end() || m_RewardedQuests.find(nextQuest) != m_RewardedQuests.end()) { if (msg) SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ); @@ -15047,18 +15040,14 @@ bool Player::SatisfyQuestPrevChain(Quest const* qInfo, bool msg) { uint32 prevId = *iter; - QuestStatusMap::iterator i_prevstatus = mQuestStatus.find(prevId); + QuestStatusMap::iterator i_prevstatus = m_QuestStatus.find(prevId); - if (i_prevstatus != mQuestStatus.end()) + // If any of the previous quests in chain active, return false + if (i_prevstatus != m_QuestStatus.end()) { - // If any of the previous quests in chain active, return false - if (i_prevstatus->second.m_status == QUEST_STATUS_INCOMPLETE - || (i_prevstatus->second.m_status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus(prevId))) - { - if (msg) - SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ); - return false; - } + if (msg) + SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ); + return false; } // check for all quests further down the chain @@ -15176,10 +15165,8 @@ bool Player::GetQuestRewardStatus(uint32 quest_id) const if (qInfo) { // for repeatable quests: rewarded field is set after first reward only to prevent getting XP more than once - QuestStatusMap::const_iterator itr = mQuestStatus.find(quest_id); - if (itr != mQuestStatus.end() && itr->second.m_status != QUEST_STATUS_NONE - && !qInfo->IsRepeatable()) - return itr->second.m_rewarded; + if (!qInfo->IsRepeatable()) + return m_RewardedQuests.find(quest_id) != m_RewardedQuests.end(); return false; } @@ -15190,9 +15177,12 @@ QuestStatus Player::GetQuestStatus(uint32 quest_id) const { if (quest_id) { - QuestStatusMap::const_iterator itr = mQuestStatus.find(quest_id); - if (itr != mQuestStatus.end()) + QuestStatusMap::const_iterator itr = m_QuestStatus.find(quest_id); + if (itr != m_QuestStatus.end()) return itr->second.m_status; + + if (m_RewardedQuests.find(quest_id) != m_RewardedQuests.end()) + return QUEST_STATUS_COMPLETE; } return QUEST_STATUS_NONE; } @@ -15202,9 +15192,9 @@ bool Player::CanShareQuest(uint32 quest_id) const Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id); if (qInfo && qInfo->HasFlag(QUEST_FLAGS_SHARABLE)) { - QuestStatusMap::const_iterator itr = mQuestStatus.find(quest_id); - if (itr != mQuestStatus.end()) - return itr->second.m_status == QUEST_STATUS_NONE || itr->second.m_status == QUEST_STATUS_INCOMPLETE; + QuestStatusMap::const_iterator itr = m_QuestStatus.find(quest_id); + if (itr != m_QuestStatus.end()) + return itr->second.m_status == QUEST_STATUS_INCOMPLETE; } return false; } @@ -15213,15 +15203,29 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status) { if (sObjectMgr->GetQuestTemplate(quest_id)) { - QuestStatusData& q_status = mQuestStatus[quest_id]; + m_QuestStatus[quest_id].m_status = status; + m_QuestStatusSave[quest_id] = true; + } - q_status.m_status = status; + UpdateForQuestWorldObjects(); +} - if (q_status.uState != QUEST_NEW) - q_status.uState = QUEST_CHANGED; +void Player::RemoveQuest(uint32 quest_id) +{ + QuestStatusMap::iterator itr = m_QuestStatus.find(quest_id); + if (itr != m_QuestStatus.end()) + { + m_QuestStatus.erase(itr); + m_QuestStatusSave[quest_id] = false; + return; } - UpdateForQuestWorldObjects(); + RewardedQuestSet::iterator rewItr = m_RewardedQuests.find(quest_id); + if (rewItr != m_RewardedQuests.end()) + { + m_RewardedQuests.erase(rewItr); + m_RewardedQuestsSave[quest_id] = false; + } } // not used in Trinity, but used in scripting code @@ -15233,7 +15237,7 @@ uint16 Player::GetReqKillOrCastCurrentCount(uint32 quest_id, int32 entry) for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) if (qInfo->ReqCreatureOrGOId[j] == entry) - return mQuestStatus[quest_id].m_creatureOrGOcount[j]; + return m_QuestStatus[quest_id].m_creatureOrGOcount[j]; return 0; } @@ -15250,8 +15254,7 @@ void Player::AdjustQuestReqItemCount(Quest const* pQuest, QuestStatusData& quest uint32 curitemcount = GetItemCount(pQuest->ReqItemId[i],true); questStatusData.m_itemcount[i] = std::min(curitemcount, reqitemcount); - if (questStatusData.uState != QUEST_NEW) - questStatusData.uState = QUEST_CHANGED; + m_QuestStatusSave[pQuest->GetQuestId()] = true; } } } @@ -15273,13 +15276,12 @@ void Player::AreaExploredOrEventHappens(uint32 questId) uint16 log_slot = FindQuestSlot(questId); if (log_slot < MAX_QUEST_LOG_SIZE) { - QuestStatusData& q_status = mQuestStatus[questId]; + QuestStatusData& q_status = m_QuestStatus[questId]; if (!q_status.m_explored) { q_status.m_explored = true; - if (q_status.uState != QUEST_NEW) - q_status.uState = QUEST_CHANGED; + m_QuestStatusSave[questId] = true; } } if (CanCompleteQuest(questId)) @@ -15313,7 +15315,7 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count) if (questid == 0) continue; - QuestStatusData& q_status = mQuestStatus[questid]; + QuestStatusData& q_status = m_QuestStatus[questid]; if (q_status.m_status != QUEST_STATUS_INCOMPLETE) continue; @@ -15333,7 +15335,8 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count) { uint16 additemcount = curitemcount + count <= reqitemcount ? count : reqitemcount - curitemcount; q_status.m_itemcount[j] += additemcount; - if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + + m_QuestStatusSave[questid] = true; SendQuestUpdateAddItem(qInfo, j, additemcount); } @@ -15364,7 +15367,7 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count) uint32 reqitem = qInfo->ReqItemId[j]; if (reqitem == entry) { - QuestStatusData& q_status = mQuestStatus[questid]; + QuestStatusData& q_status = m_QuestStatus[questid]; uint32 reqitemcount = qInfo->ReqItemCount[j]; uint16 curitemcount; @@ -15376,8 +15379,8 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count) { uint16 remitemcount = curitemcount <= reqitemcount ? count : count + reqitemcount - curitemcount; q_status.m_itemcount[j] = (curitemcount <= remitemcount) ? 0 : curitemcount - remitemcount; - if (q_status.uState != QUEST_NEW) - q_status.uState = QUEST_CHANGED; + + m_QuestStatusSave[questid] = true; IncompleteQuest(questid); } @@ -15422,7 +15425,7 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid) if (!qInfo) continue; // just if !ingroup || !noraidgroup || raidgroup - QuestStatusData& q_status = mQuestStatus[questid]; + QuestStatusData& q_status = m_QuestStatus[questid]; if (q_status.m_status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid())) { if (qInfo->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST)) @@ -15446,8 +15449,8 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid) if (curkillcount < reqkillcount) { q_status.m_creatureOrGOcount[j] = curkillcount + addkillcount; - if (q_status.uState != QUEST_NEW) - q_status.uState = QUEST_CHANGED; + + m_QuestStatusSave[questid] = true; SendQuestUpdateAddCreatureOrGo(qInfo, guid, j, curkillcount, addkillcount); } @@ -15478,7 +15481,7 @@ void Player::CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id) if (!qInfo) continue; - QuestStatusData& q_status = mQuestStatus[questid]; + QuestStatusData& q_status = m_QuestStatus[questid]; if (q_status.m_status == QUEST_STATUS_INCOMPLETE) { @@ -15525,8 +15528,8 @@ void Player::CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id) if (curCastCount < reqCastCount) { q_status.m_creatureOrGOcount[j] = curCastCount + addCastCount; - if (q_status.uState != QUEST_NEW) - q_status.uState = QUEST_CHANGED; + + m_QuestStatusSave[questid] = true; SendQuestUpdateAddCreatureOrGo(qInfo, guid, j, curCastCount, addCastCount); } @@ -15555,7 +15558,7 @@ void Player::TalkedToCreature(uint32 entry, uint64 guid) if (!qInfo) continue; - QuestStatusData& q_status = mQuestStatus[questid]; + QuestStatusData& q_status = m_QuestStatus[questid]; if (q_status.m_status == QUEST_STATUS_INCOMPLETE) { @@ -15582,8 +15585,8 @@ void Player::TalkedToCreature(uint32 entry, uint64 guid) if (curTalkCount < reqTalkCount) { q_status.m_creatureOrGOcount[j] = curTalkCount + addTalkCount; - if (q_status.uState != QUEST_NEW) - q_status.uState = QUEST_CHANGED; + + m_QuestStatusSave[questid] = true; SendQuestUpdateAddCreatureOrGo(qInfo, guid, j, curTalkCount, addTalkCount); } @@ -15610,7 +15613,7 @@ void Player::MoneyChanged(uint32 count) Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid); if (qInfo && qInfo->GetRewOrReqMoney() < 0) { - QuestStatusData& q_status = mQuestStatus[questid]; + QuestStatusData& q_status = m_QuestStatus[questid]; if (q_status.m_status == QUEST_STATUS_INCOMPLETE) { @@ -15639,7 +15642,7 @@ void Player::ReputationChanged(FactionEntry const* factionEntry) { if (qInfo->GetRepObjectiveFaction() == factionEntry->ID) { - QuestStatusData& q_status = mQuestStatus[questid]; + QuestStatusData& q_status = m_QuestStatus[questid]; if (q_status.m_status == QUEST_STATUS_INCOMPLETE) { if (GetReputationMgr().GetReputation(factionEntry) >= qInfo->GetRepObjectiveValue()) @@ -15667,7 +15670,7 @@ void Player::ReputationChanged2(FactionEntry const* factionEntry) { if (qInfo->GetRepObjectiveFaction2() == factionEntry->ID) { - QuestStatusData& q_status = mQuestStatus[questid]; + QuestStatusData& q_status = m_QuestStatus[questid]; if (q_status.m_status == QUEST_STATUS_INCOMPLETE) { if (GetReputationMgr().GetReputation(factionEntry) >= qInfo->GetRepObjectiveValue2()) @@ -15693,8 +15696,8 @@ bool Player::HasQuestForItem(uint32 itemid) const if (questid == 0) continue; - QuestStatusMap::const_iterator qs_itr = mQuestStatus.find(questid); - if (qs_itr == mQuestStatus.end()) + QuestStatusMap::const_iterator qs_itr = m_QuestStatus.find(questid); + if (qs_itr == m_QuestStatus.end()) continue; QuestStatusData const& q_status = qs_itr->second; @@ -16578,6 +16581,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) // after spell load, learn rewarded spell if need also _LoadQuestStatus(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS)); + _LoadQuestStatusRewarded(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADQUESTSTATUSREW)); _LoadDailyQuestStatus(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS)); _LoadWeeklyQuestStatus(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADWEKLYQUESTSTATUS)); _LoadRandomBGStatus(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADRANDOMBG)); @@ -17240,12 +17244,10 @@ void Player::LoadPet() void Player::_LoadQuestStatus(PreparedQueryResult result) { - mQuestStatus.clear(); - uint16 slot = 0; - //// 0 1 2 3 4 5 6 7 8 9 10 11 12 - //QueryResult *result = CharacterDatabase.PQuery("SELECT quest, status, rewarded, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, itemcount1, itemcount2, itemcount3, itemcount4 FROM character_queststatus WHERE guid = '%u'", GetGUIDLow()); + //// 0 1 3 4 5 6 7 8 9 10 11 12 + //QueryResult *result = CharacterDatabase.PQuery("SELECT quest, status, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, itemcount1, itemcount2, itemcount3, itemcount4 FROM character_queststatus WHERE guid = '%u'", GetGUIDLow()); if (result) { @@ -17259,23 +17261,22 @@ void Player::_LoadQuestStatus(PreparedQueryResult result) if (pQuest) { // find or create - QuestStatusData& questStatusData = mQuestStatus[quest_id]; + QuestStatusData& questStatusData = m_QuestStatus[quest_id]; uint8 qstatus = fields[1].GetUInt8(); if (qstatus < MAX_QUEST_STATUS) questStatusData.m_status = QuestStatus(qstatus); else { - questStatusData.m_status = QUEST_STATUS_NONE; - sLog->outError("Player %s have invalid quest %d status (%u), replaced by QUEST_STATUS_NONE(0).",GetName(),quest_id,qstatus); + questStatusData.m_status = QUEST_STATUS_INCOMPLETE; + sLog->outError("Player %s have invalid quest %d status (%u), replaced by QUEST_STATUS_INCOMPLETE(3).",GetName(),quest_id,qstatus); } - questStatusData.m_rewarded = (fields[2].GetUInt8() > 0); - questStatusData.m_explored = (fields[3].GetUInt8() > 0); + questStatusData.m_explored = (fields[2].GetUInt8() > 0); - time_t quest_time = time_t(fields[4].GetUInt64()); + time_t quest_time = time_t(fields[3].GetUInt64()); - if (pQuest->HasFlag(QUEST_TRINITY_FLAGS_TIMED) && !GetQuestRewardStatus(quest_id) && questStatusData.m_status != QUEST_STATUS_NONE) + if (pQuest->HasFlag(QUEST_TRINITY_FLAGS_TIMED) && !GetQuestRewardStatus(quest_id)) { AddTimedQuest(quest_id); @@ -17287,30 +17288,23 @@ void Player::_LoadQuestStatus(PreparedQueryResult result) else quest_time = 0; - questStatusData.m_creatureOrGOcount[0] = fields[5].GetUInt16(); - questStatusData.m_creatureOrGOcount[1] = fields[6].GetUInt16(); - questStatusData.m_creatureOrGOcount[2] = fields[7].GetUInt16(); - questStatusData.m_creatureOrGOcount[3] = fields[8].GetUInt16(); - questStatusData.m_itemcount[0] = fields[9].GetUInt16(); - questStatusData.m_itemcount[1] = fields[10].GetUInt16(); - questStatusData.m_itemcount[2] = fields[11].GetUInt16(); - questStatusData.m_itemcount[3] = fields[12].GetUInt16(); - - questStatusData.uState = QUEST_UNCHANGED; + questStatusData.m_creatureOrGOcount[0] = fields[4].GetUInt16(); + questStatusData.m_creatureOrGOcount[1] = fields[5].GetUInt16(); + questStatusData.m_creatureOrGOcount[2] = fields[6].GetUInt16(); + questStatusData.m_creatureOrGOcount[3] = fields[7].GetUInt16(); + questStatusData.m_itemcount[0] = fields[8].GetUInt16(); + questStatusData.m_itemcount[1] = fields[9].GetUInt16(); + questStatusData.m_itemcount[2] = fields[10].GetUInt16(); + questStatusData.m_itemcount[3] = fields[11].GetUInt16(); // add to quest log - if (slot < MAX_QUEST_LOG_SIZE && - ((questStatusData.m_status == QUEST_STATUS_INCOMPLETE || - questStatusData.m_status == QUEST_STATUS_COMPLETE || - questStatusData.m_status == QUEST_STATUS_FAILED) && - (!questStatusData.m_rewarded || pQuest->IsRepeatable()))) + if (slot < MAX_QUEST_LOG_SIZE) { SetQuestSlot(slot, quest_id, uint32(quest_time)); // cast can't be helped if (questStatusData.m_status == QUEST_STATUS_COMPLETE) SetQuestSlotState(slot, QUEST_STATE_COMPLETE); - - if (questStatusData.m_status == QUEST_STATUS_FAILED) + else if (questStatusData.m_status == QUEST_STATUS_FAILED) SetQuestSlotState(slot, QUEST_STATE_FAIL); for (uint8 idx = 0; idx < QUEST_OBJECTIVES_COUNT; ++idx) @@ -17320,22 +17314,6 @@ void Player::_LoadQuestStatus(PreparedQueryResult result) ++slot; } - if (questStatusData.m_rewarded) - { - // learn rewarded spell if unknown - learnQuestRewardedSpells(pQuest); - - // set rewarded title if any - if (pQuest->GetCharTitleId()) - { - if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId())) - SetTitle(titleEntry); - } - - if (pQuest->GetBonusTalents()) - m_questRewardTalentCount += pQuest->GetBonusTalents(); - } - sLog->outDebug("Quest status is {%u} for quest {%u} for player (GUID: %u)", questStatusData.m_status, quest_id, GetGUIDLow()); } } @@ -17347,6 +17325,41 @@ void Player::_LoadQuestStatus(PreparedQueryResult result) SetQuestSlot(i, 0); } +void Player::_LoadQuestStatusRewarded(PreparedQueryResult result) +{ + // SELECT quest FROM character_queststatus_rewarded WHERE guid = ? + + if (result) + { + do + { + Field* fields = result->Fetch(); + + uint32 quest_id = fields[0].GetUInt32(); + // used to be new, no delete? + Quest const* pQuest = sObjectMgr->GetQuestTemplate(quest_id); + if (pQuest) + { + // learn rewarded spell if unknown + learnQuestRewardedSpells(pQuest); + + // set rewarded title if any + if (pQuest->GetCharTitleId()) + { + if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId())) + SetTitle(titleEntry); + } + + if (pQuest->GetBonusTalents()) + m_questRewardTalentCount += pQuest->GetBonusTalents(); + } + + m_RewardedQuests.insert(quest_id); + } + while (result->NextRow()); + } +} + void Player::_LoadDailyQuestStatus(PreparedQueryResult result) { for (uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx) @@ -18316,25 +18329,36 @@ void Player::_SaveMail(SQLTransaction& trans) void Player::_SaveQuestStatus(SQLTransaction& trans) { - // we don't need transactions here. - for (QuestStatusMap::iterator i = mQuestStatus.begin(); i != mQuestStatus.end(); ++i) + QuestStatusSaveMap::iterator saveItr; + QuestStatusMap::iterator statusItr; + + for (saveItr = m_QuestStatusSave.begin(); saveItr != m_QuestStatusSave.end(); ++saveItr) { - switch (i->second.uState) + if (saveItr->second) { - case QUEST_NEW : - trans->PAppend("INSERT INTO character_queststatus (guid,quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4) " - "VALUES ('%u', '%u', '%u', '%u', '%u', '" UI64FMTD "', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", - GetGUIDLow(), i->first, i->second.m_status, i->second.m_rewarded, i->second.m_explored, uint64(i->second.m_timer / IN_MILLISECONDS+ sWorld->GetGameTime()), i->second.m_creatureOrGOcount[0], i->second.m_creatureOrGOcount[1], i->second.m_creatureOrGOcount[2], i->second.m_creatureOrGOcount[3], i->second.m_itemcount[0], i->second.m_itemcount[1], i->second.m_itemcount[2], i->second.m_itemcount[3]); - break; - case QUEST_CHANGED : - trans->PAppend("UPDATE character_queststatus SET status = '%u',rewarded = '%u',explored = '%u',timer = '" UI64FMTD "',mobcount1 = '%u',mobcount2 = '%u',mobcount3 = '%u',mobcount4 = '%u',itemcount1 = '%u',itemcount2 = '%u',itemcount3 = '%u',itemcount4 = '%u' WHERE guid = '%u' AND quest = '%u' ", - i->second.m_status, i->second.m_rewarded, i->second.m_explored, uint64(i->second.m_timer / IN_MILLISECONDS + sWorld->GetGameTime()), i->second.m_creatureOrGOcount[0], i->second.m_creatureOrGOcount[1], i->second.m_creatureOrGOcount[2], i->second.m_creatureOrGOcount[3], i->second.m_itemcount[0], i->second.m_itemcount[1], i->second.m_itemcount[2], i->second.m_itemcount[3], GetGUIDLow(), i->first); - break; - case QUEST_UNCHANGED: - break; - }; - i->second.uState = QUEST_UNCHANGED; + statusItr = m_QuestStatus.find(saveItr->first); + if (statusItr != m_QuestStatus.end() && statusItr->second.m_status != QUEST_STATUS_NONE) + { + trans->PAppend("REPLACE INTO character_queststatus (guid,quest,status,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4) " + "VALUES ('%u', '%u', '%u', '%u', '" UI64FMTD "', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", + GetGUIDLow(), statusItr->first, statusItr->second.m_status, statusItr->second.m_explored, uint64(statusItr->second.m_timer / IN_MILLISECONDS+ sWorld->GetGameTime()), statusItr->second.m_creatureOrGOcount[0], statusItr->second.m_creatureOrGOcount[1], statusItr->second.m_creatureOrGOcount[2], statusItr->second.m_creatureOrGOcount[3], statusItr->second.m_itemcount[0], statusItr->second.m_itemcount[1], statusItr->second.m_itemcount[2], statusItr->second.m_itemcount[3]); + } + } + else + trans->PAppend("DELETE FROM character_queststatus WHERE guid = %u AND quest = %u", GetGUIDLow(), saveItr->first); + } + + m_QuestStatusSave.clear(); + + for (saveItr = m_RewardedQuestsSave.begin(); saveItr != m_RewardedQuestsSave.end(); ++saveItr) + { + if (saveItr->second) + trans->PAppend("INSERT IGNORE INTO character_queststatus_rewarded (guid, quest) VALUES (%u, %u)", GetGUIDLow(), *saveItr); + else + trans->PAppend("DELETE FROM character_queststatus_rewarded WHERE guid = %u AND quest = %u", GetGUIDLow(), *saveItr); } + + m_RewardedQuestsSave.clear(); } void Player::_SaveDailyQuestStatus(SQLTransaction& trans) @@ -21305,13 +21329,9 @@ void Player::learnQuestRewardedSpells(Quest const* quest) void Player::learnQuestRewardedSpells() { // learn spells received from quest completing - for (QuestStatusMap::const_iterator itr = mQuestStatus.begin(); itr != mQuestStatus.end(); ++itr) + for (RewardedQuestSet::const_iterator itr = m_RewardedQuests.begin(); itr != m_RewardedQuests.end(); ++itr) { - // skip no rewarded quests - if (!itr->second.m_rewarded) - continue; - - Quest const* quest = sObjectMgr->GetQuestTemplate(itr->first); + Quest const* quest = sObjectMgr->GetQuestTemplate(*itr); if (!quest) continue; @@ -21524,8 +21544,8 @@ bool Player::HasQuestForGO(int32 GOId) const if (questid == 0) continue; - QuestStatusMap::const_iterator qs_itr = mQuestStatus.find(questid); - if (qs_itr == mQuestStatus.end()) + QuestStatusMap::const_iterator qs_itr = m_QuestStatus.find(questid); + if (qs_itr == m_QuestStatus.end()) continue; QuestStatusData const& qs = qs_itr->second; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index aa1d92e4184..18c13622b8a 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -505,6 +505,10 @@ enum AtLoginFlags }; typedef std::map<uint32, QuestStatusData> QuestStatusMap; +typedef std::set<uint32> RewardedQuestSet; + +// quest, keep +typedef std::map<uint32, bool> QuestStatusSaveMap; enum QuestSlotOffsets { @@ -789,7 +793,8 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOADRANDOMBG = 27, PLAYER_LOGIN_QUERY_LOADARENASTATS = 28, PLAYER_LOGIN_QUERY_LOADBANNED = 29, - MAX_PLAYER_LOGIN_QUERY = 30 + PLAYER_LOGIN_QUERY_LOADQUESTSTATUSREW = 30, + MAX_PLAYER_LOGIN_QUERY = 31 }; enum PlayerDelayedOperations @@ -1335,6 +1340,7 @@ class Player : public Unit, public GridObject<Player> bool GetQuestRewardStatus(uint32 quest_id) const; QuestStatus GetQuestStatus(uint32 quest_id) const; void SetQuestStatus(uint32 quest_id, QuestStatus status); + void RemoveQuest(uint32 quest_id); void SetDailyQuestStatus(uint32 quest_id); void SetWeeklyQuestStatus(uint32 quest_id); @@ -1473,7 +1479,8 @@ class Player : public Unit, public GridObject<Player> UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED); } - QuestStatusMap& getQuestStatusMap() { return mQuestStatus; }; + RewardedQuestSet& getRewardedQuests() { return m_RewardedQuests; } + QuestStatusMap& getQuestStatusMap() { return m_QuestStatus; }; const uint64& GetSelection() const { return m_curSelection; } Unit *GetSelectedUnit() const; @@ -2422,6 +2429,7 @@ class Player : public Unit, public GridObject<Player> void _LoadMail(); void _LoadMailedItems(Mail *mail); void _LoadQuestStatus(PreparedQueryResult result); + void _LoadQuestStatusRewarded(PreparedQueryResult result); void _LoadDailyQuestStatus(PreparedQueryResult result); void _LoadWeeklyQuestStatus(PreparedQueryResult result); void _LoadRandomBGStatus(PreparedQueryResult result); @@ -2499,7 +2507,11 @@ class Player : public Unit, public GridObject<Player> uint64 m_comboTarget; int8 m_comboPoints; - QuestStatusMap mQuestStatus; + QuestStatusMap m_QuestStatus; + QuestStatusSaveMap m_QuestStatusSave; + + RewardedQuestSet m_RewardedQuests; + QuestStatusSaveMap m_RewardedQuestsSave; SkillStatusMap mSkillStatus; diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 3f4b886f218..a9a47b5f2c8 100755 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -351,30 +351,18 @@ class Quest uint32 QuestCompleteScript; }; -enum QuestUpdateState -{ - QUEST_UNCHANGED = 0, - QUEST_CHANGED = 1, - QUEST_NEW = 2 -}; - struct QuestStatusData { - QuestStatusData() - : m_status(QUEST_STATUS_NONE),m_rewarded(false), - m_explored(false), m_timer(0), uState(QUEST_NEW) + QuestStatusData(): m_status(QUEST_STATUS_NONE), m_explored(false), m_timer(0) { memset(m_itemcount, 0, QUEST_ITEM_OBJECTIVES_COUNT * sizeof(uint16)); memset(m_creatureOrGOcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint16)); } + uint32 m_timer; + uint16 m_itemcount[QUEST_ITEM_OBJECTIVES_COUNT]; + uint16 m_creatureOrGOcount[QUEST_OBJECTIVES_COUNT]; QuestStatus m_status; - bool m_rewarded; bool m_explored; - uint32 m_timer; - QuestUpdateState uState; - - uint16 m_itemcount[ QUEST_ITEM_OBJECTIVES_COUNT ]; - uint16 m_creatureOrGOcount[ QUEST_OBJECTIVES_COUNT ]; }; #endif diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp index ec1ace4fffc..a07756f4c6d 100755 --- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp @@ -186,6 +186,10 @@ bool LoginQueryHolder::Initialize() stmt->setUInt32(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADBANNED, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_PLAYER_QUESTSTATUSREW); + stmt->setUInt32(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUSREW, stmt); + return res; } @@ -1636,7 +1640,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) } // Delete all current quests - trans->PAppend("DELETE FROM `character_queststatus` WHERE `status` = 3 AND guid ='%u'",GUID_LOPART(guid)); + trans->PAppend("DELETE FROM `character_queststatus` WHERE guid ='%u'",GUID_LOPART(guid)); // Delete record of the faction old completed quests { @@ -1668,7 +1672,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) questsStr = questsStr.substr(0, questsStr.length() - 1); if (!questsStr.empty()) - trans->PAppend("DELETE FROM `character_queststatus` WHERE guid='%u' AND quest IN (%s)", lowGuid, questsStr.c_str()); + trans->PAppend("DELETE FROM `character_queststatus_rewarded` WHERE guid='%u' AND quest IN (%s)", lowGuid, questsStr.c_str()); } if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD)) diff --git a/src/server/game/Server/Protocol/Handlers/QuestHandler.cpp b/src/server/game/Server/Protocol/Handlers/QuestHandler.cpp index d55d1ba4293..cac8bea49c6 100755 --- a/src/server/game/Server/Protocol/Handlers/QuestHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/QuestHandler.cpp @@ -409,7 +409,7 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recv_data) } _player->TakeQuestSourceItem(quest, true); // remove quest src item from player - _player->SetQuestStatus(quest, QUEST_STATUS_NONE); + _player->RemoveQuest(quest); _player->GetAchievementMgr().RemoveTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, quest); } @@ -654,7 +654,7 @@ uint32 WorldSession::getDialogStatus(Player *pPlayer, Object* questgiver, uint32 { if (pPlayer->SatisfyQuestLevel(pQuest, false)) { - if (pQuest->IsAutoComplete() || (pQuest->IsRepeatable() && pPlayer->getQuestStatusMap()[quest_id].m_rewarded)) + if (pQuest->IsAutoComplete() || (pQuest->IsRepeatable() && pPlayer->getRewardedQuests().find(quest_id) != pPlayer->getRewardedQuests().end())) result2 = DIALOG_STATUS_REWARD_REP; else if (pPlayer->getLevel() <= ((pPlayer->GetQuestLevel(pQuest) == -1) ? pPlayer->getLevel() : pPlayer->GetQuestLevel(pQuest) + sWorld->getIntConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF))) { @@ -731,19 +731,11 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket void WorldSession::HandleQueryQuestsCompleted(WorldPacket & /*recv_data*/) { - uint32 count = 0; + WorldPacket data(SMSG_QUERY_QUESTS_COMPLETED_RESPONSE, 4+4*_player->getRewardedQuests().size()); + data << uint32(_player->getRewardedQuests().size()); - WorldPacket data(SMSG_QUERY_QUESTS_COMPLETED_RESPONSE, 4+4*count); - data << uint32(count); + for (RewardedQuestSet::const_iterator itr = _player->getRewardedQuests().begin(); itr != _player->getRewardedQuests().end(); ++itr) + data << uint32(*itr); - for (QuestStatusMap::const_iterator itr = _player->getQuestStatusMap().begin(); itr != _player->getQuestStatusMap().end(); ++itr) - { - if (itr->second.m_rewarded) - { - data << uint32(itr->first); - count++; - } - } - data.put<uint32>(0, count); SendPacket(&data); } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index b738be64465..60d3fe5704c 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -6116,12 +6116,7 @@ void Spell::EffectQuestClear(SpellEffIndex effIndex) } } - // set quest status to not started (will be updated in DB at next save) - pPlayer->SetQuestStatus(quest_id, QUEST_STATUS_NONE); - - // reset rewarded for restart repeatable quest - QuestStatusData &data = qs_itr->second; - data.m_rewarded = false; + pPlayer->RemoveQuest(quest_id); } void Spell::EffectSendTaxi(SpellEffIndex effIndex) diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index 821e5e6afe4..cd9358f9ca4 100755 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -24,7 +24,7 @@ #include "ObjectMgr.h" #include "AccountMgr.h" -#define DUMP_TABLE_COUNT 26 +#define DUMP_TABLE_COUNT 27 struct DumpTable { char const* name; @@ -48,6 +48,7 @@ static DumpTable dumpTables[DUMP_TABLE_COUNT] = { "character_pet", DTT_PET }, { "character_pet_declinedname", DTT_PET }, { "character_queststatus", DTT_CHAR_TABLE }, + { "character_queststatus_rewarded", DTT_CHAR_TABLE }, { "character_reputation", DTT_CHAR_TABLE }, { "character_skills", DTT_CHAR_TABLE }, { "character_spell", DTT_CHAR_TABLE }, diff --git a/src/server/game/Tools/PlayerDump.h b/src/server/game/Tools/PlayerDump.h index bfb9bbd2120..b6544504b85 100755 --- a/src/server/game/Tools/PlayerDump.h +++ b/src/server/game/Tools/PlayerDump.h @@ -29,8 +29,8 @@ enum DumpTableType DTT_CHAR_TABLE, // // character_achievement, character_achievement_progress, // character_action, character_aura, character_homebind, - // character_queststatus, character_reputation, character_spell, - // character_spell_cooldown, character_ticket, character_talent, + // character_queststatus, character_queststatus_rewarded, character_reputation, + // character_spell, character_spell_cooldown, character_ticket, character_talent, // character_tutorial DTT_EQSET_TABLE, // <- guid // character_equipmentsets diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp index a083b62f973..25bfc1c6f45 100644 --- a/src/server/scripts/Commands/cs_quest.cpp +++ b/src/server/scripts/Commands/cs_quest.cpp @@ -142,11 +142,7 @@ public: } } - // set quest status to not started (will updated in DB at next save) - player->SetQuestStatus(entry, QUEST_STATUS_NONE); - - // reset rewarded for restart repeatable quest - player->getQuestStatusMap()[entry].m_rewarded = false; + player->RemoveQuest(entry); handler->SendSysMessage(LANG_COMMAND_QUEST_REMOVED); return true; diff --git a/src/server/scripts/Kalimdor/silithus.cpp b/src/server/scripts/Kalimdor/silithus.cpp index 4971000fa09..53d47072e51 100644 --- a/src/server/scripts/Kalimdor/silithus.cpp +++ b/src/server/scripts/Kalimdor/silithus.cpp @@ -1023,7 +1023,6 @@ public: if (!GroupMember->IsWithinDistInMap(me, EVENT_AREA_RADIUS) && GroupMember->GetQuestStatus(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD) == QUEST_STATUS_INCOMPLETE) { GroupMember->FailQuest(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD); - GroupMember->SetQuestStatus(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD, QUEST_STATUS_NONE); ++FailedMemberCount; } ++GroupMemberCount; diff --git a/src/server/scripts/Outland/shadowmoon_valley.cpp b/src/server/scripts/Outland/shadowmoon_valley.cpp index f4d6cd4a687..d98a90d6b33 100644 --- a/src/server/scripts/Outland/shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/shadowmoon_valley.cpp @@ -1464,7 +1464,6 @@ public: if (!GroupMember->IsWithinDistInMap(me, EVENT_AREA_RADIUS) && GroupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE) { GroupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); - GroupMember->SetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, QUEST_STATUS_NONE); ++FailedMemberCount; } ++GroupMemberCount; @@ -1489,7 +1488,6 @@ public: if (GroupMember && GroupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE) { GroupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); - GroupMember->SetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, QUEST_STATUS_NONE); } } Failed = true; diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 598223415c0..9189e33ffb8 100755 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -60,7 +60,7 @@ bool CharacterDatabaseConnection::Open() PrepareStatement(CHAR_LOAD_PLAYER_AURAS, "SELECT caster_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, " "base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges FROM character_aura WHERE guid = ?", true); PrepareStatement(CHAR_LOAD_PLAYER_SPELLS, "SELECT spell, active, disabled FROM character_spell WHERE guid = ?", true); - PrepareStatement(CHAR_LOAD_PLAYER_QUESTSTATUS, "SELECT quest, status, rewarded, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, " + PrepareStatement(CHAR_LOAD_PLAYER_QUESTSTATUS, "SELECT quest, status, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, " "itemcount1, itemcount2, itemcount3, itemcount4 FROM character_queststatus WHERE guid = ?", true); PrepareStatement(CHAR_LOAD_PLAYER_DAILYQUESTSTATUS, "SELECT quest, time FROM character_queststatus_daily WHERE guid = ?", true); PrepareStatement(CHAR_LOAD_PLAYER_WEKLYQUESTSTATUS, "SELECT quest FROM character_queststatus_weekly WHERE guid = ?", true); @@ -88,6 +88,7 @@ bool CharacterDatabaseConnection::Open() PrepareStatement(CHAR_LOAD_PLAYER_RANDOMBG, "SELECT guid FROM character_battleground_random WHERE guid = ?", true); PrepareStatement(CHAR_LOAD_PLAYER_ARENASTATS, "SELECT slot, personal_rating, matchmaker_rating FROM character_arena_stats WHERE guid = ? ORDER BY slot ASC", true); PrepareStatement(CHAR_LOAD_PLAYER_BANNED, "SELECT guid FROM character_banned WHERE guid = ? AND active = 1", true); + PrepareStatement(CHAR_LOAD_PLAYER_QUESTSTATUSREW, "SELECT quest FROM character_queststatus_rewarded WHERE guid = ?", true); // End LoginQueryHolder content PrepareStatement(CHAR_LOAD_PLAYER_ACTIONS_SPEC, "SELECT button, action, type FROM character_action WHERE guid = ? AND spec = ? ORDER BY button"); @@ -259,6 +260,6 @@ bool CharacterDatabaseConnection::Open() PrepareStatement(CHAR_DEL_AURA, "DELETE FROM character_aura WHERE guid = ?", true); PrepareStatement(CHAR_ADD_AURA, "INSERT INTO character_aura (guid,caster_guid,item_guid,spell,effect_mask,recalculate_mask,stackcount,amount0,amount1,amount2,base_amount0,base_amount1,base_amount2,maxduration,remaintime,remaincharges) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", true); - + return true; } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index 3d203bf67e3..560a805ba15 100755 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -91,6 +91,7 @@ enum CharacterDatabaseStatements CHAR_LOAD_PLAYER_RANDOMBG, CHAR_LOAD_PLAYER_ARENASTATS, CHAR_LOAD_PLAYER_BANNED, + CHAR_LOAD_PLAYER_QUESTSTATUSREW, CHAR_LOAD_ACCOUNT_DATA, CHAR_LOAD_PLAYER_MAILITEMS, CHAR_LOAD_AUCTION_ITEMS, |