Advertisement
Guest User

Credits: Vitor

a guest
Jul 15th, 2010
2,628
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 111.55 KB | None | 0 0
  1. src/game/Channel.cpp | 3 +-
  2. src/game/CharacterHandler.cpp | 2 +-
  3. src/game/DBCStores.cpp | 4 +-
  4. src/game/DBCStores.h | 1 +
  5. src/game/DBCStructure.h | 23 +
  6. src/game/DBCfmt.h | 1 +
  7. src/game/Group.cpp | 29 +-
  8. src/game/Group.h | 3 +
  9. src/game/GroupHandler.cpp | 13 +
  10. src/game/LFG.h | 54 ++
  11. src/game/LFGHandler.cpp | 539 +++++++--------------
  12. src/game/LFGMgr.cpp | 1069 ++++++++++++++++++++++++++++++++++++++++
  13. src/game/LFGMgr.h | 261 ++++++++++
  14. src/game/Makefile.am | 3 +
  15. src/game/ObjectGuid.cpp | 2 +
  16. src/game/ObjectGuid.h | 4 +
  17. src/game/ObjectMgr.cpp | 2 +
  18. src/game/Opcodes.cpp | 22 +-
  19. src/game/Player.h | 69 +---
  20. src/game/World.cpp | 7 +
  21. src/game/WorldSession.cpp | 6 +
  22. src/game/WorldSession.h | 26 +-
  23. win/VC100/game.vcxproj | 3 +
  24. win/VC100/game.vcxproj.filters | 9 +
  25. win/VC80/game.vcproj | 12 +
  26. win/VC90/game.vcproj | 12 +
  27. 26 files changed, 1703 insertions(+), 476 deletions(-)
  28. create mode 100644 src/game/LFG.h
  29. create mode 100644 src/game/LFGMgr.cpp
  30. create mode 100644 src/game/LFGMgr.h
  31.  
  32. diff --git a/src/game/Channel.cpp b/src/game/Channel.cpp
  33. index a749e1a..91c4c4b 100644
  34. --- a/src/game/Channel.cpp
  35. +++ b/src/game/Channel.cpp
  36. @@ -82,8 +82,7 @@ void Channel::Join(uint64 p, const char *pass)
  37. if(plr)
  38. {
  39. if(HasFlag(CHANNEL_FLAG_LFG) &&
  40. - sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && plr->GetSession()->GetSecurity() == SEC_PLAYER &&
  41. - (plr->GetGroup() || plr->m_lookingForGroup.Empty()) )
  42. + sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && plr->GetSession()->GetSecurity() == SEC_PLAYER && plr->GetGroup())
  43. {
  44. MakeNotInLfg(&data);
  45. SendToOne(&data, p);
  46. diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp
  47. index a6860f8..0fc5f3e 100644
  48. --- a/src/game/CharacterHandler.cpp
  49. +++ b/src/game/CharacterHandler.cpp
  50. @@ -839,7 +839,7 @@ void WorldSession::HandleMeetingStoneInfo( WorldPacket & /*recv_data*/ )
  51. {
  52. DEBUG_LOG( "WORLD: Received CMSG_MEETING_STONE_INFO" );
  53.  
  54. - SendLfgUpdate(0, 0, 0);
  55. + //SendLfgUpdate(0, 0, 0);
  56. }
  57.  
  58. void WorldSession::HandleTutorialFlag( WorldPacket & recv_data )
  59. diff --git a/src/game/DBCStores.cpp b/src/game/DBCStores.cpp
  60. index 8f0fd71..04999f0 100644
  61. --- a/src/game/DBCStores.cpp
  62. +++ b/src/game/DBCStores.cpp
  63. @@ -93,6 +93,7 @@ DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore(ItemRandomProp
  64. DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffixfmt);
  65. DBCStorage <ItemSetEntry> sItemSetStore(ItemSetEntryfmt);
  66.  
  67. +DBCStorage <LFGDungeonEntry> sLFGDungeonStore(LFGDungeonEntryfmt);
  68. DBCStorage <LockEntry> sLockStore(LockEntryfmt);
  69.  
  70. DBCStorage <MailTemplateEntry> sMailTemplateStore(MailTemplateEntryfmt);
  71. @@ -334,7 +335,7 @@ void LoadDBCStores(const std::string& dataPath)
  72. exit(1);
  73. }
  74.  
  75. - const uint32 DBCFilesCount = 85;
  76. + const uint32 DBCFilesCount = 86;
  77.  
  78. barGoLink bar( (int)DBCFilesCount );
  79.  
  80. @@ -421,6 +422,7 @@ void LoadDBCStores(const std::string& dataPath)
  81. LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomPropertiesStore,dbcPath,"ItemRandomProperties.dbc");
  82. LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomSuffixStore, dbcPath,"ItemRandomSuffix.dbc");
  83. LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemSetStore, dbcPath,"ItemSet.dbc");
  84. + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sLFGDungeonStore, dbcPath,"LFGDungeons.dbc");
  85. LoadDBC(availableDbcLocales,bar,bad_dbc_files,sLockStore, dbcPath,"Lock.dbc");
  86. LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMailTemplateStore, dbcPath,"MailTemplate.dbc");
  87. LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapStore, dbcPath,"Map.dbc");
  88. diff --git a/src/game/DBCStores.h b/src/game/DBCStores.h
  89. index 5051236..5e3d271 100644
  90. --- a/src/game/DBCStores.h
  91. +++ b/src/game/DBCStores.h
  92. @@ -119,6 +119,7 @@ extern DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore;
  93. extern DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore;
  94. extern DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore;
  95. extern DBCStorage <ItemSetEntry> sItemSetStore;
  96. +extern DBCStorage <LFGDungeonEntry> sLFGDungeonStore;
  97. extern DBCStorage <LockEntry> sLockStore;
  98. extern DBCStorage <MailTemplateEntry> sMailTemplateStore;
  99. extern DBCStorage <MapEntry> sMapStore;
  100. diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h
  101. index e63ae5c..cb8a8a9 100644
  102. --- a/src/game/DBCStructure.h
  103. +++ b/src/game/DBCStructure.h
  104. @@ -1075,6 +1075,29 @@ struct ItemSetEntry
  105. uint32 required_skill_value; // 52 m_requiredSkillRank
  106. };
  107.  
  108. +struct LFGDungeonEntry
  109. +{
  110. + uint32 ID; // 0
  111. + //char* name[16]; // 1-17 Name lang
  112. + uint32 minlevel; // 18
  113. + uint32 maxlevel; // 19
  114. + uint32 reclevel; // 20
  115. + uint32 recminlevel; // 21
  116. + uint32 recmaxlevel; // 22
  117. + uint32 map; // 23
  118. + uint32 heroic; // 24
  119. + //uint32 unk; // 25
  120. + uint32 type; // 26
  121. + //uint32 unk2; // 27
  122. + //char* unk3; // 28
  123. + uint32 expansion; // 29
  124. + //uint32 unk4; // 30
  125. + uint32 grouptype; // 31
  126. + //char* desc[16]; // 32-47 Description
  127. + // Helpers
  128. + uint32 Entry() const { return ID + (type << 24); }
  129. +};
  130. +
  131. #define MAX_LOCK_CASE 8
  132.  
  133. struct LockEntry
  134. diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h
  135. index 5824944..fa6eb04 100644
  136. --- a/src/game/DBCfmt.h
  137. +++ b/src/game/DBCfmt.h
  138. @@ -70,6 +70,7 @@ const char ItemLimitCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii";
  139. const char ItemRandomPropertiesfmt[]="nxiiiiissssssssssssssssx";
  140. const char ItemRandomSuffixfmt[]="nssssssssssssssssxxiiiiiiiiii";
  141. const char ItemSetEntryfmt[]="dssssssssssssssssxxxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiiiii";
  142. +const char LFGDungeonEntryfmt[]="nxxxxxxxxxxxxxxxxxiiiiiiixixxixixxxxxxxxxxxxxxxxx";
  143. const char LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx";
  144. const char MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxssssssssssssssssx";
  145. const char MapEntryfmt[]="nxixxssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixiffxixx";
  146. diff --git a/src/game/Group.cpp b/src/game/Group.cpp
  147. index 1ba7e36..f97fd51 100644
  148. --- a/src/game/Group.cpp
  149. +++ b/src/game/Group.cpp
  150. @@ -34,13 +34,14 @@
  151. #include "MapInstanced.h"
  152. #include "Util.h"
  153. #include "LootMgr.h"
  154. +#include "LFGMgr.h"
  155.  
  156. #define LOOT_ROLL_TIMEOUT (1*MINUTE*IN_MILLISECONDS)
  157.  
  158. Group::Group() : m_Id(0), m_leaderGuid(0), m_mainTank(0), m_mainAssistant(0), m_groupType(GROUPTYPE_NORMAL),
  159. m_dungeonDifficulty(REGULAR_DIFFICULTY), m_raidDifficulty(REGULAR_DIFFICULTY),
  160. m_bgGroup(NULL), m_lootMethod(FREE_FOR_ALL), m_looterGuid(0), m_lootThreshold(ITEM_QUALITY_UNCOMMON),
  161. - m_subGroupsCounts(NULL)
  162. + m_subGroupsCounts(NULL), m_guid(0), m_counter(0)
  163. {
  164. for (int i = 0; i < TARGET_ICON_COUNT; ++i)
  165. m_targetIcons[i] = 0;
  166. @@ -98,6 +99,7 @@ bool Group::Create(const uint64 &guid, const char * name)
  167. if(!isBGGroup())
  168. {
  169. m_Id = sObjectMgr.GenerateGroupId();
  170. + m_guid = MAKE_NEW_GUID(m_Id, 0, HIGHGUID_GROUP);
  171.  
  172. Player *leader = sObjectMgr.GetPlayer(guid);
  173. if(leader)
  174. @@ -133,6 +135,7 @@ bool Group::LoadGroupFromDB(Field* fields)
  175. // result = CharacterDatabase.Query("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, groupType, difficulty, raiddifficulty, leaderGuid, groupId FROM groups");
  176.  
  177. m_Id = fields[17].GetUInt32();
  178. + m_guid = MAKE_NEW_GUID(m_Id, 0, HIGHGUID_GROUP);
  179. m_leaderGuid = MAKE_NEW_GUID(fields[16].GetUInt32(),0,HIGHGUID_PLAYER);
  180.  
  181. // group leader not exist
  182. @@ -309,6 +312,11 @@ bool Group::AddMember(const uint64 &guid, const char* name)
  183.  
  184. uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method)
  185. {
  186. + //BroadcastGroupUpdate();
  187. +
  188. + if (!isBGGroup())
  189. + sLFGMgr.Leave(NULL, this);
  190. +
  191. // remove member and change leader (if need) only if strong more 2 members _before_ member remove
  192. if(GetMembersCount() > uint32(isBGGroup() ? 1 : 2)) // in BG group case allow 1 members group
  193. {
  194. @@ -324,8 +332,9 @@ uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method)
  195.  
  196. if(method == 1)
  197. {
  198. - data.Initialize( SMSG_GROUP_UNINVITE, 0 );
  199. - player->GetSession()->SendPacket( &data );
  200. + data.Initialize(SMSG_GROUP_UNINVITE, 0);
  201. + player->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_LEADER);
  202. + player->GetSession()->SendPacket(&data);
  203. }
  204.  
  205. //we already removed player from group and in player->GetGroup() is his original group!
  206. @@ -337,7 +346,7 @@ uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method)
  207. {
  208. data.Initialize(SMSG_GROUP_LIST, 1+1+1+1+8+4+4+8);
  209. data << uint8(0x10) << uint8(0) << uint8(0) << uint8(0);
  210. - data << uint64(0) << uint32(0) << uint32(0) << uint64(0);
  211. + data << uint64(m_guid) << uint32(m_counter) << uint32(0) << uint64(0);
  212. player->GetSession()->SendPacket(&data);
  213. }
  214.  
  215. @@ -355,7 +364,7 @@ uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method)
  216. }
  217. // if group before remove <= 2 disband it
  218. else
  219. - Disband(true);
  220. + Disband();
  221.  
  222. return m_memberSlots.size();
  223. }
  224. @@ -396,6 +405,8 @@ void Group::Disband(bool hideDestroy)
  225. player->SetOriginalGroup(NULL);
  226. else
  227. player->SetGroup(NULL);
  228. + player->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_GROUP_DISBAND);
  229. + player->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_LEADER);
  230. }
  231.  
  232. // quest related GO state dependent from raid membership
  233. @@ -421,7 +432,7 @@ void Group::Disband(bool hideDestroy)
  234. {
  235. data.Initialize(SMSG_GROUP_LIST, 1+1+1+1+8+4+4+8);
  236. data << uint8(0x10) << uint8(0) << uint8(0) << uint8(0);
  237. - data << uint64(0) << uint32(0) << uint32(0) << uint64(0);
  238. + data << uint64(m_guid) << uint32(m_counter) << uint32(0) << uint64(0);
  239. player->GetSession()->SendPacket(&data);
  240. }
  241.  
  242. @@ -442,6 +453,7 @@ void Group::Disband(bool hideDestroy)
  243. ResetInstances(INSTANCE_RESET_GROUP_DISBAND, true, NULL);
  244. }
  245.  
  246. + m_guid = 0;
  247. m_leaderGuid = 0;
  248. m_leaderName = "";
  249. }
  250. @@ -979,8 +991,8 @@ void Group::SendUpdate()
  251. data << uint8(0);
  252. data << uint32(0);
  253. }
  254. - data << uint64(0x50000000FFFFFFFELL); // related to voice chat?
  255. - data << uint32(0); // 3.3, this value increments every time SMSG_GROUP_LIST is sent
  256. + data << uint64(m_guid);
  257. + data << uint32(m_counter++); // 3.3, value increases every time this packet gets sent
  258. data << uint32(GetMembersCount()-1);
  259. for(member_citerator citr2 = m_memberSlots.begin(); citr2 != m_memberSlots.end(); ++citr2)
  260. {
  261. @@ -1158,6 +1170,7 @@ bool Group::_removeMember(const uint64 &guid)
  262. player->SetOriginalGroup(NULL);
  263. else
  264. player->SetGroup(NULL);
  265. + player->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_LEADER);
  266. }
  267. }
  268.  
  269. diff --git a/src/game/Group.h b/src/game/Group.h
  270. index c9cffe3..97bde46 100644
  271. --- a/src/game/Group.h
  272. +++ b/src/game/Group.h
  273. @@ -209,6 +209,7 @@ class MANGOS_DLL_SPEC Group
  274. bool isBGGroup() const { return m_bgGroup != NULL; }
  275. bool IsCreated() const { return GetMembersCount() > 0; }
  276. const uint64& GetLeaderGUID() const { return m_leaderGuid; }
  277. + const uint64& GetGUID() const { return m_guid; }
  278. const char * GetLeaderName() const { return m_leaderName.c_str(); }
  279. LootMethod GetLootMethod() const { return m_lootMethod; }
  280. const uint64& GetLooterGuid() const { return m_looterGuid; }
  281. @@ -451,5 +452,7 @@ class MANGOS_DLL_SPEC Group
  282. Rolls RollId;
  283. BoundInstancesMap m_boundInstances[MAX_DIFFICULTY];
  284. uint8* m_subGroupsCounts;
  285. + uint64 m_guid;
  286. + uint32 m_counter; // used only in SMSG_GROUP_LIST
  287. };
  288. #endif
  289. diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp
  290. index d73b233..8bdc202 100644
  291. --- a/src/game/GroupHandler.cpp
  292. +++ b/src/game/GroupHandler.cpp
  293. @@ -28,6 +28,7 @@
  294. #include "Group.h"
  295. #include "SocialMgr.h"
  296. #include "Util.h"
  297. +#include "LFG.h"
  298.  
  299. /* differeces from off:
  300. -you can uninvite yourself - is is useful
  301. @@ -161,6 +162,8 @@ void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data )
  302. data << uint32(0); // unk
  303. player->GetSession()->SendPacket(&data);
  304.  
  305. + SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
  306. + SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
  307. SendPartyResult(PARTY_OP_INVITE, membername, ERR_PARTY_RESULT_OK);
  308. }
  309.  
  310. @@ -207,6 +210,16 @@ void WorldSession::HandleGroupAcceptOpcode( WorldPacket & recv_data )
  311. // everything is fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!!
  312. if(!group->AddMember(GetPlayer()->GetGUID(), GetPlayer()->GetName()))
  313. return;
  314. +
  315. + SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
  316. + for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
  317. + if (Player *plrg = itr->getSource())
  318. + {
  319. + plrg->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_CLEAR_LOCK_LIST);
  320. + plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_CLEAR_LOCK_LIST);
  321. + }
  322. +
  323. + //group->BroadcastGroupUpdate();
  324. }
  325.  
  326. void WorldSession::HandleGroupDeclineOpcode( WorldPacket & /*recv_data*/ )
  327. diff --git a/src/game/LFG.h b/src/game/LFG.h
  328. new file mode 100644
  329. index 0000000..4ef3d20
  330. --- /dev/null
  331. +++ b/src/game/LFG.h
  332. @@ -0,0 +1,54 @@
  333. +#ifndef _LFG_H
  334. +#define _LFG_H
  335. +
  336. +#include "Platform/Define.h"
  337. +#include "Object.h"
  338. +
  339. +enum LfgRoles
  340. +{
  341. + ROLE_NONE = 0x00,
  342. + ROLE_LEADER = 0x01,
  343. + ROLE_TANK = 0x02,
  344. + ROLE_HEALER = 0x04,
  345. + ROLE_DAMAGE = 0x08,
  346. +};
  347. +
  348. +enum LfgUpdateType
  349. +{
  350. + LFG_UPDATETYPE_LEADER = 1,
  351. + LFG_UPDATETYPE_ROLECHECK_ABORTED = 4,
  352. + LFG_UPDATETYPE_JOIN_PROPOSAL = 5,
  353. + LFG_UPDATETYPE_ROLECHECK_FAILED = 6,
  354. + LFG_UPDATETYPE_REMOVED_FROM_QUEUE = 7,
  355. + LFG_UPDATETYPE_PROPOSAL_FAILED = 8,
  356. + LFG_UPDATETYPE_PROPOSAL_DECLINED = 9,
  357. + LFG_UPDATETYPE_GROUP_FOUND = 10,
  358. + LFG_UPDATETYPE_ADDED_TO_QUEUE = 12,
  359. + LFG_UPDATETYPE_PROPOSAL_FOUND = 13,
  360. + LFG_UPDATETYPE_CLEAR_LOCK_LIST = 14,
  361. + LFG_UPDATETYPE_GROUP_MEMBER_OFFLINE = 15,
  362. + LFG_UPDATETYPE_GROUP_DISBAND = 16,
  363. +};
  364. +
  365. +typedef std::set<uint32> LfgDungeonSet;
  366. +
  367. +struct LookingForGroup
  368. +{
  369. + LookingForGroup(): roles(0)
  370. + {
  371. + donerandomDungeons.clear();
  372. + applyDungeons.clear();
  373. + }
  374. + std::string comment;
  375. + int8 roles;
  376. +
  377. + bool isDungeonDone(const uint32 entry)
  378. + {
  379. + return donerandomDungeons.find(entry) != donerandomDungeons.end();
  380. + }
  381. +
  382. + LfgDungeonSet applyDungeons; // Dungeons the player have applied for
  383. + LfgDungeonSet donerandomDungeons; // Finished random Dungeons (to calculate the bonus);
  384. +};
  385. +
  386. +#endif
  387. diff --git a/src/game/LFGHandler.cpp b/src/game/LFGHandler.cpp
  388. index 8eaa56c..c077e50 100644
  389. --- a/src/game/LFGHandler.cpp
  390. +++ b/src/game/LFGHandler.cpp
  391. @@ -16,442 +16,235 @@
  392. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  393. */
  394.  
  395. +#include "LFGMgr.h"
  396. #include "WorldSession.h"
  397. -#include "Log.h"
  398. -#include "Database/DatabaseEnv.h"
  399. -#include "Player.h"
  400. #include "WorldPacket.h"
  401. -#include "ObjectMgr.h"
  402. -#include "World.h"
  403. +#include "Player.h"
  404.  
  405. -static void AttemptJoin(Player* _player)
  406. +void WorldSession::HandleLfgJoinOpcode(WorldPacket &recv_data)
  407. {
  408. - // skip not can autojoin cases and player group case
  409. - if(!_player->m_lookingForGroup.canAutoJoin() || _player->GetGroup())
  410. - return;
  411. -
  412. - //TODO: Guard Player Map
  413. - HashMapHolder<Player>::MapType const& players = sObjectAccessor.GetPlayers();
  414. - for(HashMapHolder<Player>::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter)
  415. - {
  416. - Player *plr = iter->second;
  417. -
  418. - // skip enemies and self
  419. - if(!plr || plr==_player || plr->GetTeam() != _player->GetTeam())
  420. - continue;
  421. -
  422. - //skip players not in world
  423. - if(!plr->IsInWorld())
  424. - continue;
  425. -
  426. - // skip not auto add, not group leader cases
  427. - if (!plr->GetSession()->LookingForGroup_auto_add || (plr->GetGroup() && plr->GetGroup()->GetLeaderGUID()!=plr->GetGUID()))
  428. - continue;
  429. -
  430. - // skip non auto-join or empty slots, or non compatible slots
  431. - if(!plr->m_lookingForGroup.more.canAutoJoin() || !_player->m_lookingForGroup.HaveInSlot(plr->m_lookingForGroup.more))
  432. - continue;
  433. -
  434. - // attempt create group, or skip
  435. - if(!plr->GetGroup())
  436. - {
  437. - Group* group = new Group;
  438. - if(!group->Create(plr->GetGUID(), plr->GetName()))
  439. - {
  440. - delete group;
  441. - continue;
  442. - }
  443. -
  444. - sObjectMgr.AddGroup(group);
  445. - }
  446. -
  447. - // stop at success join
  448. - if(plr->GetGroup()->AddMember(_player->GetGUID(), _player->GetName()))
  449. - {
  450. - if( sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER )
  451. - _player->LeaveLFGChannel();
  452. - break;
  453. - }
  454. - // full
  455. - else
  456. - {
  457. - if( sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && plr->GetSession()->GetSecurity() == SEC_PLAYER )
  458. - plr->LeaveLFGChannel();
  459. - }
  460. - }
  461. -}
  462. + DEBUG_LOG("CMSG_LFG_JOIN");
  463.  
  464. -static void AttemptAddMore(Player* _player)
  465. -{
  466. - // skip not group leader case
  467. - if(_player->GetGroup() && _player->GetGroup()->GetLeaderGUID()!=_player->GetGUID())
  468. - return;
  469. + uint8 numDungeons;
  470. + uint32 dungeon;
  471. + uint32 roles;
  472. + std::string comment;
  473.  
  474. - if(!_player->m_lookingForGroup.more.canAutoJoin())
  475. + recv_data >> roles;
  476. + recv_data.read_skip<uint8>(); // unk - always 0
  477. + recv_data.read_skip<uint8>(); // unk - always 0
  478. + recv_data >> numDungeons;
  479. + if (!numDungeons)
  480. + {
  481. + sLog.outError("Invalid CMSG_LFG_JOIN packet sent by %s", GetPlayer()->GetName());
  482. + recv_data.rpos(recv_data.wpos());
  483. return;
  484. + }
  485.  
  486. - //TODO: Guard Player map
  487. - HashMapHolder<Player>::MapType const& players = sObjectAccessor.GetPlayers();
  488. - for(HashMapHolder<Player>::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter)
  489. + GetPlayer()->m_lookingForGroup.roles = uint8(roles);
  490. + for (int8 i = 0 ; i < numDungeons; ++i)
  491. {
  492. - Player *plr = iter->second;
  493. -
  494. - // skip enemies and self
  495. - if(!plr || plr==_player || plr->GetTeam() != _player->GetTeam())
  496. - continue;
  497. -
  498. - if(!plr->IsInWorld())
  499. - continue;
  500. -
  501. - // skip not auto join or in group
  502. - if(!plr->GetSession()->LookingForGroup_auto_join || plr->GetGroup() )
  503. - continue;
  504. -
  505. - if(!plr->m_lookingForGroup.HaveInSlot(_player->m_lookingForGroup.more))
  506. - continue;
  507. -
  508. - // attempt create group if need, or stop attempts
  509. - if(!_player->GetGroup())
  510. - {
  511. - Group* group = new Group;
  512. - if(!group->Create(_player->GetGUID(), _player->GetName()))
  513. - {
  514. - delete group;
  515. - return; // can't create group (??)
  516. - }
  517. -
  518. - sObjectMgr.AddGroup(group);
  519. - }
  520. -
  521. - // stop at join fail (full)
  522. - if(!_player->GetGroup()->AddMember(plr->GetGUID(), plr->GetName()) )
  523. - {
  524. - if( sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER )
  525. - _player->LeaveLFGChannel();
  526. -
  527. - break;
  528. - }
  529. -
  530. - // joined
  531. - if( sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && plr->GetSession()->GetSecurity() == SEC_PLAYER )
  532. - plr->LeaveLFGChannel();
  533. -
  534. - // and group full
  535. - if(_player->GetGroup()->IsFull() )
  536. - {
  537. - if( sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER )
  538. - _player->LeaveLFGChannel();
  539. -
  540. - break;
  541. - }
  542. + recv_data >> dungeon;
  543. + // remove the type from the dungeon entry
  544. + GetPlayer()->m_lookingForGroup.applyDungeons.insert((dungeon & 0x00FFFFFF));
  545. }
  546. -}
  547. -
  548. -void WorldSession::HandleLfgJoinOpcode( WorldPacket & recv_data )
  549. -{
  550. - DEBUG_LOG("CMSG_LFG_JOIN");
  551. - LookingForGroup_auto_join = true;
  552.  
  553. - uint8 counter1, counter2;
  554. - std::string comment;
  555. -
  556. - recv_data >> Unused<uint32>(); // lfg roles
  557. - recv_data >> Unused<uint8>(); // unk1 (unused?)
  558. - recv_data >> Unused<uint8>(); // unk2 (unused?)
  559. -
  560. - recv_data >> counter1;
  561. - for (uint8 i = 0; i < counter1; i++)
  562. - recv_data >> Unused<uint32>(); // queue block? (type/zone?)
  563. -
  564. - recv_data >> counter2;
  565. - for (uint8 i = 0; i < counter2; i++)
  566. - recv_data >> Unused<uint8>(); // unk (unused?)
  567. -
  568. - recv_data >> comment; // lfg comment
  569. + recv_data >> numDungeons; // unk - always 3
  570. + for (int8 i = 0 ; i < numDungeons; ++i)
  571. + recv_data.read_skip<uint8>(); // unk - always 0
  572.  
  573. - if(!_player) // needed because STATUS_AUTHED
  574. - return;
  575. + recv_data >> comment;
  576.  
  577. - AttemptJoin(_player);
  578. + GetPlayer()->m_lookingForGroup.comment = comment;
  579. + sLFGMgr.Join(GetPlayer());
  580. }
  581.  
  582. -void WorldSession::HandleLfgLeaveOpcode( WorldPacket & /*recv_data*/ )
  583. +void WorldSession::HandleLfgLeaveOpcode(WorldPacket & /*recv_data*/)
  584. {
  585. DEBUG_LOG("CMSG_LFG_LEAVE");
  586. - LookingForGroup_auto_join = false;
  587. +
  588. + // Check cheating - only leader can leave the queue
  589. + if (Group *grp = GetPlayer()->GetGroup())
  590. + {
  591. + if (grp->GetLeaderGUID() != GetPlayer()->GetGUID())
  592. + return;
  593. + else
  594. + sLFGMgr.Leave(GetPlayer(), grp);
  595. + }
  596. + else
  597. + sLFGMgr.Leave(GetPlayer());
  598. }
  599.  
  600. -void WorldSession::HandleSearchLfgJoinOpcode( WorldPacket & recv_data )
  601. +void WorldSession::HandleLfgSetRolesOpcode(WorldPacket &recv_data)
  602. {
  603. - DEBUG_LOG("CMSG_SEARCH_LFG_JOIN");
  604. - LookingForGroup_auto_add = true;
  605. + DEBUG_LOG("CMSG_LFG_SET_ROLES");
  606.  
  607. - recv_data >> Unused<uint32>(); // join id?
  608. + uint8 roles;
  609. + recv_data >> roles; // Player Group Roles
  610.  
  611. - if(!_player) // needed because STATUS_AUTHED
  612. + Group *grp = GetPlayer()->GetGroup();
  613. + if (!grp)
  614. return;
  615. -
  616. - AttemptAddMore(_player);
  617. + GetPlayer()->m_lookingForGroup.roles = roles;
  618. + sLFGMgr.UpdateRoleCheck(grp, GetPlayer());
  619. }
  620.  
  621. -void WorldSession::HandleSearchLfgLeaveOpcode( WorldPacket & recv_data )
  622. +void WorldSession::HandleSetLfgCommentOpcode(WorldPacket & recv_data)
  623. {
  624. - DEBUG_LOG("CMSG_SEARCH_LFG_LEAVE");
  625. - LookingForGroup_auto_add = false;
  626. -
  627. - recv_data >> Unused<uint32>(); // join id?
  628. -}
  629. -
  630. -void WorldSession::HandleLfgClearOpcode( WorldPacket & /*recv_data */ )
  631. -{
  632. - // empty packet
  633. - DEBUG_LOG("CMSG_CLEAR_LOOKING_FOR_GROUP");
  634. -
  635. - for(int i = 0; i < MAX_LOOKING_FOR_GROUP_SLOT; ++i)
  636. - _player->m_lookingForGroup.slots[i].Clear();
  637. + DEBUG_LOG("CMSG_SET_LFG_COMMENT");
  638.  
  639. - if( sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER )
  640. - _player->LeaveLFGChannel();
  641. + std::string comment;
  642. + recv_data >> comment;
  643.  
  644. - SendLfgUpdate(0, 0, 0);
  645. + GetPlayer()->m_lookingForGroup.comment = comment;
  646. }
  647.  
  648. -void WorldSession::HandleLfmClearOpcode( WorldPacket & /*recv_data */)
  649. +void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket &/*recv_data*/)
  650. {
  651. - // empty packet
  652. - DEBUG_LOG("CMSG_CLEAR_LOOKING_FOR_MORE");
  653. -
  654. - _player->m_lookingForGroup.more.Clear();
  655. + DEBUG_LOG("CMSG_LFD_PLAYER_LOCK_INFO_REQUEST");
  656. + sLFGMgr.SendLfgPlayerInfo(GetPlayer());
  657. }
  658.  
  659. -void WorldSession::HandleSetLfmOpcode( WorldPacket & recv_data )
  660. +void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket &/*recv_data*/)
  661. {
  662. - DEBUG_LOG("CMSG_SET_LOOKING_FOR_MORE");
  663. - //recv_data.hexlike();
  664. - uint32 temp, entry, type;
  665. - uint8 unk1;
  666. - uint8 unk2[3];
  667. -
  668. - recv_data >> temp >> unk1 >> unk2[0] >> unk2[1] >> unk2[2];
  669. -
  670. - entry = ( temp & 0x00FFFFFF);
  671. - type = ( (temp >> 24) & 0x000000FF);
  672. -
  673. - _player->m_lookingForGroup.more.Set(entry,type);
  674. - DEBUG_LOG("LFM set: temp %u, zone %u, type %u", temp, entry, type);
  675. -
  676. - if(LookingForGroup_auto_add)
  677. - AttemptAddMore(_player);
  678. -
  679. - SendLfgResult(type, entry, 1);
  680. + DEBUG_LOG("CMSG_LFD_PARTY_LOCK_INFO_REQUEST");
  681. + sLFGMgr.SendLfgPartyInfo(GetPlayer());
  682. }
  683.  
  684. -void WorldSession::HandleSetLfgCommentOpcode( WorldPacket & recv_data )
  685. +void WorldSession::SendLfgUpdatePlayer(uint8 updateType)
  686. {
  687. - DEBUG_LOG("CMSG_SET_LFG_COMMENT");
  688. - //recv_data.hexlike();
  689. + bool queued = false;
  690. + bool extrainfo = false;
  691.  
  692. - std::string comment;
  693. - recv_data >> comment;
  694. - DEBUG_LOG("LFG comment %s", comment.c_str());
  695. -
  696. - _player->m_lookingForGroup.comment = comment;
  697. -}
  698. -
  699. -void WorldSession::HandleLookingForGroup(WorldPacket& recv_data)
  700. -{
  701. - DEBUG_LOG("MSG_LOOKING_FOR_GROUP");
  702. - //recv_data.hexlike();
  703. - uint32 type, entry, unk;
  704. -
  705. - recv_data >> type >> entry >> unk;
  706. - DEBUG_LOG("MSG_LOOKING_FOR_GROUP: type %u, entry %u, unk %u", type, entry, unk);
  707. -
  708. - if(LookingForGroup_auto_add)
  709. - AttemptAddMore(_player);
  710. + switch(updateType)
  711. + {
  712. + case LFG_UPDATETYPE_JOIN_PROPOSAL:
  713. + case LFG_UPDATETYPE_ADDED_TO_QUEUE:
  714. + queued = true;
  715. + extrainfo = true;
  716. + break;
  717. + //case LFG_UPDATETYPE_CLEAR_LOCK_LIST: // TODO: Sometimes has extrainfo - Check ocurrences...
  718. + case LFG_UPDATETYPE_PROPOSAL_FOUND:
  719. + extrainfo = true;
  720. + break;
  721. + }
  722. + DEBUG_LOG("SMSG_LFG_UPDATE_PLAYER");
  723. + WorldPacket data(SMSG_LFG_UPDATE_PLAYER, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + GetPlayer()->m_lookingForGroup.applyDungeons.size() * 4 + GetPlayer()->m_lookingForGroup.comment.length()));
  724. + data << uint8(updateType); // Lfg Update type
  725. + data << uint8(extrainfo); // Extra info
  726. + if (extrainfo)
  727. + {
  728. + data << uint8(queued); // Join the queue
  729. + data << uint8(0); // unk - Always 0
  730. + data << uint8(0); // unk - Always 0
  731.  
  732. - if(LookingForGroup_auto_join)
  733. - AttemptJoin(_player);
  734. + uint8 size = GetPlayer()->m_lookingForGroup.applyDungeons.size();
  735. + data << uint8(size);
  736.  
  737. - SendLfgResult(type, entry, 0);
  738. - SendLfgUpdate(0, 1, 0);
  739. + for (LfgDungeonSet::const_iterator it = GetPlayer()->m_lookingForGroup.applyDungeons.begin(); it != GetPlayer()->m_lookingForGroup.applyDungeons.end(); ++it)
  740. + data << uint32(*it);
  741. + data << GetPlayer()->m_lookingForGroup.comment;
  742. + }
  743. + SendPacket(&data);
  744. }
  745.  
  746. -void WorldSession::SendLfgResult(uint32 type, uint32 entry, uint8 lfg_type)
  747. +void WorldSession::SendLfgUpdateParty(uint8 updateType)
  748. {
  749. - /*uint32 number = 0;
  750. + bool join = false;
  751. + bool extrainfo = false;
  752. + bool queued = false;
  753.  
  754. - WorldPacket data(MSG_LOOKING_FOR_GROUP);
  755. - data << uint32(type); // type
  756. - data << uint32(entry); // entry from LFGDungeons.dbc
  757. -
  758. - data << uint8(0);
  759. - if(uint8)
  760. + switch(updateType)
  761. {
  762. - uint32 count1;
  763. - for(count1)
  764. - {
  765. - uint64; // player guid
  766. - }
  767. + case LFG_UPDATETYPE_JOIN_PROPOSAL:
  768. + extrainfo = true;
  769. + break;
  770. + case LFG_UPDATETYPE_ADDED_TO_QUEUE:
  771. + extrainfo = true;
  772. + join = true;
  773. + queued = true;
  774. + break;
  775. + case LFG_UPDATETYPE_CLEAR_LOCK_LIST:
  776. + // join = true; // TODO: Sometimes queued and extrainfo - Check ocurrences...
  777. + queued = true;
  778. + break;
  779. + case LFG_UPDATETYPE_PROPOSAL_FOUND:
  780. + extrainfo = true;
  781. + join = true;
  782. + break;
  783. }
  784.  
  785. - data << uint32(0); // count2
  786. - data << uint32(0);
  787. - for(count2)
  788. + DEBUG_LOG("SMSG_LFG_UPDATE_PARTY");
  789. + WorldPacket data(SMSG_LFG_UPDATE_PARTY, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + 1 + GetPlayer()->m_lookingForGroup.applyDungeons.size() * 4 + GetPlayer()->m_lookingForGroup.comment.length()));
  790. + data << uint8(updateType); // Lfg Update type
  791. + data << uint8(extrainfo); // Extra info
  792. + if (extrainfo)
  793. {
  794. - uint64 // not player guid
  795. - uint32 flags;
  796. - if(flags & 0x2)
  797. - {
  798. - data << uint8(0); // string
  799. - }
  800. - if(flags & 0x10)
  801. - {
  802. - data << uint8(0);
  803. - }
  804. - if(flags & 0x20)
  805. - {
  806. - for(int i = 0; i < 3; ++i)
  807. - {
  808. - data << uint8(0);
  809. - }
  810. - }
  811. - }
  812. + data << uint8(join); // LFG Join
  813. + data << uint8(queued); // Join the queue
  814. + data << uint8(0); // unk - Always 0
  815. + data << uint8(0); // unk - Always 0
  816. + for (uint8 i = 0; i < 3; ++i)
  817. + data << uint8(0); // unk - Always 0
  818.  
  819. - size_t count3_pos = data.wpos();
  820. - data << uint32(0); // count3
  821. - data << uint32(0); // unk
  822. + uint8 size = GetPlayer()->m_lookingForGroup.applyDungeons.size();
  823. + data << uint8(size);
  824.  
  825. - //TODO: Guard Player map
  826. - HashMapHolder<Player>::MapType const& players = sObjectAccessor.GetPlayers();
  827. - for(HashMapHolder<Player>::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter)
  828. - {
  829. - Player *plr = iter->second;
  830. -
  831. - if(!plr || plr->GetTeam() != _player->GetTeam())
  832. - continue;
  833. -
  834. - if(!plr->IsInWorld())
  835. - continue;
  836. -
  837. - if(!plr->m_lookingForGroup.HaveInSlot(entry, type))
  838. - continue;
  839. -
  840. - ++number;
  841. -
  842. - data << uint64(plr->GetGUID()); // guid
  843. -
  844. - uint32 flags = 0x1FF;
  845. - data << uint32(flags); // flags
  846. -
  847. - if(flags & 0x1)
  848. - {
  849. - data << uint8(plr->getLevel());
  850. - data << uint8(plr->getClass());
  851. - data << uint8(plr->getRace());
  852. -
  853. - for(int i = 0; i < 3; ++i)
  854. - data << uint8(0); // spent talents count in specific tab
  855. -
  856. - data << uint32(0); // resistances1
  857. - data << uint32(0); // spd/heal
  858. - data << uint32(0); // spd/heal
  859. - data << uint32(0); // combat_rating9
  860. - data << uint32(0); // combat_rating10
  861. - data << uint32(0); // combat_rating11
  862. - data << float(0); // mp5
  863. - data << float(0); // unk
  864. - data << uint32(0); // attack power
  865. - data << uint32(0); // stat1
  866. - data << uint32(0); // maxhealth
  867. - data << uint32(0); // maxpower1
  868. - data << uint32(0); // unk
  869. - data << float(0); // unk
  870. - data << uint32(0); // unk
  871. - data << uint32(0); // unk
  872. - data << uint32(0); // unk
  873. - data << uint32(0); // unk
  874. - data << uint32(0); // combat_rating20
  875. - data << uint32(0); // unk
  876. - }
  877. -
  878. - if(flags & 0x2)
  879. - data << plr->m_lookingForGroup.comment; // comment
  880. -
  881. - if(flags & 0x4)
  882. - data << uint8(0); // unk
  883. -
  884. - if(flags & 0x8)
  885. - data << uint64(0); // guid from count2 block, not player guid
  886. -
  887. - if(flags & 0x10)
  888. - data << uint8(0); // unk
  889. -
  890. - if(flags & 0x20)
  891. - data << uint8(plr->m_lookingForGroup.roles); // roles
  892. -
  893. - if(flags & 0x40)
  894. - data << uint32(plr->GetZoneId()); // areaid
  895. -
  896. - if(flags & 0x100)
  897. - data << uint8(0); // LFG/LFM flag?
  898. -
  899. - if(flags & 0x80)
  900. - {
  901. - for(uint8 j = 0; j < MAX_LOOKING_FOR_GROUP_SLOT; ++j)
  902. - {
  903. - data << uint32(plr->m_lookingForGroup.slots[j].entry | (plr->m_lookingForGroup.slots[j].type << 24));
  904. - }
  905. - }
  906. - }
  907. -
  908. - data.put<uint32>(count3_pos, number); // fill count placeholder
  909. + for (LfgDungeonSet::const_iterator it = GetPlayer()->m_lookingForGroup.applyDungeons.begin(); it != GetPlayer()->m_lookingForGroup.applyDungeons.end(); ++it)
  910. + data << uint32(*it);
  911.  
  912. - SendPacket(&data);*/
  913. + data << GetPlayer()->m_lookingForGroup.comment;
  914. + }
  915. + SendPacket(&data);
  916. }
  917.  
  918. -void WorldSession::HandleSetLfgOpcode( WorldPacket & recv_data )
  919. +void WorldSession::SendLfgRoleChosen(uint64 guid, uint8 roles)
  920. {
  921. - DEBUG_LOG("CMSG_SET_LOOKING_FOR_GROUP");
  922. - recv_data.hexlike();
  923. - uint32 slot, temp, entry, type;
  924. - uint8 roles, unk1;
  925. -
  926. - recv_data >> slot >> temp >> roles >> unk1;
  927. + DEBUG_LOG("SMSG_LFG_ROLE_CHOSEN");
  928.  
  929. - entry = ( temp & 0x00FFFFFF);
  930. - type = ( (temp >> 24) & 0x000000FF);
  931. + WorldPacket data(SMSG_LFG_ROLE_CHOSEN);
  932. + data << uint64(guid); // Guid
  933. + data << uint8(roles > 0); // Ready
  934. + data << uint32(roles); // Roles
  935. + SendPacket(&data);
  936. +}
  937.  
  938. - if(slot >= MAX_LOOKING_FOR_GROUP_SLOT)
  939. +void WorldSession::SendLfgJoinResult(uint8 checkResult, uint8 checkValue)
  940. +{
  941. + if (checkResult == LFG_JOIN_PARTY_NOT_MEET_REQS) // Should never happen - its handled in Mgr
  942. return;
  943.  
  944. - _player->m_lookingForGroup.slots[slot].Set(entry, type);
  945. - _player->m_lookingForGroup.roles = roles;
  946. - DEBUG_LOG("LFG set: looknumber %u, temp %X, type %u, entry %u", slot, temp, type, entry);
  947. -
  948. - if(LookingForGroup_auto_join)
  949. - AttemptJoin(_player);
  950. + DEBUG_LOG("SMSG_LFG_JOIN_RESULT");
  951.  
  952. - //SendLfgResult(type, entry, 0);
  953. - SendLfgUpdate(0, 1, 0);
  954. + WorldPacket data(SMSG_LFG_JOIN_RESULT);
  955. + data << uint32(checkResult); // Check Result
  956. + data << uint32(checkValue); // Check Value
  957. + SendPacket(&data);
  958. }
  959.  
  960. -void WorldSession::HandleLfgSetRoles(WorldPacket &recv_data)
  961. +void WorldSession::SendLfgQueueStatus(uint32 dungeon, int32 waitTime, int32 avgWaitTime, int32 waitTimeTanks, int32 waitTimeHealer, int32 waitTimeDps, uint32 queuedTime, uint8 tanks, uint8 healers, uint8 dps)
  962. {
  963. - DEBUG_LOG("CMSG_LFG_SET_ROLES");
  964. -
  965. - uint8 roles;
  966. - recv_data >> roles;
  967. -
  968. - _player->m_lookingForGroup.roles = roles;
  969. + DEBUG_LOG("SMSG_LFG_QUEUE_STATUS");
  970. + WorldPacket data(SMSG_LFG_QUEUE_STATUS);
  971. +
  972. + data << uint32(dungeon); // Dungeon
  973. + data << uint32(avgWaitTime); // Average Wait time
  974. + data << uint32(waitTime); // Wait Time
  975. + data << uint32(waitTimeTanks); // Wait Tanks
  976. + data << uint32(waitTimeHealer); // Wait Healers
  977. + data << uint32(waitTimeDps); // Wait Dps
  978. + data << uint8(tanks); // Tanks needed
  979. + data << uint8(healers); // Healers needed
  980. + data << uint8(dps); // Dps needed
  981. + data << uint32(queuedTime); // Player wait time in queue
  982. + SendPacket(&data);
  983. }
  984.  
  985. -void WorldSession::SendLfgUpdate(uint8 /*unk1*/, uint8 /*unk2*/, uint8 /*unk3*/)
  986. +void WorldSession::SendLfgUpdateSearch(bool update)
  987. {
  988. - // disabled
  989. - /*WorldPacket data(SMSG_LFG_UPDATE, 3);
  990. - data << uint8(unk1);
  991. - data << uint8(unk2);
  992. - data << uint8(unk3);
  993. - SendPacket(&data);*/
  994. + DEBUG_LOG("SMSG_LFG_UPDATE_SEARCH");
  995. +
  996. + WorldPacket data(SMSG_LFG_UPDATE_SEARCH);
  997. + data << uint8(update); // In Lfg Queue?
  998. + SendPacket(&data);
  999. }
  1000. diff --git a/src/game/LFGMgr.cpp b/src/game/LFGMgr.cpp
  1001. new file mode 100644
  1002. index 0000000..1112a42
  1003. --- /dev/null
  1004. +++ b/src/game/LFGMgr.cpp
  1005. @@ -0,0 +1,1069 @@
  1006. +#include "Policies/SingletonImp.h"
  1007. +#include "Common.h"
  1008. +#include "SharedDefines.h"
  1009. +#include "Group.h"
  1010. +#include "Player.h"
  1011. +#include "LFGMgr.h"
  1012. +#include "ObjectMgr.h"
  1013. +#include "WorldPacket.h"
  1014. +
  1015. +INSTANTIATE_SINGLETON_1(LFGMgr);
  1016. +
  1017. +/*********************************************************/
  1018. +/*** LFG QUEUES ***/
  1019. +/*********************************************************/
  1020. +
  1021. +LFGQueue::LFGQueue()
  1022. +{
  1023. + m_LfgQueue.clear();
  1024. + avgWaitTime = -1;
  1025. + waitTimeTanks = -1;
  1026. + waitTimeHealer = -1;
  1027. + waitTimeDps = -1;
  1028. +}
  1029. +
  1030. +LFGQueue::~LFGQueue()
  1031. +{
  1032. + m_LfgQueue.clear();
  1033. +}
  1034. +
  1035. +void LFGQueue::AddToQueue(uint64 guid, LfgQueueInfo* pqInfo)
  1036. +{
  1037. + if (LfgQueueInfo* qInfo = m_LfgQueue[guid])
  1038. + delete qInfo;
  1039. + m_LfgQueue[guid] = pqInfo;
  1040. + // ATM will only add it to the queue... No find group implementation... yet (on purpose)
  1041. +}
  1042. +
  1043. +bool LFGQueue::RemoveFromQueue(uint64 guid)
  1044. +{
  1045. + if (m_LfgQueue.empty())
  1046. + return false;
  1047. +
  1048. + LfgQueueInfoMap::iterator itr = m_LfgQueue.find(guid);
  1049. + if (itr == m_LfgQueue.end())
  1050. + return false;
  1051. +
  1052. + delete itr->second;
  1053. + m_LfgQueue.erase(itr);
  1054. + return true;
  1055. +}
  1056. +
  1057. +LfgQueueInfo* LFGQueue::GetQueueInfo(uint64 guid)
  1058. +{
  1059. + return m_LfgQueue[guid];
  1060. +}
  1061. +
  1062. +void LFGQueue::Update()
  1063. +{
  1064. + if (m_LfgQueue.empty())
  1065. + return;
  1066. +
  1067. + Player *plr;
  1068. + LfgQueueInfo *queue;
  1069. + time_t currTime = time(NULL);
  1070. + uint32 queuedTime;
  1071. + uint8 role = 0;
  1072. + int32 waitTime = -1;
  1073. + for (LfgQueueInfoMap::const_iterator itQueue = m_LfgQueue.begin(); itQueue != m_LfgQueue.end(); ++itQueue)
  1074. + {
  1075. + queue = itQueue->second;
  1076. + // Update queue status
  1077. + queuedTime = uint32(currTime - queue->joinTime);
  1078. + for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer)
  1079. + {
  1080. + plr = sObjectMgr.GetPlayer(itPlayer->first);
  1081. + if (!plr)
  1082. + continue;
  1083. + role = itPlayer->second;
  1084. + if (role & ROLE_TANK)
  1085. + {
  1086. + if (role & ROLE_HEALER || role & ROLE_DAMAGE)
  1087. + waitTime = avgWaitTime;
  1088. + else
  1089. + waitTime = waitTimeTanks;
  1090. + }
  1091. + else if (role & ROLE_HEALER)
  1092. + {
  1093. + if (role & ROLE_DAMAGE)
  1094. + waitTime = avgWaitTime;
  1095. + else
  1096. + waitTime = waitTimeDps;
  1097. + }
  1098. + plr->GetSession()->SendLfgQueueStatus(queue->dungeonId, waitTime, avgWaitTime, waitTimeTanks, waitTimeHealer, waitTimeDps, queuedTime, queue->tanks, queue->healers, queue->dps);
  1099. + }
  1100. + }
  1101. +}
  1102. +
  1103. +LFGMgr::LFGMgr()
  1104. +{
  1105. + m_QueueTimer = 0;
  1106. + m_update = true;
  1107. +}
  1108. +
  1109. +LFGMgr::~LFGMgr()
  1110. +{
  1111. + // RewardList to be removed -> query quest system
  1112. + for (LfgRewardList::iterator it = m_RewardList.begin(); it != m_RewardList.end(); ++it)
  1113. + delete *it;
  1114. + m_RewardList.clear();
  1115. +
  1116. + // RewardDoneList to be removed -> query quest system
  1117. + for (LfgRewardList::iterator it = m_RewardDoneList.begin(); it != m_RewardDoneList.end(); ++it)
  1118. + delete *it;
  1119. + m_RewardDoneList.clear();
  1120. +
  1121. + for(LFGQueueMap::iterator it = m_Queues.begin(); it != m_Queues.end(); ++it)
  1122. + delete it->second;
  1123. + m_Queues.clear();
  1124. +
  1125. + for (LfgDungeonMap::iterator it = m_DungeonsMap.begin(); it != m_DungeonsMap.end(); ++it)
  1126. + {
  1127. + it->second->clear();
  1128. + delete it->second;
  1129. + }
  1130. + m_DungeonsMap.clear();
  1131. +
  1132. + for (LfgRoleCheckMap::iterator it = m_RoleChecks.begin(); it != m_RoleChecks.end(); ++it)
  1133. + delete it->second;
  1134. + m_RoleChecks.clear();
  1135. +}
  1136. +
  1137. +void LFGMgr::Update(uint32 diff)
  1138. +{
  1139. + if (!m_update)
  1140. + return;
  1141. +
  1142. + // Update all players status queue info
  1143. + if (m_QueueTimer > LFG_QUEUEUPDATE_INTERVAL)
  1144. + {
  1145. + m_QueueTimer = 0;
  1146. + for (LFGQueueMap::iterator it = m_Queues.begin(); it != m_Queues.end(); ++it)
  1147. + it->second->Update();
  1148. + }
  1149. + else
  1150. + m_QueueTimer += diff;
  1151. +
  1152. + time_t currTime = time(NULL);
  1153. +
  1154. + // Remove obsolete role checks
  1155. + LfgRoleCheckMap::iterator itRoleCheck;
  1156. + LfgRoleCheck *pRoleCheck;
  1157. + for (LfgRoleCheckMap::iterator it = m_RoleChecks.begin(); it != m_RoleChecks.end();)
  1158. + {
  1159. + itRoleCheck = it++;
  1160. + pRoleCheck = itRoleCheck->second;
  1161. + if (currTime < pRoleCheck->cancelTime)
  1162. + continue;
  1163. + pRoleCheck->result = LFG_ROLECHECK_MISSING_ROLE;
  1164. +
  1165. + WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + pRoleCheck->dungeons.size() * 4 + 1 + pRoleCheck->roles.size() * (8 + 1 + 4 + 1));
  1166. + DEBUG_LOG("SMSG_LFG_ROLE_CHECK_UPDATE");
  1167. + BuildLfgRoleCheck(data, pRoleCheck);
  1168. + Player *plr = NULL;
  1169. + for (LfgRolesMap::const_iterator itRoles = pRoleCheck->roles.begin(); itRoles != pRoleCheck->roles.end(); ++itRoles)
  1170. + {
  1171. + plr = sObjectMgr.GetPlayer(itRoles->first);
  1172. + if (!plr)
  1173. + continue;
  1174. + plr->GetSession()->SendPacket(&data);
  1175. + plr->m_lookingForGroup.applyDungeons.clear();
  1176. + plr->m_lookingForGroup.roles = 0;
  1177. +
  1178. + if (itRoles->first == pRoleCheck->leader)
  1179. + plr->GetSession()->SendLfgJoinResult(LFG_JOIN_FAILED, pRoleCheck->result);
  1180. + }
  1181. + delete pRoleCheck;
  1182. + m_RoleChecks.erase(itRoleCheck);
  1183. + }
  1184. +}
  1185. +
  1186. +/// <summary>
  1187. +/// Initialize Looking For Group
  1188. +/// </summary>
  1189. +void LFGMgr::InitLFG()
  1190. +{
  1191. + // Fill reward data (to be removed -> query quest system)
  1192. + LfgReward *reward;
  1193. + for (uint8 i = 0; i <= LFG_REWARD_DATA_SIZE; ++i)
  1194. + {
  1195. + reward = new LfgReward();
  1196. + reward->strangers = 0;
  1197. + reward->baseXP = RewardDungeonData[i][0];
  1198. + reward->baseMoney = RewardDungeonData[i][1];
  1199. + reward->variableMoney = 0;
  1200. + reward->variableXP = 0;
  1201. + reward->itemId = RewardDungeonData[i][2];
  1202. + reward->displayId = RewardDungeonData[i][3];
  1203. + reward->stackCount = RewardDungeonData[i][4];
  1204. + m_RewardList.push_back(reward);
  1205. + }
  1206. +
  1207. + for (uint8 i = 0; i < LFG_REWARD_DATA_SIZE; ++i)
  1208. + {
  1209. + reward = new LfgReward();
  1210. + reward->strangers = 0;
  1211. + reward->baseXP = RewardDungeonDoneData[i][0];
  1212. + reward->baseMoney = RewardDungeonDoneData[i][1];
  1213. + reward->variableMoney = 0;
  1214. + reward->variableXP = 0;
  1215. + reward->itemId = RewardDungeonDoneData[i][2];
  1216. + reward->displayId = RewardDungeonDoneData[i][3];
  1217. + reward->stackCount = RewardDungeonDoneData[i][4];
  1218. + m_RewardDoneList.push_back(reward);
  1219. + }
  1220. + // Initialize dungeonMap
  1221. + m_DungeonsMap[LFG_ALL_DUNGEONS] = GetAllDungeons();
  1222. + m_DungeonsMap[LFG_RANDOM_CLASSIC] = GetDungeonsByRandom(LFG_RANDOM_CLASSIC);
  1223. + m_DungeonsMap[LFG_RANDOM_BC_NORMAL] = GetDungeonsByRandom(LFG_RANDOM_BC_NORMAL);
  1224. + m_DungeonsMap[LFG_RANDOM_BC_HEROIC] = GetDungeonsByRandom(LFG_RANDOM_BC_HEROIC);
  1225. + m_DungeonsMap[LFG_RANDOM_LK_NORMAL] = GetDungeonsByRandom(LFG_RANDOM_LK_NORMAL);
  1226. + m_DungeonsMap[LFG_RANDOM_LK_HEROIC] = GetDungeonsByRandom(LFG_RANDOM_LK_HEROIC);
  1227. +}
  1228. +
  1229. +/// <summary>
  1230. +/// Adds the player to lfg queue
  1231. +/// </summary>
  1232. +/// <param name="plr">Player</param>
  1233. +void LFGMgr::Join(Player *plr)
  1234. +{
  1235. + Group *grp = plr->GetGroup();
  1236. +
  1237. + // TODO - 2010-05-27 Anyone can init rolecheck when already in a LFD Group?
  1238. + if (grp && grp->GetLeaderGUID() != plr->GetGUID())
  1239. + return;
  1240. +
  1241. + // Previous checks before joining
  1242. + LfgJoinResult result = LFG_JOIN_OK;
  1243. + if (plr->InBattleGround() || plr->InArena())
  1244. + result = LFG_JOIN_USING_BG_SYSTEM;
  1245. + else if (plr->HasAura(LFG_SPELL_DESERTER))
  1246. + result = LFG_JOIN_DESERTER;
  1247. + else if (plr->HasAura(LFG_SPELL_COOLDOWN))
  1248. + result = LFG_JOIN_RANDOM_COOLDOWN;
  1249. + else
  1250. + {
  1251. + // Check if all dungeons are valid
  1252. + for (LfgDungeonSet::const_iterator it = plr->m_lookingForGroup.applyDungeons.begin(); it != plr->m_lookingForGroup.applyDungeons.end(); ++it)
  1253. + {
  1254. + if ((m_DungeonsMap[LFG_ALL_DUNGEONS])->find(*it) == (m_DungeonsMap[LFG_ALL_DUNGEONS])->end())
  1255. + {
  1256. + result = LFG_JOIN_DUNGEON_INVALID;
  1257. + break;
  1258. + }
  1259. + }
  1260. + }
  1261. +
  1262. + if (grp && result == LFG_JOIN_OK)
  1263. + {
  1264. + if (grp->GetMembersCount() > MAX_GROUP_SIZE)
  1265. + result = LFG_JOIN_TOO_MUCH_MEMBERS;
  1266. + else if (grp->isRaidGroup())
  1267. + result = LFG_JOIN_MIXED_RAID_DUNGEON;
  1268. + else
  1269. + {
  1270. + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL && result == LFG_JOIN_OK; itr = itr->next())
  1271. + {
  1272. + if (Player *plrg = itr->getSource())
  1273. + {
  1274. + if (plrg->HasAura(LFG_SPELL_DESERTER))
  1275. + result = LFG_JOIN_PARTY_DESERTER;
  1276. + else if (plrg->HasAura(LFG_SPELL_COOLDOWN))
  1277. + result = LFG_JOIN_PARTY_RANDOM_COOLDOWN;
  1278. + }
  1279. + else
  1280. + result = LFG_JOIN_DISCONNECTED;
  1281. + }
  1282. + }
  1283. + }
  1284. +
  1285. + if (result != LFG_JOIN_OK)
  1286. + {
  1287. + plr->m_lookingForGroup.applyDungeons.clear();
  1288. + plr->m_lookingForGroup.roles = 0;
  1289. + plr->GetSession()->SendLfgJoinResult(result, 0);
  1290. + return;
  1291. + }
  1292. +
  1293. + if (grp)
  1294. + {
  1295. + Player *plrg = NULL;
  1296. + for (GroupReference *itr = plr->GetGroup()->GetFirstMember(); itr != NULL; itr = itr->next())
  1297. + {
  1298. + plrg = itr->getSource(); // Not null, checked earlier
  1299. + plrg->m_lookingForGroup.applyDungeons = plr->m_lookingForGroup.applyDungeons;
  1300. + plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_JOIN_PROPOSAL);
  1301. + }
  1302. + UpdateRoleCheck(grp, plr);
  1303. + }
  1304. + else
  1305. + {
  1306. + plr->GetSession()->SendLfgJoinResult(LFG_JOIN_OK, 0);
  1307. + plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_JOIN_PROPOSAL);
  1308. +
  1309. + // Add player to queue
  1310. + LfgQueueInfo *pqInfo;
  1311. + uint8 groupType = 0;
  1312. + uint8 tanks = LFG_TANKS_NEEDED;
  1313. + uint8 healers = LFG_HEALERS_NEEDED;
  1314. + uint8 dps = LFG_DPS_NEEDED;
  1315. + if (plr->m_lookingForGroup.roles & ROLE_TANK)
  1316. + --tanks;
  1317. + else if (plr->m_lookingForGroup.roles & ROLE_HEALER)
  1318. + --healers;
  1319. + else
  1320. + --dps;
  1321. + m_update = false;
  1322. + for (LfgDungeonSet::const_iterator it = plr->m_lookingForGroup.applyDungeons.begin(); it != plr->m_lookingForGroup.applyDungeons.end(); ++it)
  1323. + {
  1324. + groupType = GetDungeonGroupType(*it);
  1325. + pqInfo = m_Queues[groupType] ? m_Queues[groupType]->GetQueueInfo(plr->GetGUID()) : NULL;
  1326. + // if exist we have already added the player with another dungeon sharing same GroupType
  1327. + if (pqInfo)
  1328. + continue;
  1329. + pqInfo = new LfgQueueInfo();
  1330. + pqInfo->dungeonId = *it;
  1331. + pqInfo->joinTime = time_t(time(NULL));
  1332. + pqInfo->tanks = tanks;
  1333. + pqInfo->healers = healers;
  1334. + pqInfo->dps = dps;
  1335. + pqInfo->roles[plr->GetGUID()] = plr->m_lookingForGroup.roles;
  1336. + if (!m_Queues[groupType])
  1337. + m_Queues[groupType] = new LFGQueue();
  1338. + m_Queues[groupType]->AddToQueue(plr->GetGUID(), pqInfo);
  1339. + }
  1340. + m_update = true;
  1341. + }
  1342. +}
  1343. +
  1344. +/// <summary>
  1345. +/// Leave the lfg queue
  1346. +/// </summary>
  1347. +/// <param name="plr">Player (could be NULL)</param>
  1348. +/// <param name="grp">Group (could be NULL)</param>
  1349. +void LFGMgr::Leave(Player *plr, Group *grp /* = NULL*/)
  1350. +{
  1351. + uint64 guid = grp ? grp->GetGUID() : plr ? plr->GetGUID() : 0;
  1352. + assert(guid);
  1353. +
  1354. + // Check if player was in a rolecheck
  1355. + if (grp)
  1356. + {
  1357. + LfgRoleCheckMap::iterator itRoleCheck = m_RoleChecks.find(GUID_LOPART(grp->GetGUID()));
  1358. + if (itRoleCheck != m_RoleChecks.end())
  1359. + {
  1360. + UpdateRoleCheck(grp); // No player to update role = LFG_ROLECHECK_ABORTED
  1361. + return;
  1362. + }
  1363. + }
  1364. +
  1365. + // Check if player/group was in the queue
  1366. + bool inQueue = false;
  1367. + for (LFGQueueMap::iterator it = m_Queues.begin(); it != m_Queues.end(); ++it)
  1368. + inQueue |= it->second->RemoveFromQueue(guid);
  1369. +
  1370. + // Not in queue
  1371. + if (!inQueue)
  1372. + return;
  1373. +
  1374. + if (grp)
  1375. + {
  1376. + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
  1377. + if (Player *plrg = itr->getSource())
  1378. + {
  1379. + plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
  1380. + plrg->m_lookingForGroup.applyDungeons.clear();
  1381. + plrg->m_lookingForGroup.roles = 0;
  1382. + }
  1383. + }
  1384. + else
  1385. + {
  1386. + plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
  1387. + plr->m_lookingForGroup.applyDungeons.clear();
  1388. + plr->m_lookingForGroup.roles = 0;
  1389. + }
  1390. +}
  1391. +
  1392. +/// <summary>
  1393. +/// Update the Role check info with the player selected role.
  1394. +/// </summary>
  1395. +/// <param name="grp">Group</param>
  1396. +/// <param name="plr">Player</param>
  1397. +void LFGMgr::UpdateRoleCheck(Group *grp, Player *plr /* = NULL*/)
  1398. +{
  1399. + assert(grp);
  1400. +
  1401. + uint32 rolecheckId = GUID_LOPART(grp->GetGUID());
  1402. + LfgRoleCheck *pRoleCheck = NULL;
  1403. + LfgRolesMap check_roles;
  1404. + LfgRoleCheckMap::iterator itRoleCheck = m_RoleChecks.find(rolecheckId);
  1405. + bool newRoleCheck = itRoleCheck == m_RoleChecks.end();
  1406. + if (newRoleCheck)
  1407. + {
  1408. + if (!grp->IsLeader(plr->GetGUID()))
  1409. + return;
  1410. +
  1411. + pRoleCheck = new LfgRoleCheck();
  1412. + pRoleCheck->cancelTime = time_t(time(NULL)) + LFG_TIME_ROLECHECK;
  1413. + pRoleCheck->result = LFG_ROLECHECK_INITIALITING;
  1414. + pRoleCheck->leader = plr->GetGUID();
  1415. +
  1416. + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
  1417. + if (Player *plrg = itr->getSource())
  1418. + pRoleCheck->roles[plrg->GetGUID()] = 0;
  1419. +
  1420. + pRoleCheck->dungeons = plr->m_lookingForGroup.applyDungeons;
  1421. + }
  1422. + else
  1423. + pRoleCheck = itRoleCheck->second;
  1424. +
  1425. + LfgLockStatusMap *playersLockMap = NULL;
  1426. + if (plr)
  1427. + {
  1428. + // Player selected no role.
  1429. + if (plr->m_lookingForGroup.roles < ROLE_TANK)
  1430. + pRoleCheck->result = LFG_ROLECHECK_NO_ROLE;
  1431. + else
  1432. + {
  1433. + // Check if all players have selected a role
  1434. + pRoleCheck->roles[plr->GetGUID()] = plr->m_lookingForGroup.roles;
  1435. + uint8 size = 0;
  1436. + for (LfgRolesMap::const_iterator itRoles = pRoleCheck->roles.begin(); itRoles != pRoleCheck->roles.end() && itRoles->second != ROLE_NONE; ++itRoles)
  1437. + ++size;
  1438. +
  1439. + if (pRoleCheck->roles.size() == size)
  1440. + {
  1441. + // use temporal var to check roles, CheckGroupRoles modifies the roles
  1442. + for (LfgRolesMap::const_iterator itRoles = pRoleCheck->roles.begin(); itRoles != pRoleCheck->roles.end(); ++itRoles)
  1443. + check_roles[itRoles->first] = itRoles->second;
  1444. +
  1445. + if (!CheckGroupRoles(check_roles)) // Group is not posible
  1446. + pRoleCheck->result = LFG_ROLECHECK_WRONG_ROLES;
  1447. + else
  1448. + {
  1449. + // Check if we can find a dungeon for that group
  1450. + pRoleCheck->result = LFG_ROLECHECK_FINISHED;
  1451. + if (pRoleCheck->dungeons.size() > 1)
  1452. + playersLockMap = GetPartyLockStatusDungeons(plr, &pRoleCheck->dungeons);
  1453. + else
  1454. + {
  1455. + LfgDungeonSet::const_iterator it = pRoleCheck->dungeons.begin();
  1456. + LFGDungeonEntry const *dungeon = sLFGDungeonStore.LookupEntry(*it);
  1457. + if (dungeon && dungeon->type == LFG_TYPE_RANDOM)
  1458. + playersLockMap = GetPartyLockStatusDungeons(plr, m_DungeonsMap[*it]);
  1459. + else
  1460. + playersLockMap = GetPartyLockStatusDungeons(plr, &pRoleCheck->dungeons);
  1461. + }
  1462. + }
  1463. + }
  1464. + }
  1465. + }
  1466. + else
  1467. + pRoleCheck->result = LFG_ROLECHECK_ABORTED;
  1468. +
  1469. + WorldSession *session;
  1470. + WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + pRoleCheck->dungeons.size() * 4 + 1 + pRoleCheck->roles.size() * (8 + 1 + 4 + 1));
  1471. + DEBUG_LOG("SMSG_LFG_ROLE_CHECK_UPDATE");
  1472. + BuildLfgRoleCheck(data, pRoleCheck);
  1473. +
  1474. + Player *plrg = NULL;
  1475. + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
  1476. + {
  1477. + plrg = itr->getSource();
  1478. + if (!plrg)
  1479. + continue;
  1480. +
  1481. + session = plrg->GetSession();
  1482. + if (!newRoleCheck && plr)
  1483. + session->SendLfgRoleChosen(plr->GetGUID(), plr->m_lookingForGroup.roles);
  1484. + session->SendPacket(&data);
  1485. +
  1486. + switch(pRoleCheck->result)
  1487. + {
  1488. + case LFG_ROLECHECK_INITIALITING:
  1489. + continue;
  1490. + case LFG_ROLECHECK_FINISHED:
  1491. + if (!playersLockMap)
  1492. + {
  1493. + session->SendLfgUpdateParty(LFG_UPDATETYPE_ADDED_TO_QUEUE);
  1494. + }
  1495. + else
  1496. + {
  1497. + if (grp->IsLeader(plrg->GetGUID()))
  1498. + {
  1499. + uint32 size = 0;
  1500. + for (LfgLockStatusMap::const_iterator it = playersLockMap->begin(); it != playersLockMap->end(); ++it)
  1501. + size += 8 + 4 + it->second->size() * (4 + 4);
  1502. + WorldPacket data(SMSG_LFG_JOIN_RESULT, 4 + 4 + size);
  1503. + DEBUG_LOG("SMSG_LFG_JOIN_RESULT");
  1504. + data << uint32(LFG_JOIN_PARTY_NOT_MEET_REQS); // Check Result
  1505. + data << uint32(0); // Check Value (always 0 when PartyNotMeetReqs
  1506. + BuildPartyLockDungeonBlock(data, playersLockMap);
  1507. + session->SendPacket(&data);
  1508. + }
  1509. + session->SendLfgUpdateParty(LFG_UPDATETYPE_ROLECHECK_FAILED);
  1510. + plrg->m_lookingForGroup.applyDungeons.clear();
  1511. + plrg->m_lookingForGroup.roles = 0;
  1512. + }
  1513. + break;
  1514. + default:
  1515. + if (grp->IsLeader(plrg->GetGUID()))
  1516. + session->SendLfgJoinResult(LFG_JOIN_FAILED, pRoleCheck->result);
  1517. + session->SendLfgUpdateParty(LFG_UPDATETYPE_ROLECHECK_FAILED);
  1518. + plrg->m_lookingForGroup.applyDungeons.clear();
  1519. + plrg->m_lookingForGroup.roles = 0;
  1520. + break;
  1521. + }
  1522. + }
  1523. +
  1524. + if (pRoleCheck->result == LFG_ROLECHECK_FINISHED)
  1525. + {
  1526. + // Add qroup to queue
  1527. + LfgQueueInfo *pqInfo;
  1528. + uint8 groupType = 0;
  1529. + uint8 tanks = LFG_TANKS_NEEDED;
  1530. + uint8 healers = LFG_HEALERS_NEEDED;
  1531. + uint8 dps = LFG_DPS_NEEDED;
  1532. + for (LfgRolesMap::const_iterator it = check_roles.begin(); it != check_roles.end(); ++it)
  1533. + {
  1534. + if (it->second & ROLE_TANK)
  1535. + --tanks;
  1536. + else if (it->second & ROLE_HEALER)
  1537. + --healers;
  1538. + else
  1539. + --dps;
  1540. + }
  1541. + uint64 guid = grp->GetGUID();
  1542. + m_update = false;
  1543. + for (LfgDungeonSet::const_iterator it = pRoleCheck->dungeons.begin(); it != pRoleCheck->dungeons.end(); ++it)
  1544. + {
  1545. + groupType = GetDungeonGroupType(*it);
  1546. + pqInfo = m_Queues[groupType] ? m_Queues[groupType]->GetQueueInfo(guid) : NULL;
  1547. + // if exist we have already added the player with another dungeon sharing same GroupType
  1548. + if (pqInfo)
  1549. + continue;
  1550. + pqInfo = new LfgQueueInfo();
  1551. + pqInfo->dungeonId = *it;
  1552. + pqInfo->joinTime = time_t(time(NULL));
  1553. + pqInfo->tanks = tanks;
  1554. + pqInfo->healers = healers;
  1555. + pqInfo->dps = dps;
  1556. + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
  1557. + {
  1558. + if (Player *plrg = itr->getSource())
  1559. + pqInfo->roles[plrg->GetGUID()] = plrg->m_lookingForGroup.roles;
  1560. + }
  1561. + if (!m_Queues[groupType])
  1562. + m_Queues[groupType] = new LFGQueue();
  1563. + m_Queues[groupType]->AddToQueue(guid, pqInfo);
  1564. + }
  1565. + m_update = true;
  1566. + }
  1567. +
  1568. + if (pRoleCheck->result != LFG_ROLECHECK_INITIALITING)
  1569. + {
  1570. + delete pRoleCheck;
  1571. + if (!newRoleCheck)
  1572. + m_RoleChecks.erase(itRoleCheck);
  1573. + }
  1574. + else if (newRoleCheck)
  1575. + m_RoleChecks[rolecheckId] = pRoleCheck;
  1576. +}
  1577. +
  1578. +/// <summary>
  1579. +/// Check if a group can be formed with the given group
  1580. +/// </summary>
  1581. +/// <param name="grp">Group</param>
  1582. +/// <returns>bool</returns>
  1583. +bool LFGMgr::CheckGroupRoles(LfgRolesMap &groles)
  1584. +{
  1585. + if (!groles.size())
  1586. + return false;
  1587. +
  1588. + uint8 damage = 0;
  1589. + uint8 tank = 0;
  1590. + uint8 healer = 0;
  1591. + uint64 tguid = 0;
  1592. + uint64 hguid = 0;
  1593. + uint64 dguid = 0;
  1594. + uint64 guid = 0;
  1595. + uint8 role = 0;
  1596. +
  1597. + for (LfgRolesMap::const_iterator it = groles.begin(); it != groles.end(); ++it)
  1598. + {
  1599. + guid = it->first;
  1600. + role = it->second;
  1601. +
  1602. + if (role == ROLE_NONE || role == ROLE_LEADER)
  1603. + return false;
  1604. +
  1605. + if (role & ROLE_TANK)
  1606. + if (!tank)
  1607. + {
  1608. + tguid = guid;
  1609. + ++tank;
  1610. + }
  1611. + else
  1612. + {
  1613. + if (groles[tguid] == ROLE_TANK)
  1614. + tguid = guid;
  1615. + groles[tguid] -= ROLE_TANK;
  1616. + return CheckGroupRoles(groles);
  1617. + }
  1618. +
  1619. + if (role & ROLE_HEALER)
  1620. + if (!healer)
  1621. + {
  1622. + hguid = guid;
  1623. + ++healer;
  1624. + }
  1625. + else
  1626. + {
  1627. + if (groles[hguid] == ROLE_HEALER)
  1628. + hguid = guid;
  1629. + groles[hguid] -= ROLE_HEALER;
  1630. + return CheckGroupRoles(groles);
  1631. + }
  1632. +
  1633. + if (role & ROLE_DAMAGE)
  1634. + if (damage < 3)
  1635. + {
  1636. + if (!damage)
  1637. + dguid = guid;
  1638. + ++damage;
  1639. + }
  1640. + else
  1641. + {
  1642. + if (groles[dguid] == ROLE_DAMAGE)
  1643. + dguid = guid;
  1644. + groles[dguid] -= ROLE_DAMAGE;
  1645. + return CheckGroupRoles(groles);
  1646. + }
  1647. + }
  1648. + return true;
  1649. +}
  1650. +
  1651. +
  1652. +
  1653. +// --------------------------------------------------------------------------//
  1654. +// Packet Functions
  1655. +// --------------------------------------------------------------------------//
  1656. +
  1657. +/// <summary>
  1658. +/// Build lfgRolecheck packet
  1659. +/// </summary>
  1660. +/// <param name="data">WorldPacket</param>
  1661. +/// <param name="plr">Player</param>
  1662. +/// <param name="status">Player status in LFG system</param>
  1663. +void LFGMgr::BuildLfgRoleCheck(WorldPacket &data, LfgRoleCheck *pRoleCheck)
  1664. +{
  1665. + assert(pRoleCheck);
  1666. +
  1667. + Player *plr;
  1668. + uint8 roles;
  1669. +
  1670. + data << uint32(pRoleCheck->result); // Check result
  1671. + data << uint8(pRoleCheck->result == LFG_ROLECHECK_INITIALITING);
  1672. + data << uint8(pRoleCheck->dungeons.size()); // Number of dungeons
  1673. + LFGDungeonEntry const *dungeon;
  1674. + for (LfgDungeonSet::iterator it = pRoleCheck->dungeons.begin(); it != pRoleCheck->dungeons.end(); ++it)
  1675. + {
  1676. + dungeon = sLFGDungeonStore.LookupEntry(*it); // not null - been checked at join time
  1677. + data << uint32(dungeon->Entry()); // Dungeon
  1678. + }
  1679. +
  1680. + data << uint8(pRoleCheck->roles.size()); // Players in group
  1681. + // Leader info MUST be sent 1st :S
  1682. + roles = pRoleCheck->roles[pRoleCheck->leader];
  1683. + data << uint64(pRoleCheck->leader); // Guid
  1684. + data << uint8(roles > 0); // Ready
  1685. + data << uint32(roles); // Roles
  1686. + plr = sObjectMgr.GetPlayer(pRoleCheck->leader);
  1687. + if (plr)
  1688. + data << uint8(plr->getLevel()); // Level
  1689. + else
  1690. + data << uint8(0);
  1691. +
  1692. + for (LfgRolesMap::const_iterator itPlayers = pRoleCheck->roles.begin(); itPlayers != pRoleCheck->roles.end(); ++itPlayers)
  1693. + {
  1694. + if (itPlayers->first == pRoleCheck->leader)
  1695. + continue;
  1696. +
  1697. + roles = itPlayers->second;
  1698. + data << uint64(itPlayers->first); // Guid
  1699. + data << uint8(roles > 0); // Ready
  1700. + data << uint32(roles); // Roles
  1701. + plr = sObjectMgr.GetPlayer(pRoleCheck->leader);
  1702. + if (plr)
  1703. + data << uint8(plr->getLevel()); // Level
  1704. + else
  1705. + data << uint8(0);
  1706. + }
  1707. +}
  1708. +
  1709. +/// <summary>
  1710. +/// Build and Send LFG lock player info and reward
  1711. +/// </summary>
  1712. +/// <param name="plr">Player</param>
  1713. +void LFGMgr::SendLfgPlayerInfo(Player *plr)
  1714. +{
  1715. + uint32 rsize = 0;
  1716. + uint32 lsize = 0;
  1717. + LfgDungeonSet *randomlist = GetRandomDungeons(plr->getLevel(), plr->GetSession()->Expansion());
  1718. + LfgLockStatusSet *lockSet = GetPlayerLockStatusDungeons(plr, m_DungeonsMap[LFG_ALL_DUNGEONS]);
  1719. + if (randomlist)
  1720. + rsize = randomlist->size();
  1721. + if (lockSet)
  1722. + lsize = lockSet->size();
  1723. +
  1724. + DEBUG_LOG("SMSG_LFG_PLAYER_INFO");
  1725. + WorldPacket data(SMSG_LFG_PLAYER_INFO, 1 + rsize * (4 + 1 + 4 + 4 + 4 + 4 + 1 + 4 + 4 + 4) + 4 + lsize * (4 + 4));
  1726. + if (!randomlist)
  1727. + data << uint8(0);
  1728. + else
  1729. + {
  1730. + data << uint8(randomlist->size()); // Random Dungeon count
  1731. + for (LfgDungeonSet::iterator it = randomlist->begin(); it != randomlist->end(); ++it)
  1732. + {
  1733. + data << uint32(*it); // Entry
  1734. + BuildRewardBlock(data, *it, plr);
  1735. + }
  1736. + randomlist->clear();
  1737. + delete randomlist;
  1738. + }
  1739. + BuildPlayerLockDungeonBlock(data, lockSet);
  1740. + plr->GetSession()->SendPacket(&data);
  1741. +}
  1742. +
  1743. +/// <summary>
  1744. +/// Build and Send LFG lock party info and reward
  1745. +/// </summary>
  1746. +/// <param name="plr">Player</param>
  1747. +void LFGMgr::SendLfgPartyInfo(Player *plr)
  1748. +{
  1749. + if (LfgLockStatusMap *lockMap = GetPartyLockStatusDungeons(plr, m_DungeonsMap[LFG_ALL_DUNGEONS]))
  1750. + {
  1751. + uint32 size = 0;
  1752. + for (LfgLockStatusMap::const_iterator it = lockMap->begin(); it != lockMap->end(); ++it)
  1753. + size += 8 + 4 + it->second->size() * (4 + 4);
  1754. + DEBUG_LOG("SMSG_LFG_PARTY_INFO");
  1755. + WorldPacket data(SMSG_LFG_PARTY_INFO, 1 + size);
  1756. + BuildPartyLockDungeonBlock(data, lockMap);
  1757. + plr->GetSession()->SendPacket(&data);
  1758. + }
  1759. +}
  1760. +
  1761. +/// <summary>
  1762. +/// Build Reward packet structure for a given dungeon
  1763. +/// </summary>
  1764. +/// <param name="data">WorldPacket</param>
  1765. +/// <param name="dungeon">Dungeon entry</param>
  1766. +/// <param name="plr">Player</param>
  1767. +void LFGMgr::BuildRewardBlock(WorldPacket &data, uint32 dungeon, Player *plr)
  1768. +{
  1769. + bool done = plr->m_lookingForGroup.isDungeonDone(dungeon);
  1770. + LfgReward *reward = GetRandomDungeonReward(dungeon, done, plr->getLevel());
  1771. +
  1772. + if (!reward)
  1773. + return;
  1774. +
  1775. + data << uint8(done);
  1776. + if (data.GetOpcode() == SMSG_LFG_PLAYER_REWARD)
  1777. + data << uint32(reward->strangers);
  1778. + data << uint32(reward->baseMoney);
  1779. + data << uint32(reward->baseXP);
  1780. + data << uint32(reward->variableMoney);
  1781. + data << uint32(reward->variableXP);
  1782. + data << uint8(reward->itemId != 0);
  1783. + if (reward->itemId)
  1784. + {
  1785. + data << uint32(reward->itemId);
  1786. + data << uint32(reward->displayId);
  1787. + data << uint32(reward->stackCount);
  1788. + }
  1789. +}
  1790. +
  1791. +/// <summary>
  1792. +/// Build Party Dungeon lock status packet
  1793. +/// </summary>
  1794. +/// <param name="data">WorldPacket</param>
  1795. +/// <param name="lock">lock status map</param>
  1796. +void LFGMgr::BuildPartyLockDungeonBlock(WorldPacket &data, LfgLockStatusMap *lockMap)
  1797. +{
  1798. + assert(lockMap);
  1799. +
  1800. + data << uint8(lockMap->size());
  1801. +
  1802. + LfgLockStatusSet *lockSet;
  1803. + uint64 guid;
  1804. + for (LfgLockStatusMap::const_iterator it = lockMap->begin(); it != lockMap->end(); ++it)
  1805. + {
  1806. + guid = it->first;
  1807. + lockSet = it->second;
  1808. + if (!lockSet)
  1809. + continue;
  1810. +
  1811. + data << uint64(guid); // Player guid
  1812. + BuildPlayerLockDungeonBlock(data, lockSet);
  1813. + }
  1814. + lockMap->clear();
  1815. + delete lockMap;
  1816. +}
  1817. +
  1818. +/// <summary>
  1819. +/// Build Player Dungeon lock status packet
  1820. +/// </summary>
  1821. +/// <param name="data">WorldPacket</param>
  1822. +/// <param name="lock">lock status list</param>
  1823. +void LFGMgr::BuildPlayerLockDungeonBlock(WorldPacket &data, LfgLockStatusSet *lockSet)
  1824. +{
  1825. + assert(lockSet);
  1826. + data << uint32(lockSet->size()); // Size of lock dungeons
  1827. + for (LfgLockStatusSet::iterator it = lockSet->begin(); it != lockSet->end(); ++it)
  1828. + {
  1829. + data << uint32((*it)->dungeon); // Dungeon entry + type
  1830. + data << uint32((*it)->lockstatus); // Lock status
  1831. + delete (*it);
  1832. + }
  1833. + lockSet->clear();
  1834. + delete lockSet;
  1835. +}
  1836. +
  1837. +
  1838. +
  1839. +
  1840. +// --------------------------------------------------------------------------//
  1841. +// Auxiliar Functions
  1842. +// --------------------------------------------------------------------------//
  1843. +
  1844. +/// <summary>
  1845. +/// Get all Group members list of dungeons that can't be done and reason
  1846. +/// leader excluded as the list given is he list he can do
  1847. +/// </summary>
  1848. +/// <param name="grp">Group</param>
  1849. +/// <param name="dungeons">Dungeons to check</param>
  1850. +/// <returns>LfgLockStatusMap*</returns>
  1851. +LfgLockStatusMap* LFGMgr::GetPartyLockStatusDungeons(Player *plr, LfgDungeonSet *dungeons)
  1852. +{
  1853. + assert(plr);
  1854. + assert(dungeons);
  1855. + Group *grp = plr->GetGroup();
  1856. + if (!grp)
  1857. + return NULL;
  1858. +
  1859. + Player *plrg;
  1860. + LfgLockStatusSet *dungeonSet = NULL;
  1861. + LfgLockStatusMap *dungeonMap = new LfgLockStatusMap();
  1862. + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
  1863. + {
  1864. + plrg = itr->getSource();
  1865. + if (!plrg || plrg == plr)
  1866. + continue;
  1867. +
  1868. + dungeonSet = GetPlayerLockStatusDungeons(plrg, dungeons);
  1869. + if (dungeonSet)
  1870. + (*dungeonMap)[plrg->GetGUID()] = dungeonSet;
  1871. + }
  1872. +
  1873. + if (!dungeonMap->size())
  1874. + {
  1875. + delete dungeonMap;
  1876. + dungeonMap = NULL;
  1877. + }
  1878. + return dungeonMap;
  1879. +}
  1880. +
  1881. +/// <summary>
  1882. +/// Get list of dungeons player can't do and reasons
  1883. +/// </summary>
  1884. +/// <param name="plr">Player</param>
  1885. +/// <param name="dungeons">Dungeons to check</param>
  1886. +/// <returns>LfgLockStatusSet*</returns>
  1887. +LfgLockStatusSet* LFGMgr::GetPlayerLockStatusDungeons(Player *plr, LfgDungeonSet *dungeons)
  1888. +{
  1889. + LfgLockStatusSet *list = new LfgLockStatusSet();
  1890. + LfgLockStatus *lockstatus = NULL;
  1891. + LFGDungeonEntry const *dungeon;
  1892. + LfgLockStatusType locktype;
  1893. + uint8 level = plr->getLevel();
  1894. + uint8 expansion = plr->GetSession()->Expansion();
  1895. +
  1896. + for (LfgDungeonSet::const_iterator it = dungeons->begin(); it != dungeons->end(); ++it)
  1897. + {
  1898. + dungeon = sLFGDungeonStore.LookupEntry(*it);
  1899. + assert(dungeon); // Will never happen - We provide a list from sLFGDungeonStore
  1900. +
  1901. + locktype = LFG_LOCKSTATUS_OK;
  1902. + if (dungeon->expansion > expansion)
  1903. + locktype = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION;
  1904. + else if (dungeon->minlevel > level)
  1905. + locktype = LFG_LOCKSTATUS_TOO_LOW_LEVEL;
  1906. + else if (dungeon->maxlevel < level)
  1907. + locktype = LFG_LOCKSTATUS_TOO_HIGH_LEVEL;
  1908. + /* TODO - Use these types when needed...
  1909. + else if ()
  1910. + locktype = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE;
  1911. + else if ()
  1912. + locktype = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE;
  1913. + else if () // Locked due to WG, closed by GM, done daily, etc
  1914. + locktype = LFG_LOCKSTATUS_RAID_LOCKED;
  1915. + else if ()
  1916. + locktype = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL;
  1917. + else if ()
  1918. + locktype = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL;
  1919. + else if () // Need list of instances and needed quest to enter
  1920. + locktype = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED;
  1921. + else if () // Need list of instances and needed key to enter
  1922. + locktype = LFG_LOCKSTATUS_MISSING_ITEM;
  1923. + else if () // Need list of instances and needed season to open
  1924. + locktype = LFG_LOCKSTATUS_NOT_IN_SEASON;
  1925. + */
  1926. +
  1927. + if (locktype != LFG_LOCKSTATUS_OK)
  1928. + {
  1929. + lockstatus = new LfgLockStatus();
  1930. + lockstatus->dungeon = dungeon->Entry();
  1931. + lockstatus->lockstatus = locktype;
  1932. + list->insert(lockstatus);
  1933. + }
  1934. + }
  1935. + if (!list->size())
  1936. + {
  1937. + delete list;
  1938. + list = NULL;
  1939. + }
  1940. + return list;
  1941. +}
  1942. +
  1943. +/// <summary>
  1944. +/// Get the dungeon list that can be done.
  1945. +/// </summary>
  1946. +/// <returns>LfgDungeonSet*</returns>
  1947. +LfgDungeonSet* LFGMgr::GetAllDungeons()
  1948. +{
  1949. + LfgDungeonSet *dungeons = new LfgDungeonSet();
  1950. + LFGDungeonEntry const *dungeon;
  1951. + for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i)
  1952. + {
  1953. + dungeon = sLFGDungeonStore.LookupEntry(i);
  1954. + if (!dungeon || dungeon->type == LFG_TYPE_ZONE)
  1955. + continue;
  1956. + dungeons->insert(dungeon->ID);
  1957. + }
  1958. + if (!dungeons->size())
  1959. + {
  1960. + delete dungeons;
  1961. + return NULL;
  1962. + }
  1963. + else
  1964. + return dungeons;
  1965. +}
  1966. +
  1967. +/// <summary>
  1968. +/// Get the dungeon list that can be done given a random dungeon entry.
  1969. +/// </summary>
  1970. +/// <param name="randomdungeon">Random dungeon entry</param>
  1971. +/// <returns>LfgDungeonSet*</returns>
  1972. +LfgDungeonSet* LFGMgr::GetDungeonsByRandom(uint32 randomdungeon)
  1973. +{
  1974. + LFGDungeonEntry const *dungeon = sLFGDungeonStore.LookupEntry(randomdungeon);
  1975. + if (!dungeon)
  1976. + return NULL;
  1977. +
  1978. + uint32 grouptype = dungeon->grouptype;
  1979. + LfgDungeonSet *random = new LfgDungeonSet();
  1980. + for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i)
  1981. + {
  1982. + dungeon = sLFGDungeonStore.LookupEntry(i);
  1983. + if (!dungeon || dungeon->type == LFG_TYPE_RANDOM || dungeon->grouptype != grouptype)
  1984. + continue;
  1985. + random->insert(dungeon->ID);
  1986. + }
  1987. + if (!random->size())
  1988. + {
  1989. + delete random;
  1990. + return NULL;
  1991. + }
  1992. + else
  1993. + return random;
  1994. +}
  1995. +
  1996. +/// <summary>
  1997. +/// Get the random dungeon list that can be done at a certain level and expansion.
  1998. +/// </summary>
  1999. +/// <param name="level">Player level</param>
  2000. +/// <param name="expansion">Player account expansion</param>
  2001. +/// <returns>LfgDungeonSet*</returns>
  2002. +LfgDungeonSet* LFGMgr::GetRandomDungeons(uint8 level, uint8 expansion)
  2003. +{
  2004. + LfgDungeonSet *list = new LfgDungeonSet();
  2005. + LFGDungeonEntry const *dungeon;
  2006. + for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i)
  2007. + {
  2008. + dungeon = sLFGDungeonStore.LookupEntry(i);
  2009. + if (dungeon && dungeon->expansion <= expansion && dungeon->type == LFG_TYPE_RANDOM &&
  2010. + dungeon->minlevel <= level && level <= dungeon->maxlevel)
  2011. + list->insert(dungeon->Entry());
  2012. + }
  2013. + return list;
  2014. +}
  2015. +
  2016. +/// <summary>
  2017. +/// Get the reward of a given random dungeon
  2018. +/// </summary>
  2019. +/// <param name="dungeon">random dungeon id</param>
  2020. +/// <param name="done">Dungeon previously done</param>
  2021. +/// <returns></returns>
  2022. +LfgReward* LFGMgr::GetRandomDungeonReward(uint32 dungeon, bool done, uint8 level)
  2023. +{
  2024. + uint8 index = 0;
  2025. + switch((dungeon & 0x00FFFFFF)) // Get dungeon id from dungeon entry
  2026. + {
  2027. + case LFG_RANDOM_CLASSIC:
  2028. + if (level < 15)
  2029. + index = LFG_REWARD_LEVEL0;
  2030. + else if (level < 24)
  2031. + index = LFG_REWARD_LEVEL1;
  2032. + else if (level < 35)
  2033. + index = LFG_REWARD_LEVEL2;
  2034. + else if (level < 46)
  2035. + index = LFG_REWARD_LEVEL3;
  2036. + else if (level < 56)
  2037. + index = LFG_REWARD_LEVEL4;
  2038. + else
  2039. + index = LFG_REWARD_LEVEL5;
  2040. + break;
  2041. + case LFG_RANDOM_BC_NORMAL:
  2042. + index = LFG_REWARD_BC_NORMAL;
  2043. + break;
  2044. + case LFG_RANDOM_BC_HEROIC:
  2045. + index = LFG_REWARD_BC_HEROIC;
  2046. + break;
  2047. + case LFG_RANDOM_LK_NORMAL:
  2048. + index = level == 80 ? LFG_REWARD_LK_NORMAL80 : LFG_REWARD_LK_NORMAL;
  2049. + break;
  2050. + case LFG_RANDOM_LK_HEROIC:
  2051. + index = LFG_REWARD_LK_HEROIC;
  2052. + break;
  2053. + default: // This should never happen!
  2054. + done = false;
  2055. + index = LFG_REWARD_LEVEL0;
  2056. + sLog.outError("LFGMgr::GetRandomDungeonReward: Dungeon %u is not random dungeon!", dungeon);
  2057. + break;
  2058. + }
  2059. + return done ? m_RewardDoneList.at(index) : m_RewardList.at(index);
  2060. +}
  2061. +
  2062. +/// <summary>
  2063. +/// Given a Dungeon id returns the dungeon Group Type
  2064. +/// </summary>
  2065. +/// <param name="dungeonId">Dungeon id</param>
  2066. +/// <returns>uint8: GroupType</returns>
  2067. +uint8 LFGMgr::GetDungeonGroupType(uint32 dungeonId)
  2068. +{
  2069. + LFGDungeonEntry const *dungeon = sLFGDungeonStore.LookupEntry(dungeonId);
  2070. + if (!dungeon)
  2071. + return 0;
  2072. +
  2073. + return dungeon->grouptype;
  2074. +}
  2075. diff --git a/src/game/LFGMgr.h b/src/game/LFGMgr.h
  2076. new file mode 100644
  2077. index 0000000..cddc74f
  2078. --- /dev/null
  2079. +++ b/src/game/LFGMgr.h
  2080. @@ -0,0 +1,261 @@
  2081. +#ifndef _LFGMGR_H
  2082. +#define _LFGMGR_H
  2083. +
  2084. +#include "Common.h"
  2085. +#include "Policies/Singleton.h"
  2086. +#include "Group.h"
  2087. +#include "LFG.h"
  2088. +
  2089. +enum LFGenum
  2090. +{
  2091. + LFG_TIME_ROLECHECK = 2*MINUTE,
  2092. + LFG_TANKS_NEEDED = 1,
  2093. + LFG_HEALERS_NEEDED = 1,
  2094. + LFG_DPS_NEEDED = 3,
  2095. + LFG_QUEUEUPDATE_INTERVAL = 15000,
  2096. + LFG_SPELL_COOLDOWN = 71328,
  2097. + LFG_SPELL_DESERTER = 71041,
  2098. +};
  2099. +
  2100. +enum LfgType
  2101. +{
  2102. + LFG_TYPE_DUNGEON = 1,
  2103. + LFG_TYPE_RAID = 2,
  2104. + LFG_TYPE_QUEST = 3,
  2105. + LFG_TYPE_ZONE = 4,
  2106. + LFG_TYPE_HEROIC = 5,
  2107. + LFG_TYPE_RANDOM = 6,
  2108. +};
  2109. +
  2110. +enum LfgGroupType
  2111. +{
  2112. + LFG_GROUPTYPE_CLASSIC = 1,
  2113. + LFG_GROUPTYPE_BC_NORMAL = 2,
  2114. + LFG_GROUPTYPE_BC_HEROIC = 3,
  2115. + LFG_GROUPTYPE_WTLK_NORMAL = 4,
  2116. + LFG_GROUPTYPE_WTLK_HEROIC = 5,
  2117. + LFG_GROUPTYPE_CLASSIC_RAID = 6,
  2118. + LFG_GROUPTYPE_BC_RAID = 7,
  2119. + LFG_GROUPTYPE_WTLK_RAID_10 = 8,
  2120. + LFG_GROUPTYPE_WTLK_RAID_25 = 9,
  2121. +};
  2122. +
  2123. +enum LfgLockStatusType
  2124. +{
  2125. + LFG_LOCKSTATUS_OK = 0, // Internal use only
  2126. + LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION = 1,
  2127. + LFG_LOCKSTATUS_TOO_LOW_LEVEL = 2,
  2128. + LFG_LOCKSTATUS_TOO_HIGH_LEVEL = 3,
  2129. + LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE = 4,
  2130. + LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE = 5,
  2131. + LFG_LOCKSTATUS_RAID_LOCKED = 6,
  2132. + LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL = 1001,
  2133. + LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL = 1002,
  2134. + LFG_LOCKSTATUS_QUEST_NOT_COMPLETED = 1022,
  2135. + LFG_LOCKSTATUS_MISSING_ITEM = 1025,
  2136. + LFG_LOCKSTATUS_NOT_IN_SEASON = 1031,
  2137. +};
  2138. +
  2139. +enum LfgJoinResult
  2140. +{
  2141. + LFG_JOIN_OK = 0, // Joined (no client msg)
  2142. + LFG_JOIN_FAILED = 1, // RoleCheck Failed
  2143. + LFG_JOIN_GROUPFULL = 2, // Your group is full
  2144. + LFG_JOIN_UNK3 = 3, // No client reaction
  2145. + LFG_JOIN_INTERNAL_ERROR = 4, // Internal LFG Error
  2146. + LFG_JOIN_NOT_MEET_REQS = 5, // You do not meet the requirements for the chosen dungeons
  2147. + LFG_JOIN_PARTY_NOT_MEET_REQS = 6, // One or more party members do not meet the requirements for the chosen dungeons
  2148. + LFG_JOIN_MIXED_RAID_DUNGEON = 7, // You cannot mix dungeons, raids, and random when picking dungeons
  2149. + LFG_JOIN_MULTI_REALM = 8, // The dungeon you chose does not support players from multiple realms
  2150. + LFG_JOIN_DISCONNECTED = 9, // One or more party members are pending invites or disconnected
  2151. + LFG_JOIN_PARTY_INFO_FAILED = 10, // Could not retrieve information about some party members
  2152. + LFG_JOIN_DUNGEON_INVALID = 11, // One or more dungeons was not valid
  2153. + LFG_JOIN_DESERTER = 12, // You can not queue for dungeons until your deserter debuff wears off
  2154. + LFG_JOIN_PARTY_DESERTER = 13, // One or more party members has a deserter debuff
  2155. + LFG_JOIN_RANDOM_COOLDOWN = 14, // You can not queue for random dungeons while on random dungeon cooldown
  2156. + LFG_JOIN_PARTY_RANDOM_COOLDOWN = 15, // One or more party members are on random dungeon cooldown
  2157. + LFG_JOIN_TOO_MUCH_MEMBERS = 16, // You can not enter dungeons with more that 5 party members
  2158. + LFG_JOIN_USING_BG_SYSTEM = 17, // You can not use the dungeon system while in BG or arenas
  2159. + LFG_JOIN_FAILED2 = 18, // RoleCheck Failed
  2160. +};
  2161. +
  2162. +enum LfgRoleCheckResult
  2163. +{
  2164. + LFG_ROLECHECK_FINISHED = 1, // Role check finished
  2165. + LFG_ROLECHECK_INITIALITING = 2, // Role check begins
  2166. + LFG_ROLECHECK_MISSING_ROLE = 3, // Someone didn't selected a role after 2 mins
  2167. + LFG_ROLECHECK_WRONG_ROLES = 4, // Can't form a group with that role selection
  2168. + LFG_ROLECHECK_ABORTED = 5, // Someone leave the group
  2169. + LFG_ROLECHECK_NO_ROLE = 6, // Someone selected no role
  2170. +};
  2171. +
  2172. +enum LfgRandomDungeonEntries
  2173. +{
  2174. + LFG_ALL_DUNGEONS = 0,
  2175. + LFG_RANDOM_CLASSIC = 258,
  2176. + LFG_RANDOM_BC_NORMAL = 259,
  2177. + LFG_RANDOM_BC_HEROIC = 260,
  2178. + LFG_RANDOM_LK_NORMAL = 261,
  2179. + LFG_RANDOM_LK_HEROIC = 262,
  2180. +};
  2181. +
  2182. +enum LfgRewardEnums
  2183. +{
  2184. + LFG_REWARD_LEVEL0 = 10,
  2185. + LFG_REWARD_LEVEL1 = 0,
  2186. + LFG_REWARD_LEVEL2 = 1,
  2187. + LFG_REWARD_LEVEL3 = 2,
  2188. + LFG_REWARD_LEVEL4 = 3,
  2189. + LFG_REWARD_LEVEL5 = 4,
  2190. + LFG_REWARD_BC_NORMAL = 5,
  2191. + LFG_REWARD_BC_HEROIC = 6,
  2192. + LFG_REWARD_LK_NORMAL = 7,
  2193. + LFG_REWARD_LK_NORMAL80 = 7,
  2194. + LFG_REWARD_LK_HEROIC = 8,
  2195. + LFG_REWARD_DATA_SIZE = 10,
  2196. +};
  2197. +
  2198. +const uint32 RewardDungeonData[LFG_REWARD_DATA_SIZE+1][5] =
  2199. +{ // XP, money, item, item display, count
  2200. + {310, 3500, 51999, 56915, 1}, // Classic 15-23
  2201. + {470, 7000, 52000, 56915, 1}, // Classic 24-34
  2202. + {825, 13000, 52001, 56915, 1}, // Classic 35-45
  2203. + {12250, 16500, 52002, 56915, 1}, // Classic 46-55
  2204. + {14300, 18000, 52003, 56915, 1}, // Classic 56-60
  2205. + {1600, 62000, 52004, 56915, 1}, // BC Normal
  2206. + {1900, 88000, 52005, 56915, 1}, // BC Heroic
  2207. + {33100, 148000, 47241, 62232, 2}, // LK Normal
  2208. + {0, 198600, 47241, 62232, 2}, // LK Normal - Level 80
  2209. + {0, 264600, 49426, 64062, 2}, // LK Heroic
  2210. + {0, 0, 0, 0, 0}, // Classic - No level
  2211. +};
  2212. +
  2213. +const uint32 RewardDungeonDoneData[LFG_REWARD_DATA_SIZE][5] =
  2214. +{ // XP, money, item, item display, count
  2215. + {200, 1800, 51999, 56915, 1}, // Classic 15-23
  2216. + {310, 3500, 52000, 56915, 1}, // Classic 24-34
  2217. + {550, 6500, 52001, 56915, 1}, // Classic 35-45
  2218. + {8150, 8500, 52002, 56915, 1}, // Classic 46-55
  2219. + {9550, 9000, 52003, 56915, 1}, // Classic 56-60
  2220. + {1100, 31000, 52004, 56915, 1}, // BC Normal
  2221. + {12650, 44000, 52005, 56915, 1}, // BC Heroic
  2222. + {16550, 74000, 0, 0, 0}, // LK Normal
  2223. + {0, 99300, 0, 0, 0}, // LK Normal - Level 80
  2224. + {0, 132300, 47241, 62232, 2}, // LK Heroic
  2225. +};
  2226. +
  2227. +// Dungeon and reason why player can't join
  2228. +struct LfgLockStatus
  2229. +{
  2230. + uint32 dungeon;
  2231. + LfgLockStatusType lockstatus;
  2232. +};
  2233. +
  2234. +// Reward info
  2235. +struct LfgReward
  2236. +{
  2237. + uint32 strangers;
  2238. + uint32 baseMoney;
  2239. + uint32 baseXP;
  2240. + uint32 variableMoney;
  2241. + uint32 variableXP;
  2242. + uint32 itemId;
  2243. + uint32 displayId;
  2244. + uint32 stackCount;
  2245. +};
  2246. +
  2247. +typedef std::set<LfgLockStatus*> LfgLockStatusSet;
  2248. +typedef std::vector<LfgReward*> LfgRewardList;
  2249. +typedef std::map<uint64, LfgLockStatusSet*> LfgLockStatusMap;
  2250. +typedef std::map<uint32, LfgDungeonSet*> LfgDungeonMap;
  2251. +
  2252. +typedef std::map<uint64, int8> LfgAnswerMap;
  2253. +typedef std::map<uint64, uint8> LfgRolesMap;
  2254. +typedef std::set<uint64> LfgGuidSet;
  2255. +
  2256. +// Stores player or group queue info
  2257. +struct LfgQueueInfo
  2258. +{
  2259. + time_t joinTime; // Player queue join time (to calculate wait times)
  2260. + uint32 dungeonId; // Selected Player/Group Dungeon
  2261. + LfgRolesMap roles; // Selected Player Role/s
  2262. + uint8 tanks; // Tanks needed
  2263. + uint8 healers; // Healers needed
  2264. + uint8 dps; // Dps needed
  2265. +};
  2266. +
  2267. +// Stores all rolecheck info of a group that wants to join LFG
  2268. +struct LfgRoleCheck
  2269. +{
  2270. + time_t cancelTime;
  2271. + LfgRolesMap roles;
  2272. + LfgRoleCheckResult result;
  2273. + LfgDungeonSet dungeons;
  2274. + uint64 leader;
  2275. +};
  2276. +
  2277. +typedef std::map<uint64, LfgQueueInfo*> LfgQueueInfoMap;
  2278. +typedef std::map<uint32, LfgRoleCheck*> LfgRoleCheckMap;
  2279. +
  2280. +class LFGQueue
  2281. +{
  2282. + public:
  2283. + LFGQueue();
  2284. + ~LFGQueue();
  2285. +
  2286. + void Update();
  2287. + void AddToQueue(uint64 guid, LfgQueueInfo *pqInfo);
  2288. + bool RemoveFromQueue(uint64 guid);
  2289. + LfgQueueInfo* GetQueueInfo(uint64 guid);
  2290. + private:
  2291. + LfgQueueInfoMap m_LfgQueue;
  2292. + int32 avgWaitTime;
  2293. + int32 waitTimeTanks;
  2294. + int32 waitTimeHealer;
  2295. + int32 waitTimeDps;
  2296. +};
  2297. +
  2298. +typedef std::map<uint8, LFGQueue *> LFGQueueMap;
  2299. +
  2300. +class LFGMgr
  2301. +{
  2302. +public:
  2303. + LFGMgr();
  2304. + ~LFGMgr();
  2305. +
  2306. + void InitLFG();
  2307. + void SendLfgPlayerInfo(Player *plr);
  2308. + void SendLfgPartyInfo(Player *plr);
  2309. + void Join(Player *plr);
  2310. + void Leave(Player *plr, Group *grp = NULL);
  2311. + void UpdateRoleCheck(Group *grp, Player *plr = NULL);
  2312. + void Update(uint32 diff);
  2313. +
  2314. +private:
  2315. + void BuildLfgRoleCheck(WorldPacket &data, LfgRoleCheck *pRoleCheck);
  2316. + void BuildAvailableRandomDungeonList(WorldPacket &data, Player *plr);
  2317. + void BuildRewardBlock(WorldPacket &data, uint32 dungeon, Player *plr);
  2318. + void BuildPlayerLockDungeonBlock(WorldPacket &data, LfgLockStatusSet *lockSet);
  2319. + void BuildPartyLockDungeonBlock(WorldPacket &data, LfgLockStatusMap *lockMap);
  2320. + bool CheckGroupRoles(LfgRolesMap &groles);
  2321. +
  2322. + LfgLockStatusMap* GetPartyLockStatusDungeons(Player *plr, LfgDungeonSet *dungeons);
  2323. + LfgLockStatusSet* GetPlayerLockStatusDungeons(Player *plr, LfgDungeonSet *dungeons);
  2324. + LfgDungeonSet* GetRandomDungeons(uint8 level, uint8 expansion);
  2325. + LfgDungeonSet* GetDungeonsByRandom(uint32 randomdungeon);
  2326. + LfgDungeonSet* GetAllDungeons();
  2327. + LfgReward* GetRandomDungeonReward(uint32 dungeon, bool done, uint8 level);
  2328. + uint8 GetDungeonGroupType(uint32 dungeon);
  2329. +
  2330. + LfgRewardList m_RewardList;
  2331. + LfgRewardList m_RewardDoneList;
  2332. + LfgDungeonMap m_DungeonsMap;
  2333. +
  2334. + LFGQueueMap m_Queues;
  2335. + LfgRoleCheckMap m_RoleChecks;
  2336. + uint32 m_QueueTimer;
  2337. + bool m_update;
  2338. +};
  2339. +
  2340. +#define sLFGMgr MaNGOS::Singleton<LFGMgr>::Instance()
  2341. +#endif
  2342. diff --git a/src/game/Makefile.am b/src/game/Makefile.am
  2343. index 575b4c0..cb2a398 100644
  2344. --- a/src/game/Makefile.am
  2345. +++ b/src/game/Makefile.am
  2346. @@ -170,7 +170,10 @@ libmangosgame_a_SOURCES =
  2347. Level1.cpp
  2348. Level2.cpp
  2349. Level3.cpp
  2350. + LFG.h
  2351. LFGHandler.cpp
  2352. + LFGMgr.cpp
  2353. + LFGMgr.h
  2354. LootHandler.cpp
  2355. LootMgr.cpp
  2356. LootMgr.h
  2357. diff --git a/src/game/ObjectGuid.cpp b/src/game/ObjectGuid.cpp
  2358. index b8a41f0..f0aceaf 100644
  2359. --- a/src/game/ObjectGuid.cpp
  2360. +++ b/src/game/ObjectGuid.cpp
  2361. @@ -37,6 +37,7 @@ char const* ObjectGuid::GetTypeName(HighGuid high)
  2362. case HIGHGUID_DYNAMICOBJECT:return "DynObject";
  2363. case HIGHGUID_CORPSE: return "Corpse";
  2364. case HIGHGUID_MO_TRANSPORT: return "MoTransport";
  2365. + case HIGHGUID_GROUP: return "Group";
  2366. default:
  2367. return "<unknown>";
  2368. }
  2369. @@ -105,3 +106,4 @@ template uint32 ObjectGuidGenerator<HIGHGUID_PET>::Generate();
  2370. template uint32 ObjectGuidGenerator<HIGHGUID_VEHICLE>::Generate();
  2371. template uint32 ObjectGuidGenerator<HIGHGUID_DYNAMICOBJECT>::Generate();
  2372. template uint32 ObjectGuidGenerator<HIGHGUID_CORPSE>::Generate();
  2373. +template uint32 ObjectGuidGenerator<HIGHGUID_GROUP>::Generate();
  2374. diff --git a/src/game/ObjectGuid.h b/src/game/ObjectGuid.h
  2375. index 777e753..a07ef80 100644
  2376. --- a/src/game/ObjectGuid.h
  2377. +++ b/src/game/ObjectGuid.h
  2378. @@ -70,6 +70,7 @@ enum HighGuid
  2379. HIGHGUID_DYNAMICOBJECT = 0xF100, // blizz F100/F500
  2380. HIGHGUID_CORPSE = 0xF500, // blizz F100/F500 used second variant to resolve conflict with HIGHGUID_DYNAMICOBJECT
  2381. HIGHGUID_MO_TRANSPORT = 0x1FC0, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT)
  2382. + HIGHGUID_GROUP = 0x1F50,
  2383. };
  2384.  
  2385. //*** Must be replaced by ObjectGuid use ***
  2386. @@ -95,6 +96,7 @@ inline bool IsGuidHaveEnPart(uint64 const& guid)
  2387. case HIGHGUID_DYNAMICOBJECT:
  2388. case HIGHGUID_CORPSE:
  2389. case HIGHGUID_MO_TRANSPORT:
  2390. + case HIGHGUID_GROUP:
  2391. return false;
  2392. case HIGHGUID_GAMEOBJECT:
  2393. case HIGHGUID_TRANSPORT:
  2394. @@ -170,6 +172,7 @@ class MANGOS_DLL_SPEC ObjectGuid
  2395. bool IsCorpse() const { return GetHigh() == HIGHGUID_CORPSE; }
  2396. bool IsTransport() const { return GetHigh() == HIGHGUID_TRANSPORT; }
  2397. bool IsMOTransport() const { return GetHigh() == HIGHGUID_MO_TRANSPORT; }
  2398. + bool IsGroup() const { return GetHigh() == HIGHGUID_GROUP; }
  2399.  
  2400. static TypeID GetTypeId(HighGuid high)
  2401. {
  2402. @@ -211,6 +214,7 @@ class MANGOS_DLL_SPEC ObjectGuid
  2403. case HIGHGUID_DYNAMICOBJECT:
  2404. case HIGHGUID_CORPSE:
  2405. case HIGHGUID_MO_TRANSPORT:
  2406. + case HIGHGUID_GROUP:
  2407. return false;
  2408. case HIGHGUID_GAMEOBJECT:
  2409. case HIGHGUID_TRANSPORT:
  2410. diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
  2411. index 9874aec..3251b5f 100644
  2412. --- a/src/game/ObjectMgr.cpp
  2413. +++ b/src/game/ObjectMgr.cpp
  2414. @@ -5835,6 +5835,8 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh)
  2415. return m_GameobjectGuids.Generate();
  2416. case HIGHGUID_CORPSE:
  2417. return m_CorpseGuids.Generate();
  2418. + case HIGHGUID_GROUP:
  2419. + return m_GroupIds.Generate();
  2420. default:
  2421. ASSERT(0);
  2422. }
  2423. diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp
  2424. index 6c26ded..e2c12e8 100644
  2425. --- a/src/game/Opcodes.cpp
  2426. +++ b/src/game/Opcodes.cpp
  2427. @@ -537,8 +537,8 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
  2428. /*0x1FC*/ { "SMSG_ENVIRONMENTALDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2429. /*0x1FD*/ { "CMSG_PLAYER_DIFFICULTY_CHANGE", STATUS_NEVER, &WorldSession::Handle_NULL },
  2430. /*0x1FE*/ { "SMSG_RWHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2431. - /*0x1FF*/ { "SMSG_LFG_PLAYER_REWARD", STATUS_LOGGEDIN, &WorldSession::Handle_ServerSide },
  2432. - /*0x200*/ { "SMSG_LFG_TELEPORT_DENIED", STATUS_LOGGEDIN, &WorldSession::Handle_ServerSide },
  2433. + /*0x1FF*/ { "SMSG_LFG_PLAYER_REWARD", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2434. + /*0x200*/ { "SMSG_LFG_TELEPORT_DENIED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2435. /*0x201*/ { "CMSG_UNLEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL },
  2436. /*0x202*/ { "CMSG_UNLEARN_SKILL", STATUS_LOGGEDIN, &WorldSession::HandleUnlearnSkillOpcode },
  2437. /*0x203*/ { "SMSG_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2438. @@ -888,8 +888,8 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
  2439. /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2440. /*0x35C*/ { "CMSG_LFG_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleLfgJoinOpcode },
  2441. /*0x35D*/ { "CMSG_LFG_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleLfgLeaveOpcode },
  2442. - /*0x35E*/ { "CMSG_SEARCH_LFG_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleSearchLfgJoinOpcode },
  2443. - /*0x35F*/ { "CMSG_SEARCH_LFG_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleSearchLfgLeaveOpcode },
  2444. + /*0x35E*/ { "CMSG_SEARCH_LFG_JOIN", STATUS_LOGGEDIN, &WorldSession::Handle_NULL },
  2445. + /*0x35F*/ { "CMSG_SEARCH_LFG_LEAVE", STATUS_LOGGEDIN, &WorldSession::Handle_NULL },
  2446. /*0x360*/ { "SMSG_UPDATE_LFG_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2447. /*0x361*/ { "SMSG_LFG_PROPOSAL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2448. /*0x362*/ { "CMSG_LFG_PROPOSAL_RESULT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL },
  2449. @@ -900,14 +900,14 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
  2450. /*0x367*/ { "SMSG_LFG_UPDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2451. /*0x368*/ { "SMSG_LFG_UPDATE_PARTY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2452. /*0x369*/ { "SMSG_LFG_UPDATE_SEARCH", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2453. - /*0x36A*/ { "CMSG_LFG_SET_ROLES", STATUS_NEVER, &WorldSession::Handle_NULL },
  2454. - /*0x36B*/ { "CMSG_LFG_SET_NEEDS", STATUS_NEVER, &WorldSession::Handle_NULL },
  2455. - /*0x36C*/ { "CMSG_LFG_SET_BOOT_VOTE", STATUS_NEVER, &WorldSession::Handle_NULL },
  2456. + /*0x36A*/ { "CMSG_LFG_SET_ROLES", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetRolesOpcode },
  2457. + /*0x36B*/ { "CMSG_LFG_SET_NEEDS", STATUS_LOGGEDIN, &WorldSession::Handle_NULL },
  2458. + /*0x36C*/ { "CMSG_LFG_SET_BOOT_VOTE", STATUS_LOGGEDIN, &WorldSession::Handle_NULL },
  2459. /*0x36D*/ { "SMSG_LFG_BOOT_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2460. - /*0x36E*/ { "CMSG_LFD_PLAYER_LOCK_INFO_REQUEST", STATUS_NEVER, &WorldSession::Handle_NULL },
  2461. + /*0x36E*/ { "CMSG_LFD_PLAYER_LOCK_INFO_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLfgPlayerLockInfoRequestOpcode },
  2462. /*0x36F*/ { "SMSG_LFG_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2463. - /*0x370*/ { "CMSG_LFG_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL },
  2464. - /*0x371*/ { "CMSG_LFD_PARTY_LOCK_INFO_REQUEST", STATUS_NEVER, &WorldSession::Handle_NULL },
  2465. + /*0x370*/ { "CMSG_LFG_TELEPORT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL },
  2466. + /*0x371*/ { "CMSG_LFD_PARTY_LOCK_INFO_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLfgPartyLockInfoRequestOpcode },
  2467. /*0x372*/ { "SMSG_LFG_PARTY_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2468. /*0x373*/ { "SMSG_TITLE_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2469. /*0x374*/ { "CMSG_SET_TITLE", STATUS_LOGGEDIN, &WorldSession::HandleSetTitleOpcode },
  2470. @@ -1234,7 +1234,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
  2471. /*0x4B5*/ { "SMSG_ITEM_REFUND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2472. /*0x4B6*/ { "CMSG_CORPSE_MAP_POSITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseMapPositionQuery },
  2473. /*0x4B7*/ { "SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2474. - /*0x4B8*/ { "CMSG_LFG_SET_ROLES_2", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetRoles },
  2475. + /*0x4B8*/ { "CMSG_LFG_SET_ROLES_2", STATUS_LOGGEDIN, &WorldSession::Handle_NULL },
  2476. /*0x4B9*/ { "UMSG_UNKNOWN_1209", STATUS_NEVER, &WorldSession::Handle_NULL },
  2477. /*0x4BA*/ { "CMSG_CALENDAR_CONTEXT_EVENT_SIGNUP", STATUS_NEVER, &WorldSession::Handle_NULL },
  2478. /*0x4BB*/ { "SMSG_CALENDAR_ACTION_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
  2479. diff --git a/src/game/Player.h b/src/game/Player.h
  2480. index 047bccf..e0eb788 100644
  2481. --- a/src/game/Player.h
  2482. +++ b/src/game/Player.h
  2483. @@ -37,6 +37,7 @@
  2484. #include "ReputationMgr.h"
  2485. #include "BattleGround.h"
  2486. #include "DBCEnums.h"
  2487. +#include "LFG.h"
  2488.  
  2489. #include<string>
  2490. #include<vector>
  2491. @@ -394,74 +395,6 @@ struct EnchantDuration
  2492. typedef std::list<EnchantDuration> EnchantDurationList;
  2493. typedef std::list<Item*> ItemDurationList;
  2494.  
  2495. -enum LfgType
  2496. -{
  2497. - LFG_TYPE_NONE = 0,
  2498. - LFG_TYPE_DUNGEON = 1,
  2499. - LFG_TYPE_RAID = 2,
  2500. - LFG_TYPE_QUEST = 3,
  2501. - LFG_TYPE_ZONE = 4,
  2502. - LFG_TYPE_HEROIC_DUNGEON = 5,
  2503. - LFG_TYPE_RANDOM_DUNGEON = 6
  2504. -};
  2505. -
  2506. -enum LfgRoles
  2507. -{
  2508. - LEADER = 0x01,
  2509. - TANK = 0x02,
  2510. - HEALER = 0x04,
  2511. - DAMAGE = 0x08
  2512. -};
  2513. -
  2514. -struct LookingForGroupSlot
  2515. -{
  2516. - LookingForGroupSlot() : entry(0), type(0) {}
  2517. - bool Empty() const { return !entry && !type; }
  2518. - void Clear() { entry = 0; type = 0; }
  2519. - void Set(uint32 _entry, uint32 _type ) { entry = _entry; type = _type; }
  2520. - bool Is(uint32 _entry, uint32 _type) const { return entry == _entry && type == _type; }
  2521. - bool canAutoJoin() const { return entry && (type == LFG_TYPE_DUNGEON || type == LFG_TYPE_HEROIC_DUNGEON); }
  2522. -
  2523. - uint32 entry;
  2524. - uint32 type;
  2525. -};
  2526. -
  2527. -#define MAX_LOOKING_FOR_GROUP_SLOT 3
  2528. -
  2529. -struct LookingForGroup
  2530. -{
  2531. - LookingForGroup() {}
  2532. - bool HaveInSlot(LookingForGroupSlot const& slot) const { return HaveInSlot(slot.entry, slot.type); }
  2533. - bool HaveInSlot(uint32 _entry, uint32 _type) const
  2534. - {
  2535. - for(int i = 0; i < MAX_LOOKING_FOR_GROUP_SLOT; ++i)
  2536. - if(slots[i].Is(_entry, _type))
  2537. - return true;
  2538. - return false;
  2539. - }
  2540. -
  2541. - bool canAutoJoin() const
  2542. - {
  2543. - for(int i = 0; i < MAX_LOOKING_FOR_GROUP_SLOT; ++i)
  2544. - if(slots[i].canAutoJoin())
  2545. - return true;
  2546. - return false;
  2547. - }
  2548. -
  2549. - bool Empty() const
  2550. - {
  2551. - for(int i = 0; i < MAX_LOOKING_FOR_GROUP_SLOT; ++i)
  2552. - if(!slots[i].Empty())
  2553. - return false;
  2554. - return more.Empty();
  2555. - }
  2556. -
  2557. - LookingForGroupSlot slots[MAX_LOOKING_FOR_GROUP_SLOT];
  2558. - LookingForGroupSlot more;
  2559. - std::string comment;
  2560. - uint8 roles;
  2561. -};
  2562. -
  2563. enum RaidGroupError
  2564. {
  2565. ERR_RAID_GROUP_NONE = 0,
  2566. diff --git a/src/game/World.cpp b/src/game/World.cpp
  2567. index e59d07d..9ddb0c4 100644
  2568. --- a/src/game/World.cpp
  2569. +++ b/src/game/World.cpp
  2570. @@ -62,6 +62,7 @@
  2571. #include "GMTicketMgr.h"
  2572. #include "Util.h"
  2573. #include "CharacterDatabaseCleaner.h"
  2574. +#include "LFGMgr.h"
  2575.  
  2576. INSTANTIATE_SINGLETON_1( World );
  2577.  
  2578. @@ -1194,6 +1195,10 @@ void World::SetInitialWorldSettings()
  2579. sLog.outString( "Loading GM tickets...");
  2580. sTicketMgr.LoadGMTickets();
  2581.  
  2582. + ///- Initialize Looking For Group
  2583. + sLog.outString("Starting Looking For Group System");
  2584. + sLFGMgr.InitLFG();
  2585. +
  2586. ///- Handle outdated emails (delete/return)
  2587. sLog.outString( "Returning old mails..." );
  2588. sObjectMgr.ReturnOrDeleteOldMails(false);
  2589. @@ -1452,6 +1457,8 @@ void World::Update(uint32 diff)
  2590. Player::DeleteOldCharacters();
  2591. }
  2592.  
  2593. + sLFGMgr.Update(diff);
  2594. +
  2595. // execute callbacks from sql queries that were queued recently
  2596. UpdateResultQueue();
  2597.  
  2598. diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp
  2599. index 8a8b383..2e5d27b 100644
  2600. --- a/src/game/WorldSession.cpp
  2601. +++ b/src/game/WorldSession.cpp
  2602. @@ -38,6 +38,7 @@
  2603. #include "Auth/AuthCrypt.h"
  2604. #include "Auth/HMACSHA1.h"
  2605. #include "zlib/zlib.h"
  2606. +#include "LFGMgr.h"
  2607.  
  2608. /// WorldSession constructor
  2609. WorldSession::WorldSession(uint32 id, WorldSocket *sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale) :
  2610. @@ -289,6 +290,11 @@ void WorldSession::LogoutPlayer(bool Save)
  2611.  
  2612. if (_player)
  2613. {
  2614. + sLFGMgr.Leave(_player);
  2615. + GetPlayer()->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
  2616. + GetPlayer()->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
  2617. + GetPlayer()->GetSession()->SendLfgUpdateSearch(false);
  2618. +
  2619. sLog.outChar("Account: %d (IP: %s) Logout Character:[%s] (guid: %u)", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName() ,_player->GetGUIDLow());
  2620.  
  2621. if (uint64 lguid = GetPlayer()->GetLootGUID())
  2622. diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h
  2623. index af857e2..9b14df5 100644
  2624. --- a/src/game/WorldSession.h
  2625. +++ b/src/game/WorldSession.h
  2626. @@ -161,8 +161,6 @@ class MANGOS_DLL_SPEC WorldSession
  2627. void SendNotification(const char *format,...) ATTR_PRINTF(2,3);
  2628. void SendNotification(int32 string_id,...);
  2629. void SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName);
  2630. - void SendLfgResult(uint32 type, uint32 entry, uint8 lfg_type);
  2631. - void SendLfgUpdate(uint8 unk1, uint8 unk2, uint8 unk3);
  2632. void SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res);
  2633. void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2,3);
  2634. void SendSetPhaseShift(uint32 phaseShift);
  2635. @@ -677,19 +675,9 @@ class MANGOS_DLL_SPEC WorldSession
  2636. void HandleMinimapPingOpcode(WorldPacket& recv_data);
  2637. void HandleRandomRollOpcode(WorldPacket& recv_data);
  2638. void HandleFarSightOpcode(WorldPacket& recv_data);
  2639. - void HandleSetLfgOpcode(WorldPacket& recv_data);
  2640. void HandleSetDungeonDifficultyOpcode(WorldPacket& recv_data);
  2641. void HandleSetRaidDifficultyOpcode(WorldPacket& recv_data);
  2642. void HandleMoveSetCanFlyAckOpcode(WorldPacket& recv_data);
  2643. - void HandleLfgJoinOpcode(WorldPacket& recv_data);
  2644. - void HandleLfgLeaveOpcode(WorldPacket& recv_data);
  2645. - void HandleSearchLfgJoinOpcode(WorldPacket& recv_data);
  2646. - void HandleSearchLfgLeaveOpcode(WorldPacket& recv_data);
  2647. - void HandleLfgClearOpcode(WorldPacket& recv_data);
  2648. - void HandleLfmClearOpcode(WorldPacket& recv_data);
  2649. - void HandleSetLfmOpcode(WorldPacket& recv_data);
  2650. - void HandleSetLfgCommentOpcode(WorldPacket& recv_data);
  2651. - void HandleLfgSetRoles(WorldPacket& recv_data);
  2652. void HandleSetTitleOpcode(WorldPacket& recv_data);
  2653. void HandleRealmSplitOpcode(WorldPacket& recv_data);
  2654. void HandleTimeSyncResp(WorldPacket& recv_data);
  2655. @@ -697,6 +685,20 @@ class MANGOS_DLL_SPEC WorldSession
  2656. void HandleResetInstancesOpcode(WorldPacket& recv_data);
  2657. void HandleHearthandResurrect(WorldPacket & recv_data);
  2658.  
  2659. + // Looking for Dungeon/Raid
  2660. + void HandleSetLfgCommentOpcode(WorldPacket & recv_data);
  2661. + void HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& recv_data);
  2662. + void HandleLfgPartyLockInfoRequestOpcode(WorldPacket& recv_data);
  2663. + void HandleLfgJoinOpcode(WorldPacket &recv_data);
  2664. + void HandleLfgLeaveOpcode(WorldPacket & /*recv_data*/);
  2665. + void HandleLfgSetRolesOpcode(WorldPacket &recv_data);
  2666. + void SendLfgUpdatePlayer(uint8 updateType);
  2667. + void SendLfgUpdateParty(uint8 updateType);
  2668. + void SendLfgRoleChosen(uint64 guid, uint8 roles);
  2669. + void SendLfgUpdateSearch(bool update);
  2670. + void SendLfgJoinResult(uint8 checkResult, uint8 checkValue);
  2671. + void SendLfgQueueStatus(uint32 dungeon, int32 waitTime, int32 avgWaitTime, int32 waitTimeTanks, int32 waitTimeHealer, int32 waitTimeDps, uint32 queuedTime, uint8 tanks, uint8 healers, uint8 dps);
  2672. +
  2673. // Arena Team
  2674. void HandleInspectArenaTeamsOpcode(WorldPacket& recv_data);
  2675. void HandleArenaTeamQueryOpcode(WorldPacket& recv_data);
  2676. diff --git a/win/VC100/game.vcxproj b/win/VC100/game.vcxproj
  2677. index 44858d5..5559b6a 100644
  2678. --- a/win/VC100/game.vcxproj
  2679. +++ b/win/VC100/game.vcxproj
  2680. @@ -421,6 +421,7 @@
  2681. <ClCompile Include="..\..\src\game\Level2.cpp" />
  2682. <ClCompile Include="..\..\src\game\Level3.cpp" />
  2683. <ClCompile Include="..\..\src\game\LFGHandler.cpp" />
  2684. + <ClCompile Include="..\..\src\game\LFGMgr.cpp" />
  2685. <ClCompile Include="..\..\src\game\LootHandler.cpp" />
  2686. <ClCompile Include="..\..\src\game\LootMgr.cpp" />
  2687. <ClCompile Include="..\..\src\game\Mail.cpp" />
  2688. @@ -568,6 +569,8 @@
  2689. <ClInclude Include="..\..\src\game\ItemEnchantmentMgr.h" />
  2690. <ClInclude Include="..\..\src\game\ItemPrototype.h" />
  2691. <ClInclude Include="..\..\src\game\Language.h" />
  2692. + <ClInclude Include="..\..\src\game\LFG.h" />
  2693. + <ClInclude Include="..\..\src\game\LFGMgr.h" />
  2694. <ClInclude Include="..\..\src\game\LootMgr.h" />
  2695. <ClInclude Include="..\..\src\game\Mail.h" />
  2696. <ClInclude Include="..\..\src\game\Map.h" />
  2697. diff --git a/win/VC100/game.vcxproj.filters b/win/VC100/game.vcxproj.filters
  2698. index 804e667..97cb4a6 100644
  2699. --- a/win/VC100/game.vcxproj.filters
  2700. +++ b/win/VC100/game.vcxproj.filters
  2701. @@ -150,6 +150,9 @@
  2702. <ClCompile Include="..\..\src\game\LFGHandler.cpp">
  2703. <Filter>World/Handlers</Filter>
  2704. </ClCompile>
  2705. + <ClCompile Include="..\..\src\game\LFGMgr.cpp">
  2706. + <Filter>World/Handlers</Filter>
  2707. + </ClCompile>
  2708. <ClCompile Include="..\..\src\game\LootHandler.cpp">
  2709. <Filter>World/Handlers</Filter>
  2710. </ClCompile>
  2711. @@ -543,6 +546,12 @@
  2712. <ClInclude Include="..\..\src\game\InstanceSaveMgr.h">
  2713. <Filter>World/Handlers</Filter>
  2714. </ClInclude>
  2715. + <ClInclude Include="..\..\src\game\LFG.h">
  2716. + <Filter>World/Handlers</Filter>
  2717. + </ClInclude>
  2718. + <ClInclude Include="..\..\src\game\LFGMgr.h">
  2719. + <Filter>World/Handlers</Filter>
  2720. + </ClInclude>
  2721. <ClInclude Include="..\..\src\game\Mail.h">
  2722. <Filter>World/Handlers</Filter>
  2723. </ClInclude>
  2724. diff --git a/win/VC80/game.vcproj b/win/VC80/game.vcproj
  2725. index 8f1c431..20d9369 100644
  2726. --- a/win/VC80/game.vcproj
  2727. +++ b/win/VC80/game.vcproj
  2728. @@ -818,10 +818,22 @@
  2729. >
  2730. </File>
  2731. <File
  2732. + RelativePath="..\..\src\game\LFG.h"
  2733. + >
  2734. + </File>
  2735. + <File
  2736. RelativePath="..\..\src\game\LFGHandler.cpp"
  2737. >
  2738. </File>
  2739. <File
  2740. + RelativePath="..\..\src\game\LFGMgr.cpp"
  2741. + >
  2742. + </File>
  2743. + <File
  2744. + RelativePath="..\..\src\game\LFGMgr.h"
  2745. + >
  2746. + </File>
  2747. + <File
  2748. RelativePath="..\..\src\game\LootHandler.cpp"
  2749. >
  2750. </File>
  2751. diff --git a/win/VC90/game.vcproj b/win/VC90/game.vcproj
  2752. index 1eb6872..0a6f0eb 100644
  2753. --- a/win/VC90/game.vcproj
  2754. +++ b/win/VC90/game.vcproj
  2755. @@ -811,10 +811,22 @@
  2756. >
  2757. </File>
  2758. <File
  2759. + RelativePath="..\..\src\game\LFG.h"
  2760. + >
  2761. + </File>
  2762. + <File
  2763. RelativePath="..\..\src\game\LFGHandler.cpp"
  2764. >
  2765. </File>
  2766. <File
  2767. + RelativePath="..\..\src\game\LFGMgr.cpp"
  2768. + >
  2769. + </File>
  2770. + <File
  2771. + RelativePath="..\..\src\game\LFGMgr.h"
  2772. + >
  2773. + </File>
  2774. + <File
  2775. RelativePath="..\..\src\game\LootHandler.cpp"
  2776. >
  2777. </File>
  2778. --
  2779. 1.7.0.2.msysgit.0 [/PHP]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement