aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerhood <mrambrius@gmail.com>2017-10-27 14:59:22 +0200
committerKeader <keader.android@gmail.com>2017-10-27 10:59:22 -0200
commit951fa46fe9b14a9e275ac9306b2346959e40e3e5 (patch)
tree920c104065c90d759e156222fc5b596d1327ad5e
parent04271388f8ba5160de0411451673a67a6828ae8a (diff)
Calendar/GameEvents: Store + send holiday data (#20117)
Close: #16845
-rw-r--r--sql/updates/world/3.3.5/2017_10_27_01_world.sql189
-rw-r--r--src/server/game/Events/GameEventMgr.cpp142
-rw-r--r--src/server/game/Events/GameEventMgr.h4
-rw-r--r--src/server/game/Handlers/CalendarHandler.cpp9
-rw-r--r--src/server/game/World/World.cpp3
5 files changed, 333 insertions, 14 deletions
diff --git a/sql/updates/world/3.3.5/2017_10_27_01_world.sql b/sql/updates/world/3.3.5/2017_10_27_01_world.sql
new file mode 100644
index 00000000000..b7c3e323bd9
--- /dev/null
+++ b/sql/updates/world/3.3.5/2017_10_27_01_world.sql
@@ -0,0 +1,189 @@
+DROP TABLE IF EXISTS `holiday_dates`;
+CREATE TABLE `holiday_dates` (
+ `id` INT UNSIGNED NOT NULL,
+ `date_id` TINYINT UNSIGNED NOT NULL,
+ `date_value` INT UNSIGNED NOT NULL,
+ PRIMARY KEY (`id`, `date_id`)
+);
+
+CREATE FUNCTION packDate (yy TINYINT UNSIGNED, mm TINYINT UNSIGNED, dd TINYINT UNSIGNED)
+RETURNS INT UNSIGNED DETERMINISTIC
+RETURN (yy << 24) | ((mm - 1) << 20) | ((dd - 1) << 14);
+
+INSERT INTO `holiday_dates` VALUES
+-- (181, 0, 120700928),
+-- (181, 1, 136675328),
+-- (181, 2, 154550272),
+-- (181, 3, 170967040),
+-- (181, 4, 188071936),
+-- (181, 5, 204587008),
+(181, 6, 220692480 + (1 << 14)), -- rescheduled
+(181, 7, 238338048 + (1 << 14)),
+(181, 8, 254869504 + (1 << 14)),
+(181, 9, 270958592 + (1 << 14)),
+(181, 10, 288635520), -- 7.2 (PTR) dbc
+(181, 11, 305166976),
+(181, 12, 322271872),
+
+-- (201, 0, 71319552),
+-- (201, 1, 88080384),
+-- (201, 2, 104284160),
+-- (201, 3, 121044992),
+-- (201, 4, 138461184),
+-- (201, 5, 155222016),
+-- (201, 6, 171982848),
+-- (201, 7, 188743680),
+-- (201, 8, 204931072),
+(201, 9, 221723264),
+(201, 10, 238484096),
+(201, 11, 255244928),
+(201, 12, 272661120),
+(201, 13, 289421952),
+(201, 14, 305625728),
+(201, 15, 322386560),
+
+-- (321, 0, 92456960),
+-- (321, 1, 110118912),
+-- (321, 2, 126208000),
+-- (321, 3, 142723072),
+-- (321, 4, 159823872),
+-- (321, 5, 176420864),
+-- (321, 6, 193034240),
+(321, 7, 210106368),
+(321, 8, 226704000),
+(321, 9, 243300992),
+(321, 10, 260389504),
+(321, 11, 276970112),
+(321, 12, 294075008),
+(321, 13, 310672000),
+
+-- (327, 0, 101104000),
+-- (327, 1, 118749568),
+-- (327, 2, 135346560),
+-- (327, 3, 151386496),
+-- (327, 4, 169048448),
+-- (327, 5, 184924160),
+-- (327, 6, 201684992),
+(327, 7, 218429440 + (7 << 14)),
+(327, 8, 235207296),
+(327, 9, 252967552),
+(327, 10, 269499008),
+(327, 11, 285555328),
+(327, 12, 303184512),
+(327, 13, 319224448),
+
+-- (404, 0, 161824832),
+-- (404, 1, 178585664),
+-- (404, 2, 195346496),
+-- (404, 3, 212090944),
+(404, 4, 228997760),
+(404, 5, 245758592),
+(404, 6, 262519424),
+(404, 7, 279263872),
+(404, 8, 296024704),
+(404, 9, 312785536),
+(404, 10, 329661056),
+
+-- (423, 0, 168919040),
+-- (423, 1, 185679872),
+-- (423, 2, 202440704),
+(423, 3, 219185152 + (7 << 14)),
+(423, 4, 236092032),
+(423, 5, 252738176),
+(423, 6, 269728384),
+(423, 7, 286374528),
+(423, 8, 303184512),
+(423, 9, 319881856),
+
+(374, 0, packDate(16, 12, 02)),
+(375, 0, packDate(16, 12, 30)),
+(376, 0, packDate(17, 02, 03)),
+(374, 1, packDate(17, 03, 03)),
+(375, 1, packDate(17, 03, 31)),
+(376, 1, packDate(17, 04, 28)),
+(374, 2, packDate(17, 06, 02)),
+(375, 2, packDate(17, 06, 30)),
+(376, 2, packDate(17, 08, 04)),
+(374, 3, packDate(17, 09, 01)),
+(375, 3, packDate(17, 09, 29)),
+(376, 3, packDate(17, 11, 03)),
+(374, 4, packDate(17, 12, 01)),
+(375, 4, packDate(17, 12, 29)),
+(376, 4, packDate(18, 02, 02)),
+(374, 5, packDate(18, 03, 02)),
+(375, 5, packDate(18, 03, 30)),
+(376, 5, packDate(18, 05, 04)),
+(374, 6, packDate(18, 06, 01)),
+(375, 6, packDate(18, 06, 29)),
+(376, 6, packDate(18, 08, 03)),
+(374, 7, packDate(18, 08, 31)),
+(375, 7, packDate(18, 09, 28)),
+(376, 7, packDate(18, 11, 02)),
+(374, 8, packDate(18, 11, 30)),
+(375, 8, packDate(19, 01, 04)),
+(376, 8, packDate(19, 02, 01)),
+(374, 9, packDate(19, 03, 01)),
+(375, 9, packDate(19, 03, 29)),
+(376, 9, packDate(19, 05, 03)),
+(374, 10, packDate(19, 05, 31)),
+(375, 10, packDate(19, 06, 28)),
+(376, 10, packDate(19, 08, 02)),
+(374, 11, packDate(19, 08, 30)),
+(375, 11, packDate(19, 10, 04)),
+(376, 11, packDate(19, 11, 01)),
+(374, 12, packDate(19, 11, 29)),
+(375, 12, packDate(20, 01, 03)),
+(376, 12, packDate(20, 01, 31)),
+(374, 13, packDate(20, 02, 28)),
+(375, 13, packDate(20, 04, 03)),
+(376, 13, packDate(20, 05, 01)),
+(374, 14, packDate(20, 05, 29)),
+(375, 14, packDate(20, 07, 03)),
+(376, 14, packDate(20, 07, 31)),
+(374, 15, packDate(20, 09, 04)),
+(375, 15, packDate(20, 10, 02)),
+(376, 15, packDate(20, 10, 30)),
+(374, 16, packDate(20, 12, 04)),
+(375, 16, packDate(21, 01, 01)),
+(376, 16, packDate(21, 01, 29)),
+(374, 17, packDate(21, 02, 26)),
+(375, 17, packDate(21, 04, 02)),
+(376, 17, packDate(21, 04, 30)),
+(374, 18, packDate(21, 06, 04)),
+(375, 18, packDate(21, 07, 02)),
+(376, 18, packDate(21, 07, 30)),
+(374, 19, packDate(21, 09, 03)),
+(375, 19, packDate(21, 10, 01)),
+(376, 19, packDate(21, 10, 29)),
+(374, 20, packDate(21, 12, 03)),
+(375, 20, packDate(21, 12, 31)),
+(376, 20, packDate(22, 02, 04)),
+(374, 21, packDate(22, 03, 04)),
+(375, 21, packDate(22, 04, 01)),
+(376, 21, packDate(22, 04, 29)),
+(374, 22, packDate(22, 06, 03)),
+(375, 22, packDate(22, 07, 01)),
+(376, 22, packDate(22, 07, 29)),
+(374, 23, packDate(22, 09, 02)),
+(375, 23, packDate(22, 09, 30)),
+(376, 23, packDate(22, 11, 04)),
+(374, 24, packDate(22, 12, 02)),
+(375, 24, packDate(22, 12, 30)),
+(376, 24, packDate(23, 02, 03)),
+(374, 25, packDate(23, 03, 03)),
+(375, 25, packDate(23, 03, 31)),
+(376, 25, packDate(23, 04, 28));
+
+UPDATE `holiday_dates` SET `date_value` = `date_value` & ~0x3FFF; -- All holidays start at 00:00 in 3.3.5 + some unneeded bits
+
+DROP FUNCTION packDate;
+
+ALTER TABLE `game_event` ADD COLUMN `holidayStage` TINYINT UNSIGNED NOT NULL DEFAULT '0' AFTER `holiday`;
+
+UPDATE `game_event` SET `holiday` = 424 WHERE `eventEntry` = 64; -- Correct Kalu'ak Fishing Derby
+UPDATE `game_event` SET `holiday` = 0 WHERE `eventEntry` = 63;
+UPDATE `game_event` SET `holiday` = 374 WHERE `eventEntry` = 23; -- Darkmoon construction
+UPDATE `game_event` SET `holiday` = 375 WHERE `eventEntry` = 110;
+UPDATE `game_event` SET `holiday` = 376 WHERE `eventEntry` = 62;
+UPDATE `game_event` SET `holidayStage` = 1 WHERE `eventEntry` IN (1, 2, 7, 8, 9, 10, 11, 12, 18, 19, 20, 21, 23, 26, 50, 51, 53, 54, 62, 110);
+UPDATE `game_event` SET `holidayStage` = 2 WHERE `eventEntry` IN (3, 4, 5, 24);
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index 307f5674b9c..db79a5a37a0 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -218,8 +218,8 @@ void GameEventMgr::LoadFromDB()
{
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5 6 7 8
- QueryResult result = WorldDatabase.Query("SELECT eventEntry, UNIX_TIMESTAMP(start_time), UNIX_TIMESTAMP(end_time), occurence, length, holiday, description, world_event, announce FROM game_event");
+ // 0 1 2 3 4 5 6 7 8 9
+ QueryResult result = WorldDatabase.Query("SELECT eventEntry, UNIX_TIMESTAMP(start_time), UNIX_TIMESTAMP(end_time), occurence, length, holiday, holidayStage, description, world_event, announce FROM game_event");
if (!result)
{
mGameEvent.clear();
@@ -247,10 +247,13 @@ void GameEventMgr::LoadFromDB()
pGameEvent.occurence = fields[3].GetUInt64();
pGameEvent.length = fields[4].GetUInt64();
pGameEvent.holiday_id = HolidayIds(fields[5].GetUInt32());
-
- pGameEvent.state = (GameEventState)(fields[7].GetUInt8());
+ pGameEvent.holidayStage = fields[6].GetUInt8();
+ pGameEvent.description = fields[7].GetString();
+ pGameEvent.state = (GameEventState)(fields[8].GetUInt8());
+ pGameEvent.announce = fields[9].GetUInt8();
pGameEvent.nextstart = 0;
- pGameEvent.announce = fields[8].GetUInt8();
+
+ ++count;
if (pGameEvent.length == 0 && pGameEvent.state == GAMEEVENT_NORMAL) // length>0 is validity check
{
@@ -264,12 +267,18 @@ void GameEventMgr::LoadFromDB()
{
TC_LOG_ERROR("sql.sql", "`game_event`: game event id (%i) contains nonexisting holiday id %u.", event_id, pGameEvent.holiday_id);
pGameEvent.holiday_id = HOLIDAY_NONE;
+ continue;
+ }
+ if (pGameEvent.holidayStage > MAX_HOLIDAY_DURATIONS)
+ {
+ TC_LOG_ERROR("sql.sql", "`game_event` game event id (%i) has out of range holidayStage %u.", event_id, pGameEvent.holidayStage);
+ pGameEvent.holidayStage = 0;
+ continue;
}
- }
- pGameEvent.description = fields[6].GetString();
+ SetHolidayEventTime(pGameEvent);
+ }
- ++count;
}
while (result->NextRow());
@@ -929,6 +938,45 @@ void GameEventMgr::LoadFromDB()
}
}
+void GameEventMgr::LoadHolidayDates()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT id, date_id, date_value FROM holiday_dates");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 holiday dates. DB table `holiday_dates` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 holidayId = fields[0].GetUInt32();
+ HolidaysEntry* entry = const_cast<HolidaysEntry*>(sHolidaysStore.LookupEntry(holidayId));
+ if (!entry)
+ {
+ TC_LOG_ERROR("sql.sql", "holiday_dates entry has invalid holiday id %u.", holidayId);
+ continue;
+ }
+ uint8 dateId = fields[1].GetUInt8();
+ if (dateId >= MAX_HOLIDAY_DATES)
+ {
+ TC_LOG_ERROR("sql.sql", "holiday_dates entry has out of range date_id %u.", dateId);
+ continue;
+ }
+ entry->Date[dateId] = fields[2].GetUInt32();
+ modifiedHolidays.insert(entry->Id);
+ ++count;
+
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u holiday dates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
uint32 GameEventMgr::GetNPCFlag(Creature* cr)
{
uint32 mask = 0;
@@ -1667,6 +1715,84 @@ void GameEventMgr::RunSmartAIScripts(uint16 event_id, bool activate)
});
}
+void GameEventMgr::SetHolidayEventTime(GameEventData& event)
+{
+ if (!event.holidayStage) // Ignore holiday
+ return;
+
+ const HolidaysEntry* holiday = sHolidaysStore.LookupEntry(event.holiday_id);
+
+ if (!holiday->Date[0] || !holiday->Duration[0]) // Invalid definitions
+ {
+ TC_LOG_ERROR("sql.sql", "Missing date or duration for holiday %u.", event.holiday_id);
+ return;
+ }
+
+ uint8 stageIndex = event.holidayStage - 1;
+ event.length = holiday->Duration[stageIndex] * HOUR / MINUTE;
+
+ time_t stageOffset = 0;
+ for (int i = 0; i < stageIndex; ++i)
+ stageOffset += holiday->Duration[i] * HOUR;
+
+ switch (holiday->CalendarFilterType)
+ {
+ case -1: // Yearly
+ event.occurence = YEAR / MINUTE; // Not all too useful
+ break;
+ case 0: // Weekly
+ event.occurence = WEEK / MINUTE;
+ break;
+ case 1: // Defined dates only (Darkmoon Faire)
+ break;
+ case 2: // Only used for looping events (Call to Arms)
+ break;
+ }
+
+ if (holiday->Looping)
+ {
+ event.occurence = 0;
+ for (int i = 0; i < MAX_HOLIDAY_DURATIONS && holiday->Duration[i]; ++i)
+ event.occurence += holiday->Duration[i] * HOUR / MINUTE;
+ }
+
+ bool singleDate = ((holiday->Date[0] >> 24) & 0x1F) == 31; // Events with fixed date within year have - 1
+
+ time_t curTime = time(NULL);
+ for (int i = 0; i < MAX_HOLIDAY_DATES && holiday->Date[i]; ++i)
+ {
+ uint32 date = holiday->Date[i];
+
+ tm timeInfo;
+ if (singleDate)
+ timeInfo.tm_year = localtime(&curTime)->tm_year - 1; // First try last year (event active through New Year)
+ else
+ timeInfo.tm_year = ((date >> 24) & 0x1F) + 100;
+
+ timeInfo.tm_mon = (date >> 20) & 0xF;
+ timeInfo.tm_mday = ((date >> 14) & 0x3F) + 1;
+ timeInfo.tm_hour = (date >> 6) & 0x1F;
+ timeInfo.tm_min = date & 0x3F;
+ timeInfo.tm_sec = 0;
+ timeInfo.tm_isdst = -1;
+ tm tmCopy = timeInfo;
+
+ time_t startTime = mktime(&timeInfo);
+ if (curTime < startTime + event.length * MINUTE)
+ {
+ event.start = startTime + stageOffset;
+ return;
+ }
+ else if (singleDate)
+ {
+ tmCopy.tm_year = localtime(&curTime)->tm_year; // This year
+ event.start = mktime(&tmCopy) + stageOffset;
+ return;
+ }
+ }
+ TC_LOG_ERROR("sql.sql", "No suitable start date found for holiday %u.", event.holiday_id);
+}
+
bool IsHolidayActive(HolidayIds id)
{
if (id == HOLIDAY_NONE)
diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h
index bee6dfc8fb3..f7f88ebfdd5 100644
--- a/src/server/game/Events/GameEventMgr.h
+++ b/src/server/game/Events/GameEventMgr.h
@@ -68,6 +68,7 @@ struct GameEventData
uint32 occurence; // time between end and start
uint32 length; // length of the event (minutes) after finishing all conditions
HolidayIds holiday_id;
+ uint8 holidayStage;
GameEventState state; // state of the game event, these are saved into the game_event table on change!
GameEventConditionMap conditions; // conditions to finish
std::set<uint16 /*gameevent id*/> prerequisite_events; // events that must be completed before starting this event
@@ -114,6 +115,7 @@ class TC_GAME_API GameEventMgr
bool CheckOneGameEvent(uint16 entry) const;
uint32 NextCheck(uint16 entry) const;
void LoadFromDB();
+ void LoadHolidayDates();
uint32 Update();
bool IsActiveEvent(uint16 event_id) { return (m_ActiveEvents.find(event_id) != m_ActiveEvents.end()); }
uint32 StartSystem();
@@ -147,6 +149,7 @@ class TC_GAME_API GameEventMgr
bool hasGameObjectQuestActiveEventExcept(uint32 quest_id, uint16 event_id);
bool hasCreatureActiveEventExcept(ObjectGuid::LowType creature_guid, uint16 event_id);
bool hasGameObjectActiveEventExcept(ObjectGuid::LowType go_guid, uint16 event_id);
+ void SetHolidayEventTime(GameEventData& event);
typedef std::list<ObjectGuid::LowType> GuidList;
typedef std::list<uint32> IdList;
@@ -181,6 +184,7 @@ class TC_GAME_API GameEventMgr
public:
GameEventGuidMap mGameEventCreatureGuids;
GameEventGuidMap mGameEventGameobjectGuids;
+ std::set<uint32> modifiedHolidays;
};
#define sGameEventMgr GameEventMgr::instance()
diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp
index 6d884ca2ee9..4384ff82474 100644
--- a/src/server/game/Handlers/CalendarHandler.cpp
+++ b/src/server/game/Handlers/CalendarHandler.cpp
@@ -41,6 +41,7 @@ Copied events should probably have a new owner
#include "CharacterCache.h"
#include "DatabaseEnv.h"
#include "DBCStores.h"
+#include "GameEventMgr.h"
#include "Guild.h"
#include "GuildMgr.h"
#include "InstanceSaveMgr.h"
@@ -151,12 +152,10 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/)
data << uint32(boundCounter);
data.append(dataBuffer);
- /// @todo Fix this, how we do know how many and what holidays to send?
- uint32 holidayCount = 0;
- data << uint32(holidayCount);
- for (uint32 i = 0; i < holidayCount; ++i)
+ data << uint32(sGameEventMgr->modifiedHolidays.size());
+ for (uint32 entry : sGameEventMgr->modifiedHolidays)
{
- HolidaysEntry const* holiday = sHolidaysStore.LookupEntry(666);
+ HolidaysEntry const* holiday = sHolidaysStore.LookupEntry(entry);
data << uint32(holiday->Id); // m_ID
data << uint32(holiday->Region); // m_region, might be looping
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index a403ec9e848..f4e1a7b2d74 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1766,7 +1766,8 @@ void World::SetInitialWorldSettings()
sPoolMgr->LoadFromDB();
TC_LOG_INFO("server.loading", "Loading Game Event Data..."); // must be after loading pools fully
- sGameEventMgr->LoadFromDB();
+ sGameEventMgr->LoadHolidayDates(); // Must be after loading DBC
+ sGameEventMgr->LoadFromDB(); // Must be after loading holiday dates
TC_LOG_INFO("server.loading", "Loading UNIT_NPC_FLAG_SPELLCLICK Data..."); // must be after LoadQuests
sObjectMgr->LoadNPCSpellClickSpells();