/**
 *	Time Attack mode
 */

#Extends "Modes/TrackMania/ModeBase.Script.txt"

#Const	CompatibleMapTypes	"Race"
#Const	Version		"2014-01-22"
#Const	ScriptName	"TimeAttack.Script.txt"

#Include "TextLib" as TL
#Include "Libs/Nadeo/TrackMania/UI.Script.txt" as UI

// ---------------------------------- //
// Settings
// ---------------------------------- //
#Setting S_TimeLimit 	300	as _("Time limit :")

// ---------------------------------- //
// Constants
// ---------------------------------- //
#Const C_BotsNb 0

// ---------------------------------- //
// Extend
// ---------------------------------- //
***LogVersion***
***
MB_LogVersion(ScriptName, Version);
MB_LogVersion(UI::GetScriptName(), UI::GetScriptVersion());
***

***InitServer***
***
declare Integer PrevTimeLimit = S_TimeLimit;
declare Integer StartTime;
***

***StartServer***
***
// ---------------------------------- //
// Initialize mode
PrevTimeLimit = S_TimeLimit;
StartTime = -1;
IndependantLaps = True;
MB_SetDefaultRespawnMode(CTmMode::ETMRespawnBehaviour::GiveUpBeforeFirstCheckPoint);

// ---------------------------------- //
// Initialize UI
UI::Load(["TimeGap"]);
UI::SetTimeGapMode("BestRace");

// ---------------------------------- //
// Create scores table
ST2::SetStyle("LibST_TMBaseSolo");
ST2::CreateCol("LibST_TMBestTime", "", "--:--.---", 8., 60.);
ST2::SetColTextAlign("LibST_TMBestTime", CMlControl::AlignHorizontal::Right);
ST2::SetModeIcon("Icons128x32_1|RT_TimeAttack");
ST2::SetFooterText(TL::Compose("%1 "^TL::TimeToText(S_TimeLimit*1000, False), _("Time Limit :")));
MB_SetScoresTableStyleFromXml(S_ScoresTableStylePath);
ST2::Build("TM");
***

***InitMap***
***
// ---------------------------------- //
// Initialize scores
Scores_Clear();
ST2::ClearScores();
***

***StartMap***
***
// ---------------------------------- //
// Initialize map
Mode::Ladder_OpenMatch_All();
Users_SetNbFakeUsers(C_BotsNb, 0);

// ---------------------------------- //
// Warm up
declare ObjectiveNbLaps = Map.TMObjective_NbLaps;
if (ObjectiveNbLaps <= 0 || !Map.TMObjective_IsLapRace) ObjectiveNbLaps = 1;
declare MaxTime = (Map.TMObjective_AuthorTime / ObjectiveNbLaps) * S_WarmUpDuration;
declare WarmUpTimeLimit = Now + 5000 + MaxTime + (MaxTime / 6);
MB_WarmUp(WarmUpTimeLimit);

// ---------------------------------- //
// Initialize race
StartTime = Now + 3000;
CutOffTimeLimit = StartTime + (S_TimeLimit * 1000);
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Playing;

// ---------------------------------- //
// Spawn players for the race
foreach (Player in Players) {
	TM2::StartRace(Player, StartTime);
}
***

***WarmUp***
***
if (S_WarmUpDuration > 0) {		
	WarmUp::Begin();
	WarmUp::SetProgression(1, 1);
	CutOffTimeLimit = _TimeLimit;
	
	while (Now < CutOffTimeLimit && !WarmUp::Stop() && !ServerShutdownRequested && !MatchEndRequested) {
		MB_Yield();
		WarmUp::Loop();
		WarmUp::ManageEvents();
	}
	WarmUp::End();
	
	UIManager.UIAll.BigMessage = _("End of warmup, match starting...");
	UIManager.UIAll.UISequence = CUIConfig::EUISequence::EndRound;
	CutOffTimeLimit = Now + 4000;
	while (Now < CutOffTimeLimit && !ServerShutdownRequested && !MatchEndRequested) {
		MB_Yield();
	}
	CutOffTimeLimit = -1;
	UIManager.UIAll.BigMessage = "";
	UIManager.UIAll.UISequence = CUIConfig::EUISequence::Playing;
}
***

***PlayLoop***
***
// ---------------------------------- //
// Update the map duration setting
if (PrevTimeLimit != S_TimeLimit) {
	PrevTimeLimit = S_TimeLimit;
	CutOffTimeLimit = StartTime + (S_TimeLimit * 1000);
	ST2::SetFooterText(TL::Compose("%1 "^TL::TimeToText(S_TimeLimit*1000, False), _("Time Limit :")));
}

// ---------------------------------- //
// Spawn players
foreach (Player in Players) {
	if (TM2::IsWaiting(Player)) {
		TM2::StartRace(Player);
	}
}

// ---------------------------------- //
// Manage events
foreach (Event in PendingEvents) {
	PassOn(Event);
	XmlRpc::PassOn(Event);
	
	// ---------------------------------- //
	// Waypoint
	if (Event.Type == CTmModeEvent::EType::WayPoint) {
		if (Event.IsEndRace) {
			if (Event.Player.Score != Null) {
				if (Event.Player.Score.BestRace.Compare(Event.Player.CurRace, CTmResult::ETmRaceResultCriteria::Time) <= 0) {
					Event.Player.Score.BestRace = Event.Player.CurRace;
					Event.Player.Score.BestLap = Event.Player.CurRace;
				}
			}
			Event.Player.Score.PrevRace = Event.Player.CurRace;
			TM2::EndRace(Event.Player);
			Scores_Sort(CTmMode::ETmScoreSortOrder::BestRace_Time);
		} else if (Event.IsEndLap) {
			if (Event.Player.Score != Null) {
				if (Event.Player.Score.BestLap.Compare(Event.Player.CurLap, CTmResult::ETmRaceResultCriteria::Time) <= 0) {
					Event.Player.Score.BestLap = Event.Player.CurLap;
					Event.Player.Score.BestRace = Event.Player.CurLap;
				}
			}
			Event.Player.Score.PrevRace = Event.Player.CurLap;
			Scores_Sort(CTmMode::ETmScoreSortOrder::BestRace_Time);
		}
	}
	// ---------------------------------- //
	// GiveUp
	else if (Event.Type == CTmModeEvent::EType::GiveUp) {
		TM2::WaitRace(Event.Player);
	}
}

// ---------------------------------- //
// End the map when time limit is reached
if (Now >= CutOffTimeLimit) {
	MB_StopMap = True;
}
***

***EndMap***
***
TM2::WaitRaceAll();

// ---------------------------------- //
// Close ladder
// Do not grant LP if the map was skipped
if (Now >= CutOffTimeLimit) {
	Ladder_ComputeRank(CTmMode::ETmScoreSortOrder::BestRace_Time);
	Mode::Ladder_CloseMatch();
} else {
	Mode::Ladder_CancelMatch();		
}

Scores_Sort(CTmMode::ETmScoreSortOrder::BestRace_Time);
if (Scores.existskey(0) &&  Scores[0].BestRace.Time > 0) {
	MB_VictoryMessage = TL::Compose(_("$<%1$> wins the map!"), Scores[0].User.Name);
}
***

***EndServer***
***
UI::Unload();
***