예제 #1
0
GroupJoinBattlegroundResult Group::CanJoinBattleGroundQueue(BattleGround const* bgOrTemplate, BattleGroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 /*MaxPlayerCount*/, bool isRated, uint32 arenaSlot)
{
    BattlemasterListEntry const* bgEntry = sBattlemasterListStore.LookupEntry(bgOrTemplate->GetTypeID());
    if (!bgEntry)
        return ERR_GROUP_JOIN_BATTLEGROUND_FAIL;            // shouldn't happen

    // check for min / max count
    uint32 memberscount = GetMembersCount();

    // only check for MinPlayerCount since MinPlayerCount == MaxPlayerCount for arenas...
    if (bgOrTemplate->isArena() && memberscount != MinPlayerCount)
        return ERR_ARENA_TEAM_PARTY_SIZE;

    if (memberscount > bgEntry->maxGroupSize)               // no MinPlayerCount for battlegrounds
        return ERR_BATTLEGROUND_NONE;                       // ERR_GROUP_JOIN_BATTLEGROUND_TOO_MANY handled on client side

    // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.)
    Player* reference = GetFirstMember()->getSource();
    // no reference found, can't join this way
    if (!reference)
        return ERR_BATTLEGROUND_JOIN_FAILED;

    PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bgOrTemplate->GetMapId(), reference->getLevel());
    if (!bracketEntry)
        return ERR_BATTLEGROUND_JOIN_FAILED;

    uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot);
    Team team = reference->GetTeam();

    // check every member of the group to be able to join
    for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
    {
        Player* member = itr->getSource();
        // offline member? don't let join
        if (!member)
            return ERR_BATTLEGROUND_JOIN_FAILED;
        // don't allow cross-faction join as group
        if (member->GetTeam() != team)
            return ERR_BATTLEGROUND_JOIN_TIMED_OUT;
        // not in the same battleground level bracket, don't let join
        PvPDifficultyEntry const* memberBracketEntry = GetBattlegroundBracketByLevel(bracketEntry->mapId, member->getLevel());
        if (memberBracketEntry != bracketEntry)
            return ERR_BATTLEGROUND_JOIN_RANGE_INDEX;
        // don't let join rated matches if the arena team id doesn't match
        if (isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId)
            return ERR_BATTLEGROUND_JOIN_FAILED;
        // don't let join if someone from the group is already in that bg queue
        if (member->InBattleGroundQueueForBattleGroundQueueType(bgQueueTypeId))
            return ERR_BATTLEGROUND_JOIN_FAILED;            // not blizz-like
        // check for deserter debuff in case not arena queue
        if (bgOrTemplate->GetTypeID() != BATTLEGROUND_AA && !member->CanJoinToBattleground())
            return ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS;
        // check if member can join any more battleground queues
        if (!member->HasFreeBattleGroundQueueId())
            return ERR_BATTLEGROUND_TOO_MANY_QUEUES;        // not blizz-like
    }
    return GroupJoinBattlegroundResult(bgOrTemplate->GetTypeID());
}
예제 #2
0
void Group::GetDataForXPAtKill(Unit const* victim, uint32& count, uint32& sum_level, Player*& member_with_max_level, Player*& not_gray_member_with_max_level, Player* additional)
{
    for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
    {
        Player* member = itr->getSource();
        if (!member || !member->isAlive())                  // only for alive
            continue;

        // will proccesed later
        if (member == additional)
            continue;

        if (!member->IsAtGroupRewardDistance(victim))       // at req. distance
            continue;

        ++count;
        GetDataForXPAtKill_helper(member, victim, sum_level, member_with_max_level, not_gray_member_with_max_level);
    }

    if (additional)
    {
        if (additional->IsAtGroupRewardDistance(victim))    // at req. distance
        {
            ++count;
            GetDataForXPAtKill_helper(additional, victim, sum_level, member_with_max_level, not_gray_member_with_max_level);
        }
    }
}
예제 #3
0
파일: Group.cpp 프로젝트: AlexHjelm/Core
uint32 Group::CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, BattleGroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot)
{
    // check for min / max count
    uint32 memberscount = GetMembersCount();
    if (memberscount < MinPlayerCount)
        return BG_JOIN_ERR_GROUP_NOT_ENOUGH;
    if (memberscount > MaxPlayerCount)
        return BG_JOIN_ERR_GROUP_TOO_MANY;

    // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.)
    Player* reference = GetFirstMember()->getSource();
    // no reference found, can't join this way
    if (!reference)
        return BG_JOIN_ERR_OFFLINE_MEMBER;

    BattleGroundBracketId bracket_id = reference->GetBattleGroundBracketIdFromLevel(bgTypeId);
    uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot);
    Team team = reference->GetTeam();

    // check every member of the group to be able to join
    for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
    {
        Player* member = itr->getSource();
        // offline member? don't let join
        if (!member)
            return BG_JOIN_ERR_OFFLINE_MEMBER;
        // don't allow cross-faction join as group
        if (member->GetTeam() != team)
            return BG_JOIN_ERR_MIXED_FACTION;
        // not in the same battleground level bracket, don't let join
        if (member->GetBattleGroundBracketIdFromLevel(bgTypeId) != bracket_id)
            return BG_JOIN_ERR_MIXED_LEVELS;
        // don't let join rated matches if the arena team id doesn't match
        if (isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId)
            return BG_JOIN_ERR_MIXED_ARENATEAM;
        // don't let join if someone from the group is already in that bg queue
        if (member->InBattleGroundQueueForBattleGroundQueueType(bgQueueTypeId))
            return BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE;
        // check for deserter debuff in case not arena queue
        if (bgTypeId != BATTLEGROUND_AA && !member->CanJoinToBattleground())
            return BG_JOIN_ERR_GROUP_DESERTER;
        // check if member can join any more battleground queues
        if (!member->HasFreeBattleGroundQueueId())
            return BG_JOIN_ERR_ALL_QUEUES_USED;
    }
    return BG_JOIN_ERR_OK;
}
예제 #4
0
bool Group::InCombatToInstance(uint32 instanceId)
{
    for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
    {
        Player* pPlayer = itr->getSource();
        if (pPlayer->getAttackers().size() && pPlayer->GetInstanceId() == instanceId)
            return true;
    }
    return false;
}
예제 #5
0
void Group::BroadcastReadyCheck(WorldPacket* packet)
{
    for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
    {
        Player* pl = itr->getSource();
        if (pl && pl->GetSession())
            if (IsLeader(pl->GetObjectGuid()) || IsAssistant(pl->GetObjectGuid()))
                pl->GetSession()->SendPacket(packet);
    }
}
예제 #6
0
void Group::BroadcastReadyCheck(WorldPacket const& packet) const
{
    for (auto itr = GetFirstMember(); itr != nullptr; itr = itr->next())
    {
        Player* pl = itr->getSource();
        if (pl && pl->GetSession())
            if (IsLeader(pl->GetObjectGuid()) || IsAssistant(pl->GetObjectGuid()))
                pl->GetSession()->SendPacket(packet);
    }
}
예제 #7
0
void Group::BroadcastPacket(WorldPacket* packet, bool ignorePlayersInBGRaid, int group, ObjectGuid ignore)
{
    for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
    {
        Player* pl = itr->getSource();
        if (!pl || (ignore && pl->GetObjectGuid() == ignore) || (ignorePlayersInBGRaid && pl->GetGroup() != this))
            continue;

        if (pl->GetSession() && (group == -1 || itr->getSubGroup() == group))
            pl->GetSession()->SendPacket(packet);
    }
}
예제 #8
0
파일: Group.cpp 프로젝트: AlexHjelm/Core
void Group::SetDifficulty(Difficulty difficulty)
{
    m_difficulty = difficulty;
    if (!isBGGroup())
        CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE groupId='%u'", m_difficulty, m_Id);

    for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
    {
        Player* player = itr->getSource();
        if (!player->GetSession() || player->getLevel() < LEVELREQUIREMENT_HEROIC)
            continue;
        player->SetDifficulty(difficulty);
        player->SendDungeonDifficulty(true);
    }
}
예제 #9
0
/** Provide rewards to group members at unit kill
 *
 * @param pVictim       Killed unit
 * @param player_tap    Player who tap unit if online, it can be group member or can be not if leaved after tap but before kill target
 *
 * Rewards received by group members and player_tap
 */
void Group::RewardGroupAtKill(Unit* pVictim, Player* player_tap)
{
    bool PvP = pVictim->isCharmedOwnedByPlayerOrPlayer();

    // prepare data for near group iteration (PvP and !PvP cases)
    uint32 xp = 0;

    uint32 count = 0;
    uint32 sum_level = 0;
    Player* member_with_max_level = NULL;
    Player* not_gray_member_with_max_level = NULL;

    GetDataForXPAtKill(pVictim, count, sum_level, member_with_max_level, not_gray_member_with_max_level, player_tap);

    if (member_with_max_level)
    {
        /// not get Xp in PvP or no not gray players in group
        xp = (PvP || !not_gray_member_with_max_level) ? 0 : MaNGOS::XP::Gain(not_gray_member_with_max_level, pVictim);

        /// skip in check PvP case (for speed, not used)
        bool is_raid = PvP ? false : sMapStore.LookupEntry(pVictim->GetMapId())->IsRaid() && isRaidGroup();
        bool is_dungeon = PvP ? false : sMapStore.LookupEntry(pVictim->GetMapId())->IsDungeon();
        float group_rate = MaNGOS::XP::xp_in_group_rate(count, is_raid);

        for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
        {
            Player* pGroupGuy = itr->getSource();
            if (!pGroupGuy)
                continue;

            // will proccessed later
            if (pGroupGuy == player_tap)
                continue;

            if (!pGroupGuy->IsAtGroupRewardDistance(pVictim))
                continue;                               // member (alive or dead) or his corpse at req. distance

            RewardGroupAtKill_helper(pGroupGuy, pVictim, count, PvP, group_rate, sum_level, is_dungeon, not_gray_member_with_max_level, member_with_max_level, xp);
        }

        if (player_tap)
        {
            // member (alive or dead) or his corpse at req. distance
            if (player_tap->IsAtGroupRewardDistance(pVictim))
                RewardGroupAtKill_helper(player_tap, pVictim, count, PvP, group_rate, sum_level, is_dungeon, not_gray_member_with_max_level, member_with_max_level, xp);
        }
    }
}
예제 #10
0
void Group::UpdatePlayerOutOfRange(Player* pPlayer)
{
    if (!pPlayer || !pPlayer->IsInWorld())
        return;

    if (pPlayer->GetGroupUpdateFlag() == GROUP_UPDATE_FLAG_NONE)
        return;

    WorldPacket data;
    pPlayer->GetSession()->BuildPartyMemberStatsChangedPacket(pPlayer, &data);

    for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
        if (Player* player = itr->getSource())
            if (player != pPlayer && !player->HaveAtClient(pPlayer))
                player->GetSession()->SendPacket(&data);
}
예제 #11
0
uint32 Group::GetMaxSkillValueForGroup(SkillType skill)
{
    uint32 maxvalue = 0;

    for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
    {
        Player* member = itr->getSource();
        if (!member)
            continue;

        uint32 value = member->GetSkillValue(skill);
        if (maxvalue < value)
            maxvalue = value;
    }

    return maxvalue;
}
예제 #12
0
void LfgGroup::KilledCreature(Creature *creature)
{
    if ((creature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) &&
        m_instanceStatus == INSTANCE_NOT_SAVED)
    {
        m_instanceStatus = INSTANCE_SAVED;
    }
    
    if (!m_awarded && creature->GetEntry() == sLfgMgr.GetDungeonInfo(m_dungeonInfo->ID)->lastBossId)
    {
        //Last boss
        m_instanceStatus = INSTANCE_COMPLETED;
        //Reward here
        for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
        {
            Player *plr = itr->getSource();
            if (!plr || !plr->IsInWorld())
                continue;
            WorldPacket data(SMSG_LFG_PLAYER_REWARD);
            data << uint32(GetDungeonInfo((IsRandom() || IsFromRnd(plr->GetGUID())))->Entry());
            data << uint32(m_dungeonInfo->Entry());

            uint32 ID = GetDungeonInfo((IsRandom() || IsFromRnd(plr->GetGUID())))->ID;
            sLfgMgr.BuildRewardBlock(&data, ID, plr);
            plr->GetSession()->SendPacket(&data);
            LfgReward *reward = sLfgMgr.GetDungeonReward(ID, plr->m_lookingForGroup.DoneDungeon(ID, plr), plr->getLevel());
            if (!reward)
                continue;
            plr->CompleteQuest(reward->questInfo->GetQuestId());
            if (IsRandom())
                plr->RemoveAurasDueToSpell(LFG_RANDOM_COOLDOWN);
        }
        m_awarded = true;
    }  
    SendUpdate();
}
예제 #13
0
bool Group::_addMember(ObjectGuid guid, const char* name, bool isAssistant, uint8 group)
{
    if (IsFull())
        return false;

    if (!guid)
        return false;

    Player* player = sObjectMgr.GetPlayer(guid, false);

    uint32 lastMap = 0;
    if (player && player->IsInWorld())
        lastMap = player->GetMapId();
    else if (player && player->IsBeingTeleported())
        lastMap = player->GetTeleportDest().mapid;

    MemberSlot member;
    member.guid      = guid;
    member.name      = name;
    member.group     = group;
    member.assistant = isAssistant;
    member.lastMap   = lastMap;
    m_memberSlots.push_back(member);

    SubGroupCounterIncrease(group);

    if (player)
    {
        player->SetGroupInvite(nullptr);
        // if player is in group and he is being added to BG raid group, then call SetBattleGroundRaid()
        if (player->GetGroup() && isBattleGroup())
            player->SetBattleGroundRaid(this, group);
        // if player is in bg raid and we are adding him to normal group, then call SetOriginalGroup()
        else if (player->GetGroup())
            player->SetOriginalGroup(this, group);
        // if player is not in group, then call set group
        else
            player->SetGroup(this, group);

        if (player->IsInWorld())
        {
            // if the same group invites the player back, cancel the homebind timer
            if (InstanceGroupBind* bind = GetBoundInstance(player->GetMapId()))
                if (bind->state->GetInstanceId() == player->GetInstanceId())
                    player->m_InstanceValid = true;
        }

        if (player->IsPvPFreeForAll())
        {
            player->ForceHealthAndPowerUpdate();
            for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
            {
                Player* groupMember = itr->getSource();
                if (groupMember && groupMember->GetSession())
                    groupMember->ForceHealthAndPowerUpdate();
            }
        }
    }

    if (!isRaidGroup())                                     // reset targetIcons for non-raid-groups
    {
        for (auto& m_targetIcon : m_targetIcons)
            m_targetIcon.Clear();
    }

    if (!isBattleGroup())
    {
        // insert into group table
        CharacterDatabase.PExecute("INSERT INTO group_member(groupId,memberGuid,assistant,subgroup) VALUES('%u','%u','%u','%u')",
                                   m_Id, member.guid.GetCounter(), ((member.assistant == 1) ? 1 : 0), member.group);
    }

    return true;
}
예제 #14
0
void LfgGroup::TeleportPlayer(Player *plr, DungeonInfo *dungeonInfo, uint32 originalDungeonId, bool newPlr)
{
    if(newPlr)
    {
        plr->m_lookingForGroup.queuedDungeons.clear(); // must be before remove grom group
        if (Group *group = plr->GetGroup())
        {
            if (!group->isLfgGroup())
            {
                group->RemoveMember(plr->GetGUID(), 0);
                if (group->GetMembersCount() == 0)
                    group->Disband(true);
            }
            plr->SetGroup(NULL);
        }

        plr->UnbindInstance(dungeonInfo->start_map, m_dungeonInfo->isHeroic() ? DUNGEON_DIFFICULTY_HEROIC : DUNGEON_DIFFICULTY_NORMAL);
        plr->ResetInstances(INSTANCE_RESET_GROUP_JOIN,false);
        plr->ResetInstances(INSTANCE_RESET_GROUP_JOIN,true);
        plr->ResetInstances(INSTANCE_RESET_ALL, true);
        plr->ResetInstances(INSTANCE_RESET_ALL, false);

        if (plr->getLevel() >= LEVELREQUIREMENT_HEROIC)
        {
            if (plr->GetDungeonDifficulty() != GetDungeonDifficulty())
                plr->SetDungeonDifficulty(GetDungeonDifficulty());
            if (plr->GetRaidDifficulty() != GetRaidDifficulty())
                plr->SetRaidDifficulty(GetRaidDifficulty());
        }
        plr->SetGroup(this, 0);
        plr->SetGroupInvite(NULL);

        uint32 taxi_start = 0;
        uint32 taxi_end = 0;
        uint32 mount_spell = 0;
        WorldLocation joinLoc;
        if (!plr->m_taxi.empty())
        {
           taxi_start = plr->m_taxi.GetTaxiSource();
           taxi_end = plr->m_taxi.GetTaxiDestination();
           joinLoc = WorldLocation(plr->GetMapId(), plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetOrientation());
        }
        else
        {
            // Mount spell id storing
            if (plr->IsMounted())
            {
                Unit::AuraList const& auras = plr->GetAurasByType(SPELL_AURA_MOUNTED);
                if (!auras.empty())
                    mount_spell = (*auras.begin())->GetId();
            }
            if(!mount_spell && plr->getClass() == CLASS_DRUID)
            {
                Unit::AuraList const& auras = plr->GetAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
                if (!auras.empty())
                    mount_spell = (*auras.begin())->GetId();
            }
            //Nearest graveyard if in dungeon
            if (plr->GetMap()->IsDungeon())
            {
                if (const WorldSafeLocsEntry* entry = sObjectMgr.GetClosestGraveYard(plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetMapId(), plr->GetTeam()))
                    joinLoc = WorldLocation(entry->map_id, entry->x, entry->y, entry->z, 0.f);
                else
                    joinLoc = plr->GetLocation();
            }
            else
                joinLoc = plr->GetLocation();
        }
        CharacterDatabase.PExecute("DELETE FROM group_member WHERE memberGuid='%u'", GUID_LOPART(plr->GetGUID()));
        CharacterDatabase.PExecute("INSERT INTO group_member(groupId,memberGuid,assistant,subgroup,lfg_join_x,lfg_join_y,lfg_join_z,lfg_join_o,lfg_join_map,taxi_start,taxi_end,mount_spell) "
            "VALUES('%u','%u','%u','%u','%f','%f','%f','%f','%u','%u','%u','%u')",
            m_Id, GUID_LOPART(plr->GetGUID()), 0, 1, joinLoc.x(), joinLoc.y(), joinLoc.z(), joinLoc.orientation, joinLoc.mapid, taxi_start, taxi_end, mount_spell);

        //Set info to player
        plr->m_lookingForGroup.joinLoc = joinLoc;
        plr->m_lookingForGroup.taxi_start = taxi_start;
        plr->m_lookingForGroup.taxi_end = taxi_end;
        plr->m_lookingForGroup.mount_spell = mount_spell;
        plr->m_lookingForGroup.roles = GetPlayerRole(plr->GetGUID());

        if (IsRandom())
            plr->CastSpell(plr, LFG_RANDOM_COOLDOWN, true);
    }

    // resurrect the player
    if (!plr->isAlive())
    {
        plr->ResurrectPlayer(1.0f);
        plr->SpawnCorpseBones();
    }
    // stop taxi flight at port
    if (plr->isInFlight())
    {
        plr->GetMotionMaster()->MovementExpired(false);
        plr->GetMotionMaster()->Clear(false, true);
        plr->GetMotionMaster()->MoveIdle();
        plr->m_taxi.ClearTaxiDestinations();
    }
    
    plr->ScheduleDelayedOperation(DELAYED_LFG_ENTER_DUNGEON);
    plr->ScheduleDelayedOperation(DELAYED_SAVE_PLAYER);
    plr->ScheduleDelayedOperation(DELAYED_LFG_CLEAR_LOCKS);

    if(IsMixed())
    {
        plr->m_lookingForGroup.SetMixedDungeon(dungeonInfo->start_map);
        if(newPlr)
            plr->setFaction(sWorld.getConfig(CONFIG_UINT32_TEAM_BG_FACTION_BLUE));
    }

    if (IsInDungeon())
    {
        if(newPlr)
        {
            for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
            {
                Player *player = itr->getSource();
                if (!player  || player->GetMapId() != GetDungeonInfo()->map)
                    continue;

                plr->TeleportTo(player->GetLocation());
                return;
            }
        }
        plr->TeleportTo(dungeonInfo->start_map, dungeonInfo->start_x, dungeonInfo->start_y, dungeonInfo->start_z, dungeonInfo->start_o);
        return;
    }

    //Must re-add player to reset id...
    Map *map = plr->GetMap();
    if(map->GetId() == dungeonInfo->start_map)
    {
        map->Remove(plr, false);
        map->Add(plr);
    }
    
    plr->TeleportTo(dungeonInfo->start_map, dungeonInfo->start_x,
        dungeonInfo->start_y, dungeonInfo->start_z, dungeonInfo->start_o);
}
예제 #15
0
// return true = remove from update list, false = continue
bool LfgGroup::UpdateVoteToKick(uint32 diff)
{
    if (!m_voteToKick.isInProggres)
        return true;

    if (diff)
    {
        if (m_voteToKick.GetTimeLeft() <= 0)
        {
            m_voteToKick.isInProggres = false;
            for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
            {
                Player *member = sObjectMgr.GetPlayer(citr->guid);
                if (!member || !member->GetSession())
                    continue;
                SendBootPlayer(member);
            }
            m_voteToKick.Reset();
            return true;
        }
        return false;
    }

    //Send Update
    for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
    {
        Player *member = sObjectMgr.GetPlayer(citr->guid);
        if (!member || !member->GetSession())
            continue;
        SendBootPlayer(member);
    }

    if (m_voteToKick.GetVotesNum(false) < 3)
        return false;
    else if (m_voteToKick.GetVotesNum(true) >= 3)
    {
        
        Player *victim = sObjectMgr.GetPlayer(m_voteToKick.victim);
         sLfgMgr.LfgLog("Remove member - afk rolecheck");
        RemoveMember(m_voteToKick.victim, 1);
        if (victim && victim->GetSession())
        {
            victim->ScheduleDelayedOperation(DELAYED_LFG_MOUNT_RESTORE);
            victim->ScheduleDelayedOperation(DELAYED_LFG_TAXI_RESTORE);
            victim->ScheduleDelayedOperation(DELAYED_LFG_CLEAR_LOCKS);
            victim->RemoveAurasDueToSpell(LFG_BOOST);
            WorldLocation teleLoc = victim->m_lookingForGroup.joinLoc;
            if (!teleLoc.coords.isNULL())
                victim->TeleportTo(teleLoc);
            else
                victim->TeleportToHomebind();
        }
        else
        {
            AreaTrigger const *trigger = sObjectMgr.GetGoBackTrigger(GetDungeonInfo()->map);
            if(trigger)
                Player::SavePositionInDB(trigger->target_mapId, trigger->target_X, trigger->target_Y, trigger->target_Z, trigger->target_Orientation,
                    sTerrainMgr.GetZoneId(trigger->target_mapId, trigger->target_X, trigger->target_Y, trigger->target_Z), m_voteToKick.victim);
        }
        //Change leader
        if (m_voteToKick.victim == m_leaderGuid)
        {
            for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
            {
                Player *plr = sObjectMgr.GetPlayer(citr->guid);
                if (!plr || !plr->GetSession())
                    continue;
                if (plr->m_lookingForGroup.roles & LEADER)
                {
                    ChangeLeader(plr->GetGUID());
                    break;
                }
            }
            if (m_voteToKick.victim == m_leaderGuid)
                ChangeLeader(GetFirstMember()->getSource()->GetGUID());            
        }

        m_voteToKick.Reset();
        SendUpdate();
        return true;
    }
    return false;
}
예제 #16
0
uint32 Group::RemoveMember(ObjectGuid guid, uint8 method)
{
    Player* player = sObjectMgr.GetPlayer(guid);
#ifdef BUILD_PLAYERBOT
    // if master leaves group, all bots leave group
    if (player && player->GetPlayerbotMgr())
        player->GetPlayerbotMgr()->RemoveAllBotsFromGroup();
#endif

    for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
    {
        if (Player* groupMember = itr->getSource())
        {
            if (groupMember->GetObjectGuid() == guid)
                continue;

            groupMember->RemoveAllGroupBuffsFromCaster(guid);
            if (player)
                player->RemoveAllGroupBuffsFromCaster(groupMember->GetObjectGuid());
        }
    }

    // remove member and change leader (if need) only if strong more 2 members _before_ member remove
    if (GetMembersCount() > GetMembersMinCount())
    {
        bool leaderChanged = _removeMember(guid);

        if (player)
        {
            // quest related GO state dependent from raid membership
            if (isRaidGroup())
                player->UpdateForQuestWorldObjects();

            WorldPacket data;

            if (method == 1)
            {
                data.Initialize(SMSG_GROUP_UNINVITE, 0);
                player->GetSession()->SendPacket(data);
            }

            // we already removed player from group and in player->GetGroup() is his original group!
            if (Group* group = player->GetGroup())
            {
                group->SendUpdate();
            }
            else
            {
                data.Initialize(SMSG_GROUP_LIST, 24);
                data << uint64(0) << uint64(0) << uint64(0);
                player->GetSession()->SendPacket(data);
            }

            _homebindIfInstance(player);
        }

        if (leaderChanged)
        {
            WorldPacket data(SMSG_GROUP_SET_LEADER, (m_leaderName.size() + 1));
            data << m_leaderName;
            BroadcastPacket(data, true);
        }

        SendUpdate();
    }
    // if group before remove <= 2 disband it
    else
        Disband(true);

    return m_memberSlots.size();
}