diff options
author | horn <pankrac.ja@seznam.cz> | 2012-09-23 18:23:15 +0200 |
---|---|---|
committer | horn <pankrac.ja@seznam.cz> | 2012-10-05 00:43:58 +0200 |
commit | c3f6c8141a083be363e828b5cbccf0ecbbe4e00c (patch) | |
tree | 3e035e2249ff810092686318e344b4d4869cbec9 | |
parent | b32878f02f801feb0db0a60d528322740d16c01c (diff) |
Core/LFG: Implemented seasonal bosses options and fixed entrance points for dungeons with multiple parts (like Dire Maul, Scarlet Monastery etc.)
TODO:
- implement spawning seasonal bosses by Dungeon Finder
- script seasonal bosses - all of them needs to call RewardDungeonDoneFor function in their JustDied to be able to complete dungeon (see boss_headless_horseman.cpp)
- replace lfg_entrances coords by sniffed values
- create missing template for item 54537 (Heart-Shaped Box)
-rw-r--r-- | sql/updates/world/2012_10_05_00_world_misc.sql | 56 | ||||
-rwxr-xr-x | src/server/game/DataStores/DBCStructure.h | 2 | ||||
-rwxr-xr-x | src/server/game/DataStores/DBCfmt.h | 2 | ||||
-rwxr-xr-x | src/server/game/DungeonFinding/LFGMgr.cpp | 89 | ||||
-rwxr-xr-x | src/server/game/DungeonFinding/LFGMgr.h | 13 | ||||
-rwxr-xr-x | src/server/game/Handlers/LFGHandler.cpp | 16 | ||||
-rwxr-xr-x | src/server/game/World/World.cpp | 3 | ||||
-rw-r--r-- | src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp | 8 |
8 files changed, 175 insertions, 14 deletions
diff --git a/sql/updates/world/2012_10_05_00_world_misc.sql b/sql/updates/world/2012_10_05_00_world_misc.sql new file mode 100644 index 00000000000..abde04f2a18 --- /dev/null +++ b/sql/updates/world/2012_10_05_00_world_misc.sql @@ -0,0 +1,56 @@ +/*!40101 SET NAMES utf8 */; + +/*!40101 SET SQL_MODE=''*/; + +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +/* Table structure for table `lfg_entrance` */ + +DROP TABLE IF EXISTS `lfg_entrances`; + +CREATE TABLE `lfg_entrances` ( + `dungeonId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Unique id from LFGDungeons.dbc', + `name` varchar(255) DEFAULT NULL, + `position_x` float NOT NULL DEFAULT '0', + `position_y` float NOT NULL DEFAULT '0', + `position_z` float NOT NULL DEFAULT '0', + `orientation` float NOT NULL DEFAULT '0', + PRIMARY KEY (`dungeonId`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + +-- only The Frost Lord Ahune and The Crown Chemical Co. were taken from sniffs, others from areatrigger_teleport or guessed +-- TODO: replace them by sniffed positions and probably use this table for all dungeons instead of areatrigger_teleport +-- note: this table should be used more in Cataclysm and Mists of Pandaria (there will be all events like Zalazane's Fall and scenarios) +DELETE FROM `lfg_entrances`; +INSERT INTO `lfg_entrances` (`dungeonId`,`name`,`position_x`,`position_y`,`position_z`,`orientation`) VALUES +(18,'Scarlet Monastery - Graveyard',1688.99,1053.48,18.6775,0.00117), +(26,'Maraudon - Orange Crystals',1019.69,-458.31,-43.43,0.31), +(34,'Dire Maul - East',44.4499,-154.822,-2.71201,0), +(36,'Dire Maul - West',-62.9658,159.867,-3.46206,3.14788), +(38,'Dire Maul - North',255.249,-16.0561,-2.58737,4.7), +(40,'Stratholme - Main Gate',3395.09,-3380.25,142.702,0.1), +(163,'Scarlet Monastery - Armory',1610.83,-323.433,18.6738,6.28022), +(164,'Scarlet Monastery - Cathedral',855.683,1321.5,18.6709,0.001747), +(165,'Scarlet Monastery - Library',255.346,-209.09,18.6773,6.26656), +(272,'Maraudon - Purple Crystals',752.91,-616.53,-33.11,1.37) +(273,'Maraudon - Pristine Waters',495.701904,17.337202,-96.31284,3.118538), -- guessed +(274,'Stratholme - Service Entrance',3593.15,-3646.56,138.5,5.33), +(285,'The Headless Horseman',1797.517212,1347.381104,18.8876,3.142), -- guessed +(286,'The Frost Lord Ahune',-100.396,-95.9996,-4.28423,4.712389), +(287,'Coren Direbrew',897.494995,-141.976349,-49.7563,2.125502), -- guessed +(288,'The Crown Chemical Co.',-238.075,2166.43,88.853,1.134464); + +DELETE FROM `lfg_dungeon_rewards` WHERE `dungeonId` BETWEEN 285 AND 288; +INSERT INTO `lfg_dungeon_rewards` (`dungeonId`,`maxLevel`,`firstQuestId`,`firstMoneyVar`,`firstXPVar`,`otherQuestId`,`otherMoneyVar`,`otherXPVar`) VALUES +(285,80,25482,0,0,0,0,0), +(286,80,25484,0,0,0,0,0), +(287,80,25483,0,0,0,0,0), +(288,80,25485,0,0,0,0,0); + +UPDATE `quest_template` SET `SpecialFlags`=`SpecialFlags`|8|1 WHERE `Id` IN (25482,25483,25484,25485); diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index ef949f43f49..e4ba3ebb12e 100755 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -1203,7 +1203,7 @@ struct LFGDungeonEntry uint32 recmaxlevel; // 22 int32 map; // 23 uint32 difficulty; // 24 - //uint32 flags; // 25 (flags & 4) = IsHoliday + uint32 flags; // 25 uint32 type; // 26 //uint32 unk; // 27 //char* iconname; // 28 diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 39d031e96f9..39f9009419e 100755 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -77,7 +77,7 @@ const char ItemLimitCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; const char ItemRandomPropertiesfmt[]="nxiiixxssssssssssssssssx"; const char ItemRandomSuffixfmt[]="nssssssssssssssssxxiiixxiiixx"; const char ItemSetEntryfmt[]="dssssssssssssssssxiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii"; -const char LFGDungeonEntryfmt[]="nxxxxxxxxxxxxxxxxxiiiiiiixixxixixxxxxxxxxxxxxxxxx"; +const char LFGDungeonEntryfmt[]="nxxxxxxxxxxxxxxxxxiiiiiiiiixxixixxxxxxxxxxxxxxxxx"; const char LiquidTypefmt[]="nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx"; const char MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxssssssssssssssssx"; diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 3a75066fa2d..2b425dffff0 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -24,6 +24,7 @@ #include "SocialMgr.h" #include "LFGMgr.h" #include "GroupMgr.h" +#include "GameEventMgr.h" #include "LFGScripts.h" #include "LFGGroupData.h" #include "LFGPlayerData.h" @@ -185,6 +186,38 @@ void LFGMgr::LoadRewards() sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u lfg dungeon rewards in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } +void LFGMgr::LoadEntrancePositions() +{ + uint32 oldMSTime = getMSTime(); + m_entrancePositions.clear(); + + QueryResult result = WorldDatabase.Query("SELECT dungeonId, position_x, position_y, position_z, orientation FROM lfg_entrances"); + + if (!result) + { + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 lfg entrance positions. DB table `lfg_entrances` is empty!"); + return; + } + + uint32 count = 0; + + do + { + Field* fields = result->Fetch(); + uint32 dungeonId = fields[0].GetUInt32(); + Position pos; + pos.m_positionX = fields[1].GetFloat(); + pos.m_positionY = fields[2].GetFloat(); + pos.m_positionZ = fields[3].GetFloat(); + pos.m_orientation = fields[4].GetFloat(); + m_entrancePositions[dungeonId] = pos; + ++count; + } + while (result->NextRow()); + + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u lfg entrance positions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); +} + void LFGMgr::Update(uint32 diff) { if (!m_update) @@ -438,6 +471,12 @@ void LFGMgr::InitializeLockedDungeons(Player* player) locktype = LFG_LOCKSTATUS_TOO_LOW_LEVEL; else if (dungeon->maxlevel < level) locktype = LFG_LOCKSTATUS_TOO_HIGH_LEVEL; + else if (dungeon->flags & LFG_FLAG_SEASONAL) + { + if (HolidayIds holiday = sLFGMgr->GetDungeonSeason(dungeon->ID)) + if (!IsHolidayActive(holiday)) + locktype = LFG_LOCKSTATUS_NOT_IN_SEASON; + } else if (locktype == LFG_LOCKSTATUS_OK && ar) { if (ar->achievement && !player->HasAchieved(ar->achievement)) @@ -460,7 +499,6 @@ void LFGMgr::InitializeLockedDungeons(Player* player) locktype = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE; locktype = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL; locktype = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL; - locktype = LFG_LOCKSTATUS_NOT_IN_SEASON; // Need list of instances and needed season to open */ if (locktype != LFG_LOCKSTATUS_OK) @@ -1808,13 +1846,16 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* if (!mapid) { - AreaTrigger const* at = sObjectMgr->GetMapEntranceTrigger(dungeon->map); - if (!at) + LfgEntrancePositionMap::const_iterator itr = m_entrancePositions.find(dungeon->ID); + if (itr != m_entrancePositions.end()) { - sLog->outError(LOG_FILTER_LFG, "LfgMgr::TeleportPlayer: Failed to teleport [" UI64FMTD "]: No areatrigger found for map: %u difficulty: %u", player->GetGUID(), dungeon->map, dungeon->difficulty); - error = LFG_TELEPORTERROR_INVALID_LOCATION; + mapid = dungeon->map; + x = itr->second.GetPositionX(); + y = itr->second.GetPositionY(); + z = itr->second.GetPositionZ(); + orientation = itr->second.GetOrientation(); } - else + else if (AreaTrigger const* at = sObjectMgr->GetMapEntranceTrigger(dungeon->map)) { mapid = at->target_mapId; x = at->target_X; @@ -1822,6 +1863,11 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* z = at->target_Z; orientation = at->target_Orientation; } + else + { + sLog->outError(LOG_FILTER_LFG, "LfgMgr::TeleportPlayer: Failed to teleport [" UI64FMTD "]: No areatrigger found for map: %u difficulty: %u", player->GetGUID(), dungeon->map, dungeon->difficulty); + error = LFG_TELEPORTERROR_INVALID_LOCATION; + } } if (error == LFG_TELEPORTERROR_OK) @@ -1889,11 +1935,11 @@ void LFGMgr::RewardDungeonDoneFor(const uint32 dungeonId, Player* player) ClearState(guid); SetState(guid, LFG_STATE_FINISHED_DUNGEON); - // Give rewards only if its a random dungeon + // Give rewards only if its a random or seasonal dungeon LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(rDungeonId); - if (!dungeon || dungeon->type != LFG_TYPE_RANDOM) + if (!dungeon || (dungeon->type != LFG_TYPE_RANDOM && !(dungeon->flags & LFG_FLAG_SEASONAL))) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RewardDungeonDoneFor: [" UI64FMTD "] dungeon %u is not random", guid, rDungeonId); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RewardDungeonDoneFor: [" UI64FMTD "] dungeon %u is not random nor seasonal", guid, rDungeonId); return; } @@ -2001,6 +2047,31 @@ std::string LFGMgr::ConcatenateGuids(LfgGuidList check) return o.str(); } +HolidayIds LFGMgr::GetDungeonSeason(uint32 dungeonId) +{ + HolidayIds holiday = HOLIDAY_NONE; + + switch (dungeonId) + { + case 285: + holiday = HOLIDAY_HALLOWS_END; + break; + case 286: + holiday = HOLIDAY_FIRE_FESTIVAL; + break; + case 287: + holiday = HOLIDAY_BREWFEST; + break; + case 288: + holiday = HOLIDAY_LOVE_IS_IN_THE_AIR; + break; + default: + break; + } + + return holiday; +} + LfgState LFGMgr::GetState(uint64 guid) { sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetState: [" UI64FMTD "]", guid); diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index e341b21706f..9937759741b 100755 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -41,6 +41,14 @@ enum LFGenum LFG_SPELL_LUCK_OF_THE_DRAW = 72221 }; +enum LfgFlags +{ + LFG_FLAG_UNK1 = 0x1, + LFG_FLAG_UNK2 = 0x2, + LFG_FLAG_SEASONAL = 0x4, + LFG_FLAG_UNK3 = 0x8 +}; + /// Determines the type of instance enum LfgType { @@ -143,6 +151,7 @@ typedef std::map<uint64, LfgProposalPlayer*> LfgProposalPlayerMap; typedef std::map<uint32, LfgPlayerBoot*> LfgPlayerBootMap; typedef std::map<uint64, LfgGroupData> LfgGroupDataMap; typedef std::map<uint64, LfgPlayerData> LfgPlayerDataMap; +typedef std::map<uint32, Position> LfgEntrancePositionMap; // Data needed by SMSG_LFG_JOIN_RESULT struct LfgJoinResultData @@ -279,6 +288,7 @@ class LFGMgr void UpdateProposal(uint32 proposalId, uint64 guid, bool accept); // Teleportation + void LoadEntrancePositions(); void TeleportPlayer(Player* player, bool out, bool fromOpcode = false); // Vote kick @@ -286,6 +296,8 @@ class LFGMgr void UpdateBoot(Player* player, bool accept); void OfferContinue(Group* grp); + HolidayIds GetDungeonSeason(uint32 dungeonId); + void InitializeLockedDungeons(Player* player); void _LoadFromDB(Field* fields, uint64 guid); @@ -349,6 +361,7 @@ class LFGMgr uint32 m_NumWaitTimeHealer; ///< Num of players used to calc healers wait time uint32 m_NumWaitTimeDps; ///< Num of players used to calc dps wait time LfgDungeonMap m_CachedDungeonMap; ///< Stores all dungeons by groupType + LfgEntrancePositionMap m_entrancePositions; ///< Stores special entrance positions // Reward System LfgRewardMap m_RewardMap; ///< Stores rewards for random dungeons // Queue diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index aa6d208ad3a..f5d5a0b67e2 100755 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -23,6 +23,7 @@ #include "LFGMgr.h" #include "ObjectMgr.h" #include "GroupMgr.h" +#include "GameEventMgr.h" #include "InstanceScript.h" void BuildPlayerLockDungeonBlock(WorldPacket& data, const LfgLockMap& lock) @@ -156,16 +157,25 @@ void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recv_data sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFD_PLAYER_LOCK_INFO_REQUEST [" UI64FMTD "]", guid); // Get Random dungeons that can be done at a certain level and expansion - // FIXME - Should return seasonals (when not disabled) LfgDungeonSet randomDungeons; uint8 level = GetPlayer()->getLevel(); uint8 expansion = GetPlayer()->GetSession()->Expansion(); for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) { LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(i); - if (dungeon && dungeon->type == LFG_TYPE_RANDOM && dungeon->expansion <= expansion && - dungeon->minlevel <= level && level <= dungeon->maxlevel) + if (dungeon && dungeon->expansion <= expansion && dungeon->minlevel <= level && level <= dungeon->maxlevel) + { + if (dungeon->flags & LFG_FLAG_SEASONAL) + { + if (HolidayIds holiday = sLFGMgr->GetDungeonSeason(dungeon->ID)) + if (!IsHolidayActive(holiday)) + continue; + } + else if (dungeon->type != LFG_TYPE_RANDOM) + continue; + randomDungeons.insert(dungeon->Entry()); + } } // Get player locked Dungeons diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 6ef3932252a..eef53e17774 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1467,6 +1467,9 @@ void World::SetInitialWorldSettings() sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading LFG rewards..."); sLFGMgr->LoadRewards(); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading LFG entrance positions..."); + sLFGMgr->LoadEntrancePositions(); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading SpellArea Data..."); // must be after quest load sSpellMgr->LoadSpellAreas(); diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp index 028cf640d21..ca91fb920b1 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp @@ -27,6 +27,7 @@ EndScriptData */ #include "ScriptedCreature.h" #include "SpellMgr.h" #include "scarlet_monastery.h" +#include "LFGMgr.h" //this texts are already used by 3975 and 3976 enum Says @@ -562,6 +563,13 @@ public: CAST_AI(mob_wisp_invis::mob_wisp_invisAI, wisp->AI())->SetType(4); if (instance) instance->SetData(DATA_HORSEMAN_EVENT, DONE); + + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (!players.isEmpty()) + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + if (Player* player = i->getSource()) + if (player->IsAtGroupRewardDistance(me)) + sLFGMgr->RewardDungeonDoneFor(285, player); } void SpellHit(Unit* caster, const SpellInfo* spell) |