aboutsummaryrefslogtreecommitdiff
path: root/src/game/Group.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/Group.cpp')
-rw-r--r--src/game/Group.cpp168
1 files changed, 119 insertions, 49 deletions
diff --git a/src/game/Group.cpp b/src/game/Group.cpp
index 9face6d0e7d..a3fe884a645 100644
--- a/src/game/Group.cpp
+++ b/src/game/Group.cpp
@@ -71,7 +71,7 @@ Group::~Group()
// it is undefined whether objectmgr (which stores the groups) or instancesavemgr
// will be unloaded first so we must be prepared for both cases
// this may unload some instance saves
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
for (BoundInstancesMap::iterator itr2 = m_boundInstances[i].begin(); itr2 != m_boundInstances[i].end(); ++itr2)
itr2->second.save->RemoveGroup(this);
@@ -94,22 +94,27 @@ bool Group::Create(const uint64 &guid, const char * name)
m_lootThreshold = ITEM_QUALITY_UNCOMMON;
m_looterGuid = guid;
- m_difficulty = DIFFICULTY_NORMAL;
+ m_dungeonDifficulty = DUNGEON_DIFFICULTY_NORMAL;
+ m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL;
if(!isBGGroup())
{
Player *leader = objmgr.GetPlayer(guid);
- if(leader) m_difficulty = leader->GetDifficulty();
-
+ if(leader)
+ {
+ m_dungeonDifficulty = leader->GetDungeonDifficulty();
+ m_raidDifficulty = leader->GetRaidDifficulty();
+ }
+
Player::ConvertInstancesToGroup(leader, this, guid);
// store group in database
CharacterDatabase.BeginTransaction();
CharacterDatabase.PExecute("DELETE FROM groups WHERE leaderGuid ='%u'", GUID_LOPART(m_leaderGuid));
CharacterDatabase.PExecute("DELETE FROM group_member WHERE leaderGuid ='%u'", GUID_LOPART(m_leaderGuid));
- CharacterDatabase.PExecute("INSERT INTO groups(leaderGuid,mainTank,mainAssistant,lootMethod,looterGuid,lootThreshold,icon1,icon2,icon3,icon4,icon5,icon6,icon7,icon8,isRaid,difficulty) "
- "VALUES('%u','%u','%u','%u','%u','%u','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','%u','%u')",
+ CharacterDatabase.PExecute("INSERT INTO groups (leaderGuid,mainTank,mainAssistant,lootMethod,looterGuid,lootThreshold,icon1,icon2,icon3,icon4,icon5,icon6,icon7,icon8,isRaid,difficulty,raiddifficulty) "
+ "VALUES ('%u','%u','%u','%u','%u','%u','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','%u','%u','%u')",
GUID_LOPART(m_leaderGuid), GUID_LOPART(m_mainTank), GUID_LOPART(m_mainAssistant), uint32(m_lootMethod),
- GUID_LOPART(m_looterGuid), uint32(m_lootThreshold), m_targetIcons[0], m_targetIcons[1], m_targetIcons[2], m_targetIcons[3], m_targetIcons[4], m_targetIcons[5], m_targetIcons[6], m_targetIcons[7], isRaidGroup(), m_difficulty);
+ GUID_LOPART(m_looterGuid), uint32(m_lootThreshold), m_targetIcons[0], m_targetIcons[1], m_targetIcons[2], m_targetIcons[3], m_targetIcons[4], m_targetIcons[5], m_targetIcons[6], m_targetIcons[7], isRaidGroup(), uint32(m_dungeonDifficulty), m_raidDifficulty);
}
if(!AddMember(guid, name))
@@ -129,8 +134,8 @@ bool Group::LoadGroupFromDB(const uint64 &leaderGuid, QueryResult *result, bool
if(!result)
{
external = false;
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
- result = CharacterDatabase.PQuery("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty FROM groups WHERE leaderGuid ='%u'", GUID_LOPART(leaderGuid));
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ result = CharacterDatabase.PQuery("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty, raiddifficulty FROM groups WHERE leaderGuid ='%u'", GUID_LOPART(leaderGuid));
if(!result)
return false;
}
@@ -149,7 +154,16 @@ bool Group::LoadGroupFromDB(const uint64 &leaderGuid, QueryResult *result, bool
if (m_groupType == GROUPTYPE_RAID)
_initRaidSubGroupsCounter();
- m_difficulty = (*result)[14].GetUInt8();
+ uint32 diff = (*result)[14].GetUInt8();
+ if (diff >= MAX_DUNGEON_DIFFICULTY)
+ diff = DUNGEON_DIFFICULTY_NORMAL;
+ m_dungeonDifficulty = Difficulty(diff);
+
+ uint32 r_diff = (*result)[15].GetUInt8();
+ if (r_diff >= MAX_RAID_DIFFICULTY)
+ r_diff = RAID_DIFFICULTY_10MAN_NORMAL;
+ m_raidDifficulty = Difficulty(r_diff);
+
m_mainTank = (*result)[0].GetUInt64();
m_mainAssistant = (*result)[1].GetUInt64();
m_lootMethod = (LootMethod)(*result)[2].GetUInt8();
@@ -291,12 +305,21 @@ bool Group::AddMember(const uint64 &guid, const char* name)
{
// reset the new member's instances, unless he is currently in one of them
// including raid/heroic instances that they are not permanently bound to!
- player->ResetInstances(INSTANCE_RESET_GROUP_JOIN);
+ player->ResetInstances(INSTANCE_RESET_GROUP_JOIN,false);
+ player->ResetInstances(INSTANCE_RESET_GROUP_JOIN,true);
- if(player->getLevel() >= LEVELREQUIREMENT_HEROIC && player->GetDifficulty() != GetDifficulty() )
+ if (player->getLevel() >= LEVELREQUIREMENT_HEROIC)
{
- player->SetDifficulty(m_difficulty);
- player->SendDungeonDifficulty(true);
+ if (player->GetDungeonDifficulty() != GetDungeonDifficulty())
+ {
+ player->SetDungeonDifficulty(GetDungeonDifficulty());
+ player->SendDungeonDifficulty(true);
+ }
+ if (player->GetRaidDifficulty() != GetRaidDifficulty())
+ {
+ player->SetRaidDifficulty(GetRaidDifficulty());
+ player->SendRaidDifficulty(true);
+ }
}
}
player->SetGroupUpdateFlag(GROUP_UPDATE_FULL);
@@ -441,7 +464,8 @@ void Group::Disband(bool hideDestroy)
CharacterDatabase.PExecute("DELETE FROM groups WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
CharacterDatabase.PExecute("DELETE FROM group_member WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
CharacterDatabase.CommitTransaction();
- ResetInstances(INSTANCE_RESET_GROUP_DISBAND, NULL);
+ ResetInstances(INSTANCE_RESET_GROUP_DISBAND, false, NULL);
+ ResetInstances(INSTANCE_RESET_GROUP_DISBAND, true, NULL);
}
m_leaderGuid = 0;
@@ -454,12 +478,13 @@ void Group::Disband(bool hideDestroy)
void Group::SendLootStartRoll(uint32 CountDown, const Roll &r)
{
- WorldPacket data(SMSG_LOOT_START_ROLL, (8+4+4+4+4+4));
+ WorldPacket data(SMSG_LOOT_START_ROLL, (8+4+4+4+4+4+4));
data << uint64(r.itemGUID); // guid of rolled item
data << uint32(r.totalPlayersRolling); // maybe the number of players rolling for it???
data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for
data << uint32(r.itemRandomSuffix); // randomSuffix
data << uint32(r.itemRandomPropId); // item random property ID
+ data << uint32(r.itemCount); // items in stack
data << uint32(CountDown); // the countdown time to choose "need" or "greed"
for (Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr!=r.playerVote.end(); ++itr)
@@ -475,7 +500,7 @@ void Group::SendLootStartRoll(uint32 CountDown, const Roll &r)
void Group::SendLootRoll(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r)
{
- WorldPacket data(SMSG_LOOT_ROLL, (8+4+8+4+4+4+1+1));
+ WorldPacket data(SMSG_LOOT_ROLL, (8+4+8+4+4+4+1+1+1));
data << uint64(SourceGuid); // guid of the item rolled
data << uint32(0); // unknown, maybe amount of players
data << uint64(TargetGuid);
@@ -704,23 +729,23 @@ void Group::CountRollVote(const uint64& playerGUID, const uint64& Guid, uint32 N
switch (Choise)
{
- case 0: //Player choose pass
+ case ROLL_PASS: // Player choose pass
{
- SendLootRoll(0, playerGUID, 128, 128, *roll);
+ SendLootRoll(0, playerGUID, 0, ROLL_PASS, *roll);
++roll->totalPass;
itr->second = PASS;
}
break;
- case 1: //player choose Need
+ case ROLL_NEED: // player choose Need
{
- SendLootRoll(0, playerGUID, 0, 0, *roll);
+ SendLootRoll(0, playerGUID, 0, ROLL_NEED, *roll);
++roll->totalNeed;
itr->second = NEED;
}
break;
- case 2: //player choose Greed
+ case ROLL_GREED: // player choose Greed
{
- SendLootRoll(0, playerGUID, 128, 2, *roll);
+ SendLootRoll(0, playerGUID, 128, ROLL_GREED, *roll);
++roll->totalGreed;
itr->second = GREED;
}
@@ -768,14 +793,14 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers)
continue;
uint8 randomN = urand(1, 99);
- SendLootRoll(0, itr->first, randomN, 1, *roll);
+ SendLootRoll(0, itr->first, randomN, ROLL_NEED, *roll);
if (maxresul < randomN)
{
maxguid = itr->first;
maxresul = randomN;
}
}
- SendLootRollWon(0, maxguid, maxresul, 1, *roll);
+ SendLootRollWon(0, maxguid, maxresul, ROLL_NEED, *roll);
player = objmgr.GetPlayer(maxguid);
if(player && player->GetSession())
@@ -815,14 +840,14 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers)
continue;
uint8 randomN = urand(1, 99);
- SendLootRoll(0, itr->first, randomN, 2, *roll);
+ SendLootRoll(0, itr->first, randomN, ROLL_GREED, *roll);
if (maxresul < randomN)
{
maxguid = itr->first;
maxresul = randomN;
}
}
- SendLootRollWon(0, maxguid, maxresul, 2, *roll);
+ SendLootRollWon(0, maxguid, maxresul, ROLL_GREED, *roll);
player = objmgr.GetPlayer(maxguid);
if(player && player->GetSession())
@@ -959,7 +984,8 @@ void Group::SendUpdate()
data << (uint8)m_lootMethod; // loot method
data << (uint64)m_looterGuid; // looter guid
data << (uint8)m_lootThreshold; // loot threshold
- data << (uint8)m_difficulty; // Heroic Mod Group
+ data << (uint8)m_dungeonDifficulty; // Dungeon Difficulty
+ data << (uint8)m_raidDifficulty; // Raid Difficulty
}
player->GetSession()->SendPacket( &data );
}
@@ -1076,7 +1102,7 @@ bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant, u
else
player->SetGroup(this, group);
// if the same group invites the player back, cancel the homebind timer
- InstanceGroupBind *bind = GetBoundInstance(player->GetMapId(), player->GetDifficulty());
+ InstanceGroupBind *bind = GetBoundInstance(player);
if(bind && bind->save->GetInstanceId() == player->GetInstanceId())
player->m_InstanceValid = true;
}
@@ -1162,7 +1188,7 @@ void Group::_setLeader(const uint64 &guid)
Player *player = objmgr.GetPlayer(slot->guid);
if(player)
{
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end();)
{
@@ -1211,7 +1237,7 @@ void Group::_removeRolls(const uint64 &guid)
roll->playerVote.erase(itr2);
- CountRollVote(guid, roll->itemGUID, GetMembersCount()-1, 3);
+ CountRollVote(guid, roll->itemGUID, GetMembersCount()-1, MAX_ROLL_TYPE);
}
}
@@ -1449,19 +1475,38 @@ void Roll::targetObjectBuildLink()
getTarget()->addLootValidatorRef(this);
}
-void Group::SetDifficulty(uint8 difficulty)
+void Group::SetDungeonDifficulty(Difficulty difficulty)
{
- m_difficulty = difficulty;
- if (!isBGGroup())
- CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE leaderGuid ='%u'", m_difficulty, GUID_LOPART(m_leaderGuid));
-
+ m_dungeonDifficulty = difficulty;
+ if(!isBGGroup())
+ CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE leaderGuid ='%u'", m_dungeonDifficulty, GUID_LOPART(m_leaderGuid));
+
for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *player = itr->getSource();
if(!player->GetSession() || player->getLevel() < LEVELREQUIREMENT_HEROIC)
continue;
- player->SetDifficulty(difficulty);
+ player->SetDungeonDifficulty(difficulty);
player->SendDungeonDifficulty(true);
+ //send player to recall positio nis a dungeon (to avoid an exploit)
+ if (sMapStore.LookupEntry(player->GetMap()->IsDungeon()))
+ player->TeleportTo(player->m_recallMap, player->m_recallX, player->m_recallY, player->m_recallZ, player->m_recallO);
+ }
+}
+
+void Group::SetRaidDifficulty(Difficulty difficulty)
+{
+ m_raidDifficulty = difficulty;
+ if(!isBGGroup())
+ CharacterDatabase.PExecute("UPDATE groups SET raiddifficulty = %u WHERE leaderGuid ='%u'", m_raidDifficulty, GUID_LOPART(m_leaderGuid));
+
+ for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
+ {
+ Player *player = itr->getSource();
+ if(!player->GetSession() || player->getLevel() < LEVELREQUIREMENT_HEROIC)
+ continue;
+ player->SetRaidDifficulty(difficulty);
+ player->SendRaidDifficulty(true);
}
}
@@ -1470,7 +1515,7 @@ bool Group::InCombatToInstance(uint32 instanceId)
for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *pPlayer = itr->getSource();
- if(pPlayer && pPlayer->getAttackers().size() && pPlayer->GetInstanceId() == instanceId && (pPlayer->GetMap()->IsRaid() || pPlayer->GetMap()->IsHeroic()))
+ if(pPlayer && pPlayer->getAttackers().size() && pPlayer->GetInstanceId() == instanceId && (pPlayer->GetMap()->IsRaidOrHeroicDungeon()))
for (std::set<Unit*>::const_iterator i = pPlayer->getAttackers().begin(); i!=pPlayer->getAttackers().end(); ++i)
if((*i) && (*i)->GetTypeId() == TYPEID_UNIT && ((Creature*)(*i))->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
return true;
@@ -1478,7 +1523,7 @@ bool Group::InCombatToInstance(uint32 instanceId)
return false;
}
-void Group::ResetInstances(uint8 method, Player* SendMsgTo)
+void Group::ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo)
{
if(isBGGroup())
return;
@@ -1486,13 +1531,13 @@ void Group::ResetInstances(uint8 method, Player* SendMsgTo)
// method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_DISBAND
// we assume that when the difficulty changes, all instances that can be reset will be
- uint8 dif = GetDifficulty();
+ Difficulty diff = GetDifficulty(isRaid);
- for (BoundInstancesMap::iterator itr = m_boundInstances[dif].begin(); itr != m_boundInstances[dif].end();)
+ for (BoundInstancesMap::iterator itr = m_boundInstances[diff].begin(); itr != m_boundInstances[diff].end(); )
{
InstanceSave *p = itr->second.save;
const MapEntry *entry = sMapStore.LookupEntry(itr->first);
- if(!entry || (!p->CanReset() && method != INSTANCE_RESET_GROUP_DISBAND))
+ if(!entry || entry->IsRaid() != isRaid || !p->CanReset() && method != INSTANCE_RESET_GROUP_DISBAND)
{
++itr;
continue;
@@ -1501,7 +1546,7 @@ void Group::ResetInstances(uint8 method, Player* SendMsgTo)
if(method == INSTANCE_RESET_ALL)
{
// the "reset all instances" method can only reset normal maps
- if(dif == DIFFICULTY_HEROIC || entry->map_type == MAP_RAID)
+ if (entry->map_type == MAP_RAID || diff == DUNGEON_DIFFICULTY_HEROIC)
{
++itr;
continue;
@@ -1531,8 +1576,8 @@ void Group::ResetInstances(uint8 method, Player* SendMsgTo)
if(p->CanReset()) p->DeleteFromDB();
else CharacterDatabase.PExecute("DELETE FROM group_instance WHERE instance = '%u'", p->GetInstanceId());
// i don't know for sure if hash_map iterators
- m_boundInstances[dif].erase(itr);
- itr = m_boundInstances[dif].begin();
+ m_boundInstances[diff].erase(itr);
+ itr = m_boundInstances[diff].begin();
// this unloads the instance save unless online players are bound to it
// (eg. permanent binds or GM solo binds)
p->RemoveGroup(this);
@@ -1542,11 +1587,19 @@ void Group::ResetInstances(uint8 method, Player* SendMsgTo)
}
}
-InstanceGroupBind* Group::GetBoundInstance(uint32 mapid, uint8 difficulty)
+InstanceGroupBind* Group::GetBoundInstance(Player* player)
{
+ uint32 mapid = player->GetMapId();
+ MapEntry const* mapEntry = sMapStore.LookupEntry(mapid);
+ if(!mapEntry)
+ return NULL;
+
+ Difficulty difficulty = player->GetDifficulty(mapEntry->IsRaid());
+
// some instances only have one difficulty
- const MapEntry* entry = sMapStore.LookupEntry(mapid);
- if(!entry || !entry->SupportsHeroicMode()) difficulty = DIFFICULTY_NORMAL;
+ MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty);
+ if(!mapDiff)
+ difficulty = DUNGEON_DIFFICULTY_NORMAL;
BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(mapid);
if(itr != m_boundInstances[difficulty].end())
@@ -1555,6 +1608,24 @@ InstanceGroupBind* Group::GetBoundInstance(uint32 mapid, uint8 difficulty)
return NULL;
}
+InstanceGroupBind* Group::GetBoundInstance(Map* aMap)
+{
+ // Currently spawn numbering not different from map difficulty
+ Difficulty difficulty = GetDifficulty(aMap->IsRaid());
+
+ // some instances only have one difficulty
+ MapDifficulty const* mapDiff = GetMapDifficultyData(aMap->GetId(),difficulty);
+ if(!mapDiff)
+ return NULL;
+
+ BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(aMap->GetId());
+ if(itr != m_boundInstances[difficulty].end())
+ return &itr->second;
+ else
+ return NULL;
+}
+
+
InstanceGroupBind* Group::BindToInstance(InstanceSave *save, bool permanent, bool load)
{
if(save && !isBGGroup())
@@ -1624,4 +1695,3 @@ void Group::BroadcastGroupUpdate(void)
}
}
}
-