Core/Quests: Reset seasonal quests based on saved completion time and intended holiday start time
Port From (https://github.com/TrinityCore/TrinityCore/commit/49ad0d2d495a9f817ad2820f8e616f3a6564b480)
This commit is contained in:
@@ -101,7 +101,7 @@ namespace Framework.Database
|
|||||||
PrepareStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS_DAILY, "SELECT quest, time FROM character_queststatus_daily WHERE guid = ?");
|
PrepareStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS_DAILY, "SELECT quest, time FROM character_queststatus_daily WHERE guid = ?");
|
||||||
PrepareStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS_WEEKLY, "SELECT quest FROM character_queststatus_weekly WHERE guid = ?");
|
PrepareStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS_WEEKLY, "SELECT quest FROM character_queststatus_weekly WHERE guid = ?");
|
||||||
PrepareStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS_MONTHLY, "SELECT quest FROM character_queststatus_monthly WHERE guid = ?");
|
PrepareStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS_MONTHLY, "SELECT quest FROM character_queststatus_monthly WHERE guid = ?");
|
||||||
PrepareStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS_SEASONAL, "SELECT quest, event FROM character_queststatus_seasonal WHERE guid = ?");
|
PrepareStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS_SEASONAL, "SELECT quest, event, completedTime FROM character_queststatus_seasonal WHERE guid = ?");
|
||||||
PrepareStatement(CharStatements.DEL_CHARACTER_QUESTSTATUS_DAILY, "DELETE FROM character_queststatus_daily WHERE guid = ?");
|
PrepareStatement(CharStatements.DEL_CHARACTER_QUESTSTATUS_DAILY, "DELETE FROM character_queststatus_daily WHERE guid = ?");
|
||||||
PrepareStatement(CharStatements.DEL_CHARACTER_QUESTSTATUS_WEEKLY, "DELETE FROM character_queststatus_weekly WHERE guid = ?");
|
PrepareStatement(CharStatements.DEL_CHARACTER_QUESTSTATUS_WEEKLY, "DELETE FROM character_queststatus_weekly WHERE guid = ?");
|
||||||
PrepareStatement(CharStatements.DEL_CHARACTER_QUESTSTATUS_MONTHLY, "DELETE FROM character_queststatus_monthly WHERE guid = ?");
|
PrepareStatement(CharStatements.DEL_CHARACTER_QUESTSTATUS_MONTHLY, "DELETE FROM character_queststatus_monthly WHERE guid = ?");
|
||||||
@@ -109,11 +109,11 @@ namespace Framework.Database
|
|||||||
PrepareStatement(CharStatements.INS_CHARACTER_QUESTSTATUS_DAILY, "INSERT INTO character_queststatus_daily (guid, quest, time) VALUES (?, ?, ?)");
|
PrepareStatement(CharStatements.INS_CHARACTER_QUESTSTATUS_DAILY, "INSERT INTO character_queststatus_daily (guid, quest, time) VALUES (?, ?, ?)");
|
||||||
PrepareStatement(CharStatements.INS_CHARACTER_QUESTSTATUS_WEEKLY, "INSERT INTO character_queststatus_weekly (guid, quest) VALUES (?, ?)");
|
PrepareStatement(CharStatements.INS_CHARACTER_QUESTSTATUS_WEEKLY, "INSERT INTO character_queststatus_weekly (guid, quest) VALUES (?, ?)");
|
||||||
PrepareStatement(CharStatements.INS_CHARACTER_QUESTSTATUS_MONTHLY, "INSERT INTO character_queststatus_monthly (guid, quest) VALUES (?, ?)");
|
PrepareStatement(CharStatements.INS_CHARACTER_QUESTSTATUS_MONTHLY, "INSERT INTO character_queststatus_monthly (guid, quest) VALUES (?, ?)");
|
||||||
PrepareStatement(CharStatements.INS_CHARACTER_QUESTSTATUS_SEASONAL, "INSERT INTO character_queststatus_seasonal (guid, quest, event) VALUES (?, ?, ?)");
|
PrepareStatement(CharStatements.INS_CHARACTER_QUESTSTATUS_SEASONAL, "INSERT INTO character_queststatus_seasonal (guid, quest, event, completedTime) VALUES (?, ?, ?, ?)");
|
||||||
PrepareStatement(CharStatements.DEL_RESET_CHARACTER_QUESTSTATUS_DAILY, "DELETE FROM character_queststatus_daily");
|
PrepareStatement(CharStatements.DEL_RESET_CHARACTER_QUESTSTATUS_DAILY, "DELETE FROM character_queststatus_daily");
|
||||||
PrepareStatement(CharStatements.DEL_RESET_CHARACTER_QUESTSTATUS_WEEKLY, "DELETE FROM character_queststatus_weekly");
|
PrepareStatement(CharStatements.DEL_RESET_CHARACTER_QUESTSTATUS_WEEKLY, "DELETE FROM character_queststatus_weekly");
|
||||||
PrepareStatement(CharStatements.DEL_RESET_CHARACTER_QUESTSTATUS_MONTHLY, "DELETE FROM character_queststatus_monthly");
|
PrepareStatement(CharStatements.DEL_RESET_CHARACTER_QUESTSTATUS_MONTHLY, "DELETE FROM character_queststatus_monthly");
|
||||||
PrepareStatement(CharStatements.DEL_RESET_CHARACTER_QUESTSTATUS_SEASONAL_BY_EVENT, "DELETE FROM character_queststatus_seasonal WHERE event = ?");
|
PrepareStatement(CharStatements.DEL_RESET_CHARACTER_QUESTSTATUS_SEASONAL_BY_EVENT, "DELETE FROM character_queststatus_seasonal WHERE event = ? AND completedTime < ?");
|
||||||
|
|
||||||
PrepareStatement(CharStatements.SEL_CHARACTER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?");
|
PrepareStatement(CharStatements.SEL_CHARACTER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?");
|
||||||
PrepareStatement(CharStatements.SEL_CHARACTER_INVENTORY, "SELECT " + SelectItemInstanceContent + ", bag, slot FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE ci.guid = ? ORDER BY (ii.flags & 0x80000) ASC, bag ASC, slot ASC");
|
PrepareStatement(CharStatements.SEL_CHARACTER_INVENTORY, "SELECT " + SelectItemInstanceContent + ", bag, slot FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE ci.guid = ? ORDER BY (ii.flags & 0x80000) ASC, bag ASC, slot ASC");
|
||||||
|
|||||||
@@ -931,11 +931,16 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
uint quest_id = result.Read<uint>(0);
|
uint quest_id = result.Read<uint>(0);
|
||||||
uint event_id = result.Read<uint>(1);
|
uint event_id = result.Read<uint>(1);
|
||||||
|
long completedTime = result.Read<long>(2);
|
||||||
Quest quest = Global.ObjectMgr.GetQuestTemplate(quest_id);
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(quest_id);
|
||||||
if (quest == null)
|
if (quest == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
m_seasonalquests.Add(event_id, quest_id);
|
if (!m_seasonalquests.ContainsKey(event_id))
|
||||||
|
m_seasonalquests[event_id] = new();
|
||||||
|
|
||||||
|
m_seasonalquests[event_id][quest_id] = completedTime;
|
||||||
|
|
||||||
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(quest_id);
|
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(quest_id);
|
||||||
if (questBit != 0)
|
if (questBit != 0)
|
||||||
SetQuestCompletedBit(questBit, true);
|
SetQuestCompletedBit(questBit, true);
|
||||||
@@ -2128,13 +2133,17 @@ namespace Game.Entities
|
|||||||
if (m_seasonalquests.Empty())
|
if (m_seasonalquests.Empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var iter in m_seasonalquests)
|
foreach (var (eventId, dictionary) in m_seasonalquests)
|
||||||
{
|
{
|
||||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHARACTER_QUESTSTATUS_SEASONAL);
|
foreach (var (questId, completedTime) in dictionary)
|
||||||
stmt.AddValue(0, GetGUID().GetCounter());
|
{
|
||||||
stmt.AddValue(1, iter.Value);
|
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHARACTER_QUESTSTATUS_SEASONAL);
|
||||||
stmt.AddValue(2, iter.Key);
|
stmt.AddValue(0, GetGUID().GetCounter());
|
||||||
trans.Append(stmt);
|
stmt.AddValue(1, questId);
|
||||||
|
stmt.AddValue(2, eventId);
|
||||||
|
stmt.AddValue(3, completedTime);
|
||||||
|
trans.Append(stmt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void _SaveMonthlyQuestStatus(SQLTransaction trans)
|
void _SaveMonthlyQuestStatus(SQLTransaction trans)
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ namespace Game.Entities
|
|||||||
List<uint> m_timedquests = new();
|
List<uint> m_timedquests = new();
|
||||||
List<uint> m_weeklyquests = new();
|
List<uint> m_weeklyquests = new();
|
||||||
List<uint> m_monthlyquests = new();
|
List<uint> m_monthlyquests = new();
|
||||||
MultiMap<uint, uint> m_seasonalquests = new();
|
Dictionary<uint, Dictionary<uint, long>> m_seasonalquests = new();
|
||||||
Dictionary<uint, QuestStatusData> m_QuestStatus = new();
|
Dictionary<uint, QuestStatusData> m_QuestStatus = new();
|
||||||
MultiMap<(QuestObjectiveType Type, int ObjectID), QuestObjectiveStatusData> m_questObjectiveStatus = new();
|
MultiMap<(QuestObjectiveType Type, int ObjectID), QuestObjectiveStatusData> m_questObjectiveStatus = new();
|
||||||
Dictionary<uint, QuestSaveType> m_QuestStatusSave = new();
|
Dictionary<uint, QuestSaveType> m_QuestStatusSave = new();
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ using Game.Networking.Packets;
|
|||||||
using Game.Spells;
|
using Game.Spells;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Game.Entities
|
namespace Game.Entities
|
||||||
{
|
{
|
||||||
@@ -200,22 +201,29 @@ namespace Game.Entities
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetSeasonalQuestStatus(ushort event_id)
|
public void ResetSeasonalQuestStatus(ushort event_id, long eventStartTime)
|
||||||
{
|
{
|
||||||
|
// DB data deleted in caller
|
||||||
|
m_SeasonalQuestChanged = false;
|
||||||
|
|
||||||
var eventList = m_seasonalquests.LookupByKey(event_id);
|
var eventList = m_seasonalquests.LookupByKey(event_id);
|
||||||
if (eventList.Empty())
|
if (eventList.Empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (uint questId in eventList)
|
foreach (var (questId, completedTime) in eventList.ToList())
|
||||||
{
|
{
|
||||||
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
|
if (completedTime < eventStartTime)
|
||||||
if (questBit != 0)
|
{
|
||||||
SetQuestCompletedBit(questBit, false);
|
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
|
||||||
|
if (questBit != 0)
|
||||||
|
SetQuestCompletedBit(questBit, false);
|
||||||
|
|
||||||
|
eventList.Remove(questId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_seasonalquests.Remove(event_id);
|
if (eventList.Empty())
|
||||||
// DB data deleted in caller
|
m_seasonalquests.Remove(event_id);
|
||||||
m_SeasonalQuestChanged = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetMonthlyQuestStatus()
|
public void ResetMonthlyQuestStatus()
|
||||||
@@ -1673,7 +1681,7 @@ namespace Game.Entities
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// if not found in cooldown list
|
// if not found in cooldown list
|
||||||
return !list.Contains(qInfo.Id);
|
return !list.ContainsKey(qInfo.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SatisfyQuestExpansion(Quest qInfo, bool msg)
|
public bool SatisfyQuestExpansion(Quest qInfo, bool msg)
|
||||||
@@ -1864,7 +1872,7 @@ namespace Game.Entities
|
|||||||
ushort eventId = qInfo.GetEventIdForQuest();
|
ushort eventId = qInfo.GetEventIdForQuest();
|
||||||
if (m_seasonalquests.ContainsKey(eventId))
|
if (m_seasonalquests.ContainsKey(eventId))
|
||||||
{
|
{
|
||||||
m_seasonalquests.Remove(eventId, questId);
|
m_seasonalquests[eventId].Remove(questId);
|
||||||
m_SeasonalQuestChanged = true;
|
m_SeasonalQuestChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3041,7 +3049,10 @@ namespace Game.Entities
|
|||||||
if (quest == null)
|
if (quest == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_seasonalquests.Add(quest.GetEventIdForQuest(), quest_id);
|
if (!m_seasonalquests.ContainsKey(quest.GetEventIdForQuest()))
|
||||||
|
m_seasonalquests[quest.GetEventIdForQuest()] = new();
|
||||||
|
|
||||||
|
m_seasonalquests[quest.GetEventIdForQuest()][quest_id] = GameTime.GetGameTime();
|
||||||
m_SeasonalQuestChanged = true;
|
m_SeasonalQuestChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1100,7 +1100,7 @@ namespace Game
|
|||||||
RunSmartAIScripts(event_id, true);
|
RunSmartAIScripts(event_id, true);
|
||||||
|
|
||||||
// check for seasonal quest reset.
|
// check for seasonal quest reset.
|
||||||
Global.WorldMgr.ResetEventSeasonalQuests(event_id);
|
Global.WorldMgr.ResetEventSeasonalQuests(event_id, GetLastStartTime(event_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateEventNPCFlags(ushort event_id)
|
void UpdateEventNPCFlags(ushort event_id)
|
||||||
@@ -1676,6 +1676,21 @@ namespace Game
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long GetLastStartTime(ushort event_id)
|
||||||
|
{
|
||||||
|
if (event_id >= mGameEvent.Length)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (mGameEvent[event_id].state != GameEventState.Normal)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
DateTime now = GameTime.GetSystemTime();
|
||||||
|
DateTime eventInitialStart = Time.UnixTimeToDateTime(mGameEvent[event_id].start);
|
||||||
|
TimeSpan occurence = TimeSpan.FromMinutes(mGameEvent[event_id].occurence);
|
||||||
|
TimeSpan durationSinceLastStart = TimeSpan.FromTicks((now - eventInitialStart).Ticks % occurence.Ticks);
|
||||||
|
return Time.DateTimeToUnixTime(now - durationSinceLastStart);
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsHolidayActive(HolidayIds id)
|
public bool IsHolidayActive(HolidayIds id)
|
||||||
{
|
{
|
||||||
if (id == HolidayIds.None)
|
if (id == HolidayIds.None)
|
||||||
|
|||||||
@@ -2215,15 +2215,15 @@ namespace Game
|
|||||||
SetWorldState(WorldStates.CurrencyResetTime, (ulong)m_NextCurrencyReset);
|
SetWorldState(WorldStates.CurrencyResetTime, (ulong)m_NextCurrencyReset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetEventSeasonalQuests(ushort event_id)
|
public void ResetEventSeasonalQuests(ushort event_id, long eventStartTime)
|
||||||
{
|
{
|
||||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_RESET_CHARACTER_QUESTSTATUS_SEASONAL_BY_EVENT);
|
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_RESET_CHARACTER_QUESTSTATUS_SEASONAL_BY_EVENT);
|
||||||
stmt.AddValue(0, event_id);
|
stmt.AddValue(0, event_id);
|
||||||
|
stmt.AddValue(1, eventStartTime);
|
||||||
DB.Characters.Execute(stmt);
|
DB.Characters.Execute(stmt);
|
||||||
|
|
||||||
foreach (var session in m_sessions.Values)
|
foreach (var session in m_sessions.Values)
|
||||||
if (session.GetPlayer())
|
session.GetPlayer()?.ResetSeasonalQuestStatus(event_id, eventStartTime);
|
||||||
session.GetPlayer().ResetSeasonalQuestStatus(event_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetRandomBG()
|
void ResetRandomBG()
|
||||||
|
|||||||
@@ -1426,6 +1426,7 @@ CREATE TABLE `character_queststatus_seasonal` (
|
|||||||
`guid` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier',
|
`guid` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier',
|
||||||
`quest` int unsigned NOT NULL DEFAULT '0' COMMENT 'Quest Identifier',
|
`quest` int unsigned NOT NULL DEFAULT '0' COMMENT 'Quest Identifier',
|
||||||
`event` int unsigned NOT NULL DEFAULT '0' COMMENT 'Event Identifier',
|
`event` int unsigned NOT NULL DEFAULT '0' COMMENT 'Event Identifier',
|
||||||
|
`completedTime` bigint NOT NULL DEFAULT '0',
|
||||||
PRIMARY KEY (`guid`,`quest`),
|
PRIMARY KEY (`guid`,`quest`),
|
||||||
KEY `idx_guid` (`guid`)
|
KEY `idx_guid` (`guid`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Player System';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Player System';
|
||||||
@@ -3670,7 +3671,8 @@ INSERT INTO `updates` VALUES
|
|||||||
('2022_02_28_00_characters_2020_09_27_00_characters.sql','2292A1ED0E7F46DEC41384F75FA6D9461464EEB8','ARCHIVED','2022-02-28 12:43:58',0),
|
('2022_02_28_00_characters_2020_09_27_00_characters.sql','2292A1ED0E7F46DEC41384F75FA6D9461464EEB8','ARCHIVED','2022-02-28 12:43:58',0),
|
||||||
('2022_03_06_00_characters.sql','474AAF9D03E6A56017899C968DC9875368301934','ARCHIVED','2022-03-06 15:12:24',0),
|
('2022_03_06_00_characters.sql','474AAF9D03E6A56017899C968DC9875368301934','ARCHIVED','2022-03-06 15:12:24',0),
|
||||||
('2022_03_11_00_characters_2021_07_18_00_characters.sql','0BA579ED21F4E75AC2B4797421B5029568B3F6E2','RELEASED','2022-03-11 18:56:07',0),
|
('2022_03_11_00_characters_2021_07_18_00_characters.sql','0BA579ED21F4E75AC2B4797421B5029568B3F6E2','RELEASED','2022-03-11 18:56:07',0),
|
||||||
('2022_06_01_00_characters.sql','582AC6E256F8365F83AB70BA165CCC8B218E19FF','RELEASED','2022-06-01 21:16:56',0);
|
('2022_06_01_00_characters.sql','582AC6E256F8365F83AB70BA165CCC8B218E19FF','RELEASED','2022-06-01 21:16:56',0),
|
||||||
|
('2022_07_03_00_characters.sql','D3F04078C0846BCF7C8330AC20C39B8C3AEE7002','RELEASED','2022-07-03 23:37:24',0);
|
||||||
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
|
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
ALTER TABLE `character_queststatus_seasonal` ADD `completedTime` bigint NOT NULL DEFAULT '0' AFTER `event`;
|
||||||
|
|
||||||
|
UPDATE `character_queststatus_seasonal` SET `completedTime` = UNIX_TIMESTAMP();
|
||||||
|
|
||||||
|
DELETE FROM `worldstates` WHERE `entry` BETWEEN 1 AND 85;
|
||||||
Reference in New Issue
Block a user