Dungeon Finder: Add vote kick support

--HG--
branch : trunk
This commit is contained in:
Spp
2010-08-13 15:38:10 +02:00
parent 55705e91d4
commit 3e29ae1ee8
7 changed files with 230 additions and 16 deletions
+149
View File
@@ -57,6 +57,10 @@ LFGMgr::~LFGMgr()
delete it->second;
m_Proposals.clear();
for (LfgPlayerBootMap::iterator it = m_Boots.begin(); it != m_Boots.end(); ++it)
delete it->second;
m_Boots.clear();
for (LfgRoleCheckMap::iterator it = m_RoleChecks.begin(); it != m_RoleChecks.end(); ++it)
delete it->second;
m_RoleChecks.clear();
@@ -1092,6 +1096,115 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t
m_Proposals.erase(itProposal);
}
/// <summary>
/// Initialize a boot kick vote
/// </summary>
/// <param name="Group *">Group</param>
/// <param name="uint32">Player low guid who inits the vote kick</param>
/// <param name="uint32">Player low guid to be kicked </param>
/// <param name="std::string">kick reason</param>
void LFGMgr::InitBoot(Group *grp, uint32 iLowGuid, uint32 vLowguid, std::string reason)
{
if (!grp)
return;
LfgPlayerBoot *pBoot = new LfgPlayerBoot();
pBoot->inProgress = true;
pBoot->cancelTime = time_t(time(NULL)) + LFG_TIME_BOOT;
pBoot->reason = reason;
pBoot->victimLowGuid = vLowguid;
pBoot->votedNeeded = GROUP_LFG_KICK_VOTES_NEEDED;
PlayerSet players;
uint32 pLowGuid = 0;
for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
{
if (Player *plrg = itr->getSource())
{
pLowGuid = plrg->GetGUIDLow();
if (pLowGuid == vLowguid)
pBoot->votes[pLowGuid] = 0; // Victim auto vote NO
else if (pLowGuid == iLowGuid)
pBoot->votes[pLowGuid] = 1; // Kicker auto vote YES
else
{
pBoot->votes[pLowGuid] = -1; // Other members need to vote
players.insert(plrg);
}
}
}
for (PlayerSet::const_iterator it = players.begin(); it != players.end(); ++it)
SendLfgBootPlayer(*it, pBoot);
grp->SetLfgKickActive(true);
m_Boots[grp->GetLowGUID()] = pBoot;
}
/// <summary>
/// Update Boot info with player answer
/// </summary>
/// <param name="Player *">Player guid</param>
/// <param name="uint8">Player answer</param>
void LFGMgr::UpdateBoot(Player *plr, uint8 accept)
{
Group *grp = plr ? plr->GetGroup() : NULL;
if (!grp)
return;
uint32 bootId = grp->GetLowGUID();
uint32 lowGuid = plr->GetGUIDLow();
LfgPlayerBootMap::iterator itBoot = m_Boots.find(bootId);
if (itBoot == m_Boots.end())
return;
LfgPlayerBoot *pBoot = itBoot->second;
if (!pBoot)
return;
if (pBoot->votes[lowGuid] != -1) // Cheat check: Player can't vote twice
return;
pBoot->votes[lowGuid] = accept;
uint8 votesNum = 0;
uint8 agreeNum = 0;
for (LfgAnswerMap::const_iterator itVotes = pBoot->votes.begin(); itVotes != pBoot->votes.end(); ++itVotes)
{
if (itVotes->second != -1)
{
++votesNum;
if (itVotes->second == 1)
++agreeNum;
}
}
if (agreeNum == pBoot->votedNeeded || // Vote passed
votesNum == pBoot->votes.size() || // All voted but not passed
(pBoot->votes.size() - votesNum + agreeNum) < pBoot->votedNeeded) // Vote didnt passed
{
// Send update info to all players
pBoot->inProgress = false;
for (LfgAnswerMap::const_iterator itVotes = pBoot->votes.begin(); itVotes != pBoot->votes.end(); ++itVotes)
if (Player *plrg = sObjectMgr.GetPlayer(itVotes->first))
if (plrg->GetGUIDLow() != pBoot->victimLowGuid)
SendLfgBootPlayer(plrg, pBoot);
if (agreeNum == pBoot->votedNeeded) // Vote passed - Kick player
{
Player::RemoveFromGroup(grp, MAKE_NEW_GUID(pBoot->victimLowGuid, 0, HIGHGUID_PLAYER));
if (Player *victim = sObjectMgr.GetPlayer(pBoot->victimLowGuid))
victim->TeleportToBGEntryPoint();
OfferContinue(grp);
grp->SetLfgKicks(grp->GetLfgKicks() + 1);
}
grp->SetLfgKickActive(false);
delete pBoot;
m_Boots.erase(itBoot);
}
}
/// <summary>
/// Teleports the player in or out the dungeon
/// </summary>
@@ -1305,6 +1418,42 @@ void LFGMgr::SendLfgPartyInfo(Player *plr)
}
}
/// <summary>
/// Build and Send LFG boot player info
/// </summary>
/// <param name="Player *">Player</param>
/// <param name="LfgPlayerBoot *">Boot info</param>
void LFGMgr::SendLfgBootPlayer(Player *plr, LfgPlayerBoot *pBoot)
{
sLog.outDebug("SMSG_LFG_BOOT_PLAYER");
int8 playerVote = pBoot->votes[plr->GetGUIDLow()];
uint8 votesNum = 0;
uint8 agreeNum = 0;
uint32 secsleft = uint8((pBoot->cancelTime - time(NULL)) / 1000);
for (LfgAnswerMap::const_iterator it = pBoot->votes.begin(); it != pBoot->votes.end(); ++it)
{
if (it->second != -1)
{
++votesNum;
if (it->second == 1)
++agreeNum;
}
}
WorldPacket data(SMSG_LFG_BOOT_PLAYER, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + pBoot->reason.length());
data << uint8(pBoot->inProgress); // Vote in progress
data << uint8(playerVote != -1); // Did Vote
data << uint8(playerVote == 1); // Agree
data << uint64(MAKE_NEW_GUID(pBoot->victimLowGuid, 0, HIGHGUID_PLAYER)); // Victim GUID
data << uint32(votesNum); // Total Votes
data << uint32(agreeNum); // Agree Count
data << uint32(secsleft); // Time Left
data << uint32(pBoot->votedNeeded); // Needed Votes
data << pBoot->reason.c_str(); // Kick reason
plr->GetSession()->SendPacket(&data);
}
/// <summary>
/// Build and Send LFG player reward
/// </summary>
+18 -8
View File
@@ -27,8 +27,8 @@
enum LFGenum
{
LFG_TIME_ROLECHECK = 2*MINUTE,
LFG_TIME_BOOT = 2*MINUTE,
LFG_TIME_PROPOSAL = 2*MINUTE,
LFG_VOTES_NEEDED = 3,
LFG_TANKS_NEEDED = 1,
LFG_HEALERS_NEEDED = 1,
LFG_DPS_NEEDED = 3,
@@ -158,13 +158,6 @@ enum LfgRewardEnums
LFG_REWARD_DATA_SIZE = 10,
};
enum LfgDungeonStatus
{
LFG_STATUS_SAVED = 0,
LFG_STATUS_NOT_SAVED = 1,
LFG_STATUS_COMPLETE = 2,
};
const uint32 RewardDungeonData[LFG_REWARD_DATA_SIZE+1][5] =
{ // XP, money, item, item display, count
{310, 3500, 51999, 56915, 1}, // Classic 15-23
@@ -273,6 +266,17 @@ struct LfgRoleCheck
uint32 leader;
};
// Stores information of a current vote to kick someone from a group
struct LfgPlayerBoot
{
time_t cancelTime; // Time left to vote
bool inProgress; // Vote in progress
LfgAnswerMap votes; // Player votes (-1 not answer | 0 Not agree | 1 agree)
uint32 victimLowGuid; // Player guid to be kicked (can't vote)
uint8 votedNeeded; // Votes needed to kick the player
std::string reason; // kick reason
};
typedef std::set<Player*> PlayerSet;
typedef std::set<LfgLockStatus*> LfgLockStatusSet;
typedef std::vector<LfgReward*> LfgRewardList;
@@ -282,6 +286,7 @@ typedef std::map<uint32, LfgLockStatusSet*> LfgLockStatusMap;
typedef std::map<uint64, LfgQueueInfo*> LfgQueueInfoMap;
typedef std::map<uint32, LfgRoleCheck*> LfgRoleCheckMap;
typedef std::map<uint32, LfgProposal*> LfgProposalMap;
typedef std::map<uint32, LfgPlayerBoot*> LfgPlayerBootMap;
typedef std::list<Player *> LfgPlayerList;
class LFGMgr
@@ -297,14 +302,17 @@ class LFGMgr
void OfferContinue(Group *grp);
void TeleportPlayer(Player *plr, bool out);
void UpdateProposal(uint32 proposalId, uint32 lowGuid, uint8 accept);
void UpdateBoot(Player *plr, uint8 accept);
void UpdateRoleCheck(Group *grp, Player *plr = NULL);
void Update(uint32 diff);
void SendLfgPlayerInfo(Player *plr);
void SendLfgPartyInfo(Player *plr);
bool isRandomDungeon(uint32 dungeonId);
void InitBoot(Group *grp, uint32 plowGuid, uint32 vlowGuid, std::string reason);
private:
void SendLfgBootPlayer(Player *plr, LfgPlayerBoot *pBoot);
void SendUpdateProposal(Player *plr, uint32 proposalId, LfgProposal *pProp);
void SendLfgPlayerReward(Player *plr);
@@ -312,6 +320,7 @@ class LFGMgr
void BuildAvailableRandomDungeonList(WorldPacket &data, Player *plr);
void BuildPlayerLockDungeonBlock(WorldPacket &data, LfgLockStatusSet *lockSet);
void BuildPartyLockDungeonBlock(WorldPacket &data, LfgLockStatusMap *lockMap);
void BuildBootPlayerBlock(WorldPacket &data, LfgPlayerBoot *pBoot, uint32 lowGuid);
void AddToQueue(uint64 guid, LfgRolesMap *roles, LfgDungeonSet *dungeons);
bool RemoveFromQueue(uint64 guid);
@@ -335,6 +344,7 @@ class LFGMgr
LfgGuidList m_currentQueue; // Ordered list. Used to find groups
LfgGuidList m_newToQueue; // New groups to add to queue;
LfgProposalMap m_Proposals; // Current Proposals
LfgPlayerBootMap m_Boots; // Current player kicks
LfgRoleCheckMap m_RoleChecks; // Current Role checks
uint32 m_QueueTimer; // used to check interval of update
uint32 m_lfgProposalId; // used as internal counter for proposals