//
// AVP_Multiplayer_GameMessageSystem.cpp
//
// Created by JG - 17 September 2008
//
// Copyright (C) 2008 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"

// This file's header.
#include "Multiplayer/AVP_Multiplayer_GameMessageSystem.h"

// Engine
#include "Core/Asura_HashedLocalisedText.h"
#include "Core/Asura_Timers.h"
#include "GuiMenu/Asura_GuiMenu_Element_Text.h"

// Project
#include "Blueprint/AVP_Blueprint_HashIDs.h"
#include "Core/AVP_Game_Core.h"
#include "Entity/PhysicalObject/Actor/AVP_ClientEntity_Actor.h"
#include "Entity/PhysicalObject/CommandPost/AVP_ClientEntity_CommandPost.h"
#include "Entity/PlayerInfo/AVP_ClientEntity_PlayerInfo.h"
#include "GUIMenu/AVP_GUIMenu_System.h"
#include "Multiplayer/AVP_Multiplayer_GameRules.h"
#include "Multiplayer/AVP_Multiplayer_HashIDs.h"
#include "Network/AVP_Player.h"

// Globals
bool		AVP_Multiplayer_GameMessageSystem::s_bShowRespawnTimer		= false; 
bool		AVP_Multiplayer_GameMessageSystem::s_bShowPriorityMessage	= false; 
bool		AVP_Multiplayer_GameMessageSystem::s_bShowCaptureInProgress = false; 
bool		AVP_Multiplayer_GameMessageSystem::s_bShowCapturePointList	= false; 

AVP_Multiplayer_GameMessageSystem::SpamMessageEntry						AVP_Multiplayer_GameMessageSystem::s_xSpamMessages[s_uAVP_MULTIPLAYER_SPAM_MESSAGES_MAX_NUMBER]; 
Asura_List<AVP_Multiplayer_GameMessageSystem::SpamMessageEntry>			AVP_Multiplayer_GameMessageSystem::s_xSortedMesagesList; 
Asura_LinkList<AVP_Multiplayer_GameMessageSystem::CapturePointState>	AVP_Multiplayer_GameMessageSystem::s_xSortedCapturePointState; 


void AVP_Multiplayer_GameMessageSystem::Initialise()
{
	// Add the console commands and vars 
	AddConsoleCmdsAndVars(); 
}

void AVP_Multiplayer_GameMessageSystem::Update()
{
	// Activate the game message system menu page if needed
	if (!Asura_GUIMenu_System::IsMenuPageHashActive( s_uAVP_MULTIPLAYER_GAME_MESSAGE_SYSTEM_MENU ))
	{
		// Activate the game message menu page 
		AVP_GUIMenu_System::Activate( s_uAVP_MULTIPLAYER_GAME_MESSAGE_SYSTEM_MENU, false, false ); 
	}

	// Update the spam message timers
	for (u_int uIndex = 0; uIndex < s_uAVP_MULTIPLAYER_SPAM_MESSAGES_MAX_NUMBER; uIndex++)
	{
		// Not showing on the screen anymore?
		if (s_xSpamMessages[uIndex].m_fTimeRemainingOnScreen > 0.0f)
		{
			s_xSpamMessages[uIndex].m_fTimeRemainingOnScreen -= Asura_Timers::GetGameTimeSlice(); 
		}
	}

	// Sort by time (newer messages first)

	// Clear the messages sorted from last time
	s_xSortedMesagesList.ClearList(); 

	for (u_int uIndex = 0; uIndex < s_uAVP_MULTIPLAYER_SPAM_MESSAGES_MAX_NUMBER; uIndex++)
	{
		// Only sort active messages
		if (s_xSpamMessages[uIndex].m_fTimeRemainingOnScreen > 0.0f)
		{
			s_xSortedMesagesList.InsertInList( &(s_xSpamMessages[uIndex]), SortMessagesByTimeRemaining );  
		}
	}

	// Update the capture point state list
	UpdateCapturePointsState(); 
}

void AVP_Multiplayer_GameMessageSystem::Render()
{
}

void AVP_Multiplayer_GameMessageSystem::Shutdown()
{
	// Deactivate the game message menu page 
	AVP_GUIMenu_System::Deactivate( s_uAVP_MULTIPLAYER_GAME_MESSAGE_SYSTEM_MENU ); 

	// Make sure the respawn timer is deactivated 
	HideRespawnTimer(); 

	// Clean up sorted list messages
	s_xSortedMesagesList.ClearList(); 

	// Clean up the capture point list
	s_xSortedCapturePointState.Clear(); 
}

void AVP_Multiplayer_GameMessageSystem::OnActorGetsKilled(Asura_Guid uExecutorGuid, Asura_Guid uVictimGuid, Asura_Hash_ID uDamageType, bool bStealth)
{
	// Get both names and create the new spam message
	AVP_ClientEntity_Actor* pxVictimActor = AVP_ClientEntity_Actor::FindEntity( uVictimGuid ); 
	if (pxVictimActor)
	{
		// Only spam players about other players
		if (pxVictimActor->IsPlayer())
		{
			// Find player info
			AVP_ClientEntity_PlayerInfo* pxVictimPlayerInfo = AVP_ClientEntity_PlayerInfo::GetList()->FindEntity( pxVictimActor->GetPlayerInfoGuid() ); 
			if (pxVictimPlayerInfo)			
			{		
				if (uExecutorGuid != ASURA_GUID_UNREGISTERED)
				{
					// Find who killed us
					AVP_ClientEntity_Actor* pxExecutorActor = AVP_ClientEntity_Actor::FindEntity( uExecutorGuid ); 
					if (pxExecutorActor)
					{
						// Did a player kill another player?
						if (pxExecutorActor->IsPlayer() && pxVictimActor->IsPlayer())
						{
							// Find the executor player info
							AVP_ClientEntity_PlayerInfo* pxExecutorPlayerInfo = AVP_ClientEntity_PlayerInfo::FindEntity( pxExecutorActor->GetPlayerInfoGuid() ); 
							if (pxExecutorPlayerInfo)
							{
								// Suicide?
								if (pxExecutorPlayerInfo->GetGuid() == pxVictimPlayerInfo->GetGuid())
								{
									// Message: player kill himself
									Asura_UnicodeChar aswzBuffer[128]; 
									Asura_PrintfToBfr(aswzBuffer, L"%s killed himself", 128, false, pxExecutorPlayerInfo->GetPlayerName()); 
									AddSpamMessage(aswzBuffer, 5.0f); 
								}
								else
								{
									// Message: player kill player
									Asura_UnicodeChar aswzBuffer[128]; 
									Asura_UnicodeChar* paswFormat = L"%s killed %s";

									if ((uDamageType == uAVP_BLUEPRINT_NAME_DAMAGE_MELEE) || (uDamageType == uAVP_BLUEPRINT_NAME_DAMAGE_GRAPPLE) || (uDamageType == uAVP_BLUEPRINT_NAME_DAMAGE_CLAW))
									{
										if (bStealth)
										{
											paswFormat = L"%s stealth killed %s"; 
										}
										else
										{
											paswFormat = L"%s melee killed %s"; 
										}
									}
									else if (uDamageType == uAVP_BLUEPRINT_NAME_DAMAGE_BITE)
									{
										paswFormat = L"%s head bit %s"; 
									}
									else if (uDamageType == uAVP_BLUEPRINT_NAME_DAMAGE_DISMEMBER)
									{
										// Special kills per species
										AVP_Settings::Species eSpecies = pxExecutorActor->GetSpeciesByClassification(); 
										switch (eSpecies)
										{
											case AVP_Settings::AVP_SPECIES_PREDATOR:
											{
												paswFormat = L"%s trophy killed %s"; 
												break; 
											}
											case AVP_Settings::AVP_SPECIES_ALIEN:
											case AVP_Settings::AVP_SPECIES_HUMAN:
											default:
											{
												paswFormat = L"%s dismembered %s"; 
											}
										}
									} 
									else if (uDamageType == uAVP_BLUEPRINT_NAME_DAMAGE_DISC )
									{
										paswFormat = L"%s cut %s"; 
									}
									else if ((uDamageType == uAVP_BLUEPRINT_NAME_DAMAGE_BLADE) || (uDamageType == uAVP_BLUEPRINT_NAME_DAMAGE_TAIL) || (uDamageType == uAVP_BLUEPRINT_NAME_DAMAGE_SPEAR) )
									{
										paswFormat = L"%s stabbed %s"; 
									} 
									else if (uDamageType == uAVP_BLUEPRINT_NAME_DAMAGE_EXPLOSIVE)
									{
										paswFormat = L"%s blew up %s"; 
									} 
									else if (uDamageType == uAVP_BLUEPRINT_NAME_DAMAGE_FLAME)
									{
										paswFormat = L"%s torched %s"; 
									}

									Asura_PrintfToBfr(aswzBuffer, paswFormat, 128, false, pxExecutorPlayerInfo->GetPlayerName(), pxVictimPlayerInfo->GetPlayerName()); 
									AddSpamMessage(aswzBuffer, 5.0f); 
								}
							
								// Changing role on-screen messages
								if (AVP_Settings::GetGameType() == AVP_Settings::AVP_GAMETYPE_HUNT)
								{
									if (pxVictimPlayerInfo->GetMultiplayerRole() == AVP_Settings::AVP_ROLE_HUNTER &&
										pxExecutorPlayerInfo->GetMultiplayerRole() == AVP_Settings::AVP_ROLE_PREY &&
										AVP_Game_Core::IsLocalPlayer(uExecutorGuid))
									{
										ShowPriorityMessage(); 
									}
								}
							}
						}
					}
				}
				else
				{
					// Message: Player died
					Asura_UnicodeChar aswzBuffer[128]; 
					Asura_PrintfToBfr(aswzBuffer, L"%s died", 128, false, pxVictimPlayerInfo->GetPlayerName()); 
					AddSpamMessage(aswzBuffer, 5.0f); 
				}
			}
			else
			{
				// No player info, can't tell the name of the player controlling this actor unfortunately. 
				// Feel tempted to assert here, but probably the player will get a spam message about people leaving / joining the game
			}
		}
	}
}

void AVP_Multiplayer_GameMessageSystem::ShowRespawnTimer()
{
	s_bShowRespawnTimer = true; 
}

void AVP_Multiplayer_GameMessageSystem::HideRespawnTimer()
{
	s_bShowRespawnTimer = false; 
}

void AVP_Multiplayer_GameMessageSystem::ShowPriorityMessage()
{
	s_bShowPriorityMessage = true; 
}

void AVP_Multiplayer_GameMessageSystem::HidePriorityMessage()
{
	s_bShowPriorityMessage = false; 
}

void AVP_Multiplayer_GameMessageSystem::ShowCaptureInProgress()
{
	s_bShowCaptureInProgress = true; 
}

void AVP_Multiplayer_GameMessageSystem::HideCaptureInProgress()
{
	s_bShowCaptureInProgress = false; 
}

void AVP_Multiplayer_GameMessageSystem::ShowCapturePointList()
{
	s_bShowCapturePointList = true; 
}

void AVP_Multiplayer_GameMessageSystem::HideCapturePointList()
{
	s_bShowCapturePointList = false; 
}

void AVP_Multiplayer_GameMessageSystem::UpdateRespawnTimer(float fRemainingTime)
{
	// Get the respawn timer 
	Asura_GUIMenu_Element_Text* pxTimer = static_cast<Asura_GUIMenu_Element_Text*>( 
		AVP_GUIMenu_System::GetHUDElement( AVP_GUIMenu_System::MULTIPLAYER_RESPAWN_TIMER, s_uAVP_MULTIPLAYER_GAME_MESSAGE_SYSTEM_MENU ));

	if (pxTimer)
	{
		// Convert to unicode (in seconds)
		Asura_UnicodeChar wszString[3]; 
		Asura_PrintfToBfr( wszString, L"%2d", 3, false, Asura_Maths::FloatToInt( fRemainingTime ) ); 
		
		pxTimer->SetText( wszString ); 
	}
}

void AVP_Multiplayer_GameMessageSystem::UpdateRankPlayers(int iNumberOfPlayers)
{
	// Get the number of players guid
	Asura_GUIMenu_Element_Text* pxNumberOfPlayers = static_cast<Asura_GUIMenu_Element_Text*>( 
		AVP_GUIMenu_System::GetHUDElement( AVP_GUIMenu_System::MULTIPLAYER_RANK_PLAYERS, s_uAVP_MULTIPLAYER_GAME_MESSAGE_SYSTEM_MENU ));

	if (pxNumberOfPlayers)
	{
		// Convert to unicode 
		Asura_UnicodeChar wszString[3]; 
		Asura_PrintfToBfr( wszString, L"%2d", 3, false, iNumberOfPlayers ); 
		
		pxNumberOfPlayers->SetText( wszString ); 
	}
}

void AVP_Multiplayer_GameMessageSystem::UpdateRankPlace(int iPlaceInRank)
{
	// Get the rank place
	Asura_GUIMenu_Element_Text* pxPlace = static_cast<Asura_GUIMenu_Element_Text*>( 
		AVP_GUIMenu_System::GetHUDElement( AVP_GUIMenu_System::MULTIPLAYER_RANK_PLACE, s_uAVP_MULTIPLAYER_GAME_MESSAGE_SYSTEM_MENU ));

	if (pxPlace)
	{
		// Convert to unicode
		Asura_UnicodeChar wszString[3]; 
		Asura_PrintfToBfr( wszString, L"%2d", 3, false, iPlaceInRank ); 
		
		pxPlace->SetText( wszString ); 
	}
}

void AVP_Multiplayer_GameMessageSystem::UpdateTeamScore(AVP_Settings::Team eTeam, int iScore)
{
	// Get the team score
	AVP_GUIMenu_System::STORED_WIDGETS eTeamWidget = AVP_GUIMenu_System::MULTIPLAYER_TEAMSCORE_TEAM1;
	switch (eTeam)
	{
		default:
		case AVP_Settings::AVP_TEAM_ONE:
		{
			eTeamWidget = AVP_GUIMenu_System::MULTIPLAYER_TEAMSCORE_TEAM1;
			break; 
		}
		case AVP_Settings::AVP_TEAM_TWO:
		{
			eTeamWidget = AVP_GUIMenu_System::MULTIPLAYER_TEAMSCORE_TEAM2;
			break; 
		}
		case AVP_Settings::AVP_TEAM_THREE:
		{
			eTeamWidget = AVP_GUIMenu_System::MULTIPLAYER_TEAMSCORE_TEAM3;
			break; 
		}
	}

	Asura_GUIMenu_Element_Text* pxTeamScore = static_cast<Asura_GUIMenu_Element_Text*>( 
		AVP_GUIMenu_System::GetHUDElement( eTeamWidget, s_uAVP_MULTIPLAYER_GAME_MESSAGE_SYSTEM_MENU ));

	if (pxTeamScore)
	{
		// Convert to unicode 
		Asura_UnicodeChar wszString[3]; 
		Asura_PrintfToBfr( wszString, L"%2d", 3, false, iScore ); 
		
		pxTeamScore->SetText( wszString ); 
	}
}

void AVP_Multiplayer_GameMessageSystem::UpdateCapturePointsState()
{
	Asura_LinkList_It<CapturePointState> xCapturePointStateIt( s_xSortedCapturePointState ); 
	while (!xCapturePointStateIt.Done())
	{
		CapturePointState* pxCurrentCapturePointState = xCapturePointStateIt.GetCurrent(); 
		xCapturePointStateIt.Next(); 

		if (pxCurrentCapturePointState)
		{
			const AVP_ClientEntity_CommandPost* pxCapturePointEntity = AVP_ClientEntity_CommandPost::FindEntity( pxCurrentCapturePointState->m_uGuid ); 
			if (pxCapturePointEntity)
			{
				pxCurrentCapturePointState->m_bContested = pxCapturePointEntity->IsContested(); 
				pxCurrentCapturePointState->m_eControlledByTeam = static_cast<AVP_Settings::Team>( pxCapturePointEntity->GetCurrentFaction() ); 
			}
			else
			{
				Asura_Assert( false, "Couldn't find client entity command post entity, HUD information is likely to be wrong" ); 
			}
		}
		else
		{
			Asura_Assert( false, "Error in the capture point sorted list" ); 
		}
	}
}

bool AVP_Multiplayer_GameMessageSystem::VisibilityCPEnemy( u_int uElementIndex, bool bInterrogate, bool bHelp )
{
	if (uElementIndex < s_xSortedCapturePointState.Size())
	{
		const Asura_ListElt<CapturePointState>* pxCurrentCapturePoint = s_xSortedCapturePointState[uElementIndex];
		if (pxCurrentCapturePoint)
		{
			AVP_Player* pxLocalPlayer = AVP_Game_Core::GetPlayer();
			AVP_Settings::Team eLocalPlayerTeam = AVP_Settings::AVP_TEAM_NONE;
			AVP_Settings::Team eCapturePointTeam = pxCurrentCapturePoint->Data().m_eControlledByTeam; 

			if (pxLocalPlayer)
			{
				eLocalPlayerTeam = pxLocalPlayer->GetMultiplayerTeam(); 
			}

			bool bCapturePointIsEnemy = ( eCapturePointTeam != AVP_Settings::AVP_TEAM_NONE && eCapturePointTeam != eLocalPlayerTeam ); 
			Asura_CommandConsole::Printf( bCapturePointIsEnemy ? "1" : "0" ); 
		}
		else
		{
			Asura_Assert( pxCurrentCapturePoint, "Invalid capture point pointer, shouldn't get here" );
		}
		return true; 
	}
	return false; 
}

bool AVP_Multiplayer_GameMessageSystem::VisibilityCPFriendly( u_int uElementIndex, bool bInterrogate, bool bHelp )
{
	if (uElementIndex < s_xSortedCapturePointState.Size())
	{
		const Asura_ListElt<CapturePointState>* pxCurrentCapturePoint = s_xSortedCapturePointState[uElementIndex];
		if (pxCurrentCapturePoint)
		{
			AVP_Player* pxLocalPlayer = AVP_Game_Core::GetPlayer();
			AVP_Settings::Team eLocalPlayerTeam = AVP_Settings::AVP_TEAM_NONE;
			AVP_Settings::Team eCapturePointTeam = pxCurrentCapturePoint->Data().m_eControlledByTeam; 

			if (pxLocalPlayer)
			{
				eLocalPlayerTeam = pxLocalPlayer->GetMultiplayerTeam(); 
			}

			bool bCapturePointIsFriendly = ( eCapturePointTeam != AVP_Settings::AVP_TEAM_NONE && eCapturePointTeam == eLocalPlayerTeam ); 
			Asura_CommandConsole::Printf( bCapturePointIsFriendly ? "1" : "0" ); 
		}
		else
		{
			Asura_Assert( pxCurrentCapturePoint, "Invalid capture point pointer, shouldn't get here" );
		}
		return true; 
	}
	return false; 
}
bool AVP_Multiplayer_GameMessageSystem::VisibilityCPContested( u_int uElementIndex, bool bInterrogate, bool bHelp )
{
	if (uElementIndex < s_xSortedCapturePointState.Size())
	{
		const Asura_ListElt<CapturePointState>* pxCurrentCapturePoint = s_xSortedCapturePointState[uElementIndex];
		if (pxCurrentCapturePoint)
		{
			bool bCapturePointIsContested = pxCurrentCapturePoint->Data().m_bContested; 
			Asura_CommandConsole::Printf( bCapturePointIsContested ? "1" : "0" ); 
		}
		else
		{
			Asura_Assert( pxCurrentCapturePoint, "Invalid capture point pointer, shouldn't get here" );
		}
		return true; 
	}
	return false; 
}

bool AVP_Multiplayer_GameMessageSystem::VisibilityCPNeutral( u_int uElementIndex, bool bInterrogate, bool bHelp )
{
	if (uElementIndex < s_xSortedCapturePointState.Size())
	{
		const Asura_ListElt<CapturePointState>* pxCurrentCapturePoint = s_xSortedCapturePointState[uElementIndex];
		if (pxCurrentCapturePoint)
		{
			bool bCapturePointIsNeutral = ( pxCurrentCapturePoint->Data().m_eControlledByTeam == AVP_Settings::AVP_TEAM_NONE ); 
			Asura_CommandConsole::Printf( bCapturePointIsNeutral ? "1" : "0" ); 
		}
		else
		{
			Asura_Assert( pxCurrentCapturePoint, "Invalid capture point pointer, shouldn't get here" );
		}
		return true; 
	}
	return false; 
}

bool AVP_Multiplayer_GameMessageSystem::PopulateCPName( u_int uElementIndex, bool bInterrogate, bool bHelp )
{
	if (uElementIndex < s_xSortedCapturePointState.Size())
	{
		const Asura_ListElt<CapturePointState>* pxCurrentCapturePoint = s_xSortedCapturePointState[uElementIndex];
		if (pxCurrentCapturePoint)
		{
			Asura_CommandConsole::Printf( L"%s", pxCurrentCapturePoint->Data().m_aswzCapturePointName ); 
		}
		else
		{
			Asura_Assert( pxCurrentCapturePoint, "Invalid capture point pointer, shouldn't get here" );
		}
		return true; 
	}
	return false; 
}

bool AVP_Multiplayer_GameMessageSystem::GetNumberOfTeams( bool bHelp )
{
	if (!bHelp)
	{
		int iNumberOfTeams = AVP_Multiplayer_GameRules::GetNumberOfTeams(); 
		Asura_CommandConsole::Printf( "%d", iNumberOfTeams ); 
	
		return true; 
	}
	return false; 
}

bool AVP_Multiplayer_GameMessageSystem::IsTeamBasedGame( bool bHelp )
{
	if (!bHelp)
	{
		bool bIsTeamBasedGame = AVP_Multiplayer_GameRules::IsTeamBasedGame();  
		Asura_CommandConsole::Printf( bIsTeamBasedGame ? "1" : "0" ); 

		return true; 
	}
	return false; 
}

void AVP_Multiplayer_GameMessageSystem::AddConsoleCmdsAndVars()
{
	Asura_UnicodeChar awcBuffer[256];

	Asura_PrintfToBfr( awcBuffer, L"%S", 256, true, "Multiplayer.GetSpamMessageByIndex" );
	if (!Asura_CommandConsole::CmdExists(awcBuffer))
	{
		Asura_CommandConsole::AddCmd( awcBuffer, GetSpamMessageByIndex );
	}

	Asura_PrintfToBfr( awcBuffer, L"%S", 256, true, "Multiplayer.ShowRespawnTimer" );
	if (!Asura_CommandConsole::VarExists(awcBuffer))
	{
		Asura_CommandConsole::AddVar( awcBuffer, &s_bShowRespawnTimer, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	}

	Asura_PrintfToBfr( awcBuffer, L"%S", 256, true, "Multiplayer.ShowPriorityMessage" );
	if (!Asura_CommandConsole::VarExists(awcBuffer))
	{
		Asura_CommandConsole::AddVar( awcBuffer, &s_bShowPriorityMessage, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	}

	Asura_PrintfToBfr( awcBuffer, L"%S", 256, true, "Multiplayer.ShowCaptureInProgress" );
	if (!Asura_CommandConsole::VarExists(awcBuffer))
	{
		Asura_CommandConsole::AddVar( awcBuffer, &s_bShowCaptureInProgress, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	}

	Asura_PrintfToBfr( awcBuffer, L"%S", 256, true, "Multiplayer.CMD.VisibilityCPEnemy" );
	if (!Asura_CommandConsole::CmdExists(awcBuffer))
	{
		Asura_CommandConsole::AddCmd( awcBuffer, VisibilityCPEnemy );
	}

	Asura_PrintfToBfr( awcBuffer, L"%S", 256, true, "Multiplayer.CMD.VisibilityCPFriendly" );
	if (!Asura_CommandConsole::CmdExists(awcBuffer))
	{
		Asura_CommandConsole::AddCmd( awcBuffer, VisibilityCPFriendly );
	}

	Asura_PrintfToBfr( awcBuffer, L"%S", 256, true, "Multiplayer.CMD.VisibilityCPContested" );
	if (!Asura_CommandConsole::CmdExists(awcBuffer))
	{
		Asura_CommandConsole::AddCmd( awcBuffer, VisibilityCPContested );
	}

	Asura_PrintfToBfr( awcBuffer, L"%S", 256, true, "Multiplayer.CMD.VisibilityCPNeutral" );
	if (!Asura_CommandConsole::CmdExists(awcBuffer))
	{
		Asura_CommandConsole::AddCmd( awcBuffer, VisibilityCPNeutral );
	}

	Asura_PrintfToBfr( awcBuffer, L"%S", 256, true, "Multiplayer.CMD.PopulateCPName" );
	if (!Asura_CommandConsole::CmdExists(awcBuffer))
	{
		Asura_CommandConsole::AddCmd( awcBuffer, PopulateCPName );
	}

	Asura_PrintfToBfr( awcBuffer, L"%S", 256, true, "Multiplayer.CMD.GetNumberOfTeams" );
	if (!Asura_CommandConsole::CmdExists(awcBuffer))
	{
		Asura_CommandConsole::AddCmd( awcBuffer, GetNumberOfTeams );
	}

	Asura_PrintfToBfr( awcBuffer, L"%S", 256, true, "Multiplayer.CMD.IsTeamBasedGame" );
	if (!Asura_CommandConsole::CmdExists(awcBuffer))
	{
		Asura_CommandConsole::AddCmd( awcBuffer, IsTeamBasedGame );
	}

}

bool AVP_Multiplayer_GameMessageSystem::GetSpamMessageByIndex( u_int uMessageIndex, bool bInterrogate, bool bHelp )
{
	if (bHelp || bInterrogate) { return false; }
	if (uMessageIndex < s_uAVP_MULTIPLAYER_SPAM_MESSAGES_MAX_NUMBER)
	{
		const SpamMessageEntry* pxSpamMessage = s_xSortedMesagesList.GetEntryByIndex(uMessageIndex); 
		if (pxSpamMessage)
		{
			if (pxSpamMessage->m_fTimeRemainingOnScreen > 0.0f)
			{
				Asura_CommandConsole::Printf(pxSpamMessage->m_aswzSpamMessageBuffer);
				return true;
			}
			else
			{
				Asura_Assert(false, "Expired message got sorted into this list, shouldn't be happenning"); 
			}
		}
	}
	return false;
}

int AVP_Multiplayer_GameMessageSystem::SortMessagesByTimeRemaining( const SpamMessageEntry& xMessageA, const SpamMessageEntry& xMessageB )
{
	if (xMessageA.m_fTimeRemainingOnScreen >= xMessageB.m_fTimeRemainingOnScreen)
	{
		return -1; 
	}
	else
	{
		return 1;
	}
}

int AVP_Multiplayer_GameMessageSystem::SortCapturePointsByGuid( const CapturePointState& xCapturePointA, const CapturePointState& xCapturePointB )
{
	if (xCapturePointA.m_uGuid >= xCapturePointB.m_uGuid)
	{
		return 1; 
	}
	else
	{
		return -1;
	}
}

void AVP_Multiplayer_GameMessageSystem::AddSpamMessage(Asura_UnicodeChar *swzMessage, float fDisplayTime)
{
	// Find the first string buffer going spare 
	for (u_int uIndex = 0; uIndex < s_uAVP_MULTIPLAYER_SPAM_MESSAGES_MAX_NUMBER; uIndex++)
	{
		// Not showing on the screen anymore?
		if (s_xSpamMessages[uIndex].m_fTimeRemainingOnScreen <= 0.0f)
		{
			Asura_PrintfToBfr(s_xSpamMessages[uIndex].m_aswzSpamMessageBuffer, swzMessage, s_uAVP_MULTIPLAYER_SPAM_MESSAGES_MAX_LENGTH ); 
			s_xSpamMessages[uIndex].m_fTimeRemainingOnScreen = fDisplayTime; 
			break; 
		}
	}
}

void AVP_Multiplayer_GameMessageSystem::AddCapturePoint(Asura_Guid uCapturePointGuid)
{
	// Ignore the request if we already have an entry for this Guid
	if ( s_xSortedCapturePointState.FindByGuid(uCapturePointGuid) != NULL)
	{
		return; 
	}

	const AVP_ClientEntity_CommandPost* pxCommandPost = AVP_ClientEntity_CommandPost::FindEntity( uCapturePointGuid ); 
	if (pxCommandPost)
	{
		struct AVP_Multiplayer_GameMessageSystem::CapturePointState xNewCapturePointState;
		xNewCapturePointState.m_uGuid = uCapturePointGuid; 
		xNewCapturePointState.m_bContested = pxCommandPost->IsContested(); 
		xNewCapturePointState.m_eControlledByTeam = static_cast<AVP_Settings::Team>( pxCommandPost->GetCurrentFaction() ); 
		Asura_Hash_ID uNameHashID = pxCommandPost->GetNameHashID(); 
		if (ASURA_HASH_ID_UNSET == uNameHashID)
		{
			Asura_PrintfToBfr( xNewCapturePointState.m_aswzCapturePointName, L"CP%u", 32, false, uCapturePointGuid ); 
		}
		else
		{
			// Find the localised string
			Asura_Hash_ID uMenuPage = Asura_GetHashID("Menu") ;
			const Asura_HashedLocalisedText_Page* pxPage = Asura_HashedLocalisedText::GetPage(uMenuPage);

			if(pxPage)
			{
				Asura_PrintfToBfr( xNewCapturePointState.m_aswzCapturePointName, L"%s", 32, false, pxPage->GetString(uNameHashID) );
			}
		}

		s_xSortedCapturePointState.Insert( xNewCapturePointState, SortCapturePointsByGuid );
	}
	else
	{
		Asura_Assert( false, "Couldn't find capture point client entity to register with the HUD, capture point list won't work with this entity" );
	}
}