--===========================================================================
--
--						SP MISSION TEMPLATE
--
--===========================================================================
-- Conventions: 'sg_' for sobgroup; 'obj_' for objectives index; 'ev_' for event index;
-- g/l for global/local; s/f/i/t/mt for string/float/integer/table/matrix;
-- 'png_' for ping/pointer index; 'cam_' for cameras; 'vol_' for volumes/points

--=========================== EXTERNAL FILES ================================

dofilepath("data:scripts/scar/restrict.lua")
dofilepath("data:scripts/scar/scar_util.lua")

--============================= INITIALIZE VARIABLES =========================
-- Those are used to assess victory/defeat and end the game.

gs_gameOver = "ongoing"
gi_victoryLevel = 0


--=========================== OBJECTIVES ====================================
-- Text samples to be replaced by localised strings.
-- "title" and "desc" are the text displayed in the objectives box; "id" is the objective index;
-- "level" is used to set objectives as 'primary' or 'secondary' (they don't determine .
-- Achievement or failure of primary objectives ends the mission; secondary objectives do not end the mission.

objectives = {}
objectives.obj_DestroyObject = 
{ 
   	title = "Destroy the enemy carrier.", 
	id = 0, 
	desc = "Use your interceptors to distract the strikecraft from guarding the carrier.\n\nYour bombers will do the main work.", 
	level = "primary", }
objectives.obj_DestroyEnemyForces = 
{ 
	title = "Neutralize all enemy forces.", 
	id = 0, 
	desc = "Only military ships must be destroyed.", 
	level = "primary", }
objectives.obj_DestroyObjectWithTimer = 
{ 
   	title = "You have 3:30 minutes to destroy the enemy carrier.", 
	id = 0, 
	desc = "Use your interceptors to distract the strikecraft from guarding the carrier.\n\nYour bombers will do the main work.", 
	level = "primary", }
objectives.obj_ExtractFromZone = 
{ 
   	title = "Withdraw all forces from the enemy carrier.", 
	id = 0, 
	desc = "They must withdraw at least 10000 m from the carrier.\n\Do this in good order. This is a retreat, not a root.", 
	level = "primary", }
objectives.obj_RallyPoint = 
{ 
   	title = "Rally all your forces at this point.", 
	id = 0, 
	desc = "All ships must be within 1000m of the rally point.", 
	level = "primary", }
objectives.obj_ForceComposition = 
{ 
   	title = "Preserve force composition", 
   	id = 0, 
   	desc = "You must keep at least 50% of your current fleet.", 
	level = "secondary", }
objectives.obj_RetainShip = 
{ 
   	title = "Retain both marine frigates.", 
   	id = 0, 
   	desc = "Provide them with adequate cover or eliminate enemy forces first.", 
	level = "secondary", }
objectives.obj_CaptureObject = 
{ 
   	title = "Capture this Vaygr hyperspace portal.", 
   	id = 0, 
   	desc = "Send your marine frigates to control the portal.\n\nDistract the guarding Vaygr force with your strikecraft.", 
	level = "primary", }
objectives.obj_Recon = 
{ 
   	title = "Gather data on the Vaygr carrier.", 
   	id = 0, 
   	desc = "We have equiped a defensefield frigate with advanced scanners and electronic detection devices.\n\nKeep the frigate in close proximity of the carrier to collect data.\n\nTwo minutes are needed to collect full information.", 
	level = "primary", }


--=========================== EVENTS ========================================
-- Text samples to be replaced by localised strings.

Events = {}

-- Standard introduction briefing -------------------------------------------
-- The main objective(s) should be stated in the intro
Events.ev_TacticalBriefing = 
{ 
	{ 
		{ "Camera_UseCameraPoint('cam_Start')", "", },
	},
	{
		HW2_Letterbox(1),
		HW2_Wait(2),
		{ "Sound_EnableAllSpeech(1)",""},
		{ "Sound_EnterIntelEvent()","" },
		{ "Universe_EnableSkip(1)", "" },
		{ "Universe_AllowPlayerOrders(0)", "" },
		{ "Camera_AllowControl(0)", "" },
		{ "Sensors_EnableCameraZoom(0)", "" },
	},
	{
		HW2_Pause(1),
	}, 
	{
		HW2_Wait(1), 
	}, 
	{
		HW2_LocationCardEvent("PLACE", 2),
	}, 
	{
		HW2_Wait(0.5), 
	}, 
	{
		HW2_LocationCardEvent("TIME", 2),
	}, 
	{
		HW2_Wait(0.5), 
	}, 
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "This is a sample tactical briefing", 2.5), -- timing should more or less fit the time to say the message
	},
	{
		HW2_Wait(0.5), 
	}, 
	{ 
		{ "Sensors_Toggle(1)", "", },
	},
	{
		HW2_Wait(0.5), 
	}, 
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Switching to sensors manager can be useful.", 2.5), 
	},
	{
		HW2_Wait(0.5), 
	}, 
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Briefing is over.", 2), 
	},
	{
		HW2_Letterbox(0),
		HW2_Wait(2),
		HW2_Pause(0),
		{ "Sound_ExitIntelEvent()","" },
		{ "Sound_SetMuteActor(' ')", ""},
		{ "Sensors_Toggle(0)", "", },
		{ "Universe_AllowPlayerOrders( 1 )", "" },
		{ "Camera_AllowControl( 1 )", "" },
		{ "Sensors_EnableCameraZoom( 1 )", "" },
		{ "Universe_EnableSkip(0)", "", },
	},
}
-- Standard closing speech -------------------------------------------
Events.ev_Victory =
{
	{	
		HW2_Letterbox(1),
		HW2_Wait(2),
		{ "Sound_EnableAllSpeech( 1 )",""},
		{ "Sound_EnterIntelEvent()","" },
		{ "Universe_EnableSkip( 0 )", "" },
		{ "Universe_AllowPlayerOrders( 0 )", "" },
	},
	{
		HW2_SubTitleEvent( Actor_FleetIntel,"You have achieved your objectives.", 3 ),
	},
	{
		HW2_Wait(1),
	},
	{
		HW2_LocationCardEvent("MISSION COMPLETE", 4),
	},
	{
		{ "Universe_AllowPlayerOrders( 1 )", "" },
		{ "setMissionComplete(1)", "" },
		},
}
Events.ev_MarginalVictory =
{
	{	
		HW2_Letterbox(1),
		HW2_Wait(2),
		{ "Sound_EnableAllSpeech( 1 )",""},
		{ "Sound_EnterIntelEvent()","" },
		{ "Universe_EnableSkip( 0 )", "" },
		{ "Universe_AllowPlayerOrders( 0 )", "" },
	},
	{
		HW2_SubTitleEvent( Actor_FleetIntel,"You have achieved your objectives, but the price paid was high.", 3 ),
	},
	{
		HW2_Wait(1),
	},
	{
		HW2_LocationCardEvent("MISSION COMPLETE", 4),
	},
	{
		{ "Universe_AllowPlayerOrders( 1 )", "" },
		{ "setMissionComplete(1)", "" },
		},
}
Events.ev_LargeVictory =
{
	{	
		HW2_Letterbox(1),
		HW2_Wait(2),
		{ "Sound_EnableAllSpeech( 1 )",""},
		{ "Sound_EnterIntelEvent()","" },
		{ "Universe_EnableSkip( 0 )", "" },
		{ "Universe_AllowPlayerOrders( 0 )", "" },
	},
	{
		HW2_SubTitleEvent( Actor_FleetIntel,"FleetCommand congratulates you on your success.", 3 ),
	},
	{
		HW2_Wait(1),
	},
	{
		HW2_LocationCardEvent("MISSION COMPLETE", 4),
	},
	{
		{ "Universe_AllowPlayerOrders( 1 )", "" },
		{ "setMissionComplete(1)", "" },
		},
}
Events.ev_Defeat =
{
	{	
		HW2_Letterbox(1),
		HW2_Wait(2),
		{ "Sound_EnableAllSpeech(1)",""},
		{ "Sound_EnterIntelEvent()","" },
		{ "Universe_EnableSkip(0)", "" },
		{ "Universe_AllowPlayerOrders(0)", "" },
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel,"You were unable to fulfil your objective.", 3),
	},
	{
		HW2_Wait(1),
	},
	{
		HW2_LocationCardEvent("MISSION FAILED", 4),
	},
	{
		{ "Universe_AllowPlayerOrders(1)", "" },
		{ "setMissionComplete(0)", "" },
	},
}
Events.ev_LargeDefeat =
{
	{	
		HW2_Letterbox(1),
		HW2_Wait(2),
		{ "Sound_EnableAllSpeech( 1 )",""},
		{ "Sound_EnterIntelEvent()","" },
		{ "Universe_EnableSkip( 0 )", "" },
		{ "Universe_AllowPlayerOrders( 0 )", "" },
	},
	{
		HW2_SubTitleEvent( Actor_FleetIntel,"Your failure is total. You are demoted.", 3 ),
	},
	{
		HW2_Wait(1),
	},
	{
		HW2_LocationCardEvent("MISSION FAILED", 4),
	},
	{
		{ "Universe_AllowPlayerOrders( 1 )", "" },
		{ "setMissionComplete(0)", "" },
		},
}


-- Events for destroy object task -------------------------------------------
Events.ev_DestroyObject = 
{
	{
		{ "Camera_FocusSobGroupWithBuffer('sg_TargetObject', 2000, 2000, 4)", "" },
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Destroy this ship.", 2), 
	},
	{
		HW2_Wait(1),
	},
	{
		{ "png_TargetObject = Ping_AddSobGroup('Vaygr Carrier', 'anomaly', 'sg_TargetObject')", "", }, 
		{ "Ping_AddDescription(png_TargetObject, 0, 'Enemy capital ship' )", "", }, 
	},
}

Events.ev_ObjectIsDestroyed =
{
	{
		{ "Ping_Remove('png_TargetObject')", "", }, 
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Target Destroyed", 2), 
	},
	{
		HW2_Wait(1),
	},
}
-- Events for destroy object with timer task -------------------------------------------
Events.ev_DestroyObjectWithTimer = 
{
	{
		{ "Camera_FocusSobGroupWithBuffer('sg_TargetObject', 2000, 2000, 4)", "" },
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "You have 3:30 minutes to destroy this ship.", 2), 
	},
	{
		HW2_Wait(1),
	},
	{
		{ "png_TargetObject = Ping_AddSobGroup('Vaygr Carrier', 'anomaly', 'sg_TargetObject')", "", }, 
		{ "Ping_AddDescription(png_TargetObject, 0, 'Enemy capital ship' )", "", }, 
	},
}

Events.ev_ObjectIsDestroyedInTime =
{
	{
		{ "Ping_Remove(png_TargetObject)", "", },
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Target Destroyed in time.", 2), 
	},
	{
		HW2_Wait(1),
	},
}
Events.ev_DestroyObjectTimeout =
{
	{
		{ "Ping_Remove(png_TargetObject)", "", },
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Objective timed out.", 2), 
	},
	{
		HW2_Wait(1),
	},
}
-- Events for capture object task -------------------------------------------
Events.ev_CaptureObject = 
{
	{
		{ "Camera_FocusSobGroupWithBuffer('sg_ObjectToCapture', 2000, 2000, 4)", "" },
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Capture this hyperspace portal.", 2), 
	},
	{
		HW2_Wait(1),
	},
	{
		{ "png_CaptureObject = Ping_AddSobGroup('Gate', 'anomaly', 'sg_ObjectToCapture')", "", }, 
		{ "Ping_AddDescription(png_CaptureObject, 0, 'Vaygr hyperspace portal' )", "", }, 
	},
}

Events.ev_ObjectIsCaptured =
{
	{
		{ "Ping_Remove('png_CaptureObject')", "", }, 
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Object captured.", 2), 
	},
	{
		HW2_Wait(1),
	},
}
-- Events for Destroy enemy forces task -------------------------------------
Events.ev_DestroyEnemyForces = 
{
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Neutralise all enemy forces.", 2.5), 
	},
}

Events.ev_EnemyForcesAreDestroyed =
{
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Enemy forces have been neutralised.", 2.5), 
	},
}
-- Events for extraction from zone task --------------------------------------
Events.ev_ExtractFromZone = 
{
	{
		{ "png_Zone = EventPointer_AddVolume('vol_ExtractionZone', HW2_rgb(230, 30, 30), 60000)", "", }, 
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Now withdraw all forces at least 40000m from map centre", 2.5), 
	},
}
Events.ev_ExtractionIsDone =
{
	{
		{ "EventPointer_Remove(png_Zone)", "", },
	},
}

-- Events for move to rally point task ----------------------------------------
Events.ev_RallyPoint = 
{
	{
		{ "png_RallyZone = EventPointer_AddVolume('vol_RallyZone', HW2_rgb(30, 230, 30), 1000)", "", }, 
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Rally all forces at the designated location.", 2.5), 
	},
}

Events.ev_MoveIsDone =
{
	{
		{ "gi_eventIsRunning = 1", "", },
		{ "EventPointer_Remove(png_RallyZone)", "", },
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Forces rallied. Ready to proceed.", 2.5), 
	},
	{
		HW2_Wait(2.5),
	},
	{
		{ "gi_eventIsRunning = 0", "", },
	},
}
-- Events for Recon task ----------------------------------------
Events.ev_Recon = 
{
	{
		{ "Camera_FocusSave()", "" },
		{ "Camera_FocusSobGroupWithBuffer('sg_SobToRecon', 1000, 1000, 2)", "" },
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "We must collect data on this Vaygr carrier model.", 3), 
	},
	{
		HW2_Wait(0.5),
	},
	{
		{ "Camera_FocusRestore()", "" },
		HW2_SubTitleEvent(Actor_FleetIntel, "A defense field frigate has been equiped with advanced scanning and detection devices.", 3), 
	},
	{
		HW2_Wait(0.5),
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "It will collect data when in close proximity of the carrier; two minutes of scanning are necessary.", 3), 
	},
	{
		{ "png_SobToRecon = Ping_AddSobGroup('Vaygr Carrier', 'anomaly', 'sg_TargetObject')", "", }, 
		{ "Ping_AddDescription(png_SobToRecon, 0, 'Vessel to scan' )", "", }, 
	},
}

Events.ev_ReconIsDone =
{
	{
		{ "Ping_Remove(png_SobToRecon)", "", },
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Data collected.", 2), 
	},
	{
		HW2_Wait(1),
	},
}
Events.ev_ReconFailed =
{
	{
		{ "Ping_Remove(png_SobToRecon)", "", },
	},
	{
		HW2_SubTitleEvent(Actor_FleetIntel, "Unable to complete data collection.", 2), 
	},
	{
		HW2_Wait(1),
	},
}
-- Events for retain ship task -------------------------------------------------
Events.ev_RetainShip =
{
	{
		{ "png_ShipToRetain = EventPointer_AddSobGroup('sg_ShipToRetain', HW2_rgb(30,230,30), 200)", "", },
	},
}
Events.ev_ShipIsLost =
{
	{

		{ "EventPointer_Remove(png_ShipToRetain)", "", },
	},
}



--=========================== INIT RULES ========================================

-- comment out all mission inits save the one you want to play/test
function OnInit()
	Player_Setup()
	AI_Setup()
	Rule_Add("Rule_InitMission1")
--	Rule_Add("Rule_InitMission2")
--	Rule_Add("Rule_InitMission3")
--	Rule_Add("Rule_InitMission4")
end

function Rule_InitMission1() -- one single objective
	Player_Kill(2)
	SobGroup_Despawn("sg_HiigaranMarines")
	SobGroup_Despawn("sg_ReconFrigate")
	Event_Start("ev_TacticalBriefing")
	Rule_Add("Rule_DestroyObject")
	Rule_AddInterval("Rule_WatchObjectives", 3)
	Rule_Remove("Rule_InitMission1")
end

function Rule_InitMission2() -- a primary objective and a secondary one
	Player_Kill(2)
	SobGroup_Despawn("sg_HiigaranMarines")
	SobGroup_Despawn("sg_ReconFrigate")
	Event_Start("ev_TacticalBriefing")
	Rule_Add("Rule_DestroyObjectWithTimer")
	Rule_Add("Rule_RetainShip")
	Rule_AddInterval("Rule_WatchObjectives", 3)
	Rule_Remove("Rule_InitMission2")
end

function Rule_InitMission3() -- two simultaneous primary objectives
	SobGroup_Despawn("sg_ReconFrigate")
	Event_Start("ev_TacticalBriefing")
	Rule_Add("Rule_CaptureObject")
	Rule_Add("Rule_DestroyEnemyForces")
	Rule_AddInterval("Rule_WatchObjectives", 3)
	Rule_Remove("Rule_InitMission3")
end

function Rule_InitMission4() -- two successive primary objectives and one secondary
	SobGroup_Despawn("sg_HiigaranMarines")
	Event_Start("ev_TacticalBriefing")
	Rule_Add("Rule_RallyPoint")
	gi_rallyPointDone = 0
	Rule_Add("Rule_Recon")
	Rule_Add("Rule_ForceComposition")
	Rule_AddInterval("Rule_WatchObjectives", 3)
	Rule_Remove("Rule_InitMission4")
end

--================== FUNCTIONS: SET PLAYER AND GROUP DETAILS =======================

function Player_Setup()
	Player_SetTeamColours(0, {109/255, 164/255, 217/255}, {219/255, 223/255, 163/255})
	Player_SetBadgeTexture(0, "DATA:badges/KIITH SJET.tga")
	SobGroup_SetTeamColours("sg_HiigaranMarines", { 77/255, 9/255, 9/255, }, { 0/255, 0/255, 0/255, }, "DATA:Badges/KIITH SOBAN.tga")
end	   

function AI_Setup()
	SetAlliance(1, 2)
	SetAlliance(2, 1)
	Player_SetTeamColours(1, {30/255, 30/255, 30/255}, {225/255, 225/255, 225/255})
	Player_SetBadgeTexture(1, "DATA:badges/VAYGR.TGA")
	Player_SetTeamColours(2, { 125/255, 0/255, 0/255, }, { 225/255, 225/255, 225/255, })
	Player_SetBadgeTexture(2, "DATA:badges/VAYGR.TGA")
	Player_SetPlayerName(1, "Vaygr Armada")
	Player_SetPlayerName(2, "Vaygr Raiders")
	Player_SetDefaultShipTactic(1, AggressiveTactics)
	Player_SetDefaultShipTactic(2, AggressiveTactics)
	SobGroup_FormHyperspaceGate("sg_Portal1", "sg_Portal2") -- can be deleted
end

--=========================== TASK: DESTROY OBJECT ===============================
-- The only thing on the to-do-list is to define target. It is done here by a 'FillShipsByType' function.
-- It can be done by simply adding a level-defined SobGroup to 'sg_TargetObject' by SobGroup_SobGroupAdd.
-- It can also be done by a 'FillSobGroupInVolume' function with a volume (level-defined or set with 'Volume_AddSphere').
-- Many other ways are possible.

--initialization
function Rule_DestroyObject()
	if Event_IsDone("ev_TacticalBriefing") == 1 then -- it's advisable to start the first objective only after the first event is done
		SobGroup_Create("sg_TargetObject")
		Player_FillShipsByType("sg_TargetObject", 1, "vgr_carrier") -- define target here
		addObjective("obj_DestroyObject")
		Event_Start("ev_DestroyObject")
		Rule_AddInterval("Rule_WatchObjectDestroyed", 5)
		Rule_Remove("Rule_DestroyObject")
	end
end
	
--watch rule
function Rule_WatchObjectDestroyed() 
	local li_testflag = 0
	if SobGroup_Empty("sg_TargetObject") == 1 then
		li_testflag = 1
	elseif SobGroup_AreAnyFromTheseAttackFamilies("Player_Ships0", "Fighter") == 0 then -- can be deleted
		li_testflag = 2 -- can be deleted
	end
	if li_testflag == 1 then
		Event_Start("ev_ObjectIsDestroyed")
		completeObjective("obj_DestroyObject")
		Rule_Remove("Rule_WatchObjectDestroyed")
	elseif li_testflag == 2 then
		failedObjective("obj_DestroyObject")
		Rule_Remove("Rule_WatchObjectDestroyed")
	end
end

--=========================== TASK: DESTROY OBJECT WITH TIMER ====================

--initialization rule
function Rule_DestroyObjectWithTimer()
	if Event_IsDone("ev_TacticalBriefing") == 1 then
		SobGroup_Create("sg_TargetObject")
		Player_FillShipsByType("sg_TargetObject", 1, "vgr_carrier") -- define target here
		addObjective("obj_DestroyObjectWithTimer")
		Event_Start("ev_DestroyObjectWithTimer")
		Timer_Start(0, 210) -- define timer amount here (in seconds)
		Subtitle_TimeCounter(0, 8000) -- 8000 points to a localised string (see locale directory)
		Rule_AddInterval("Rule_WatchObjectDestroyedWithTimer", 1)
		Rule_Remove("Rule_DestroyObjectWithTimer")
	end
end

--watch rule
function Rule_WatchObjectDestroyedWithTimer() 
	local li_testflag = 0
	if SobGroup_Empty("sg_TargetObject") == 1 then
		li_testflag = 1
	elseif Timer_GetRemaining(0) < 1 then
		li_testflag = 2
	end
	if li_testflag == 1 then
		Event_Start("obj_ObjectIsDestroyedInTime")
		Subtitle_TimeCounterEnd()
		completeObjective("obj_DestroyObjectWithTimer")
		Rule_Remove("Rule_WatchObjectDestroyedWithTimer")
	elseif li_testflag == 2 then
		Event_Start("ev_DestroyObjectTimeout")
		Subtitle_TimeCounterEnd()
		failedObjective("obj_DestroyObjectWithTimer")
		Rule_Remove("Rule_WatchObjectDestroyedWithTimer")
	end
end

--=========================== TASK: CAPTURE OBJECT ===============================

--initialization
function Rule_CaptureObject()
	if Event_IsDone("ev_TacticalBriefing") == 1 then 
		SobGroup_Create("sg_ObjectToCapture")
		SobGroup_SobGroupAdd("sg_ObjectToCapture", "sg_Portal2") -- define target here
		SobGroup_SetSwitchOwnerFlag("sg_ObjectToCapture", 0)
		addObjective("obj_CaptureObject")
		Event_Start("ev_CaptureObject")
		SobGroup_Create("sg_tempGroup")
		Rule_Add("Rule_VaygrSendReinforcement") -- can be deleted
		Rule_AddInterval("Rule_WatchObjectCaptured", 5)
		Rule_Remove("Rule_CaptureObject")
	end
end
	
-- watch rule
-- assumes capture changes ownership; if it only disables the captured ship, use 'CanDoAbility' test 
function Rule_WatchObjectCaptured() 
	local li_testflag = 0
	if SobGroup_OwnedBy("sg_ObjectToCapture") == 0 then
		li_testflag = 1
	elseif SobGroup_AreAnyOfTheseTypes("Player_Ships0", "hgn_marinefrigate") == 0 or SobGroup_Empty("sg_ObjectToCapture") == 1 then -- can be deleted (if you can build marine frigs)
		li_testflag = 2 -- can be deleted (if you can build marine frigs)
	end
	if li_testflag == 1 then
		Event_Start("ev_ObjectIsCaptured")
		completeObjective("obj_CaptureObject")
		Rule_Remove("Rule_WatchObjectCaptured")
	elseif li_testflag == 2 then
		failedObjective("obj_CaptureObject")
		Rule_Remove("Rule_WatchObjectCaptured")
	end
end

function Rule_VaygrSendReinforcement()
	if SobGroup_FillProximitySobGroup("sg_tempGroup", "sg_ObjectToCapture", "sg_HiigaranMarines", 4000) == 1 then
		SobGroup_UseHyperspaceGate("sg_VaygrGroup1", "sg_Portal1")
		Rule_Remove("Rule_VaygrSendReinforcement")
	end
end

--=========================== TASK: DESTROY ENEMY FORCES ============================

--initialization rule
function Rule_DestroyEnemyForces()
	addObjective("obj_DestroyEnemyForces")
	Event_Start("ev_DestroyEnemyForces")
	Rule_AddInterval("Rule_WatchDestroyEnemyForces", 5)
	Rule_Remove("Rule_DestroyEnemyForces")
end

-- watch rule
function Rule_WatchDestroyEnemyForces()
	local li_testflag = 0
	if HW2_PlayerHasMilitary(1) == 0 then -- alternative: HW2_PlayerHasShipWithBuildQueue
		li_testflag = 1
	end
	if li_testflag == 1 then
		Event_Start("ev_EnemyForcesAreDestroyed")
		completeObjective("obj_DestroyEnemyForces")
		Rule_Remove("Rule_WatchDestroyEnemyForces")
	end
end

 --=========================== TASK: EXTRACT FROM ZONE =============================
-- The objective is assessed against all military ships but nothing else (notably excl. probes).
-- Alternatively, it could be assessed against a percentage of the fleet (eg using Stats functions).

--initialization rule
function Rule_ExtractFromZone()
if Event_IsDone("ev_ObjectIsDestroyed") == 1 then
	Volume_AddSphere("vol_ExtractionZone", {0,0,0}, 40000) --define volume center point and radius here
	SobGroup_Create("sg_ShipsInZone")
	addObjective("obj_ExtractFromZone")
	Event_Start("ev_ExtractFromZone")
	Rule_AddInterval("Rule_WatchExtractFromZone", 5)
	Rule_Remove("Rule_ExtractFromZone")
end
end
	
--watch rule
function Rule_WatchExtractFromZone() 
	SobGroup_FillSobGroupInVolume("sg_ShipsInZone", "Player_Ships0", "vol_ExtractionZone")
	local li_testflag = 0
	if SobGroup_Empty("sg_ShipsInZone") == 1 then
		li_testflag = 1
	elseif SobGroup_AreAnyFromTheseAttackFamilies("sg_ShipsInZone", "Fighter, Corvette, Frigate, SmallCapitalShip, BigCapitalShip, Mothership, Capturer") == 0 then  --probes and utilities excluded
		li_testflag = 1
	end
	SobGroup_Clear("sg_ShipsInZone")
	if li_testflag == 1 then
		completeObjective("obj_ExtractFromZone")
		Volume_Delete("vol_ExtractionZone")
		Event_Start("ev_ExtractionIsDone")
		Rule_Remove("Rule_WatchExtractFromZone")
	end
end


--=========================== TASK: MOVE TO RALLY POINT ==============================
-- The objective is assessed against all military ships but nothing else (notably excl. probes).
-- The volume can also be added in the level file.

--initialization rule
function Rule_RallyPoint()
	if Event_IsDone("ev_TacticalBriefing") == 1 then
		Volume_AddSphere("vol_RallyZone", {3000,1000,-3000}, 1000) --define volume center point and radius here
		SobGroup_Create("sg_ShipsInRallyZone")
		SobGroup_Create("sg_ShipsOutsideRallyZone")
		addObjective("obj_RallyPoint")
		Event_Start("ev_RallyPoint")
		Rule_AddInterval("Rule_WatchRallyPoint", 5)
		Rule_Remove("Rule_RallyPoint")
	end
end
	
--watch rule
function Rule_WatchRallyPoint() 
	SobGroup_FillSobGroupInVolume("sg_ShipsInRallyZone", "Player_Ships0", "vol_RallyZone")
	SobGroup_FillSubstract("sg_ShipsOutsideRallyZone", "Player_Ships0", "sg_ShipsInRallyZone")
	local li_testflag = 0
	if SobGroup_Empty("sg_ShipsOutsideRallyZone") == 1 then
		li_testflag = 1
	elseif SobGroup_AreAnyFromTheseAttackFamilies("sg_ShipsOutsideRallyZone", "Fighter, Corvette, Frigate, SmallCapitalShip, BigCapitalShip, Mothership, Capturer") == 0 then -- check out only military units
		li_testflag = 1
	end
	SobGroup_Clear("sg_ShipsInRallyZone")
	if li_testflag == 1 then
		gi_rallyPointDone =1 
		completeObjective("obj_RallyPoint")
		Volume_Delete("vol_RallyZone")
		Event_Start("ev_MoveIsDone")
		Rule_Remove("Rule_WatchRallyPoint")
	end
end

--===================== TASK: RECON ============================================
-- set here as a second primary objective assigned when the first is done

function Rule_Recon()
	if gi_rallyPointDone == 1 then -- wait for the first objective to be flagged 'done'
		SobGroup_Create("sg_SobToRecon")
		SobGroup_Create("sg_tempSobGroup")	
		Player_FillShipsByType("sg_SobToRecon", 1, "vgr_carrier") -- define object here
		addObjective("obj_Recon")
		Rule_Add("Rule_DisplayReconEvent")
		Timer_Start(1, 120) -- define timer amount here (in seconds)
		Timer_Pause(1)
		gi_timerIsRunning = 0
		Rule_AddInterval("Rule_WatchRecon", 1)
		Rule_AddInterval("Rule_VaygrCarrierFlees", 1) -- can be deleted
		Rule_Remove("Rule_Recon")
	end
end

function Rule_DisplayReconEvent() -- It waits for the closing event of first objective before to display this one
	if gi_eventIsRunning == 0 then
		Event_Start("ev_Recon")
		Subtitle_TimeCounter(1, 8010)
		Rule_Remove("Rule_DisplayReconEvent")
	end
end

function Rule_WatchRecon()
	if gi_timerIsRunning == 0 and SobGroup_FillProximitySobGroup("sg_tempSobGroup", "sg_SobToRecon", "sg_ReconFrigate", 800) == 1 then -- set 'recon' ships and radius here
		Timer_Resume(1)
		gi_timerIsRunning = 1
	elseif gi_timerIsRunning == 1 and SobGroup_FillProximitySobGroup("sg_tempSobGroup", "sg_SobToRecon", "sg_ReconFrigate", 800) == 0 then -- same here
		Timer_Pause(1)
		gi_timerIsRunning = 0
	end
	local li_testflag = 0
	if Timer_GetRemaining(1) < 1 then
		li_testflag = 1
	elseif SobGroup_Empty("sg_ReconFrigate") == 1 or SobGroup_Empty("sg_SobToRecon") == 1 then
		li_testflag = 2
	end
	if li_testflag == 1 then
		completeObjective("obj_Recon")
		Subtitle_TimeCounterEnd()
		Event_Start("ev_ReconIsDone")
		Rule_Remove("Rule_WatchRecon")
	elseif li_testflag == 2 then
		failedObjective("obj_Recon")
		Subtitle_TimeCounterEnd()
		Event_Start("ev_ReconFailed")
		Rule_Remove("Rule_WatchRecon")
	end
end

function Rule_VaygrCarrierFlees()
	if SobGroup_FillProximitySobGroup("sg_tempSobGroup", "sg_SobToRecon", "sg_ReconFrigate", 4000) == 1 then
		CPU_RemoveSobGroup(1, "sg_SobToRecon")
		SobGroup_Move(1, "sg_SobToRecon", "vol_FleeSphere")
		SobGroup_Create("sg_Vaygr2Interceptors")
		SobGroup_Create("sg_Vaygr2Bombers")
		Player_FillShipsByType("sg_Vaygr2Interceptors", 2, "vgr_interceptor")
		Player_FillShipsByType("sg_Vaygr2Bombers", 2, "vgr_bomber")
		SobGroup_AttackPlayer("sg_Vaygr2Interceptors", 0)
		SobGroup_Attack(2, "sg_Vaygr2Bombers", "sg_ReconFrigate")
		Rule_Remove("Rule_VaygrCarrierFlees")
	end
end


--=====================TASK: RETAIN SHIP========================================
-- the watch test is designed as secondary; changes are necessary if set as primary.

--initialization rule
function Rule_RetainShip()
	SobGroup_Create("sg_ShipToRetain") 
	Player_FillShipsByType("sg_ShipToRetain", 0, "hgn_marinefrigate") --define ships here
	addObjective("obj_RetainShip")
	Event_Start("ev_RetainShip")
	Rule_AddInterval("Rule_WatchShipRetained", 3)
	Rule_Remove("Rule_RetainShip")
end
	
--watch rule
function Rule_WatchShipRetained()
	local li_testflag = 0
	if SobGroup_Count("sg_ShipToRetain") < 2 then -- modify this if the objective is to keep at least 1 ship
		li_testflag = 1
	elseif gs_gameOver ~= "ongoing" then
		li_testflag = 2
	end
	if li_testflag == 1 then
		failedObjective("obj_RetainShip")
		Event_Start("ev_ShipIsLost")
		Rule_Remove("Rule_WatchShipRetained")
	end
	if li_testflag == 2 then
		completeObjective("obj_RetainShip")
		Rule_Remove("Rule_WatchShipRetained")
	end
end

--======================TASK: PRESERVE FORCE COMPOSITION=========================
-- This objective can be assessed against the number of ships or their value in RUs.
-- the watch test is designed as secondary; changes are necessary if set as primary.

function Rule_ForceComposition()
	addObjective("obj_ForceComposition")
	gf_stat1 = SobGroup_Count("Player_Ships0")*0.5 -- calculate minimal force to keep here
	Rule_AddInterval("Rule_WatchForceComposition", 5)
	Rule_Remove("Rule_ForceComposition")
end

function Rule_WatchForceComposition()
	local li_testflag = 0
	gf_stat2 = SobGroup_Count("Player_Ships0") -- use the same calculation to check the force composition
	if gf_stat2 < gf_stat1 then
		li_testflag = 1
	elseif gs_gameOver ~= "ongoing" then
		li_testflag = 2
	end
	if li_testflag == 1 then
		failedObjective("obj_ForceComposition")
		Rule_Remove("Rule_WatchForceComposition")
	end
	if li_testflag == 2 then
		completeObjective("obj_ForceComposition")
		Rule_Remove("Rule_WatchForceComposition")
	end
end

--======================== END OF GAME RULES =====================================
-- Assesses the objectives assigned from the "objectives" table (unassigned objectives are not tested).
-- Game is ended when all primaries are complete or when any of them has been failed.
-- This implies that all victory conditions are expressed as primary objectives.
-- If primary objectives are successively assigned, make sure to assign the next one before setting the previous one as complete.
-- 'Victory level' is modulated in accordance with secondary objectives; it can be used to change the closing speech or for dynamic campaigns.

function Rule_WatchObjectives()
	if Event_IsDone("ev_TacticalBriefing") == 1 then -- always wait for the objectives to be set 
		gs_gameOver = "victory"
		for i, iCount in objectives do -- watches primaries to end game
			if iCount.level == "primary" then 
				if Objective_GetState(iCount.id) == OS_Incomplete then
					gs_gameOver = "ongoing"
				end
			end
		end	
		for i, iCount in objectives do -- watches primaries to end game
			if iCount.level == "primary" then 
				if Objective_GetState(iCount.id) == OS_Failed then
					gs_gameOver = "defeat"
				end
			end
		end	
		if HW2_PlayerHasMilitary(0) == 0 then -- always end when player has no military ship left
			gs_gameOver = "defeat"
		end
		if gs_gameOver ~= "ongoing" then 
			Rule_AddInterval("Rule_GameEnds", 5) -- set sufficient interval for all secondaries to be assessed before actual end
			Rule_Remove("Rule_WatchObjectives")
		end
	end
end

function Rule_GameEnds()
	for i, iCount in objectives do -- evaluates secondaries to determine the victory level
		if iCount.id ~= 0 and iCount.level == "secondary" then
			if Objective_GetState(iCount.id) == OS_Failed then
				gi_victoryLevel = gi_victoryLevel - 1
			elseif Objective_GetState(iCount.id) == OS_Complete then
				gi_victoryLevel = gi_victoryLevel + 1
			end
		end
	end
	if gs_gameOver == "victory" and gi_victoryLevel == 0 then 
		Event_Start("ev_Victory")
	elseif gs_gameOver == "victory" and gi_victoryLevel < 0 then
		Event_Start("ev_MarginalVictory")
	elseif gs_gameOver == "victory" and gi_victoryLevel > 0 then
		Event_Start("ev_LargeVictory")
	elseif gs_gameOver == "defeat" and gi_victoryLevel < 0 then
		Event_Start("ev_LargeDefeat")
	elseif gs_gameOver == "defeat" and gi_victoryLevel >= 0 then
		Event_Start("ev_Defeat")
	end
end


--======================== FUNCTION: OBJECTIVES ==============================
-- Add and set the named objective from the "objectives" table. 
-- Mikail's modified version of the function found in the tutorial missions.
-- Further modified by SunTzu to enable standard game ending routine.

function addObjective(sObj)
	if objectives[sObj].level == "secondary" then 
		objectives[sObj].id = Objective_Add(objectives[sObj].title, OT_Secondary)
	else
		objectives[sObj].id = Objective_Add(objectives[sObj].title, OT_Primary)
	end
	if (objectives[sObj].desc) then
		Objective_AddDescription(objectives[sObj].id, objectives[sObj].desc)
	end
end

function completeObjective(obj)
	Objective_SetState(objectives[obj].id, OS_Complete)
end

function failedObjective(obj)
	Objective_SetState(objectives[obj].id, OS_Failed)
end

function ignoreObjective(obj)
	Objective_SetState(objectives[obj].id, OS_Off)
end