diff options
| -rw-r--r-- | sql/updates/world/3.3.5/2017_10_27_01_world.sql | 189 | ||||
| -rw-r--r-- | src/server/game/Events/GameEventMgr.cpp | 142 | ||||
| -rw-r--r-- | src/server/game/Events/GameEventMgr.h | 4 | ||||
| -rw-r--r-- | src/server/game/Handlers/CalendarHandler.cpp | 9 | ||||
| -rw-r--r-- | src/server/game/World/World.cpp | 3 | 
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(); | 
