mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-24 02:46:33 +01:00
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)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user