aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSubv2112 <s.v.h.21@hotmail.com>2012-01-14 17:37:28 +0100
committerMachiavelli <machiavelli.trinity@gmail.com>2012-01-14 17:37:28 +0100
commitf4075f0f945c842fe2b1a08ea4a7fa253e8e2e53 (patch)
treebe27baca490ad8088774a2f7e7c20c319a766b01 /src
parentdbbac0bdaae4b6d8a0125999962c4a686092bd80 (diff)
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 <machiavelli.trinity@gmail.com>
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/DungeonFinding/LFGMgr.cpp115
-rwxr-xr-xsrc/server/game/DungeonFinding/LFGMgr.h8
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp96
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h1
-rwxr-xr-xsrc/server/game/Groups/Group.cpp121
-rwxr-xr-xsrc/server/game/Groups/Group.h3
-rw-r--r--src/server/game/Groups/GroupMgr.cpp8
-rwxr-xr-xsrc/server/game/Groups/GroupReference.cpp4
-rw-r--r--src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp14
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/LFGHandler.cpp3
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp12
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp4
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h3
13 files changed, 339 insertions, 53 deletions
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index e0a16d4868b..0f146598a6e 100755
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -72,6 +72,54 @@ LFGMgr::~LFGMgr()
delete it->second;
}
+void LFGMgr::_LoadFromDB(Field* fields, uint64 guid)
+{
+ if (!fields)
+ return;
+
+ if (!IS_GROUP(guid))
+ return;
+
+ uint32 dungeon = fields[16].GetUInt32();
+
+ uint8 state = fields[17].GetUInt8();
+
+ if (!dungeon || !state)
+ return;
+
+ SetDungeon(guid, dungeon);
+
+ switch (state)
+ {
+ case LFG_STATE_DUNGEON:
+ case LFG_STATE_FINISHED_DUNGEON:
+ SetState(guid, (LfgState)state);
+ break;
+ default:
+ break;
+ }
+}
+
+void LFGMgr::_SaveToDB(uint64 guid, uint32 db_guid)
+{
+ if (!IS_GROUP(guid))
+ return;
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_LFG_DATA);
+
+ stmt->setUInt32(0, db_guid);
+
+ CharacterDatabase.Execute(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_LFG_DATA);
+ stmt->setUInt32(0, db_guid);
+
+ stmt->setUInt32(1, GetDungeon(guid));
+ stmt->setUInt32(2, GetState(guid));
+
+ CharacterDatabase.Execute(stmt);
+}
+
/// Load rewards for completing dungeons
void LFGMgr::LoadRewards()
{
@@ -245,7 +293,8 @@ void LFGMgr::Update(uint32 diff)
UpdateProposal(m_lfgProposalId, guid, true);
}
else
- currentQueue.push_back(frontguid); // Lfg group not found, add this group to the queue.
+ if (std::find(currentQueue.begin(), currentQueue.end(), frontguid) == currentQueue.end()) //already in queue?
+ currentQueue.push_back(frontguid); // Lfg group not found, add this group to the queue.
firstNew.clear();
}
}
@@ -382,7 +431,10 @@ void LFGMgr::InitializeLockedDungeons(Player* player)
else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player))
locktype = LFG_LOCKSTATUS_RAID_LOCKED;
else if (dungeon->difficulty > DUNGEON_DIFFICULTY_NORMAL && player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty)))
- locktype = LFG_LOCKSTATUS_RAID_LOCKED;
+ {
+ if (!player->GetGroup() || !player->GetGroup()->isLFGGroup() || GetDungeon(player->GetGroup()->GetGUID(), true) != dungeon->ID || GetState(player->GetGroup()->GetGUID()) != LFG_STATE_DUNGEON)
+ locktype = LFG_LOCKSTATUS_RAID_LOCKED;
+ }
else if (dungeon->minlevel > level)
locktype = LFG_LOCKSTATUS_TOO_LOW_LEVEL;
else if (dungeon->maxlevel < level)
@@ -808,7 +860,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal)
{
uint64 guid = (*it);
LfgQueueInfoMap::iterator itQueue = m_QueueInfoMap.find(guid);
- if (itQueue == m_QueueInfoMap.end())
+ if (itQueue == m_QueueInfoMap.end() || GetState(guid) != LFG_STATE_QUEUED)
{
sLog->outError("LFGMgr::CheckCompatibility: [" UI64FMTD "] is not queued but listed as queued!", (*it));
RemoveFromQueue(guid);
@@ -923,6 +975,42 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal)
if (numPlayers != MAXGROUPSIZE)
{
sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) Compatibles but not match. Players(%u)", strGuids.c_str(), numPlayers);
+ uint8 Tanks_Needed = LFG_TANKS_NEEDED;
+ uint8 Healers_Needed = LFG_HEALERS_NEEDED;
+ uint8 Dps_Needed = LFG_DPS_NEEDED;
+ for (LfgQueueInfoMap::const_iterator itQueue = pqInfoMap.begin(); itQueue != pqInfoMap.end(); ++itQueue)
+ {
+ LfgQueueInfo* queue = itQueue->second;
+ for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer)
+ {
+ uint8 roles = itPlayer->second;
+ if ((roles & ROLE_TANK) && Tanks_Needed > 0)
+ --Tanks_Needed;
+ else if ((roles & ROLE_HEALER) && Healers_Needed > 0)
+ --Healers_Needed;
+ else if ((roles & ROLE_DAMAGE) && Dps_Needed > 0)
+ --Dps_Needed;
+ }
+ }
+ for (PlayerSet::const_iterator itPlayers = players.begin(); itPlayers != players.end(); ++itPlayers)
+ {
+ for (LfgQueueInfoMap::const_iterator itQueue = pqInfoMap.begin(); itQueue != pqInfoMap.end(); ++itQueue)
+ {
+ LfgQueueInfo* queue = itQueue->second;
+ if (!queue)
+ continue;
+
+ for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer)
+ {
+ if (*itPlayers == ObjectAccessor::FindPlayer(itPlayer->first))
+ {
+ queue->tanks = Tanks_Needed;
+ queue->healers = Healers_Needed;
+ queue->dps = Dps_Needed;
+ }
+ }
+ }
+ }
return true;
}
sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) MATCH! Group formed", strGuids.c_str());
@@ -1078,6 +1166,11 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /*
}
m_QueueInfoMap[gguid] = pqInfo;
+ if(GetState(gguid) != LFG_STATE_NONE)
+ {
+ LfgGuidList& currentQueue = m_currentQueue[team];
+ currentQueue.push_front(gguid);
+ }
AddToQueue(gguid, team);
}
@@ -1384,6 +1477,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept)
break;
}
}
+ m_teleport.push_back(pguid);
grp->SetLfgRoles(pguid, pProposal->players[pguid]->role);
SetState(pguid, LFG_STATE_DUNGEON);
}
@@ -1395,6 +1489,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept)
uint64 gguid = grp->GetGUID();
SetDungeon(gguid, dungeon->Entry());
SetState(gguid, LFG_STATE_DUNGEON);
+ _SaveToDB(gguid, grp->GetDbStoreId());
// Remove players/groups from Queue
for (LfgGuidList::const_iterator it = pProposal->queues.begin(); it != pProposal->queues.end(); ++it)
@@ -1509,7 +1604,9 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t
for (LfgGuidList::const_iterator it = pProposal->queues.begin(); it != pProposal->queues.end(); ++it)
{
uint64 guid = *it;
- AddToQueue(guid, team);
+ LfgGuidList& currentQueue = m_currentQueue[team];
+ currentQueue.push_front(guid); //Add GUID for high priority
+ AddToQueue(guid, team); //We have to add each GUID in newQueue to check for a new groups
}
delete pProposal;
@@ -1921,6 +2018,16 @@ const std::string& LFGMgr::GetComment(uint64 guid)
return m_Players[guid].GetComment();
}
+bool LFGMgr::IsTeleported(uint64 pguid)
+{
+ if (std::find(m_teleport.begin(), m_teleport.end(), pguid) != m_teleport.end())
+ {
+ m_teleport.remove(pguid);
+ return true;
+ }
+ return false;
+}
+
const LfgDungeonSet& LFGMgr::GetSelectedDungeons(uint64 guid)
{
sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetSelectedDungeons: [" UI64FMTD "]", guid);
diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h
index 3e324f4b5f4..d10902b9553 100755
--- a/src/server/game/DungeonFinding/LFGMgr.h
+++ b/src/server/game/DungeonFinding/LFGMgr.h
@@ -287,6 +287,9 @@ class LFGMgr
void InitializeLockedDungeons(Player* player);
+ void _LoadFromDB(Field* fields, uint64 guid);
+ void _SaveToDB(uint64 guid, uint32 db_guid);
+
void SetComment(uint64 guid, const std::string& comment);
const LfgLockMap& GetLockedDungeons(uint64 guid);
LfgState GetState(uint64 guid);
@@ -298,7 +301,9 @@ class LFGMgr
void RemoveGroupData(uint64 guid);
uint8 GetKicksLeft(uint64 gguid);
uint8 GetVotesNeeded(uint64 gguid);
+ bool IsTeleported(uint64 pguid);
void SetRoles(uint64 guid, uint8 roles);
+ void SetSelectedDungeons(uint64 guid, const LfgDungeonSet& dungeons);
private:
@@ -306,10 +311,8 @@ class LFGMgr
const std::string& GetComment(uint64 gguid);
void RestoreState(uint64 guid);
void SetDungeon(uint64 guid, uint32 dungeon);
- void SetSelectedDungeons(uint64 guid, const LfgDungeonSet& dungeons);
void SetLockedDungeons(uint64 guid, const LfgLockMap& lock);
void DecreaseKicksLeft(uint64 guid);
- void NoExiste(uint8 lala);
// Queue
void AddToQueue(uint64 guid, uint8 queueId);
@@ -352,6 +355,7 @@ class LFGMgr
LfgGuidListMap m_currentQueue; ///< Ordered list. Used to find groups
LfgGuidListMap m_newToQueue; ///< New groups to add to queue
LfgCompatibleMap m_CompatibleMap; ///< Compatible dungeons
+ LfgGuidList m_teleport; ///< Players being teleported
// Rolecheck - Proposal - Vote Kicks
LfgRoleCheckMap m_RoleChecks; ///< Current Role checks
LfgProposalMap m_Proposals; ///< Current Proposals
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 46f903ee71a..6a4b729e58a 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -2305,9 +2305,14 @@ bool Player::TeleportToBGEntryPoint()
if (m_bgData.joinPos.m_mapId == MAPID_INVALID)
return false;
+ Group* group = GetGroup();
+ if (group && group->isLFGGroup() && group->GetMembersCount() == 1)
+ group->Disband();
+ else
+ ScheduleDelayedOperation(DELAYED_BG_GROUP_RESTORE);
+
ScheduleDelayedOperation(DELAYED_BG_MOUNT_RESTORE);
ScheduleDelayedOperation(DELAYED_BG_TAXI_RESTORE);
- ScheduleDelayedOperation(DELAYED_BG_GROUP_RESTORE);
return TeleportTo(m_bgData.joinPos);
}
@@ -7371,6 +7376,22 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
SendInitWorldStates(newZone, newArea); // only if really enters to new zone, not just area change, works strange...
}
+ // group update
+ if (GetGroup())
+ {
+ SetGroupUpdateFlag(GROUP_UPDATE_FULL);
+ Group* grp = GetGroup();
+ if (GetSession() && grp->isLFGGroup() && sLFGMgr->IsTeleported(GetGUID()))
+ {
+ for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
+ {
+ Player* tempplr = itr->getSource();
+ if (tempplr)
+ GetSession()->SendNameQueryOpcode(tempplr->GetGUID());
+ }
+ }
+ }
+
m_zoneUpdateId = newZone;
m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL;
@@ -7458,10 +7479,6 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
// recent client version not send leave/join channel packets for built-in local channels
UpdateLocalChannels(newZone);
- // group update
- if (GetGroup())
- SetGroupUpdateFlag(GROUP_UPDATE_FULL);
-
UpdateZoneDependentAuras(newZone);
}
@@ -11794,6 +11811,75 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const
return EQUIP_ERR_ITEM_NOT_FOUND;
}
+InventoryResult Player::CanRollForItem(ItemTemplate const* proto) const
+{
+ if (!proto)
+ return EQUIP_ERR_ITEM_NOT_FOUND;
+ // Used by group, function NeedBeforeGreed, to know if a prototype can be used by a player
+
+ const static uint32 item_weapon_skills[MAX_ITEM_SUBCLASS_WEAPON] =
+ {
+ SKILL_AXES, SKILL_2H_AXES, SKILL_BOWS, SKILL_GUNS, SKILL_MACES,
+ SKILL_2H_MACES, SKILL_POLEARMS, SKILL_SWORDS, SKILL_2H_SWORDS, 0,
+ SKILL_STAVES, 0, 0, SKILL_FIST_WEAPONS, 0,
+ SKILL_DAGGERS, SKILL_THROWN, SKILL_ASSASSINATION, SKILL_CROSSBOWS, SKILL_WANDS,
+ SKILL_FISHING
+ }; //Copy from function Item::GetSkill()
+
+ if ((proto->AllowableClass & getClassMask()) == 0 || (proto->AllowableRace & getRaceMask()) == 0)
+ return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
+
+ if (proto->RequiredSpell != 0 && !HasSpell(proto->RequiredSpell))
+ return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+
+ if (proto->RequiredSkill != 0)
+ {
+ if (!GetSkillValue(proto->RequiredSkill))
+ return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ else if (GetSkillValue(proto->RequiredSkill) < proto->RequiredSkillRank)
+ return EQUIP_ERR_CANT_EQUIP_SKILL;
+ }
+
+ uint8 _class = getClass();
+
+ if (proto->Class == ITEM_CLASS_WEAPON && GetSkillValue(item_weapon_skills[proto->SubClass]) == 0)
+ return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+
+ if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass > ITEM_SUBCLASS_ARMOR_MISC && proto->SubClass < ITEM_SUBCLASS_ARMOR_BUCKLER && proto->InventoryType != INVTYPE_CLOAK)
+ {
+ if (_class == CLASS_WARRIOR || _class == CLASS_PALADIN || _class == CLASS_DEATH_KNIGHT)
+ {
+ if (getLevel() < 40)
+ {
+ if (proto->SubClass != ITEM_SUBCLASS_ARMOR_MAIL)
+ return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ }
+ else if (proto->SubClass != ITEM_SUBCLASS_ARMOR_PLATE)
+ return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ }
+ else if (_class == CLASS_HUNTER || _class == CLASS_SHAMAN)
+ {
+ if (getLevel() < 40)
+ {
+ if (proto->SubClass != ITEM_SUBCLASS_ARMOR_LEATHER)
+ return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ }
+ else if (proto->SubClass != ITEM_SUBCLASS_ARMOR_MAIL)
+ return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ }
+
+ if (_class == CLASS_ROGUE || _class == CLASS_DRUID)
+ if (proto->SubClass != ITEM_SUBCLASS_ARMOR_LEATHER)
+ return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+
+ if (_class == CLASS_MAGE || _class == CLASS_PRIEST || _class == CLASS_WARLOCK)
+ if (proto->SubClass != ITEM_SUBCLASS_ARMOR_CLOTH)
+ return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+ }
+
+ return EQUIP_ERR_OK;
+}
+
InventoryResult Player::CanUseAmmo(uint32 item) const
{
sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "STORAGE: CanUseAmmo item = %u", item);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index aa1d4e8185e..2b8ea7bbdc8 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1277,6 +1277,7 @@ class Player : public Unit, public GridObject<Player>
bool HasItemTotemCategory(uint32 TotemCategory) const;
InventoryResult CanUseItem(ItemTemplate const* pItem) const;
InventoryResult CanUseAmmo(uint32 item) const;
+ InventoryResult CanRollForItem(ItemTemplate const* item) const;
Item* StoreNewItem(ItemPosCountVec const& pos, uint32 item, bool update, int32 randomPropertyId = 0);
Item* StoreNewItem(ItemPosCountVec const& pos, uint32 item, bool update, int32 randomPropertyId, AllowedLooterSet &allowedLooters);
Item* StoreItem(ItemPosCountVec const& pos, Item* pItem, bool update);
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 49472880edd..b2fb59ea993 100755
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -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;
-
- if (itr->second == PASS)
- SendLootRoll(newitemGUID, p->GetGUID(), 128, ROLL_PASS, *r);
- }
+ Player* p = ObjectAccessor::FindPlayer(itr->first);
+ if (!p || !p->GetSession())
+ continue;
+
+ 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)
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index bed112d5511..caa49125100 100755
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -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);
diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp
index 412814a60d2..ae400852c73 100644
--- a/src/server/game/Groups/GroupMgr.cpp
+++ b/src/server/game/Groups/GroupMgr.cpp
@@ -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!");
diff --git a/src/server/game/Groups/GroupReference.cpp b/src/server/game/Groups/GroupReference.cpp
index 4d5890aa4e6..68d85c5bce9 100755
--- a/src/server/game/Groups/GroupReference.cpp
+++ b/src/server/game/Groups/GroupReference.cpp
@@ -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);
}
diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp
index 35276bb1d0a..bd9668ce5b8 100644
--- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp
@@ -43,6 +43,7 @@
#include "ScriptMgr.h"
#include "Battleground.h"
#include "AccountMgr.h"
+#include "LFGMgr.h"
class LoginQueryHolder : public SQLQueryHolder
{
@@ -196,7 +197,7 @@ bool LoginQueryHolder::Initialize()
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_INSTANCELOCKTIMES);
stmt->setUInt32(0, m_accountId);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADINSTANCELOCKTIMES, stmt);
-
+
return res;
}
@@ -892,6 +893,17 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
}
}
+ if (Group* group = pCurrChar->GetGroup())
+ {
+ if (group->isLFGGroup())
+ {
+ LfgDungeonSet Dungeons;
+ Dungeons.insert(sLFGMgr->GetDungeon(group->GetGUID()));
+ sLFGMgr->SetSelectedDungeons(pCurrChar->GetGUID(), Dungeons);
+ sLFGMgr->SetState(pCurrChar->GetGUID(), sLFGMgr->GetState(group->GetGUID()));
+ }
+ }
+
if (!pCurrChar->GetMap()->AddPlayerToMap(pCurrChar) || !pCurrChar->CheckInstanceLoginValid())
{
AreaTrigger const* at = sObjectMgr->GetGoBackTrigger(pCurrChar->GetMapId());
diff --git a/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp b/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp
index 52b4d4abbed..3c6bd28b5cb 100755
--- a/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp
@@ -48,7 +48,8 @@ void BuildPartyLockDungeonBlock(WorldPacket& data, const LfgLockPartyMap& lockMa
void WorldSession::HandleLfgJoinOpcode(WorldPacket& recv_data)
{
if (!sWorld->getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE) ||
- (GetPlayer()->GetGroup() && GetPlayer()->GetGroup()->GetLeaderGUID() != GetPlayer()->GetGUID()))
+ (GetPlayer()->GetGroup() && GetPlayer()->GetGroup()->GetLeaderGUID() != GetPlayer()->GetGUID() &&
+ (GetPlayer()->GetGroup()->GetMembersCount() == MAXGROUPSIZE || !GetPlayer()->GetGroup()->isLFGGroup())))
{
recv_data.rfinish();
return;
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 38e5771ccca..3fb2c4f3319 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -1445,7 +1445,17 @@ class spell_gen_luck_of_the_draw : public SpellScriptLoader
if (GetUnitOwner()->GetTypeId() != TYPEID_PLAYER)
return;
- LFGDungeonEntry const* randomDungeon = sLFGDungeonStore.LookupEntry(*(sLFGMgr->GetSelectedDungeons(GetUnitOwner()->GetGUID()).begin()));
+ const LfgDungeonSet dungeons = sLFGMgr->GetSelectedDungeons(GetUnitOwner()->GetGUID());
+ LfgDungeonSet::const_iterator itr = dungeons.begin();
+
+ if (itr == dungeons.end())
+ {
+ Remove(AURA_REMOVE_BY_DEFAULT);
+ return;
+ }
+
+
+ LFGDungeonEntry const* randomDungeon = sLFGDungeonStore.LookupEntry(*itr);
Group* group = GetUnitOwner()->ToPlayer()->GetGroup();
Map const* map = GetUnitOwner()->GetMap();
if (group && group->isLFGGroup())
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index a24f17a8b76..24b99219f46 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -325,6 +325,10 @@ void CharacterDatabaseConnection::DoPrepareStatements()
// For loading and deleting expired auctions at startup
PREPARE_STATEMENT(CHAR_SEL_EXPIRED_AUCTIONS, "SELECT id, auctioneerguid, itemguid, itemEntry, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid WHERE ah.time <= ?", CONNECTION_SYNCH)
+
+ // LFG Data
+ PREPARE_STATEMENT(CHAR_INS_LFG_DATA, "INSERT INTO lfg_data (guid, dungeon, state) VALUES (?, ?, ?)", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_DEL_LFG_DATA, "DELETE FROM lfg_data WHERE guid = ?", CONNECTION_ASYNC)
// Player saving
PREPARE_STATEMENT(CHAR_INS_CHARACTER, "INSERT INTO characters (guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index a239e274a54..18b488e055a 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -351,6 +351,9 @@ enum CharacterDatabaseStatements
CHAR_DEL_CHARACTER_SOCIAL,
CHAR_UPD_CHARACTER_SOCIAL_NOTE,
CHAR_UPD_CHARACTER_POSITION,
+
+ CHAR_INS_LFG_DATA,
+ CHAR_DEL_LFG_DATA,
MAX_CHARACTERDATABASE_STATEMENTS,
};