-- Survival Insane V1
-- Modified by Brock Samson
-- Based on Survival Extreme V3FA script

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- imports and variables
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local ScenarioUtils = import('/lua/sim/ScenarioUtilities.lua');
local ScenarioFramework = import('/lua/ScenarioFramework.lua');
local Utilities = import('/lua/utilities.lua');
local Entity = import('/lua/sim/Entity.lua').Entity;

-- global vars
local gameEnd = false;		-- true when game is over
local beatTime = 1;			-- seconds to wait between game logic calculations
local playercount = 0;		-- how many human players?

-- survival mode
local numGatesOpen = 0; 	-- how many spawn gates are alive
local gates = {nil, nil, nil, nil, nil, nil, nil, nil};	-- gate pointers
local numSpecialsOpen = 0;	-- how many special weapons are alive
local specials = {nil, nil, nil, nil}; -- special pointers
local killCount = { ARMY_1 = 0,		-- number of gates/specials killed by each player+2 ai's
					ARMY_2 = 0,
					ARMY_3 = 0,
					ARMY_4 = 0,
					ARMY_SUPERWEAPON = 0,
					ARMY_SURVIVAL_ENEMY = 0};

-- Survival Insane Vars
local HealthBuff = 1; -- health multiplier
local HealthBuffAir = 1; -- for air units
local UnitCountMult = 1; -- unit count multiplier
local AirFreqCount = 0; -- counter for air wave frequency



------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- engine invoked main functions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-- this function is called once before game start, it does some player initialization
function OnPopulate()
	-- make default settings work
	if (ScenarioInfo.Options.opt_difficulty == nil) then
		ScenarioInfo.Options.opt_difficulty = 3;
	end
	if (ScenarioInfo.Options.opt_startupTime == nil) then
		ScenarioInfo.Options.opt_startupTime = 180;
	end
	if (ScenarioInfo.Options.opt_waveTime == nil) then
		ScenarioInfo.Options.opt_waveTime = 75;
	end
	if (ScenarioInfo.Options.opt_airFrequency == nil) then
		ScenarioInfo.Options.opt_airFrequency = 2;
	end
	if (ScenarioInfo.Options.opt_defenseObject == nil) then
		ScenarioInfo.Options.opt_defenseObject = 3;
	end
	
	ScenarioUtils.InitializeArmies();
	
	-- count number of players
	local armies = ListArmies();
	playercount = table.getn(armies) - 2;	-- num armies minus 2 ai players
	LOG("___SE___ PlayerCount: "..playercount);
end

-- this function creates all mex and hydrocarbon markers
-- resource scale script (c) Jotto, reworked by tecxx
function ScenarioUtils.CreateResources()
	-- fetch markers and iterate them
	local markers = ScenarioUtils.GetMarkers();
	for i, tblData in pairs(markers) do
		-- spawn resources?
		local doit = false;
		if (tblData.resource and not tblData.SpawnWithArmy) then
			-- standard resources, spawn it
			doit = true;
		elseif (tblData.resource and tblData.SpawnWithArmy) then
			-- resources bound to player, check if army is presend
			for j, army in ListArmies() do
				if (tblData.SpawnWithArmy == army) then
					doit = true;  -- we made sure the army is present, allow spawn
					break;
				end
			end
		end
		
		if (doit) then
			-- check type of resource and set parameters
			local bp, albedo, sx, sz, lod;
			if (tblData.type == "Mass") then
				albedo = "/env/common/splats/mass_marker.dds";
				bp = "/env/common/props/massDeposit01_prop.bp";
				sx = 2;
				sz = 2;
				lod = 100;
			else
				albedo = "/env/common/splats/hydrocarbon_marker.dds";
				bp = "/env/common/props/hydrocarbonDeposit01_prop.bp";
				sx = 6;
				sz = 6;
				lod = 200;
			end
			-- create the resource
			CreateResourceDeposit(tblData.type,	tblData.position[1], tblData.position[2], tblData.position[3], tblData.size);
			-- create the resource graphic on the map
			CreatePropHPR(bp, tblData.position[1], tblData.position[2], tblData.position[3], Random(0,360), 0, 0);
			-- create the resource icon on the map
			CreateSplat(
				tblData.position,           # Position
				0,                          # Heading (rotation)
				albedo,                     # Texture name for albedo
				sx, sz,                     # SizeX/Z
				lod,                        # LOD
				0,                          # Duration (0 == does not expire)
				-1,                         # army (-1 == not owned by any single army)
				0							# ???
			);
		end
	end
end

-- start of map script
function OnStart(self)
	-- initiate game modes and spawn players
	setupGame();
	
	-- start the game logic
	startScenarioThreads();
	
	-- set score calculation to show total kills
	for index, brain in ArmyBrains do
		brain.CalculateScore = function(thisBrain)
			return armyKills(thisBrain) + killCount[ArmyIndexer(thisBrain)]*1000;
		end
	end 
end

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- main game logic
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

--creates the different scenario threads 
startScenarioThreads = function()
	--start main thread
	local mainThread = ForkThread(function(self)
		LOG("___SE___ Main thread running!");
	
		while (gameEnd == false) do
			--wait time between each beat
			WaitSeconds(beatTime);
			-- run game logic
			gameLogic();
		end
		
		KillThread(self);
    end);
	
	--this creates a new spawn thread,, only in survival mode
	local spawnThread = ForkThread(spawnThread);
end

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- survival mode
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- unit tables, seperated by air/ground
local unitTableGroundBS = {
	{ -- Wave Set 1
		'UAL0106', -- aeon light assault
		'UAL0201', -- aeon light tank
		'URL0106', -- cybran light assault
		'URL0107', -- cybran heavy assault
		'UEL0106', -- uef light assault
		'UEL0201', -- uef medium tank
		'xsl0101', -- seraphim combat scout
		'xsl0201', -- seraphim medium tank

		'UAL0201', -- aeon light tank
		'URL0107', -- cybran heavy assault
		'UEL0201', -- uef medium tank
		'xsl0201', -- seraphim medium tank

		'UAL0101', -- aeon scout
		'UAL0103', -- aeon t1 arty
		'URL0101', -- cybran scout
		'URL0103', -- cybran t1 arty
		'UEL0101', -- uef scout
		'UEL0103', -- uef t1 arty	
		'xsl0101', -- seraphim combat scout
		'xsl0103', -- seraphim light artillery

		'UAL0205', -- aeon t2 aa
		'URL0205', -- cybran t2 aa
		'UEL0205', -- uef t2 aa	
		'xsl0205', -- seraphim t2 anti air
	},
	{ -- Wave Set 2
		'UAL0106', -- aeon light assault
		'UAL0201', -- aeon light tank
		'URL0106', -- cybran light assault
		'URL0107', -- cybran heavy assault
		'UEL0106', -- uef light assault
		'UEL0201', -- uef medium tank
		'xsl0101', -- seraphim combat scout
		'xsl0201', -- seraphim medium tank

		'UAL0101', -- aeon scout
		'UAL0103', -- aeon t1 arty
		'URL0101', -- cybran scout
		'URL0103', -- cybran t1 arty
		'UEL0101', -- uef scout
		'UEL0103', -- uef t1 arty	
		'xsl0101', -- seraphim combat scout
		'xsl0103', -- seraphim light artillery

		'UAL0202', -- aeon t2 tank
		'UAL0205', -- aeon t2 aa
		'URL0202', -- cybran t2 tank
		--'URL0203', -- cybran t2 amphibious tank
		'URL0205', -- cybran t2 aa
		'UEL0202', -- uef t2 tank
		--'UEL0203', -- uef t2 amphibious tank
		'UEL0205', -- uef t2 aa	
		'DRL0204', -- cybran t2 rocket
		--'DEL0204', -- uef t2 gatling
		'xal0203', -- aeon t2 assault tank
		--'xsl0202', -- seraphim t2 assault bot
		'xsl0203', -- seraphim t2 hover tank
		'xsl0205', -- seraphim t2 anti air
	},
	{ -- Wave Set 3
		'UAL0201', -- aeon light tank
		'URL0107', -- cybran heavy assault
		'UEL0201', -- uef medium tank
		'xsl0201', -- seraphim medium tank

		'UAL0101', -- aeon scout
		'UAL0103', -- aeon t1 arty
		'URL0101', -- cybran scout
		'URL0103', -- cybran t1 arty
		'UEL0101', -- uef scout
		'UEL0103', -- uef t1 arty	
		'xsl0101', -- seraphim combat scout
		'xsl0103', -- seraphim light artillery

		'UAL0202', -- aeon t2 tank
		'UAL0111', -- aeon t2 missile launcher
		--'UAL0307', -- aeon t2 shield
		'UAL0205', -- aeon t2 aa
		'URL0202', -- cybran t2 tank
		'URL0203', -- cybran t2 amphibious tank
		'URL0111', -- cybran t2 missile launcher
		--'URL0306', -- cybran t2 stealth
		'URL0205', -- cybran t2 aa
		'UEL0202', -- uef t2 tank
		'UEL0203', -- uef t2 amphibious tank
		'UEL0111', -- uef t2 missile launcher
		--'UEL0307', -- uef t2 shield
		'UEL0205', -- uef t2 aa	
		'DRL0204', -- cybran t2 rocket
		'DEL0204', -- uef t2 gatling
		'xal0203', -- aeon t2 assault tank
		'xsl0202', -- seraphim t2 assault bot
		'xsl0203', -- seraphim t2 hover tank
		'xsl0205', -- seraphim t2 anti air
		'xsl0111', -- seraphim t2 mobile missile
	},
	{ -- Wave Set 4
		'UAL0202', -- aeon t2 tank
		'UAL0111', -- aeon t2 missile launcher
		'UAL0307', -- aeon t2 shield
		'UAL0205', -- aeon t2 aa
		'URL0202', -- cybran t2 tank
		'URL0203', -- cybran t2 amphibious tank
		'URL0111', -- cybran t2 missile launcher
--		'URL0306', -- cybran t2 stealth
		'URL0205', -- cybran t2 aa
		'UEL0202', -- uef t2 tank
		'UEL0203', -- uef t2 amphibious tank
		'UEL0111', -- uef t2 missile launcher
		'UEL0307', -- uef t2 shield
		'UEL0205', -- uef t2 aa	
		'DRL0204', -- cybran t2 rocket
		'DEL0204', -- uef t2 gatling
		'xal0203', -- aeon t2 assault tank
		'xsl0202', -- seraphim t2 assault bot
		'xsl0203', -- seraphim t2 hover tank
		'xsl0205', -- seraphim t2 anti air
		'xsl0111', -- seraphim t2 mobile missile
	},
	{ -- Wave Set 5
		'UAL0202', -- aeon t2 tank
		'UAL0111', -- aeon t2 missile launcher
		'UAL0307', -- aeon t2 shield
		'UAL0205', -- aeon t2 aa
		'URL0202', -- cybran t2 tank
		'URL0203', -- cybran t2 amphibious tank
		'URL0111', -- cybran t2 missile launcher
--		'URL0306', -- cybran t2 stealth
		'URL0205', -- cybran t2 aa
		'UEL0202', -- uef t2 tank
		'UEL0203', -- uef t2 amphibious tank
		'UEL0111', -- uef t2 missile launcher
		'UEL0307', -- uef t2 shield
		'UEL0205', -- uef t2 aa	
		'DRL0204', -- cybran t2 rocket
		'DEL0204', -- uef t2 gatling
		'xal0203', -- aeon t2 assault tank
		'xsl0202', -- seraphim t2 assault bot
		'xsl0203', -- seraphim t2 hover tank
		'xsl0205', -- seraphim t2 anti air
		'xsl0111', -- seraphim t2 mobile missile

		'UAL0303', -- aeon t3 assault bot
		'URL0303', -- cybran t3 assault bot
		'UEL0303', -- uef t3 assault bot
		'xsl0303', -- seraphim t3 siege tank
	},
	{ -- Wave Set 6
		'UAL0111', -- aeon t2 missile launcher
		'UAL0307', -- aeon t2 shield
		'UAL0205', -- aeon t2 aa
		'URL0203', -- cybran t2 amphibious tank
		'URL0111', -- cybran t2 missile launcher
		'URL0306', -- cybran t2 stealth
		'URL0205', -- cybran t2 aa
		'UEL0203', -- uef t2 amphibious tank
		'UEL0111', -- uef t2 missile launcher
		'UEL0307', -- uef t2 shield
		'UEL0205', -- uef t2 aa	
		'DRL0204', -- cybran t2 rocket
		'DEL0204', -- uef t2 gatling
		'xal0203', -- aeon t2 assault tank
		'xsl0202', -- seraphim t2 assault bot
		'xsl0205', -- seraphim t2 anti air
		'xsl0111', -- seraphim t2 mobile missile

		'UAL0303', -- aeon t3 assault bot
		'URL0303', -- cybran t3 assault bot
		'UEL0303', -- uef t3 assault bot
		'xsl0303', -- seraphim t3 siege tank
		'UAL0303', -- aeon t3 assault bot
		'URL0303', -- cybran t3 assault bot
		'UEL0303', -- uef t3 assault bot
		'xsl0303', -- seraphim t3 siege tank
	},
	{ -- Wave Set 7
		'UAL0111', -- aeon t2 missile launcher
		'UAL0307', -- aeon t2 shield
		'UAL0205', -- aeon t2 aa
		'URL0111', -- cybran t2 missile launcher
		'URL0306', -- cybran t2 stealth
		'URL0205', -- cybran t2 aa
		'UEL0111', -- uef t2 missile launcher
		'UEL0307', -- uef t2 shield
		'UEL0205', -- uef t2 aa	
		'xsl0205', -- seraphim t2 anti air
		'xsl0111', -- seraphim t2 mobile missile

		'UAL0303', -- aeon t3 assault bot
		'URL0303', -- cybran t3 assault bot
		'UEL0303', -- uef t3 assault bot
		'xsl0303', -- seraphim t3 siege tank
		'UAL0303', -- aeon t3 assault bot
		'URL0303', -- cybran t3 assault bot
		'UEL0303', -- uef t3 assault bot
		'xsl0303', -- seraphim t3 siege tank

		'DAL0310', -- aeon shield disruptor
		'xal0305', -- aeon sniper bot
		'xel0306', -- uef t3 mobile missile platform
		'xsl0307', -- seraphim t3 mobile shield gen
		'xsl0305', -- seraphim t3 sniper bot
	},
	{ -- Wave Set 8
		'UAL0111', -- aeon t2 missile launcher
		'UAL0307', -- aeon t2 shield
		'UAL0205', -- aeon t2 aa
		'URL0111', -- cybran t2 missile launcher
		'URL0306', -- cybran t2 stealth
		'URL0205', -- cybran t2 aa
		'UEL0111', -- uef t2 missile launcher
		'UEL0307', -- uef t2 shield
		'UEL0205', -- uef t2 aa	
		'xsl0205', -- seraphim t2 anti air
		'xsl0111', -- seraphim t2 mobile missile

		'UAL0303', -- aeon t3 assault bot
		'URL0303', -- cybran t3 assault bot
		'UEL0303', -- uef t3 assault bot
		'xsl0303', -- seraphim t3 siege tank
		'UAL0303', -- aeon t3 assault bot
		'URL0303', -- cybran t3 assault bot
		'UEL0303', -- uef t3 assault bot
		'xsl0303', -- seraphim t3 siege tank

		'DAL0310', -- aeon shield disruptor
		'xal0305', -- aeon sniper bot
		'xel0306', -- uef t3 mobile missile platform
		'xsl0307', -- seraphim t3 mobile shield gen
		'xsl0305', -- seraphim t3 sniper bot

		'xrl0305', -- cybran t3 armored assault bot
		'xel0305', -- uef t3 armored assault bot
		'xel0306', -- uef t3 mobile missile platform
--		'URS0201', -- cybran salem class
	},
	{ -- Wave Set 9
		'UAL0307', -- aeon t2 shield
		'UAL0205', -- aeon t2 aa
		'URL0306', -- cybran t2 stealth
		'URL0205', -- cybran t2 aa
		'UEL0307', -- uef t2 shield
		'UEL0205', -- uef t2 aa	
		'xsl0205', -- seraphim t2 anti air

		'UAL0303', -- aeon t3 assault bot
		'URL0303', -- cybran t3 assault bot
		'UEL0303', -- uef t3 assault bot
		'xsl0303', -- seraphim t3 siege tank

		'DAL0310', -- aeon shield disruptor
		'xal0305', -- aeon sniper bot
		'xel0306', -- uef t3 mobile missile platform
		'xsl0307', -- seraphim t3 mobile shield gen
		'xsl0305', -- seraphim t3 sniper bot

		'xrl0305', -- cybran t3 armored assault bot
		'xel0305', -- uef t3 armored assault bot
		'xrl0305', -- cybran t3 armored assault bot
		'xel0305', -- uef t3 armored assault bot
		'xel0306', -- uef t3 mobile missile platform
--		'URS0201', -- cybran salem class
		'URS0201', -- cybran salem class
	},
	{ -- Wave Set 10
		'UAL0307', -- aeon t2 shield
		'UAL0205', -- aeon t2 aa
		'URL0306', -- cybran t2 stealth
		'URL0205', -- cybran t2 aa
		'UEL0307', -- uef t2 shield
		'UEL0205', -- uef t2 aa	
		'xsl0205', -- seraphim t2 anti air

		'DAL0310', -- aeon shield disruptor
		'xal0305', -- aeon sniper bot
		'xel0306', -- uef t3 mobile missile platform
		'xsl0307', -- seraphim t3 mobile shield gen
		'xsl0305', -- seraphim t3 sniper bot

		'xrl0305', -- cybran t3 armored assault bot
		'xel0305', -- uef t3 armored assault bot
		'xrl0305', -- cybran t3 armored assault bot
		'xel0305', -- uef t3 armored assault bot
		'xel0306', -- uef t3 mobile missile platform
		'URS0201', -- cybran salem class
		'URS0201', -- cybran salem class

		'UAL0301', -- aeon support commander
		'URL0301', -- cybran support commander 
		'UEL0301', -- uef support commander
		'xsl0301', -- seraphim support commander
	},
	{ -- Wave Set 11
		'UAL0307', -- aeon t2 shield
		'UAL0205', -- aeon t2 aa
		'URL0306', -- cybran t2 stealth
		'URL0205', -- cybran t2 aa
		'UEL0307', -- uef t2 shield
		'UEL0205', -- uef t2 aa	
		'xsl0205', -- seraphim t2 anti air

		'DAL0310', -- aeon shield disruptor
		'xal0305', -- aeon sniper bot
		'xel0306', -- uef t3 mobile missile platform
		'xsl0307', -- seraphim t3 mobile shield gen
		'xsl0305', -- seraphim t3 sniper bot

		'xrl0305', -- cybran t3 armored assault bot
		'xel0305', -- uef t3 armored assault bot
		'xrl0305', -- cybran t3 armored assault bot
		'xel0305', -- uef t3 armored assault bot
		'xel0306', -- uef t3 mobile missile platform
		'URS0201', -- cybran salem class
		'URS0201', -- cybran salem class

		'UAL0301', -- aeon support commander
		'URL0301', -- cybran support commander 
		'UEL0301', -- uef support commander
		'xsl0301', -- seraphim support commander
		'UAL0301', -- aeon support commander
		'URL0301', -- cybran support commander 
		'UEL0301', -- uef support commander
		'xsl0301', -- seraphim support commander

		'UAL0304', -- aeon t3 arty
		'URL0304', -- cybran t3 arty
		'UEL0304', -- uef t3 arty
		'xsl0304',	-- seraphim t3 heavy artillery
	},
};

local unitTableAirBS = {
	{ -- Wave Set 1
		-- t1
		'UAA0102',	-- aeon interceptor
		'URA0103',	-- cybran interceptor
		'UEA0102',	-- uef interceptor
		'xsa0102',	-- seraphim interceptor

		'xra0105', 	-- cybran t1 light gunship

		'UAA0103',	-- aeon t1 bomber
		'URA0103',	-- cybran bomber
		'UEA0103',	-- uef bomber
		'xsa0103',	-- seraphim bomber
	},
	{ -- Wave Set 2
		-- t1
		'UAA0102',	-- aeon interceptor
		'URA0103',	-- cybran interceptor
		'UEA0102',	-- uef interceptor
		'xsa0102',	-- seraphim interceptor

		'xra0105', 	-- cybran t1 light gunship

		'UAA0103',	-- aeon t1 bomber
		'URA0103',	-- cybran bomber
		'UEA0103',	-- uef bomber
		'xsa0103',	-- seraphim bomber

		-- t2
		'DRA0202',	-- cybran corsair
		'DEA0202',	-- uef janus
		'xaa0202', 	-- aeon t2 combat fighter
		'xsa0202',	-- seraphim fighter/bomber

		'UAA0203',	-- aeon gunship
		'URA0203',	-- cybran gunship
		'UEA0203',	-- uef gunship
		'xsa0203',	-- seraphim gunship
	},
	{ -- Wave Set 3
		-- t2
		'DRA0202',	-- cybran corsair
		'DEA0202',	-- uef janus
		'xaa0202', 	-- aeon t2 combat fighter
		'xsa0202',	-- seraphim fighter/bomber

		'UAA0203',	-- aeon gunship
		'URA0203',	-- cybran gunship
		'UEA0203',	-- uef gunship
		'xsa0203',	-- seraphim gunship
	},
	{ -- Wave Set 4
		-- t2
		'DRA0202',	-- cybran corsair
		'DEA0202',	-- uef janus
		'xaa0202', 	-- aeon t2 combat fighter
		'xsa0202',	-- seraphim fighter/bomber

		'UAA0203',	-- aeon gunship
		'URA0203',	-- cybran gunship
		'UEA0203',	-- uef gunship
		'xsa0203',	-- seraphim gunship

		-- t3
		'UEA0305',	-- uef t3 gunship
		'xra0305', 	-- cybran T3 gunship
	},
	{ -- Wave Set 5
		-- t2
		'DRA0202',	-- cybran corsair
		'DEA0202',	-- uef janus
		'xaa0202', 	-- aeon t2 combat fighter
		'xsa0202',	-- seraphim fighter/bomber

		-- t3
		'UEA0305',	-- uef t3 gunship
		'xaa0305', 	-- aeon T3 AA gunship
		'xra0305', 	-- cybran T3 gunship

		'UEA0305',	-- uef t3 gunship
		'xra0305', 	-- cybran T3 gunship
	},
	{ -- Wave Set 6
		-- t3
		'UAA0303',	-- aeon air superiority
		'URA0303',	-- cybran air superiority
		'UEA0303',	-- uef air superiority
		'xsa0303',	-- seraphim air superiority

		'UEA0305',	-- uef t3 gunship
		'xaa0305', 	-- aeon T3 AA gunship
		'xra0305', 	-- cybran T3 gunship

		'UEA0305',	-- uef t3 gunship
		'xra0305', 	-- cybran T3 gunship
	},
	{ -- Wave Set 7
		-- t3
		'UAA0303',	-- aeon air superiority
		'URA0303',	-- cybran air superiority
		'UEA0303',	-- uef air superiority
		'xsa0303',	-- seraphim air superiority

		'UEA0305',	-- uef t3 gunship
		'xaa0305', 	-- aeon T3 AA gunship
		'xra0305', 	-- cybran T3 gunship

		'UAA0303',	-- aeon air superiority
		'URA0303',	-- cybran air superiority
		'UEA0303',	-- uef air superiority
		'xsa0303',	-- seraphim air superiority

		'UEA0305',	-- uef t3 gunship
		'xaa0305', 	-- aeon T3 AA gunship
		'xra0305', 	-- cybran T3 gunship

		'UAA0304',	-- aeon t3 bomber
		'URA0304',	-- cybran t3 bomber
		'UEA0304',	-- uef t3 bomber
		'xsa0304',	-- seraphim bomber
	},
};

local unitTableTimesBS = {
	{ -- ground
		'0', -- 0m 0
		'240', -- 4m 1
		'480', -- 8m 2
		'720', -- 12m 3
		'960', -- 16m 4
		'1200', -- 20m 5
		'1440', -- 24m 6
		'1680', -- 28m 7
		'1920', -- 32m 8
		'2160', -- 36m 9
		'2400', -- 40m 10
	},
	{ -- air
		'0', -- 0m 1
		'420', -- 7m 2
		'840', -- 14m 3
		'1260', -- 21m 4
		'1680', -- 28m 5
		'2100', -- 35m 6
		'2520', -- 42m 7
--		'0', -- 0m 0
--		'120', -- 2m 1
--		'600', -- 10m 2
--		'1080', -- 18m 3
--		'1560', -- 26m 4
--		'2040', -- 34m 5
	},
};

-- upgrades list for SCU's
local upgradeTable = {
	-- aeon
	A={
		'Shield',
		'ShieldHeavy',
		'StabilitySuppressant',
		'SystemIntegrityCompensator',
		},
	-- cybran
	R={
		'CloakingGenerator',
		'EMPCharge',
		'FocusConvertor',
		'NaniteMissileSystem',
		'SelfRepairSystem',
		'StealthGenerator', -- NOTE requires cloaking generator first
		},
	-- uef
	E={
		'AdvancedCoolingUpgrade',
		'HighExplosiveOrdnance',
		'RadarJammer',
		'Shield',
		'ShieldGeneratorField',
		},
	-- seraphim
	S={
		'DamageStabilization',
		'Missile',
		'Overcharge',
		'Shield',
		},
};

-- defines possible formations for the units
local formationTable = {
	'AttackFormation',
	'GrowthFormation',
	'SixWideFormation',
	'TravellingFormation',
};

setupGame = function()
	ScenarioInfo.Options.Victory = 'sandbox'; 			-- custom victory condition
	-- misc settings
	Utilities.UserConRequest("ui_ForceLifbarsOnEnemy");	--show enemy life bars

	-- setup army specific things
	for i, army in ListArmies() do
		if (army == "ARMY_1" or army == "ARMY_2" or army == "ARMY_3" or army == "ARMY_4") then 
			-- restrict players from building walls
			ScenarioFramework.AddRestriction(army, categories.WALL);
			-- set alliances
			SetAlliance(army, "ARMY_SURVIVAL_ENEMY", 'Enemy'); 
			SetAlliance(army, "ARMY_SUPERWEAPON", 'Ally'); 
			SetAlliedVictory(army, true); 
			-- set alliance with all other hill players!
			for j, army2 in ListArmies() do
				if (army2 == "ARMY_1" or army2 == "ARMY_2" or army2 == "ARMY_3" or army2 == "ARMY_4") then 
					SetAlliance(army, army2, 'Ally'); 
				end
			end			
		end
	end

	-- spawnwaves and superweapon are enemies
	SetAlliance("ARMY_SURVIVAL_ENEMY", "ARMY_SUPERWEAPON", 'Enemy'); 
	-- spawnwaves don't have a unit cap
	SetIgnoreArmyUnitCap('ARMY_SURVIVAL_ENEMY', true);

-- set difficulty options
	if (ScenarioInfo.Options.opt_difficulty == 1) then
		HealthBuff = 0.25;
	else
		HealthBuff = ((ScenarioInfo.Options.opt_difficulty - 1) / 2); -- 1/4 to 4x hp
	end

	HealthBuffAir = ScenarioInfo.Options.opt_difficulty / 3; -- 1/3 to 3x hp

	UnitCountMult = 5 + (ScenarioInfo.Options.opt_difficulty * 5);

	-- spawn the gates
	spawnGates();
	spawnScathis();
	
-- spawn the defense object

	local object = nil;

	if (ScenarioInfo.Options.opt_defenseObject > 1) then
	
		-- no object
		if (ScenarioInfo.Options.opt_defenseObject == 2) then
			-- black sun default
			local object = "UEC1902";
		end

		-- mavor
		if (ScenarioInfo.Options.opt_defenseObject == 3) then
			object = "UEB2401";
		end

		-- aeon rapid fire arty
		if (ScenarioInfo.Options.opt_defenseObject == 4) then
			object = "XAB2307";
		end

		if (object != nil) then
			local pos = ScenarioUtils.MarkerToPosition("HILL_CENTER");
			local def = CreateUnitHPR( object, "ARMY_SUPERWEAPON", pos[1], pos[2], pos[3], 0,0,0);
			def:SetReclaimable(false);
			def:SetCapturable(false);
			def:SetProductionPerSecondEnergy(99999);

			if (ScenarioInfo.Options.opt_defenseObject > 2) then
				local wp = def:GetWeapon(1);

				if (wp != nil) then
					--local RangeBuff = 375 - (ScenarioInfo.Options.opt_difficulty * 25);
					local RangeBuff = 368.75 - (ScenarioInfo.Options.opt_difficulty * 18.75); -- 200 to 350
					wp:ChangeMaxRadius(RangeBuff); -- 300
					wp:ChangeMinRadius(150); -- 100 too short

				-- speed mod
					wp.TurretPitchSpeed = 6;
					wp.TurretYawSpeed = 9;
				end
			end
		
			-- set onkilled function
			def.OldOnKilled = def.OnKilled;
			def.OnKilled = function(self, instigator, type, overkillRatio)
				--spawn a nuke
				nuke(self:GetPosition());

				msgOut("The defense object has been destroyed. You have lost!");
				self.OldOnKilled(self, instigator, type, overkillRatio);

				loopEnd = true;
				gameEnd = true;
				for i, army in ListArmies() do
					if (army == "ARMY_1" or army == "ARMY_2" or army == "ARMY_3" or army == "ARMY_4") then
					killAllCommanders(army);
					GetArmyBrain(army):OnDefeat();
					end
				end
			end	

			-- adjust health of defense object based on difficulty
			local DefHealth = 19500 - (ScenarioInfo.Options.opt_difficulty * 2000); -- 1500 to 17500
			def:SetMaxHealth(DefHealth);
			def:SetHealth(nil, (DefHealth)); --100000 * HealthBuff
		end
	end
end

-- spawns 8 scathis at edge of map to prevent players from building outside of hill
spawnScathis = function()
-- mod
	local RangeBuff = 275 + (ScenarioInfo.Options.opt_difficulty * 25); -- 300 to 500
	local ScathisHealth = ScenarioInfo.Options.opt_difficulty * 4000; -- 4000 - 36000

	for i = 1,8 do
		local scName = "SCATHIS"..i;
		local pos = ScenarioUtils.MarkerToPosition(scName);
		local sc = CreateUnitHPR( 'url0401', "ARMY_SURVIVAL_ENEMY", pos[1], pos[2], pos[3], 0,0,0);

--		local NovaxID = 'xea0002';
--		local NovaxBP = GetUnitBlueprintByName(NovaxID);
--		local OldNovaxBP = NovaxBP;
--		NovaxBP.Defense.MaxHealth = 100000;
--		NovaxBP.Weapon[1].MaxRadius = RangeBuff;
--		NovaxBP.Weapon[1].MinRadius = 150;
--		NovaxBP.Weapon[1].BeamLifetime = 1;
--		NovaxBP.Weapon[1].RateOfFire = 1;
--		NovaxBP.Weapon[1].NeedPrep = false;
		
		
--		local pos = ScenarioUtils.MarkerToPosition("HILL_CENTER");
--		local sc = CreateUnitHPR( 'xea0002', "ARMY_SURVIVAL_ENEMY", pos[1], pos[2], pos[3], 0,0,0);
--		local sc = CreateUnitHPR(NovaxID, "ARMY_SURVIVAL_ENEMY", pos[1], pos[2], pos[3], 0,0,0);
--		NovaxBP = OldNovaxBP;

		sc:SetReclaimable(false);
		sc:SetCapturable(false);
		sc:SetProductionPerSecondEnergy(99999);
-- mod here
	-- novax mods
--		sc:SetSpeedMult(0.0);
--		local novaxbp = sc:GetBlueprint();
--		novaxbp.Physics.RotateOnSpot = true;
--		novaxbp.Air.MaxAirSpeed = 0;
--		novaxbp.Physics.MaxSpeed = 0;
--		novaxbp.Physics.MinSpeedPercent = 0;
--		novaxbp.Physics.TurnRadius = 0;
--		novaxbp.Physics.MotionType = 'RULEUMT_None';
--		novaxbp.Air.KLift = 100;
--		novaxbp.Air.KLiftDamping = 1;
--		novaxbp.Air.KMove = 0;
--		novaxbp.Air.KMoveDamping = 1;
--		novaxbp.Air.KTurn = 1;
--		novaxbp.Air.KTurnDamping = 1;
--		novaxbp.Air.LiftFactor = 100;
--		novaxbp.Air.StartTurnDistance = 0;

		sc:SetIntelRadius('Radar', (RangeBuff + 25)); --400);
		local wp = sc:GetWeapon(1);
		wp:ChangeMinRadius(100);
		wp:ChangeMaxRadius(RangeBuff); -- 300
--		wp.BeamCollisionDelay = 0.25;
--		wp.BeamLifetime = 2;
--		wp.RateOfFire = 0.33;
--		wp.NeedPrep = false;
--		wp.TurretPitchRange = 360;
--		wp.TurretPitchSpeed = 720;
--		wp.TurretYawRange = 360;
--		wp.TurretYawSpeed = 720;
--		novaxbp.Weapon[1].BeamCollisionDelay = 0.25;
--		novaxbp.Weapon[1].BeamLifetime = 2;
--		novaxbp.Weapon[1].RateOfFire = 0.33;
--		novaxbp.Weapon[1].NeedPrep = false;
--		novaxbp.Weapon[1].TurretPitchRange = 360;
--		novaxbp.Weapon[1].TurretPitchSpeed = 720;
--		novaxbp.Weapon[1].TurretYawRange = 360;
--		novaxbp.Weapon[1].TurretYawSpeed = 720;



	-- modding here
		--wp.WeaponRepackTimeout = 100000;
--		sc:SetSpeedMult(0);
--		wp.WeaponUnpackLocksMotion = true;
--		wp.WeaponUnpacks = true;

--		wp.NeedPrep = false;
--		wp.MaximumBeamLength = RangeBuff + 200;
--		wp.DamageFriendly = false;

		sc:SetMaxHealth(ScathisHealth);
		sc:SetHealth(nil, (ScathisHealth)); --100000 * HealthBuff
-- remove scathis wreckage issue
		local bpw = sc:GetBlueprint();
		if (bpw != nil) then
			bpw.Wreckage = nil; -- bp.Wreckage.WreckageLayers.Land=false;
		end
		
		-- set onkilled function
		sc.OldOnKilled = sc.OnKilled;
		sc.OnKilled = function(self, instigator, type, overkillRatio)
			--spawn a nuke
			nuke(self:GetPosition());

			-- add points to player
			local instArmy = instigator:GetArmy();
			local armyName = ArmyIndexer(GetArmyBrain(instArmy));
			LOG("___SE___ scathis killed, instigator army: "..instArmy.."/"..armyName);
			killCount[armyName] = killCount[armyName] + 1;
			
			-- handle game logic
			msgOut("A scathis was destroyed by " .. getUsername(instArmy) .. "!");
			self.OldOnKilled(self, instigator, type, overkillRatio);
		end
	end
end

spawnGates = function()
	-- spawn gates at the outer edges for enemy units to teleport in
	-- 8 gates have to be destroyed
	numGatesOpen = 8;
	for i = 1,8 do
		if (gates[i] == nil) then
			local gateName = "Gate"..i;
			local pos = ScenarioUtils.MarkerToPosition(gateName);
			local r = Utilities.GetRandomInt(1,4);
			local gateFaction;
			if (r == 1) then
				gateFaction = 'UAB0304';
			elseif (r == 2) then
				gateFaction = 'URB0304';
			elseif (r == 3) then
				gateFaction = 'UEB0304';
			else
				gateFaction = 'XSB0304';
			end
			gates[i] = CreateUnitHPR( gateFaction, "ARMY_SURVIVAL_ENEMY", pos[1], pos[2], pos[3], 0,0,0);
-- mod here
			local GateHealth = 250000;

			if (ScenarioInfo.Options.opt_difficulty < 9) then
				GateHealth = 25000 * ScenarioInfo.Options.opt_difficulty;
			end

			gates[i]:SetMaxHealth(GateHealth);
			gates[i]:SetHealth(nil, (GateHealth)); --100000 * HealthBuff
			--gates[i]:SetMaxHealth(500000);
			--gates[i]:SetHealth(nil, 500000);
			gates[i]:SetReclaimable(false);
			gates[i]:SetCapturable(false);
			gates[i]:SetProductionPerSecondEnergy(99999);

			-- remove gate wreckage
			local bpw = gates[i]:GetBlueprint();
			if (bpw != nil) then
				bpw.Wreckage = nil; -- bp.Wreckage.WreckageLayers.Land=false;
			end
			
			-- set gate onkilled function
			gates[i].OldOnKilled = gates[i].OnKilled;
			gates[i].myID = i;
			gates[i].OnKilled = function(self, instigator, type, overkillRatio)
				--spawn a nuke
				nuke(self:GetPosition());

				-- add points to player
				local instArmy = instigator:GetArmy();
				local armyName = ArmyIndexer(GetArmyBrain(instArmy));
				LOG("___SE___ gate killed, id="..self.myID.." instigator army: "..instArmy.."/"..armyName);
				killCount[armyName] = killCount[armyName] + 1;
				
				-- handle game logic
				numGatesOpen = numGatesOpen - 1;
				msgOut("A gate was destroyed by " .. getUsername(instArmy) .. "! "..numGatesOpen.. " gates left.");
				gates[self.myID] = nil;
				self.OldOnKilled(self, instigator, type, overkillRatio);
				if (numGatesOpen < 1) then
					msgOut("All gates were destroyed!");
				end
			end
		end
	end
end

gameLogic = function()
	-- check if all gates and specials were destroyed
	if (numGatesOpen < 1) then
		-- all gates down, display victory and end game
		for i, army in ListArmies() do
			if (army == "ARMY_1" or army == "ARMY_2" or army == "ARMY_3" or army == "ARMY_4" or
			    army == "ARMY_5" or army == "ARMY_6" or army == "ARMY_7" or army == "ARMY_8") then
				GetArmyBrain(army):OnVictory();
			end
		end
		GetArmyBrain("ARMY_SURVIVAL_ENEMY"):OnDefeat();
		gameEnd = true;
	end
end

spawnThread = function(self)
	LOG("___SE___ Spawn thread running!");
	-- wait before starting the unit spam
	local startupTime = ScenarioInfo.Options.opt_startupTime;
	local now = 1;

	LOG("___SEBS___ spawnThread: " .. startupTime .. now);
--	if (startupTime > 0) then
		while (now < startupTime) do
			now = GetGameTimeSeconds();
			local rest = startupTime - now;
			if (rest < 0) then rest = 0; end
			Sync.ObjectiveTimer = math.floor(rest);
			WaitSeconds(1);
		end
--	end
	Sync.ObjectiveTimer = 0;
	
	msgOut("Attack waves have spawned!");

-- the waves start at id 1
-- the while loop repeats every spawn interval to spawn a new wave

	-- set the default waves to 1
	local groundwaveid = 1;
	local airwaveid = 1;

	-- loop each wave interval to spawn a new set of waves
	while (gameEnd == false) do

		-- first figure out which wave sets to spawn
		now = GetGameTimeSeconds(); -- get the game time
		timetolerance = 5; -- tolerance because this tends to loop several seconds before the actual time, resulting in delayed wave sets

	-- check game time vs wave times to figure out which wave sets we are on

		local groundtimes = unitTableTimesBS[1];

--		LOG("___SEBS___ groundtimes: " .. now .. "   " .. table.getn(groundtimes) .. "   " .. groundtimes[1]);

		for i = groundwaveid, table.getn(groundtimes) do -- loop through remaining ground waves
			if ((now + timetolerance ) >= tonumber(groundtimes[i])) then -- if the current time is past the time for this wave...
				groundwaveid = i; -- update the ground wave
			else -- if the next wave time hasn't been reached we can break the loop
				break -- break the loop 
			end
		end

		local airtimes = unitTableTimesBS[2];

		for i = airwaveid, table.getn(airtimes) do -- loop through remaining ground waves
			if ((now + timetolerance) >= tonumber(airtimes[i])) then -- if the current time is past the time for this wave...
				airwaveid = i; -- update the ground wave
			else -- if the next wave time hasn't been reached we can break the loop
				break -- break the loop 
			end
		end

	-- now that we know which ground and air waves to spawn...

		-- spawn some waves
		spawnWaveBS(groundwaveid, airwaveid);
--		spawnAirWaveBS(airwaveid);

	-- now wait for next wave time

		-- wait for next wave
		local waitTime = ScenarioInfo.Options.opt_waveTime;
--		LOG("___SEBS___ waveTimes: " .. ScenarioInfo.Options.opt_waveTime .. waitTime);
		WaitSeconds(waitTime);

--		spawnWaves();
		-- at loop end spawn the special weapons, and wait 2 minutes
--		if (gameEnd == false) then
--			WaitSeconds(60*2);
--		end
	end
	--no more waves to send, kill thread
	KillThread(self);
end

spawnWaveBS = function(gwaveid, awaveid)
	
	LOG("___SE___ spawning waves: G" .. gwaveid .. " A" .. awaveid);

	--AirCount = UnitCountMult / (11 - gwaveid); -- increase amount of planes with each GROUND wave (since this happens more frequently)

	-- air count should range from 40% to 100% of the ground count based on time with 45 minutes being max
	AirCount = UnitCountMult * (0.3 + (0.7 * (GetGameTimeSeconds() / 2700)));

	AirFreqCount = AirFreqCount + 1; -- increment air frequency counter

	if (AirFreqCount == ScenarioInfo.Options.opt_airFrequency) then
		AirFreqCount = 0;
	end

	--spawn one wave per player
	for i = 1,playercount do
		spawnwave(unitTableGroundBS[gwaveid], UnitCountMult);

		if (AirFreqCount == 0) then
			spawnwave(unitTableAirBS[awaveid], AirCount);
		end
	end
end

-- used to calculate a spawn position
CalcSpawnPos = function()

	-- if no more gates are open, do nothing
	if (numGatesOpen == 0)	then
		return nil;
	end	

	-- try to fetch a random gate and it's position
	local pos = nil;	-- position of the gate
	local tryCount = 0;	-- don' try more than 8 times, as there are only 8 gates
	local r = Utilities.GetRandomInt(1,8);	-- start with a random gate

	while (true) do
		local gateName = "Gate"..r;

		if (gates[r] != nil) then
			pos = ScenarioUtils.MarkerToPosition(gateName);
			return pos; --break;	-- we found a valid gate
		end

		-- gate is already dead, increase trycount
		tryCount = tryCount + 1;

		if (tryCount > 8) then 	-- no open gates. stop trying.
			return nil;
		end

		-- try next gate
		r = r + 1;

		if (r > 8) then
			r = 1;
		end
	end

	return pos;
end

-- figure out what to spawn and where
spawnwave = function(spawntable, spawncount, groundorair)
	-- if no more gates are open, do nothing
	if (numGatesOpen == 0)	then return; end	
	
	-- try to fetch a random gate and it's position
	local pos = nil;	-- position of the gate
	local tryCount = 0;	-- don' try more than 8 times, as there are only 8 gates
	local r = Utilities.GetRandomInt(1,8);	-- start with a random gate
	while (true) do
		local gateName = "Gate"..r;
		if (gates[r] != nil) then
			pos = ScenarioUtils.MarkerToPosition(gateName);
			break;	-- we found a valid gate
		end
		-- gate is already dead, increase trycount
		tryCount = tryCount + 1;
		if (tryCount > 8) then 	-- no open gates. stop trying.
			return;
		end
		-- try next gate
		r = r + 1;
		if (r > 8) then
			r = 1;
		end
	end

	-- make sure gate was found
	if (pos == nil) then
		LOG("___SE___ error: trying to spawn at nil gate");
		return;
	end

	local spawnList = {}; -- empty spawn list

	local bpCount = table.getn(spawntable); -- how many unit types are available in this wave set

	-- pull a random entry from the available units table and add it to the spawning table
	-- repeat for as many units as we will spawn
	for c = 1, spawncount do
		local rr = Utilities.GetRandomInt(1, bpCount);
		table.insert(spawnList, spawntable[rr]);
	end

	-- create an empty array to combine spawned units to one platoon
	local platoonUnits = {};

	-- iterate through the blueprint-list we have just generated and spawn the units
	for index, bp in spawnList do
		if (groundorair == 1) then
			doSpawnUnit(bp, pos, platoonUnits, HealthBuff);
		else
			doSpawnUnit(bp, pos, platoonUnits, HealthBuffAir);
		end
			
	end

	--give attack order
	startAttackMove(platoonUnits);
end

-- does the actual spawning of a unit
doSpawnUnit = function(bp, pos, platoon, hpbuff)
	--calculate offset position of unit
	local xside = math.random(0,1);
	local yside = math.random(0,1);
	local xoff = -10 + xside*16 + math.random(0,1)*4;
	local yoff = -10 + yside*16 + math.random(0,1)*4;

	-- spawn unit
	local unit = CreateUnitHPR( bp, "ARMY_SURVIVAL_ENEMY", pos[1]+xoff, pos[2], pos[3]+yoff, 0,0,0);		
	if (unit == nil) then
		return;
	end
	-- no wreckages after first round (to speed up game, can be removed when we all have quadcores/octacores ;=)
--	if (loop > 0) then
		local bp = unit:GetBlueprint();
		if (bp != nil) then
			bp.Wreckage = nil; -- bp.Wreckage.WreckageLayers.Land=false;
		end
--	end

	-- insert to platoon list
	table.insert(platoon, unit); 
	
	-- check for upgrades
	local skip = Utilities.GetRandomInt(1, 4);
	if (skip != 3) then	-- one out of four commanders has no upgrades
		if (bp == "UAL0301") then		-- aeon
			local ucnt = table.getn(upgradeTable["A"]);
			local enh = upgradeTable["A"][Utilities.GetRandomInt(1, ucnt)];
			unit:CreateEnhancement(enh);
		elseif (bp == "URL0301") then	-- cybran
			local ucnt = table.getn(upgradeTable["R"]);
			local enh = upgradeTable["R"][Utilities.GetRandomInt(1, ucnt)];
			if (enh == 'StealthGenerator') then	-- stealth needs cloaking first, bug in game
				unit:CreateEnhancement('CloakingGenerator');
			end
			unit:CreateEnhancement(enh);
		elseif (bp == "UEL0301") then	-- uef
			local ucnt = table.getn(upgradeTable["E"]);
			local enh = upgradeTable["E"][Utilities.GetRandomInt(1, ucnt)];
			unit:CreateEnhancement(enh);
		elseif (bp == "xsl0301") then	-- seraphim
			local ucnt = table.getn(upgradeTable["S"]);
			local enh = upgradeTable["S"][Utilities.GetRandomInt(1, ucnt)];
			unit:CreateEnhancement(enh);
		end
	end
	
	--apply buffs based on  difficulty
	unit:SetMaxHealth(unit:GetHealth() * hpbuff);
	unit:SetHealth(nil, unit:GetHealth() * hpbuff);

	--local difficultyBuff = ScenarioInfo.Options.opt_difficulty;
	--unit:SetMaxHealth(unit:GetHealth()*difficultyBuff);
	--unit:SetHealth(nil, unit:GetHealth()*difficultyBuff);
end


--forms a platoon to attack the hill with a given set of units
startAttackMove = function(units)	
	if (table.getn(units) > 0) then
		local aiBrain = GetArmyBrain("ARMY_SURVIVAL_ENEMY");
		local attackPlatoon = aiBrain:MakePlatoon('','');
		local fcnt = table.getn(formationTable);
		local formation = formationTable[Utilities.GetRandomInt(1, fcnt)];
		aiBrain:AssignUnitsToPlatoon(attackPlatoon, units, 'Attack', formation);
		-- add a random waypoint
		local r = Utilities.GetRandomInt(1,8);
		local waypointName = "WP"..r;
		local posWP = ScenarioUtils.MarkerToPosition(waypointName);
		attackPlatoon:AggressiveMoveToLocation(posWP);

		local posCENTER = ScenarioUtils.MarkerToPosition('HILL_CENTER');
		attackPlatoon:AggressiveMoveToLocation(posCENTER);
	end
end


------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- misc funcs
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-- spawn acu and kill it to create a fake nuke explosion :=) *hack hack hack, but the gpg devs said it's easiest way atm*
nuke = function(position)
	local acu = CreateUnitHPR( "ual0001", "ARMY_SURVIVAL_ENEMY", position[1], position[2], position[3], 0,0,0);
	if (acu != nil) then
		acu:Kill();
	end
end

-- kills all commanders of a specified army
killAllCommanders = function(army)
	local list = GetArmyBrain(army):GetListOfUnits(categories.COMMAND , false);
	for i, u in list do
		if (u:IsDead() == false) then
			u:Kill();
		end
	end
end


--given a player returns a proper username
getUsername = function(army)
	return GetArmyBrain(army).Nickname;
end

--given an ai brain returns an army index
function ArmyIndexer(aiBrain)
	local army = aiBrain:GetArmyIndex();
	for i, v in ListArmies() do
		if (i == army) then
			return v;
		end
	end
end

--given a player returns the number of kills
--armyKills = function(army)
--	local kills = GetArmyBrain(army):GetArmyStat('Enemies_Killed',0.0).Value;
--	return kills;
--end

armyKills = function(brain)
	local kills = brain:GetArmyStat('Enemies_Killed',0.0).Value;
	return kills;
end

-- display mm:ss instead of seconds
secondsToTime = function(seconds)
	return string.format("%02d:%02d", math.floor(seconds/60), math.mod(seconds, 60));
end

-- display a text message
msgOut = function(text, army)
	local color = nil;
	if (army != nil) then
		local colorIndex = ScenarioInfo.ArmySetup[army].PlayerColor;
		color = import('/lua/GameColors.lua').GameColors.ArmyColors[colorIndex];
	end
	PrintText(text, 20, color, 10, 'center') ;	
end

--EOF