Core/LFG:

Fix priority of the player when its added to the lfg group
        Better implementation of the Dungeon Deserter debuff
        Rewrite the NeedBeforeGreed loot
        Fixed players being shown as Unknown Entity when entering the lfg group
        Some incremental optimizations after original patch
Thanks to Retriman and Paecman for base implementation

Signed-off-by: Machiavelli <[email protected]>
This commit is contained in:
Subv2112
2012-01-14 17:37:28 +01:00
committed by Machiavelli
parent dbbac0bdaa
commit f4075f0f94
14 changed files with 346 additions and 52 deletions
+88 -31
View File
@@ -190,6 +190,9 @@ void Group::LoadGroupFromDB(Field* fields)
m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL;
else
m_raidDifficulty = Difficulty(r_diff);
if (m_groupType & GROUPTYPE_LFG)
sLFGMgr->_LoadFromDB(fields, GetGUID());
}
void Group::LoadMemberFromDB(uint32 guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles)
@@ -211,6 +214,14 @@ void Group::LoadMemberFromDB(uint32 guidLow, uint8 memberFlags, uint8 subgroup,
m_memberSlots.push_back(member);
SubGroupCounterIncrease(subgroup);
if (isLFGGroup())
{
LfgDungeonSet Dungeons;
Dungeons.insert(sLFGMgr->GetDungeon(GetGUID()));
sLFGMgr->SetSelectedDungeons(member.guid, Dungeons);
sLFGMgr->SetState(member.guid, sLFGMgr->GetState(GetGUID()));
}
}
void Group::ConvertToLFG()
@@ -441,7 +452,7 @@ bool Group::RemoveMember(uint64 guid, const RemoveMethod &method /*= GROUP_REMOV
return m_memberSlots.size();
// remove member and change leader (if need) only if strong more 2 members _before_ member remove (BG allow 1 member group)
if (GetMembersCount() > (isBGGroup() ? 1u : 2u))
if (GetMembersCount() > ((isBGGroup() || isLFGGroup()) ? 1u : 2u))
{
Player* player = ObjectAccessor::FindPlayer(guid);
if (player)
@@ -485,6 +496,8 @@ bool Group::RemoveMember(uint64 guid, const RemoveMethod &method /*= GROUP_REMOV
CharacterDatabase.Execute(stmt);
DelinkMember(guid);
// Reevaluate group enchanter if the leaving player had enchanting skill or the player is offline
if ((player && player->GetSkillValue(SKILL_ENCHANTING)) || !player)
ResetMaxEnchantingLevel();
@@ -534,6 +547,20 @@ bool Group::RemoveMember(uint64 guid, const RemoveMethod &method /*= GROUP_REMOV
}
SendUpdate();
if (isLFGGroup() && GetMembersCount() == 1)
{
Player* Leader = ObjectAccessor::FindPlayer(GetLeaderGUID());
LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(sLFGMgr->GetDungeon(GetGUID()));
if ((Leader && dungeon && Leader->isAlive() && Leader->GetMapId() != dungeon->map) || !dungeon)
{
Disband();
return false;
}
}
if (m_memberMgr.getSize() < ((isLFGGroup() || isBGGroup()) ? 1u : 2u))
Disband();
return true;
}
@@ -673,6 +700,10 @@ void Group::Disband(bool hideDestroy /* = false */)
CharacterDatabase.CommitTransaction(trans);
ResetInstances(INSTANCE_RESET_GROUP_DISBAND, false, NULL);
ResetInstances(INSTANCE_RESET_GROUP_DISBAND, true, NULL);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_LFG_DATA);
stmt->setUInt32(0, m_dbStoreId);
CharacterDatabase.Execute(stmt);
sGroupMgr->FreeGroupDbStoreId(this);
}
@@ -709,6 +740,28 @@ void Group::SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll &r)
}
}
void Group::SendLootStartRollToPlayer(uint32 CountDown, uint32 mapid, Player* p, bool NeedBlocked, const Roll &r)
{
if (!p || !p->GetSession())
return;
WorldPacket data(SMSG_LOOT_START_ROLL, (8 + 4 + 4 + 4 + 4 + 4 + 4 + 1 ));
data << uint64(r.itemGUID); // guid of rolled item
data << uint32(mapid); // 3.3.3 mapid
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"
uint8 VoteMask = r.rollVoteMask;
if (NeedBlocked)
VoteMask &= ~ROLL_FLAG_TYPE_NEED;
data << uint8(VoteMask); // roll type mask
p->GetSession()->SendPacket(&data);
}
void Group::SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r)
{
WorldPacket data(SMSG_LOOT_ROLL, (8+4+8+4+4+4+1+1+1));
@@ -887,7 +940,7 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
}
}
void Group::NeedBeforeGreed(Loot* loot, WorldObject* pLootedObject)
void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
{
ItemTemplate const* item;
uint8 itemSlot = 0;
@@ -902,7 +955,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* pLootedObject)
if (item->Quality >= uint32(m_lootThreshold))
{
uint64 newitemGUID = MAKE_NEW_GUID(sObjectMgr->GenerateLowGuid(HIGHGUID_ITEM), 0, HIGHGUID_ITEM);
Roll* r=new Roll(newitemGUID, *i);
Roll* r = new Roll(newitemGUID, *i);
for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
@@ -911,21 +964,17 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* pLootedObject)
continue;
bool allowedForPlayer = i->AllowedForPlayer(playerToRoll);
if (playerToRoll->CanUseItem(item) == EQUIP_ERR_OK && allowedForPlayer)
if (allowedForPlayer && playerToRoll->IsWithinDistInMap(lootedObject, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false))
{
if (playerToRoll->IsWithinDistInMap(pLootedObject, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false))
r->totalPlayersRolling++;
if (playerToRoll->GetPassOnGroupLoot())
{
r->totalPlayersRolling++;
if (playerToRoll->GetPassOnGroupLoot())
{
r->playerVote[playerToRoll->GetGUID()] = PASS;
r->totalPass++;
// can't broadcast the pass now. need to wait until all rolling players are known.
}
else
r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;
r->playerVote[playerToRoll->GetGUID()] = PASS;
r->totalPass++;
// can't broadcast the pass now. need to wait until all rolling players are known.
}
else
r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;
}
}
@@ -941,25 +990,24 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* pLootedObject)
loot->items[itemSlot].is_blocked = true;
// If there is any "auto pass", broadcast the pass now.
if (r->totalPass)
//Broadcast Pass and Send Rollstart
for (Roll::PlayerVote::const_iterator itr=r->playerVote.begin(); itr != r->playerVote.end(); ++itr)
{
for (Roll::PlayerVote::const_iterator itr=r->playerVote.begin(); itr != r->playerVote.end(); ++itr)
{
Player* p = ObjectAccessor::FindPlayer(itr->first);
if (!p || !p->GetSession())
continue;
Player* p = ObjectAccessor::FindPlayer(itr->first);
if (!p || !p->GetSession())
continue;
if (itr->second == PASS)
SendLootRoll(newitemGUID, p->GetGUID(), 128, ROLL_PASS, *r);
}
if (itr->second == PASS)
SendLootRoll(newitemGUID, p->GetGUID(), 128, ROLL_PASS, *r);
if (p->CanRollForItem(item) == EQUIP_ERR_OK)
SendLootStartRollToPlayer(60000, lootedObject->GetMapId(), p, false, *r);
else
SendLootStartRollToPlayer(60000, lootedObject->GetMapId(), p, true, *r);
}
SendLootStartRoll(60000, pLootedObject->GetMapId(), *r);
RollId.push_back(r);
if (Creature* creature = pLootedObject->ToCreature())
if (Creature* creature = lootedObject->ToCreature())
{
creature->m_groupLootTimer = 60000;
creature->lootingGroupLowGUID = GetLowGUID();
@@ -1242,9 +1290,7 @@ void Group::SendTargetIconList(WorldSession* session)
void Group::SendUpdate()
{
for (member_witerator witr = m_memberSlots.begin(); witr != m_memberSlots.end(); ++witr)
{
SendUpdateToPlayer(witr->guid, &(*witr));
}
}
void Group::SendUpdateToPlayer(uint64 playerGUID, MemberSlot* slot)
@@ -2118,8 +2164,19 @@ void Group::LinkMember(GroupReference* pRef)
m_memberMgr.insertFirst(pRef);
}
void Group::DelinkMember(GroupReference* /*pRef*/) const
void Group::DelinkMember(uint64 guid)
{
GroupReference* ref = m_memberMgr.getFirst();
while (ref)
{
GroupReference* nextRef = ref->next();
if (ref->getSource()->GetGUID() == guid)
{
ref->unlink();
break;
}
ref = nextRef;
}
}
Group::BoundInstancesMap& Group::GetBoundInstances(Difficulty difficulty)
+2 -1
View File
@@ -273,6 +273,7 @@ class Group
bool isRollLootActive() const;
void SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll &r);
void SendLootStartRollToPlayer(uint32 CountDown, uint32 mapid, Player* p, bool NeedBlocked, const Roll &r);
void SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r);
void SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r);
void SendLootAllPassed(uint32 NumberOfPlayers, const Roll &r);
@@ -289,7 +290,7 @@ class Group
void ResetMaxEnchantingLevel();
void LinkMember(GroupReference* pRef);
void DelinkMember(GroupReference* /*pRef*/) const;
void DelinkMember(uint64 guid);
InstanceGroupBind* BindToInstance(InstanceSave* save, bool permanent, bool load = false);
void UnbindInstance(uint32 mapid, uint8 difficulty, bool unload = false);
+4 -4
View File
@@ -119,10 +119,10 @@ void GroupMgr::LoadGroups()
// Delete all groups with less than 2 members
CharacterDatabase.DirectExecute("DELETE FROM groups WHERE guid NOT IN (SELECT guid FROM group_member GROUP BY guid HAVING COUNT(guid) > 1)");
// 0 1 2 3 4 5 6 7 8 9
QueryResult result = CharacterDatabase.PQuery("SELECT leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6"
// 10 11 12 13 14 15
", icon7, icon8, groupType, difficulty, raiddifficulty, guid FROM groups ORDER BY guid ASC");
// 0 1 2 3 4 5 6 7 8 9
QueryResult result = CharacterDatabase.PQuery("SELECT g.leaderGuid, g.lootMethod, g.looterGuid, g.lootThreshold, g.icon1, g.icon2, g.icon3, g.icon4, g.icon5, g.icon6"
// 10 11 12 13 14 15 16 17
", g.icon7, g.icon8, g.groupType, g.difficulty, g.raiddifficulty, g.guid, lfg.dungeon, lfg.state FROM groups g LEFT JOIN lfg_data lfg ON lfg.guid = g.guid ORDER BY g.guid ASC");
if (!result)
{
sLog->outString(">> Loaded 0 group definitions. DB table `groups` is empty!");
+2 -2
View File
@@ -28,12 +28,12 @@ void GroupReference::targetObjectBuildLink()
void GroupReference::targetObjectDestroyLink()
{
// called from unlink()
getTarget()->DelinkMember(this);
//getTarget()->DelinkMember(this);
}
void GroupReference::sourceObjectDestroyLink()
{
// called from invalidate()
getTarget()->DelinkMember(this);
//getTarget()->DelinkMember(this);
}