class AMC extends Mutator
	config(AdjustingMapcycle);
	
struct MapConfig
{
	var string mapname;
	var int minAvgPlayers;
	var int maxAvgPlayers;
};	

var config MapConfig mapcycle[32];
var config int currentIndex;
var bool bPostInit;
//////////////////////
var Pawn skipVotes[16];
var config float skipPercentage;
//////////////////////
var config float avgPopulation;
//////////////////////
var bool bNotEnded;


function PostBeginPlay() 
{
	if(bPostInit)
		return;
	
	bNotEnded = True;
	bPostInit = True;
	Level.Game.RegisterMessageMutator(Self);
	SetTimer(60 * Level.TimeDilation, True);
	
	BroadcastMessage("If you want to see this map skipped say !skip.");
	BroadcastMessage(int(100 * skipPercentage) $ "% !skip-votes needed.");
}

function Timer()
{
	if(bNotEnded)
	{
		avgPopulation += (Level.Game.NumPlayers - avgPopulation) / 4;
		Log(Level.Game.NumPlayers $ " -> " $ avgPopulation);
	}
	else //delay after we ended game
	{
		Level.ServerTravel(mapList[currentIndex].mapname, False);
		//Level.Game.ProcessServerTravel(mapList[currentIndex].mapname, False);
	}
}

function bool MutatorTeamMessage(Actor Sender, Pawn Receiver, PlayerReplicationInfo PRI, coerce string Msg, name Type, optional bool bBeep) 
{
	if(Sender == Receiver) 
	{ 
		if (Left(Msg, 5) == "!skip") 
		{ 
			if(Level.TimeSeconds < 35)
			{
				Receiver.ClientMessage("Wait for " $ int(1 + (35 - Level.TimeSeconds)/Level.TimeDilation) $ " seconds then say it again.");
			}
			else
				ProcessSkipVote(Receiver);
		}
	}
  
	if(NextMessageMutator != None)
		return NextMessageMutator.MutatorTeamMessage( Sender, Receiver, PRI, S, Type, bBeep );
	else
		return true;
}

function ProcessSkipVote(Pawn p)
{
	local int i, k;
	local bool bDone;
	
	//clean
	for(i = 0; i < 16; i++)
	{
		if(skipVotes[i] == None)
		{
			if(!bDone)
			{
				skipVotes[i] = p;
				k++;
				bDone = True;
			}
		}
		else //count
			k++;
	}
	
	if(k >= skipPercentage * Level.Game.NumPlayers)
	{
		Log("skip this map");
		if(!NextMap(True))
			BroadcastMessage("No other map matching current population");
	}
}

function bool Nextmap(bool skipMap)
{
	local int oldIndex;
	
	oldIndex = currentIndex;

	Log(currentIndex $ " old");
	//find a matching map
	while(++currentIndex == 32 || mapList[currentIndex].mapname == "" || 
		mapList[currentIndex].minAvgPlayers > avgPopulation ||
		mapList[currentIndex].maxAvgPlayers < avgPopulation)
		{}
	Log(currentIndex $ " new");
	
	if(currentIndex == oldIndex)//ending on the same map!
		return False;

	SaveConfig();
	
	//prepare
	DeathMatchPlus(Level.Game).bDontRestart = True;
	
	//last calculation
	avgPopulation += (Level.Game.NumPlayers - avgPopulation) / 4;
	SaveConfig();//save now
	Log(Level.Game.NumPlayers $ " ->NM " $ avgPopulation);
	
	//delay
	bNotEnded = False;//delay mode in timer()
	if(skipMap)
		SetTimer(10, False);
	else
		SetTimer(15, False);
		
	return True;
}


function bool HandleEndGame()
{
	Super.HandleEndGame();
	
	if(tgp.teams[0].Score != tgp.teams[1].Score)
	{
		//find next suitable map - and start end-game timer
		NextMap(False);
		//show winner
		Level.Game.SetEndCams();
		
		return True;
	}
	else
		return False;
}


defaultproperties
{
	skipPercentage=0.6
}