mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-13 01:08:35 +00:00
643 lines
31 KiB
C++
643 lines
31 KiB
C++
/*
|
|
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Affero General Public License as published by the
|
|
* Free Software Foundation; either version 3 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef _LFGMGR_H
|
|
#define _LFGMGR_H
|
|
|
|
#include <utility>
|
|
|
|
#include "DBCStructure.h"
|
|
#include "Field.h"
|
|
#include "LFG.h"
|
|
#include "LFGGroupData.h"
|
|
#include "LFGPlayerData.h"
|
|
#include "LFGQueue.h"
|
|
#include "Map.h"
|
|
|
|
class Group;
|
|
class Player;
|
|
class Quest;
|
|
class WorldLocation;
|
|
|
|
namespace lfg
|
|
{
|
|
|
|
enum LfgOptions
|
|
{
|
|
LFG_OPTION_ENABLE_DUNGEON_FINDER = 0x01,
|
|
LFG_OPTION_ENABLE_RAID_BROWSER = 0x02,
|
|
LFG_OPTION_ENABLE_SEASONAL_BOSSES = 0x04
|
|
};
|
|
|
|
enum LFGMgrEnum
|
|
{
|
|
LFG_TIME_ROLECHECK = 45 * IN_MILLISECONDS,
|
|
LFG_TIME_BOOT = 120,
|
|
LFG_TIME_PROPOSAL = 40,
|
|
LFG_QUEUEUPDATE_INTERVAL = 8 * IN_MILLISECONDS,
|
|
LFG_SPELL_DUNGEON_COOLDOWN = 71328,
|
|
LFG_SPELL_DUNGEON_DESERTER = 71041,
|
|
LFG_SPELL_LUCK_OF_THE_DRAW = 72221,
|
|
LFG_GROUP_KICK_VOTES_NEEDED = 3
|
|
};
|
|
|
|
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
|
|
{
|
|
LFG_TYPE_NONE = 0,
|
|
LFG_TYPE_DUNGEON = 1,
|
|
LFG_TYPE_RAID = 2,
|
|
LFG_TYPE_ZONE = 4,
|
|
LFG_TYPE_HEROIC = 5,
|
|
LFG_TYPE_RANDOM = 6
|
|
};
|
|
|
|
/// Proposal states
|
|
enum LfgProposalState
|
|
{
|
|
LFG_PROPOSAL_INITIATING = 0,
|
|
LFG_PROPOSAL_FAILED = 1,
|
|
LFG_PROPOSAL_SUCCESS = 2
|
|
};
|
|
|
|
/// Teleport errors
|
|
enum LfgTeleportError
|
|
{
|
|
// 7 = "You can't do that right now" | 5 = No client reaction
|
|
LFG_TELEPORTERROR_OK = 0, // Internal use
|
|
LFG_TELEPORTERROR_PLAYER_DEAD = 1,
|
|
LFG_TELEPORTERROR_FALLING = 2,
|
|
LFG_TELEPORTERROR_IN_VEHICLE = 3,
|
|
LFG_TELEPORTERROR_FATIGUE = 4,
|
|
LFG_TELEPORTERROR_INVALID_LOCATION = 6,
|
|
LFG_TELEPORTERROR_COMBAT = 8 // FIXME - It can be 7 or 8 (Need proper data)
|
|
};
|
|
|
|
/// Queue join results
|
|
enum LfgJoinResult
|
|
{
|
|
// 3 = No client reaction | 18 = "Rolecheck failed"
|
|
LFG_JOIN_OK = 0, // Joined (no client msg)
|
|
LFG_JOIN_FAILED = 1, // RoleCheck Failed
|
|
LFG_JOIN_GROUPFULL = 2, // Your group is full
|
|
LFG_JOIN_INTERNAL_ERROR = 4, // Internal LFG Error
|
|
LFG_JOIN_NOT_MEET_REQS = 5, // You do not meet the requirements for the chosen dungeons
|
|
LFG_JOIN_PARTY_NOT_MEET_REQS = 6, // One or more party members do not meet the requirements for the chosen dungeons
|
|
LFG_JOIN_MIXED_RAID_DUNGEON = 7, // You cannot mix dungeons, raids, and random when picking dungeons
|
|
LFG_JOIN_MULTI_REALM = 8, // The dungeon you chose does not support players from multiple realms
|
|
LFG_JOIN_DISCONNECTED = 9, // One or more party members are pending invites or disconnected
|
|
LFG_JOIN_PARTY_INFO_FAILED = 10, // Could not retrieve information about some party members
|
|
LFG_JOIN_DUNGEON_INVALID = 11, // One or more dungeons was not valid
|
|
LFG_JOIN_DESERTER = 12, // You can not queue for dungeons until your deserter debuff wears off
|
|
LFG_JOIN_PARTY_DESERTER = 13, // One or more party members has a deserter debuff
|
|
LFG_JOIN_RANDOM_COOLDOWN = 14, // You can not queue for random dungeons while on random dungeon cooldown
|
|
LFG_JOIN_PARTY_RANDOM_COOLDOWN = 15, // One or more party members are on random dungeon cooldown
|
|
LFG_JOIN_TOO_MUCH_MEMBERS = 16, // You can not enter dungeons with more that 5 party members
|
|
LFG_JOIN_USING_BG_SYSTEM = 17 // You can not use the dungeon system while in BG or arenas
|
|
};
|
|
|
|
/// Role check states
|
|
enum LfgRoleCheckState
|
|
{
|
|
LFG_ROLECHECK_DEFAULT = 0, // Internal use = Not initialized.
|
|
LFG_ROLECHECK_FINISHED = 1, // Role check finished
|
|
LFG_ROLECHECK_INITIALITING = 2, // Role check begins
|
|
LFG_ROLECHECK_MISSING_ROLE = 3, // Someone didn't selected a role after 2 mins
|
|
LFG_ROLECHECK_WRONG_ROLES = 4, // Can't form a group with that role selection
|
|
LFG_ROLECHECK_ABORTED = 5, // Someone leave the group
|
|
LFG_ROLECHECK_NO_ROLE = 6 // Someone selected no role
|
|
};
|
|
|
|
enum LfgUpdateFlag // pussywizard: for raid browser
|
|
{
|
|
LFG_UPDATE_FLAG_NONE = 0x00,
|
|
LFG_UPDATE_FLAG_CHARACTERINFO = 0x01,
|
|
LFG_UPDATE_FLAG_COMMENT = 0x02,
|
|
LFG_UPDATE_FLAG_GROUPLEADER = 0x04,
|
|
LFG_UPDATE_FLAG_GROUPGUID = 0x08,
|
|
LFG_UPDATE_FLAG_ROLES = 0x10,
|
|
LFG_UPDATE_FLAG_AREA = 0x20,
|
|
LFG_UPDATE_FLAG_STATUS = 0x40,
|
|
LFG_UPDATE_FLAG_BINDED = 0x80
|
|
};
|
|
|
|
enum LfgSeasonalDungeons
|
|
{
|
|
LFG_DUNGEON_HEADLESS_HORSEMAN = 285,
|
|
LFG_DUNGEON_FROST_LORD_AHUNE = 286,
|
|
LFG_DUNGEON_COREN_DIREBREW = 287,
|
|
LFG_DUNGEON_CROWN_CHEMICAL_CO = 288
|
|
};
|
|
|
|
struct RBEntryInfo
|
|
{
|
|
RBEntryInfo() = default;
|
|
RBEntryInfo(uint8 _roles, std::string _comment) : roles(_roles), comment(std::move(_comment)) {}
|
|
uint8 roles;
|
|
std::string comment;
|
|
};
|
|
|
|
struct RBInternalInfo
|
|
{
|
|
ObjectGuid guid;
|
|
std::string comment;
|
|
bool isGroupLeader;
|
|
ObjectGuid groupGuid;
|
|
uint8 roles;
|
|
uint32 encounterMask;
|
|
ObjectGuid instanceGuid;
|
|
|
|
// additional character info parameters:
|
|
uint8 _online;
|
|
uint8 _level;
|
|
uint8 _class;
|
|
uint8 _race;
|
|
float _avgItemLevel;
|
|
// --
|
|
uint8 _talents0;
|
|
uint8 _talents1;
|
|
uint8 _talents2;
|
|
uint32 _area;
|
|
uint32 _armor;
|
|
uint32 _spellDamage;
|
|
uint32 _spellHeal;
|
|
// --
|
|
uint32 _critRatingMelee;
|
|
uint32 _critRatingRanged;
|
|
uint32 _critRatingSpell;
|
|
float _mp5;
|
|
float _mp5combat;
|
|
// --
|
|
uint32 _attackPower;
|
|
uint32 _agility;
|
|
uint32 _health;
|
|
uint32 _mana;
|
|
uint32 _defenseSkill;
|
|
// --
|
|
uint32 _dodgeRating;
|
|
uint32 _blockRating;
|
|
uint32 _parryRating;
|
|
uint32 _hasteRating;
|
|
uint32 _expertiseRating;
|
|
|
|
RBInternalInfo() = default;
|
|
RBInternalInfo(ObjectGuid guid, std::string comment, bool isGroupLeader, ObjectGuid groupGuid, uint8 roles, uint32 encounterMask, ObjectGuid instanceGuid,
|
|
uint8 _online, uint8 _level, uint8 _class, uint8 _race, float _avgItemLevel,
|
|
uint8 (&_talents)[3], uint32 _area, uint32 _armor, uint32 _spellDamage, uint32 _spellHeal,
|
|
uint32 _critRatingMelee, uint32 _critRatingRanged, uint32 _critRatingSpell, float _mp5, float _mp5combat,
|
|
uint32 _attackPower, uint32 _agility, uint32 _health, uint32 _mana, uint32 _defenseSkill,
|
|
uint32 _dodgeRating, uint32 _blockRating, uint32 _parryRating, uint32 _hasteRating, uint32 _expertiseRating)
|
|
: guid(guid), comment(std::move(comment)), isGroupLeader(isGroupLeader), groupGuid(groupGuid), roles(roles), encounterMask(encounterMask), instanceGuid(instanceGuid),
|
|
_online(_online), _level(_level), _class(_class), _race(_race), _avgItemLevel(_avgItemLevel),
|
|
_talents0(_talents[0]), _talents1(_talents[1]), _talents2(_talents[2]), _area(_area), _armor(_armor), _spellDamage(_spellDamage), _spellHeal(_spellHeal),
|
|
_critRatingMelee(_critRatingMelee), _critRatingRanged(_critRatingRanged), _critRatingSpell(_critRatingSpell), _mp5(_mp5), _mp5combat(_mp5combat),
|
|
_attackPower(_attackPower), _agility(_agility), _health(_health), _mana(_mana), _defenseSkill(_defenseSkill),
|
|
_dodgeRating(_dodgeRating), _blockRating(_blockRating), _parryRating(_parryRating), _hasteRating(_hasteRating), _expertiseRating(_expertiseRating)
|
|
{}
|
|
[[nodiscard]] bool PlayerSameAs(RBInternalInfo const& i) const
|
|
{
|
|
return isGroupLeader == i.isGroupLeader && groupGuid == i.groupGuid && roles == i.roles && (isGroupLeader || (comment == i.comment && encounterMask == i.encounterMask && instanceGuid == i.instanceGuid))
|
|
&& _online == i._online && _level == i._level && _class == i._class && _race == i._race && std::fabs(_avgItemLevel - i._avgItemLevel) < 0.01f
|
|
&& _talents0 == i._talents0 && _talents1 == i._talents1 && _talents2 == i._talents2 && _area == i._area && _armor == i._armor && _spellDamage == i._spellDamage && _spellHeal == i._spellHeal
|
|
&& _critRatingMelee == i._critRatingMelee && _critRatingRanged == i._critRatingRanged && _critRatingSpell == i._critRatingSpell && std::fabs(_mp5 - i._mp5) < 0.01f && std::fabs(_mp5combat - i._mp5combat) < 0.01f
|
|
&& _attackPower == i._attackPower && _agility == i._agility && _health == i._health && _mana == i._mana && _defenseSkill == i._defenseSkill
|
|
&& _dodgeRating == i._dodgeRating && _blockRating == i._blockRating && _parryRating == i._parryRating && _hasteRating == i._hasteRating && _expertiseRating == i._expertiseRating;
|
|
}
|
|
void CopyStats(RBInternalInfo const& i)
|
|
{
|
|
_avgItemLevel = i._avgItemLevel;
|
|
_talents0 = i._talents0;
|
|
_talents1 = i._talents1;
|
|
_talents2 = i._talents2;
|
|
_area = i._area;
|
|
_armor = i._armor;
|
|
_spellDamage = i._spellDamage;
|
|
_spellHeal = i._spellHeal;
|
|
_critRatingMelee = i._critRatingMelee;
|
|
_critRatingRanged = i._critRatingRanged;
|
|
_critRatingSpell = i._critRatingSpell;
|
|
_mp5 = i._mp5;
|
|
_mp5combat = i._mp5combat;
|
|
_attackPower = i._attackPower;
|
|
_agility = i._agility;
|
|
_health = i._health;
|
|
_mana = i._mana;
|
|
_defenseSkill = i._defenseSkill;
|
|
_dodgeRating = i._dodgeRating;
|
|
_blockRating = i._blockRating;
|
|
_parryRating = i._parryRating;
|
|
_hasteRating = i._hasteRating;
|
|
_expertiseRating = i._expertiseRating;
|
|
}
|
|
};
|
|
|
|
// Forward declaration (just to have all typedef together)
|
|
struct LFGDungeonData;
|
|
struct LfgReward;
|
|
struct LfgQueueInfo;
|
|
struct LfgRoleCheck;
|
|
struct LfgProposal;
|
|
struct LfgProposalPlayer;
|
|
struct LfgPlayerBoot;
|
|
|
|
typedef std::map<uint8, LFGQueue> LfgQueueContainer;
|
|
typedef std::multimap<uint32, LfgReward const*> LfgRewardContainer;
|
|
typedef std::pair<LfgRewardContainer::const_iterator, LfgRewardContainer::const_iterator> LfgRewardContainerBounds;
|
|
typedef std::map<uint8, LfgDungeonSet> LfgCachedDungeonContainer;
|
|
typedef std::map<ObjectGuid, LfgAnswer> LfgAnswerContainer;
|
|
typedef std::map<ObjectGuid, LfgRoleCheck> LfgRoleCheckContainer;
|
|
typedef std::map<uint32, LfgProposal> LfgProposalContainer;
|
|
typedef std::map<ObjectGuid, LfgProposalPlayer> LfgProposalPlayerContainer;
|
|
typedef std::map<ObjectGuid, LfgPlayerBoot> LfgPlayerBootContainer;
|
|
typedef std::map<ObjectGuid, LfgGroupData> LfgGroupDataContainer;
|
|
typedef std::map<ObjectGuid, LfgPlayerData> LfgPlayerDataContainer;
|
|
typedef std::unordered_map<uint32, LFGDungeonData> LFGDungeonContainer;
|
|
|
|
// Data needed by SMSG_LFG_JOIN_RESULT
|
|
struct LfgJoinResultData
|
|
{
|
|
LfgJoinResultData(LfgJoinResult _result = LFG_JOIN_OK, LfgRoleCheckState _state = LFG_ROLECHECK_DEFAULT):
|
|
result(_result), state(_state) {}
|
|
LfgJoinResult result;
|
|
LfgRoleCheckState state;
|
|
LfgLockPartyMap lockmap;
|
|
};
|
|
|
|
// Data needed by SMSG_LFG_UPDATE_PARTY and SMSG_LFG_UPDATE_PLAYER
|
|
struct LfgUpdateData
|
|
{
|
|
LfgUpdateData(LfgUpdateType _type = LFG_UPDATETYPE_DEFAULT): updateType(_type), comment("") { }
|
|
LfgUpdateData(LfgUpdateType _type, LfgDungeonSet _dungeons, std::string _comment):
|
|
updateType(_type), state(LFG_STATE_NONE), dungeons(std::move(_dungeons)), comment(std::move(_comment)) { }
|
|
LfgUpdateData(LfgUpdateType _type, LfgState _state, LfgDungeonSet _dungeons, std::string _comment = ""):
|
|
updateType(_type), state(_state), dungeons(std::move(_dungeons)), comment(std::move(_comment)) { }
|
|
|
|
LfgUpdateType updateType;
|
|
LfgState state{LFG_STATE_NONE};
|
|
LfgDungeonSet dungeons;
|
|
std::string comment;
|
|
};
|
|
|
|
// Data needed by SMSG_LFG_QUEUE_STATUS
|
|
struct LfgQueueStatusData
|
|
{
|
|
LfgQueueStatusData(uint32 _dungeonId = 0, int32 _waitTime = -1, int32 _waitTimeAvg = -1, int32 _waitTimeTank = -1, int32 _waitTimeHealer = -1,
|
|
int32 _waitTimeDps = -1, uint32 _queuedTime = 0, uint8 _tanks = 0, uint8 _healers = 0, uint8 _dps = 0) :
|
|
dungeonId(_dungeonId), waitTime(_waitTime), waitTimeAvg(_waitTimeAvg), waitTimeTank(_waitTimeTank), waitTimeHealer(_waitTimeHealer),
|
|
waitTimeDps(_waitTimeDps), queuedTime(_queuedTime), tanks(_tanks), healers(_healers), dps(_dps) {}
|
|
|
|
uint32 dungeonId;
|
|
int32 waitTime;
|
|
int32 waitTimeAvg;
|
|
int32 waitTimeTank;
|
|
int32 waitTimeHealer;
|
|
int32 waitTimeDps;
|
|
uint32 queuedTime;
|
|
uint8 tanks;
|
|
uint8 healers;
|
|
uint8 dps;
|
|
};
|
|
|
|
struct LfgPlayerRewardData
|
|
{
|
|
LfgPlayerRewardData(uint32 random, uint32 current, bool _done, Quest const* _quest):
|
|
rdungeonEntry(random), sdungeonEntry(current), done(_done), quest(_quest) { }
|
|
uint32 rdungeonEntry;
|
|
uint32 sdungeonEntry;
|
|
bool done;
|
|
Quest const* quest;
|
|
};
|
|
|
|
// Reward info
|
|
struct LfgReward
|
|
{
|
|
LfgReward(uint32 _maxLevel = 0, uint32 _firstQuest = 0, uint32 _otherQuest = 0):
|
|
maxLevel(_maxLevel), firstQuest(_firstQuest), otherQuest(_otherQuest) { }
|
|
|
|
uint32 maxLevel;
|
|
uint32 firstQuest;
|
|
uint32 otherQuest;
|
|
};
|
|
|
|
// Stores player data related to proposal to join
|
|
struct LfgProposalPlayer
|
|
{
|
|
LfgProposalPlayer() = default;
|
|
uint8 role{0}; ///< Proposed role
|
|
LfgAnswer accept{LFG_ANSWER_PENDING}; ///< Accept status (-1 not answer | 0 Not agree | 1 agree)
|
|
ObjectGuid group; ///< Original group guid. 0 if no original group
|
|
};
|
|
|
|
// Stores group data related to proposal to join
|
|
struct LfgProposal
|
|
{
|
|
LfgProposal(uint32 dungeon = 0): dungeonId(dungeon)
|
|
{ }
|
|
|
|
uint32 id{0}; ///< Proposal Id
|
|
uint32 dungeonId; ///< Dungeon to join
|
|
LfgProposalState state{LFG_PROPOSAL_INITIATING}; ///< State of the proposal
|
|
ObjectGuid group; ///< Proposal group (0 if new)
|
|
ObjectGuid leader; ///< Leader guid.
|
|
time_t cancelTime{0}; ///< Time when we will cancel this proposal
|
|
uint32 encounters{0}; ///< Dungeon Encounters
|
|
bool isNew{true}; ///< Determines if it's new group or not
|
|
Lfg5Guids queues; ///< Queue Ids to remove/readd
|
|
LfgGuidList showorder; ///< Show order in update window
|
|
LfgProposalPlayerContainer players; ///< Players data
|
|
};
|
|
|
|
// Stores all rolecheck info of a group that wants to join
|
|
struct LfgRoleCheck
|
|
{
|
|
time_t cancelTime; ///< Time when the rolecheck will fail
|
|
LfgRolesMap roles; ///< Player selected roles
|
|
LfgRoleCheckState state; ///< State of the rolecheck
|
|
LfgDungeonSet dungeons; ///< Dungeons group is applying for (expanded random dungeons)
|
|
uint32 rDungeonId; ///< Random Dungeon Id.
|
|
ObjectGuid leader; ///< Leader of the group
|
|
};
|
|
|
|
// Stores information of a current vote to kick someone from a group
|
|
struct LfgPlayerBoot
|
|
{
|
|
time_t cancelTime; ///< Time left to vote
|
|
bool inProgress; ///< Vote in progress
|
|
LfgAnswerContainer votes; ///< Player votes (-1 not answer | 0 Not agree | 1 agree)
|
|
ObjectGuid victim; ///< Player guid to be kicked (can't vote)
|
|
std::string reason; ///< kick reason
|
|
};
|
|
|
|
struct LFGDungeonData
|
|
{
|
|
LFGDungeonData(): name("")
|
|
{ }
|
|
LFGDungeonData(LFGDungeonEntry const* dbc) : id(dbc->ID), name(dbc->Name[0]), map(dbc->MapID),
|
|
type(dbc->TypeID), expansion(uint8(dbc->ExpansionLevel)), group(uint8(dbc->GroupID)),
|
|
minlevel(uint8(dbc->MinLevel)), maxlevel(uint8(dbc->MaxLevel)), difficulty(Difficulty(dbc->Difficulty)),
|
|
seasonal((dbc->Flags & LFG_FLAG_SEASONAL) != 0), x(0.0f), y(0.0f), z(0.0f), o(0.0f)
|
|
{ }
|
|
|
|
uint32 id{0};
|
|
std::string name;
|
|
uint16 map{0};
|
|
uint8 type{0};
|
|
uint8 expansion{0};
|
|
uint8 group{0};
|
|
uint8 minlevel{0};
|
|
uint8 maxlevel{0};
|
|
Difficulty difficulty{REGULAR_DIFFICULTY};
|
|
bool seasonal{false};
|
|
float x{0.0f}, y{0.0f}, z{0.0f}, o{0.0f};
|
|
|
|
// Helpers
|
|
[[nodiscard]] uint32 Entry() const { return id + (type << 24); }
|
|
};
|
|
|
|
class LFGMgr
|
|
{
|
|
private:
|
|
LFGMgr();
|
|
~LFGMgr();
|
|
|
|
// pussywizard: RAIDBROWSER
|
|
typedef std::unordered_map<ObjectGuid /*playerGuid*/, RBEntryInfo> RBEntryInfoMap;
|
|
typedef std::unordered_map<uint32 /*dungeonId*/, RBEntryInfoMap> RBStoreMap;
|
|
RBStoreMap RaidBrowserStore[2]; // for 2 factions
|
|
typedef std::unordered_map<ObjectGuid /*playerGuid*/, uint32 /*dungeonId*/> RBSearchersMap;
|
|
RBSearchersMap RBSearchersStore[2]; // for 2 factions
|
|
typedef std::unordered_map<uint32 /*dungeonId*/, WorldPacket> RBCacheMap;
|
|
RBCacheMap RBCacheStore[2]; // for 2 factions
|
|
typedef std::unordered_map<ObjectGuid /*guid*/, RBInternalInfo> RBInternalInfoMap;
|
|
typedef std::unordered_map<uint32 /*dungeonId*/, RBInternalInfoMap> RBInternalInfoMapMap;
|
|
RBInternalInfoMapMap RBInternalInfoStorePrev[2]; // for 2 factions
|
|
RBInternalInfoMapMap RBInternalInfoStoreCurr[2]; // for 2 factions
|
|
typedef std::set<uint32 /*dungeonId*/> RBUsedDungeonsSet; // needs to be ordered
|
|
RBUsedDungeonsSet RBUsedDungeonsStore[2]; // for 2 factions
|
|
|
|
public:
|
|
static LFGMgr* instance();
|
|
|
|
// Functions used outside lfg namespace
|
|
void Update(uint32 diff, uint8 task);
|
|
|
|
// World.cpp
|
|
/// Finish the dungeon for the given group. All check are performed using internal lfg data
|
|
void FinishDungeon(ObjectGuid gguid, uint32 dungeonId, const Map* currMap);
|
|
/// Loads rewards for random dungeons
|
|
void LoadRewards();
|
|
/// Loads dungeons from dbc and adds teleport coords
|
|
void LoadLFGDungeons(bool reload = false);
|
|
|
|
// Multiple files
|
|
/// Check if given guid applied for random dungeon
|
|
bool selectedRandomLfgDungeon(ObjectGuid guid);
|
|
/// Check if given guid applied for given map and difficulty. Used to know
|
|
bool inLfgDungeonMap(ObjectGuid guid, uint32 map, Difficulty difficulty);
|
|
/// Get selected dungeons
|
|
LfgDungeonSet const& GetSelectedDungeons(ObjectGuid guid);
|
|
/// Get current lfg state
|
|
LfgState GetState(ObjectGuid guid);
|
|
/// Get current dungeon
|
|
uint32 GetDungeon(ObjectGuid guid, bool asId = true);
|
|
/// Get the map id of the current dungeon
|
|
uint32 GetDungeonMapId(ObjectGuid guid);
|
|
/// Get kicks left in current group
|
|
uint8 GetKicksLeft(ObjectGuid gguid);
|
|
/// Load Lfg group info from DB
|
|
void _LoadFromDB(Field* fields, ObjectGuid guid);
|
|
/// Initializes player data after loading group data from DB
|
|
void SetupGroupMember(ObjectGuid guid, ObjectGuid gguid);
|
|
/// Return Lfg dungeon entry for given dungeon id
|
|
uint32 GetLFGDungeonEntry(uint32 id);
|
|
|
|
// cs_lfg
|
|
/// Get current player roles
|
|
uint8 GetRoles(ObjectGuid guid);
|
|
/// Get current player comment (used for LFR)
|
|
std::string const& GetComment(ObjectGuid gguid);
|
|
/// Gets current lfg options
|
|
uint32 GetOptions();
|
|
/// Sets new lfg options
|
|
void SetOptions(uint32 options);
|
|
/// Checks if given lfg option is enabled
|
|
bool isOptionEnabled(uint32 option);
|
|
/// Clears queue - Only for internal testing
|
|
void Clean();
|
|
|
|
// LFGScripts
|
|
/// Get leader of the group (using internal data)
|
|
ObjectGuid GetLeader(ObjectGuid guid);
|
|
/// Initializes locked dungeons for given player (called at login or level change)
|
|
void InitializeLockedDungeons(Player* player, Group const* group = nullptr);
|
|
/// Sets player team
|
|
void SetTeam(ObjectGuid guid, TeamId teamId);
|
|
/// Sets player group
|
|
void SetGroup(ObjectGuid guid, ObjectGuid group);
|
|
/// Gets player group
|
|
ObjectGuid GetGroup(ObjectGuid guid);
|
|
/// Sets the leader of the group
|
|
void SetLeader(ObjectGuid gguid, ObjectGuid leader);
|
|
/// Removes saved group data
|
|
void RemoveGroupData(ObjectGuid guid);
|
|
/// Removes a player from a group
|
|
uint8 RemovePlayerFromGroup(ObjectGuid gguid, ObjectGuid guid);
|
|
/// Adds player to group
|
|
void AddPlayerToGroup(ObjectGuid gguid, ObjectGuid guid);
|
|
/// Xinef: Set Random Players Count
|
|
void SetRandomPlayersCount(ObjectGuid guid, uint8 count);
|
|
/// Xinef: Get Random Players Count
|
|
uint8 GetRandomPlayersCount(ObjectGuid guid);
|
|
|
|
// LFGHandler
|
|
/// Get locked dungeons
|
|
LfgLockMap const& GetLockedDungeons(ObjectGuid guid);
|
|
/// Returns current lfg status
|
|
LfgUpdateData GetLfgStatus(ObjectGuid guid);
|
|
/// Checks if Seasonal dungeon is active
|
|
bool IsSeasonActive(uint32 dungeonId);
|
|
/// Gets the random dungeon reward corresponding to given dungeon and player level
|
|
LfgReward const* GetRandomDungeonReward(uint32 dungeon, uint8 level);
|
|
/// Returns all random and seasonal dungeons for given level and expansion
|
|
LfgDungeonSet GetRandomAndSeasonalDungeons(uint8 level, uint8 expansion);
|
|
/// Teleport a player to/from selected dungeon
|
|
void TeleportPlayer(Player* player, bool out, WorldLocation const* teleportLocation = nullptr);
|
|
/// Inits new proposal to boot a player
|
|
void InitBoot(ObjectGuid gguid, ObjectGuid kicker, ObjectGuid victim, std::string const& reason);
|
|
/// Updates player boot proposal with new player answer
|
|
void UpdateBoot(ObjectGuid guid, bool accept);
|
|
/// Updates proposal to join dungeon with player answer
|
|
void UpdateProposal(uint32 proposalId, ObjectGuid guid, bool accept);
|
|
/// Updates the role check with player answer
|
|
void UpdateRoleCheck(ObjectGuid gguid, ObjectGuid guid = ObjectGuid::Empty, uint8 roles = PLAYER_ROLE_NONE);
|
|
/// Sets player lfg roles
|
|
void SetRoles(ObjectGuid guid, uint8 roles);
|
|
/// Sets player lfr comment
|
|
void SetComment(ObjectGuid guid, std::string const& comment);
|
|
/// Join Lfg with selected roles, dungeons and comment
|
|
void JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, std::string const& comment);
|
|
/// Leaves lfg
|
|
void LeaveLfg(ObjectGuid guid);
|
|
/// pussywizard: cleans all queues' data
|
|
void LeaveAllLfgQueues(ObjectGuid guid, bool allowgroup, ObjectGuid groupguid = ObjectGuid::Empty);
|
|
/// pussywizard: Raid Browser
|
|
void JoinRaidBrowser(Player* player, uint8 roles, LfgDungeonSet& dungeons, std::string comment);
|
|
void LeaveRaidBrowser(ObjectGuid guid);
|
|
void LfrSearchAdd(Player* p, uint32 dungeonId);
|
|
void LfrSearchRemove(Player* p);
|
|
void SendRaidBrowserCachedList(Player* player, uint32 dungeonId);
|
|
void UpdateRaidBrowser(uint32 diff);
|
|
void LfrSetComment(Player* p, std::string comment);
|
|
void SendRaidBrowserJoinedPacket(Player* p, LfgDungeonSet& dungeons, std::string comment);
|
|
void RBPacketAppendGroup(const RBInternalInfo& info, ByteBuffer& buffer);
|
|
void RBPacketAppendPlayer(const RBInternalInfo& info, ByteBuffer& buffer);
|
|
void RBPacketBuildDifference(WorldPacket& differencePacket, uint32 dungeonId, uint32 deletedCounter, ByteBuffer& buffer_deleted, uint32 groupCounter, ByteBuffer& buffer_groups, uint32 playerCounter, ByteBuffer& buffer_players);
|
|
void RBPacketBuildFull(WorldPacket& fullPacket, uint32 dungeonId, RBInternalInfoMap& infoMap);
|
|
|
|
// LfgQueue
|
|
/// Get last lfg state (NONE, DUNGEON or FINISHED_DUNGEON)
|
|
LfgState GetOldState(ObjectGuid guid);
|
|
/// Check if given group guid is lfg
|
|
bool IsLfgGroup(ObjectGuid guid);
|
|
/// Gets the player count of given group
|
|
uint8 GetPlayerCount(ObjectGuid guid);
|
|
/// Add a new Proposal
|
|
uint32 AddProposal(LfgProposal& proposal);
|
|
/// Checks if all players are queued
|
|
bool AllQueued(Lfg5Guids const& check);
|
|
/// Checks if given roles match, modifies given roles map with new roles
|
|
static uint8 CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag = true);
|
|
/// Checks if given players are ignoring each other
|
|
static bool HasIgnore(ObjectGuid guid1, ObjectGuid guid2);
|
|
/// Sends queue status to player
|
|
static void SendLfgQueueStatus(ObjectGuid guid, LfgQueueStatusData const& data);
|
|
// debug lfg command
|
|
void ToggleTesting();
|
|
/// For 1 player queue testing
|
|
[[nodiscard]] bool IsTesting() const { return m_Testing; }
|
|
|
|
void SetDungeon(ObjectGuid guid, uint32 dungeon);
|
|
|
|
private:
|
|
TeamId GetTeam(ObjectGuid guid);
|
|
void RestoreState(ObjectGuid guid, char const* debugMsg);
|
|
void ClearState(ObjectGuid guid, char const* debugMsg);
|
|
void SetSelectedDungeons(ObjectGuid guid, LfgDungeonSet const& dungeons);
|
|
void SetLockedDungeons(ObjectGuid guid, LfgLockMap const& lock);
|
|
void DecreaseKicksLeft(ObjectGuid guid);
|
|
void SetState(ObjectGuid guid, LfgState state);
|
|
void SetCanOverrideRBState(ObjectGuid guid, bool val);
|
|
void GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap);
|
|
void _SaveToDB(ObjectGuid guid);
|
|
LFGDungeonData const* GetLFGDungeon(uint32 id);
|
|
|
|
// Proposals
|
|
void RemoveProposal(LfgProposalContainer::iterator itProposal, LfgUpdateType type);
|
|
void MakeNewGroup(LfgProposal const& proposal);
|
|
|
|
// Generic
|
|
LFGQueue& GetQueue(ObjectGuid guid);
|
|
LfgDungeonSet const& GetDungeonsByRandom(uint32 randomdungeon);
|
|
LfgType GetDungeonType(uint32 dungeon);
|
|
|
|
void SendLfgBootProposalUpdate(ObjectGuid guid, LfgPlayerBoot const& boot);
|
|
void SendLfgJoinResult(ObjectGuid guid, LfgJoinResultData const& data);
|
|
void SendLfgRoleChosen(ObjectGuid guid, ObjectGuid pguid, uint8 roles);
|
|
void SendLfgRoleCheckUpdate(ObjectGuid guid, LfgRoleCheck const& roleCheck);
|
|
void SendLfgUpdateParty(ObjectGuid guid, LfgUpdateData const& data);
|
|
void SendLfgUpdatePlayer(ObjectGuid guid, LfgUpdateData const& data);
|
|
void SendLfgUpdateProposal(ObjectGuid guid, LfgProposal const& proposal);
|
|
|
|
LfgGuidSet const& GetPlayers(ObjectGuid guid);
|
|
|
|
// General variables
|
|
uint32 m_lfgProposalId; ///< used as internal counter for proposals
|
|
uint32 m_options; ///< Stores config options
|
|
uint32 lastProposalId; ///< pussywizard, store it here because of splitting LFGMgr update into tasks
|
|
uint32 m_raidBrowserUpdateTimer[2]; ///< pussywizard
|
|
uint32 m_raidBrowserLastUpdatedDungeonId[2]; ///< pussywizard: for 2 factions
|
|
|
|
LfgQueueContainer QueuesStore; ///< Queues
|
|
LfgCachedDungeonContainer CachedDungeonMapStore; ///< Stores all dungeons by groupType
|
|
// Reward System
|
|
LfgRewardContainer RewardMapStore; ///< Stores rewards for random dungeons
|
|
LFGDungeonContainer LfgDungeonStore;
|
|
// Rolecheck - Proposal - Vote Kicks
|
|
LfgRoleCheckContainer RoleChecksStore; ///< Current Role checks
|
|
LfgProposalContainer ProposalsStore; ///< Current Proposals
|
|
LfgPlayerBootContainer BootsStore; ///< Current player kicks
|
|
LfgPlayerDataContainer PlayersStore; ///< Player data
|
|
LfgGroupDataContainer GroupsStore; ///< Group data
|
|
bool m_Testing;
|
|
};
|
|
|
|
template <typename T, FMT_ENABLE_IF(std::is_enum_v<T>)>
|
|
auto format_as(T f) { return fmt::underlying(f); }
|
|
|
|
} // namespace lfg
|
|
|
|
#define sLFGMgr lfg::LFGMgr::instance()
|
|
|
|
#endif |