diff options
-rw-r--r-- | sql/updates/world/2012_01_03_00_world_game_event_seasonal_questrelation.sql | 387 | ||||
-rw-r--r-- | sql/updates/world/2012_01_03_01_characters_character_queststatus_seasonal.sql | 8 | ||||
-rwxr-xr-x | src/server/game/Entities/Player/Player.cpp | 125 | ||||
-rwxr-xr-x | src/server/game/Entities/Player/Player.h | 12 | ||||
-rwxr-xr-x | src/server/game/Events/GameEventMgr.cpp | 43 | ||||
-rwxr-xr-x | src/server/game/Globals/ObjectMgr.h | 5 | ||||
-rwxr-xr-x | src/server/game/Quests/QuestDef.cpp | 1 | ||||
-rwxr-xr-x | src/server/game/Quests/QuestDef.h | 5 | ||||
-rw-r--r--[-rwxr-xr-x] | src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp | 8 | ||||
-rwxr-xr-x | src/server/game/World/World.cpp | 11 | ||||
-rwxr-xr-x | src/server/game/World/World.h | 1 | ||||
-rw-r--r--[-rwxr-xr-x] | src/server/shared/Database/Implementation/CharacterDatabase.cpp | 10 | ||||
-rw-r--r--[-rwxr-xr-x] | src/server/shared/Database/Implementation/CharacterDatabase.h | 10 |
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, |