void C4TeamList::ReassignAllTeams() { assert(::Control.isCtrlHost()); if (!::Control.isCtrlHost()) return; // go through all player infos; reset team in them int32_t idStart = -1; C4PlayerInfo *pNfo; while ((pNfo = Game.PlayerInfos.GetNextPlayerInfoByID(idStart))) { idStart = pNfo->GetID(); if (pNfo->HasJoinIssued()) continue; pNfo->SetTeam(0); // mark changed info as updated C4ClientPlayerInfos *pCltInfo = Game.PlayerInfos.GetClientInfoByPlayerID(idStart); assert(pCltInfo); if (pCltInfo) { pCltInfo->SetUpdated(); } } // clear players from team lists RecheckPlayers(); EnsureTeamCount(); // reassign them idStart = -1; while ((pNfo = Game.PlayerInfos.GetNextPlayerInfoByID(idStart))) { idStart = pNfo->GetID(); if (pNfo->HasJoinIssued()) continue; assert(!pNfo->GetTeam()); RecheckPlayerInfoTeams(*pNfo, true); } }
void C4TeamList::RecheckTeams() { // automatic team distributions only if (!IsRandomTeam()) return; // host decides random teams if (!::Control.isCtrlHost()) { // Still make sure that we have the right number of teams on the clients as well so that // GetTeamCount() does not report inconsistent values. EnsureTeamCount(); return; } // random teams in auto generate mode? Make sure there are exactly two teams if (IsAutoGenerateTeams() && GetTeamCount() != 2) { ReassignAllTeams(); return; } // redistribute players of largest team that has relocatable players left towards smaller teams for (;;) { C4Team *pLowestTeam = GetRandomSmallestTeam(); if (!pLowestTeam) break; // no teams: Nothing to re-distribute. // get largest team that has relocateable players C4Team *pLargestTeam = nullptr; C4Team **ppCheck=ppList; int32_t iCnt=iTeamCount; for (; iCnt--; ++ppCheck) if (!pLargestTeam || pLargestTeam->GetPlayerCount() > (*ppCheck)->GetPlayerCount()) if ((*ppCheck)->GetFirstUnjoinedPlayerID()) pLargestTeam = *ppCheck; // no team can redistribute? if (!pLargestTeam) break; // redistribution won't help much? if (pLargestTeam->GetPlayerCount() - pLowestTeam->GetPlayerCount() <= 1) break; // okay; redistribute one player! int32_t idRedistPlayer = pLargestTeam->GetFirstUnjoinedPlayerID(); C4PlayerInfo *pInfo = Game.PlayerInfos.GetPlayerInfoByID(idRedistPlayer); assert(pInfo); if (!pInfo) break; // umn...serious problems pLargestTeam->RemovePlayerByID(idRedistPlayer); pLowestTeam->AddPlayer(*pInfo, true); C4ClientPlayerInfos *pClrInfo = Game.PlayerInfos.GetClientInfoByPlayerID(idRedistPlayer); assert(pClrInfo); // player info change: mark updated to remote clients get information if (pClrInfo) { pClrInfo->SetUpdated(); } } }
void C4PlayerInfoListAttributeConflictResolver::ResolveInPacket() { // check all player infos fAnyChange = false; int32_t iCheck = 0; while ((pResolveInfo = pResolvePacket->GetPlayerInfo(iCheck++))) { // not already joined? Joined player must not change their attributes! if (pResolveInfo->HasJoined()) continue; DWORD dwPrevColor = pResolveInfo->GetColor(); StdStrBuf sPrevForcedName; sPrevForcedName.Copy(pResolveInfo->GetForcedName()); // check attributes: Name and color for (eAttr = C4PlayerInfo::PLRATT_Color; eAttr != C4PlayerInfo::PLRATT_Last; eAttr = (C4PlayerInfo::Attribute) (eAttr+1)) { if (eAttr == C4PlayerInfo::PLRATT_Color) { // no color change in savegame associations if (pResolveInfo->GetAssociatedSavegamePlayerID()) continue; // or forced team colors if (Game.Teams.IsTeamColors() && Game.Teams.GetTeamByID(pResolveInfo->GetTeam())) continue; } else if (eAttr == C4PlayerInfo::PLRATT_Name) { // no name change if a league name is used if (pResolveInfo->getLeagueAccount() && *pResolveInfo->getLeagueAccount()) continue; } // not if attributes are otherwise fixed (e.g., for script players) if (pResolveInfo->IsAttributesFixed()) continue; // resolve in this info ResolveInInfo(); } // mark change for return value if anything was changed if (pResolveInfo->GetColor() != dwPrevColor || (pResolveInfo->GetForcedName() != sPrevForcedName)) fAnyChange = true; // next player info check } // mark update if anything was changed if (fAnyChange) pResolvePacket->SetUpdated(); }
void C4TeamList::ReassignAllTeams() { assert(::Control.isCtrlHost()); if (!::Control.isCtrlHost()) return; // go through all player infos; reset team in them int32_t idStart = -1; C4PlayerInfo *pNfo; while ((pNfo = Game.PlayerInfos.GetNextPlayerInfoByID(idStart))) { idStart = pNfo->GetID(); if (pNfo->HasJoinIssued()) continue; pNfo->SetTeam(0); // mark changed info as updated C4ClientPlayerInfos *pCltInfo = Game.PlayerInfos.GetClientInfoByPlayerID(idStart); assert(pCltInfo); if (pCltInfo) { pCltInfo->SetUpdated(); } } // clear players from team lists RecheckPlayers(); // in random autogenerate mode, there must be exactly two teams if (IsRandomTeam()) if (IsAutoGenerateTeams() && GetTeamCount() != 2) { ClearTeams(); GenerateDefaultTeams(2); } // reassign them idStart = -1; while ((pNfo = Game.PlayerInfos.GetNextPlayerInfoByID(idStart))) { idStart = pNfo->GetID(); if (pNfo->HasJoinIssued()) continue; assert(!pNfo->GetTeam()); RecheckPlayerInfoTeams(*pNfo, true); } }