Exemplo n.º 1
0
void C4Team::AddPlayer(C4PlayerInfo &rInfo, bool fAdjustPlayer)
{
	// must not happen!
	assert(rInfo.GetID());
	if (!rInfo.GetID()) return;
	// add player; grow vector if necessary
	if (iPlayerCount >= iPlayerCapacity)
	{
		int32_t *piNewPlayers = new int32_t[iPlayerCapacity = (iPlayerCount+4)&~3];
		if (iPlayerCount) memcpy(piNewPlayers, piPlayers, iPlayerCount*sizeof(int32_t));
		delete [] piPlayers; piPlayers = piNewPlayers;
	}
	// store new player
	piPlayers[iPlayerCount++] = rInfo.GetID();
	if (!fAdjustPlayer) return;
	// set values in info
	rInfo.SetTeam(GetID());
	if (Game.Teams.IsTeamColors()) rInfo.SetColor(GetColor());
	// and in actual player, if it is joined already
	if (rInfo.IsJoined())
	{
		C4Player *pJoinedPlr = ::Players.GetByInfoID(rInfo.GetID());
		assert(pJoinedPlr || (rInfo.GetType() == C4PT_Script));
		if (pJoinedPlr)
		{
			pJoinedPlr->Team = GetID();
			if (Game.Teams.IsTeamColors()) pJoinedPlr->SetPlayerColor(GetColor());
		}
	}
}
Exemplo n.º 2
0
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);
	}
}
Exemplo n.º 3
0
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);
	}
}
Exemplo n.º 4
0
bool C4TeamList::RecheckPlayerInfoTeams(C4PlayerInfo &rNewJoin, bool fByHost)
{
	// only if enabled
	assert(IsMultiTeams());
	if (!IsMultiTeams()) return false;
	// check whether a new team is to be assigned first
	C4Team *pCurrentTeam = GetTeamByPlayerID(rNewJoin.GetID());
	int32_t idCurrentTeam = pCurrentTeam ? pCurrentTeam->GetID() : 0;
	if (rNewJoin.GetTeam())
	{
		// was that team a change to the current team?
		// no change anyway: OK, skip this info
		if (idCurrentTeam == rNewJoin.GetTeam()) return true;
		// the player had a different team assigned: Check if changes are allowed at all
		if (eTeamDist == TEAMDIST_Free || (eTeamDist == TEAMDIST_Host && fByHost))
			// also make sure that selecting this team is allowed, e.g. doesn't break the team limit
			// this also checks whether the team number is a valid team - but it would accept TEAMID_New, which shouldn't be used in player infos!
			if (rNewJoin.GetTeam() != TEAMID_New && IsJoin2TeamAllowed(rNewJoin.GetTeam()))
				// okay; accept change
				return true;
		// Reject change by reassigning the current team
		rNewJoin.SetTeam(idCurrentTeam);
		// and determine a new team, if none has been assigned yet
		if (idCurrentTeam) return true;
	}
	// new team assignment
	// teams are always needed in the lobby, so there's a team preset to change
	// for runtime joins, teams are needed if specified by teams.txt or if any teams have been created before (to avoid mixed team-noteam-scenarios)
	// but only assign teams in runtime join if the player won't pick it himself
	bool fWillHaveLobby = ::Network.isEnabled() && !::Network.Status.isPastLobby() && Game.fLobby;
	bool fHasOrWillHaveLobby = ::Network.isLobbyActive() || fWillHaveLobby;
	bool fCanPickTeamAtRuntime = !IsRandomTeam() && (rNewJoin.GetType() == C4PT_User) && IsRuntimeJoinTeamChoice();
	bool fIsTeamNeeded = IsRuntimeJoinTeamChoice() || GetTeamCount();
	if (!fHasOrWillHaveLobby && (!fIsTeamNeeded || fCanPickTeamAtRuntime)) return false;
	// get least-used team
	C4Team *pAssignTeam=NULL;
	C4Team *pLowestTeam = GetRandomSmallestTeam();
	// melee mode
	if (IsAutoGenerateTeams() && !IsRandomTeam())
	{
		// reuse old team only if it's empty
		if (pLowestTeam && !pLowestTeam->GetPlayerCount())
			pAssignTeam = pLowestTeam;
		else
		{
			// no empty team: generate new
			GenerateDefaultTeams(iLastTeamID+1);
			pAssignTeam = GetTeamByID(iLastTeamID);
		}
	}
	else
	{
		if (!pLowestTeam)
		{
			// not enough teams defined in teamwork mode?
			// then create two teams as default
			if (!GetTeamByIndex(1))
				GenerateDefaultTeams(2);
			else
				// otherwise, all defined teams are full. This is a scenario error, because MaxPlayer should have been adjusted
				return false;
			pLowestTeam = GetTeamByIndex(0);
		}
		pAssignTeam = pLowestTeam;
	}
	// assign it
	if (!pAssignTeam) return false;
	pAssignTeam->AddPlayer(rNewJoin, true);
	return true;
}