aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlinencloth <none@none>2010-12-26 04:16:18 +0100
committerlinencloth <none@none>2010-12-26 04:16:18 +0100
commitb150172521636fa5646489688e53d03f0773b9be (patch)
treeb078947617c1deead6699123567e8beabdb2477b
parent8fdbe7c4e69f5b0a8eb907aa76cc2afd2b297cd3 (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.sql9
-rw-r--r--sql/updates/10828_characters_character_queststatus.sql13
-rwxr-xr-xsrc/server/game/Achievements/AchievementMgr.cpp12
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp348
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h18
-rwxr-xr-xsrc/server/game/Quests/QuestDef.h20
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/CharacterHandler.cpp8
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/QuestHandler.cpp20
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp7
-rwxr-xr-xsrc/server/game/Tools/PlayerDump.cpp3
-rwxr-xr-xsrc/server/game/Tools/PlayerDump.h4
-rw-r--r--src/server/scripts/Commands/cs_quest.cpp6
-rw-r--r--src/server/scripts/Kalimdor/silithus.cpp1
-rw-r--r--src/server/scripts/Outland/shadowmoon_valley.cpp2
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.cpp5
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.h1
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,