Dear forum users! In compliance with the new European GDPR regulations, we'd just like to inform you that if you have an account, your email address is stored in our database. We do not share your information with third parties, and your email address and password are encrypted for security reasons.

New to the forum? Say hello in this topic! Also make sure to read the rules.

Team rotation script

Custom scripts
Forum rules
By using the forum you agree to the following rules.
Post Reply
User avatar
Gurt
Lead Programmer
Lead Programmer
Posts: 1884
Joined: Sun Feb 28, 2016 3:22 pm
Title: Lead programmer
Started SFD: Made it!
Location: Sweden
Gender:
Age: 34

Team rotation script

Post by Gurt » Mon May 30, 2016 10:16 pm

This extension script is a replacement script for the built-in even teams and shuffle teams function for anyone running a server that wants some variation on the team setup.
Each 30 minutes the script will go from free-for-all to 2v2v2v2 and 4v4 (if enough players are online).

You can tinker with the script if you like or make it easier to customize. I didn't bother to add constants to it to make it easy to customize.

Code: Select all

/*
* TeamRotation.txt
* By Gurt - Mytho-Logic Interactive.
*
* Disable even teams and shuffle teams options and set all teams to independent. This script will handle the rest.
*/

private static string MESSAGE = "First 12 minutes each half hour is FREE FOR ALL. Remaining time is TEAM GAMEPLAY (if enough players).";

private void CheckMessage()
{
	int prevMinute = 0;
	if (!int.TryParse(Game.Data, out prevMinute)) {
		prevMinute = -60; // Forces message to be shown if not yet shown
	}
	int currentMinute = DateTime.Now.Hour * 60 + DateTime.Now.Minute;
	if (Math.Abs(currentMinute - prevMinute) >= 10) {
		// Show it each 10 mintues or so...
		Game.RunCommand("/MSG " + "==================================");
		Game.RunCommand("/MSG " + MESSAGE);
		Game.RunCommand("/MSG " + "==================================");
		Game.Data = currentMinute.ToString();
	}
}

private int m_minute = 0;
private string m_lastTeamSetup = "";
private string m_lastAlonePlayer = "";
private Random m_rnd = null;

public void OnStartup()
{
	m_rnd = new Random((int)DateTime.Now.Millisecond * (int)DateTime.Now.Minute * 1000);
	if (Game.IsFirstUpdate) 
	{
		CheckMessage();
		
		m_minute = DateTime.Now.Minute;
		if (m_minute >= 30)
			m_minute -= 30;
		
		BalanceTeams(false);
		// after 3 seconds - rebalance teams if anyone left.
		IObjectTimerTrigger timer = (IObjectTimerTrigger)Game.CreateObject("TimerTrigger");
		timer.SetRepeatCount(2);
		timer.SetIntervalTime(1000);
		timer.SetScriptMethod("RecheckBalance");
		timer.Trigger();
	}
}

public void RecheckBalance(TriggerArgs args)
{
	BalanceTeams(true);
}

// Based on players and current clock - even teams
public void BalanceTeams(bool isRecheck)
{
	// cycle team rotation each 30 minutes	
	List<IPlayer> players = GetActivePlayers();
	if (players.Count == 0)
		return;
	
	bool freeForAllTime = (m_minute < 12); // 12 minutes each 30 minutes do FREE FOR ALL else TEAMS
	bool bigTeamsTime = (m_minute >= 25); // 5 minutes each 30 minutes when TEAMS do BIG TEAMS!
	
	if ((players.Count == 5 || players.Count == 7) && !freeForAllTime)
	{
		// special. If 5 or 7 players and it's not FREE-FOR-ALL time remove the one with HIGHEST WIN-RATIO to play ALONE
		IPlayer highestScoringPlayer = GetPlayerUserWithHighestWinRatio(players);
		if (highestScoringPlayer != null)
		{
			players.Remove(highestScoringPlayer);
			highestScoringPlayer.SetTeam(PlayerTeam.Team4);
			IUser user = highestScoringPlayer.GetUser();
			if (user != null && m_lastAlonePlayer != user.Name)
			{
				m_lastAlonePlayer = user.Name;
				Game.RunCommand("/MSG " + user.Name + " with highest win-ratio will be playing alone this round.");
			}
		}
	}
	
	if (players.Count % 2 == 1 || players.Count < 4 || freeForAllTime)
	{
		// UNEVEN COUNT FOR TEAMS or FREE-FOR-ALL TIME
		DistributeTeams(players, PlayerTeam.Independent, 
								 PlayerTeam.Independent, 
								 PlayerTeam.Independent, 
								 PlayerTeam.Independent, 
								 PlayerTeam.Independent, 
								 PlayerTeam.Independent, 
								 PlayerTeam.Independent, 
								 PlayerTeam.Independent);
		AnnouncCurrentTeamSetup("FREE FOR ALL", isRecheck);
	}
	else 
	{
		// possible setups:
		// 2,2
		// 2,2,2 / 3,3 (BIG TEAMS)
		// 2,2,2,2 / 4,4 (BIG TEAMS)
		if (bigTeamsTime && players.Count == 6)
		{
			DistributeTeams(players, PlayerTeam.Team1, 
									 PlayerTeam.Team1, 
									 PlayerTeam.Team1, 
									 PlayerTeam.Team2, 
									 PlayerTeam.Team2, 
									 PlayerTeam.Team2);
			AnnouncCurrentTeamSetup("TEAMS (3v3)", isRecheck);
		} 
		else if (bigTeamsTime && players.Count == 8)
		{
			DistributeTeams(players, PlayerTeam.Team1, 
									 PlayerTeam.Team1, 
									 PlayerTeam.Team1, 
									 PlayerTeam.Team1, 
									 PlayerTeam.Team2, 
									 PlayerTeam.Team2, 
									 PlayerTeam.Team2, 
									 PlayerTeam.Team2);
			AnnouncCurrentTeamSetup("TEAMS (4v4)", isRecheck);
		} 
		else 
		{
			// this distribute for 2v2, 2v2v2 and 2v2v2v2... 
			if (players.Count == 4)
			{
				DistributeTeams(players, PlayerTeam.Team1, 
										 PlayerTeam.Team1, 
										 PlayerTeam.Team2, 
										 PlayerTeam.Team2);
			} 
			else if (players.Count == 6) 
			{
				DistributeTeams(players, PlayerTeam.Team1, 
										 PlayerTeam.Team1, 
										 PlayerTeam.Team2, 
										 PlayerTeam.Team2, 
										 PlayerTeam.Team3, 
										 PlayerTeam.Team3);
			}
			else 
			{
				DistributeTeams(players, PlayerTeam.Team1, 
										 PlayerTeam.Team1, 
										 PlayerTeam.Team2, 
										 PlayerTeam.Team2, 
										 PlayerTeam.Team3, 
										 PlayerTeam.Team3, 
										 PlayerTeam.Team4, 
										 PlayerTeam.Team4);
			}
			AnnouncCurrentTeamSetup("TEAMS (2v2)", isRecheck);
		}
	}
}


private IPlayer GetPlayerUserWithHighestWinRatio(List<IPlayer> players)
{
	float highestWinRatio = -1f;
	List<IPlayer> highestScoringPlayers = new List<IPlayer>();
	foreach(IPlayer player in players)
	{
		IUser user = player.GetUser();
		if (user != null)
		{
			float userWinRatio = (user.TotalGames >= 2 ? (float)user.TotalWins / (float)user.TotalGames : 0f);
			if (userWinRatio == highestWinRatio)
			{
				highestScoringPlayers.Add(player);
			} 
			else if (userWinRatio > highestWinRatio)
			{
				highestWinRatio = userWinRatio;
				highestScoringPlayers.Clear();
				highestScoringPlayers.Add(player);
			}
		}
	}
	if (highestScoringPlayers.Count == 0)
		return null;
	if (highestScoringPlayers.Count == 1)
		return highestScoringPlayers[0];
	// Return random highest scoring player
	
	return highestScoringPlayers[m_rnd.Next(0, highestScoringPlayers.Count)];
}

private void DistributeTeams(List<IPlayer> players, params PlayerTeam[] teams)
{
	if (players == null || teams == null) return;
	
	// If teams already distributed correctly - ignore randomizing a new distribution!
	if (CheckTeamsDistributed(players, teams)) return;
	
	// randomize team distribution
	List<IPlayer> playersToShuffle = new List<IPlayer>(players);
	int teamIndex = 0;
	while(playersToShuffle.Count > 0 && teamIndex < teams.Length)
	{
		int playerIndex = m_rnd.Next(0, playersToShuffle.Count);
		IPlayer player = playersToShuffle[playerIndex];
		playersToShuffle.RemoveAt(playerIndex);
		player.SetTeam(teams[teamIndex]);
		teamIndex ++;
	}
}

// Checks if the players are distributed according to the teams layout.
private bool CheckTeamsDistributed(List<IPlayer> players, params PlayerTeam[] teams)
{
	if (players == null || teams == null) return false;
	
	List<PlayerTeam> checkTeams = new List<PlayerTeam>(teams);
	foreach(IPlayer player in players)
	{
		PlayerTeam playerTeam = player.GetTeam();
		if (!checkTeams.Remove(playerTeam)) 
		{
			return false;
		}
	}
	// Check if checkTeams contains team 1-4 - if so distribution is not fullfilled
	return !checkTeams.Any(x => x != PlayerTeam.Independent);
}

// ActiveUsers
// ActiveUsers controlling a player
private List<IPlayer> GetActivePlayers() 
{
	List<IPlayer> activePlayers = new List<IPlayer>();
	IUser[] users = Game.GetActiveUsers();
	foreach(IUser user in users)
	{
	    IPlayer plr = user.GetPlayer();
		if (plr != null)
		{
			activePlayers.Add(plr);
		}
	}
	return activePlayers;
}

private void AnnouncCurrentTeamSetup(string msg, bool isRecheck)
{
	if (m_lastTeamSetup != msg)
	{
		m_lastTeamSetup = msg;
		Game.RunCommand("/MSG " + msg + (isRecheck ? " (Someone left the game early)" : ""));
	}
}
6 x
Gurt

Post Reply