Skip to content

Commit 03bfd20

Browse files
committed
Merge TC 3.3.5
2 parents 77f7318 + cbabaa0 commit 03bfd20

File tree

9 files changed

+65
-33
lines changed

9 files changed

+65
-33
lines changed

sql/base/characters_database.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,7 @@ CREATE TABLE `character_queststatus_seasonal` (
10881088
`guid` int unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier',
10891089
`quest` int unsigned NOT NULL DEFAULT '0' COMMENT 'Quest Identifier',
10901090
`event` int unsigned NOT NULL DEFAULT '0' COMMENT 'Event Identifier',
1091+
`completedTime` bigint NOT NULL DEFAULT '0',
10911092
PRIMARY KEY (`guid`,`quest`),
10921093
KEY `idx_guid` (`guid`)
10931094
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Player System';
@@ -2688,7 +2689,8 @@ INSERT INTO `updates` VALUES
26882689
('2024_04_10_00_characters.sql','E0D6E19ACE6759332402FA27C23B0F7745C49742','ARCHIVED','2024-04-10 16:07:02',0),
26892690
('2024_08_17_00_characters.sql','08705FBCB8504E8B1009FDAF955F56D734FAD782','ARCHIVED','2024-08-17 22:26:12',0),
26902691
('2024_10_03_00_characters.sql','408249A6992999A36EB94089D184972E8E0767A3','ARCHIVED','2024-10-03 11:10:18',0),
2691-
('2024_11_22_00_characters.sql','9EA2A4F88036D1D5F47EE8A6B634D52D0014986E','ARCHIVED','2024-11-22 23:18:14',0);
2692+
('2024_11_22_00_characters.sql','9EA2A4F88036D1D5F47EE8A6B634D52D0014986E','ARCHIVED','2024-11-22 23:18:14',0),
2693+
('2025_07_20_00_characters_2022_07_03_00_characters.sql','D3F04078C0846BCF7C8330AC20C39B8C3AEE7002','RELEASED','2022-07-03 23:37:24',0);
26922694
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
26932695
UNLOCK TABLES;
26942696

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TABLE `character_queststatus_seasonal` ADD `completedTime` bigint NOT NULL DEFAULT '0' AFTER `event`;
2+
3+
UPDATE `character_queststatus_seasonal` SET `completedTime` = UNIX_TIMESTAMP();
4+
5+
DELETE FROM `worldstates` WHERE `entry` BETWEEN 1 AND 85;

src/server/database/Database/Implementation/CharacterDatabase.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,19 @@ void CharacterDatabaseConnection::DoPrepareStatements()
7979
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_DAILY, "SELECT quest, time FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
8080
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_WEEKLY, "SELECT quest FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC);
8181
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_MONTHLY, "SELECT quest FROM character_queststatus_monthly WHERE guid = ?", CONNECTION_ASYNC);
82-
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_SEASONAL, "SELECT quest, event FROM character_queststatus_seasonal WHERE guid = ?", CONNECTION_ASYNC);
82+
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_SEASONAL, "SELECT quest, event, completedTime FROM character_queststatus_seasonal WHERE guid = ?", CONNECTION_ASYNC);
8383
PrepareStatement(CHAR_DEL_CHARACTER_QUESTSTATUS_DAILY, "DELETE FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
8484
PrepareStatement(CHAR_DEL_CHARACTER_QUESTSTATUS_WEEKLY, "DELETE FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC);
8585
PrepareStatement(CHAR_DEL_CHARACTER_QUESTSTATUS_MONTHLY, "DELETE FROM character_queststatus_monthly WHERE guid = ?", CONNECTION_ASYNC);
8686
PrepareStatement(CHAR_DEL_CHARACTER_QUESTSTATUS_SEASONAL, "DELETE FROM character_queststatus_seasonal WHERE guid = ?", CONNECTION_ASYNC);
8787
PrepareStatement(CHAR_INS_CHARACTER_QUESTSTATUS_DAILY, "INSERT INTO character_queststatus_daily (guid, quest, time) VALUES (?, ?, ?)", CONNECTION_ASYNC);
8888
PrepareStatement(CHAR_INS_CHARACTER_QUESTSTATUS_WEEKLY, "INSERT INTO character_queststatus_weekly (guid, quest) VALUES (?, ?)", CONNECTION_ASYNC);
8989
PrepareStatement(CHAR_INS_CHARACTER_QUESTSTATUS_MONTHLY, "INSERT INTO character_queststatus_monthly (guid, quest) VALUES (?, ?)", CONNECTION_ASYNC);
90-
PrepareStatement(CHAR_INS_CHARACTER_QUESTSTATUS_SEASONAL, "INSERT INTO character_queststatus_seasonal (guid, quest, event) VALUES (?, ?, ?)", CONNECTION_ASYNC);
90+
PrepareStatement(CHAR_INS_CHARACTER_QUESTSTATUS_SEASONAL, "INSERT INTO character_queststatus_seasonal (guid, quest, event, completedTime) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
9191
PrepareStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_DAILY, "DELETE FROM character_queststatus_daily", CONNECTION_ASYNC);
9292
PrepareStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_WEEKLY, "DELETE FROM character_queststatus_weekly", CONNECTION_ASYNC);
9393
PrepareStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_MONTHLY, "DELETE FROM character_queststatus_monthly", CONNECTION_ASYNC);
94-
PrepareStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_SEASONAL_BY_EVENT, "DELETE FROM character_queststatus_seasonal WHERE event = ?", CONNECTION_ASYNC);
94+
PrepareStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_SEASONAL_BY_EVENT, "DELETE FROM character_queststatus_seasonal WHERE event = ? AND completedTime < ?", CONNECTION_ASYNC);
9595

9696
PrepareStatement(CHAR_SEL_CHARACTER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?", CONNECTION_ASYNC);
9797
PrepareStatement(CHAR_SEL_CHARACTER_INVENTORY, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, bag, slot, "

src/server/game/Entities/Player/Player.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18647,11 +18647,12 @@ void Player::_LoadSeasonalQuestStatus(PreparedQueryResult result)
1864718647
Field* fields = result->Fetch();
1864818648
uint32 quest_id = fields[0].GetUInt32();
1864918649
uint32 event_id = fields[1].GetUInt32();
18650+
uint32 completedTime = fields[2].GetInt64();
1865018651
Quest const* quest = sObjectMgr->GetQuestTemplate(quest_id);
1865118652
if (!quest)
1865218653
continue;
1865318654

18654-
m_seasonalquests[event_id].insert(quest_id);
18655+
m_seasonalquests[event_id][quest_id] = completedTime;
1865518656
TC_LOG_DEBUG("entities.player.loading", "Player::_LoadSeasonalQuestStatus: Loaded seasonal quest cooldown (QuestID: {}) for player '{}' ({})",
1865618657
quest_id, GetName(), GetGUID().ToString());
1865718658
}
@@ -20030,18 +20031,20 @@ void Player::_SaveSeasonalQuestStatus(CharacterDatabaseTransaction trans)
2003020031
if (m_seasonalquests.empty())
2003120032
return;
2003220033

20033-
for (SeasonalEventQuestMap::const_iterator iter = m_seasonalquests.begin(); iter != m_seasonalquests.end(); ++iter)
20034+
for (SeasonalQuestMapByEvent::const_iterator iter = m_seasonalquests.begin(); iter != m_seasonalquests.end(); ++iter)
2003420035
{
2003520036
uint16 eventId = iter->first;
2003620037

20037-
for (SeasonalQuestSet::const_iterator itr = iter->second.begin(); itr != iter->second.end(); ++itr)
20038+
for (SeasonalQuestMapByQuest::const_iterator itr = iter->second.begin(); itr != iter->second.end(); ++itr)
2003820039
{
20039-
uint32 questId = *itr;
20040+
uint32 questId = itr->first;
20041+
time_t completedTime = itr->second;
2004020042

2004120043
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_QUESTSTATUS_SEASONAL);
2004220044
stmt->setUInt32(0, GetGUID().GetCounter());
2004320045
stmt->setUInt32(1, questId);
2004420046
stmt->setUInt32(2, eventId);
20047+
stmt->setInt64(3, completedTime);
2004520048
trans->Append(stmt);
2004620049
}
2004720050
}
@@ -23241,7 +23244,7 @@ void Player::SetSeasonalQuestStatus(uint32 quest_id)
2324123244
if (!quest)
2324223245
return;
2324323246

23244-
m_seasonalquests[quest->GetEventIdForQuest()].insert(quest_id);
23247+
m_seasonalquests[quest->GetEventIdForQuest()][quest_id] = GameTime::GetGameTime();
2324523248
m_SeasonalQuestChanged = true;
2324623249
}
2324723250

@@ -23273,14 +23276,29 @@ void Player::ResetWeeklyQuestStatus()
2327323276
m_WeeklyQuestChanged = false;
2327423277
}
2327523278

23276-
void Player::ResetSeasonalQuestStatus(uint16 event_id)
23279+
void Player::ResetSeasonalQuestStatus(uint16 event_id, time_t eventStartTime)
2327723280
{
23278-
if (m_seasonalquests.empty() || m_seasonalquests[event_id].empty())
23279-
return;
23280-
23281-
m_seasonalquests.erase(event_id);
2328223281
// DB data deleted in caller
2328323282
m_SeasonalQuestChanged = false;
23283+
23284+
auto eventItr = m_seasonalquests.find(event_id);
23285+
if (eventItr == m_seasonalquests.end())
23286+
return;
23287+
23288+
if (eventItr->second.empty())
23289+
return;
23290+
23291+
for (auto questItr = eventItr->second.begin(); questItr != eventItr->second.end(); )
23292+
{
23293+
if (questItr->second < eventStartTime)
23294+
questItr = eventItr->second.erase(questItr);
23295+
else
23296+
++questItr;
23297+
}
23298+
23299+
if (eventItr->second.empty())
23300+
m_seasonalquests.erase(eventItr);
23301+
2328423302
}
2328523303

2328623304
void Player::ResetMonthlyQuestStatus()

src/server/game/Entities/Player/Player.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,7 +1299,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
12991299
void ResetDailyQuestStatus();
13001300
void ResetWeeklyQuestStatus();
13011301
void ResetMonthlyQuestStatus();
1302-
void ResetSeasonalQuestStatus(uint16 event_id);
1302+
void ResetSeasonalQuestStatus(uint16 event_id, time_t eventStartTime);
13031303

13041304
uint16 FindQuestSlot(uint32 quest_id) const;
13051305
uint32 GetQuestSlotQuestId(uint16 slot) const;
@@ -2276,12 +2276,12 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
22762276

22772277
//We allow only one timed quest active at the same time. Below can then be simple value instead of set.
22782278
typedef std::set<uint32> QuestSet;
2279-
typedef std::set<uint32> SeasonalQuestSet;
2280-
typedef std::unordered_map<uint32, SeasonalQuestSet> SeasonalEventQuestMap;
2279+
typedef std::unordered_map<uint32, time_t> SeasonalQuestMapByQuest;
2280+
typedef std::unordered_map<uint32, SeasonalQuestMapByQuest> SeasonalQuestMapByEvent;
22812281
QuestSet m_timedquests;
22822282
QuestSet m_weeklyquests;
22832283
QuestSet m_monthlyquests;
2284-
SeasonalEventQuestMap m_seasonalquests;
2284+
SeasonalQuestMapByEvent m_seasonalquests;
22852285

22862286
ObjectGuid m_playerSharingQuest;
22872287
uint32 m_sharedQuestId;

src/server/game/Events/GameEventMgr.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,6 @@ bool GameEventMgr::StartEvent(uint16 event_id, bool overwrite)
144144
if (data.end <= data.start)
145145
data.end = data.start + data.length * MINUTE;
146146
}
147-
148-
// When event is started, set its worldstate to current time
149-
sWorld->setWorldState(event_id, GameTime::GetGameTime());
150147
#ifdef ELUNA
151148
if (IsActiveEvent(event_id))
152149
if (Eluna* e = sWorld->GetEluna())
@@ -192,9 +189,6 @@ void GameEventMgr::StopEvent(uint16 event_id, bool overwrite)
192189
RemoveActiveEvent(event_id);
193190
UnApplyEvent(event_id);
194191

195-
// When event is stopped, clean up its worldstate
196-
sWorld->setWorldState(event_id, 0);
197-
198192
if (overwrite && !serverwide_evt)
199193
{
200194
data.start = GameTime::GetGameTime() - data.length * MINUTE;
@@ -1125,8 +1119,6 @@ uint32 GameEventMgr::Update() // return the next e
11251119
}
11261120
else
11271121
{
1128-
// If event is inactive, periodically clean up its worldstate
1129-
sWorld->setWorldState(itr, 0);
11301122
//TC_LOG_DEBUG("misc", "GameEvent {} is not active", itr->first);
11311123
if (IsActiveEvent(itr))
11321124
deactivate.insert(itr);
@@ -1210,10 +1202,8 @@ void GameEventMgr::ApplyNewEvent(uint16 event_id)
12101202
//! Run SAI scripts with SMART_EVENT_GAME_EVENT_START
12111203
RunSmartAIScripts(event_id, true);
12121204

1213-
// If event's worldstate is 0, it means the event hasn't been started yet. In that case, reset seasonal quests.
1214-
// When event ends (if it expires or if it's stopped via commands) worldstate will be set to 0 again, ready for another seasonal quest reset.
1215-
if (sWorld->getWorldState(event_id) == 0)
1216-
sWorld->ResetEventSeasonalQuests(event_id);
1205+
// check for seasonal quest reset.
1206+
sWorld->ResetEventSeasonalQuests(event_id, GetLastStartTime(event_id));
12171207
}
12181208

12191209
void GameEventMgr::UpdateEventNPCFlags(uint16 event_id)
@@ -1847,6 +1837,21 @@ void GameEventMgr::SetHolidayEventTime(GameEventData& event)
18471837
}
18481838
}
18491839

1840+
time_t GameEventMgr::GetLastStartTime(uint16 event_id) const
1841+
{
1842+
if (event_id >= mGameEvent.size())
1843+
return 0;
1844+
1845+
if (mGameEvent[event_id].state != GAMEEVENT_NORMAL)
1846+
return 0;
1847+
1848+
SystemTimePoint now = GameTime::GetSystemTime();
1849+
SystemTimePoint eventInitialStart = std::chrono::system_clock::from_time_t(mGameEvent[event_id].start);
1850+
Minutes occurence(mGameEvent[event_id].occurence);
1851+
SystemTimePoint::duration durationSinceLastStart = (now - eventInitialStart) % occurence;
1852+
return std::chrono::system_clock::to_time_t(now - durationSinceLastStart);
1853+
}
1854+
18501855
bool IsHolidayActive(HolidayIds id)
18511856
{
18521857
if (id == HOLIDAY_NONE)

src/server/game/Events/GameEventMgr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ class TC_GAME_API GameEventMgr
148148
bool hasCreatureActiveEventExcept(ObjectGuid::LowType creature_guid, uint16 event_id);
149149
bool hasGameObjectActiveEventExcept(ObjectGuid::LowType go_guid, uint16 event_id);
150150
void SetHolidayEventTime(GameEventData& event);
151+
time_t GetLastStartTime(uint16 event_id) const;
151152

152153
typedef std::list<ObjectGuid::LowType> GuidList;
153154
typedef std::list<uint32> IdList;

src/server/game/World/World.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3454,17 +3454,18 @@ void World::InitGuildResetTime()
34543454
sWorld->setWorldState(WS_GUILD_DAILY_RESET_TIME, uint64(m_NextGuildReset));
34553455
}
34563456

3457-
void World::ResetEventSeasonalQuests(uint16 event_id)
3457+
void World::ResetEventSeasonalQuests(uint16 event_id, time_t eventStartTime)
34583458
{
34593459
TC_LOG_INFO("misc", "Seasonal quests reset for all characters.");
34603460

34613461
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_SEASONAL_BY_EVENT);
34623462
stmt->setUInt16(0, event_id);
3463+
stmt->setInt64(1, eventStartTime);
34633464
CharacterDatabase.Execute(stmt);
34643465

34653466
for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
34663467
if (itr->second->GetPlayer())
3467-
itr->second->GetPlayer()->ResetSeasonalQuestStatus(event_id);
3468+
itr->second->GetPlayer()->ResetSeasonalQuestStatus(event_id, eventStartTime);
34683469
}
34693470

34703471
void World::ResetRandomBG()

src/server/game/World/World.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ class TC_GAME_API World
764764

765765
uint32 GetCleaningFlags() const { return m_CleaningFlags; }
766766
void SetCleaningFlags(uint32 flags) { m_CleaningFlags = flags; }
767-
void ResetEventSeasonalQuests(uint16 event_id);
767+
void ResetEventSeasonalQuests(uint16 event_id, time_t eventStartTime);
768768

769769
void ReloadRBAC();
770770

0 commit comments

Comments
 (0)