From a38f97f71c0c8ce652ef6fdced44c1a898eb44f8 Mon Sep 17 00:00:00 2001 From: NoFantasy Date: Fri, 29 Oct 2010 20:38:09 +0200 Subject: [PATCH] [10655] Add support for monthly quests Quest that can repeated each month are set by quest_template.SpecialFlags |0x04 flag Quest are reset at midnight the first day of each month. Note: for the time being, quest must also be set repeatable (SpecialFlags |0x01) Signed-off-by: NoFantasy --- sql/characters.sql | 24 +++++- ...aracters_character_queststatus_monthly.sql | 12 +++ sql/updates/Makefile.am | 2 + src/game/CharacterHandler.cpp | 1 + src/game/ObjectMgr.cpp | 9 ++ src/game/Player.cpp | 85 ++++++++++++++++++- src/game/Player.h | 8 ++ src/game/QuestDef.h | 17 ++-- src/game/World.cpp | 65 ++++++++++++++ src/game/World.h | 4 + src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 2 +- 12 files changed, 218 insertions(+), 13 deletions(-) create mode 100644 sql/updates/10655_01_characters_character_queststatus_monthly.sql diff --git a/sql/characters.sql b/sql/characters.sql index 796482cd2..ad7c0282b 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -21,7 +21,7 @@ DROP TABLE IF EXISTS `character_db_version`; CREATE TABLE `character_db_version` ( - `required_10568_01_characters_character_tutorial` bit(1) default NULL + `required_10655_01_characters_character_queststatus_monthly` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; -- @@ -725,6 +725,27 @@ LOCK TABLES `character_queststatus_daily` WRITE; /*!40000 ALTER TABLE `character_queststatus_daily` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `character_queststatus_monthly` +-- + +DROP TABLE IF EXISTS `character_queststatus_monthly`; +CREATE TABLE `character_queststatus_monthly` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `quest` int(11) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + PRIMARY KEY (`guid`,`quest`), + KEY `idx_guid` (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_queststatus_monthly` +-- + +LOCK TABLES `character_queststatus_monthly` WRITE; +/*!40000 ALTER TABLE `character_queststatus_monthly` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_queststatus_monthly` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `character_queststatus_weekly` -- @@ -1624,6 +1645,7 @@ CREATE TABLE `saved_variables` ( `NextArenaPointDistributionTime` bigint(40) UNSIGNED NOT NULL DEFAULT '0', `NextDailyQuestResetTime` bigint(40) unsigned NOT NULL default '0', `NextWeeklyQuestResetTime` bigint(40) unsigned NOT NULL default '0', + `NextMonthlyQuestResetTime` bigint(40) unsigned NOT NULL default '0', `cleaning_flags` int(11) unsigned NOT NULL default '0' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Variable Saves'; diff --git a/sql/updates/10655_01_characters_character_queststatus_monthly.sql b/sql/updates/10655_01_characters_character_queststatus_monthly.sql new file mode 100644 index 000000000..f709c7d38 --- /dev/null +++ b/sql/updates/10655_01_characters_character_queststatus_monthly.sql @@ -0,0 +1,12 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_10568_01_characters_character_tutorial required_10655_01_characters_character_queststatus_monthly bit; + +DROP TABLE IF EXISTS character_queststatus_monthly; +CREATE TABLE character_queststatus_monthly ( + guid int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + quest int(11) unsigned NOT NULL default '0' COMMENT 'Quest Identifier', + PRIMARY KEY (guid,quest), + KEY idx_guid (guid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +ALTER TABLE saved_variables + ADD COLUMN NextMonthlyQuestResetTime bigint(40) unsigned NOT NULL default '0' AFTER NextWeeklyQuestResetTime; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 5704e0d2e..17f5ab22f 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -110,6 +110,7 @@ pkgdata_DATA = \ 10628_01_mangos_mangos_string.sql \ 10629_01_mangos_mangos_string.sql \ 10654_01_mangos_game_event_creature_quest.sql \ + 10655_01_characters_character_queststatus_monthly.sql \ README ## Additional files to include when running 'make dist' @@ -200,4 +201,5 @@ EXTRA_DIST = \ 10628_01_mangos_mangos_string.sql \ 10629_01_mangos_mangos_string.sql \ 10654_01_mangos_game_event_creature_quest.sql \ + 10655_01_characters_character_queststatus_monthly.sql \ README diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 08bf61e02..59678ac12 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -79,6 +79,7 @@ bool LoginQueryHolder::Initialize() res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS, "SELECT quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4 FROM character_queststatus WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS,"SELECT quest FROM character_queststatus_daily WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADWEEKLYQUESTSTATUS,"SELECT quest FROM character_queststatus_weekly WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADMONTHLYQUESTSTATUS,"SELECT quest FROM character_queststatus_monthly WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADREPUTATION, "SELECT faction,standing,flags FROM character_reputation WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADINVENTORY, "SELECT data,text,bag,slot,item,item_template FROM character_inventory JOIN item_instance ON character_inventory.item = item_instance.guid WHERE character_inventory.guid = '%u' ORDER BY bag,slot", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACTIONS, "SELECT spec,button,action,type FROM character_action WHERE guid = '%u' ORDER BY button", GUID_LOPART(m_guid)); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 1ea8b01d4..3ed99bdce 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -3685,6 +3685,15 @@ void ObjectMgr::LoadQuests() } } + if (qinfo->QuestFlags & QUEST_MANGOS_FLAGS_MONTHLY) + { + if (!(qinfo->QuestFlags & QUEST_MANGOS_FLAGS_REPEATABLE)) + { + sLog.outErrorDb("Monthly quest %u not marked as repeatable in `SpecialFlags`, added.", qinfo->GetQuestId()); + qinfo->QuestFlags |= QUEST_MANGOS_FLAGS_REPEATABLE; + } + } + if (qinfo->QuestFlags & QUEST_FLAGS_AUTO_REWARDED) { // at auto-reward can be rewarded only RewChoiceItemId[0] diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 33584ed4f..ef980af11 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -13275,7 +13275,8 @@ bool Player::CanSeeStartQuest(Quest const *pQuest) const if (SatisfyQuestClass(pQuest, false) && SatisfyQuestRace(pQuest, false) && SatisfyQuestSkill(pQuest, false) && SatisfyQuestExclusiveGroup(pQuest, false) && SatisfyQuestReputation(pQuest, false) && SatisfyQuestPreviousQuest(pQuest, false) && SatisfyQuestNextChain(pQuest, false) && - SatisfyQuestPrevChain(pQuest, false) && SatisfyQuestDay(pQuest, false) && SatisfyQuestWeek(pQuest, false)) + SatisfyQuestPrevChain(pQuest, false) && SatisfyQuestDay(pQuest, false) && SatisfyQuestWeek(pQuest, false) && + SatisfyQuestMonth(pQuest, false)) { return getLevel() + sWorld.getConfig(CONFIG_UINT32_QUEST_HIGH_LEVEL_HIDE_DIFF) >= pQuest->GetMinLevel(); } @@ -13290,7 +13291,7 @@ bool Player::CanTakeQuest(Quest const *pQuest, bool msg) const SatisfyQuestSkill(pQuest, msg) && SatisfyQuestReputation(pQuest, msg) && SatisfyQuestPreviousQuest(pQuest, msg) && SatisfyQuestTimed(pQuest, msg) && SatisfyQuestNextChain(pQuest, msg) && SatisfyQuestPrevChain(pQuest, msg) && - SatisfyQuestDay(pQuest, msg) && SatisfyQuestWeek(pQuest, msg); + SatisfyQuestDay(pQuest, msg) && SatisfyQuestWeek(pQuest, msg) && SatisfyQuestMonth(pQuest, msg); } bool Player::CanAddQuest(Quest const *pQuest, bool msg) const @@ -13409,7 +13410,7 @@ bool Player::CanRewardQuest(Quest const *pQuest, bool msg) const return false; // daily quest can't be rewarded (25 daily quest already completed) - if (!SatisfyQuestDay(pQuest, true) || !SatisfyQuestWeek(pQuest, true)) + if (!SatisfyQuestDay(pQuest, true) || !SatisfyQuestWeek(pQuest, true) || !SatisfyQuestMonth(pQuest, true)) return false; // rewarded and not repeatable quest (only cheating case, then ignore without message) @@ -13695,6 +13696,9 @@ void Player::RewardQuest(Quest const *pQuest, uint32 reward, Object* questGiver, if (pQuest->IsWeekly()) SetWeeklyQuestStatus(quest_id); + if (pQuest->IsMonthly()) + SetMonthlyQuestStatus(quest_id); + if (!pQuest->IsRepeatable()) SetQuestStatus(quest_id, QUEST_STATUS_COMPLETE); else @@ -14133,6 +14137,15 @@ bool Player::SatisfyQuestWeek(Quest const* qInfo, bool msg) const return m_weeklyquests.find(qInfo->GetQuestId()) == m_weeklyquests.end(); } +bool Player::SatisfyQuestMonth(Quest const* qInfo, bool msg) const +{ + if (!qInfo->IsMonthly() || m_monthlyquests.empty()) + return true; + + // if not found in cooldown list + return m_monthlyquests.find(qInfo->GetQuestId()) == m_monthlyquests.end(); +} + bool Player::CanGiveQuestSourceItem( Quest const *pQuest, ItemPosCountVec* dest ) const { uint32 srcitem = pQuest->GetSrcItemId(); @@ -15458,6 +15471,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS)); _LoadDailyQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS)); _LoadWeeklyQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADWEEKLYQUESTSTATUS)); + _LoadMonthlyQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADMONTHLYQUESTSTATUS)); _LoadTalents(holder->GetResult(PLAYER_LOGIN_QUERY_LOADTALENTS)); @@ -16291,6 +16305,36 @@ void Player::_LoadWeeklyQuestStatus(QueryResult *result) m_WeeklyQuestChanged = false; } +void Player::_LoadMonthlyQuestStatus(QueryResult *result) +{ + m_monthlyquests.clear(); + + //QueryResult *result = CharacterDatabase.PQuery("SELECT quest FROM character_queststatus_weekly WHERE guid = '%u'", GetGUIDLow()); + + if (result) + { + do + { + Field *fields = result->Fetch(); + + uint32 quest_id = fields[0].GetUInt32(); + + Quest const* pQuest = sObjectMgr.GetQuestTemplate(quest_id); + if (!pQuest) + continue; + + m_monthlyquests.insert(quest_id); + + DEBUG_LOG("Monthly quest {%u} cooldown for player (GUID: %u)", quest_id, GetGUIDLow()); + } + while( result->NextRow() ); + + delete result; + } + + m_MonthlyQuestChanged = false; +} + void Player::_LoadSpells(QueryResult *result) { //QueryResult *result = CharacterDatabase.PQuery("SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'",GetGUIDLow()); @@ -16911,6 +16955,7 @@ void Player::SaveToDB() _SaveQuestStatus(); _SaveDailyQuestStatus(); _SaveWeeklyQuestStatus(); + _SaveMonthlyQuestStatus(); _SaveSpells(); _SaveSpellCooldowns(); _SaveActions(); @@ -17239,6 +17284,24 @@ void Player::_SaveWeeklyQuestStatus() m_WeeklyQuestChanged = false; } +void Player::_SaveMonthlyQuestStatus() +{ + if (!m_MonthlyQuestChanged || m_monthlyquests.empty()) + return; + + // we don't need transactions here. + CharacterDatabase.PExecute("DELETE FROM character_queststatus_monthly WHERE guid = '%u'", GetGUIDLow()); + + for (QuestSet::const_iterator iter = m_monthlyquests.begin(); iter != m_monthlyquests.end(); ++iter) + { + uint32 quest_id = *iter; + + CharacterDatabase.PExecute("INSERT INTO character_queststatus_monthly (guid, quest) VALUES ('%u', '%u')", GetGUIDLow(), quest_id); + } + + m_MonthlyQuestChanged = false; +} + void Player::_SaveSkills() { // we don't need transactions here. @@ -19941,6 +20004,12 @@ void Player::SetWeeklyQuestStatus( uint32 quest_id ) m_WeeklyQuestChanged = true; } +void Player::SetMonthlyQuestStatus(uint32 quest_id) +{ + m_monthlyquests.insert(quest_id); + m_MonthlyQuestChanged = true; +} + void Player::ResetDailyQuestStatus() { for(uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx) @@ -19960,6 +20029,16 @@ void Player::ResetWeeklyQuestStatus() m_WeeklyQuestChanged = false; } +void Player::ResetMonthlyQuestStatus() +{ + if (m_monthlyquests.empty()) + return; + + m_monthlyquests.clear(); + // DB data deleted in caller + m_MonthlyQuestChanged = false; +} + BattleGround* Player::GetBattleGround() const { if(GetBattleGroundId()==0) diff --git a/src/game/Player.h b/src/game/Player.h index 7d705b6db..5bc7ae612 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -914,6 +914,7 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOADMAILEDITEMS, PLAYER_LOGIN_QUERY_LOADTALENTS, PLAYER_LOGIN_QUERY_LOADWEEKLYQUESTSTATUS, + PLAYER_LOGIN_QUERY_LOADMONTHLYQUESTSTATUS, MAX_PLAYER_LOGIN_QUERY }; @@ -1435,6 +1436,7 @@ class MANGOS_DLL_SPEC Player : public Unit bool SatisfyQuestPrevChain( Quest const* qInfo, bool msg ) const; bool SatisfyQuestDay( Quest const* qInfo, bool msg ) const; bool SatisfyQuestWeek( Quest const* qInfo, bool msg ) const; + bool SatisfyQuestMonth(Quest const* qInfo, bool msg) const; bool CanGiveQuestSourceItem( Quest const *pQuest, ItemPosCountVec* dest = NULL) const; void GiveQuestSourceItem( Quest const *pQuest ); bool TakeQuestSourceItem( uint32 quest_id, bool msg ); @@ -1444,8 +1446,10 @@ class MANGOS_DLL_SPEC Player : public Unit void SetDailyQuestStatus( uint32 quest_id ); void SetWeeklyQuestStatus( uint32 quest_id ); + void SetMonthlyQuestStatus(uint32 quest_id); void ResetDailyQuestStatus(); void ResetWeeklyQuestStatus(); + void ResetMonthlyQuestStatus(); 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); } @@ -2425,6 +2429,7 @@ class MANGOS_DLL_SPEC Player : public Unit typedef std::set QuestSet; QuestSet m_timedquests; QuestSet m_weeklyquests; + QuestSet m_monthlyquests; uint64 m_divider; uint32 m_ingametime; @@ -2442,6 +2447,7 @@ class MANGOS_DLL_SPEC Player : public Unit void _LoadQuestStatus(QueryResult *result); void _LoadDailyQuestStatus(QueryResult *result); void _LoadWeeklyQuestStatus(QueryResult *result); + void _LoadMonthlyQuestStatus(QueryResult *result); void _LoadGroup(QueryResult *result); void _LoadSkills(QueryResult *result); void _LoadSpells(QueryResult *result); @@ -2466,6 +2472,7 @@ class MANGOS_DLL_SPEC Player : public Unit void _SaveQuestStatus(); void _SaveDailyQuestStatus(); void _SaveWeeklyQuestStatus(); + void _SaveMonthlyQuestStatus(); void _SaveSkills(); void _SaveSpells(); void _SaveEquipmentSets(); @@ -2565,6 +2572,7 @@ class MANGOS_DLL_SPEC Player : public Unit bool m_DailyQuestChanged; bool m_WeeklyQuestChanged; + bool m_MonthlyQuestChanged; uint32 m_drunkTimer; uint16 m_drunk; diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h index f00b7f736..6d2a4b3f4 100644 --- a/src/game/QuestDef.h +++ b/src/game/QuestDef.h @@ -160,15 +160,17 @@ enum __QuestFlags QUEST_FLAGS_AUTO_ACCEPT = 0x00080000, // quests in starting areas // Mangos flags for set SpecialFlags in DB if required but used only at server - QUEST_MANGOS_FLAGS_REPEATABLE = 0x01000000, // Set by 1 in SpecialFlags from DB - QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT = 0x02000000, // Set by 2 in SpecialFlags from DB (if required area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script DLL) - QUEST_MANGOS_FLAGS_DB_ALLOWED = 0xFFFFFF | QUEST_MANGOS_FLAGS_REPEATABLE | QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT, + QUEST_MANGOS_FLAGS_REPEATABLE = 0x001000000, // Set by 1 in SpecialFlags from DB + QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT = 0x002000000, // Set by 2 in SpecialFlags from DB (if required area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script DLL) + QUEST_MANGOS_FLAGS_MONTHLY = 0x004000000, // 4 in SpecialFlags. Quest reset for player at beginning of month. + QUEST_MANGOS_FLAGS_DB_ALLOWED = 0xFFFFFF | + QUEST_MANGOS_FLAGS_REPEATABLE | QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT | QUEST_MANGOS_FLAGS_MONTHLY, // Mangos flags for internal use only - QUEST_MANGOS_FLAGS_DELIVER = 0x04000000, // Internal flag computed only - QUEST_MANGOS_FLAGS_SPEAKTO = 0x08000000, // Internal flag computed only - QUEST_MANGOS_FLAGS_KILL_OR_CAST = 0x10000000, // Internal flag computed only - QUEST_MANGOS_FLAGS_TIMED = 0x20000000, // Internal flag computed only + QUEST_MANGOS_FLAGS_DELIVER = 0x008000000, // Internal flag computed only + QUEST_MANGOS_FLAGS_SPEAKTO = 0x010000000, // Internal flag computed only + QUEST_MANGOS_FLAGS_KILL_OR_CAST = 0x020000000, // Internal flag computed only + QUEST_MANGOS_FLAGS_TIMED = 0x040000000, // Internal flag computed only }; struct QuestLocale @@ -257,6 +259,7 @@ class Quest uint32 GetFlags() const { return QuestFlags; } bool IsDaily() const { return QuestFlags & QUEST_FLAGS_DAILY; } bool IsWeekly() const { return QuestFlags & QUEST_FLAGS_WEEKLY; } + bool IsMonthly() const { return QuestFlags & QUEST_MANGOS_FLAGS_MONTHLY; } bool IsDailyOrWeekly() const { return QuestFlags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY); } bool IsAutoAccept() const { return QuestFlags & QUEST_FLAGS_AUTO_ACCEPT; } bool IsAllowedInRaid() const; diff --git a/src/game/World.cpp b/src/game/World.cpp index 4fb965c6f..1df858939 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1311,6 +1311,9 @@ void World::SetInitialWorldSettings() sLog.outString("Calculate next weekly quest reset time..." ); InitWeeklyQuestResetTime(); + sLog.outString("Calculate next monthly quest reset time..." ); + SetMonthlyQuestResetTime(); + sLog.outString("Starting objects Pooling system..." ); sPoolMgr.Initialize(); @@ -1395,6 +1398,10 @@ void World::Update(uint32 diff) if (m_gameTime > m_NextWeeklyQuestReset) ResetWeeklyQuests(); + /// Handle monthly quests reset time + if (m_gameTime > m_NextMonthlyQuestReset) + ResetMonthlyQuests(); + ///
  • Handle auctions when the timer has passed if (m_timers[WUPDATE_AUCTIONS].Passed()) { @@ -1994,6 +2001,52 @@ void World::InitDailyQuestResetTime() delete result; } +void World::SetMonthlyQuestResetTime(bool initialize) +{ + if (initialize) + { + QueryResult * result = CharacterDatabase.Query("SELECT NextMonthlyQuestResetTime FROM saved_variables"); + + if (!result) + m_NextMonthlyQuestReset = time_t(time(NULL)); + else + m_NextMonthlyQuestReset = time_t((*result)[0].GetUInt64()); + + delete result; + } + + // generate time + time_t currentTime = time(NULL); + tm localTm = *localtime(¤tTime); + + int month = localTm.tm_mon; + int year = localTm.tm_year; + + ++month; + + // month 11 is december, next is january (0) + if (month > 11) + { + month = 0; + year += 1; + } + + // reset time for next month + localTm.tm_year = year; + localTm.tm_mon = month; + localTm.tm_mday = 1; // don't know if we really need config option for day/hour + localTm.tm_hour = 0; + localTm.tm_min = 0; + localTm.tm_sec = 0; + + time_t nextMonthResetTime = mktime(&localTm); + + m_NextMonthlyQuestReset = (initialize && m_NextMonthlyQuestReset < nextMonthResetTime) ? m_NextMonthlyQuestReset : nextMonthResetTime; + + // Row must exist for this to work. Currently row is added by InitDailyQuestResetTime(), called before this function + CharacterDatabase.PExecute("UPDATE saved_variables SET NextMonthlyQuestResetTime = '"UI64FMTD"'", uint64(m_NextMonthlyQuestReset)); +} + void World::ResetDailyQuests() { DETAIL_LOG("Daily quests reset for all characters."); @@ -2018,6 +2071,18 @@ void World::ResetWeeklyQuests() CharacterDatabase.PExecute("UPDATE saved_variables SET NextWeeklyQuestResetTime = '"UI64FMTD"'", uint64(m_NextWeeklyQuestReset)); } +void World::ResetMonthlyQuests() +{ + DETAIL_LOG("Monthly quests reset for all characters."); + CharacterDatabase.Execute("TRUNCATE character_queststatus_monthly"); + + for(SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) + if (itr->second->GetPlayer()) + itr->second->GetPlayer()->ResetMonthlyQuestStatus(); + + SetMonthlyQuestResetTime(false); +} + void World::SetPlayerLimit( int32 limit, bool needUpdate ) { if (limit < -SEC_ADMINISTRATOR) diff --git a/src/game/World.h b/src/game/World.h index 3d10f2148..099ad5961 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -583,8 +583,11 @@ class World void InitDailyQuestResetTime(); void InitWeeklyQuestResetTime(); + void SetMonthlyQuestResetTime(bool initialize = true); void ResetDailyQuests(); void ResetWeeklyQuests(); + void ResetMonthlyQuests(); + private: void setConfig(eConfigUInt32Values index, char const* fieldname, uint32 defvalue); void setConfig(eConfigInt32Values index, char const* fieldname, int32 defvalue); @@ -655,6 +658,7 @@ class World // next daily quests reset time time_t m_NextDailyQuestReset; time_t m_NextWeeklyQuestReset; + time_t m_NextMonthlyQuestReset; //Player Queue Queue m_QueuedPlayer; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b9457002b..53ff96d3b 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "10654" + #define REVISION_NR "10655" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 32d57dd32..7617b1863 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ - #define REVISION_DB_CHARACTERS "required_10568_01_characters_character_tutorial" + #define REVISION_DB_CHARACTERS "required_10655_01_characters_character_queststatus_monthly" #define REVISION_DB_MANGOS "required_10654_01_mangos_game_event_creature_quest" #define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version" #endif // __REVISION_SQL_H__