diff options
author | n0n4m3 <none@none> | 2010-04-15 08:26:30 +0400 |
---|---|---|
committer | n0n4m3 <none@none> | 2010-04-15 08:26:30 +0400 |
commit | 8abcca0a06d48d4c9d7039bf7a6b27c57f7eb878 (patch) | |
tree | 849deb42364506716453fd34131d4fea0af972f8 | |
parent | 6bcb297de4d5231373a3e2bf2b40e527b91cdf46 (diff) |
Another fix quest flags, Implement support weekly quests cooldowns(Original patch by GriffonHeart), also code cleanups.
--HG--
branch : trunk
-rw-r--r-- | sql/characters.sql | 22 | ||||
-rw-r--r-- | sql/updates/7914_characters_character_queststatus_weekly.sql | 7 | ||||
-rw-r--r-- | sql/updates/7914_characters_worldstates.sql | 1 | ||||
-rw-r--r-- | src/game/CharacterHandler.cpp | 1 | ||||
-rw-r--r-- | src/game/GossipDef.cpp | 77 | ||||
-rw-r--r-- | src/game/ObjectMgr.cpp | 30 | ||||
-rw-r--r-- | src/game/Player.cpp | 89 | ||||
-rw-r--r-- | src/game/Player.h | 13 | ||||
-rw-r--r-- | src/game/QuestDef.h | 2 | ||||
-rw-r--r-- | src/game/QuestHandler.cpp | 2 | ||||
-rw-r--r-- | src/game/World.cpp | 40 | ||||
-rw-r--r-- | src/game/World.h | 4 | ||||
-rw-r--r-- | src/shared/Common.h | 1 |
13 files changed, 242 insertions, 47 deletions
diff --git a/sql/characters.sql b/sql/characters.sql index a57adbf0744..c6dafbe533d 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -914,6 +914,27 @@ LOCK TABLES `character_queststatus_daily` WRITE; UNLOCK TABLES; -- +-- Table structure for table `character_queststatus_weekly` +-- + +DROP TABLE IF EXISTS `character_queststatus_weekly`; +CREATE TABLE `character_queststatus_weekly` ( + `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_weekly` +-- + +LOCK TABLES `character_queststatus_weekly` WRITE; +/*!40000 ALTER TABLE `character_queststatus_weekly` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_queststatus_weekly` ENABLE KEYS */; +UNLOCK TABLES; + +-- -- Table structure for table `character_reputation` -- @@ -1915,6 +1936,7 @@ DROP TABLE IF EXISTS `worldstates`; CREATE TABLE `worldstates` ( `entry` mediumint(11) UNSIGNED NOT NULL DEFAULT '0', `value` bigint(40) UNSIGNED NOT NULL DEFAULT '0', + `NextWeeklyQuestResetTime` bigint(40) unsigned NOT NULL default '0', `comment` text NOT NULL, PRIMARY KEY (`entry`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Variable Saves'; diff --git a/sql/updates/7914_characters_character_queststatus_weekly.sql b/sql/updates/7914_characters_character_queststatus_weekly.sql new file mode 100644 index 00000000000..1bced542b9f --- /dev/null +++ b/sql/updates/7914_characters_character_queststatus_weekly.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS `character_queststatus_weekly`; +CREATE TABLE `character_queststatus_weekly` ( + `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'; diff --git a/sql/updates/7914_characters_worldstates.sql b/sql/updates/7914_characters_worldstates.sql new file mode 100644 index 00000000000..5b150518e87 --- /dev/null +++ b/sql/updates/7914_characters_worldstates.sql @@ -0,0 +1 @@ +ALTER TABLE `worldstates` ADD COLUMN `NextWeeklyQuestResetTime` bigint(40) unsigned NOT NULL default '0' AFTER `value`; diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 2ccbce54e10..a823cd5c0e4 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -76,6 +76,7 @@ bool LoginQueryHolder::Initialize() res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, "SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'", GUID_LOPART(m_guid)); 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,time FROM character_queststatus_daily WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADWEKLYQUESTSTATUS,"SELECT quest FROM character_queststatus_weekly 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 a.button,a.action,a.type FROM character_action as a, characters as c WHERE a.guid = c.guid AND a.spec = c.activespec AND a.guid = '%u' ORDER BY button", GUID_LOPART(m_guid)); diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp index bfb81dfa724..f72ae563622 100644 --- a/src/game/GossipDef.cpp +++ b/src/game/GossipDef.cpp @@ -166,8 +166,8 @@ void PlayerMenu::SendGossipMenu(uint32 TitleTextId, uint64 objectGUID) data << uint32(questID); data << uint32(qItem.m_qIcon); - data << uint32(pSession->GetPlayer()->GetQuestLevel(pQuest)); - data << uint32(pQuest->GetClientFlags()); // 3.3.3 quest flags + data << int32(pQuest->GetQuestLevel()); + data << uint32(pQuest->GetFlags()); // 3.3.3 quest flags data << uint8(0); // 3.3.3 changes icon: blue question or yellow exclamation std::string Title = pQuest->GetTitle(); @@ -387,34 +387,40 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote eEmote, const std::string& Title data << Title; data << uint32(eEmote._Delay); // player emote data << uint32(eEmote._Emote); // NPC emote - data << uint8 (mQuestMenu.MenuItemCount()); - for (uint32 iI = 0; iI < mQuestMenu.MenuItemCount(); ++iI) + size_t count_pos = data.wpos(); + data << uint8 ( mQuestMenu.MenuItemCount()); + uint32 count = 0; + for (; count < mQuestMenu.MenuItemCount(); ++count) { - QuestMenuItem const& qmi = mQuestMenu.GetItem(iI); + QuestMenuItem const& qmi = mQuestMenu.GetItem(count); uint32 questID = qmi.m_qId; - Quest const *pQuest = objmgr.GetQuestTemplate(questID); - - std::string title = pQuest ? pQuest->GetTitle() : ""; - int loc_idx = pSession->GetSessionDbLocaleIndex(); - if (loc_idx >= 0) + if (Quest const *pQuest = objmgr.GetQuestTemplate(questID)) { - if (QuestLocale const *ql = objmgr.GetQuestLocale(questID)) + std::string title = pQuest->GetTitle(); + + int loc_idx = pSession->GetSessionDbLocaleIndex(); + if (loc_idx >= 0) { - if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) - title=ql->Title[loc_idx]; + if (QuestLocale const *ql = objmgr.GetQuestLocale(questID)) + { + if (ql->Title.size() > (size_t)loc_idx && !ql->Title[loc_idx].empty()) + title = ql->Title[loc_idx]; + } } - } - data << uint32(questID); - data << uint32(qmi.m_qIcon); - data << uint32(pSession->GetPlayer()->GetQuestLevel(pQuest)); - data << uint32(pQuest->GetClientFlags()); // 3.3.3 quest flags - data << uint8(0); // 3.3.3 changes icon: blue question or yellow exclamation - data << title; + data << uint32(questID); + data << uint32(qmi.m_qIcon); + data << int32(pQuest->GetQuestLevel()); + data << uint32(pQuest->GetFlags()); // 3.3.3 quest flags + data << uint8(0); // 3.3.3 changes icon: blue question or yellow exclamation + data << title; + } } + + data.put<uint8>(count_pos, count); pSession->SendPacket(&data); sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_LIST NPC Guid=%u", GUID_LOPART(npcGUID)); } @@ -461,15 +467,16 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const *pQuest, uint64 npcGUID, data << Details; data << Objectives; data << uint8(ActivateAccept ? 1 : 0); // auto finish - data << uint32(pQuest->GetClientFlags()); // 3.3.3 questFlags + data << uint32(pQuest->GetFlags()); // 3.3.3 questFlags data << uint32(pQuest->GetSuggestedPlayers()); - data << uint8(0); // IsFinished, value is sent back to server in quest accept packet + data << uint8(0); // IsFinished? value is sent back to server in quest accept packet if (pQuest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) { data << uint32(0); // Rewarded chosen items hidden data << uint32(0); // Rewarded items hidden data << uint32(0); // Rewarded money hidden + data << uint32(0); // Rewarded XP hidden } else { @@ -478,10 +485,14 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const *pQuest, uint64 npcGUID, data << uint32(pQuest->GetRewChoiceItemsCount()); for (uint32 i=0; i < QUEST_REWARD_CHOICES_COUNT; ++i) { - if (!pQuest->RewChoiceItemId[i]) continue; + if (!pQuest->RewChoiceItemId[i]) + continue; + data << uint32(pQuest->RewChoiceItemId[i]); data << uint32(pQuest->RewChoiceItemCount[i]); + IProto = objmgr.GetItemPrototype(pQuest->RewChoiceItemId[i]); + if (IProto) data << uint32(IProto->DisplayInfoID); else @@ -489,12 +500,17 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const *pQuest, uint64 npcGUID, } data << uint32(pQuest->GetRewItemsCount()); + for (uint32 i=0; i < QUEST_REWARDS_COUNT; ++i) { - if (!pQuest->RewItemId[i]) continue; + if (!pQuest->RewItemId[i]) + continue; + data << uint32(pQuest->RewItemId[i]); data << uint32(pQuest->RewItemCount[i]); + IProto = objmgr.GetItemPrototype(pQuest->RewItemId[i]); + if (IProto) data << uint32(IProto->DisplayInfoID); else @@ -603,12 +619,12 @@ void PlayerMenu::SendQuestQueryResponse(Quest const *pQuest) data << uint32(Trinity::Honor::hk_honor_at_level(pSession->GetPlayer()->getLevel(), pQuest->GetRewHonorableKills())); data << float(0); // new reward honor (multipled by ~62 at client side) data << uint32(pQuest->GetSrcItemId()); // source item id - data << uint32(pQuest->GetClientFlags()); // quest flags + data << uint32(pQuest->GetFlags() & 0xFFFF); // quest flags data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles) data << uint32(pQuest->GetPlayersSlain()); // players slain data << uint32(pQuest->GetBonusTalents()); // bonus talents data << uint32(pQuest->GetRewArenaPoints()); // bonus arena points - data << uint32(0); // unknown + data << uint32(0); // review rep show mask int iI; @@ -708,7 +724,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* pQuest, uint64 npcGUID, data << OfferRewardText; data << uint8(EnableNext ? 1 : 0); // Auto Finish - data << uint32(pQuest->GetClientFlags()); // 3.3.3 questFlags + data << uint32(pQuest->GetFlags()); // 3.3.3 questFlags data << uint32(pQuest->GetSuggestedPlayers()); // SuggestedGroupNum uint32 EmoteCount = 0; @@ -828,7 +844,7 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const *pQuest, uint64 npcGUID, else data << uint32(0x00); - data << uint32(pQuest->GetClientFlags()); // 3.3.3 questFlags + data << uint32(pQuest->GetFlags()); // 3.3.3 questFlags data << uint32(pQuest->GetSuggestedPlayers()); // SuggestedGroupNum // Required Money @@ -838,8 +854,11 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const *pQuest, uint64 npcGUID, ItemPrototype const *pItem; for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) { - if (!pQuest->ReqItemId[i]) continue; + if (!pQuest->ReqItemId[i]) + continue; + pItem = objmgr.GetItemPrototype(pQuest->ReqItemId[i]); + data << uint32(pQuest->ReqItemId[i]); data << uint32(pQuest->ReqItemCount[i]); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index beb4ca2839e..d1b2b1c525b 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -3653,26 +3653,41 @@ void ObjectMgr::LoadQuests() sLog.outErrorDb("Quest %u has `Method` = %u, expected values are 0, 1 or 2.",qinfo->GetQuestId(),qinfo->GetQuestMethod()); } - if (qinfo->GetFlags() & ~QUEST_TRINITY_FLAGS_DB_ALLOWED) + if (qinfo->QuestFlags & ~QUEST_TRINITY_FLAGS_DB_ALLOWED) { sLog.outErrorDb("Quest %u has `SpecialFlags` = %u > max allowed value. Correct `SpecialFlags` to value <= %u", - qinfo->GetQuestId(),qinfo->GetFlags(),QUEST_TRINITY_FLAGS_DB_ALLOWED >> 20); + qinfo->GetQuestId(),qinfo->QuestFlags >> 20, QUEST_TRINITY_FLAGS_DB_ALLOWED >> 20); qinfo->QuestFlags &= QUEST_TRINITY_FLAGS_DB_ALLOWED; } - if (qinfo->GetFlags() & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY)) + if (qinfo->QuestFlags & QUEST_FLAGS_DAILY && qinfo->QuestFlags & QUEST_FLAGS_WEEKLY) { - if (!(qinfo->GetFlags() & QUEST_TRINITY_FLAGS_REPEATABLE)) + sLog.outErrorDb("Weekly Quest %u is marked as daily quest in `QuestFlags`, removed daily flag.",qinfo->GetQuestId()); + qinfo->QuestFlags &= ~QUEST_FLAGS_DAILY; + } + + if (qinfo->QuestFlags & QUEST_FLAGS_DAILY) + { + if (!(qinfo->QuestFlags & QUEST_TRINITY_FLAGS_REPEATABLE)) { sLog.outErrorDb("Daily Quest %u not marked as repeatable in `SpecialFlags`, added.",qinfo->GetQuestId()); - qinfo->SetFlag(QUEST_TRINITY_FLAGS_REPEATABLE); + qinfo->QuestFlags |= QUEST_TRINITY_FLAGS_REPEATABLE; + } + } + + if (qinfo->QuestFlags & QUEST_FLAGS_WEEKLY) + { + if (!(qinfo->QuestFlags & QUEST_TRINITY_FLAGS_REPEATABLE)) + { + sLog.outErrorDb("Weekly Quest %u not marked as repeatable in `SpecialFlags`, added.",qinfo->GetQuestId()); + qinfo->QuestFlags |= QUEST_TRINITY_FLAGS_REPEATABLE; } } - if (qinfo->GetFlags() & QUEST_FLAGS_AUTO_REWARDED) + if (qinfo->QuestFlags & QUEST_FLAGS_AUTO_REWARDED) { // at auto-reward can be rewarded only RewChoiceItemId[0] - for (uint8 j = 1; j < QUEST_REWARD_CHOICES_COUNT; ++j) + for(int j = 1; j < QUEST_REWARD_CHOICES_COUNT; ++j ) { if (uint32 id = qinfo->RewChoiceItemId[j]) { @@ -4450,7 +4465,6 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename) continue; } - // if (!objmgr.GetMangosStringLocale(tmp.dataint)) will checked after db_script_string loading break; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 10aac3aa60b..405e144c75a 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1198,7 +1198,7 @@ void Player::Update(uint32 p_time) if (!m_timedquests.empty()) { - std::set<uint32>::iterator iter = m_timedquests.begin(); + QuestSet::iterator iter = m_timedquests.begin(); while (iter != m_timedquests.end()) { QuestStatusData& q_status = mQuestStatus[*iter]; @@ -13578,7 +13578,7 @@ void Player::SendPreparedQuest(uint64 guid) PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, CanRewardQuest(pQuest, false), true); // Send completable on repeatable and autoCompletable quest if player don't have quest // TODO: verify if check for !pQuest->IsDaily() is really correct (possibly not) - else if (pQuest->IsAutoComplete() && pQuest->IsRepeatable() && !pQuest->IsDaily()) + else if (pQuest->IsAutoComplete() && pQuest->IsRepeatable() && !pQuest->IsDailyOrWeekly()) PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, CanCompleteRepeatableQuest(pQuest), true); else PlayerTalkClass->SendQuestGiverQuestDetails(pQuest, guid, true); @@ -13696,7 +13696,7 @@ bool Player::CanSeeStartQuest(Quest const *pQuest) if (SatisfyQuestRace(pQuest, false) && SatisfyQuestSkillOrClass(pQuest, false) && SatisfyQuestExclusiveGroup(pQuest, false) && SatisfyQuestReputation(pQuest, false) && SatisfyQuestPreviousQuest(pQuest, false) && SatisfyQuestNextChain(pQuest, false) && - SatisfyQuestPrevChain(pQuest, false) && SatisfyQuestDay(pQuest, false)) + SatisfyQuestPrevChain(pQuest, false) && SatisfyQuestDay(pQuest, false) && SatisfyQuestWeek(pQuest, false)) { return getLevel() + sWorld.getConfig(CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF) >= pQuest->GetMinLevel(); } @@ -13711,7 +13711,7 @@ bool Player::CanTakeQuest(Quest const *pQuest, bool msg) && SatisfyQuestSkillOrClass(pQuest, msg) && SatisfyQuestReputation(pQuest, msg) && SatisfyQuestPreviousQuest(pQuest, msg) && SatisfyQuestTimed(pQuest, msg) && SatisfyQuestNextChain(pQuest, msg) && SatisfyQuestPrevChain(pQuest, msg) - && SatisfyQuestDay(pQuest, msg); + && SatisfyQuestDay(pQuest, msg) && SatisfyQuestWeek(pQuest, msg); } bool Player::CanAddQuest(Quest const *pQuest, bool msg) @@ -13831,7 +13831,7 @@ bool Player::CanRewardQuest(Quest const *pQuest, bool msg) return false; // daily quest can't be rewarded (25 daily quest already completed) - if (!SatisfyQuestDay(pQuest,true)) + if (!SatisfyQuestDay(pQuest,true) || !SatisfyQuestWeek(pQuest,true)) return false; // rewarded and not repeatable quest (only cheating case, then ignore without message) @@ -14126,6 +14126,9 @@ void Player::RewardQuest(Quest const *pQuest, uint32 reward, Object* questGiver, GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, 1); } + if (pQuest->IsWeekly()) + SetWeeklyQuestStatus(quest_id); + if (!pQuest->IsRepeatable()) SetQuestStatus(quest_id, QUEST_STATUS_COMPLETE); else @@ -14472,10 +14475,11 @@ 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 = objmgr.GetQuestTemplate(exclude_Id); - if (!SatisfyQuestDay(Nquest, false)) + if (!SatisfyQuestDay(Nquest, false) || !SatisfyQuestWeek(Nquest, false)) { if (msg) SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ); + return false; } @@ -14574,6 +14578,15 @@ bool Player::SatisfyQuestDay(Quest const* qInfo, bool msg) return true; } +bool Player::SatisfyQuestWeek( Quest const* qInfo, bool msg ) +{ + if (!qInfo->IsWeekly() || m_weeklyquests.empty()) + return true; + + // if not found in cooldown list + return m_weeklyquests.find(qInfo->GetQuestId()) == m_weeklyquests.end(); +} + bool Player::GiveQuestSourceItem(Quest const *pQuest) { uint32 srcitem = pQuest->GetSrcItemId(); @@ -16047,6 +16060,7 @@ bool Player::LoadFromDB(uint32 guid, SqlQueryHolder *holder) // after spell load, learn rewarded spell if need also _LoadQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS)); _LoadDailyQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS)); + _LoadWeeklyQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADWEKLYQUESTSTATUS)); // after spell and quest load InitTalentForLevel(); @@ -16820,6 +16834,33 @@ void Player::_LoadDailyQuestStatus(QueryResult_AutoPtr result) m_DailyQuestChanged = false; } +void Player::_LoadWeeklyQuestStatus(QueryResult_AutoPtr result) +{ + m_weeklyquests.clear(); + + if (result) + { + do + { + Field *fields = result->Fetch(); + + uint32 quest_id = fields[0].GetUInt32(); + + Quest const* pQuest = objmgr.GetQuestTemplate(quest_id); + + if (!pQuest) + continue; + + m_weeklyquests.insert(quest_id); + + sLog.outDebug("Weekly quest {%u} cooldown for player (GUID: %u)", quest_id, GetGUIDLow()); + } + while(result->NextRow()); + } + + m_WeeklyQuestChanged = false; +} + void Player::_LoadSpells(QueryResult_AutoPtr result) { //QueryResult *result = CharacterDatabase.PQuery("SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'",GetGUIDLow()); @@ -17434,6 +17475,7 @@ void Player::SaveToDB() _SaveInventory(); _SaveQuestStatus(); _SaveDailyQuestStatus(); + _SaveWeeklyQuestStatus(); _SaveTalents(); _SaveSpells(); _SaveSpellCooldowns(); @@ -17730,6 +17772,24 @@ void Player::_SaveDailyQuestStatus() GetGUIDLow(), GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx),uint64(m_lastDailyQuestTime)); } +void Player::_SaveWeeklyQuestStatus() +{ + if (!m_WeeklyQuestChanged || m_weeklyquests.empty()) + return; + + // we don't need transactions here. + CharacterDatabase.PExecute("DELETE FROM character_queststatus_weekly WHERE guid = '%u'",GetGUIDLow()); + + for (QuestSet::const_iterator iter = m_weeklyquests.begin(); iter != m_weeklyquests.end(); ++iter) + { + uint32 quest_id = *iter; + + CharacterDatabase.PExecute("INSERT INTO character_queststatus_weekly (guid,quest) VALUES ('%u', '%u')", GetGUIDLow(), quest_id); + } + + m_WeeklyQuestChanged = false; +} + void Player::_SaveSkills() { // we don't need transactions here. @@ -20905,6 +20965,13 @@ void Player::SetDailyQuestStatus(uint32 quest_id) } } + +void Player::SetWeeklyQuestStatus(uint32 quest_id) +{ + m_weeklyquests.insert(quest_id); + m_WeeklyQuestChanged = true; +} + void Player::ResetDailyQuestStatus() { for (uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx) @@ -20915,6 +20982,16 @@ void Player::ResetDailyQuestStatus() m_lastDailyQuestTime = 0; } +void Player::ResetWeeklyQuestStatus() +{ + if (m_weeklyquests.empty()) + return; + + m_weeklyquests.clear(); + // DB data deleted in caller + m_WeeklyQuestChanged = false; +} + BattleGround* Player::GetBattleGround() const { if (GetBattleGroundId() == 0) diff --git a/src/game/Player.h b/src/game/Player.h index bccf9030fe1..119c70ffe5a 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -851,7 +851,8 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOADTALENTS = 23, PLAYER_LOGIN_QUERY_LOADACCOUNTDATA = 24, PLAYER_LOGIN_QUERY_LOADSKILLS = 25, - MAX_PLAYER_LOGIN_QUERY = 26 + PLAYER_LOGIN_QUERY_LOADWEKLYQUESTSTATUS = 26, + MAX_PLAYER_LOGIN_QUERY = 27 }; enum PlayerDelayedOperations @@ -1328,6 +1329,7 @@ class Player : public Unit, public GridObject<Player> bool SatisfyQuestNextChain(Quest const* qInfo, bool msg); bool SatisfyQuestPrevChain(Quest const* qInfo, bool msg); bool SatisfyQuestDay(Quest const* qInfo, bool msg); + bool SatisfyQuestWeek(Quest const* qInfo, bool msg); bool GiveQuestSourceItem(Quest const *pQuest); bool TakeQuestSourceItem(uint32 quest_id, bool msg); bool GetQuestRewardStatus(uint32 quest_id) const; @@ -1335,7 +1337,9 @@ class Player : public Unit, public GridObject<Player> void SetQuestStatus(uint32 quest_id, QuestStatus status); void SetDailyQuestStatus(uint32 quest_id); + void SetWeeklyQuestStatus(uint32 quest_id); void ResetDailyQuestStatus(); + void ResetWeeklyQuestStatus(); 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); } @@ -2363,7 +2367,9 @@ 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. - std::set<uint32> m_timedquests; + typedef std::set<uint32> QuestSet; + QuestSet m_timedquests; + QuestSet m_weeklyquests; uint64 m_divider; uint32 m_ingametime; @@ -2382,6 +2388,7 @@ class Player : public Unit, public GridObject<Player> void _LoadMailedItems(Mail *mail); void _LoadQuestStatus(QueryResult_AutoPtr result); void _LoadDailyQuestStatus(QueryResult_AutoPtr result); + void _LoadWeeklyQuestStatus(QueryResult_AutoPtr result); void _LoadGroup(QueryResult_AutoPtr result); void _LoadSkills(QueryResult_AutoPtr result); void _LoadSpells(QueryResult_AutoPtr result); @@ -2405,6 +2412,7 @@ class Player : public Unit, public GridObject<Player> void _SaveMail(); void _SaveQuestStatus(); void _SaveDailyQuestStatus(); + void _SaveWeeklyQuestStatus(); void _SaveSkills(); void _SaveSpells(); void _SaveEquipmentSets(); @@ -2508,6 +2516,7 @@ class Player : public Unit, public GridObject<Player> uint32 tradeGold; bool m_DailyQuestChanged; + bool m_WeeklyQuestChanged; time_t m_lastDailyQuestTime; uint32 m_drunkTimer; diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h index c8537c8eff3..c694c65abb9 100644 --- a/src/game/QuestDef.h +++ b/src/game/QuestDef.h @@ -239,9 +239,9 @@ class Quest bool IsRepeatable() const { return QuestFlags & QUEST_TRINITY_FLAGS_REPEATABLE; } bool IsAutoComplete() const { return QuestMethod ? false : true; } uint32 GetFlags() const { return QuestFlags; } - uint32 GetClientFlags() const { return QuestFlags & 0xFFFFF; } bool IsDaily() const { return QuestFlags & QUEST_FLAGS_DAILY; } bool IsWeekly() const { return QuestFlags & QUEST_FLAGS_WEEKLY; } + bool IsDailyOrWeekly() const { return QuestFlags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY); } bool IsAutoAccept() const { return QuestFlags & QUEST_FLAGS_AUTO_ACCEPT; } // multiple values diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index 53bb4335169..c7632cf10f0 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -619,7 +619,7 @@ uint32 WorldSession::getDialogStatus(Player *pPlayer, Object* questgiver, uint32 result2 = DIALOG_STATUS_REWARD_REP; else if (pPlayer->getLevel() <= ((pPlayer->GetQuestLevel(pQuest) == -1) ? pPlayer->getLevel() : pPlayer->GetQuestLevel(pQuest) + sWorld.getConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF))) { - if (pQuest->IsDaily()) + if (pQuest->HasFlag(QUEST_FLAGS_DAILY) || pQuest->HasFlag(QUEST_FLAGS_WEEKLY)) result2 = DIALOG_STATUS_AVAILABLE_REP; else result2 = DIALOG_STATUS_AVAILABLE; diff --git a/src/game/World.cpp b/src/game/World.cpp index 057e3489216..7419e65772d 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -105,6 +105,7 @@ World::World() m_MaxPlayerCount = 0; m_resultQueue = NULL; m_NextDailyQuestReset = 0; + m_NextWeeklyQuestReset = 0; m_scheduledScripts = 0; m_defaultDbcLocale = LOCALE_enUS; @@ -1680,6 +1681,9 @@ void World::SetInitialWorldSettings() sLog.outString("Calculate next daily quest reset time..."); InitDailyQuestResetTime(); + sLog.outString("Calculate next weekly quest reset time..." ); + InitWeeklyQuestResetTime(); + sLog.outString("Starting objects Pooling system..."); poolhandler.Initialize(); @@ -1844,6 +1848,12 @@ void World::Update(uint32 diff) m_NextDailyQuestReset += DAY; } + if (m_gameTime > m_NextWeeklyQuestReset) + { + ResetWeeklyQuests(); + m_NextWeeklyQuestReset += WEEK; + } + /// <ul><li> Handle auctions when the timer has passed if (m_timers[WUPDATE_AUCTIONS].Passed()) { @@ -2486,6 +2496,25 @@ void World::_UpdateRealmCharCount(QueryResult_AutoPtr resultCharCount, uint32 ac } } +void World::InitWeeklyQuestResetTime() +{ + QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT NextWeeklyQuestResetTime FROM worldstates"); + if (!result) + { + m_NextWeeklyQuestReset = time_t(m_gameTime + WEEK); + CharacterDatabase.PExecute("INSERT INTO worldstates (NextWeeklyQuestResetTime) VALUES ('"UI64FMTD"')", uint64(m_NextWeeklyQuestReset)); + } + else + { + m_NextWeeklyQuestReset = time_t((*result)[0].GetUInt64()); + + // move to just before if need + time_t cur = time(NULL); + if (m_NextWeeklyQuestReset < cur) + m_NextWeeklyQuestReset += WEEK * ((cur - m_NextWeeklyQuestReset) / WEEK); + } +} + void World::InitDailyQuestResetTime() { time_t mostRecentQuestTime; @@ -2543,6 +2572,17 @@ void World::UpdateAllowedSecurity() } } +void World::ResetWeeklyQuests() +{ + CharacterDatabase.Execute("DELETE FROM character_queststatus_weekly"); + for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) + if (itr->second->GetPlayer()) + itr->second->GetPlayer()->ResetWeeklyQuestStatus(); + + m_NextWeeklyQuestReset = time_t(m_NextWeeklyQuestReset + WEEK); + CharacterDatabase.PExecute("UPDATE worldstates SET NextWeeklyQuestResetTime = '"UI64FMTD"'", uint64(m_NextWeeklyQuestReset)); +} + void World::SetPlayerLimit(int32 limit, bool needUpdate) { m_playerLimit = limit; diff --git a/src/game/World.h b/src/game/World.h index 0a336395921..7477c317617 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -550,6 +550,7 @@ class World void SetRecordDiffInterval(int32 t) { if (t >= 0) m_configs[CONFIG_INTERVAL_LOG_UPDATE] = (uint32)t; } /// Next daily quests reset time time_t GetNextDailyQuestsResetTime() const { return m_NextDailyQuestReset; } + time_t GetNextWeeklyQuestsResetTime() const { return m_NextWeeklyQuestReset; } /// Get the maximum skill level a player can reach uint16 GetConfigMaxSkillValue() const @@ -670,7 +671,9 @@ class World void _UpdateRealmCharCount(QueryResult_AutoPtr resultCharCount, uint32 accountId); void InitDailyQuestResetTime(); + void InitWeeklyQuestResetTime(); void ResetDailyQuests(); + void ResetWeeklyQuests(); private: static volatile bool m_stopEvent; static uint8 m_ExitCode; @@ -738,6 +741,7 @@ class World // next daily quests reset time time_t m_NextDailyQuestReset; + time_t m_NextWeeklyQuestReset; //Player Queue Queue m_QueuedPlayer; diff --git a/src/shared/Common.h b/src/shared/Common.h index 4310c426883..be61019cef0 100644 --- a/src/shared/Common.h +++ b/src/shared/Common.h @@ -165,6 +165,7 @@ enum TimeConstants MINUTE = 60, HOUR = MINUTE*60, DAY = HOUR*24, + WEEK = DAY*7, MONTH = DAY*30, YEAR = MONTH*12, IN_MILISECONDS = 1000 |