aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShocker <shocker@freakz.ro>2012-01-04 13:11:34 -0800
committerShocker <shocker@freakz.ro>2012-01-04 13:11:34 -0800
commit8d7f77eb00000cb1c83b246214672f6b04a23d0f (patch)
tree2e4175a7125bae58f29007751171e24372202346
parentde2bcb1caa8a8de77e5b14eae66622f57f6ac98b (diff)
parent46fb199ee1c5d27ea79f65d63f6fd8dbe29612c6 (diff)
Merge pull request #4616 from kandera/fix_seasonal_quest_reset
Core/Quests: Add implementation of seasonal quest reset
-rw-r--r--sql/updates/world/2012_01_03_00_world_game_event_seasonal_questrelation.sql387
-rw-r--r--sql/updates/world/2012_01_03_01_characters_character_queststatus_seasonal.sql8
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp125
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h12
-rwxr-xr-xsrc/server/game/Events/GameEventMgr.cpp43
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.h5
-rwxr-xr-xsrc/server/game/Quests/QuestDef.cpp1
-rwxr-xr-xsrc/server/game/Quests/QuestDef.h5
-rw-r--r--[-rwxr-xr-x]src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp8
-rwxr-xr-xsrc/server/game/World/World.cpp11
-rwxr-xr-xsrc/server/game/World/World.h1
-rw-r--r--[-rwxr-xr-x]src/server/shared/Database/Implementation/CharacterDatabase.cpp10
-rw-r--r--[-rwxr-xr-x]src/server/shared/Database/Implementation/CharacterDatabase.h10
13 files changed, 608 insertions, 18 deletions
diff --git a/sql/updates/world/2012_01_03_00_world_game_event_seasonal_questrelation.sql b/sql/updates/world/2012_01_03_00_world_game_event_seasonal_questrelation.sql
new file mode 100644
index 00000000000..b4ff9c1da5e
--- /dev/null
+++ b/sql/updates/world/2012_01_03_00_world_game_event_seasonal_questrelation.sql
@@ -0,0 +1,387 @@
+DROP TABLE IF EXISTS `game_event_seasonal_questrelation`;
+CREATE TABLE `game_event_seasonal_questrelation` (
+ `quest` mediumint(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier',
+ `event` mediumint(10) NOT NULL DEFAULT '0' COMMENT 'Quest Identifier',
+ PRIMARY KEY (`quest`,`event`),
+ KEY `idx_quest` (`quest`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
+
+INSERT INTO `game_event_seasonal_questrelation` (`quest`,`event`) VALUES
+ (1657, 12),
+ (1658, 12),
+ (6961, 2),
+ (6962, 2),
+ (6963, 2),
+ (6964, 2),
+ (6983, 3),
+ (6984, 3),
+ (7021, 2),
+ (7022, 2),
+ (7023, 2),
+ (7024, 2),
+ (7025, 2),
+ (7042, 2),
+ (7043, 2),
+ (7045, 2),
+ (7061, 2),
+ (7062, 2),
+ (7063, 2),
+ (8149, 11),
+ (8150, 11),
+ (8311, 12),
+ (8312, 12),
+ (8322, 12),
+ (8353, 12),
+ (8354, 12),
+ (8355, 12),
+ (8356, 12),
+ (8357, 12),
+ (8358, 12),
+ (8359, 12),
+ (8360, 12),
+ (8373, 12),
+ (8409, 12),
+ (8744, 52),
+ (8746, 2),
+ (8762, 2),
+ (8763, 2),
+ (8767, 52),
+ (8768, 52),
+ (8769, 52),
+ (8788, 52),
+ (8799, 2),
+ (8803, 52),
+ (8827, 2),
+ (8828, 2),
+ (8860, 6),
+ (8861, 6),
+ (8868, 7),
+ (8897, 8),
+ (8898, 8),
+ (8899, 8),
+ (8900, 8),
+ (8901, 8),
+ (8902, 8),
+ (8903, 8),
+ (8904, 8),
+ (8971, -1),
+ (8972, -1),
+ (8973, -1),
+ (8974, -1),
+ (8975, -1),
+ (8976, -1),
+ (8979, 8),
+ (8980, 8),
+ (8981, 8),
+ (8982, 8),
+ (8983, 8),
+ (8984, 8),
+ (8993, 8),
+ (9024, 8),
+ (9025, 8),
+ (9026, 8),
+ (9027, 8),
+ (9028, 8),
+ (11131, 12),
+ (11135, 12),
+ (11219, 12),
+ (11220, 12),
+ (11242, 12),
+ (11356, 12),
+ (11357, 12),
+ (11360, 12),
+ (11361, 12),
+ (11392, 12),
+ (11401, 12),
+ (11403, 12),
+ (11404, 12),
+ (11405, 12),
+ (11435, 12),
+ (11439, 12),
+ (11440, 12),
+ (11449, 12),
+ (11450, 12),
+ (11528, 52),
+ (11558, 8),
+ (11580, 1),
+ (11581, 1),
+ (11583, 1),
+ (11584, 1),
+ (11696, 1),
+ (11732, 1),
+ (11734, 1),
+ (11735, 1),
+ (11736, 1),
+ (11737, 1),
+ (11738, 1),
+ (11739, 1),
+ (11740, 1),
+ (11741, 1),
+ (11742, 1),
+ (11743, 1),
+ (11744, 1),
+ (11745, 1),
+ (11746, 1),
+ (11747, 1),
+ (11748, 1),
+ (11749, 1),
+ (11750, 1),
+ (11751, 1),
+ (11752, 1),
+ (11753, 1),
+ (11754, 1),
+ (11755, 1),
+ (11756, 1),
+ (11757, 1),
+ (11758, 1),
+ (11759, 1),
+ (11760, 1),
+ (11761, 1),
+ (11762, 1),
+ (11763, 1),
+ (11764, 1),
+ (11765, 1),
+ (11766, 1),
+ (11767, 1),
+ (11768, 1),
+ (11769, 1),
+ (11770, 1),
+ (11771, 1),
+ (11772, 1),
+ (11773, 1),
+ (11774, 1),
+ (11775, 1),
+ (11776, 1),
+ (11777, 1),
+ (11778, 1),
+ (11779, 1),
+ (11780, 1),
+ (11781, 1),
+ (11782, 1),
+ (11783, 1),
+ (11784, 1),
+ (11785, 1),
+ (11786, 1),
+ (11787, 1),
+ (11799, 1),
+ (11800, 1),
+ (11801, 1),
+ (11802, 1),
+ (11803, 1),
+ (11804, 1),
+ (11805, 1),
+ (11806, 1),
+ (11807, 1),
+ (11808, 1),
+ (11809, 1),
+ (11810, 1),
+ (11811, 1),
+ (11812, 1),
+ (11813, 1),
+ (11814, 1),
+ (11815, 1),
+ (11816, 1),
+ (11817, 1),
+ (11818, 1),
+ (11819, 1),
+ (11820, 1),
+ (11821, 1),
+ (11822, 1),
+ (11823, 1),
+ (11824, 1),
+ (11825, 1),
+ (11826, 1),
+ (11827, 1),
+ (11828, 1),
+ (11829, 1),
+ (11830, 1),
+ (11831, 1),
+ (11832, 1),
+ (11833, 1),
+ (11834, 1),
+ (11835, 1),
+ (11836, 1),
+ (11837, 1),
+ (11838, 1),
+ (11839, 1),
+ (11840, 1),
+ (11841, 1),
+ (11842, 1),
+ (11843, 1),
+ (11844, 1),
+ (11845, 1),
+ (11846, 1),
+ (11847, 1),
+ (11848, 1),
+ (11849, 1),
+ (11850, 1),
+ (11851, 1),
+ (11852, 1),
+ (11853, 1),
+ (11854, 1),
+ (11855, 1),
+ (11856, 1),
+ (11857, 1),
+ (11858, 1),
+ (11859, 1),
+ (11860, 1),
+ (11861, 1),
+ (11862, 1),
+ (11863, 1),
+ (11937, 1),
+ (11976, 1),
+ (12133, 12),
+ (12135, 12),
+ (12139, 12),
+ (12155, 12),
+ (12286, -1),
+ (12313, 24),
+ (12331, 12),
+ (12332, 12),
+ (12333, 12),
+ (12334, 12),
+ (12335, 12),
+ (12336, 12),
+ (12337, 12),
+ (12338, 12),
+ (12339, 12),
+ (12340, 12),
+ (12341, 12),
+ (12342, 12),
+ (12343, 12),
+ (12344, 12),
+ (12345, 12),
+ (12346, 12),
+ (12347, 12),
+ (12348, 12),
+ (12349, 12),
+ (12350, 12),
+ (12351, 12),
+ (12352, 12),
+ (12353, 12),
+ (12354, 12),
+ (12355, 12),
+ (12356, 12),
+ (12357, 12),
+ (12358, 12),
+ (12359, 12),
+ (12360, 12),
+ (12361, 12),
+ (12362, 12),
+ (12363, 12),
+ (12364, 12),
+ (12365, 12),
+ (12366, 12),
+ (12367, 12),
+ (12368, 12),
+ (12369, 12),
+ (12370, 12),
+ (12371, 12),
+ (12373, 12),
+ (12374, 12),
+ (12375, 12),
+ (12376, 12),
+ (12377, 12),
+ (12378, 12),
+ (12379, 12),
+ (12380, 12),
+ (12381, 12),
+ (12382, 12),
+ (12383, 12),
+ (12384, 12),
+ (12385, 12),
+ (12386, 12),
+ (12387, 12),
+ (12388, 12),
+ (12389, 12),
+ (12390, 12),
+ (12391, 12),
+ (12392, 12),
+ (12393, 12),
+ (12394, 12),
+ (12395, 12),
+ (12396, 12),
+ (12397, 12),
+ (12398, 12),
+ (12399, 12),
+ (12400, 12),
+ (12401, 12),
+ (12402, 12),
+ (12403, 12),
+ (12404, 12),
+ (12405, 12),
+ (12406, 12),
+ (12407, 12),
+ (12408, 12),
+ (12409, 12),
+ (12410, 12),
+ (12940, 12),
+ (12941, 12),
+ (12944, 12),
+ (12945, 12),
+ (12946, 12),
+ (12947, 12),
+ (12950, 12),
+ (13203, 52),
+ (13433, 12),
+ (13434, 12),
+ (13435, 12),
+ (13436, 12),
+ (13437, 12),
+ (13438, 12),
+ (13439, 12),
+ (13440, 12),
+ (13441, 12),
+ (13442, 12),
+ (13443, 12),
+ (13444, 12),
+ (13445, 12),
+ (13446, 12),
+ (13447, 12),
+ (13448, 12),
+ (13449, 12),
+ (13450, 12),
+ (13451, 12),
+ (13452, 12),
+ (13453, 12),
+ (13454, 12),
+ (13455, 12),
+ (13456, 12),
+ (13457, 12),
+ (13458, 12),
+ (13459, 12),
+ (13460, 12),
+ (13461, 12),
+ (13462, 12),
+ (13463, 12),
+ (13464, 12),
+ (13465, 12),
+ (13466, 12),
+ (13467, 12),
+ (13468, 12),
+ (13469, 12),
+ (13470, 12),
+ (13471, 12),
+ (13472, 12),
+ (13473, 12),
+ (13474, 12),
+ (13485, 1),
+ (13486, 1),
+ (13487, 1),
+ (13488, 1),
+ (13489, 1),
+ (13490, 1),
+ (13491, 1),
+ (13492, 1),
+ (13493, 1),
+ (13494, 1),
+ (13495, 1),
+ (13496, 1),
+ (13497, 1),
+ (13498, 1),
+ (13499, 1),
+ (13500, 1),
+ (13501, 12),
+ (13548, 12),
+ (13966, 52);
+
diff --git a/sql/updates/world/2012_01_03_01_characters_character_queststatus_seasonal.sql b/sql/updates/world/2012_01_03_01_characters_character_queststatus_seasonal.sql
new file mode 100644
index 00000000000..88264c424cc
--- /dev/null
+++ b/sql/updates/world/2012_01_03_01_characters_character_queststatus_seasonal.sql
@@ -0,0 +1,8 @@
+DROP TABLE IF EXISTS `character_queststatus_seasonal`;
+CREATE TABLE `character_queststatus_seasonal` (
+ `guid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier',
+ `quest` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Quest Identifier',
+ `event` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Event Identifier',
+ PRIMARY KEY (`guid`,`quest`),
+ KEY `idx_guid` (`guid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System'; \ No newline at end of file
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index c5c025c96df..6d6a8fd5071 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -14529,7 +14529,7 @@ bool Player::CanSeeStartQuest(Quest const* quest)
SatisfyQuestExclusiveGroup(quest, false) && SatisfyQuestReputation(quest, false) &&
SatisfyQuestPreviousQuest(quest, false) && SatisfyQuestNextChain(quest, false) &&
SatisfyQuestPrevChain(quest, false) && SatisfyQuestDay(quest, false) && SatisfyQuestWeek(quest, false) &&
- !DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this))
+ SatisfyQuestSeasonal(quest, false) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this))
{
return getLevel() + sWorld->getIntConfig(CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF) >= quest->GetMinLevel();
}
@@ -14545,7 +14545,7 @@ bool Player::CanTakeQuest(Quest const* quest, bool msg)
&& SatisfyQuestPreviousQuest(quest, msg) && SatisfyQuestTimed(quest, msg)
&& SatisfyQuestNextChain(quest, msg) && SatisfyQuestPrevChain(quest, msg)
&& SatisfyQuestDay(quest, msg) && SatisfyQuestWeek(quest, msg)
- && !DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this)
+ && SatisfyQuestSeasonal(quest,msg) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this)
&& SatisfyQuestConditions(quest, msg);
}
@@ -14669,7 +14669,7 @@ bool Player::CanRewardQuest(Quest const* quest, bool msg)
return false;
// daily quest can't be rewarded (25 daily quest already completed)
- if (!SatisfyQuestDay(quest, true) || !SatisfyQuestWeek(quest, true))
+ if (!SatisfyQuestDay(quest, true) || !SatisfyQuestWeek(quest, true) || !SatisfyQuestSeasonal(quest,true))
return false;
// rewarded and not repeatable quest (only cheating case, then ignore without message)
@@ -14978,6 +14978,8 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
}
else if (quest->IsWeekly())
SetWeeklyQuestStatus(quest_id);
+ else if (quest->IsSeasonal())
+ SetSeasonalQuestStatus(quest_id);
RemoveActiveQuest(quest_id);
m_RewardedQuests.insert(quest_id);
@@ -15333,7 +15335,7 @@ bool Player::SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg)
// not allow have daily quest if daily quest from exclusive group already recently completed
Quest const* Nquest = sObjectMgr->GetQuestTemplate(exclude_Id);
- if (!SatisfyQuestDay(Nquest, false) || !SatisfyQuestWeek(Nquest, false))
+ if (!SatisfyQuestDay(Nquest, false) || !SatisfyQuestWeek(Nquest, false) || !SatisfyQuestSeasonal(Nquest,false))
{
if (msg)
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
@@ -15342,7 +15344,7 @@ bool Player::SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg)
}
// alternative quest already started or completed - but don't check rewarded states if both are repeatable
- if (GetQuestStatus(exclude_Id) != QUEST_STATUS_NONE || (!(qInfo->IsRepeatable() && Nquest->IsRepeatable()) && m_RewardedQuests.find(exclude_Id) != m_RewardedQuests.end()))
+ if (GetQuestStatus(exclude_Id) != QUEST_STATUS_NONE || (!(qInfo->IsRepeatable() && Nquest->IsRepeatable()) && (m_RewardedQuests.find(exclude_Id) != m_RewardedQuests.end())))
{
if (msg)
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
@@ -15443,6 +15445,15 @@ bool Player::SatisfyQuestWeek(Quest const* qInfo, bool /*msg*/)
return m_weeklyquests.find(qInfo->GetQuestId()) == m_weeklyquests.end();
}
+bool Player::SatisfyQuestSeasonal(Quest const* qInfo, bool /*msg*/)
+{
+ if (!qInfo->IsSeasonal() || m_seasonalquests.empty())
+ return true;
+ if (m_seasonalquests.find(qInfo->GetSeasonalQuestEvent()) == m_seasonalquests.end()) return false;
+ // if not found in cooldown list
+ return m_seasonalquests[qInfo->GetSeasonalQuestEvent()].find(qInfo->GetQuestId()) == m_seasonalquests[qInfo->GetSeasonalQuestEvent()].end();
+}
+
bool Player::GiveQuestSourceItem(Quest const* quest)
{
uint32 srcitem = quest->GetSrcItemId();
@@ -16980,7 +16991,8 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
_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));
+ _LoadWeeklyQuestStatus(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADWEEKLYQUESTSTATUS));
+ _LoadSeasonalQuestStatus(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADSEASONALQUESTSTATUS));
_LoadRandomBGStatus(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADRANDOMBG));
// after spell and quest load
@@ -17846,6 +17858,29 @@ void Player::_LoadWeeklyQuestStatus(PreparedQueryResult result)
m_WeeklyQuestChanged = false;
}
+void Player::_LoadSeasonalQuestStatus(PreparedQueryResult result)
+{
+ m_seasonalquests.clear();
+
+ if (result)
+ {
+ do
+ {
+ uint32 quest_id = (*result)[0].GetUInt32();
+ uint16 event_id = (*result)[1].GetUInt16();
+ Quest const* quest = sObjectMgr->GetQuestTemplate(quest_id);
+ if (!quest)
+ continue;
+
+ m_seasonalquests[event_id].insert(quest_id);
+ sLog->outDebug(LOG_FILTER_PLAYER_LOADING, "Seasonal quest {%u} cooldown for player (GUID: %u)", quest_id, GetGUIDLow());
+ }
+ while (result->NextRow());
+ }
+
+ m_SeasonalQuestChanged = false;
+}
+
void Player::_LoadSpells(PreparedQueryResult result)
{
//QueryResult* result = CharacterDatabase.PQuery("SELECT spell, active, disabled FROM character_spell WHERE guid = '%u'", GetGUIDLow());
@@ -18572,6 +18607,7 @@ void Player::SaveToDB(bool create /*=false*/)
_SaveQuestStatus(trans);
_SaveDailyQuestStatus(trans);
_SaveWeeklyQuestStatus(trans);
+ _SaveSeasonalQuestStatus(trans);
_SaveTalents(trans);
_SaveSpells(trans);
_SaveSpellCooldowns(trans);
@@ -18910,18 +18946,28 @@ void Player::_SaveDailyQuestStatus(SQLTransaction& trans)
// save last daily quest time for all quests: we need only mostly reset time for reset check anyway
// we don't need transactions here.
- trans->PAppend("DELETE FROM character_queststatus_daily WHERE guid = '%u'", GetGUIDLow());
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_QUEST_STATUS_DAILY_CHAR);
+ stmt->setUInt32(0, GetGUIDLow());
+ trans->Append(stmt);
for (uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx)
if (GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx))
- trans->PAppend("INSERT INTO character_queststatus_daily (guid, quest, time) VALUES ('%u', '%u', '" UI64FMTD "')",
- GetGUIDLow(), GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx), uint64(m_lastDailyQuestTime));
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_DAILYQUESTSTATUS);
+ stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(1, GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx));
+ stmt->setUInt64(2, uint64(m_lastDailyQuestTime));
+ trans->Append(stmt);
+ }
if (!m_DFQuests.empty())
{
for (DFQuestsDoneList::iterator itr = m_DFQuests.begin(); itr != m_DFQuests.end(); ++itr)
{
- trans->PAppend("INSERT INTO character_queststatus_daily (guid, quest, time) VALUES ('%u', '%u', '" UI64FMTD "')",
- GetGUIDLow(), (*itr), uint64(m_lastDailyQuestTime));
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_DAILYQUESTSTATUS);
+ stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(1, (*itr));
+ stmt->setUInt64(2, uint64(m_lastDailyQuestTime));
+ trans->Append(stmt);
}
}
}
@@ -18932,18 +18978,51 @@ void Player::_SaveWeeklyQuestStatus(SQLTransaction& trans)
return;
// we don't need transactions here.
- trans->PAppend("DELETE FROM character_queststatus_weekly WHERE guid = '%u'", GetGUIDLow());
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_QUEST_STATUS_WEEKLY_CHAR);
+ stmt->setUInt32(0, GetGUIDLow());
+ trans->Append(stmt);
for (QuestSet::const_iterator iter = m_weeklyquests.begin(); iter != m_weeklyquests.end(); ++iter)
{
uint32 quest_id = *iter;
- trans->PAppend("INSERT INTO character_queststatus_weekly (guid, quest) VALUES ('%u', '%u')", GetGUIDLow(), quest_id);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS);
+ stmt->setUInt32(0, GetGUIDLow());
+ stmt->setUInt32(1, quest_id);
+ trans->Append(stmt);
}
m_WeeklyQuestChanged = false;
}
+void Player::_SaveSeasonalQuestStatus(SQLTransaction& trans)
+{
+ if (!m_SeasonalQuestChanged || m_seasonalquests.empty())
+ return;
+
+ // we don't need transactions here.
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_QUEST_STATUS_SEASONAL_CHAR);
+ stmt->setUInt32(0, GetGUIDLow());
+ trans->Append(stmt);
+
+ for (SeasonalEventQuestMap::const_iterator iter = m_seasonalquests.begin(); iter != m_seasonalquests.end(); ++iter)
+ {
+ uint16 event_id = iter->first;
+ for (SeasonalQuestSet::const_iterator itr = (iter->second).begin(); itr != (iter->second).end(); ++itr)
+ {
+ uint32 quest_id = (*itr);
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_SEASONALQUESTSTATUS);
+ stmt->setUInt32(0,GetGUIDLow());
+ stmt->setUInt32(1,quest_id);
+ stmt->setUInt16(1,event_id);
+ trans->Append(stmt);
+ }
+ }
+
+ m_SeasonalQuestChanged = false;
+}
+
void Player::_SaveSkills(SQLTransaction& trans)
{
// we don't need transactions here.
@@ -22036,6 +22115,16 @@ void Player::SetWeeklyQuestStatus(uint32 quest_id)
m_WeeklyQuestChanged = true;
}
+void Player::SetSeasonalQuestStatus(uint32 quest_id)
+{
+ Quest const* q = sObjectMgr->GetQuestTemplate(quest_id);
+ if (!q)
+ return;
+
+ m_seasonalquests[q->GetSeasonalQuestEvent()].insert(quest_id);
+ m_SeasonalQuestChanged = true;
+}
+
void Player::ResetDailyQuestStatus()
{
for (uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx)
@@ -22058,6 +22147,16 @@ void Player::ResetWeeklyQuestStatus()
m_WeeklyQuestChanged = false;
}
+void Player::ResetSeasonalQuestStatus(uint16 event_id)
+{
+ if (m_seasonalquests.empty() || m_seasonalquests[event_id].empty())
+ return;
+
+ m_seasonalquests.erase(event_id);
+ // DB data deleted in caller
+ m_SeasonalQuestChanged = false;
+}
+
Battleground* Player::GetBattleground() const
{
if (GetBattlegroundId() == 0)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 7da008d597b..21c87a993dc 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -815,11 +815,12 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOADTALENTS = 23,
PLAYER_LOGIN_QUERY_LOADACCOUNTDATA = 24,
PLAYER_LOGIN_QUERY_LOADSKILLS = 25,
- PLAYER_LOGIN_QUERY_LOADWEKLYQUESTSTATUS = 26,
+ PLAYER_LOGIN_QUERY_LOADWEEKLYQUESTSTATUS = 26,
PLAYER_LOGIN_QUERY_LOADRANDOMBG = 27,
PLAYER_LOGIN_QUERY_LOADBANNED = 28,
PLAYER_LOGIN_QUERY_LOADQUESTSTATUSREW = 29,
PLAYER_LOGIN_QUERY_LOADINSTANCELOCKTIMES = 30,
+ PLAYER_LOGIN_QUERY_LOADSEASONALQUESTSTATUS = 31,
MAX_PLAYER_LOGIN_QUERY,
};
@@ -1422,6 +1423,7 @@ class Player : public Unit, public GridObject<Player>
bool SatisfyQuestPrevChain(Quest const* qInfo, bool msg);
bool SatisfyQuestDay(Quest const* qInfo, bool msg);
bool SatisfyQuestWeek(Quest const* qInfo, bool msg);
+ bool SatisfyQuestSeasonal(Quest const* qInfo, bool msg);
bool GiveQuestSourceItem(Quest const* quest);
bool TakeQuestSourceItem(uint32 questId, bool msg);
bool GetQuestRewardStatus(uint32 quest_id) const;
@@ -1432,8 +1434,10 @@ class Player : public Unit, public GridObject<Player>
void SetDailyQuestStatus(uint32 quest_id);
void SetWeeklyQuestStatus(uint32 quest_id);
+ void SetSeasonalQuestStatus(uint32 quest_id);
void ResetDailyQuestStatus();
void ResetWeeklyQuestStatus();
+ void ResetSeasonalQuestStatus(uint16 event_id);
uint16 FindQuestSlot(uint32 quest_id) const;
uint32 GetQuestSlotQuestId(uint16 slot) const { return GetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot * MAX_QUEST_OFFSET + QUEST_ID_OFFSET); }
@@ -2558,8 +2562,11 @@ class Player : public Unit, public GridObject<Player>
//We allow only one timed quest active at the same time. Below can then be simple value instead of set.
typedef std::set<uint32> QuestSet;
+ typedef std::set<uint32> SeasonalQuestSet;
+ typedef UNORDERED_MAP<uint32,SeasonalQuestSet> SeasonalEventQuestMap;
QuestSet m_timedquests;
QuestSet m_weeklyquests;
+ SeasonalEventQuestMap m_seasonalquests;
uint64 m_divider;
uint32 m_ingametime;
@@ -2580,6 +2587,7 @@ class Player : public Unit, public GridObject<Player>
void _LoadQuestStatusRewarded(PreparedQueryResult result);
void _LoadDailyQuestStatus(PreparedQueryResult result);
void _LoadWeeklyQuestStatus(PreparedQueryResult result);
+ void _LoadSeasonalQuestStatus(PreparedQueryResult result);
void _LoadRandomBGStatus(PreparedQueryResult result);
void _LoadGroup(PreparedQueryResult result);
void _LoadSkills(PreparedQueryResult result);
@@ -2605,6 +2613,7 @@ class Player : public Unit, public GridObject<Player>
void _SaveQuestStatus(SQLTransaction& trans);
void _SaveDailyQuestStatus(SQLTransaction& trans);
void _SaveWeeklyQuestStatus(SQLTransaction& trans);
+ void _SaveSeasonalQuestStatus(SQLTransaction& trans);
void _SaveSkills(SQLTransaction& trans);
void _SaveSpells(SQLTransaction& trans);
void _SaveEquipmentSets(SQLTransaction& trans);
@@ -2716,6 +2725,7 @@ class Player : public Unit, public GridObject<Player>
bool m_DailyQuestChanged;
bool m_WeeklyQuestChanged;
+ bool m_SeasonalQuestChanged;
time_t m_lastDailyQuestTime;
uint32 m_drunkTimer;
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index 8b9e2fe047b..e1900c6c994 100755
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -759,6 +759,47 @@ void GameEventMgr::LoadFromDB()
}
}
+ sLog->outString("Loading Game Event Seasonal Quest Relations...");
+ {
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1
+ QueryResult result = WorldDatabase.Query("SELECT quest, event FROM game_event_seasonal_questrelation");
+
+ if (!result)
+ {
+ sLog->outString(">> Loaded 0 seasonal quests additions in game events. DB table `game_event_seasonal_questrelation` is empty.");
+ sLog->outString();
+ }
+ else
+ {
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 quest = fields[0].GetUInt32();
+ uint16 event_id = fields[1].GetUInt16();
+
+ if (event_id >= mGameEvent.size())
+ {
+ sLog->outErrorDb("`game_event_seasonal_questrelation` event id (%u) is out of range compared to max event in `game_event`", event_id);
+ continue;
+ }
+
+ Quest * qInfo = sObjectMgr->GetQuestTemplate(quest);
+ if (qInfo)
+ qInfo->SetSeasonalQuestEvent(event_id);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ sLog->outString(">> Loaded %u quests additions in game events in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ sLog->outString();
+ }
+ }
+
sLog->outString("Loading Game Event Vendor Additions Data...");
{
uint32 oldMSTime = getMSTime();
@@ -1079,6 +1120,8 @@ void GameEventMgr::UnApplyEvent(uint16 event_id)
UpdateEventNPCVendor(event_id, false);
// update bg holiday
UpdateBattlegroundSettings();
+ // check for seasonal quest reset.
+ sWorld->ResetEventSeasonalQuests(event_id);
}
void GameEventMgr::ApplyNewEvent(uint16 event_id)
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 57c6fe1ad2f..1b6d90da0a6 100755
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -687,6 +687,11 @@ class ObjectMgr
QuestMap::const_iterator itr = mQuestTemplates.find(quest_id);
return itr != mQuestTemplates.end() ? itr->second : NULL;
}
+ Quest * GetQuestTemplate(uint32 quest_id)
+ {
+ QuestMap::const_iterator itr = mQuestTemplates.find(quest_id);
+ return itr != mQuestTemplates.end() ? itr->second : NULL;
+ }
QuestMap const& GetQuestTemplates() const { return mQuestTemplates; }
uint32 GetQuestForAreaTrigger(uint32 Trigger_ID) const
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index 14a6577b1b5..674f54d07a8 100755
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -65,6 +65,7 @@ Quest::Quest(Field* questRecord)
RequiredPlayerKills = questRecord[40].GetUInt32();
RewardTalents = questRecord[41].GetUInt32();
RewardArenaPoints = questRecord[42].GetInt32();
+ SeasonalQuestEvent = 0;
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
RewardItemId[i] = questRecord[43+i].GetUInt32();
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 90905f2fa34..4fbfcd176f4 100755
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -187,6 +187,7 @@ class Quest
bool HasFlag(uint32 flag) const { return (Flags & flag) != 0; }
void SetFlag(uint32 flag) { Flags |= flag; }
+ void SetSeasonalQuestEvent(uint16 event_id) { SeasonalQuestEvent = event_id; }
// table data accessors:
uint32 GetQuestId() const { return Id; }
@@ -246,11 +247,13 @@ class Quest
uint32 GetCompleteEmote() const { return EmoteOnComplete; }
uint32 GetQuestStartScript() const { return StartScript; }
uint32 GetQuestCompleteScript() const { return CompleteScript; }
+ uint16 GetSeasonalQuestEvent() const {return SeasonalQuestEvent; }
bool IsRepeatable() const { return Flags & QUEST_TRINITY_FLAGS_REPEATABLE; }
bool IsAutoComplete() const;
uint32 GetFlags() const { return Flags; }
bool IsDaily() const { return Flags & QUEST_FLAGS_DAILY; }
bool IsWeekly() const { return Flags & QUEST_FLAGS_WEEKLY; }
+ bool IsSeasonal() const { return ZoneOrSort == -22; }
bool IsDailyOrWeekly() const { return Flags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY); }
bool IsAutoAccept() const { return Flags & QUEST_FLAGS_AUTO_ACCEPT; }
bool IsRaidQuest() const { return Type == QUEST_TYPE_RAID || Type == QUEST_TYPE_RAID_10 || Type == QUEST_TYPE_RAID_25; }
@@ -295,6 +298,8 @@ class Quest
uint32 m_reqCreatureOrGOcount;
uint32 m_rewchoiceitemscount;
uint32 m_rewitemscount;
+ //additional data needed for seasonal quest events
+ uint16 SeasonalQuestEvent;
// table data
protected:
diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp
index 11de2c68ca1..47af8c9bc1e 100755..100644
--- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp
@@ -93,9 +93,13 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt32(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS, stmt);
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_WEKLYQUESTSTATUS);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_WEEKLYQUESTSTATUS);
stmt->setUInt32(0, lowGuid);
- res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADWEKLYQUESTSTATUS, stmt);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADWEEKLYQUESTSTATUS, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SEASONALQUESTSTATUS);
+ stmt->setUInt32(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADSEASONALQUESTSTATUS, stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_REPUTATION);
stmt->setUInt32(0, lowGuid);
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 388bafc503d..426a93fda57 100755
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -2748,6 +2748,17 @@ void World::ResetWeeklyQuests()
sPoolMgr->ChangeWeeklyQuests();
}
+void World::ResetEventSeasonalQuests(uint16 event_id)
+{
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_QUEST_STATUS_SEASONAL);
+ stmt->setUInt16(0,event_id);
+ CharacterDatabase.Execute(stmt);
+
+ for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
+ if (itr->second->GetPlayer())
+ itr->second->GetPlayer()->ResetSeasonalQuestStatus(event_id);
+}
+
void World::ResetRandomBG()
{
sLog->outDetail("Random BG status reset for all characters.");
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 02438375058..bedd8a87b20 100755
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -746,6 +746,7 @@ class World
uint32 GetCleaningFlags() const { return m_CleaningFlags; }
void SetCleaningFlags(uint32 flags) { m_CleaningFlags = flags; }
+ void ResetEventSeasonalQuests(uint16 event_id);
protected:
void _UpdateGameTime();
// callback for UpdateRealmCharacters
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index b5b174a19eb..31fd5f66375 100755..100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -46,6 +46,10 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_SEL_GUID_RACE_ACC_BY_NAME, "SELECT guid, race, account FROM characters WHERE name = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_DEL_QUEST_STATUS_DAILY, "DELETE FROM character_queststatus_daily", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_DEL_QUEST_STATUS_WEEKLY, "DELETE FROM character_queststatus_weekly", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_DEL_QUEST_STATUS_SEASONAL, "DELETE FROM character_queststatus_seasonal WHERE event = ?", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_DEL_QUEST_STATUS_DAILY_CHAR, "DELETE FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_DEL_QUEST_STATUS_WEEKLY_CHAR, "DELETE FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_DEL_QUEST_STATUS_SEASONAL_CHAR, "DELETE FROM character_queststatus_seasonal WHERE guid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_DEL_BATTLEGROUND_RANDOM, "DELETE FROM character_battleground_random", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_INS_BATTLEGROUND_RANDOM, "INSERT INTO character_battleground_random (guid) VALUES (?)", CONNECTION_ASYNC);
@@ -63,7 +67,11 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_SEL_CHARACTER_QUESTSTATUS, "SELECT quest, status, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, "
"itemcount1, itemcount2, itemcount3, itemcount4, playercount FROM character_queststatus WHERE guid = ?", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_SEL_CHARACTER_DAILYQUESTSTATUS, "SELECT quest, time FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC)
- PREPARE_STATEMENT(CHAR_SEL_CHARACTER_WEKLYQUESTSTATUS, "SELECT quest FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_SEL_CHARACTER_WEEKLYQUESTSTATUS, "SELECT quest FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_SEL_CHARACTER_SEASONALQUESTSTATUS, "SELECT quest FROM character_queststatus_seasonal WHERE guid = ?", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_INS_CHARACTER_DAILYQUESTSTATUS, "INSERT INTO character_queststatus_daily (guid, quest, time) VALUES (?, ?, ?)", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS, "INSERT INTO character_queststatus_weekly (guid, quest) VALUES (?, ?)", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_INS_CHARACTER_SEASONALQUESTSTATUS, "INSERT INTO character_queststatus_seasonal (guid, quest, event) VALUES (?, ?, ?)", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_SEL_CHARACTER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_SEL_CHARACTER_INVENTORY, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, bag, slot, "
"item, itemEntry FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid WHERE ci.guid = ? ORDER BY bag, slot", CONNECTION_ASYNC)
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index a0f5b9a9954..a239e274a54 100755..100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -66,6 +66,10 @@ enum CharacterDatabaseStatements
CHAR_SEL_GUID_RACE_ACC_BY_NAME,
CHAR_DEL_QUEST_STATUS_DAILY,
CHAR_DEL_QUEST_STATUS_WEEKLY,
+ CHAR_DEL_QUEST_STATUS_SEASONAL,
+ CHAR_DEL_QUEST_STATUS_DAILY_CHAR,
+ CHAR_DEL_QUEST_STATUS_WEEKLY_CHAR,
+ CHAR_DEL_QUEST_STATUS_SEASONAL_CHAR,
CHAR_DEL_BATTLEGROUND_RANDOM,
CHAR_INS_BATTLEGROUND_RANDOM,
@@ -76,7 +80,11 @@ enum CharacterDatabaseStatements
CHAR_SEL_CHARACTER_SPELL,
CHAR_SEL_CHARACTER_QUESTSTATUS,
CHAR_SEL_CHARACTER_DAILYQUESTSTATUS,
- CHAR_SEL_CHARACTER_WEKLYQUESTSTATUS,
+ CHAR_SEL_CHARACTER_WEEKLYQUESTSTATUS,
+ CHAR_SEL_CHARACTER_SEASONALQUESTSTATUS,
+ CHAR_INS_CHARACTER_DAILYQUESTSTATUS,
+ CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS,
+ CHAR_INS_CHARACTER_SEASONALQUESTSTATUS,
CHAR_SEL_CHARACTER_REPUTATION,
CHAR_SEL_CHARACTER_INVENTORY,
CHAR_SEL_CHARACTER_ACTIONS,