2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #ifndef MANGOSSERVER_GROUP_H
20 #define MANGOSSERVER_GROUP_H
22 #include "GroupReference.h"
23 #include "GroupRefManager.h"
24 #include "BattleGround.h"
31 #define MAX_GROUP_SIZE 5
32 #define MAX_RAID_SIZE 40
33 #define MAX_RAID_SUBGROUPS (MAX_RAID_SIZE / MAX_GROUP_SIZE)
34 #define TARGET_ICON_COUNT 8
45 #define ALL_ROLL_VOTE_MASK 0x0F // set what votes allowed
54 // other not send by client
55 MAX_ROLL_FROM_CLIENT
= 4,
57 ROLL_NOT_EMITED_YET
= 4, // send to client
58 ROLL_NOT_VALID
= 5 // not send to client
61 enum GroupMemberOnlineStatus
63 MEMBER_STATUS_OFFLINE
= 0x0000,
64 MEMBER_STATUS_ONLINE
= 0x0001,
65 MEMBER_STATUS_PVP
= 0x0002,
66 MEMBER_STATUS_UNK0
= 0x0004, // dead? (health=0)
67 MEMBER_STATUS_UNK1
= 0x0008, // ghost? (health=1)
68 MEMBER_STATUS_UNK2
= 0x0010, // never seen
69 MEMBER_STATUS_UNK3
= 0x0020, // never seen
70 MEMBER_STATUS_UNK4
= 0x0040, // appears with dead and ghost flags
71 MEMBER_STATUS_UNK5
= 0x0080, // never seen
74 enum GroupType
// group type flags?
76 GROUPTYPE_NORMAL
= 0x00,
78 GROUPTYPE_RAID
= 0x02,
79 GROUPTYPE_BGRAID
= GROUPTYPE_BG
| GROUPTYPE_RAID
, // mask
82 // 0x10, leave/change group?, I saw this flag when leaving group and after leaving BG while in group
87 GROUP_ASSISTANT
= 0x01,
88 GROUP_MAIN_ASSISTANT
= 0x02,
89 GROUP_MAIN_TANK
= 0x04,
96 GROUP_UPDATE_FLAG_NONE
= 0x00000000, // nothing
97 GROUP_UPDATE_FLAG_STATUS
= 0x00000001, // uint16, flags
98 GROUP_UPDATE_FLAG_CUR_HP
= 0x00000002, // uint32
99 GROUP_UPDATE_FLAG_MAX_HP
= 0x00000004, // uint32
100 GROUP_UPDATE_FLAG_POWER_TYPE
= 0x00000008, // uint8
101 GROUP_UPDATE_FLAG_CUR_POWER
= 0x00000010, // uint16
102 GROUP_UPDATE_FLAG_MAX_POWER
= 0x00000020, // uint16
103 GROUP_UPDATE_FLAG_LEVEL
= 0x00000040, // uint16
104 GROUP_UPDATE_FLAG_ZONE
= 0x00000080, // uint16
105 GROUP_UPDATE_FLAG_POSITION
= 0x00000100, // uint16, uint16
106 GROUP_UPDATE_FLAG_AURAS
= 0x00000200, // uint64 mask, for each bit set uint32 spellid + uint8 unk
107 GROUP_UPDATE_FLAG_PET_GUID
= 0x00000400, // uint64 pet guid
108 GROUP_UPDATE_FLAG_PET_NAME
= 0x00000800, // pet name, NULL terminated string
109 GROUP_UPDATE_FLAG_PET_MODEL_ID
= 0x00001000, // uint16, model id
110 GROUP_UPDATE_FLAG_PET_CUR_HP
= 0x00002000, // uint32 pet cur health
111 GROUP_UPDATE_FLAG_PET_MAX_HP
= 0x00004000, // uint32 pet max health
112 GROUP_UPDATE_FLAG_PET_POWER_TYPE
= 0x00008000, // uint8 pet power type
113 GROUP_UPDATE_FLAG_PET_CUR_POWER
= 0x00010000, // uint16 pet cur power
114 GROUP_UPDATE_FLAG_PET_MAX_POWER
= 0x00020000, // uint16 pet max power
115 GROUP_UPDATE_FLAG_PET_AURAS
= 0x00040000, // uint64 mask, for each bit set uint32 spellid + uint8 unk, pet auras...
116 GROUP_UPDATE_FLAG_VEHICLE_SEAT
= 0x00080000, // uint32 vehicle_seat_id (index from VehicleSeat.dbc)
117 GROUP_UPDATE_PET
= 0x0007FC00, // all pet flags
118 GROUP_UPDATE_FULL
= 0x0007FFFF, // all known flags
121 #define GROUP_UPDATE_FLAGS_COUNT 20
122 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,16,17,18,19
123 static const uint8 GroupUpdateLength
[GROUP_UPDATE_FLAGS_COUNT
] = { 0, 2, 2, 2, 1, 2, 2, 2, 2, 4, 8, 8, 1, 2, 2, 2, 1, 2, 2, 8};
127 class Roll
: public LootValidatorRef
130 Roll(ObjectGuid _lootedTragetGuid
, LootItem
const& li
)
131 : lootedTargetGUID(_lootedTragetGuid
), itemid(li
.itemid
), itemRandomPropId(li
.randomPropertyId
), itemRandomSuffix(li
.randomSuffix
),
132 itemCount(li
.count
), totalPlayersRolling(0), totalNeed(0), totalGreed(0), totalPass(0), itemSlot(0) {}
134 void setLoot(Loot
*pLoot
) { link(pLoot
, this); }
135 Loot
*getLoot() { return getTarget(); }
136 void targetObjectBuildLink();
138 ObjectGuid lootedTargetGUID
;
140 int32 itemRandomPropId
;
141 uint32 itemRandomSuffix
;
143 typedef std::map
<uint64
, RollVote
> PlayerVote
;
144 PlayerVote playerVote
; //vote position correspond with player position (in group)
145 uint8 totalPlayersRolling
;
152 struct InstanceGroupBind
156 /* permanent InstanceGroupBinds exist iff the leader has a permanent
157 PlayerInstanceBind for the same instance. */
158 InstanceGroupBind() : save(NULL
), perm(false) {}
161 /** request member stats checken **/
162 /** todo: uninvite people that not accepted invite **/
163 class MANGOS_DLL_SPEC Group
173 typedef std::list
<MemberSlot
> MemberSlotList
;
174 typedef MemberSlotList::const_iterator member_citerator
;
176 typedef UNORDERED_MAP
< uint32
/*mapId*/, InstanceGroupBind
> BoundInstancesMap
;
178 typedef MemberSlotList::iterator member_witerator
;
179 typedef std::set
<Player
*> InvitesList
;
181 typedef std::vector
<Roll
*> Rolls
;
187 // group manipulation methods
188 bool Create(const uint64
&guid
, const char * name
);
189 bool LoadGroupFromDB(Field
*fields
);
190 bool LoadMemberFromDB(uint32 guidLow
, uint8 subgroup
, bool assistant
);
191 bool AddInvite(Player
*player
);
192 uint32
RemoveInvite(Player
*player
);
193 void RemoveAllInvites();
194 bool AddLeaderInvite(Player
*player
);
195 bool AddMember(const uint64
&guid
, const char* name
);
196 // method: 0=just remove, 1=kick
197 uint32
RemoveMember(const uint64
&guid
, const uint8
&method
);
198 void ChangeLeader(const uint64
&guid
);
199 void SetLootMethod(LootMethod method
) { m_lootMethod
= method
; }
200 void SetLooterGuid(const uint64
&guid
) { m_looterGuid
= guid
; }
201 void UpdateLooterGuid( Creature
* creature
, bool ifneed
= false );
202 void SetLootThreshold(ItemQualities threshold
) { m_lootThreshold
= threshold
; }
203 void Disband(bool hideDestroy
=false);
205 // properties accessories
206 uint32
GetId() const { return m_Id
; }
207 bool IsFull() const { return (m_groupType
== GROUPTYPE_NORMAL
) ? (m_memberSlots
.size() >= MAX_GROUP_SIZE
) : (m_memberSlots
.size() >= MAX_RAID_SIZE
); }
208 bool isRaidGroup() const { return m_groupType
& GROUPTYPE_RAID
; }
209 bool isBGGroup() const { return m_bgGroup
!= NULL
; }
210 bool IsCreated() const { return GetMembersCount() > 0; }
211 const uint64
& GetLeaderGUID() const { return m_leaderGuid
; }
212 const char * GetLeaderName() const { return m_leaderName
.c_str(); }
213 LootMethod
GetLootMethod() const { return m_lootMethod
; }
214 const uint64
& GetLooterGuid() const { return m_looterGuid
; }
215 ItemQualities
GetLootThreshold() const { return m_lootThreshold
; }
217 // member manipulation methods
218 bool IsMember(const uint64
& guid
) const { return _getMemberCSlot(guid
) != m_memberSlots
.end(); }
219 bool IsLeader(const uint64
& guid
) const { return (GetLeaderGUID() == guid
); }
220 uint64
GetMemberGUID(const std::string
& name
)
222 for(member_citerator itr
= m_memberSlots
.begin(); itr
!= m_memberSlots
.end(); ++itr
)
224 if(itr
->name
== name
)
231 bool IsAssistant(uint64 guid
) const
233 member_citerator mslot
= _getMemberCSlot(guid
);
234 if(mslot
==m_memberSlots
.end())
237 return mslot
->assistant
;
239 Player
* GetInvited(const uint64
& guid
) const;
240 Player
* GetInvited(const std::string
& name
) const;
242 bool SameSubGroup(uint64 guid1
,const uint64
& guid2
) const
244 member_citerator mslot2
= _getMemberCSlot(guid2
);
245 if(mslot2
==m_memberSlots
.end())
248 return SameSubGroup(guid1
,&*mslot2
);
251 bool SameSubGroup(uint64 guid1
, MemberSlot
const* slot2
) const
253 member_citerator mslot1
= _getMemberCSlot(guid1
);
254 if(mslot1
==m_memberSlots
.end() || !slot2
)
257 return (mslot1
->group
==slot2
->group
);
260 bool HasFreeSlotSubGroup(uint8 subgroup
) const
262 return (m_subGroupsCounts
&& m_subGroupsCounts
[subgroup
] < MAX_GROUP_SIZE
);
265 bool SameSubGroup(Player
const* member1
, Player
const* member2
) const;
267 MemberSlotList
const& GetMemberSlots() const { return m_memberSlots
; }
268 GroupReference
* GetFirstMember() { return m_memberMgr
.getFirst(); }
269 uint32
GetMembersCount() const { return m_memberSlots
.size(); }
270 void GetDataForXPAtKill(Unit
const* victim
, uint32
& count
,uint32
& sum_level
, Player
* & member_with_max_level
, Player
* & not_gray_member_with_max_level
, Player
* additional
= NULL
);
271 uint8
GetMemberGroup(uint64 guid
) const
273 member_citerator mslot
= _getMemberCSlot(guid
);
274 if(mslot
==m_memberSlots
.end())
275 return MAX_RAID_SUBGROUPS
+ 1;
280 // some additional raid methods
281 void ConvertToRaid();
283 void SetBattlegroundGroup(BattleGround
*bg
) { m_bgGroup
= bg
; }
284 GroupJoinBattlegroundResult
CanJoinBattleGroundQueue(BattleGround
const* bgOrTemplate
, BattleGroundQueueTypeId bgQueueTypeId
, uint32 MinPlayerCount
, uint32 MaxPlayerCount
, bool isRated
, uint32 arenaSlot
);
286 void ChangeMembersGroup(const uint64
&guid
, uint8 group
);
287 void ChangeMembersGroup(Player
*player
, uint8 group
);
289 uint64
const& GetMainTank() const { return m_mainTank
; }
290 uint64
const& GetMainAssistant() const { return m_mainAssistant
; }
292 void SetAssistant(uint64 guid
, bool state
)
296 if(_setAssistantFlag(guid
, state
))
299 void SetMainTank(uint64 guid
)
304 if(_setMainTank(guid
))
307 void SetMainAssistant(uint64 guid
)
312 if(_setMainAssistant(guid
))
316 void SetTargetIcon(uint8 id
, uint64 whoGuid
, uint64 targetGuid
);
318 Difficulty
GetDifficulty(bool isRaid
) const { return isRaid
? m_raidDifficulty
: m_dungeonDifficulty
; }
319 Difficulty
GetDungeonDifficulty() const { return m_dungeonDifficulty
; }
320 Difficulty
GetRaidDifficulty() const { return m_raidDifficulty
; }
321 void SetDungeonDifficulty(Difficulty difficulty
);
322 void SetRaidDifficulty(Difficulty difficulty
);
324 bool InCombatToInstance(uint32 instanceId
);
325 void ResetInstances(uint8 method
, bool isRaid
, Player
* SendMsgTo
);
327 void SendTargetIconList(WorldSession
*session
);
329 void UpdatePlayerOutOfRange(Player
* pPlayer
);
330 // ignore: GUID of player that will be ignored
331 void BroadcastPacket(WorldPacket
*packet
, bool ignorePlayersInBGRaid
, int group
=-1, uint64 ignore
=0);
332 void BroadcastReadyCheck(WorldPacket
*packet
);
333 void OfflineReadyCheck();
335 void RewardGroupAtKill(Unit
* pVictim
, Player
* player_tap
);
337 /*********************************************************/
338 /*** LOOT SYSTEM ***/
339 /*********************************************************/
341 void SendLootStartRoll(uint32 CountDown
, uint32 mapid
, const Roll
&r
);
342 void SendLootRoll(ObjectGuid
const& targetGuid
, uint8 rollNumber
, uint8 rollType
, const Roll
&r
);
343 void SendLootRollWon(ObjectGuid
const& targetGuid
, uint8 rollNumber
, RollVote rollType
, const Roll
&r
);
344 void SendLootAllPassed(const Roll
&r
);
345 void GroupLoot(Creature
*creature
, Loot
*loot
);
346 void NeedBeforeGreed(Creature
*creature
, Loot
*loot
);
347 void MasterLoot(Creature
*creature
, Loot
*loot
);
348 void CountRollVote(ObjectGuid
const& playerGUID
, ObjectGuid
const& lootedTarget
, uint32 itemSlot
, RollVote choise
);
349 void StartLootRool(Creature
* lootTarget
, Loot
* loot
, uint8 itemSlot
, bool skipIfCanNotUse
);
352 void LinkMember(GroupReference
*pRef
) { m_memberMgr
.insertFirst(pRef
); }
353 void DelinkMember(GroupReference
* /*pRef*/ ) { }
355 InstanceGroupBind
* BindToInstance(InstanceSave
*save
, bool permanent
, bool load
= false);
356 void UnbindInstance(uint32 mapid
, uint8 difficulty
, bool unload
= false);
357 InstanceGroupBind
* GetBoundInstance(Player
* player
);
358 InstanceGroupBind
* GetBoundInstance(Map
* aMap
, Difficulty difficulty
);
359 BoundInstancesMap
& GetBoundInstances(Difficulty difficulty
) { return m_boundInstances
[difficulty
]; }
362 bool _addMember(const uint64
&guid
, const char* name
, bool isAssistant
=false);
363 bool _addMember(const uint64
&guid
, const char* name
, bool isAssistant
, uint8 group
);
364 bool _removeMember(const uint64
&guid
); // returns true if leader has changed
365 void _setLeader(const uint64
&guid
);
367 void _removeRolls(const uint64
&guid
);
369 bool _setMembersGroup(const uint64
&guid
, uint8 group
);
370 bool _setAssistantFlag(const uint64
&guid
, const bool &state
);
371 bool _setMainTank(const uint64
&guid
);
372 bool _setMainAssistant(const uint64
&guid
);
374 void _homebindIfInstance(Player
*player
);
376 void _initRaidSubGroupsCounter()
378 // Sub group counters initialization
379 if (!m_subGroupsCounts
)
380 m_subGroupsCounts
= new uint8
[MAX_RAID_SUBGROUPS
];
382 memset((void*)m_subGroupsCounts
, 0, MAX_RAID_SUBGROUPS
* sizeof(uint8
));
384 for (member_citerator itr
= m_memberSlots
.begin(); itr
!= m_memberSlots
.end(); ++itr
)
385 ++m_subGroupsCounts
[itr
->group
];
388 member_citerator
_getMemberCSlot(uint64 Guid
) const
390 for(member_citerator itr
= m_memberSlots
.begin(); itr
!= m_memberSlots
.end(); ++itr
)
392 if (itr
->guid
== Guid
)
395 return m_memberSlots
.end();
398 member_witerator
_getMemberWSlot(uint64 Guid
)
400 for(member_witerator itr
= m_memberSlots
.begin(); itr
!= m_memberSlots
.end(); ++itr
)
402 if (itr
->guid
== Guid
)
405 return m_memberSlots
.end();
408 void SubGroupCounterIncrease(uint8 subgroup
)
410 if (m_subGroupsCounts
)
411 ++m_subGroupsCounts
[subgroup
];
414 void SubGroupCounterDecrease(uint8 subgroup
)
416 if (m_subGroupsCounts
)
417 --m_subGroupsCounts
[subgroup
];
420 void CountTheRoll(Rolls::iterator
& roll
); // iterator update to next, in CountRollVote if true
421 bool CountRollVote(ObjectGuid
const& playerGUID
, Rolls::iterator
& roll
, RollVote choise
);
423 GroupFlagMask
GetFlags(MemberSlot
const& slot
) const
427 flags
|= GROUP_ASSISTANT
;
428 if (slot
.guid
== m_mainAssistant
)
429 flags
|= GROUP_MAIN_ASSISTANT
;
430 if (slot
.guid
== m_mainTank
)
431 flags
|= GROUP_MAIN_TANK
;
432 return GroupFlagMask(flags
);
435 uint32 m_Id
; // 0 for not created or BG groups
436 MemberSlotList m_memberSlots
;
437 GroupRefManager m_memberMgr
;
438 InvitesList m_invitees
;
440 std::string m_leaderName
;
442 uint64 m_mainAssistant
;
443 GroupType m_groupType
;
444 Difficulty m_dungeonDifficulty
;
445 Difficulty m_raidDifficulty
;
446 BattleGround
* m_bgGroup
;
447 uint64 m_targetIcons
[TARGET_ICON_COUNT
];
448 LootMethod m_lootMethod
;
449 ItemQualities m_lootThreshold
;
452 BoundInstancesMap m_boundInstances
[MAX_DIFFICULTY
];
453 uint8
* m_subGroupsCounts
;