//============================================================
// TTeamFixMessages.uc	- Used for sending custom notification messages to clients
//============================================================
//	TitanTeamFix
//		- A modular team balancing tool initially coded for the Titan servers:
//			http://ut2004.titaninternet.co.uk/
//
//	Copyright (C) 2007-2008 John "Shambler" Barrett (JBarrett847@Gmail.com or Shambler@OldUnreal.com)
//
//	This program is free software; you can redistribute and/or modify
//	it under the terms of the Open Unreal Mod License version 1.1.
//
//============================================================
//
// This class implements the only existing clientside code
// portion of TitanTeamFix; the custom message handling.
//
//============================================================
Class TTeamFixMessages extends LocalMessage;


// Is there any point to setting these as localized? (I suppose that it at least lets clients modify these messages if they like)
var localized string SwitchedMessage;		// Message given to players who have been switched
var localized string AnnounceMessage;		// Message given to all players when a player is switched
var localized string MultipleAnnounceMessage;	// Same as above, but replaces the above string when more than one player is switched
var localized string ImbalanceMessage;		// Message given to all players when the teams become unbalanced
var localized string SlotOpenedMessage;		// Message given to spectators when a slot opens up
var localized string ShuffleMessage;		// Message given to all players when the teams are randomized


// Special multi-switch encoding:
/*
	The LAST three bits of the 'Switch' parameter will determine the switch type; so that means
	that you need to use (Switch & 0x7) to determine the switch type (that allows this class to
	receive 7 different switch types, which is plenty for now).

	The first 28 bits are specially used by the 'MultipleAnnounceMessage' code to determine
	exactly which players on the larger team are being switched.

	It works by gathering a list of players from the bigger team and sorting them in the order
	of their PlayerID's; each bit in the first 28 bits of the 'Switch' parameter corresponds
	DIRECTLY to the resulting list, with players that are being switched denoted by a binary '1'
	(have since reversed the bit order to start near the switch bits, as I was inadvertently
	screwing up the sign bits and corrupted the integer).


	N.B. When doing this 'MultipleAnnounceMessage', the first related PRI will only be set to
	indicate what team the switching players are coming from.

	UPDATE: This only seems to be accurate to the last 16 bits (maybe due to network
	compression? Or is that just inherent to integers, i.e. the way they are negative after a
	certain number) but that is probably more than is needed as it can successfully list the
	first 13 switched players; and it's highly unlikely to switch even that many most of the
	time.
*/

static function string GetString(optional int Switch, optional bool bPRI1HUD, optional PlayerReplicationInfo RelatedPRI_1,
					optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject)
{
	switch (Switch & 0x7)
	{
		case 0:
			return default.SwitchedMessage;

		case 1:
			return Repl(default.AnnounceMessage, "%p", RelatedPRI_1.PlayerName);

		case 2:
			// If there isn't enough data to do a proper MultipleAnnounceMessage, fallback to a singular message
			if (GameReplicationInfo(OptionalObject) == none)
				return Repl(default.AnnounceMessage, "%p", RelatedPRI_1.PlayerName);

			return Repl(default.MultipleAnnounceMessage, "%p",
				DecodeMultipleAnnounce(Switch, GameReplicationInfo(OptionalObject), RelatedPRI_1.GetTeamNum()));

		case 3:
			return default.ImbalanceMessage;

		case 4:
			return default.SlotOpenedMessage;

		case 5:
			return default.ShuffleMessage;
	}
}

// This is a hacky way of squeezing extra info into a 'ReceiveLocalizedMessage' call through the 'Switch' parameter
static final function string DecodeMultipleAnnounce(int Indicies, GameReplicationInfo GRI, int Team)
{
	local array<PlayerReplicationInfo> PRIList;
	local PlayerReplicationInfo PRI, PRI2;
	local int i;
	local string ReturnStr;

	// Generate the list of players from the bigger team and sort by player id
	foreach GRI.PRIArray(PRI)
	{
		if (PRI.GetTeamNum() != Team)
			continue;

		if (PRIList.Length == 0)
		{
			PRIList.AddItem(PRI);
		}
		else
		{
			foreach PRIList(PRI2, i)
			{
				if (PRI.PlayerID < PRI2.PlayerID)
				{
					PRIList.InsertItem(i, PRI);
					break;
				}
			}

			if (PRIList[i] != PRI)
				PRIList.AddItem(PRI);
		}
	}


	// Nullify invalid entries within the list
	for (i=0; i<PRIList.Length; ++i)
		if (!bool(Indicies & (0x8 << i)))
			PRIList[i] = none;

	PRIList.RemoveItem(none);


	// Now construct the return string
	for (i=0; i<PRIList.Length; ++i)
	{
		switch (PRIList.Length-i)
		{
		case 1:
			ReturnStr = ReturnStr@PRIList[i].PlayerName;
			break;

		case 2:
			ReturnStr = ReturnStr@PRIList[i].PlayerName@"and";
			break;

		default:
			ReturnStr = ReturnStr@PRIList[i].PlayerName$",";
		}
	}

	return ReturnStr;
}

defaultproperties
{
	bIsSpecial=False
	Lifetime=6.000000
	DrawColor=(R=145,G=135,B=181)

	SwitchedMessage="TitanTeamFix: You have been switched to balance the teams"
	AnnounceMessage="TitanTeamFix: %p has been switched to balance the teams"
	MultipleAnnounceMessage="TitanTeamFix: %p have been switched to balance the teams"
	ImbalanceMessage="TitanTeamFix: The teams have become uneven"
	SlotOpenedMessage="TitanTeamFix: A slot has opened, another player can join the game"
	ShuffleMessage="TitanTeamFix: The teams have been randomized"
}