OregonCore  revision 3611e8a-git
Your Favourite TBC server
Group.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Common.h"
19 #include "Opcodes.h"
20 #include "WorldPacket.h"
21 #include "WorldSession.h"
22 #include "Player.h"
23 #include "World.h"
24 #include "ObjectMgr.h"
25 #include "Group.h"
26 #include "Formulas.h"
27 #include "ObjectAccessor.h"
28 #include "Battleground.h"
29 #include "MapManager.h"
30 #include "InstanceSaveMgr.h"
31 #include "Util.h"
32 #include "ScriptMgr.h"
33 
35 {
36  m_leaderGuid = 0;
37  m_mainTank = 0;
38  m_mainAssistant = 0;
40  m_bgGroup = NULL;
42  m_looterGuid = 0;
45  m_subGroupsCounts = NULL;
47 
48  for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
49  m_targetIcons[i] = 0;
50 }
51 
53 {
54  if (m_bgGroup)
55  {
56  sLog.outDebug("Group::~Group: battleground group being deleted.");
57  if (m_bgGroup->GetBgRaid(ALLIANCE) == this) m_bgGroup->SetBgRaid(ALLIANCE, NULL);
58  else if (m_bgGroup->GetBgRaid(HORDE) == this) m_bgGroup->SetBgRaid(HORDE, NULL);
59  else sLog.outError("Group::~Group: battleground group is not linked to the correct battleground.");
60  }
61  Rolls::iterator itr;
62  while (!RollId.empty())
63  {
64  itr = RollId.begin();
65  Roll* r = *itr;
66  RollId.erase(itr);
67  delete(r);
68  }
69 
70  // it is undefined whether objectmgr (which stores the groups) or instancesavemgr
71  // will be unloaded first so we must be prepared for both cases
72  // this may unload some instance saves
73  for (uint8 i = 0; i < TOTAL_DIFFICULTIES; i++)
74  for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
75  itr->second.save->RemoveGroup(this);
76 
77  // Sub group counters clean up
79  delete[] m_subGroupsCounts;
80 }
81 
82 bool Group::Create(const uint64& guid, const char* name)
83 {
84  m_leaderGuid = guid;
85  m_leaderName = name;
86 
88 
91 
94  m_looterGuid = guid;
96 
98  Player* leader = sObjectMgr.GetPlayer(guid, true);
99 
100  if (!leader)
101  return false;
102 
103  if (!isBGGroup())
104  {
105  if (leader)
106  m_difficulty = leader->GetDifficulty();
107 
108  Player::ConvertInstancesToGroup(leader, this, guid);
109 
110  // store group in database
112  CharacterDatabase.PExecute("DELETE FROM groups WHERE leaderGuid ='%u'", GUID_LOPART(m_leaderGuid));
113  CharacterDatabase.PExecute("DELETE FROM group_member WHERE leaderGuid ='%u'", GUID_LOPART(m_leaderGuid));
114  CharacterDatabase.PExecute("INSERT INTO groups(leaderGuid,mainTank,mainAssistant,lootMethod,looterGuid,lootThreshold,icon1,icon2,icon3,icon4,icon5,icon6,icon7,icon8,isRaid,difficulty,masterLooterGuid) "
115  "VALUES('%u','%u','%u','%u','%u','%u','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','%u','%u','%u')",
118  }
119 
120  if (!AddMember(guid, name))
121  return false;
122 
124 
125  sScriptMgr.OnGroupCreated(leader->GetGroup(), leader);
126 
127  return true;
128 }
129 
130 bool Group::LoadGroupFromDB(const uint64& leaderGuid, QueryResult_AutoPtr result, bool loadMembers)
131 {
132  if (isBGGroup())
133  return false;
134 
135  if (!result)
136  {
137  // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
138  result = CharacterDatabase.PQuery("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty, masterLooterGuid FROM groups WHERE leaderGuid ='%u'", GUID_LOPART(leaderGuid));
139  if (!result)
140  return false;
141  }
142 
143  m_leaderGuid = leaderGuid;
144 
145  // group leader not exist
146  if (!sObjectMgr.GetPlayerNameByGUID(m_leaderGuid, m_leaderName))
147  return false;
148 
149  m_groupType = (*result)[13].GetBool() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL;
150 
153 
154  m_difficulty = (DungeonDifficulty)(*result)[14].GetUInt8();
155  m_mainTank = (*result)[0].GetUInt64();
156  m_mainAssistant = (*result)[1].GetUInt64();
157  m_lootMethod = (LootMethod)(*result)[2].GetUInt8();
158  m_looterGuid = MAKE_NEW_GUID((*result)[3].GetUInt32(), 0, HIGHGUID_PLAYER);
159  m_lootThreshold = (ItemQualities)(*result)[4].GetUInt16();
160  m_masterLooterGuid = MAKE_NEW_GUID((*result)[15].GetUInt32(), 0, HIGHGUID_PLAYER);
161 
162  for (int i = 0; i < TARGETICONCOUNT; i++)
163  m_targetIcons[i] = (*result)[5 + i].GetUInt64();
164 
165  if (loadMembers)
166  {
167  result = CharacterDatabase.PQuery("SELECT memberGuid, assistant, subgroup FROM group_member WHERE leaderGuid ='%u'", GUID_LOPART(leaderGuid));
168  if (!result)
169  return false;
170 
171  do
172  {
173  LoadMemberFromDB((*result)[0].GetUInt32(), (*result)[2].GetUInt8(), (*result)[1].GetBool());
174  }
175  while (result->NextRow());
176 
177  if (GetMembersCount() < 2) // group too small
178  return false;
179  }
180 
181  return true;
182 }
183 
184 bool Group::LoadMemberFromDB(uint32 guidLow, uint8 subgroup, bool assistant)
185 {
186  MemberSlot member;
187  member.guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER);
188 
189  // skip non-existed member
190  if (!sObjectMgr.GetPlayerNameByGUID(member.guid, member.name))
191  return false;
192 
193  member.group = subgroup;
194  member.assistant = assistant;
195 
196  m_memberSlots.push_back(member);
197 
198  SubGroupCounterIncrease(subgroup);
199 
200  return true;
201 }
202 
204 {
206 
208 
209  if (!isBGGroup())
210  CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
211  SendUpdate();
212 }
213 
214 bool Group::AddInvite(Player* player, bool isLeader)
215 {
216  if (!player || player->GetGroupInvite())
217  return false;
218  Group* group = player->GetGroup();
219  if (group && group->isBGGroup())
220  group = player->GetOriginalGroup();
221  if (group)
222  return false;
223 
224  RemoveInvite(player);
225 
226  m_invitees.insert(player);
227 
228  player->SetGroupInvite(this);
229 
230  if (!isLeader)
231  sScriptMgr.OnGroupPlayerInvited(this, player);
232 
233  return true;
234 }
235 
237 {
238  if (!AddInvite(player, true))
239  return false;
240 
241  m_leaderGuid = player->GetGUID();
242  m_leaderName = player->GetName();
243  return true;
244 }
245 
247 {
248  m_invitees.erase(player);
249 
250  player->SetGroupInvite(NULL);
251  return GetMembersCount();
252 }
253 
255 {
256  for (InvitesList::iterator itr = m_invitees.begin(); itr != m_invitees.end(); ++itr)
257  (*itr)->SetGroupInvite(NULL);
258 
259  m_invitees.clear();
260 }
261 
262 Player* Group::GetInvited(const uint64& guid) const
263 {
264  for (InvitesList::const_iterator itr = m_invitees.begin(); itr != m_invitees.end(); ++itr)
265  {
266  if ((*itr)->GetGUID() == guid)
267  return (*itr);
268  }
269  return NULL;
270 }
271 
272 Player* Group::GetInvited(const std::string& name) const
273 {
274  for (InvitesList::const_iterator itr = m_invitees.begin(); itr != m_invitees.end(); ++itr)
275  {
276  if ((*itr)->GetName() == name)
277  return (*itr);
278  }
279  return NULL;
280 }
281 
282 bool Group::AddMember(const uint64& guid, const char* name)
283 {
284  if (!_addMember(guid, name))
285  return false;
286  SendUpdate();
287 
288  Player* player = sObjectMgr.GetPlayer(guid, true);
289  if (player)
290  {
291  if (!IsLeader(player->GetGUID()) && !isBGGroup())
292  {
293  // reset the new member's instances, unless he is currently in one of them
294  // including raid/heroic instances that they are not permanently bound to!
296 
297  if (player->getLevel() >= LEVELREQUIREMENT_HEROIC && player->GetDifficulty() != GetDifficulty())
298  {
299  player->SetDifficulty(m_difficulty);
300  player->SendDungeonDifficulty(true);
301  }
302  sScriptMgr.OnGroupPlayerJoined(this, player);
303  }
305  UpdatePlayerOutOfRange(player);
306  }
307 
308  return true;
309 }
310 
311 uint32 Group::RemoveMember(const uint64& guid, const RemoveMethod& method /* = GROUP_REMOVEMETHOD_DEFAULT */, uint64 kicker /* = 0 */, const char* reason /* = NULL */)
312 {
314 
315  // remove member and change leader (if need) only if strong more 2 members _before_ member remove
316  if (GetMembersCount() > (isBGGroup() ? 1 : 2)) // in BG group case allow 1 members group
317  {
318  bool leaderChanged = _removeMember(guid);
319 
320  if (Player* player = sObjectMgr.GetPlayer(guid, true))
321  {
322  WorldPacket data;
323 
324  sScriptMgr.OnGroupPlayerRemoved(this, player, method, kicker, reason);
325 
326  if (method == GROUP_REMOVEMETHOD_KICK)
327  {
329  player->GetSession()->SendPacket(&data);
330  }
331 
332  // we already removed player from group and in player->GetGroup() is his original group!
333  if (Group* group = player->GetGroup())
334  group->SendUpdate();
335  else
336  {
337  data.Initialize(SMSG_GROUP_LIST, 24);
338  data << uint64(0) << uint64(0) << uint64(0);
339  player->GetSession()->SendPacket(&data);
340  }
341 
342  _homebindIfInstance(player);
343 
344  }
345 
346  if (leaderChanged)
347  {
348  WorldPacket data(SMSG_GROUP_SET_LEADER, (m_memberSlots.front().name.size() + 1));
349  data << m_memberSlots.front().name;
350  BroadcastPacket(&data, true);
351  }
352 
353  SendUpdate();
354  }
355  // if group before remove <= 2 disband it
356  else
357  Disband(true);
358 
359 
360  return m_memberSlots.size();
361 }
362 
363 void Group::ChangeLeader(const uint64& guid)
364 {
365  member_citerator slot = _getMemberCSlot(guid);
366 
367  if (slot == m_memberSlots.end())
368  return;
369 
370  Player* oldLeader = sObjectMgr.GetPlayer(this->GetLeaderGUID());
371  _setLeader(guid);
372  Player* newLeader = sObjectMgr.GetPlayer(guid);
373 
374  if (oldLeader && newLeader)
375  sScriptMgr.OnGroupLeaderChanged(this, oldLeader, newLeader);
376 
377  WorldPacket data(SMSG_GROUP_SET_LEADER, slot->name.size() + 1);
378  data << slot->name;
379  BroadcastPacket(&data, true);
380  SendUpdate();
381 }
382 
383 void Group::Disband(bool hideDestroy)
384 {
385  Player* player = sObjectMgr.GetPlayer(this->GetLeaderGUID());
386 
387  if (player && player->GetSession())
388  sScriptMgr.OnGroupDisbanded(this, player);
389 
390  for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
391  {
392  player = sObjectMgr.GetPlayer(citr->guid, true);
393  if (!player)
394  continue;
395 
396  // we cannot call _removeMember because it would invalidate member iterator
397  // if we are removing player from battleground raid
398  if (isBGGroup())
399  player->RemoveFromBattlegroundRaid();
400  else
401  {
402  // we can remove player who is in battleground from his original group
403  if (player->GetOriginalGroup() == this)
404  player->SetOriginalGroup(NULL);
405  else
406  player->SetGroup(NULL);
407  }
408 
409  if (!player->GetSession())
410  continue;
411 
412  WorldPacket data;
413  if (!hideDestroy)
414  {
416  player->GetSession()->SendPacket(&data);
417  }
418 
419  // we already removed player from group and in player->GetGroup() is his original group, send update
420  if (Group* group = player->GetGroup())
421  group->SendUpdate();
422  else
423  {
424  data.Initialize(SMSG_GROUP_LIST, 24);
425  data << uint64(0) << uint64(0) << uint64(0);
426  player->GetSession()->SendPacket(&data);
427  }
428 
429  _homebindIfInstance(player);
430  }
431  RollId.clear();
432  m_memberSlots.clear();
433 
435 
436  if (!isBGGroup())
437  {
439  CharacterDatabase.PExecute("DELETE FROM groups WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
440  CharacterDatabase.PExecute("DELETE FROM group_member WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
443  }
444 
445  m_leaderGuid = 0;
446  m_leaderName = "";
447 }
448 
449 /*********************************************************/
450 /*** LOOT SYSTEM ***/
451 /*********************************************************/
452 
453 void Group::SendLootStartRoll(uint32 CountDown, const Roll& r)
454 {
455  WorldPacket data(SMSG_LOOT_START_ROLL, (8 + 4 + 4 + 4 + 4 + 4));
456  data << uint64(r.itemGUID); // guid of rolled item
457  data << uint32(r.totalPlayersRolling); // maybe the number of players rolling for it???
458  data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for
459  data << uint32(r.itemRandomSuffix); // randomSuffix
460  data << uint32(r.itemRandomPropId); // item random property ID
461  data << uint32(CountDown); // the countdown time to choose "need" or "greed"
462 
463  for (Roll::PlayerVote::const_iterator itr = r.playerVote.begin(); itr != r.playerVote.end(); ++itr)
464  {
465  Player* p = sObjectMgr.GetPlayer(itr->first);
466  if (!p || !p->GetSession())
467  continue;
468 
469  if (itr->second != ROLL_NOT_VALID)
470  p->GetSession()->SendPacket(&data);
471  }
472 }
473 
474 void Group::SendLootRoll(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll& r)
475 {
476  WorldPacket data(SMSG_LOOT_ROLL, (8 + 4 + 8 + 4 + 4 + 4 + 1 + 1 + 1));
477  data << uint64(SourceGuid); // guid of the item rolled
478  data << uint32(0); // unknown, maybe amount of players
479  data << uint64(TargetGuid);
480  data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for
481  data << uint32(r.itemRandomSuffix); // randomSuffix
482  data << uint32(r.itemRandomPropId); // Item random property ID
483  data << uint8(RollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number
484  data << uint8(RollType); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll
485  data << uint8(0); // auto pass on NeedBeforeGreed loot because player cannot use the object
486 
487  for (Roll::PlayerVote::const_iterator itr = r.playerVote.begin(); itr != r.playerVote.end(); ++itr)
488  {
489  Player* p = sObjectMgr.GetPlayer(itr->first, true);
490  if (!p || !p->GetSession())
491  continue;
492 
493  if (itr->second != ROLL_NOT_VALID)
494  p->GetSession()->SendPacket(&data);
495  }
496 }
497 
498 void Group::SendLootRollWon(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll& r)
499 {
500  WorldPacket data(SMSG_LOOT_ROLL_WON, (8 + 4 + 4 + 4 + 4 + 8 + 1 + 1));
501  data << uint64(SourceGuid); // guid of the item rolled
502  data << uint32(0); // unknown, maybe amount of players
503  data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for
504  data << uint32(r.itemRandomSuffix); // randomSuffix
505  data << uint32(r.itemRandomPropId); // Item random property
506  data << uint64(TargetGuid); // guid of the player who won.
507  data << uint8(RollNumber); // rollnumber realted to SMSG_LOOT_ROLL
508  data << uint8(RollType); // Rolltype related to SMSG_LOOT_ROLL
509 
510  for (Roll::PlayerVote::const_iterator itr = r.playerVote.begin(); itr != r.playerVote.end(); ++itr)
511  {
512  Player* p = sObjectMgr.GetPlayer(itr->first, true);
513  if (!p || !p->GetSession())
514  continue;
515 
516  if (itr->second != ROLL_NOT_VALID)
517  p->GetSession()->SendPacket(&data);
518  }
519 }
520 
521 void Group::SendLootAllPassed(uint32 NumberOfPlayers, const Roll& r)
522 {
523  WorldPacket data(SMSG_LOOT_ALL_PASSED, (8 + 4 + 4 + 4 + 4));
524  data << uint64(r.itemGUID); // Guid of the item rolled
525  data << uint32(NumberOfPlayers); // The number of players rolling for it???
526  data << uint32(r.itemid); // The itemEntryId for the item that shall be rolled for
527  data << uint32(r.itemRandomPropId); // Item random property ID
528  data << uint32(r.itemRandomSuffix); // Item random suffix ID
529 
530  for (Roll::PlayerVote::const_iterator itr = r.playerVote.begin(); itr != r.playerVote.end(); ++itr)
531  {
532  Player* p = sObjectMgr.GetPlayer(itr->first, true);
533  if (!p || !p->GetSession())
534  continue;
535 
536  if (itr->second != ROLL_NOT_VALID)
537  p->GetSession()->SendPacket(&data);
538  }
539 }
540 
541 // notify group members which player is the allowed looter for the given creature
542 void Group::SendLooter(Creature* creature, Player* groupLooter)
543 {
544  ASSERT(creature);
545 
546  WorldPacket data(SMSG_LOOT_LIST, (8+8));
547  data << uint64(creature->GetGUID());
548 
549  if (GetLootMethod() == MASTER_LOOT && creature->loot.hasOverThresholdItem())
550  data << GetMasterLooterGuid();
551  else
552  data << uint8(0);
553 
554  if (groupLooter)
555  data << groupLooter->GetPackGUID();
556  else
557  data << uint8(0);
558 
559  BroadcastPacket(&data, false);
560 }
561 
562 void Group::GroupLoot(const uint64& playerGUID, Loot* loot, WorldObject* object)
563 {
564  std::vector<LootItem>::iterator i;
565  ItemTemplate const* item;
566  uint8 itemSlot = 0;
567  Player* player = sObjectMgr.GetPlayer(playerGUID);
568  Group* group = player->GetGroup();
569 
570  for (i = loot->items.begin(); i != loot->items.end(); ++i, ++itemSlot)
571  {
572  if (i->freeforall)
573  continue;
574 
575  item = sObjectMgr.GetItemTemplate(i->itemid);
576  if (!item)
577  {
578  //sLog.outDebug("Group::GroupLoot: missing item prototype for item with id: %d", i->itemid);
579  continue;
580  }
581 
582  //roll for over-threshold item if it's one-player loot
583  if (item->Quality >= uint32(m_lootThreshold))
584  {
585  uint64 newitemGUID = MAKE_NEW_GUID(sObjectMgr.GenerateLowGuid(HIGHGUID_ITEM), 0, HIGHGUID_ITEM);
586  Roll* r = new Roll(newitemGUID, *i);
587 
588  //a vector is filled with only near party members
589  for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
590  {
591  Player* member = itr->GetSource();
592  if (!member || !member->GetSession())
593  continue;
594  if (i->AllowedForPlayer(member))
595  {
596  if (member->IsWithinDistInMap(object, sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE), false))
597  {
598  r->playerVote[member->GetGUID()] = ROLL_NOT_EMITED_YET;
599  ++r->totalPlayersRolling;
600  }
601  }
602  }
603 
604  r->setLoot(loot);
605  r->itemSlot = itemSlot;
606 
607  group->SendLootStartRoll(60000, *r);
608 
609  loot->items[itemSlot].is_blocked = true;
610  object->m_groupLootTimer = 60000;
611  object->lootingGroupLeaderGUID = GetLeaderGUID();
612 
613  RollId.push_back(r);
614  }
615  else
616  i->is_underthreshold = 1;
617  }
618 }
619 
620 void Group::NeedBeforeGreed(const uint64& playerGUID, Loot* loot, WorldObject* object)
621 {
622  ItemTemplate const* item;
623  Player* player = sObjectMgr.GetPlayer(playerGUID);
624  Group* group = player->GetGroup();
625 
626  uint8 itemSlot = 0;
627  for (std::vector<LootItem>::iterator i = loot->items.begin(); i != loot->items.end(); ++i, ++itemSlot)
628  {
629  item = sObjectMgr.GetItemTemplate(i->itemid);
630 
631  //only roll for one-player items, not for ones everyone can get
632  if (item->Quality >= uint32(m_lootThreshold) && !i->freeforall)
633  {
634  uint64 newitemGUID = MAKE_NEW_GUID(sObjectMgr.GenerateLowGuid(HIGHGUID_ITEM), 0, HIGHGUID_ITEM);
635  Roll* r = new Roll(newitemGUID, *i);
636 
637  for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
638  {
639  Player* playerToRoll = itr->GetSource();
640  if (!playerToRoll || !playerToRoll->GetSession())
641  continue;
642 
643  if (playerToRoll->CanUseItem(item) && i->AllowedForPlayer(playerToRoll))
644  {
645  if (playerToRoll->GetDistance2d(object) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
646  {
647  r->playerVote[playerToRoll->GetGUID()] = ROLL_NOT_EMITED_YET;
648  ++r->totalPlayersRolling;
649  }
650  }
651  }
652 
653  if (r->totalPlayersRolling > 0)
654  {
655  r->setLoot(loot);
656  r->itemSlot = itemSlot;
657 
658  group->SendLootStartRoll(60000, *r);
659 
660  loot->items[itemSlot].is_blocked = true;
661 
662  RollId.push_back(r);
663  }
664  else
665  delete r;
666  }
667  else
668  i->is_underthreshold = 1;
669  }
670 }
671 
672 void Group::MasterLoot(const uint64& playerGUID, Loot* loot, WorldObject* object)
673 {
674  Player* player = sObjectMgr.GetPlayer(playerGUID);
675  if (!player)
676  return;
677 
678  sLog.outDebug("Group::MasterLoot (SMSG_LOOT_MASTER_LIST, 330) player = [%s].", player->GetName());
679 
680  for (std::vector<LootItem>::iterator i = loot->items.begin(); i != loot->items.end(); ++i)
681  {
682  if (i->freeforall)
683  continue;
684 
685  i->is_blocked = !i->is_underthreshold;
686  }
687 
688  for (std::vector<LootItem>::iterator i = loot->quest_items.begin(); i != loot->quest_items.end(); ++i)
689  i->is_blocked = !i->is_underthreshold;
690 
691  uint32 real_count = 0;
692 
694  data << (uint8)GetMembersCount();
695 
696  for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
697  {
698  Player* looter = itr->GetSource();
699  if (!looter->IsInWorld())
700  continue;
701 
702  if (looter->GetDistance2d(object) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
703  {
704  data << uint64(looter->GetGUID());
705  ++real_count;
706  }
707  }
708 
709  data.put<uint8>(0, real_count);
710 
711  for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
712  {
713  Player* looter = itr->GetSource();
714  if (looter->GetDistance2d(object) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
715  looter->GetSession()->SendPacket(&data);
716  }
717 }
718 
719 void Group::CountRollVote(const uint64& playerGUID, const uint64& Guid, uint32 NumberOfPlayers, uint8 Choice)
720 {
721  Rolls::iterator rollI = GetRoll(Guid);
722  if (rollI == RollId.end())
723  return;
724  Roll* roll = *rollI;
725 
726  Roll::PlayerVote::iterator itr = roll->playerVote.find(playerGUID);
727  // this condition means that player joins to the party after roll begins
728  if (itr == roll->playerVote.end())
729  return;
730 
731  if (roll->getLoot())
732  if (roll->getLoot()->items.empty())
733  return;
734 
735  switch (Choice)
736  {
737  case ROLL_PASS: // Player choose pass
738  SendLootRoll(0, playerGUID, 128, 128, *roll);
739  ++roll->totalPass;
740  itr->second = ROLL_PASS;
741  break;
742  case ROLL_NEED: // player choose Need
743  SendLootRoll(0, playerGUID, 0, 0, *roll);
744  ++roll->totalNeed;
745  itr->second = ROLL_NEED;
746  break;
747  case ROLL_GREED: // player choose Greed
748  SendLootRoll(0, playerGUID, 128, 2, *roll);
749  ++roll->totalGreed;
750  itr->second = ROLL_GREED;
751  break;
752  default: // Roll removed case
753  break;
754  }
755 
756  if (roll->totalPass + roll->totalGreed + roll->totalNeed >= roll->totalPlayersRolling)
757  CountTheRoll(rollI, NumberOfPlayers);
758 }
759 
760 //called when roll timer expires
762 {
763  Rolls::iterator itr;
764  while (!RollId.empty())
765  {
766  //need more testing here, if rolls disappear
767  itr = RollId.begin();
768  CountTheRoll(itr, GetMembersCount()); //i don't have to edit player votes, who didn't vote ... he will pass
769  }
770 }
771 
772 void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers)
773 {
774  Roll* roll = *rollI;
775  if (!roll->isValid()) // is loot already deleted ?
776  {
777  RollId.erase(rollI);
778  delete roll;
779  return;
780  }
781  //end of the roll
782  if (roll->totalNeed > 0)
783  {
784  if (!roll->playerVote.empty())
785  {
786  uint8 maxresul = 0;
787  uint64 maxguid = (*roll->playerVote.begin()).first;
788  Player* player;
789 
790  for (Roll::PlayerVote::const_iterator itr = roll->playerVote.begin(); itr != roll->playerVote.end(); ++itr)
791  {
792  if (itr->second != ROLL_NEED)
793  continue;
794 
795  uint8 randomN = urand(1, 100);
796  SendLootRoll(0, itr->first, randomN, ROLL_NEED, *roll);
797  if (maxresul < randomN)
798  {
799  maxguid = itr->first;
800  maxresul = randomN;
801  }
802  }
803  SendLootRollWon(0, maxguid, maxresul, ROLL_NEED, *roll);
804  player = sObjectMgr.GetPlayer(maxguid);
805 
806  if (player && player->GetSession())
807  {
808  ItemPosCountVec dest;
809  LootItem* item = &(roll->getLoot()->items[roll->itemSlot]);
810  uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count);
811  if (msg == EQUIP_ERR_OK)
812  {
813  item->is_looted = true;
814  roll->getLoot()->NotifyItemRemoved(roll->itemSlot);
815  --roll->getLoot()->unlootedCount;
816  player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId);
817  }
818  else
819  {
820  item->is_blocked = false;
821  player->SendEquipError(msg, NULL, NULL);
822  }
823  }
824  }
825  }
826  else if (roll->totalGreed > 0)
827  {
828  if (!roll->playerVote.empty())
829  {
830  uint8 maxresul = 0;
831  uint64 maxguid = (*roll->playerVote.begin()).first;
832  Player* player;
833 
834  Roll::PlayerVote::iterator itr;
835  for (itr = roll->playerVote.begin(); itr != roll->playerVote.end(); ++itr)
836  {
837  if (itr->second != ROLL_GREED)
838  continue;
839 
840  uint8 randomN = urand(1, 100);
841  SendLootRoll(0, itr->first, randomN, itr->second, *roll);
842  if (maxresul < randomN)
843  {
844  maxguid = itr->first;
845  maxresul = randomN;
846  }
847  }
848  SendLootRollWon(0, maxguid, maxresul, ROLL_GREED, *roll);
849  player = sObjectMgr.GetPlayer(maxguid);
850 
851  if (player && player->GetSession())
852  {
853  ItemPosCountVec dest;
854  LootItem* item = &(roll->getLoot()->items[roll->itemSlot]);
855  uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count);
856  if (msg == EQUIP_ERR_OK)
857  {
858  item->is_looted = true;
859  roll->getLoot()->NotifyItemRemoved(roll->itemSlot);
860  --roll->getLoot()->unlootedCount;
861  player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId);
862  }
863  else
864  {
865  item->is_blocked = false;
866  player->SendEquipError(msg, NULL, NULL);
867  }
868  }
869  }
870  }
871  else
872  {
873  SendLootAllPassed(NumberOfPlayers, *roll);
874 
875  // remove is_blocked so that the item is lootable by all players
876  LootItem* item = &(roll->itemSlot >= roll->getLoot()->items.size() ? roll->getLoot()->quest_items[roll->itemSlot - roll->getLoot()->items.size()] : roll->getLoot()->items[roll->itemSlot]);
877  if (item)
878  item->is_blocked = false;
879  }
880  RollId.erase(rollI);
881  delete roll;
882 }
883 
885 {
886  if (id >= TARGETICONCOUNT)
887  return;
888 
889  // clean other icons
890  if (guid != 0)
891  for (int i = 0; i < TARGETICONCOUNT; i++)
892  if (m_targetIcons[i] == guid)
893  SetTargetIcon(i, 0);
894 
895  m_targetIcons[id] = guid;
896 
897  WorldPacket data(MSG_RAID_TARGET_UPDATE, (1 + 1 + 8));
898  data << (uint8)0;
899  data << uint8(id);
900  data << uint64(guid);
901  BroadcastPacket(&data, true);
902 }
903 
904 void Group::GetDataForXPAtKill(Unit const* victim, uint32& count, uint32& sum_level, Player*& member_with_max_level, Player*& not_gray_member_with_max_level)
905 {
906  for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
907  {
908  Player* member = itr->GetSource();
909  if (!member || !member->IsAlive()) // only for alive
910  continue;
911 
912  if (!member->IsAtGroupRewardDistance(victim)) // at req. distance
913  continue;
914 
915  ++count;
916  sum_level += member->getLevel();
917  if (!member_with_max_level || member_with_max_level->getLevel() < member->getLevel())
918  member_with_max_level = member;
919 
920  uint32 gray_level = Oregon::XP::GetGrayLevel(member->getLevel());
921  // if the victim is higher level than the gray level of the currently examined group member,
922  // then set not_gray_member_with_max_level if needed.
923  if (victim->getLevel() > gray_level && (!not_gray_member_with_max_level
924  || not_gray_member_with_max_level->getLevel() < member->getLevel()))
925  not_gray_member_with_max_level = member;
926  }
927 }
928 
930 {
931  if (!session)
932  return;
933 
935  data << uint8(1); // list targets
936 
937  for (int i = 0; i < TARGETICONCOUNT; ++i)
938  {
939  if (m_targetIcons[i] == 0)
940  continue;
941 
942  data << uint8(i);
943  data << uint64(m_targetIcons[i]);
944  }
945 
946  session->SendPacket(&data);
947 }
948 
950 {
951  Player* player;
952  for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
953  {
954  player = sObjectMgr.GetPlayer(citr->guid, true);
955  if (!player || !player->GetSession() || player->GetGroup() != this)
956  continue;
957 
958  // client would crash if this is sent while he's at aloading screen
959  if (!player->IsInWorld())
960  {
962  continue;
963  }
964 
965  // guess size
966  WorldPacket data(SMSG_GROUP_LIST, (1 + 1 + 1 + 1 + 8 + 4 + GetMembersCount() * 20));
967  data << (uint8)m_groupType; // group type
968  data << (uint8)(isBGGroup() ? 1 : 0); // 2.0.x, isBattlegroundGroup?
969  data << (uint8)(citr->group); // groupid
970  data << (uint8)(GetFlags(*citr)); // group flags
971  data << uint64(0x50000000FFFFFFFELL); // related to voice chat?
972  data << uint32(GetMembersCount() - 1);
973  for (member_citerator citr2 = m_memberSlots.begin(); citr2 != m_memberSlots.end(); ++citr2)
974  {
975  if (citr->guid == citr2->guid)
976  continue;
977 
978  Player* member = sObjectMgr.GetPlayer(citr2->guid, true);
979  uint8 onlineState = (member) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE;
980  onlineState = onlineState | ((isBGGroup()) ? MEMBER_STATUS_PVP : 0);
981 
982  data << citr2->name;
983  data << (uint64)citr2->guid;
984  // online-state
985  data << (uint8)(onlineState);
986  data << (uint8)(citr2->group); // groupid
987  data << (uint8)(GetFlags(*citr2)); // group flags
988  }
989 
990  data << uint64(m_leaderGuid); // leader guid
991  if (GetMembersCount() - 1)
992  {
993  data << uint8(m_lootMethod); // loot method
994 
995  if (m_lootMethod == MASTER_LOOT)
996  data << uint64(m_masterLooterGuid); // master looter guid
997  else
998  data << uint64(0);
999 
1000  data << uint8(m_lootThreshold); // loot threshold
1001  data << uint8(m_difficulty); // Heroic Mod Group
1002  }
1003  player->GetSession()->SendPacket(&data);
1004  }
1005 }
1006 
1008 {
1009  if (!player || !player->IsInWorld())
1010  return;
1011 
1012  if (player->GetGroupUpdateFlag() == GROUP_UPDATE_FLAG_NONE)
1013  return;
1014 
1015  WorldPacket data;
1016  player->GetSession()->BuildPartyMemberStatsChangedPacket(player, &data);
1017 
1018  Player* member;
1019  for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
1020  {
1021  member = itr->GetSource();
1022  if (member && member != player && (!member->IsInMap(player) || !member->IsWithinDist(player, member->GetSightRange(), false)))
1023  member->GetSession()->SendPacket(&data);
1024  }
1025 }
1026 
1027 void Group::BroadcastPacket(WorldPacket* packet, bool ignorePlayersInBGRaid, int group, uint64 ignore)
1028 {
1029  for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
1030  {
1031  Player* pl = itr->GetSource();
1032  if (!pl || (ignore != 0 && pl->GetGUID() == ignore) || (ignorePlayersInBGRaid && pl->GetGroup() != this))
1033  continue;
1034 
1035  if (pl->GetSession() && (group == -1 || itr->getSubGroup() == group))
1036  pl->GetSession()->SendPacket(packet);
1037  }
1038 }
1039 
1041 {
1042  for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
1043  {
1044  Player* pl = itr->GetSource();
1045  if (pl && pl->GetSession())
1046  if (IsLeader(pl->GetGUID()) || IsAssistant(pl->GetGUID()))
1047  pl->GetSession()->SendPacket(packet);
1048  }
1049 }
1050 
1052 {
1053  for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
1054  {
1055  Player* pl = sObjectMgr.GetPlayer(citr->guid, true);
1056  if (!pl || !pl->GetSession())
1057  {
1059  data << uint64(citr->guid);
1060  data << uint8(0);
1061  BroadcastReadyCheck(&data);
1062  }
1063  }
1064 }
1065 
1066 bool Group::_addMember(const uint64& guid, const char* name, bool isAssistant)
1067 {
1068  // get first not-full group
1069  uint8 groupid = 0;
1070  if (m_subGroupsCounts)
1071  {
1072  bool groupFound = false;
1073  for (; groupid < MAXRAIDSIZE / MAXGROUPSIZE; ++groupid)
1074  {
1075  if (m_subGroupsCounts[groupid] < MAXGROUPSIZE)
1076  {
1077  groupFound = true;
1078  break;
1079  }
1080  }
1081  // We are raid group and no one slot is free
1082  if (!groupFound)
1083  return false;
1084  }
1085 
1086  return _addMember(guid, name, isAssistant, groupid);
1087 }
1088 
1089 bool Group::_addMember(const uint64& guid, const char* name, bool isAssistant, uint8 group)
1090 {
1091  if (IsFull())
1092  return false;
1093 
1094  if (!guid)
1095  return false;
1096 
1097  Player* player = sObjectMgr.GetPlayer(guid, true);
1098 
1099  MemberSlot member;
1100  member.guid = guid;
1101  member.name = name;
1102  member.group = group;
1103  member.assistant = isAssistant;
1104  m_memberSlots.push_back(member);
1105 
1106  SubGroupCounterIncrease(group);
1107 
1108  if (player)
1109  {
1110  player->SetGroupInvite(NULL);
1111  // if player is in group and he is being added to BG raid group, then call SetBattlegroundRaid()
1112  if (player->GetGroup() && isBGGroup())
1113  player->SetBattlegroundRaid(this, group);
1114  // if player is in bg raid and we are adding him to normal group, then call SetOriginalGroup()
1115  else if (player->GetGroup())
1116  player->SetOriginalGroup(this, group);
1117  // if player is not in group, then call set group
1118  else
1119  player->SetGroup(this, group);
1120 
1121  if (player->IsInWorld())
1122  {
1123  // if the same group invites the player back, cancel the homebind timer
1124  InstanceGroupBind* bind = GetBoundInstance(player);
1125  if (bind && bind->save->GetInstanceId() == player->GetInstanceId())
1126  player->m_InstanceValid = true;
1127  }
1128  }
1129 
1130  if (!isRaidGroup()) // reset targetIcons for non-raid-groups
1131  {
1132  for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
1133  m_targetIcons[i] = 0;
1134  }
1135 
1136  if (!isBGGroup())
1137  {
1138  // insert into group table
1139  CharacterDatabase.PExecute("INSERT INTO group_member(leaderGuid,memberGuid,assistant,subgroup) VALUES('%u','%u','%u','%u')", GUID_LOPART(m_leaderGuid), GUID_LOPART(member.guid), ((member.assistant == 1) ? 1 : 0), member.group);
1140  }
1141 
1142  // ONCREATEGROUP HOOK
1143 
1144  return true;
1145 }
1146 
1147 bool Group::_removeMember(const uint64& guid)
1148 {
1149  Player* player = sObjectMgr.GetPlayer(guid, true);
1150  if (player)
1151  {
1152  // if we are removing player from battleground raid
1153  if (isBGGroup())
1154  player->RemoveFromBattlegroundRaid();
1155  else
1156  {
1157  // we can remove player who is in battleground from his original group
1158  if (player->GetOriginalGroup() == this)
1159  player->SetOriginalGroup(NULL);
1160  else
1161  player->SetGroup(NULL);
1162  }
1163  }
1164 
1165  _removeRolls(guid);
1166 
1167  member_witerator slot = _getMemberWSlot(guid);
1168  if (slot != m_memberSlots.end())
1169  {
1170  SubGroupCounterDecrease(slot->group);
1171 
1172  m_memberSlots.erase(slot);
1173  }
1174 
1175  if (!isBGGroup())
1176  CharacterDatabase.PExecute("DELETE FROM group_member WHERE memberGuid='%u'", GUID_LOPART(guid));
1177 
1178  if (m_leaderGuid == guid) // leader was removed
1179  {
1180  if (GetMembersCount() > 0)
1181  _setLeader(m_memberSlots.front().guid);
1182  return true;
1183  }
1184 
1185  return false;
1186 }
1187 
1188 void Group::_setLeader(const uint64& guid)
1189 {
1190  member_citerator slot = _getMemberCSlot(guid);
1191  if (slot == m_memberSlots.end())
1192  return;
1193 
1194  if (!isBGGroup())
1195  {
1196  // @todo set a time limit to have this function run rarely cause it can be slow
1198 
1199  // update the group's bound instances when changing leaders
1200 
1201  // remove all permanent binds from the group
1202  // in the DB also remove solo binds that will be replaced with permbinds
1203  // from the new leader
1205  "DELETE FROM group_instance WHERE leaderguid='%u' AND (permanent = 1 OR "
1206  "instance IN (SELECT instance FROM character_instance WHERE guid = '%u')"
1207  ")", GUID_LOPART(m_leaderGuid), GUID_LOPART(slot->guid)
1208  );
1209 
1210  Player* player = sObjectMgr.GetPlayer(slot->guid, true);
1211  if (player)
1212  {
1213  for (uint8 i = 0; i < TOTAL_DIFFICULTIES; i++)
1214  {
1215  for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end();)
1216  {
1217  if (itr->second.perm)
1218  {
1219  itr->second.save->RemoveGroup(this);
1220  m_boundInstances[i].erase(itr++);
1221  }
1222  else
1223  ++itr;
1224  }
1225  }
1226  }
1227 
1228  // update the group's solo binds to the new leader
1229  CharacterDatabase.PExecute("UPDATE group_instance SET leaderGuid='%u' WHERE leaderGuid = '%u'", GUID_LOPART(slot->guid), GUID_LOPART(m_leaderGuid));
1230 
1231  // copy the permanent binds from the new leader to the group
1232  // overwriting the solo binds with permanent ones if necessary
1233  // in the DB those have been deleted already
1234  Player::ConvertInstancesToGroup(player, this, slot->guid);
1235 
1236  // update the group leader
1237  CharacterDatabase.PExecute("UPDATE groups SET leaderGuid='%u' WHERE leaderGuid='%u'", GUID_LOPART(slot->guid), GUID_LOPART(m_leaderGuid));
1238  CharacterDatabase.PExecute("UPDATE group_member SET leaderGuid='%u' WHERE leaderGuid='%u'", GUID_LOPART(slot->guid), GUID_LOPART(m_leaderGuid));
1240  }
1241 
1242  m_leaderGuid = slot->guid;
1243  m_leaderName = slot->name;
1244 }
1245 
1246 void Group::_removeRolls(const uint64& guid)
1247 {
1248  for (Rolls::iterator it = RollId.begin(); it < RollId.end(); ++it)
1249  {
1250  Roll* roll = *it;
1251  Roll::PlayerVote::iterator itr2 = roll->playerVote.find(guid);
1252  if (itr2 == roll->playerVote.end())
1253  continue;
1254 
1255  if (itr2->second == ROLL_GREED)
1256  --roll->totalGreed;
1257  if (itr2->second == ROLL_NEED)
1258  --roll->totalNeed;
1259  if (itr2->second == ROLL_PASS)
1260  --roll->totalPass;
1261  if (itr2->second != ROLL_NOT_VALID)
1262  --roll->totalPlayersRolling;
1263 
1264  roll->playerVote.erase(itr2);
1265 
1266  CountRollVote(guid, roll->itemGUID, GetMembersCount() - 1, 3);
1267  }
1268 }
1269 
1270 bool Group::_setMembersGroup(const uint64& guid, const uint8& group)
1271 {
1272  member_witerator slot = _getMemberWSlot(guid);
1273  if (slot == m_memberSlots.end())
1274  return false;
1275 
1276  slot->group = group;
1277 
1278  SubGroupCounterIncrease(group);
1279 
1280  if (!isBGGroup()) CharacterDatabase.PExecute("UPDATE group_member SET subgroup='%u' WHERE memberGuid='%u'", group, GUID_LOPART(guid));
1281 
1282  return true;
1283 }
1284 
1285 bool Group::_setAssistantFlag(const uint64& guid, const bool& state)
1286 {
1287  member_witerator slot = _getMemberWSlot(guid);
1288  if (slot == m_memberSlots.end())
1289  return false;
1290 
1291  slot->assistant = state;
1292  if (!isBGGroup())
1293  CharacterDatabase.PExecute("UPDATE group_member SET assistant='%u' WHERE memberGuid='%u'", (state == true) ? 1 : 0, GUID_LOPART(guid));
1294  return true;
1295 }
1296 
1297 bool Group::_setMainTank(const uint64& guid)
1298 {
1299  member_citerator slot = _getMemberCSlot(guid);
1300  if (slot == m_memberSlots.end())
1301  return false;
1302 
1303  if (m_mainAssistant == guid)
1304  _setMainAssistant(0);
1305  m_mainTank = guid;
1306  if (!isBGGroup())
1307  CharacterDatabase.PExecute("UPDATE groups SET mainTank='%u' WHERE leaderGuid='%u'", GUID_LOPART(m_mainTank), GUID_LOPART(m_leaderGuid));
1308  return true;
1309 }
1310 
1312 {
1313  member_witerator slot = _getMemberWSlot(guid);
1314  if (slot == m_memberSlots.end())
1315  return false;
1316 
1317  if (m_mainTank == guid)
1318  _setMainTank(0);
1319  m_mainAssistant = guid;
1320  if (!isBGGroup())
1321  CharacterDatabase.PExecute("UPDATE groups SET mainAssistant='%u' WHERE leaderGuid='%u'", GUID_LOPART(m_mainAssistant), GUID_LOPART(m_leaderGuid));
1322  return true;
1323 }
1324 
1325 bool Group::SameSubGroup(Player const* member1, Player const* member2) const
1326 {
1327  if (!member1 || !member2) return false;
1328  if (member1->GetGroup() != this || member2->GetGroup() != this) return false;
1329  else return member1->GetSubGroup() == member2->GetSubGroup();
1330 }
1331 
1332 // allows setting subgroup for offline members
1333 void Group::ChangeMembersGroup(const uint64& guid, const uint8& group)
1334 {
1335  if (!isRaidGroup())
1336  return;
1337  Player* player = sObjectMgr.GetPlayer(guid, true);
1338 
1339  if (player)
1340  {
1341  uint8 prevSubGroup = player->GetSubGroup();
1342  if (player->GetGroup() == this)
1343  player->GetGroupRef().setSubGroup(group);
1344  // if player is in BG raid, it is possible that he is also in normal raid - and that normal raid is stored in m_originalGroup reference
1345  else
1346  {
1347  prevSubGroup = player->GetOriginalSubGroup();
1348  player->GetOriginalGroupRef().setSubGroup(group);
1349  }
1350 
1351  SubGroupCounterDecrease(prevSubGroup);
1352 
1353  if (_setMembersGroup(guid, group))
1354  SendUpdate();
1355  }
1356  else
1357  // This methods handles itself groupcounter decrease
1358  ChangeMembersGroup(player, group);
1359 }
1360 
1361 // only for online members
1362 void Group::ChangeMembersGroup(Player* player, const uint8& group)
1363 {
1364  if (!player || !isRaidGroup())
1365  return;
1366 
1367  if (_setMembersGroup(player->GetGUID(), group))
1368  {
1369  uint8 prevSubGroup;
1370  prevSubGroup = player->GetSubGroup();
1371 
1372  SubGroupCounterDecrease(prevSubGroup);
1373 
1374  player->GetGroupRef().setSubGroup(group);
1375  SendUpdate();
1376  }
1377 }
1378 
1379 void Group::UpdateLooterGuid(WorldObject* object, bool ifneed)
1380 {
1381  // round robin style looting applies for all low
1382  // quality items in each loot method except free for all
1383  if (GetLootMethod() == FREE_FOR_ALL)
1384  return;
1385 
1386  uint64 oldLooterGUID = GetLooterGuid();
1387  member_citerator guid_itr = _getMemberCSlot(oldLooterGUID);
1388  if (guid_itr != m_memberSlots.end())
1389  {
1390  if (ifneed)
1391  {
1392  // not update if only update if need and ok
1393  Player* looter = ObjectAccessor::FindPlayer(guid_itr->guid);
1394  if (looter && looter->IsWithinDistInMap(object, sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE), false))
1395  return;
1396  }
1397  ++guid_itr;
1398  }
1399 
1400  // search next after current
1401  Player* pNewLooter = NULL;
1402  for (member_citerator itr = guid_itr; itr != m_memberSlots.end(); ++itr)
1403  {
1404  if (Player* player = ObjectAccessor::FindPlayer(itr->guid))
1405  if (player->IsWithinDistInMap(object, sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE), false))
1406  {
1407  pNewLooter = player;
1408  break;
1409  }
1410  }
1411 
1412  if (!pNewLooter)
1413  {
1414  // search from start
1415  for (member_citerator itr = m_memberSlots.begin(); itr != guid_itr; ++itr)
1416  {
1417  if (Player* player = ObjectAccessor::FindPlayer(itr->guid))
1418  if (player->IsWithinDistInMap(object, sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE), false))
1419  {
1420  pNewLooter = player;
1421  break;
1422  }
1423  }
1424  }
1425 
1426  if (pNewLooter)
1427  {
1428  if (oldLooterGUID != pNewLooter->GetGUID())
1429  {
1430  SetLooterGuid(pNewLooter->GetGUID());
1431  SendUpdate();
1432  }
1433  }
1434  else
1435  {
1436  SetLooterGuid(0);
1437  SendUpdate();
1438  }
1439 }
1440 
1441 uint32 Group::CanJoinBattlegroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot)
1442 {
1443  // check for min / max count
1444  uint32 memberscount = GetMembersCount();
1445  if (memberscount < MinPlayerCount)
1447  if (memberscount > MaxPlayerCount)
1449 
1450  // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.)
1451  Player* reference = GetFirstMember()->GetSource();
1452  // no reference found, can't join this way
1453  if (!reference)
1455 
1456  uint32 bgQueueId = reference->GetBattlegroundQueueIdFromLevel();
1457  uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot);
1458  uint32 team = reference->GetTeam();
1459 
1460  // check every member of the group to be able to join
1461  for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
1462  {
1463  Player* member = itr->GetSource();
1464  // offline member? don't let join
1465  if (!member)
1467  // don't allow cross-faction join as group
1468  if (member->GetTeam() != team)
1470  // not in the same battleground level braket, don't let join
1471  if (member->GetBattlegroundQueueIdFromLevel() != bgQueueId)
1472  return BG_JOIN_ERR_MIXED_LEVELS;
1473  // don't let join rated matches if the arena team id doesn't match
1474  if (isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId)
1476  // don't let join if someone from the group is already in that bg queue
1477  if (member->InBattlegroundQueueForBattlegroundQueueType(bgQueueType))
1479  // check for deserter debuff in case not arena queue
1480  if (bgTypeId != BATTLEGROUND_AA && !member->CanJoinToBattleground())
1482  // check if member can join any more battleground queues
1483  if (!member->HasFreeBattlegroundQueueId())
1485  }
1486  return BG_JOIN_ERR_OK;
1487 }
1488 
1489 //===================================================
1490 //============== Roll ===============================
1491 //===================================================
1492 
1494 {
1495  // called from link()
1496  getTarget()->addLootValidatorRef(this);
1497 }
1498 
1500 {
1501  m_difficulty = difficulty;
1502  if (!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE leaderGuid ='%u'", m_difficulty, GUID_LOPART(m_leaderGuid));
1503 
1504  for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
1505  {
1506  Player* player = itr->GetSource();
1507  if (!player->GetSession() || player->getLevel() < LEVELREQUIREMENT_HEROIC)
1508  continue;
1509  player->SetDifficulty(difficulty);
1510  player->SendDungeonDifficulty(true);
1511  }
1512 }
1513 
1515 {
1516  for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
1517  {
1518  Player* pPlayer = itr->GetSource();
1519  if (pPlayer && pPlayer->getAttackers().size() && pPlayer->GetInstanceId() == instanceId && (pPlayer->GetMap()->IsRaid() || pPlayer->GetMap()->IsHeroic()))
1520  for (std::set<Unit*>::const_iterator i = pPlayer->getAttackers().begin(); i != pPlayer->getAttackers().end(); ++i)
1521  if ((*i) && (*i)->GetTypeId() == TYPEID_UNIT && (*i)->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
1522  return true;
1523  }
1524  return false;
1525 }
1526 
1527 void Group::ResetInstances(uint8 method, Player* SendMsgTo)
1528 {
1529  if (isBGGroup())
1530  return;
1531 
1532  // method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_DISBAND
1533 
1534  // we assume that when the difficulty changes, all instances that can be reset will be
1535  uint8 diff = GetDifficulty();
1536 
1537  for (BoundInstancesMap::iterator itr = m_boundInstances[diff].begin(); itr != m_boundInstances[diff].end();)
1538  {
1539  InstanceSave* p = itr->second.save;
1540  const MapEntry* entry = sMapStore.LookupEntry(itr->first);
1541  if (!entry || (!p->CanReset() && method != INSTANCE_RESET_GROUP_DISBAND))
1542  {
1543  ++itr;
1544  continue;
1545  }
1546 
1547  if (method == INSTANCE_RESET_ALL)
1548  {
1549  // the "reset all instances" method can only reset normal maps
1550  if (diff == DIFFICULTY_HEROIC || entry->IsRaid())
1551  {
1552  ++itr;
1553  continue;
1554  }
1555  }
1556 
1557  bool isEmpty = true;
1558  // if the map is loaded, reset it
1559  Map* map = MapManager::Instance().FindMap(p->GetMapId(), p->GetInstanceId());
1560  if (map && map->IsDungeon())
1561  {
1562  if (p->CanReset())
1563  isEmpty = ((InstanceMap*)map)->Reset(method);
1564  else
1565  isEmpty = !map->HavePlayers();
1566  }
1567 
1568  if (SendMsgTo)
1569  {
1570  if (isEmpty) SendMsgTo->SendResetInstanceSuccess(p->GetMapId());
1571  else SendMsgTo->SendResetInstanceFailed(0, p->GetMapId());
1572  }
1573 
1574  if (isEmpty || method == INSTANCE_RESET_GROUP_DISBAND || method == INSTANCE_RESET_CHANGE_DIFFICULTY)
1575  {
1576  // do not reset the instance, just unbind if others are permanently bound to it
1577  if (p->CanReset()) p->DeleteFromDB();
1578  else CharacterDatabase.PExecute("DELETE FROM group_instance WHERE instance = '%u'", p->GetInstanceId());
1579  // i don't know for sure if hash_map iterators
1580  m_boundInstances[diff].erase(itr);
1581  itr = m_boundInstances[diff].begin();
1582  // this unloads the instance save unless online players are bound to it
1583  // (eg. permanent binds or GM solo binds)
1584  p->RemoveGroup(this);
1585  }
1586  else
1587  ++itr;
1588  }
1589 }
1590 
1592 {
1593  uint32 mapid = player->GetMapId();
1594  MapEntry const* mapEntry = sMapStore.LookupEntry(mapid);
1595  return GetBoundInstance(mapEntry);
1596 }
1597 
1599 {
1600  // Currently spawn numbering not different from map difficulty
1601  DungeonDifficulty difficulty = GetDifficulty();
1602  return GetBoundInstance(difficulty, aMap->GetId());
1603 }
1604 
1606 {
1607  if (!mapEntry || !mapEntry->IsDungeon())
1608  return NULL;
1609 
1610  DungeonDifficulty difficulty = GetDifficulty();
1611  return GetBoundInstance(difficulty, mapEntry->MapID);
1612 }
1613 
1615 {
1616  BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(mapId);
1617  if (itr != m_boundInstances[difficulty].end())
1618  return &itr->second;
1619  else
1620  return NULL;
1621 }
1622 
1624 {
1625  return m_boundInstances[difficulty];
1626 }
1627 
1628 InstanceGroupBind* Group::BindToInstance(InstanceSave* save, bool permanent, bool load)
1629 {
1630  if (save && !isBGGroup())
1631  {
1632  InstanceGroupBind& bind = m_boundInstances[save->GetDifficulty()][save->GetMapId()];
1633  if (bind.save)
1634  {
1635  // when a boss is killed or when copying the player's binds to the group
1636  if (permanent != bind.perm || save != bind.save)
1637  if (!load) CharacterDatabase.PExecute("UPDATE group_instance SET instance = '%u', permanent = '%u' WHERE leaderGuid = '%u' AND instance = '%u'", save->GetInstanceId(), permanent, GUID_LOPART(GetLeaderGUID()), bind.save->GetInstanceId());
1638  }
1639  else if (!load) CharacterDatabase.PExecute("INSERT INTO group_instance (leaderGuid, instance, permanent) VALUES ('%u', '%u', '%u')", GUID_LOPART(GetLeaderGUID()), save->GetInstanceId(), permanent);
1640 
1641  if (bind.save != save)
1642  {
1643  if (bind.save) bind.save->RemoveGroup(this);
1644  save->AddGroup(this);
1645  }
1646 
1647  bind.save = save;
1648  bind.perm = permanent;
1649  if (!load) sLog.outDebug("Group::BindToInstance: %d is now bound to map %d, instance %d, difficulty %d", GUID_LOPART(GetLeaderGUID()), save->GetMapId(), save->GetInstanceId(), save->GetDifficulty());
1650  return &bind;
1651  }
1652  else
1653  return NULL;
1654 }
1655 
1656 void Group::UnbindInstance(uint32 mapid, uint8 difficulty, bool unload)
1657 {
1658  BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(mapid);
1659  if (itr != m_boundInstances[difficulty].end())
1660  {
1661  if (!unload)
1662  CharacterDatabase.PExecute("DELETE FROM group_instance WHERE leaderGuid = '%u' AND instance = '%u'", GUID_LOPART(GetLeaderGUID()), itr->second.save->GetInstanceId());
1663  itr->second.save->RemoveGroup(this); // save can become invalid
1664  m_boundInstances[difficulty].erase(itr);
1665  }
1666 }
1667 
1669 {
1670  if (player && !player->IsGameMaster() && sMapStore.LookupEntry(player->GetMapId())->IsDungeon())
1671  {
1672  // leaving the group in an instance, the homebind timer is started
1673  // unless the player is permanently saved to the instance
1674  InstanceSave* save = sInstanceSaveMgr.GetInstanceSave(player->GetInstanceId());
1675  InstancePlayerBind* playerBind = save ? player->GetBoundInstance(save->GetMapId(), save->GetDifficulty()) : NULL;
1676  if (!playerBind || !playerBind->perm)
1677  player->m_InstanceValid = false;
1678  }
1679 }
1680 
1682 {
1683  // FG: HACK: force flags update on group leave - for values update hack
1684  // -- not very efficient but safe
1685  for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
1686  {
1687  if (Player* pp = sObjectMgr.GetPlayer(citr->guid))
1688  {
1689  pp->ForceValuesUpdateAtIndex(UNIT_FIELD_HEALTH);
1690  pp->ForceValuesUpdateAtIndex(UNIT_FIELD_MAXHEALTH);
1691  pp->ForceValuesUpdateAtIndex(UNIT_FIELD_BYTES_2);
1692  pp->ForceValuesUpdateAtIndex(UNIT_FIELD_FACTIONTEMPLATE);
1693 
1694  if (Pet* pet = pp->GetPet())
1695  {
1696  pet->ForceValuesUpdateAtIndex(UNIT_FIELD_HEALTH);
1697  pet->ForceValuesUpdateAtIndex(UNIT_FIELD_MAXHEALTH);
1698  pet->ForceValuesUpdateAtIndex(UNIT_FIELD_BYTES_2);
1699  pet->ForceValuesUpdateAtIndex(UNIT_FIELD_FACTIONTEMPLATE);
1700  }
1701 
1702  DEBUG_LOG("-- Forced group value update for '%s'", pp->GetName());
1703  }
1704  }
1705 }
1706 
InstanceSave * save
Definition: Group.h:145
void SetLooterGuid(const uint64 &guid)
Definition: Group.h:193
uint8 GetSubGroup() const
Definition: Player.h:2602
bool _setAssistantFlag(const uint64 &guid, const bool &state)
Definition: Group.cpp:1285
Group * GetGroup()
Definition: Player.h:2589
void SetTargetIcon(uint8 id, uint64 guid)
Definition: Group.cpp:884
uint64 itemGUID
Definition: Group.h:130
bool SameSubGroup(uint64 guid1, const uint64 &guid2) const
Definition: Group.h:275
#define GUID_LOPART(x)
Definition: ObjectGuid.h:110
MemberSlotList::iterator member_witerator
Definition: Group.h:169
void _initRaidSubGroupsCounter()
Definition: Group.h:451
MemberSlotList::const_iterator member_citerator
Definition: Group.h:165
uint32 MapID
Definition: DBCStructure.h:514
Map * GetMap() const
Definition: Object.h:829
void GroupLoot(const uint64 &playerGUID, Loot *loot, WorldObject *object)
Definition: Group.cpp:562
member_witerator _getMemberWSlot(uint64 Guid)
Definition: Group.h:473
void SetGroupInvite(Group *group)
Definition: Player.h:2585
Rolls RollId
Definition: Group.h:521
uint8 totalPlayersRolling
Definition: Group.h:136
InstanceGroupBind * BindToInstance(InstanceSave *save, bool permanent, bool load=false)
Definition: Group.cpp:1628
bool BeginTransaction()
Definition: Database.cpp:533
DungeonDifficulty GetDifficulty()
uint32 itemRandomSuffix
Definition: Group.h:133
void BroadcastReadyCheck(WorldPacket *packet)
Definition: Group.cpp:1040
bool IsRaid() const
Definition: Map.h:431
InvitesList m_invitees
Definition: Group.h:508
QueryResult_AutoPtr PQuery(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:400
void SendLootRoll(const uint64 &SourceGuid, const uint64 &TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r)
Definition: Group.cpp:474
GroupReference & GetGroupRef()
Definition: Player.h:2597
bool isRaidGroup() const
Definition: Group.h:210
void RemoveAllInvites()
Definition: Group.cpp:254
PlayerVote playerVote
Definition: Group.h:135
void BroadcastGroupUpdate(void)
Definition: Group.cpp:1681
void SetBgRaid(uint32 TeamID, Group *bg_raid)
Definition: Battleground.h:599
void _homebindIfInstance(Player *player)
Definition: Group.cpp:1668
uint32 GetGroupUpdateFlag()
Definition: Player.h:2606
bool InBattlegroundQueueForBattlegroundQueueType(uint32 bgQueueType) const
Definition: Player.h:2248
void MasterLoot(const uint64 &playerGUID, Loot *loot, WorldObject *object)
Definition: Group.cpp:672
uint8 * m_subGroupsCounts
Definition: Group.h:523
void BroadcastPacket(WorldPacket *packet, bool ignorePlayersInBGRaid, int group=-1, uint64 ignore=0)
Definition: Group.cpp:1027
void SendLootAllPassed(uint32 NumberOfPlayers, const Roll &r)
Definition: Group.cpp:521
uint32 GetGrayLevel(uint32 pl_level)
Definition: Formulas.h:36
Loot loot
Definition: Creature.h:662
void SendDungeonDifficulty(bool IsInGroup)
Definition: Player.cpp:16958
bool _setMembersGroup(const uint64 &guid, const uint8 &group)
Definition: Group.cpp:1270
#define sLog
Log class singleton.
Definition: Log.h:187
void ChangeLeader(const uint64 &guid)
Definition: Group.cpp:363
bool is_blocked
Definition: LootMgr.h:132
uint32 GetMapId()
LootMethod m_lootMethod
Definition: Group.h:517
uint32 itemid
Definition: Group.h:131
bool CanJoinToBattleground() const
Definition: Player.cpp:18631
bool IsDungeon() const
Definition: Map.h:427
bool IsAssistant(uint64 guid) const
Definition: Group.h:264
void ChangeMembersGroup(const uint64 &guid, const uint8 &group)
Definition: Group.cpp:1333
uint64 m_masterLooterGuid
Definition: Group.h:520
void Initialize(uint16 opcode, size_t newres=200)
Definition: WorldPacket.h:37
bool IsAtGroupRewardDistance(WorldObject const *pRewardSource) const
Definition: Player.cpp:19908
bool IsGameMaster() const
Definition: Player.h:1009
Item * StoreNewItem(ItemPosCountVec const &pos, uint32 item, bool update, int32 randomPropertyId=0)
Definition: Player.cpp:10277
#define TARGETICONCOUNT
Definition: Group.h:30
void SetDifficulty(DungeonDifficulty difficulty)
Definition: Group.cpp:1499
int32 itemRandomPropId
Definition: Group.h:132
void SendLootStartRoll(uint32 CountDown, const Roll &r)
Definition: Group.cpp:453
uint64 m_looterGuid
Definition: Group.h:519
DungeonDifficulty GetDifficulty()
Definition: Player.h:1884
bool is_looted
Definition: LootMgr.h:131
DungeonDifficulty
#define sObjectMgr
Definition: ObjectMgr.h:1285
uint64 m_mainAssistant
Definition: Group.h:512
void SendPacket(WorldPacket const *packet)
uint32 CanJoinBattlegroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot)
Definition: Group.cpp:1441
bool CommitTransaction()
Definition: Database.cpp:551
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
uint64 m_mainTank
Definition: Group.h:511
Definition: Group.h:113
Battleground * m_bgGroup
Definition: Group.h:515
member_citerator _getMemberCSlot(uint64 Guid) const
Definition: Group.h:463
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true) const
Definition: Object.h:762
void NotifyItemRemoved(uint8 lootIndex)
Definition: LootMgr.cpp:534
float GetDistance2d(const WorldObject *obj) const
Definition: Object.h:721
uint8 CanStoreNewItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, uint32 item, uint32 count, uint32 *no_space_count=NULL) const
Definition: Player.h:1147
uint64 m_targetIcons[TARGETICONCOUNT]
Definition: Group.h:516
void UpdatePlayerOutOfRange(Player *pPlayer)
Definition: Group.cpp:1007
void AddGroup(Group *group)
int32 randomPropertyId
Definition: LootMgr.h:128
bool AddMember(const uint64 &guid, const char *name)
Definition: Group.cpp:282
uint8 totalNeed
Definition: Group.h:137
void BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data)
GroupType
Definition: Group.h:57
uint32 GetId(void) const
Definition: Map.h:333
void SendResetInstanceFailed(uint32 reason, uint32 MapId)
Definition: Player.cpp:17031
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true) const
Definition: Object.h:758
bool IsFull() const
Definition: Group.h:206
void UpdateLooterGuid(WorldObject *object, bool ifneed=false)
Definition: Group.cpp:1379
MemberSlotList m_memberSlots
Definition: Group.h:506
void SetOriginalGroup(Group *group, int8 subgroup=-1)
Definition: Player.cpp:20199
BoundInstancesMap m_boundInstances[TOTAL_DIFFICULTIES]
Definition: Group.h:522
void CountRollVote(const uint64 &playerGUID, const uint64 &Guid, uint32 NumberOfPlayers, uint8 Choise)
Definition: Group.cpp:719
void RemoveFromBattlegroundRaid()
Definition: Player.cpp:20187
ACE_UINT8 uint8
Definition: Define.h:73
uint32 GetInstanceId()
void ResetInstances(uint8 method)
Definition: Player.cpp:16976
void setSubGroup(uint8 pSubGroup)
#define UI64FMTD
Definition: Common.h:149
AttackerSet const & getAttackers() const
Definition: Unit.h:980
Definition: Unit.h:297
const bool & IsInWorld() const
Definition: Object.h:129
bool IsLeader(const uint64 &guid) const
Definition: Group.h:251
bool _removeMember(const uint64 &guid)
Definition: Group.cpp:1147
void targetObjectBuildLink() override
Definition: Group.cpp:1493
uint64 GetMasterLooterGuid() const
Definition: Group.h:240
Group * GetGroupInvite()
Definition: Player.h:2581
uint8 unlootedCount
Definition: LootMgr.h:310
bool IsHeroic() const
Definition: Map.h:435
void SendLootRollWon(const uint64 &SourceGuid, const uint64 &TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r)
Definition: Group.cpp:498
GroupFlagMask GetFlags(MemberSlot const &slot) const
Definition: Group.h:495
bool _setMainAssistant(const uint64 &guid)
Definition: Group.cpp:1311
uint32 RemoveMember(const uint64 &guid, const RemoveMethod &method=GROUP_REMOVEMETHOD_DEFAULT, uint64 kicker=0, const char *reason=NULL)
Definition: Group.cpp:311
void SendResetInstanceSuccess(uint32 MapId)
Definition: Player.cpp:17024
Definition: LootMgr.h:290
bool IsAlive() const
Definition: Unit.h:1433
void SetBattlegroundRaid(Group *group, int8 subgroup=-1)
Definition: Player.cpp:20177
Rolls::iterator GetRoll(uint64 Guid)
Definition: Group.h:405
void SetDifficulty(DungeonDifficulty dungeon_difficulty)
Definition: Player.h:1880
void NeedBeforeGreed(const uint64 &playerGUID, Loot *loot, WorldObject *object)
Definition: Group.cpp:620
#define MAKE_NEW_GUID(l, e, h)
Definition: ObjectGuid.h:80
static Player * FindPlayer(uint64, bool force=false)
void OfflineReadyCheck()
Definition: Group.cpp:1051
uint32 GetInstanceId() const
Definition: Object.h:682
~Group()
Definition: Group.cpp:52
UNORDERED_MAP< uint32, InstanceGroupBind > BoundInstancesMap
Definition: Group.h:167
void SendEquipError(uint8 msg, Item *pItem, Item *pItem2)
Definition: Player.cpp:11571
bool LoadGroupFromDB(const uint64 &leaderGuid, QueryResult_AutoPtr result=QueryResult_AutoPtr(NULL), bool loadMembers=true)
Definition: Group.cpp:130
bool isBGGroup() const
Definition: Group.h:214
void SendTargetIconList(WorldSession *session)
Definition: Group.cpp:929
PackedGuid const & GetPackGUID() const
Definition: Object.h:172
#define DEBUG_LOG(...)
Definition: Log.h:194
bool m_InstanceValid
Definition: Player.h:2555
bool IsDungeon() const
Definition: DBCStructure.h:550
void ScheduleDelayedOperation(uint32 operation)
Definition: Player.h:2689
InstancePlayerBind * GetBoundInstance(uint32 mapid, uint8 difficulty)
Definition: Player.cpp:15838
uint32 GetMapId() const
Definition: Object.h:585
bool assistant
Definition: Group.h:162
DungeonDifficulty GetDifficulty()
Definition: Group.h:361
void SubGroupCounterDecrease(uint8 subgroup)
Definition: Group.h:489
bool HavePlayers() const
Definition: Map.h:472
GroupReference * GetFirstMember()
Definition: Group.h:304
bool IsInMap(const WorldObject *obj) const
Definition: Object.h:733
std::string name
Definition: Group.h:160
bool PExecute(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:441
Definition: Map.h:266
void SetGroup(Group *group, int8 subgroup=-1)
Definition: Player.cpp:18969
Map * FindMap(uint32 mapid, uint32 instanceId=0) const
Definition: MapManager.cpp:137
uint32 RemoveInvite(Player *player)
Definition: Group.cpp:246
GroupReference * next()
void SendLooter(Creature *creature, Player *pLooter)
Definition: Group.cpp:542
bool IsRaid() const
Definition: DBCStructure.h:558
#define sInstanceSaveMgr
void UnbindInstance(uint32 mapid, uint8 difficulty, bool unload=false)
Definition: Group.cpp:1656
bool _setMainTank(const uint64 &guid)
Definition: Group.cpp:1297
GroupReference & GetOriginalGroupRef()
Definition: Player.h:2636
GroupType m_groupType
Definition: Group.h:513
bool LoadMemberFromDB(uint32 guidLow, uint8 subgroup, bool assistant)
Definition: Group.cpp:184
uint64 guid
Definition: Group.h:159
const char * GetName() const
Definition: Object.h:692
std::vector< ItemPosCount > ItemPosCountVec
Definition: Player.h:605
ACE_UINT64 uint64
Definition: Define.h:70
ItemQualities
uint8 GetOriginalSubGroup() const
Definition: Player.h:2640
const uint64 & GetLeaderGUID() const
Definition: Group.h:222
uint32 GetArenaTeamId(uint8 slot)
Definition: Player.h:1862
Group * GetOriginalGroup()
Definition: Player.h:2632
std::vector< LootItem > items
Definition: LootMgr.h:307
#define MAXRAIDSIZE
Definition: Group.h:29
uint64 m_leaderGuid
Definition: Group.h:509
void Disband(bool hideDestroy=false)
Definition: Group.cpp:383
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
Definition: QueryResult.h:113
void EndRoll()
Definition: Group.cpp:761
Loot * getLoot()
Definition: Group.h:124
FROM * GetSource() const
Definition: Reference.h:92
bool Create(const uint64 &guid, const char *name)
Definition: Group.cpp:82
DungeonDifficulty m_difficulty
Definition: Group.h:514
uint32 GetMembersCount() const
Definition: Group.h:309
void GetDataForXPAtKill(Unit const *victim, uint32 &count, uint32 &sum_level, Player *&member_with_max_level, Player *&not_gray_member_with_max_level)
Definition: Group.cpp:904
bool HasFreeBattlegroundQueueId()
Definition: Player.h:2270
Player * GetInvited(const uint64 &guid) const
Definition: Group.cpp:262
LootMethod
Definition: LootMgr.h:34
#define MAXGROUPSIZE
Definition: Group.h:28
ItemQualities m_lootThreshold
Definition: Group.h:518
uint32 GetTeam() const
Definition: Player.h:2075
bool hasOverThresholdItem() const
Definition: LootMgr.cpp:740
#define ASSERT
Definition: Errors.h:33
LootMethod GetLootMethod() const
Definition: Group.h:230
void _setLeader(const uint64 &guid)
Definition: Group.cpp:1188
void _removeRolls(const uint64 &guid)
Definition: Group.cpp:1246
bool InCombatToInstance(uint32 instanceId)
Definition: Group.cpp:1514
#define sScriptMgr
Definition: Group.h:526
void SetGroupUpdateFlag(uint32 flag)
Definition: Player.h:2610
void ConvertToRaid()
Definition: Group.cpp:203
bool isValid() const
Definition: Reference.h:74
void SubGroupCounterIncrease(uint8 subgroup)
Definition: Group.h:483
Group()
Definition: Group.cpp:34
WorldSession * GetSession() const
Definition: Player.h:1959
#define sWorld
Definition: World.h:860
uint8 count
Definition: LootMgr.h:130
uint8 CanUseItem(Item *pItem, bool not_loading=true) const
Definition: Player.cpp:10128
InstanceGroupBind * GetBoundInstance(Player *player)
Definition: Group.cpp:1591
DatabaseType CharacterDatabase
Accessor to the character database.
Definition: Main.cpp:54
bool _addMember(const uint64 &guid, const char *name, bool isAssistant=false)
Definition: Group.cpp:1066
bool AddLeaderInvite(Player *player)
Definition: Group.cpp:236
ACE_UINT32 uint32
Definition: Define.h:71
bool RemoveGroup(Group *group)
uint32 GetBattlegroundQueueIdFromLevel() const
Definition: Player.cpp:19436
static void ConvertInstancesToGroup(Player *player, Group *group=NULL, uint64 player_guid=0)
Definition: Player.cpp:15989
void CountTheRoll(Rolls::iterator roll, uint32 NumberOfPlayers)
Definition: Group.cpp:772
Definition: Unit.h:884
std::string m_leaderName
Definition: Group.h:510
uint32 getLevel() const
Definition: Unit.h:1029
uint8 itemSlot
Definition: Group.h:140
void ResetInstances(uint8 method, Player *SendMsgTo)
Definition: Group.cpp:1527
bool AddInvite(Player *player, bool leader)
Definition: Group.cpp:214
Definition: Player.h:922
RemoveMethod
Definition: Group.h:98
const uint64 GetLooterGuid() const
Definition: Group.h:234
float GetSightRange(const WorldObject *target=NULL) const
Definition: Object.cpp:1557
std::vector< LootItem > quest_items
Definition: LootMgr.h:308
uint8 totalPass
Definition: Group.h:139
void SendUpdate()
Definition: Group.cpp:949
Definition: Pet.h:146
Group * GetBgRaid(uint32 TeamID) const
Definition: Battleground.h:595
Definition: Group.h:154
BoundInstancesMap & GetBoundInstances(DungeonDifficulty difficulty)
Definition: Group.cpp:1623
uint32 urand(uint32 min, uint32 max)
Definition: Util.cpp:71
const uint64 & GetGUID() const
Definition: Object.h:156
uint8 totalGreed
Definition: Group.h:138