1require "common"
2
3local DebugEnabled = false
4
5local function EchoDebug(inStr)
6	if DebugEnabled then
7		game:SendToConsole("ScoutHandler: " .. inStr)
8	end
9end
10
11ScoutHandler = class(Module)
12
13function ScoutHandler:Name()
14	return "ScoutHandler"
15end
16
17function ScoutHandler:internalName()
18	return "scouthandler"
19end
20
21function ScoutHandler:Init()
22	self.spotsToScout = {}
23	self.lastCount = {}
24	self.sameCount = {}
25	self.usingStarts = {}
26end
27
28function ScoutHandler:ScoutLos(scoutbehaviour, position)
29	local los
30	if ai.maphandler:IsUnderWater(position) and unitTable[scoutbehaviour.name].sonarRadius == 0 then
31		-- treat underwater spots as surface spots if the scout has no sonar, so that it moves on
32		local lt = ai.loshandler:AllLos(position)
33		if lt[2] then
34			los = 2
35		else
36			los = 0
37		end
38	else
39		los = ai.loshandler:GroundLos(position)
40	end
41	return los
42end
43
44function ScoutHandler:ClosestSpot(scoutbehaviour)
45	local unit = scoutbehaviour.unit:Internal()
46	local position = unit:GetPosition()
47	local mtype = scoutbehaviour.mtype
48	if mtype == nil then mtype = "air" end
49	if network == nil then network = 1 end
50	-- initializing the necessary tables if they're not yet
51	if self.spotsToScout[mtype] == nil then self.spotsToScout[mtype] = {} end
52	if self.spotsToScout[mtype][network] == nil then self.spotsToScout[mtype][network] = {} end
53	if self.usingStarts[mtype] == nil then self.usingStarts[mtype] = {} end
54	if self.usingStarts[mtype][network] == nil then self.usingStarts[mtype][network] = false end
55	if self.lastCount[mtype] == nil then self.lastCount[mtype] = {} end
56	if self.lastCount[mtype][network] == nil then self.lastCount[mtype][network] = 0 end
57	if self.sameCount[mtype] == nil then self.sameCount[mtype] = {} end
58	if self.sameCount[mtype][network] == nil then self.sameCount[mtype][network] = 0 end
59	-- filling table of spots to scout if empty
60	if #self.spotsToScout[mtype][network] == 0 then
61		if not self.usingStarts[mtype][network] then
62			if ai.startLocations[mtype] ~= nil then
63				if ai.startLocations[mtype][network] ~= nil then
64					-- scout all probable start locations first
65					EchoDebug(unit:Name() .. " got starts")
66					for i, p in pairs(ai.startLocations[mtype][network]) do
67						table.insert(self.spotsToScout[mtype][network], p)
68					end
69				end
70			end
71			-- true even if no start locations were in network, so that it moves onto using metals/geos next
72			self.usingStarts[mtype][network] = true
73		elseif self.usingStarts[mtype][network] then
74			-- then use metal and geo spots
75			EchoDebug(unit:Name() .. " got metals and geos")
76			for i, p in pairs(ai.scoutSpots[mtype][network]) do
77				table.insert(self.spotsToScout[mtype][network], p)
78			end
79			self.usingStarts[mtype][network] = false
80		end
81	end
82	EchoDebug(mtype .. " " .. network .. " has " .. #self.spotsToScout[mtype][network] .. " spots")
83	-- find the closest spot
84	local pos = nil
85	local index = nil
86	local bestDistance = 10000
87	for i, p in ipairs(self.spotsToScout[mtype][network]) do
88		local los
89		if ai.maphandler:IsUnderWater(p) and unitTable[scoutbehaviour.name].sonarRadius == 0 then
90			-- treat underwater spots as surface spots if the scout has no sonar, so that it moves on
91			local lt = ai.loshandler:AllLos(p)
92			if lt[2] then
93				los = 2
94			else
95				los = 0
96			end
97		else
98			los = ai.loshandler:GroundLos(p)
99		end
100		if los == 2 or los == 3 or not ai.targethandler:IsSafePosition(p, unit, 1) then
101			table.remove(self.spotsToScout[mtype][network], i)
102		else
103			local dist = Distance(position, p)
104			if dist < bestDistance then
105				bestDistance = dist
106				pos = p
107				index = i
108			end
109		end
110	end
111	-- make sure we're not getting quixotic
112	if #self.spotsToScout[mtype][network] == self.lastCount[mtype][network] then
113		self.sameCount[mtype][network] = self.sameCount[mtype][network] + 1
114		if self.sameCount[mtype][network] > 15 then
115			-- if the last spots can't be scouted for some reason, just clear the list to repopulate it
116			self.spotsToScout[mtype][network] = {}
117		end
118	else
119		self.sameCount[mtype][network] = 0
120	end
121	self.lastCount[mtype][network] = #self.spotsToScout[mtype][network]
122	if pos ~= nil then
123		EchoDebug("and spot found")
124		pos.y = 0
125	else
126		EchoDebug("but NO spot found")
127	end
128	return pos
129end