uint32 Group::RemoveMember(const uint64 &guid) { uint32 i, j; bool leaderFlag; for( i = 0; i < m_count; i++ ) { if (m_members[i].guid == guid) { leaderFlag = m_members[i].guid == m_leaderGuid; for( j = i + 1; j < m_count; j++ ) { m_members[j-1].guid = m_members[j].guid; m_members[j-1].name = m_members[j].name; } break; } } m_count--; if (m_count > 1 && leaderFlag) ChangeLeader(m_members[0].guid); return m_count; }
bool Group::DelMemberOOZ(const char *Name, bool checkleader) { if(!Name) return false; bool removed = false; // If a member out of zone has disbanded, clear out their name. for(unsigned int i = 0; i < MAX_GROUP_MEMBERS; i++) { if(!strcasecmp(Name, membername[i])) { // This shouldn't be called if the member is in this zone. if(!members[i]) { memset(membername[i], 0, 64); MemberRoles[i] = 0; removed = true; Log.Out(Logs::Detail, Logs::Group, "DelMemberOOZ: Removed Member: %s", Name); break; } } } if(GroupCount() < 2) { DisbandGroup(); return true; } if(checkleader) { Log.Out(Logs::Detail, Logs::Group, "DelMemberOOZ: Checking leader..."); if (strcmp(GetOldLeaderName(),Name) == 0 && GroupCount() >= 2) { for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) { if(members[nl]) { if (members[nl]->IsClient()) { ChangeLeader(members[nl]); break; } } } } } return removed; }
// removes a client from a lobby. (returns false if the client isn't in the lobby) bool RemoveClient(LOBBY* l,CLIENT* c) { unsigned int x; operation_lock(l); for (x = 0; x < l->maxClients; x++) if (l->clients[x] == c) break; if (x >= l->maxClients) { operation_unlock(l); return false; } operation_lock(c); l->clients[x] = NULL; c->lobbyID = 0; operation_unlock(c); ChangeLeader(l,x); operation_unlock(l); return true; }
void Group::_chooseLeader(bool offline /*= false*/) { if (GetMembersCount() < GetMembersMinCount()) return; ObjectGuid first = ObjectGuid(); // First available: if no suitable canditates are found ObjectGuid chosen = ObjectGuid(); // Player matching prio creteria for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) { if (citr->guid == m_leaderGuid) continue; // Prioritize online players Player* player = sObjectMgr.GetPlayer(citr->guid); if (!player || !player->GetSession() || player->GetGroup() != this) continue; // Prioritize assistants for raids if (isRaidGroup() && !citr->assistant) { if (first.IsEmpty()) first = citr->guid; continue; } chosen = citr->guid; break; } if (chosen.IsEmpty()) chosen = first; // If we are choosing a new leader due to inactivity, check if everyone is offline first if (offline && chosen.IsEmpty()) return; // Still nobody online... if (chosen.IsEmpty()) chosen = m_memberSlots.front().guid; // Do announce if we are choosing a new leader due to old one being offline return (offline ? ChangeLeader(chosen) : _setLeader(chosen)); }
// atomically changes a client's lobby. this is necessary since changing lobbies // by calling AddClient/RemoveClient can cause massive errors if two clients do // it at the same time. // note that this function assigns client IDs from the end, backwards (i.e. 11 is // first, 0 is last in lobbies; blue is first, red is last in games). I use this // to debug some in-game commands that put the client ID in odd places. to change // this behavior back to normal, replace the two lines above the commented lines // with the commented lines. bool ChangeLobby(LOBBY* current,LOBBY* next,CLIENT* c) { if (current == next) return true; unsigned int nx,cx,num; operation_lock(next); num = CountLobbyPlayers(next); if ((num == 0xFFFFFFFF) || (num >= next->maxClients)) { operation_unlock(next); return false; } for (nx = next->maxClients - 1; nx >= 0; nx--) if (!next->clients[nx]) break; if (nx < 0) //for (nx = 0; nx < next->maxClients; nx++) if (!next->clients[nx]) break; //if (nx >= next->maxClients) { operation_unlock(next); return false; } operation_lock(current); for (cx = 0; cx < current->maxClients; cx++) if (current->clients[cx] == c) break; if (cx >= current->maxClients) { operation_unlock(current); operation_unlock(next); return false; } current->clients[cx] = NULL; ChangeLeader(current,cx); next->clients[nx] = c; if (num == 0) next->leaderID = nx; operation_lock(c); c->clientID = nx; c->lobbyID = next->lobbyID; operation_unlock(c); operation_unlock(current); operation_unlock(next); return true; }
bool Group::DelMember(Mob* oldmember,bool ignoresender) { if (oldmember == nullptr){ return false; } for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { if (members[i] == oldmember) { members[i] = nullptr; membername[i][0] = '\0'; memset(membername[i],0,64); MemberRoles[i] = 0; break; } } //handle leader quitting group gracefully if (oldmember == GetLeader() && GroupCount() >= 2) { for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) { if(members[nl]) { ChangeLeader(members[nl]); break; } } } ServerPacket* pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct)); ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer; gl->gid = GetID(); gl->zoneid = zone->GetZoneID(); gl->instance_id = zone->GetInstanceID(); strcpy(gl->member_name, oldmember->GetName()); worldserver.SendPacket(pack); safe_delete(pack); EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupLeader_Struct)); GroupLeader_Struct* gu = (GroupLeader_Struct*) outapp->pBuffer; gu->action = groupActLeave; strcpy(gu->membername, oldmember->GetCleanName()); strcpy(gu->yourname, oldmember->GetCleanName()); for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { if (members[i] == nullptr) { //if (DEBUG>=5) LogFile->write(EQEMuLog::Debug, "Group::DelMember() null member at slot %i", i); continue; } if (members[i] != oldmember) { strcpy(gu->yourname, members[i]->GetCleanName()); if(members[i]->IsClient()) members[i]->CastToClient()->QueuePacket(outapp); } } if (!ignoresender) { strcpy(gu->yourname,oldmember->GetCleanName()); strcpy(gu->membername,oldmember->GetCleanName()); gu->action = groupActLeave; if(oldmember->IsClient()) oldmember->CastToClient()->QueuePacket(outapp); } if(oldmember->IsClient()) database.SetGroupID(oldmember->GetCleanName(), 0, oldmember->CastToClient()->CharacterID()); oldmember->SetGrouped(false); disbandcheck = true; safe_delete(outapp); return true; }
//================================================================================================= void TeamPanel::Update(float dt) { GamePanel::Update(dt); if(focus) { if(Key.Focus() && IsInside(GUI.cursor_pos)) scrollbar.ApplyMouseWheel(); scrollbar.mouse_focus = mouse_focus; scrollbar.Update(dt); if(picking && Key.Focus()) { picked = -1; GUI.Intersect(hitboxes, GUI.cursor_pos, &picked); if(Key.Pressed(VK_LBUTTON)) { picking = false; if(picked >= 0) { target = Team.members[picked]; switch(mode) { case Bt_GiveGold: GiveGold(); break; case Bt_Kick: Kick(); break; case Bt_Leader: ChangeLeader(); break; } } } else if(Key.Pressed(VK_RBUTTON)) picking = false; } } // enable change leader button if player is leader if(Net::IsClient()) { bool was_leader = bt[2].state != Button::DISABLED; bool is_leader = Team.IsLeader(); if(was_leader != is_leader) bt[2].state = (is_leader ? Button::NONE : Button::DISABLED); } int count = (Net::IsOnline() ? 4 : 2); for(int i = 0; i < count; ++i) { bt[i].mouse_focus = focus; bt[i].Update(dt); } if(focus && Key.Focus() && Key.PressedRelease(VK_ESCAPE)) Hide(); }
// 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; }
bool Group::DelMember(Mob* oldmember,bool ignoresender) { if (oldmember == nullptr) { return false; } for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { if (members[i] == oldmember) { members[i] = nullptr; membername[i][0] = '\0'; memset(membername[i],0,64); MemberRoles[i] = 0; Log.Out(Logs::Detail, Logs::Group, "DelMember: Removed Member: %s", oldmember->GetCleanName()); break; } } if(GroupCount() < 2) { DisbandGroup(); return true; } // If the leader has quit and we have 2 or more players left in group, we want to first check the zone the old leader was in for a new leader. // If a suitable replacement cannot be found, we need to go out of zone. If checkleader remains true after this method completes, another // loop will be run in DelMemberOOZ. bool checkleader = true; if (strcmp(GetOldLeaderName(),oldmember->GetCleanName()) == 0 && GroupCount() >= 2) { for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) { if(members[nl]) { if (members[nl]->IsClient()) { ChangeLeader(members[nl]); checkleader = false; break; } } } } ServerPacket* pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct)); ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer; gl->gid = GetID(); gl->zoneid = zone->GetZoneID(); gl->instance_id = zone->GetInstanceID(); strcpy(gl->member_name, oldmember->GetName()); gl->checkleader = checkleader; worldserver.SendPacket(pack); safe_delete(pack); EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gu = (GroupJoin_Struct*)outapp->pBuffer; gu->action = groupActLeave; strcpy(gu->membername, oldmember->GetCleanName()); strcpy(gu->yourname, oldmember->GetCleanName()); for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { if (members[i] == nullptr) { //if (DEBUG>=5) Log.Out(Logs::Detail, Logs::Group, "Group::DelMember() null member at slot %i", i); continue; } if (members[i] != oldmember) { strcpy(gu->yourname, members[i]->GetCleanName()); if(members[i]->IsClient()) members[i]->CastToClient()->QueuePacket(outapp); } } if (!ignoresender) { strcpy(gu->yourname,oldmember->GetCleanName()); strcpy(gu->membername,oldmember->GetCleanName()); gu->action = groupActLeave; if(oldmember->IsClient()) oldmember->CastToClient()->QueuePacket(outapp); } if(oldmember->IsClient()) { database.SetGroupID(oldmember->GetCleanName(), 0, oldmember->CastToClient()->CharacterID()); } oldmember->SetGrouped(false); disbandcheck = true; safe_delete(outapp); return true; }