-- Star Wars Empire at War: Secrets of a Fallen Empire
-- Lua Script: //Scripts/GameObject/ObjectScript_MineLayer.lua
-- Author: Galyana
-- Updated: 1 November, 2023

require("PGBase")
require("PGStateMachine")

function Definitions()
	ServiceRate = 1

	Define_State("State_Init", State_Init);
	Define_State("State_AI_Autofire", State_AI_Autofire)
	Define_State("State_Human_No_Autofire", State_Human_No_Autofire)
	Define_State("State_Human_Autofire", State_Human_Autofire)

	ability_name = "DEPLOY_SQUAD"
	-- DEPLOY_SQUAD cannot be force activated via .Activate_Ability()
	-- Object.Activate_Ability(ability_name, true)
	
	-- Prevent stacking minefields too close to each other
	unit_prox_range = 200
	unit_trigger_number = 1
end

function State_Init(message)
	if message == OnEnter then
		-- prevent this from doing anything in galactic mode
		if Get_Game_Mode() ~= "Space" then
			ScriptExit()
		end
		
		faction = Object.Get_Owner().Get_Faction_Name()

		if faction == "REBEL" then 
			ref_type = Find_Object_Type("Rebel_Minefield")
		elseif faction == "EMPIRE" then 
			ref_type = Find_Object_Type("Empire_Minefield")
		elseif faction == "UNDERWORLD" then 
			ref_type = Find_Object_Type("Underworld_Minefield")
		elseif faction == "HUTTS" then 
			ref_type = Find_Object_Type("Hutt_Minefield")
		else
			-- Unknown faction, abort
			ScriptExit()
		end
	
		Register_Prox(Object, Unit_Prox, unit_prox_range)
		nearby_minefield_count = 0
		recent_minefield_units = {}

		if Object.Get_Owner().Is_Human() then
			Set_Next_State("State_Human_No_Autofire")
		else
			-- AI does not use Deploy Squadron ability to spawn minefields
			-- Disable hangar minefields and only use scripted spawning for AI
			Object.Set_Garrison_Spawn(false)
			Set_Next_State("State_AI_Autofire")
		end
	end
end

function State_AI_Autofire(message)
	if message == OnUpdate then
		if nearby_minefield_count >= unit_trigger_number then
			-- move to a new random location
			x,y,z = Object.Get_Position().Get_XYZ()
			pos = Create_Position((x + GameRandom(-500, 500)), (y + GameRandom(-500, 500)), z)
			Object.Move_To(pos)
			Sleep(10)
		elseif unit_trigger_number > nearby_minefield_count then
			if Object.Is_Ability_Ready(ability_name) then
				-- spawn a generic minefield without respect to hangar capacity
				position = Object.Get_Position()
				player = Object.Get_Owner()
				Create_Generic_Object(ref_type, position, player)
				Object.Force_Ability_Recharge(ability_name)

				-- move to a new random location
				x,y,z = Object.Get_Position().Get_XYZ()
				pos = Create_Position((x + GameRandom(-500, 500)), (y + GameRandom(-500, 500)), z)
				Object.Move_To(pos)
				Sleep(20)
			end
		end

		nearby_minefield_count = 0
		recent_minefield_units = {}
	end
end

function State_Human_No_Autofire(message)
	if message == OnUpdate then
		if Object.Is_Ability_Autofire(ability_name) then
			Set_Next_State("State_Human_Autofire")
		end
	end
end

function State_Human_Autofire(message)
	if message == OnUpdate then
		if Object.Is_Ability_Autofire(ability_name) then
			if nearby_minefield_count >= unit_trigger_number then
				-- move to a new random location
				x,y,z = Object.Get_Position().Get_XYZ()
				pos = Create_Position((x + GameRandom(-500, 500)), (y + GameRandom(-500, 500)), z)
				Object.Move_To(pos)
				Sleep(10)
			elseif unit_trigger_number > nearby_minefield_count then	
				if Object.Is_Ability_Ready(ability_name) then
					-- spawn a generic minefield without respect to hangar capacity
					position = Object.Get_Position()
					player = Object.Get_Owner()
					Create_Generic_Object(ref_type, position, player)
					Object.Force_Ability_Recharge(ability_name)

					-- move to a new random location
					x,y,z = Object.Get_Position().Get_XYZ()
					pos = Create_Position((x + GameRandom(-500, 500)), (y + GameRandom(-500, 500)), z)
					Object.Move_To(pos)
					Sleep(20)
				end
			end
		else
			Set_Next_State("State_Human_No_Autofire")
		end

		nearby_minefield_count = 0
		recent_minefield_units = {}
	end
end

function Unit_Prox(self_obj, trigger_obj)
	if not trigger_obj.Get_Type() == ref_type then
		return
	end

	-- If we haven't seen this unit recently, track him
	if recent_minefield_units[trigger_obj] == nil and trigger_obj.Get_Type() == ref_type then
		nearby_minefield_count = nearby_minefield_count + 1
		recent_minefield_units[trigger_obj] = trigger_obj
	end
end