Update filehandler.uc

Update filehandler.uc

Added Name As (for file renaming)

# filehandler.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.95 on 3/28/2014 2:13:18 PM
# Comment: File handler

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, InputFile, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique, FilterTally

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: True
Exclude: False
Comment: File handler
Selected: False
Highlight: True
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: True
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
FilterTally: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
InputFile:
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Selected: True
Find:
Replace: {@Token:: : ~~ Properties: ucStatementSep }

Criteria: 2
Comment:
Pass: 1

Criteria: 3
BackColor: Yellow
SkipOver: True
Find: ' {Comment:".*"}
Replace: [Skip over]

Criteria: 4
BackColor: DeepSkyBlue
Find: {@Start}
Replace: #include <iostream>
         #include <fstream>
         {@Var: FreeFileNum}

Criteria: 5
BackColor: DeepSkyBlue
Find: Open {filespec}
      { For {{Input: Input}|{Output: Output}|{Append: Append}|{Binary: Binary}|{Random: Random}}|{Default: } }
      { Access Read | Access Write | Access Read Write | }
      { Lock {{LockRead: Read}|{LockWrite: Write}|{LockBoth: Read Write}|{LockShared: Shared}}|{LockDefault: } }
      As [#]{filenum} [Len = {size=128}]
Replace: fstream file_{filenum} (string({filespec}).c_str(),
            {Input:   ios::in}
            {Output:  ios::out | ios::trunc}
            {Append:  ios::out | ios::app}
            {Binary:  ios::binary | ios::in | ios::out}
            {Random:  ios::binary | ios::in | ios::out}
            {Default: ios::binary | ios::in | ios::out}
         );

Criteria: 6
BackColor: Lime
Find: Close [#]{filenum}
Replace: file_{filenum}.close() ' PB: Close #{filenum}

Criteria: 7
BackColor: RoyalBlue
PassOnce: False
Find: Close [#]{file1}, {more}
Replace: Close {file1}
         Close {more}

Criteria: 8
BackColor: Pink
Find: Seek [#] {filenum}, {position}
Replace: file_{filenum}.seekg({position}-1)
         file_{filenum}.seekp({position}-1)

Criteria: 9
Find: Seek([#] {filenum})
Replace: file_{filenum}.tellg()+1

Criteria: 10
BackColor: SlateBlue
Find: LOF({filenum})
Replace: PB_LOF({filenum})

Criteria: 11
Find: EOF({filenum})
Replace: file_{filenum}.eof()

Criteria: 12
Find: FreeFile
Replace: {@Eval: FreeFileNum += 1; FreeFileNum}

Criteria: 13
BackColor: Green
Find: Get$ [#] {filenum}, {count}, {StringVar}
Replace: {StringVar}.resize({count})
         file_{filenum}.read(&{StringVar}[0], {count})

Criteria: 14
BackColor: SandyBrown
Find: Put$ [#] {filenum}, {text}
Replace: file_{filenum}.write(&{text}[0], {text}.size())

Criteria: 15
Find: IsFile({file})
Replace: PB_ISFILE({file})

Criteria: 16
Find: Name {oldname} As {newname}
Replace: PB_NAME({oldname}, {newname})

Criteria: 17
BackColor: Gold
Find: EXE.Extn$
Replace: PB_EXE_EXTN

Criteria: 18
BackColor: Silver
Find: EXE.Full$
Replace: PB_EXE_FULL()

Criteria: 19
Find: EXE.Name$
Replace: PB_EXE_NAME

Criteria: 20
BackColor: CornflowerBlue
Find: EXE.Namex$
Replace: PB_EXE_NAMEX

Criteria: 21
Find: EXE.Path$
Replace: PB_EXE_PATH

Criteria: 22
Find: Dir$({mask})
Replace: PB_DIR({mask})

Criteria: 23
Find: Dir$([Next])
Replace: PB_DIR_NEXT()

Criteria: 24
Find: Print #{filenum}
Replace: file_{filenum} << endl

Criteria: 25
Find: Print #{filenum}, {text}
Replace: file_{filenum} << {text} << endl

Criteria: 26
Find: Print #{filenum}, {text};
Replace: file_{filenum} << {text}

Criteria: 27
PassOnce: False
Find: Print #{filenum}, {text}; {MoreText}
Replace: Print #{filenum}, {text} << {MoreText}

Criteria: 28
Comment:
Pass: 2

Criteria: 29
BackColor: Yellow
Find: fstream {file} ({args+})
Replace: {@Eval: Replace('{Self}', '{"[ \n]+"}', ' ')}

# End Search

# filehandler.uc - uCalc Transformation file
# This file was saved with uCalc Transform 2.95 on 3/25/2014 6:01:40 PM
# Comment: File handler

ExternalKeywords: Exclude, Comment, Selected, ParentChild, FindMode, InputFile, OutputFile, BatchAction, SEND
ExternalKeywords: Highlight, ForeColor, BackColor, FontName, FontSize, FontStyle
ExternalKeywords: FilterEndText, FilterSeparator, FilterSort, FilterSortFunc, FilterStartText, FilterUnique, FilterTally

FindMode: Replace

# Definitions

# Search Criteria

Criteria: 0
Enabled: True
Exclude: False
Comment: File handler
Selected: False
Highlight: True
ForeColor: ControlText
BackColor: Aqua
FontName:
FontSize:
FontStyle:
CaseSensitive: False
QuoteSensitive: True
CodeBlockSensitive: True
FilterEndText:
FilterSeparator: {#10}
FilterSort: False
FilterSortFunc:
FilterStartText:
FilterUnique: False
FilterTally: False
Min: 0
Max: -1
MinSoft: 0
MaxSoft: -1
BatchAction: Transform
InputFile:
OutputFile:
SEND:
StartAfter: 0
StopAfter: -1
SkipOver: False
ParentChild: 0
Pass: 0
PassOnce: True
Precedence: 0
RightToLeft: False

Criteria: 1
Comment:
Pass: 1

Criteria: 2
BackColor: Yellow
SkipOver: True
Find: ' {Comment:".*"}
Replace: [Skip over]

Criteria: 3
BackColor: DeepSkyBlue
Find: {@Start}
Replace: #include <iostream>
         #include <fstream>
         {@Var: FreeFileNum}

Criteria: 4
BackColor: DeepSkyBlue
Find: Open {filespec}
      { For {{Input: Input}|{Output: Output}|{Append: Append}|{Binary: Binary}|{Random: Random}}|{Default: } }
      { Access Read | Access Write | Access Read Write | }
      { Lock {{LockRead: Read}|{LockWrite: Write}|{LockBoth: Read Write}|{LockShared: Shared}}|{LockDefault: } }
      As [#]{filenum} [Len = {size=128}]
Replace: fstream file_{filenum} (string({filespec}).c_str(),
            {Input:   ios::in}
            {Output:  ios::out | ios::trunc}
            {Append:  ios::out | ios::app}
            {Binary:  ios::binary | ios::in | ios::out}
            {Random:  ios::binary | ios::in | ios::out}
            {Default: ios::binary | ios::in | ios::out}
         );

Criteria: 5
BackColor: Lime
Find: Close [#]{filenum}
Replace: file_{filenum}.close() ' PB: Close #{filenum}

Criteria: 6
BackColor: RoyalBlue
PassOnce: False
Find: Close [#]{file1}, {more}
Replace: Close {file1}
         Close {more}

Criteria: 7
BackColor: Pink
Find: Seek [#] {filenum}, {position}
Replace: file_{filenum}.seekg({position}-1)
         file_{filenum}.seekp({position}-1)

Criteria: 8
Find: Seek([#] {filenum})
Replace: file_{filenum}.tellg()+1

Criteria: 9
Selected: True
BackColor: SlateBlue
Find: LOF({filenum})
Replace: PB_LOF({filenum})

Criteria: 10
Find: EOF({filenum})
Replace: file_{filenum}.eof()

Criteria: 11
Find: FreeFile
Replace: {@Eval: FreeFileNum += 1; FreeFileNum}

Criteria: 12
BackColor: Green
Find: Get$ [#] {filenum}, {count}, {StringVar}
Replace: {StringVar}.resize({count})
         file_{filenum}.read(&{StringVar}[0], {count})

Criteria: 13
BackColor: SandyBrown
Find: Put$ [#] {filenum}, {text}
Replace: file_{filenum}.write(&{text}[0], {text}.size())

Criteria: 14
Find: IsFile({file})
Replace: PB_ISFILE({file})

Criteria: 15
BackColor: Gold
Find: EXE.Extn$
Replace: PB_EXE_EXTN

Criteria: 16
BackColor: Silver
Find: EXE.Full$
Replace: PB_EXE_FULL()

Criteria: 17
Find: EXE.Name$
Replace: PB_EXE_NAME

Criteria: 18
BackColor: CornflowerBlue
Find: EXE.Namex$
Replace: PB_EXE_NAMEX

Criteria: 19
Find: EXE.Path$
Replace: PB_EXE_PATH

Criteria: 20
Find: Dir$({mask})
Replace: PB_DIR({mask})

Criteria: 21
Find: Dir$([Next])
Replace: PB_DIR_NEXT()

Criteria: 22
Find: Print #{filenum}
Replace: file_{filenum} << endl

Criteria: 23
Find: Print #{filenum}, {text}
Replace: file_{filenum} << {text} << endl

Criteria: 24
Find: Print #{filenum}, {text};
Replace: file_{filenum} << {text}

Criteria: 25
PassOnce: False
Find: Print #{filenum}, {text}; {MoreText}
Replace: Print #{filenum}, {text} << {MoreText}

Criteria: 26
Comment:
Pass: 2

Criteria: 27
BackColor: Yellow
Find: fstream {file} ({args+})
Replace: {@Eval: Replace('{Self}', '{"[ \n]+"}', ' ')}

# End Search


#596 - typo fix

#596 - typo fix

//---------------------------------------------------------------------------------------
//  FILE:    XComGameState_DarkEvent.uc
//  AUTHOR:  Mark Nauta
//
//---------------------------------------------------------------------------------------
//  Copyright (c) 2016 Firaxis Games, Inc. All rights reserved.
//---------------------------------------------------------------------------------------
class XComGameState_DarkEvent extends XComGameState_BaseObject
	dependson(X2StrategyGameRulesetDataStructures)
	config(GameData);

var() protected name                   m_TemplateName;
var() protected X2DarkEventTemplate    m_Template;

var int								   Weight;
var int								   TimesPlayed;
var int								   TimesSucceeded;
var bool							   bSecretEvent;
var bool							   bChosenActionEvent;
var StateObjectReference			   ChosenRef;
var TDateTime						   StartDateTime;
var TDateTime						   EndDateTime;
var float							   TimeRemaining;
var StrategyCost					   RevealCost;

// Issue #596
/// HL-Docs: feature:TemporarilyBlockDarkEventActivation; issue:597; tags:strategy,compat
/// While this flag is turned on, the dark event cannot activate/complete (transition from preparing to active)
/// and will simply "wait" until this flag is turned off. Another possible way of looking at it
/// is that the DE is postponed indefinitely while this flag is active but only if the EndDateTime was reached.
/// HL-Include:
var bool							   bTemporarilyBlockActivation;
///

var localized string				   SecretTitle;
var localized string				   SecretSummary;
var localized string				   SecretPreMissionText;

var config string					   SecretImagePath;
var config array<int>				   StartingIntelCost;
var config array<int>				   IntelCostIncrease;

// #######################################################################################
// -------------------- INITIALIZATION ---------------------------------------------------
// #######################################################################################

//---------------------------------------------------------------------------------------
static function X2StrategyElementTemplateManager GetMyTemplateManager()
{
	return class'X2StrategyElementTemplateManager'.static.GetStrategyElementTemplateManager();
}

//---------------------------------------------------------------------------------------
simulated function name GetMyTemplateName()
{
	return m_TemplateName;
}

//---------------------------------------------------------------------------------------
simulated function X2DarkEventTemplate GetMyTemplate()
{
	if(m_Template == none)
	{
		m_Template = X2DarkEventTemplate(GetMyTemplateManager().FindStrategyElementTemplate(m_TemplateName));
	}
	return m_Template;
}

//---------------------------------------------------------------------------------------
event OnCreation(optional X2DataTemplate InitTemplate)
{
	super.OnCreation( InitTemplate );

	m_Template = X2DarkEventTemplate(InitTemplate);
	m_TemplateName = m_Template.DataName;
	Weight = m_Template.StartingWeight;
}

//---------------------------------------------------------------------------------------
static function SetUpDarkEvents(XComGameState StartState)
{
	local array<X2StrategyElementTemplate> DarkEventTemplates;
	local int idx;

	// Grab all DarkEvent Templates
	DarkEventTemplates = GetMyTemplateManager().GetAllTemplatesOfClass(class'X2DarkEventTemplate');

	// Iterate through the templates and build each DarkEvent State Object
	for(idx = 0; idx < DarkEventTemplates.Length; idx++)
	{
		StartState.CreateNewStateObject(class'XComGameState_DarkEvent', DarkEventTemplates[idx]);
	}
}

// #######################################################################################
// -------------------- DISPLAY FUNCTIONS ------------------------------------------------
// #######################################################################################

//---------------------------------------------------------------------------------------
function string GetDisplayName()
{
	if(bSecretEvent)
	{
		return SecretTitle;
	}

	return GetMyTemplate().DisplayName;
}

//---------------------------------------------------------------------------------------
function string GetSummary()
{
	local XGParamTag ParamTag;
	local array<StrategyCostScalar> CostScalars;

	if(bSecretEvent)
	{
		CostScalars.Length = 0;
		ParamTag = XGParamTag(`XEXPANDCONTEXT.FindTag("XGParam"));
		ParamTag.StrValue0 = class'UIUtilities_Strategy'.static.GetStrategyCostString(RevealCost, CostScalars);
		return `XEXPAND.ExpandString(SecretSummary);
	}

	if(GetMyTemplate().GetSummaryFn != none)
	{
		return GetMyTemplate().GetSummaryFn(GetMyTemplate().SummaryText);
	}

	return GetMyTemplate().SummaryText;
}
//---------------------------------------------------------------------------------------
function string GetCost()
{
	local array<StrategyCostScalar> CostScalars;

	if(bSecretEvent)
	{
		CostScalars.Length = 0;
		return class'UIUtilities_Strategy'.static.GetStrategyCostString(RevealCost, CostScalars);
	}

	return "";
}
//---------------------------------------------------------------------------------------
function string GetQuote()
{
	if(bSecretEvent)
	{
		return "";
	}

	return GetMyTemplate().QuoteText;
}
//---------------------------------------------------------------------------------------
function string GetQuoteAuthor()
{
	if(bSecretEvent)
	{
		return "";
	}

	return GetMyTemplate().QuoteTextAuthor;
}
//---------------------------------------------------------------------------------------
function string GetPreMissionText()
{
	if(bSecretEvent)
	{
		return SecretPreMissionText;
	}

	if(GetMyTemplate().GetPreMissionTextFn != none)
	{
		return GetMyTemplate().GetPreMissionTextFn(GetMyTemplate().PreMissionText);
	}

	return GetMyTemplate().PreMissionText;
}

//---------------------------------------------------------------------------------------
function string GetPostMissionText(bool bSuccess)
{
	if(bSuccess)
	{
		return GetMyTemplate().PostMissionSuccessText;
	}

	return GetMyTemplate().PostMissionFailureText;
}

//---------------------------------------------------------------------------------------
function string GetImage()
{
	if(bSecretEvent)
	{
		return SecretImagePath;
	}

	return GetMyTemplate().ImagePath;
}

// #######################################################################################
// -------------------- ACTIVATION/DEACTIVATION ------------------------------------------
// #######################################################################################

//---------------------------------------------------------------------------------------
function OnActivated(XComGameState NewGameState)
{
	// Reveal the Event
	bSecretEvent = false;
	RevealCost.ResourceCosts.Length = 0;
	RevealCost.ArtifactCosts.Length = 0;

	if(GetMyTemplate().OnActivatedFn != none)
	{
		GetMyTemplate().OnActivatedFn(NewGameState, self.GetReference());
	}
	RevealObjectiveUI(NewGameState);
	class'XComGameState_HeadquartersResistance'.static.RecordResistanceActivity(NewGameState, 'ResAct_DarkEventsCompleted');
}

//---------------------------------------------------------------------------------------
function OnDeactivated(XComGameState NewGameState)
{
	// Issue #753
	//
	/// HL-Docs: feature:PreDarkEventDeactivated; issue:753; tags:strategy
	/// Notifies listeners of when a dark event has expired/been deactivated. This
	/// event fires before the dark event's deactivation code runs, so register an
	/// ELD_Immediate listener if you want access to the state before that happens,
	/// or an ELD_OnStateSubmitted listener if you want the state *after* the full
	/// deactivation.
	///
	/// ```unrealscript
	/// EventID: PreDarkEventDeactivated
	/// EventData: XCGS_DarkEvent
	/// EventSource: XCGS_DarkEvent
	/// NewGameState: yes
	/// ```
	`XEVENTMGR.TriggerEvent('PreDarkEventDeactivated', self, self, NewGameState);
	// End Issue #753

	if(GetMyTemplate().OnDeactivatedFn != none)
	{
		GetMyTemplate().OnDeactivatedFn(NewGameState, self.GetReference());
	}
	DeactivateObjectiveUI(NewGameState);
	bChosenActionEvent = false;
	ChosenRef.ObjectID = 0;
}

//---------------------------------------------------------------------------------------
function bool CanActivate()
{
	// Event is non-repeatable and has already been activated
	if(!GetMyTemplate().bRepeatable && TimesSucceeded > 0)
	{
		return false;
	}

	// Event is repeatable but has activated its max amount of times
	if((GetMyTemplate().bRepeatable) && (GetMyTemplate().MaxSuccesses > 0) && (TimesSucceeded >= GetMyTemplate().MaxSuccesses))
	{
		return false;
	}

	// Check template specific function
	if(GetMyTemplate().CanActivateFn != none)
	{
		return GetMyTemplate().CanActivateFn(self);
	}

	return true;
}

//---------------------------------------------------------------------------------------
function bool CanComplete()
{
	if(GetMyTemplate().CanCompleteFn != none)
	{
		return GetMyTemplate().CanCompleteFn(self);
	}

	return true;
}

// #######################################################################################
// -------------------- TIMER HELPERS ----------------------------------------------------
// #######################################################################################

//---------------------------------------------------------------------------------------
function StartActivationTimer(optional MinMaxDays ActivationTime)
{
	local int HoursToAdd, MinDays, MaxDays;

	StartDateTime = `STRATEGYRULES.GameTime;
	EndDateTime = StartDateTime;

	if(ActivationTime.MaxDays > 0)
	{
		MinDays = ActivationTime.MinDays;
		MaxDays = ActivationTime.MaxDays;
	}
	else
	{
		MinDays = GetMyTemplate().MinActivationDays;
		MaxDays = GetMyTemplate().MaxActivationDays;
	}

	HoursToAdd = (MinDays * 24) + `SYNC_RAND_STATIC((MaxDays * 24) - (MinDays * 24) + 1);

	class'X2StrategyGameRulesetDataStructures'.static.AddHours(EndDateTime, HoursToAdd);
	TimeRemaining = class'X2StrategyGameRulesetDataStructures'.static.DifferenceInSeconds(EndDateTime, StartDateTime);
}

//---------------------------------------------------------------------------------------
// Helper for Hack Rewards to modify duration
function ExtendActivationTimer(int ExtraHours)
{
	class'X2StrategyGameRulesetDataStructures'.static.AddHours(EndDateTime, ExtraHours);
	TimeRemaining = class'X2StrategyGameRulesetDataStructures'.static.DifferenceInSeconds(EndDateTime, StartDateTime);
}

//---------------------------------------------------------------------------------------
// Helper for Expired GOps to modify duration
function DecreaseActivationTimer(int ExtraHours)
{
	class'X2StrategyGameRulesetDataStructures'.static.RemoveHours(EndDateTime, ExtraHours);
	TimeRemaining = class'X2StrategyGameRulesetDataStructures'.static.DifferenceInSeconds(EndDateTime, StartDateTime);
}

//---------------------------------------------------------------------------------------
function StartDurationTimer(optional int DurationHours = 0)
{
	local int HoursToAdd;

	StartDateTime = `STRATEGYRULES.GameTime;
	EndDateTime = StartDateTime;

	if (DurationHours > 0)
	{
		HoursToAdd = DurationHours;
	}
	else
	{
		HoursToAdd = (GetMyTemplate().MinDurationDays * 24) + `SYNC_RAND_STATIC((GetMyTemplate().MaxDurationDays * 24) - (GetMyTemplate().MinDurationDays * 24) + 1);
	}

	class'X2StrategyGameRulesetDataStructures'.static.AddHours(EndDateTime, HoursToAdd);
	TimeRemaining = class'X2StrategyGameRulesetDataStructures'.static.DifferenceInSeconds(EndDateTime, StartDateTime);
}

//---------------------------------------------------------------------------------------
function PauseTimer()
{
	// Update Time remaining and set end time to unreachable future
	TimeRemaining = class'X2StrategyGameRulesetDataStructures'.static.DifferenceInSeconds(EndDateTime, `STRATEGYRULES.GameTime);
	EndDateTime.m_iYear = 9999;
}

//---------------------------------------------------------------------------------------
function ResumeTimer()
{
	// Update the start time then calculate the end time using the time remaining
	StartDateTime = `STRATEGYRULES.GameTime;
	EndDateTime = StartDateTime;

	class'X2StrategyGameRulesetDataStructures'.static.AddTime(EndDateTime, TimeRemaining);
}

// #######################################################################################
// -------------------- REVEAL COST ------------------------------------------------------
// #######################################################################################

//---------------------------------------------------------------------------------------
function SetRevealCost()
{
	local XComGameStateHistory History;
	local XComGameState_HeadquartersResistance ResistanceHQ;
	local ArtifactCost IntelCost;

	History = `XCOMHISTORY;
	ResistanceHQ = XComGameState_HeadquartersResistance(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersResistance'));

	RevealCost.ResourceCosts.Length = 0;
	IntelCost.ItemTemplateName = 'Intel';
	IntelCost.Quantity = `ScaleStrategyArrayInt(default.StartingIntelCost) + (ResistanceHQ.NumMonths * `ScaleStrategyArrayInt(default.IntelCostIncrease));
	RevealCost.ResourceCosts.AddItem(IntelCost);
}

//---------------------------------------------------------------------------------------
function RevealEvent(XComGameState NewGameState)
{
	local XComGameStateHistory History;
	local XComGameState_HeadquartersXCom XComHQ;
	local array<StrategyCostScalar> CostScalars;

	History = `XCOMHISTORY;
	XComHQ = XComGameState_HeadquartersXCom(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersXCom'));
	XComHQ = XComGameState_HeadquartersXCom(NewGameState.ModifyStateObject(class'XComGameState_HeadquartersXCom', XComHQ.ObjectID));

	CostScalars.Length = 0;
	XComHQ.PayStrategyCost(NewGameState, RevealCost, CostScalars);

	bSecretEvent = false;
	RevealCost.ResourceCosts.Length = 0;
	RevealCost.ArtifactCosts.Length = 0;
}

// #######################################################################################
// -------------------- REVEAL OBJECTIVE UI ----------------------------------------------
// #######################################################################################

function RevealObjectiveUI(XComGameState NewGameState)
{
	local ObjectiveDisplayInfo ObjDisplayInfo;
	local XComGameStateHistory History;
	local XComGameState_ObjectivesList ObjListState;

	if( bSecretEvent )
	{
		return;
	}

	if( !GetMyTemplate().bNeverShowObjective )
	{
		History = `XCOMHISTORY;

			foreach NewGameState.IterateByClassType(class'XComGameState_ObjectivesList', ObjListState)
		{
				break;
			}

		if( ObjListState == None )
		{
			foreach History.IterateByClassType(class'XComGameState_ObjectivesList', ObjListState)
			{
				break;
			}

			if( ObjListState != none )
			{
				ObjListState = XComGameState_ObjectivesList(NewGameState.ModifyStateObject(class'XComGameState_ObjectivesList', ObjListState.ObjectID));
			}
			else
			{
				ObjListState = XComGameState_ObjectivesList(NewGameState.CreateNewStateObject(class'XComGameState_ObjectivesList'));
			}
		}

		ObjDisplayInfo.ShowHeader = false;
		ObjDisplayInfo.ShowCheckBox = false;
		ObjDisplayInfo.bIsDarkEvent = true;
		ObjDisplayInfo.MissionType = "DARKEVENTOBJECTIVE";

		ObjDisplayInfo.GroupID = ObjectID;
		ObjDisplayInfo.DisplayLabel = GetDisplayName();
		ObjDisplayInfo.HideInTactical = true;
		ObjDisplayInfo.GPObjective = true;
		ObjDisplayInfo.ObjectiveTemplateName = GetMyTemplateName();
		ObjListState.SetObjectiveDisplay(ObjDisplayInfo);

		class'X2StrategyGameRulesetDataStructures'.static.UpdateObjectivesUI(NewGameState);
	}
}

function DeactivateObjectiveUI(XComGameState NewGameState)
{
	local XComGameStateHistory History;
	local XComGameState_ObjectivesList ObjListState;

	History = `XCOMHISTORY;

	foreach NewGameState.IterateByClassType(class'XComGameState_ObjectivesList', ObjListState)
	{
		break;
	}

	if( ObjListState == None )
	{
		foreach History.IterateByClassType(class'XComGameState_ObjectivesList', ObjListState)
		{
			break;
		}

		if( ObjListState != none )
		{
			ObjListState = XComGameState_ObjectivesList(NewGameState.ModifyStateObject(class'XComGameState_ObjectivesList', ObjListState.ObjectID));
		}
		else
		{
			ObjListState = XComGameState_ObjectivesList(NewGameState.CreateNewStateObject(class'XComGameState_ObjectivesList'));
		}
	}

	ObjListState.HideObjectiveDisplay("DARKEVENTOBJECTIVE", GetDisplayName());
	class'X2StrategyGameRulesetDataStructures'.static.UpdateObjectivesUI(NewGameState);
}

DefaultProperties
{
}

//---------------------------------------------------------------------------------------
//  FILE:    XComGameState_DarkEvent.uc
//  AUTHOR:  Mark Nauta
//
//---------------------------------------------------------------------------------------
//  Copyright (c) 2016 Firaxis Games, Inc. All rights reserved.
//---------------------------------------------------------------------------------------
class XComGameState_DarkEvent extends XComGameState_BaseObject
	dependson(X2StrategyGameRulesetDataStructures)
	config(GameData);

var() protected name                   m_TemplateName;
var() protected X2DarkEventTemplate    m_Template;

var int								   Weight;
var int								   TimesPlayed;
var int								   TimesSucceeded;
var bool							   bSecretEvent;
var bool							   bChosenActionEvent;
var StateObjectReference			   ChosenRef;
var TDateTime						   StartDateTime;
var TDateTime						   EndDateTime;
var float							   TimeRemaining;
var StrategyCost					   RevealCost;

// Issue #596
/// HL-Docs: feature:TemporarilyBlockDarkEventActivation; issue:597; tags:strategy,compat
/// While this flag is turned on, the dark event cannot activate/complete (transition from preparing to active)
/// and will simply "wait" until this flag is turned off. Another possible way of looking at it
/// is that the DE is postponed indefinetly while this flag is active but only if the EndDateTime was reached.
/// HL-Include:
var bool							   bTemporarilyBlockActivation;
///

var localized string				   SecretTitle;
var localized string				   SecretSummary;
var localized string				   SecretPreMissionText;

var config string					   SecretImagePath;
var config array<int>				   StartingIntelCost;
var config array<int>				   IntelCostIncrease;

// #######################################################################################
// -------------------- INITIALIZATION ---------------------------------------------------
// #######################################################################################

//---------------------------------------------------------------------------------------
static function X2StrategyElementTemplateManager GetMyTemplateManager()
{
	return class'X2StrategyElementTemplateManager'.static.GetStrategyElementTemplateManager();
}

//---------------------------------------------------------------------------------------
simulated function name GetMyTemplateName()
{
	return m_TemplateName;
}

//---------------------------------------------------------------------------------------
simulated function X2DarkEventTemplate GetMyTemplate()
{
	if(m_Template == none)
	{
		m_Template = X2DarkEventTemplate(GetMyTemplateManager().FindStrategyElementTemplate(m_TemplateName));
	}
	return m_Template;
}

//---------------------------------------------------------------------------------------
event OnCreation(optional X2DataTemplate InitTemplate)
{
	super.OnCreation( InitTemplate );

	m_Template = X2DarkEventTemplate(InitTemplate);
	m_TemplateName = m_Template.DataName;
	Weight = m_Template.StartingWeight;
}

//---------------------------------------------------------------------------------------
static function SetUpDarkEvents(XComGameState StartState)
{
	local array<X2StrategyElementTemplate> DarkEventTemplates;
	local int idx;

	// Grab all DarkEvent Templates
	DarkEventTemplates = GetMyTemplateManager().GetAllTemplatesOfClass(class'X2DarkEventTemplate');

	// Iterate through the templates and build each DarkEvent State Object
	for(idx = 0; idx < DarkEventTemplates.Length; idx++)
	{
		StartState.CreateNewStateObject(class'XComGameState_DarkEvent', DarkEventTemplates[idx]);
	}
}

// #######################################################################################
// -------------------- DISPLAY FUNCTIONS ------------------------------------------------
// #######################################################################################

//---------------------------------------------------------------------------------------
function string GetDisplayName()
{
	if(bSecretEvent)
	{
		return SecretTitle;
	}

	return GetMyTemplate().DisplayName;
}

//---------------------------------------------------------------------------------------
function string GetSummary()
{
	local XGParamTag ParamTag;
	local array<StrategyCostScalar> CostScalars;

	if(bSecretEvent)
	{
		CostScalars.Length = 0;
		ParamTag = XGParamTag(`XEXPANDCONTEXT.FindTag("XGParam"));
		ParamTag.StrValue0 = class'UIUtilities_Strategy'.static.GetStrategyCostString(RevealCost, CostScalars);
		return `XEXPAND.ExpandString(SecretSummary);
	}

	if(GetMyTemplate().GetSummaryFn != none)
	{
		return GetMyTemplate().GetSummaryFn(GetMyTemplate().SummaryText);
	}

	return GetMyTemplate().SummaryText;
}
//---------------------------------------------------------------------------------------
function string GetCost()
{
	local array<StrategyCostScalar> CostScalars;

	if(bSecretEvent)
	{
		CostScalars.Length = 0;
		return class'UIUtilities_Strategy'.static.GetStrategyCostString(RevealCost, CostScalars);
	}

	return "";
}
//---------------------------------------------------------------------------------------
function string GetQuote()
{
	if(bSecretEvent)
	{
		return "";
	}

	return GetMyTemplate().QuoteText;
}
//---------------------------------------------------------------------------------------
function string GetQuoteAuthor()
{
	if(bSecretEvent)
	{
		return "";
	}

	return GetMyTemplate().QuoteTextAuthor;
}
//---------------------------------------------------------------------------------------
function string GetPreMissionText()
{
	if(bSecretEvent)
	{
		return SecretPreMissionText;
	}

	if(GetMyTemplate().GetPreMissionTextFn != none)
	{
		return GetMyTemplate().GetPreMissionTextFn(GetMyTemplate().PreMissionText);
	}

	return GetMyTemplate().PreMissionText;
}

//---------------------------------------------------------------------------------------
function string GetPostMissionText(bool bSuccess)
{
	if(bSuccess)
	{
		return GetMyTemplate().PostMissionSuccessText;
	}

	return GetMyTemplate().PostMissionFailureText;
}

//---------------------------------------------------------------------------------------
function string GetImage()
{
	if(bSecretEvent)
	{
		return SecretImagePath;
	}

	return GetMyTemplate().ImagePath;
}

// #######################################################################################
// -------------------- ACTIVATION/DEACTIVATION ------------------------------------------
// #######################################################################################

//---------------------------------------------------------------------------------------
function OnActivated(XComGameState NewGameState)
{
	// Reveal the Event
	bSecretEvent = false;
	RevealCost.ResourceCosts.Length = 0;
	RevealCost.ArtifactCosts.Length = 0;

	if(GetMyTemplate().OnActivatedFn != none)
	{
		GetMyTemplate().OnActivatedFn(NewGameState, self.GetReference());
	}
	RevealObjectiveUI(NewGameState);
	class'XComGameState_HeadquartersResistance'.static.RecordResistanceActivity(NewGameState, 'ResAct_DarkEventsCompleted');
}

//---------------------------------------------------------------------------------------
function OnDeactivated(XComGameState NewGameState)
{
	// Issue #753
	//
	/// HL-Docs: feature:PreDarkEventDeactivated; issue:753; tags:strategy
	/// Notifies listeners of when a dark event has expired/been deactivated. This
	/// event fires before the dark event's deactivation code runs, so register an
	/// ELD_Immediate listener if you want access to the state before that happens,
	/// or an ELD_OnStateSubmitted listener if you want the state *after* the full
	/// deactivation.
	///
	/// ```unrealscript
	/// EventID: PreDarkEventDeactivated
	/// EventData: XCGS_DarkEvent
	/// EventSource: XCGS_DarkEvent
	/// NewGameState: yes
	/// ```
	`XEVENTMGR.TriggerEvent('PreDarkEventDeactivated', self, self, NewGameState);
	// End Issue #753

	if(GetMyTemplate().OnDeactivatedFn != none)
	{
		GetMyTemplate().OnDeactivatedFn(NewGameState, self.GetReference());
	}
	DeactivateObjectiveUI(NewGameState);
	bChosenActionEvent = false;
	ChosenRef.ObjectID = 0;
}

//---------------------------------------------------------------------------------------
function bool CanActivate()
{
	// Event is non-repeatable and has already been activated
	if(!GetMyTemplate().bRepeatable && TimesSucceeded > 0)
	{
		return false;
	}

	// Event is repeatable but has activated its max amount of times
	if((GetMyTemplate().bRepeatable) && (GetMyTemplate().MaxSuccesses > 0) && (TimesSucceeded >= GetMyTemplate().MaxSuccesses))
	{
		return false;
	}

	// Check template specific function
	if(GetMyTemplate().CanActivateFn != none)
	{
		return GetMyTemplate().CanActivateFn(self);
	}

	return true;
}

//---------------------------------------------------------------------------------------
function bool CanComplete()
{
	if(GetMyTemplate().CanCompleteFn != none)
	{
		return GetMyTemplate().CanCompleteFn(self);
	}

	return true;
}

// #######################################################################################
// -------------------- TIMER HELPERS ----------------------------------------------------
// #######################################################################################

//---------------------------------------------------------------------------------------
function StartActivationTimer(optional MinMaxDays ActivationTime)
{
	local int HoursToAdd, MinDays, MaxDays;

	StartDateTime = `STRATEGYRULES.GameTime;
	EndDateTime = StartDateTime;

	if(ActivationTime.MaxDays > 0)
	{
		MinDays = ActivationTime.MinDays;
		MaxDays = ActivationTime.MaxDays;
	}
	else
	{
		MinDays = GetMyTemplate().MinActivationDays;
		MaxDays = GetMyTemplate().MaxActivationDays;
	}

	HoursToAdd = (MinDays * 24) + `SYNC_RAND_STATIC((MaxDays * 24) - (MinDays * 24) + 1);

	class'X2StrategyGameRulesetDataStructures'.static.AddHours(EndDateTime, HoursToAdd);
	TimeRemaining = class'X2StrategyGameRulesetDataStructures'.static.DifferenceInSeconds(EndDateTime, StartDateTime);
}

//---------------------------------------------------------------------------------------
// Helper for Hack Rewards to modify duration
function ExtendActivationTimer(int ExtraHours)
{
	class'X2StrategyGameRulesetDataStructures'.static.AddHours(EndDateTime, ExtraHours);
	TimeRemaining = class'X2StrategyGameRulesetDataStructures'.static.DifferenceInSeconds(EndDateTime, StartDateTime);
}

//---------------------------------------------------------------------------------------
// Helper for Expired GOps to modify duration
function DecreaseActivationTimer(int ExtraHours)
{
	class'X2StrategyGameRulesetDataStructures'.static.RemoveHours(EndDateTime, ExtraHours);
	TimeRemaining = class'X2StrategyGameRulesetDataStructures'.static.DifferenceInSeconds(EndDateTime, StartDateTime);
}

//---------------------------------------------------------------------------------------
function StartDurationTimer(optional int DurationHours = 0)
{
	local int HoursToAdd;

	StartDateTime = `STRATEGYRULES.GameTime;
	EndDateTime = StartDateTime;

	if (DurationHours > 0)
	{
		HoursToAdd = DurationHours;
	}
	else
	{
		HoursToAdd = (GetMyTemplate().MinDurationDays * 24) + `SYNC_RAND_STATIC((GetMyTemplate().MaxDurationDays * 24) - (GetMyTemplate().MinDurationDays * 24) + 1);
	}

	class'X2StrategyGameRulesetDataStructures'.static.AddHours(EndDateTime, HoursToAdd);
	TimeRemaining = class'X2StrategyGameRulesetDataStructures'.static.DifferenceInSeconds(EndDateTime, StartDateTime);
}

//---------------------------------------------------------------------------------------
function PauseTimer()
{
	// Update Time remaining and set end time to unreachable future
	TimeRemaining = class'X2StrategyGameRulesetDataStructures'.static.DifferenceInSeconds(EndDateTime, `STRATEGYRULES.GameTime);
	EndDateTime.m_iYear = 9999;
}

//---------------------------------------------------------------------------------------
function ResumeTimer()
{
	// Update the start time then calculate the end time using the time remaining
	StartDateTime = `STRATEGYRULES.GameTime;
	EndDateTime = StartDateTime;

	class'X2StrategyGameRulesetDataStructures'.static.AddTime(EndDateTime, TimeRemaining);
}

// #######################################################################################
// -------------------- REVEAL COST ------------------------------------------------------
// #######################################################################################

//---------------------------------------------------------------------------------------
function SetRevealCost()
{
	local XComGameStateHistory History;
	local XComGameState_HeadquartersResistance ResistanceHQ;
	local ArtifactCost IntelCost;

	History = `XCOMHISTORY;
	ResistanceHQ = XComGameState_HeadquartersResistance(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersResistance'));

	RevealCost.ResourceCosts.Length = 0;
	IntelCost.ItemTemplateName = 'Intel';
	IntelCost.Quantity = `ScaleStrategyArrayInt(default.StartingIntelCost) + (ResistanceHQ.NumMonths * `ScaleStrategyArrayInt(default.IntelCostIncrease));
	RevealCost.ResourceCosts.AddItem(IntelCost);
}

//---------------------------------------------------------------------------------------
function RevealEvent(XComGameState NewGameState)
{
	local XComGameStateHistory History;
	local XComGameState_HeadquartersXCom XComHQ;
	local array<StrategyCostScalar> CostScalars;

	History = `XCOMHISTORY;
	XComHQ = XComGameState_HeadquartersXCom(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersXCom'));
	XComHQ = XComGameState_HeadquartersXCom(NewGameState.ModifyStateObject(class'XComGameState_HeadquartersXCom', XComHQ.ObjectID));

	CostScalars.Length = 0;
	XComHQ.PayStrategyCost(NewGameState, RevealCost, CostScalars);

	bSecretEvent = false;
	RevealCost.ResourceCosts.Length = 0;
	RevealCost.ArtifactCosts.Length = 0;
}

// #######################################################################################
// -------------------- REVEAL OBJECTIVE UI ----------------------------------------------
// #######################################################################################

function RevealObjectiveUI(XComGameState NewGameState)
{
	local ObjectiveDisplayInfo ObjDisplayInfo;
	local XComGameStateHistory History;
	local XComGameState_ObjectivesList ObjListState;

	if( bSecretEvent )
	{
		return;
	}

	if( !GetMyTemplate().bNeverShowObjective )
	{
		History = `XCOMHISTORY;

			foreach NewGameState.IterateByClassType(class'XComGameState_ObjectivesList', ObjListState)
		{
				break;
			}

		if( ObjListState == None )
		{
			foreach History.IterateByClassType(class'XComGameState_ObjectivesList', ObjListState)
			{
				break;
			}

			if( ObjListState != none )
			{
				ObjListState = XComGameState_ObjectivesList(NewGameState.ModifyStateObject(class'XComGameState_ObjectivesList', ObjListState.ObjectID));
			}
			else
			{
				ObjListState = XComGameState_ObjectivesList(NewGameState.CreateNewStateObject(class'XComGameState_ObjectivesList'));
			}
		}

		ObjDisplayInfo.ShowHeader = false;
		ObjDisplayInfo.ShowCheckBox = false;
		ObjDisplayInfo.bIsDarkEvent = true;
		ObjDisplayInfo.MissionType = "DARKEVENTOBJECTIVE";

		ObjDisplayInfo.GroupID = ObjectID;
		ObjDisplayInfo.DisplayLabel = GetDisplayName();
		ObjDisplayInfo.HideInTactical = true;
		ObjDisplayInfo.GPObjective = true;
		ObjDisplayInfo.ObjectiveTemplateName = GetMyTemplateName();
		ObjListState.SetObjectiveDisplay(ObjDisplayInfo);

		class'X2StrategyGameRulesetDataStructures'.static.UpdateObjectivesUI(NewGameState);
	}
}

function DeactivateObjectiveUI(XComGameState NewGameState)
{
	local XComGameStateHistory History;
	local XComGameState_ObjectivesList ObjListState;

	History = `XCOMHISTORY;

	foreach NewGameState.IterateByClassType(class'XComGameState_ObjectivesList', ObjListState)
	{
		break;
	}

	if( ObjListState == None )
	{
		foreach History.IterateByClassType(class'XComGameState_ObjectivesList', ObjListState)
		{
			break;
		}

		if( ObjListState != none )
		{
			ObjListState = XComGameState_ObjectivesList(NewGameState.ModifyStateObject(class'XComGameState_ObjectivesList', ObjListState.ObjectID));
		}
		else
		{
			ObjListState = XComGameState_ObjectivesList(NewGameState.CreateNewStateObject(class'XComGameState_ObjectivesList'));
		}
	}

	ObjListState.HideObjectiveDisplay("DARKEVENTOBJECTIVE", GetDisplayName());
	class'X2StrategyGameRulesetDataStructures'.static.UpdateObjectivesUI(NewGameState);
}

DefaultProperties
{
}


Issue #425 - PreventGeoscapeTick event

Issue #425 - PreventGeoscapeTick event

class XGGeoscape extends Actor
	dependson(XGMissionControlUI)
	dependson(XComEarth);

// SAVE DATA
var float                     m_fTimeScale;           // The speed at which the game is moving
var float                     m_fGameTimer;           // Timer for Game ticks
var bool                      m_bGlobeHidden;

var TDateTime                 m_kDateTime;
var bool                      m_bInPauseMenu;
var bool                      m_bInCombat;
var float                     m_fCombatCooldown;
var array<string>             m_arrMissionList;
var XGBase                    m_kBase;

const MIN_FLIGHT_SECONDS = 3.0f;
const PAUSED = 0;
const ONE_MINUTE = 60;
const TEN_MINUTES = 600;
const FIFTEEN_MINUTES = 900;
const THIRTY_MINUTES = 1800;
const ONE_HOUR = 3600;
const TWELVE_HOURS = 43200;
const TWENTY_FOUR_HOURS = 86400;
const MAXIMUM_TIMESLICE = 60;
const SCAN_TIMESLICE = 1800;

function Init()
{
	m_kDateTime = `STRATEGYRULES.GameTime;
	m_kBase = Spawn( class'XGBase' );
	m_kBase.Init();
}

//------------------------------------------------
function InitLoadGame()
{
	m_fTimeScale = 0;   // Always start paused
}

//------------------------------------------------
//-------------------------------------------------------------------------------
function vector2d GetShortestDist( vector2d v2Start, vector2d v2End )
{
	return vect2d( ShortestWrappedDistance( v2Start.X, v2End.X ), v2End.Y - v2Start.Y );
}
//-------------------------------------------------------------------------------
function float ShortestWrappedDistance( float fStart, float fEnd )
{
	local float fA, fB, fabsA, fabsB;

	fA = fEnd - fStart;

	if( fStart < fEnd )
		fB = (fEnd-1)-fStart;
	else
		fB = (fEnd+1)-fStart;

	fabsA = Abs(fA);
	fabsB = Abs(fB);
	if (fabsA <= fabsB)
		return fA;

	return fB;
}

//#############################################################################################
//----------------   GAME   -------------------------------------------------------------------
//#############################################################################################

//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
function bool CanExit()
{
	return true;
}
//-----------------------------------------------------------------------
function OnExitMissionControl()
{
	Pause();
	`XSTRATEGYSOUNDMGR.PlaySoundEvent("Play_AvengerNoRoom");
	`XSTRATEGYSOUNDMGR.PlayBaseViewMusic();
}

//-----------------------------------------------------------------------
//This method is called immediately after returning from a mission
function OnEnterMissionControl(optional bool bSimCombat = false)
{
	local XComGameStateHistory History;
	local XComGameState_HeadquartersXCom XComHQ;
	local XComGameState_HeadquartersAlien AlienHQ;
	local XComGameState_Airship Dropship;
	local XGStrategy kStrategy;
	local XComHQPresentationLayer HQPres;
	local XComStrategySoundManager SoundManager;
	local XComGameState NewGameState;

	NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Pre Mission End UI Sequence Hook");
	`XEVENTMGR.TriggerEvent('PreMissionDone', , , NewGameState);
	`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);

	kStrategy = `Game;
	History = `XCOMHISTORY;
	HQPres = `HQPRES;
	SoundManager = `XSTRATEGYSOUNDMGR;
	XComHQ = XComGameState_HeadquartersXCom(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersXCom'));
	AlienHQ = XComGameState_HeadquartersAlien(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersAlien'));

	SoundManager.StopHQMusicEvent();

	// Clear out any playing or queued narrative - requested by Jake
	HQPres.m_kNarrativeUIMgr.ClearConversationQueueOfNonTentpoles();

	ShowRealEarth();

	SetTimer(0.25f, false, nameof(ClearCameraFadeAndLoadingScreen));
	StartHQMusic();

	if( XComHQ.GetObjectiveStatus('T0_M0_TutorialFirstMission') == eObjectiveState_InProgress )
	{
		//HQPres.m_kFacilityGrid.Hide();
		//class'XComGameStateContext_StrategyGameRule'.static.RemoveInvalidSoldiersFromSquad();
		//class'XComGameStateContext_StrategyGameRule'.static.AddLootToInventory();
		HQPres.ExitPostMissionSequence();
	}
	//If we loaded from a save, go straight to the map
	else if(kStrategy.m_bLoadedFromSave)
	{
		kStrategy.PostLoadSaveGame();
		//HQPres.UIEnterStrategyMap();
	}
	else if(XComHQ.bXComFullGameVictory)
	{
		HQPres.UIEnterStrategyMap();
		SoundManager.PlaySoundEvent("Geoscape_SkyrangerStop");
		NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Victory Hook");
		`XEVENTMGR.TriggerEvent('XComVictory', , , NewGameState);
		`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);

		// Movie will have already played so jump to player stats screen
		HQPres.UIYouWin();
	}
	else if(AlienHQ.bAlienFullGameVictory)
	{
		HQPres.UIEnterStrategyMap();
		SoundManager.PlaySoundEvent("Geoscape_SkyrangerStop");
		// Movie has not played yet, play it then it triggers stats on complete
		class'X2StrategyElement_DefaultAlienAI'.static.PlayerLossAction();
	}
	else if(!XComHQ.bReturningFromMission)
	{
		HQPres.UIEnterStrategyMap();
	}
	else
	{
		//Find the dropship
		foreach History.IterateByClassType(class'XComGameState_Airship', Dropship)
		{
			if(Dropship.IsCurrentlyInFlight())
			{
				break;
			}
		}

		//Make sure we are paused, otherwise map events will fire during the dropship sequence
		if(m_fTimeScale != PAUSED)
		{
			m_fTimeScale = PAUSED;
		}

		//Instantly complete the dropship's flight back
		if (Dropship != none)
			Dropship.ProcessFlightComplete();

		// only proceed with the normal after action mission flow if there are no narrative conversations preempting it
		//if( !HQPres.m_kNarrativeUIMgr.AnyActiveConversations() )
		//{
			HQPres.UIAfterAction(bSimCombat);
		//}
	}

	SoundManager.PlaySoundEvent("Stop_AvengerAmbience");
}

function ClearCameraFadeAndLoadingScreen()
{
	`HQPRES.HideLoadingScreen();
	WorldInfo.MyLocalEnvMapManager.SetEnableCaptures(true);
	class'WorldInfo'.static.GetWorldInfo().GetALocalPlayerController().ClientSetCameraFade(false, , , 1.0);
}

function StartHQMusic()
{
	`XSTRATEGYSOUNDMGR.PlayHQMusicEvent();
}

event Tick( float fDeltaT )
{
	local int i, iSlices;
	local float fGameTime, fRemainderTime, fUseMaximumTimeslice;

	if( !`HQPRES.ScreenStack.IsInStack(class'UIPauseMenu') )
		`GAME.m_fGameDuration += fDeltaT;

	fGameTime = fDeltaT * m_fTimeScale;

	// Never fully process a tick while the tactical start state is the head of the history -
	// this could result in strategy states being layered on top of the start state, which has other downstream effects
	// (such as InitBattle() attempting to execute the LoadTacticalGame path instead of the CreateTacticalGame path).
	if( fGameTime > 0 && `XCOMHISTORY.GetStartState() != None )
	{
		fGameTime = 0;
	}

	// Start issue #425
	if (fGameTime > 0 && ShouldPreventTick())
	{
		fGameTime = 0;
	}
	// End issue #425

	// IF( PAUSED )
	if (fGameTime == 0)
	{
		UpdateUIVisualsOnly();
		return;
	}

	if( fGameTime >= MAXIMUM_TIMESLICE )
	{
		if( fGameTime <= FIFTEEN_MINUTES ) //FIFTEEN_MINUTE timescale is used while aircraft are flying
		{
			fUseMaximumTimeslice = MAXIMUM_TIMESLICE;
		}
		else
		{
			fUseMaximumTimeslice = SCAN_TIMESLICE; //Maximum time slice for advancing time to help perf on the consoles
		}

		fRemainderTime = fGameTime > fUseMaximumTimeslice ? (fGameTime % fUseMaximumTimeslice) : 0.0f;
		iSlices = max( fGameTime/fUseMaximumTimeslice, 1 );

		for( i = 0; i < iSlices; i++ )
		{
			GameTick( fUseMaximumTimeslice );
		}

		if( fRemainderTime > 0 )
			GameTick( fRemainderTime );
	}
	else
	{
		GameTick( fGameTime );
	}

	UpdateUI( fDeltaT );
}

// Start issue #425
protected function bool ShouldPreventTick()
{
	local XComLWTuple Tuple;

	Tuple = new class'XComLWTuple';
 	Tuple.Id = 'PreventGeoscapeTick';
 	Tuple.Data.Add(1);
 	Tuple.Data[0].kind = XComLWTVBool;
	Tuple.Data[0].b = false;

	`XEVENTMGR.TriggerEvent('PreventGeoscapeTick', self, self);

	return Tuple.Data[0].b;
}
// End issue #425

function GameTick( float fGameTime )
{
	local XComHeadquartersCheatManager CheatMgr;

	if (class'XComGameState_HeadquartersXCom'.static.GetObjectiveStatus('T5_M3_CompleteFinalMission') != eObjectiveState_InProgress)
	{
		m_fGameTimer -= fGameTime;
		if (m_fGameTimer <= 0)
		{
			XGMissionControlUI(`HQPRES.GetMgr(class'XGMissionControlUI')).UpdateView();
			m_fGameTimer += ONE_HOUR;
		}

		class'X2StrategyGameRulesetDataStructures'.static.AddTime(m_kDateTime, fGameTime);
		`STRATEGYRULES.GameTime = m_kDateTime;
		`EARTH.SetTime(m_kDateTime);
		UpdateAlienAI();
		UpdateResistance();
		UpdateDLCs();
		//UpdateHiddenMapElements(); Nothing is actually hidden and this is a terrible function vis-a-vis framerate
		UpdateMissionCalendar();

		CheatMgr = XComHeadquartersCheatManager(class'WorldInfo'.static.GetWorldInfo().GetALocalPlayerController().CheatManager);

		if (CheatMgr != none && CheatMgr.bGamesComDemo)
		{
			if (class'X2StrategyGameRulesetDataStructures'.static.LessThan(CheatMgr.DarkEventPopupTime, `STRATEGYRULES.GameTime))
			{
				CheatMgr.DarkEventsPopup();
			}
		}
	}
}

function UpdateMissionCalendar()
{
	local XComGameState NewGameState;
	local XComGameState_MissionCalendar CalendarState;
	local XComGameStateHistory History;
	local X2StrategyElementTemplateManager StratMgr;
	local X2MissionSourceTemplate MissionSource;
	local UIStrategyMap StrategyMap;

	History = `XCOMHISTORY;
	NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Update Mission Calendar");
	CalendarState = XComGameState_MissionCalendar(History.GetSingleGameStateObjectForClass(class'XComGameState_MissionCalendar'));
	CalendarState = XComGameState_MissionCalendar(NewGameState.ModifyStateObject(class'XComGameState_MissionCalendar', CalendarState.ObjectID));

	if(!CalendarState.Update(NewGameState))
	{
		NewGameState.PurgeGameStateForObjectID(CalendarState.ObjectID);
	}

	if(NewGameState.GetNumGameStateObjects() > 0)
	{
		`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);
	}
	else
	{
		History.CleanupPendingGameState(NewGameState);
	}

	History = `XCOMHISTORY;
	CalendarState = XComGameState_MissionCalendar(History.GetSingleGameStateObjectForClass(class'XComGameState_MissionCalendar'));

	StrategyMap = `HQPRES.StrategyMap2D;
	if (CalendarState.MissionPopupSources.Length > 0 && StrategyMap != none && StrategyMap.m_eUIState != eSMS_Flight && !`HQPRES.ScreenStack.IsCurrentClass(class'UIAlert'))
	{
		StratMgr = class'X2StrategyElementTemplateManager'.static.GetStrategyElementTemplateManager();
		MissionSource = X2MissionSourceTemplate(StratMgr.FindStrategyElementTemplate(CalendarState.MissionPopupSources[0]));

		NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Mission Calendar: Remove Popup Signal");
		CalendarState = XComGameState_MissionCalendar(NewGameState.ModifyStateObject(class'XComGameState_MissionCalendar', CalendarState.ObjectID));
		CalendarState.MissionPopupSources.Remove(0, 1);
		`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);

		if(MissionSource != none && MissionSource.MissionPopupFn != none)
		{
			Pause();
			MissionSource.MissionPopupFn();
		}
	}
}

function UpdateHiddenMapElements()
{
	local XComGameState NewGameState;
	local XComGameStateHistory History;
	local XComGameState_BaseObject TestObject;
	local HiddenOnMap HiddenObj;

	History = `XCOMHISTORY;

	foreach History.IterateByClassType(class'XComGameState_BaseObject', TestObject)
	{
		HiddenObj = HiddenOnMap(TestObject);

		if(HiddenObj != none)
		{
			if(HiddenObj.IsHidden() && HiddenObj.AvengerInRegion() && HiddenObj.UnhideTimerComplete())
			{
				NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Unhide Map Element");
				HiddenObj.Unhide(NewGameState);
				break;
			}
		}
	}

	if(NewGameState != none)
	{
		if(NewGameState.GetNumGameStateObjects() > 0)
		{
			`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);
			HiddenObj.UnhiddenNotification();
		}
		else
		{
			History.CleanupPendingGameState(NewGameState);
		}
	}
}

function UpdateAlienAI()
{
	local XComGameStateHistory History;
	local XComGameState_HeadquartersAlien AlienHQ;

	History = `XCOMHISTORY;
	AlienHQ = XComGameState_HeadquartersAlien(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersAlien'));
	AlienHQ.Update();
}

function UpdateResistance()
{
	local XComGameState NewGameState;
	local XComGameState_HeadquartersResistance ResistanceHQ;
	local XComGameState_HeadquartersAlien AlienHQ;
	local XComGameStateHistory History;
	local XComGameState_MissionSite MissionState;
	local StateObjectReference EmptyRef;

	History = `XCOMHISTORY;
	NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Update ResistanceHQ");
	ResistanceHQ = XComGameState_HeadquartersResistance(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersResistance'));
	ResistanceHQ = XComGameState_HeadquartersResistance(NewGameState.ModifyStateObject(class'XComGameState_HeadquartersResistance', ResistanceHQ.ObjectID));

	if(!ResistanceHQ.Update(NewGameState))
	{
		NewGameState.PurgeGameStateForObjectID(ResistanceHQ.ObjectID);
	}

	if(NewGameState.GetNumGameStateObjects() > 0)
	{
		`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);

		if(ResistanceHQ.bEndOfMonthNotify)
		{
			ResistanceHQ.EndOfMonthPopup();
		}
	}
	else
	{
		History.CleanupPendingGameState(NewGameState);
	}

	History = `XCOMHISTORY;
	ResistanceHQ = XComGameState_HeadquartersResistance(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersResistance'));

	if(ResistanceHQ.ExpiredMission != EmptyRef)
	{
		MissionState = XComGameState_MissionSite(History.GetGameStateForObjectID(ResistanceHQ.ExpiredMission.ObjectID));
		NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Clear Expiring Mission");
		ResistanceHQ = XComGameState_HeadquartersResistance(NewGameState.ModifyStateObject(class'XComGameState_HeadquartersResistance', ResistanceHQ.ObjectID));
		ResistanceHQ.ExpiredMission = EmptyRef;
		AlienHQ = XComGameState_HeadquartersAlien(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersAlien'));
		AlienHQ = XComGameState_HeadquartersAlien(NewGameState.ModifyStateObject(class'XComGameState_HeadquartersAlien', AlienHQ.ObjectID));
		AlienHQ.StartAcceleratingDoom();
		`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);
		`HQPRES.UIMissionExpired(MissionState);
	}
}

function UpdateDLCs()
{
	local XComOnlineEventMgr EventManager;
	local array<X2DownloadableContentInfo> DLCInfos;
	local int i;

	// Update each DLC
	EventManager = `ONLINEEVENTMGR;
	DLCInfos = EventManager.GetDLCInfos(false);
	for (i = 0; i < DLCInfos.Length; ++i)
	{
		DLCInfos[i].UpdateDLC();
	}
}

//---------------------------------------------------------------
function bool IsBusy()
{
	return false;
}
//---------------------------------------------------------------
function bool IsPaused()
{
	return m_fTimeScale == PAUSED;
}
//---------------------------------------------------------------
function Pause()
{
	local XComGameState NewGameState;
	local XComGameState StartState;
	local XComGameState_GameTime TimeState;
	local XComGameState_HeadquartersXCom XComHQ;

	if (IsScanning())
	{
		XComHQ = class'UIUtilities_Strategy'.static.GetXComHQ();
		XComHQ.ToggleSiteScanning(false);

		`XCOMGRI.DoRemoteEvent('FastForwardOff');
	}

	m_fTimeScale = PAUSED;

	//  @TODO - this is probably not the best place to have this, but for now it will do
	//  Update the game time in the history so that we can't go backward in time by saving/loading the game.
	StartState = `XCOMHISTORY.GetStartState();
	if(StartState == none) //If there is a start state, it means we are launching tactical and the history is locked
	{
		TimeState = XComGameState_GameTime(`XCOMHISTORY.GetSingleGameStateObjectForClass(class'XComGameState_GameTime'));
		NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Geoscape Pause");
		TimeState = XComGameState_GameTime(NewGameState.ModifyStateObject(TimeState.Class, TimeState.ObjectID));
		TimeState.CurrentTime = m_kDateTime;
		`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);
	}
}
//---------------------------------------------------------------
function Resume()
{
	// IF( The game is fast forwarding )
	if(m_fTimeScale == TWELVE_HOURS)
		return;

	m_fTimeScale = ONE_MINUTE;
}
//---------------------------------------------------------------
function bool DecreaseTimeScale()
{
	if(m_fTimeScale == TWELVE_HOURS)
		m_fTimeScale = THIRTY_MINUTES;
	else if (m_fTimeScale == THIRTY_MINUTES)
		m_fTimeScale = ONE_MINUTE;
	else if (m_fTimeScale == ONE_MINUTE)
		return false;//m_fTimeScale = PAUSED;

	return true;
}
//---------------------------------------------------------------
function bool IncreaseTimeScale()
{
	if (m_fTimeScale == ONE_MINUTE)
		m_fTimeScale = THIRTY_MINUTES;
	else if (m_fTimeScale == THIRTY_MINUTES)
		m_fTimeScale = TWELVE_HOURS;
	else if(m_fTimeScale == TWELVE_HOURS)
		return false;

	return true;
}

//---------------------------------------------------------------
function bool IsScanning()
{
	return m_fTimeScale == TWELVE_HOURS;
}
//---------------------------------------------------------------
function bool CanScan()
{
	return m_fTimeScale <= ONE_MINUTE;
}
//---------------------------------------------------------------
function FastForward()
{
	m_fTimeScale = TWELVE_HOURS;
	`XCOMGRI.DoRemoteEvent('FastForwardOn');
}
function RestoreNormalTimeFrame()
{
	`XCOMGRI.DoRemoteEvent('FastForwardOff');
	m_fTimeScale = ONE_MINUTE;
}
//-----------------------------------------------------
function vector2D WrapCoords( Vector2D v2Coords )
{
	local Vector2D v2Wrapped;

	if( v2Coords.X > 1 )
		v2Wrapped.X = v2Coords.X - 1;
	else if( v2Coords.X < 0 )
		v2Wrapped.X = v2Coords.X + 1;
	else
		v2Wrapped.X = v2Coords.X;

	if( v2Coords.Y > 1 )
		v2Wrapped.Y = v2Coords.Y - 1;
	else if( v2Coords.Y < 0 )
		v2Wrapped.Y = v2Coords.Y + 1;
	else
		v2Wrapped.Y = v2Coords.Y;

	return v2Wrapped;
}

//-----------------------------------------------------
function ShowRealEarth()
{
	//SOUND().PlaySFX(SNDLIB().SFX_UI_HologlobeDeactivation);
	TriggerGlobalEventClass( class'SeqEvent_MissionControl', self, 4 );
	TriggerGlobalEventClass( class'SeqEvent_MissionControl', self, 3 );
}

//-----------------------------------------------------
function UpdateUI( float fDeltaT )
{
	local XComStrategyMap XComMap;
	local XComGameStateHistory History;
	local XComGameState_HeadquartersXCom XComHQ;
	local XComGameState_Skyranger Skyranger;
	local Vector2D MoveDelta, CurLoc;

	XComMap = `HQPRES.m_kXComStrategyMap;

	if(XComMap != none)
	{
		XComMap.UpdateStrategyMap();
		XComMap.UpdateMovers(fDeltaT);
		XComMap.UpdateVisuals(); //update visuals last to reflect the other changes
	}

	//Only lock to the ship while it flies
	History = `XCOMHISTORY;
	XComHQ = XComGameState_HeadquartersXCom(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersXCom'));
	Skyranger = XComGameState_Skyranger(History.GetGameStateForObjectID(XComHQ.SkyrangerRef.ObjectID));

	if(XComHQ.IsCurrentlyInFlight())
	{
		CurLoc = `EARTH.GetViewLocation();
		MoveDelta = XComHQ.Get2DLocation();
		MoveDelta.X -= CurLoc.X;
		MoveDelta.Y -= CurLoc.Y;

		`EARTH.MoveViewLocation(MoveDelta);
	}
	else if (Skyranger.IsCurrentlyInFlight())
	{
		CurLoc = `EARTH.GetViewLocation();
		MoveDelta = Skyranger.Get2DLocation();
		MoveDelta.X -= CurLoc.X;
		MoveDelta.Y -= CurLoc.Y;

		`EARTH.MoveViewLocation(MoveDelta);
	}

}

function UpdateUIVisualsOnly()
{
	local XComStrategyMap XComMap;

	XComMap = `HQPRES.m_kXComStrategyMap;

	if (XComMap != none)
	{
		XComMap.UpdateVisuals(); //update visuals last to reflect the other changes
	}
}

defaultproperties
{
	m_fTimeScale=PAUSED
}

class XGGeoscape extends Actor
	dependson(XGMissionControlUI)
	dependson(XComEarth);

// SAVE DATA
var float                     m_fTimeScale;           // The speed at which the game is moving
var float                     m_fGameTimer;           // Timer for Game ticks
var bool                      m_bGlobeHidden;

var TDateTime                 m_kDateTime;
var bool                      m_bInPauseMenu;
var bool                      m_bInCombat;
var float                     m_fCombatCooldown;
var array<string>             m_arrMissionList;
var XGBase                    m_kBase;

const MIN_FLIGHT_SECONDS = 3.0f;
const PAUSED = 0;
const ONE_MINUTE = 60;
const TEN_MINUTES = 600;
const FIFTEEN_MINUTES = 900;
const THIRTY_MINUTES = 1800;
const ONE_HOUR = 3600;
const TWELVE_HOURS = 43200;
const TWENTY_FOUR_HOURS = 86400;
const MAXIMUM_TIMESLICE = 60;
const SCAN_TIMESLICE = 1800;

function Init()
{
	m_kDateTime = `STRATEGYRULES.GameTime;
	m_kBase = Spawn( class'XGBase' );
	m_kBase.Init();
}

//------------------------------------------------
function InitLoadGame()
{
	m_fTimeScale = 0;   // Always start paused
}

//------------------------------------------------
//-------------------------------------------------------------------------------
function vector2d GetShortestDist( vector2d v2Start, vector2d v2End )
{
	return vect2d( ShortestWrappedDistance( v2Start.X, v2End.X ), v2End.Y - v2Start.Y );
}
//-------------------------------------------------------------------------------
function float ShortestWrappedDistance( float fStart, float fEnd )
{
	local float fA, fB, fabsA, fabsB;

	fA = fEnd - fStart;

	if( fStart < fEnd )
		fB = (fEnd-1)-fStart;
	else
		fB = (fEnd+1)-fStart;

	fabsA = Abs(fA);
	fabsB = Abs(fB);
	if (fabsA <= fabsB)
		return fA;

	return fB;
}

//#############################################################################################
//----------------   GAME   -------------------------------------------------------------------
//#############################################################################################

//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
function bool CanExit()
{
	return true;
}
//-----------------------------------------------------------------------
function OnExitMissionControl()
{
	Pause();
	`XSTRATEGYSOUNDMGR.PlaySoundEvent("Play_AvengerNoRoom");
	`XSTRATEGYSOUNDMGR.PlayBaseViewMusic();
}

//-----------------------------------------------------------------------
//This method is called immediately after returning from a mission
function OnEnterMissionControl(optional bool bSimCombat = false)
{
	local XComGameStateHistory History;
	local XComGameState_HeadquartersXCom XComHQ;
	local XComGameState_HeadquartersAlien AlienHQ;
	local XComGameState_Airship Dropship;
	local XGStrategy kStrategy;
	local XComHQPresentationLayer HQPres;
	local XComStrategySoundManager SoundManager;
	local XComGameState NewGameState;

	NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Pre Mission End UI Sequence Hook");
	`XEVENTMGR.TriggerEvent('PreMissionDone', , , NewGameState);
	`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);

	kStrategy = `Game;
	History = `XCOMHISTORY;
	HQPres = `HQPRES;
	SoundManager = `XSTRATEGYSOUNDMGR;
	XComHQ = XComGameState_HeadquartersXCom(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersXCom'));
	AlienHQ = XComGameState_HeadquartersAlien(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersAlien'));

	SoundManager.StopHQMusicEvent();

	// Clear out any playing or queued narrative - requested by Jake
	HQPres.m_kNarrativeUIMgr.ClearConversationQueueOfNonTentpoles();

	ShowRealEarth();

	SetTimer(0.25f, false, nameof(ClearCameraFadeAndLoadingScreen));
	StartHQMusic();

	if( XComHQ.GetObjectiveStatus('T0_M0_TutorialFirstMission') == eObjectiveState_InProgress )
	{
		//HQPres.m_kFacilityGrid.Hide();
		//class'XComGameStateContext_StrategyGameRule'.static.RemoveInvalidSoldiersFromSquad();
		//class'XComGameStateContext_StrategyGameRule'.static.AddLootToInventory();
		HQPres.ExitPostMissionSequence();
	}
	//If we loaded from a save, go straight to the map
	else if(kStrategy.m_bLoadedFromSave)
	{
		kStrategy.PostLoadSaveGame();
		//HQPres.UIEnterStrategyMap();
	}
	else if(XComHQ.bXComFullGameVictory)
	{
		HQPres.UIEnterStrategyMap();
		SoundManager.PlaySoundEvent("Geoscape_SkyrangerStop");
		NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Victory Hook");
		`XEVENTMGR.TriggerEvent('XComVictory', , , NewGameState);
		`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);

		// Movie will have already played so jump to player stats screen
		HQPres.UIYouWin();
	}
	else if(AlienHQ.bAlienFullGameVictory)
	{
		HQPres.UIEnterStrategyMap();
		SoundManager.PlaySoundEvent("Geoscape_SkyrangerStop");
		// Movie has not played yet, play it then it triggers stats on complete
		class'X2StrategyElement_DefaultAlienAI'.static.PlayerLossAction();
	}
	else if(!XComHQ.bReturningFromMission)
	{
		HQPres.UIEnterStrategyMap();
	}
	else
	{
		//Find the dropship
		foreach History.IterateByClassType(class'XComGameState_Airship', Dropship)
		{
			if(Dropship.IsCurrentlyInFlight())
			{
				break;
			}
		}

		//Make sure we are paused, otherwise map events will fire during the dropship sequence
		if(m_fTimeScale != PAUSED)
		{
			m_fTimeScale = PAUSED;
		}

		//Instantly complete the dropship's flight back
		if (Dropship != none)
			Dropship.ProcessFlightComplete();

		// only proceed with the normal after action mission flow if there are no narrative conversations preempting it
		//if( !HQPres.m_kNarrativeUIMgr.AnyActiveConversations() )
		//{
			HQPres.UIAfterAction(bSimCombat);
		//}
	}

	SoundManager.PlaySoundEvent("Stop_AvengerAmbience");
}

function ClearCameraFadeAndLoadingScreen()
{
	`HQPRES.HideLoadingScreen();
	WorldInfo.MyLocalEnvMapManager.SetEnableCaptures(true);
	class'WorldInfo'.static.GetWorldInfo().GetALocalPlayerController().ClientSetCameraFade(false, , , 1.0);
}

function StartHQMusic()
{
	`XSTRATEGYSOUNDMGR.PlayHQMusicEvent();
}

event Tick( float fDeltaT )
{
	local int i, iSlices;
	local float fGameTime, fRemainderTime, fUseMaximumTimeslice;

	if( !`HQPRES.ScreenStack.IsInStack(class'UIPauseMenu') )
		`GAME.m_fGameDuration += fDeltaT;

	fGameTime = fDeltaT * m_fTimeScale;

	// Never fully process a tick while the tactical start state is the head of the history -
	// this could result in strategy states being layered on top of the start state, which has other downstream effects
	// (such as InitBattle() attempting to execute the LoadTacticalGame path instead of the CreateTacticalGame path).
	if( fGameTime > 0 && `XCOMHISTORY.GetStartState() != None )
	{
		fGameTime = 0;
	}

	// IF( PAUSED )
	if (fGameTime == 0)
	{
		UpdateUIVisualsOnly();
		return;
	}

	if( fGameTime >= MAXIMUM_TIMESLICE )
	{
		if( fGameTime <= FIFTEEN_MINUTES ) //FIFTEEN_MINUTE timescale is used while aircraft are flying
		{
			fUseMaximumTimeslice = MAXIMUM_TIMESLICE;
		}
		else
		{
			fUseMaximumTimeslice = SCAN_TIMESLICE; //Maximum time slice for advancing time to help perf on the consoles
		}

		fRemainderTime = fGameTime > fUseMaximumTimeslice ? (fGameTime % fUseMaximumTimeslice) : 0.0f;
		iSlices = max( fGameTime/fUseMaximumTimeslice, 1 );

		for( i = 0; i < iSlices; i++ )
		{
			GameTick( fUseMaximumTimeslice );
		}

		if( fRemainderTime > 0 )
			GameTick( fRemainderTime );
	}
	else
	{
		GameTick( fGameTime );
	}

	UpdateUI( fDeltaT );
}

function GameTick( float fGameTime )
{
	local XComHeadquartersCheatManager CheatMgr;

	if (class'XComGameState_HeadquartersXCom'.static.GetObjectiveStatus('T5_M3_CompleteFinalMission') != eObjectiveState_InProgress)
	{
		m_fGameTimer -= fGameTime;
		if (m_fGameTimer <= 0)
		{
			XGMissionControlUI(`HQPRES.GetMgr(class'XGMissionControlUI')).UpdateView();
			m_fGameTimer += ONE_HOUR;
		}

		class'X2StrategyGameRulesetDataStructures'.static.AddTime(m_kDateTime, fGameTime);
		`STRATEGYRULES.GameTime = m_kDateTime;
		`EARTH.SetTime(m_kDateTime);
		UpdateAlienAI();
		UpdateResistance();
		UpdateDLCs();
		//UpdateHiddenMapElements(); Nothing is actually hidden and this is a terrible function vis-a-vis framerate
		UpdateMissionCalendar();

		CheatMgr = XComHeadquartersCheatManager(class'WorldInfo'.static.GetWorldInfo().GetALocalPlayerController().CheatManager);

		if (CheatMgr != none && CheatMgr.bGamesComDemo)
		{
			if (class'X2StrategyGameRulesetDataStructures'.static.LessThan(CheatMgr.DarkEventPopupTime, `STRATEGYRULES.GameTime))
			{
				CheatMgr.DarkEventsPopup();
			}
		}
	}
}

function UpdateMissionCalendar()
{
	local XComGameState NewGameState;
	local XComGameState_MissionCalendar CalendarState;
	local XComGameStateHistory History;
	local X2StrategyElementTemplateManager StratMgr;
	local X2MissionSourceTemplate MissionSource;
	local UIStrategyMap StrategyMap;

	History = `XCOMHISTORY;
	NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Update Mission Calendar");
	CalendarState = XComGameState_MissionCalendar(History.GetSingleGameStateObjectForClass(class'XComGameState_MissionCalendar'));
	CalendarState = XComGameState_MissionCalendar(NewGameState.ModifyStateObject(class'XComGameState_MissionCalendar', CalendarState.ObjectID));

	if(!CalendarState.Update(NewGameState))
	{
		NewGameState.PurgeGameStateForObjectID(CalendarState.ObjectID);
	}

	if(NewGameState.GetNumGameStateObjects() > 0)
	{
		`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);
	}
	else
	{
		History.CleanupPendingGameState(NewGameState);
	}

	History = `XCOMHISTORY;
	CalendarState = XComGameState_MissionCalendar(History.GetSingleGameStateObjectForClass(class'XComGameState_MissionCalendar'));

	StrategyMap = `HQPRES.StrategyMap2D;
	if (CalendarState.MissionPopupSources.Length > 0 && StrategyMap != none && StrategyMap.m_eUIState != eSMS_Flight && !`HQPRES.ScreenStack.IsCurrentClass(class'UIAlert'))
	{
		StratMgr = class'X2StrategyElementTemplateManager'.static.GetStrategyElementTemplateManager();
		MissionSource = X2MissionSourceTemplate(StratMgr.FindStrategyElementTemplate(CalendarState.MissionPopupSources[0]));

		NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Mission Calendar: Remove Popup Signal");
		CalendarState = XComGameState_MissionCalendar(NewGameState.ModifyStateObject(class'XComGameState_MissionCalendar', CalendarState.ObjectID));
		CalendarState.MissionPopupSources.Remove(0, 1);
		`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);

		if(MissionSource != none && MissionSource.MissionPopupFn != none)
		{
			Pause();
			MissionSource.MissionPopupFn();
		}
	}
}

function UpdateHiddenMapElements()
{
	local XComGameState NewGameState;
	local XComGameStateHistory History;
	local XComGameState_BaseObject TestObject;
	local HiddenOnMap HiddenObj;

	History = `XCOMHISTORY;

	foreach History.IterateByClassType(class'XComGameState_BaseObject', TestObject)
	{
		HiddenObj = HiddenOnMap(TestObject);

		if(HiddenObj != none)
		{
			if(HiddenObj.IsHidden() && HiddenObj.AvengerInRegion() && HiddenObj.UnhideTimerComplete())
			{
				NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Unhide Map Element");
				HiddenObj.Unhide(NewGameState);
				break;
			}
		}
	}

	if(NewGameState != none)
	{
		if(NewGameState.GetNumGameStateObjects() > 0)
		{
			`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);
			HiddenObj.UnhiddenNotification();
		}
		else
		{
			History.CleanupPendingGameState(NewGameState);
		}
	}
}

function UpdateAlienAI()
{
	local XComGameStateHistory History;
	local XComGameState_HeadquartersAlien AlienHQ;

	History = `XCOMHISTORY;
	AlienHQ = XComGameState_HeadquartersAlien(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersAlien'));
	AlienHQ.Update();
}

function UpdateResistance()
{
	local XComGameState NewGameState;
	local XComGameState_HeadquartersResistance ResistanceHQ;
	local XComGameState_HeadquartersAlien AlienHQ;
	local XComGameStateHistory History;
	local XComGameState_MissionSite MissionState;
	local StateObjectReference EmptyRef;

	History = `XCOMHISTORY;
	NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Update ResistanceHQ");
	ResistanceHQ = XComGameState_HeadquartersResistance(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersResistance'));
	ResistanceHQ = XComGameState_HeadquartersResistance(NewGameState.ModifyStateObject(class'XComGameState_HeadquartersResistance', ResistanceHQ.ObjectID));

	if(!ResistanceHQ.Update(NewGameState))
	{
		NewGameState.PurgeGameStateForObjectID(ResistanceHQ.ObjectID);
	}

	if(NewGameState.GetNumGameStateObjects() > 0)
	{
		`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);

		if(ResistanceHQ.bEndOfMonthNotify)
		{
			ResistanceHQ.EndOfMonthPopup();
		}
	}
	else
	{
		History.CleanupPendingGameState(NewGameState);
	}

	History = `XCOMHISTORY;
	ResistanceHQ = XComGameState_HeadquartersResistance(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersResistance'));

	if(ResistanceHQ.ExpiredMission != EmptyRef)
	{
		MissionState = XComGameState_MissionSite(History.GetGameStateForObjectID(ResistanceHQ.ExpiredMission.ObjectID));
		NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Clear Expiring Mission");
		ResistanceHQ = XComGameState_HeadquartersResistance(NewGameState.ModifyStateObject(class'XComGameState_HeadquartersResistance', ResistanceHQ.ObjectID));
		ResistanceHQ.ExpiredMission = EmptyRef;
		AlienHQ = XComGameState_HeadquartersAlien(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersAlien'));
		AlienHQ = XComGameState_HeadquartersAlien(NewGameState.ModifyStateObject(class'XComGameState_HeadquartersAlien', AlienHQ.ObjectID));
		AlienHQ.StartAcceleratingDoom();
		`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);
		`HQPRES.UIMissionExpired(MissionState);
	}
}

function UpdateDLCs()
{
	local XComOnlineEventMgr EventManager;
	local array<X2DownloadableContentInfo> DLCInfos;
	local int i;

	// Update each DLC
	EventManager = `ONLINEEVENTMGR;
	DLCInfos = EventManager.GetDLCInfos(false);
	for (i = 0; i < DLCInfos.Length; ++i)
	{
		DLCInfos[i].UpdateDLC();
	}
}

//---------------------------------------------------------------
function bool IsBusy()
{
	return false;
}
//---------------------------------------------------------------
function bool IsPaused()
{
	return m_fTimeScale == PAUSED;
}
//---------------------------------------------------------------
function Pause()
{
	local XComGameState NewGameState;
	local XComGameState StartState;
	local XComGameState_GameTime TimeState;
	local XComGameState_HeadquartersXCom XComHQ;

	if (IsScanning())
	{
		XComHQ = class'UIUtilities_Strategy'.static.GetXComHQ();
		XComHQ.ToggleSiteScanning(false);

		`XCOMGRI.DoRemoteEvent('FastForwardOff');
	}

	m_fTimeScale = PAUSED;

	//  @TODO - this is probably not the best place to have this, but for now it will do
	//  Update the game time in the history so that we can't go backward in time by saving/loading the game.
	StartState = `XCOMHISTORY.GetStartState();
	if(StartState == none) //If there is a start state, it means we are launching tactical and the history is locked
	{
		TimeState = XComGameState_GameTime(`XCOMHISTORY.GetSingleGameStateObjectForClass(class'XComGameState_GameTime'));
		NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Geoscape Pause");
		TimeState = XComGameState_GameTime(NewGameState.ModifyStateObject(TimeState.Class, TimeState.ObjectID));
		TimeState.CurrentTime = m_kDateTime;
		`XCOMGAME.GameRuleset.SubmitGameState(NewGameState);
	}
}
//---------------------------------------------------------------
function Resume()
{
	// IF( The game is fast forwarding )
	if(m_fTimeScale == TWELVE_HOURS)
		return;

	m_fTimeScale = ONE_MINUTE;
}
//---------------------------------------------------------------
function bool DecreaseTimeScale()
{
	if(m_fTimeScale == TWELVE_HOURS)
		m_fTimeScale = THIRTY_MINUTES;
	else if (m_fTimeScale == THIRTY_MINUTES)
		m_fTimeScale = ONE_MINUTE;
	else if (m_fTimeScale == ONE_MINUTE)
		return false;//m_fTimeScale = PAUSED;

	return true;
}
//---------------------------------------------------------------
function bool IncreaseTimeScale()
{
	if (m_fTimeScale == ONE_MINUTE)
		m_fTimeScale = THIRTY_MINUTES;
	else if (m_fTimeScale == THIRTY_MINUTES)
		m_fTimeScale = TWELVE_HOURS;
	else if(m_fTimeScale == TWELVE_HOURS)
		return false;

	return true;
}

//---------------------------------------------------------------
function bool IsScanning()
{
	return m_fTimeScale == TWELVE_HOURS;
}
//---------------------------------------------------------------
function bool CanScan()
{
	return m_fTimeScale <= ONE_MINUTE;
}
//---------------------------------------------------------------
function FastForward()
{
	m_fTimeScale = TWELVE_HOURS;
	`XCOMGRI.DoRemoteEvent('FastForwardOn');
}
function RestoreNormalTimeFrame()
{
	`XCOMGRI.DoRemoteEvent('FastForwardOff');
	m_fTimeScale = ONE_MINUTE;
}
//-----------------------------------------------------
function vector2D WrapCoords( Vector2D v2Coords )
{
	local Vector2D v2Wrapped;

	if( v2Coords.X > 1 )
		v2Wrapped.X = v2Coords.X - 1;
	else if( v2Coords.X < 0 )
		v2Wrapped.X = v2Coords.X + 1;
	else
		v2Wrapped.X = v2Coords.X;

	if( v2Coords.Y > 1 )
		v2Wrapped.Y = v2Coords.Y - 1;
	else if( v2Coords.Y < 0 )
		v2Wrapped.Y = v2Coords.Y + 1;
	else
		v2Wrapped.Y = v2Coords.Y;

	return v2Wrapped;
}

//-----------------------------------------------------
function ShowRealEarth()
{
	//SOUND().PlaySFX(SNDLIB().SFX_UI_HologlobeDeactivation);
	TriggerGlobalEventClass( class'SeqEvent_MissionControl', self, 4 );
	TriggerGlobalEventClass( class'SeqEvent_MissionControl', self, 3 );
}

//-----------------------------------------------------
function UpdateUI( float fDeltaT )
{
	local XComStrategyMap XComMap;
	local XComGameStateHistory History;
	local XComGameState_HeadquartersXCom XComHQ;
	local XComGameState_Skyranger Skyranger;
	local Vector2D MoveDelta, CurLoc;

	XComMap = `HQPRES.m_kXComStrategyMap;

	if(XComMap != none)
	{
		XComMap.UpdateStrategyMap();
		XComMap.UpdateMovers(fDeltaT);
		XComMap.UpdateVisuals(); //update visuals last to reflect the other changes
	}

	//Only lock to the ship while it flies
	History = `XCOMHISTORY;
	XComHQ = XComGameState_HeadquartersXCom(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersXCom'));
	Skyranger = XComGameState_Skyranger(History.GetGameStateForObjectID(XComHQ.SkyrangerRef.ObjectID));

	if(XComHQ.IsCurrentlyInFlight())
	{
		CurLoc = `EARTH.GetViewLocation();
		MoveDelta = XComHQ.Get2DLocation();
		MoveDelta.X -= CurLoc.X;
		MoveDelta.Y -= CurLoc.Y;

		`EARTH.MoveViewLocation(MoveDelta);
	}
	else if (Skyranger.IsCurrentlyInFlight())
	{
		CurLoc = `EARTH.GetViewLocation();
		MoveDelta = Skyranger.Get2DLocation();
		MoveDelta.X -= CurLoc.X;
		MoveDelta.Y -= CurLoc.Y;

		`EARTH.MoveViewLocation(MoveDelta);
	}

}

function UpdateUIVisualsOnly()
{
	local XComStrategyMap XComMap;

	XComMap = `HQPRES.m_kXComStrategyMap;

	if (XComMap != none)
	{
		XComMap.UpdateVisuals(); //update visuals last to reflect the other changes
	}
}

defaultproperties
{
	m_fTimeScale=PAUSED
}


Bump version to 1.12.0

Bump version to 1.12.0

//---------------------------------------------------------------------------------------
//  FILE:    CHXComGameVersionTemplate.uc
//  AUTHOR:  X2CommunityCore
//  PURPOSE: Version information for the Community Highlander XComGame replacement.
//
//  Issue #1
//
//  This is implemented as a template to allow mods to detect whether the Community Highlander
//  is installed. It's a template to avoid needing to compile against any
//  new sources to get mods to build (which would then crash the game if it tried
//  to access a function //  or variable that wasn't installed anyway). Can be queried by:
//
//  1) Query the StrategyElementTemplateManager for a template named 'CHXComGameVersion'. If you get back
//     a non-none result the XcomGame replacement is installed (or someone is lying and added the template without
//     the actual XComGame replacement...)
//  2) If you need more fine-grained info, such as the particular version, then once you get back a non-none
//     result you can cast it to class 'CHXComGameVersionTemplate' to get the version number through the API below.
//
//  Don't directly look up the template and cast it without checking if you got a non-none result or the game will
//  probably crash when the replacement XComGame isn't present.
//
//  Supports major, minor, and build versions, but build is currently unimplemented.
//---------------------------------------------------------------------------------------
class CHXComGameVersionTemplate extends X2StrategyElementTemplate;

var int MajorVersion;
var int MinorVersion;
var int PatchVersion;

// "Short" version number (minus the patch)
function String GetShortVersionString()
{
    return default.MajorVersion $ "." $ default.MinorVersion;
}

// Version number in string format.
function String GetVersionString()
{
    return default.MajorVersion $ "." $ default.MinorVersion $ "." $ default.PatchVersion;
}

// Version number in comparable numeric format. Number in decimal is MMmmmmPPPP where:O
// "M" is major version
// "m" is minor version
// "P" is patch number
//
// Allows for approx. 2 digits of major, 4 digits of minor versions and 9,999 builds before overflowing.
//
// Optional params take individual components of the version
//
// Note: build number currently disabled and is always 0.
function int GetVersionNumber()
{
    return (default.MajorVersion * 100000000) + (default.MinorVersion * 10000) + (default.PatchVersion);
}

defaultproperties
{
    MajorVersion = 1;
    MinorVersion = 12;
    PatchVersion = 0;
}

//---------------------------------------------------------------------------------------
//  FILE:    CHXComGameVersionTemplate.uc
//  AUTHOR:  X2CommunityCore
//  PURPOSE: Version information for the Community Highlander XComGame replacement.
//
//  Issue #1
//
//  This is implemented as a template to allow mods to detect whether the Community Highlander
//  is installed. It's a template to avoid needing to compile against any
//  new sources to get mods to build (which would then crash the game if it tried
//  to access a function //  or variable that wasn't installed anyway). Can be queried by:
//
//  1) Query the StrategyElementTemplateManager for a template named 'CHXComGameVersion'. If you get back
//     a non-none result the XcomGame replacement is installed (or someone is lying and added the template without
//     the actual XComGame replacement...)
//  2) If you need more fine-grained info, such as the particular version, then once you get back a non-none
//     result you can cast it to class 'CHXComGameVersionTemplate' to get the version number through the API below.
//
//  Don't directly look up the template and cast it without checking if you got a non-none result or the game will
//  probably crash when the replacement XComGame isn't present.
//
//  Supports major, minor, and build versions, but build is currently unimplemented.
//---------------------------------------------------------------------------------------
class CHXComGameVersionTemplate extends X2StrategyElementTemplate;

var int MajorVersion;
var int MinorVersion;
var int PatchVersion;

// "Short" version number (minus the patch)
function String GetShortVersionString()
{
    return default.MajorVersion $ "." $ default.MinorVersion;
}

// Version number in string format.
function String GetVersionString()
{
    return default.MajorVersion $ "." $ default.MinorVersion $ "." $ default.PatchVersion;
}

// Version number in comparable numeric format. Number in decimal is MMmmmmPPPP where:O
// "M" is major version
// "m" is minor version
// "P" is patch number
//
// Allows for approx. 2 digits of major, 4 digits of minor versions and 9,999 builds before overflowing.
//
// Optional params take individual components of the version
//
// Note: build number currently disabled and is always 0.
function int GetVersionNumber()
{
    return (default.MajorVersion * 100000000) + (default.MinorVersion * 10000) + (default.PatchVersion);
}

defaultproperties
{
    MajorVersion = 1;
    MinorVersion = 11;
    PatchVersion = 1;
}