Autolase - better calculation of LoS for lasing, somewhat faster detection

This commit is contained in:
Applevangelist 2021-10-07 09:49:06 +02:00
parent 554f063def
commit d112ffaf6a

View File

@ -53,7 +53,8 @@
-- :InitDelayOff()
-- :OnSpawnGroup(
-- function (group)
-- local name = group:GetName()
-- local unit = group:GetUnit(1)
-- local name = unit:GetName()
-- autolaser:SetRecceLaserCode(name,1688)
-- end
-- )
@ -107,7 +108,7 @@ AUTOLASE = {
--- AUTOLASE class version.
-- @field #string version
AUTOLASE.version = "0.0.3"
AUTOLASE.version = "0.0.4"
-------------------------------------------------------------------
-- Begin Functional.Autolase.lua
@ -179,6 +180,8 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
self.smoketargets = false
self.smokecolor = SMOKECOLOR.Red
self.notifypilots = true
--self.statusupdate = -28 -- for #INTEL
self.targetsperrecce = {}
-- Set some string id for output to DCS.log file.
self.lid=string.format("AUTOLASE %s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown")
@ -308,7 +311,7 @@ end
--- Function to get a laser code by recce name
-- @param #AUTOLASE self
-- @param #string RecceName Name of the Recce
-- @param #string RecceName Unit(!) name of the Recce
-- @return #AUTOLASE self
function AUTOLASE:GetLaserCode(RecceName)
local code = 1688
@ -341,7 +344,7 @@ end
--- (User) Function to set a specific code to a Recce.
-- @param #AUTOLASE self
-- @param #string RecceName Name of the Recce
-- @param #string RecceName (Unit!) Name of the Recce
-- @param #number Code The lase code
-- @return #AUTOLASE self
function AUTOLASE:SetRecceLaserCode(RecceName, Code)
@ -367,8 +370,8 @@ end
-- @param #number Duration (Max) duration for lasing in seconds
-- @return #AUTOLASE self
function AUTOLASE:SetLasingParameters(Distance, Duration)
self.LaseDistance = distance or 4000
self.LaseDuration = duration or 120
self.LaseDistance = Distance or 5000
self.LaseDuration = Duration or 300
return self
end
@ -383,14 +386,40 @@ function AUTOLASE:SetSmokeTargets(OnOff,Color)
return self
end
--- (Internal) Function to calculate line of sight.
-- @param #AUTOLASE self
-- @param Wrapper.Unit#UNIT Unit
-- @return #number LOS Line of sight in meters
function AUTOLASE:GetLosFromUnit(Unit)
local lasedistance = self.LaseDistance
local unitheight = Unit:GetHeight()
local coord = Unit:GetCoordinate()
local landheight = coord:GetLandHeight()
local asl = unitheight - landheight
if asl > 100 then
local absquare = lasedistance^2+asl^2
lasedistance = math.sqrt(absquare)
end
--self:I({lasedistance=lasedistance})
return lasedistance
end
--- (Internal) Function to check on lased targets.
-- @param #AUTOLASE self
-- @return #AUTOLASE self
function AUTOLASE:CleanCurrentLasing()
local lasingtable = self.CurrentLasing
local newtable = {}
local newreccecount = {}
local lasing = 0
for _ind,_entry in pairs(lasingtable) do
local entry = _entry -- #AUTOLASE.LaserSpot
if not newreccecount[entry.reccename] then
newreccecount[entry.reccename] = 0
end
end
for _ind,_entry in pairs(lasingtable) do
local entry = _entry -- #AUTOLASE.LaserSpot
local valid = 0
@ -425,8 +454,9 @@ function AUTOLASE:CleanCurrentLasing()
if not reccedead and not unitdead then
local coord = unit:GetCoordinate() -- Core.Point#COORDINATE
local coord2 = recce:GetCoordinate() -- Core.Point#COORDINATE
local dist = coord2:Get2DDistance(coord)
if dist <= self.LaseDistance then
local dist = coord2:Get3DDistance(coord)
local lasedistance = self:GetLosFromUnit(recce)
if dist <= lasedistance then
valid = valid + 1
else
lostsight = true
@ -450,10 +480,13 @@ function AUTOLASE:CleanCurrentLasing()
if valid == 4 then
self.lasingindex = self.lasingindex + 1
newtable[self.lasingindex] = entry
newreccecount[entry.reccename] = newreccecount[entry.reccename] + 1
lasing = lasing + 1
end
end
self.CurrentLasing = newtable
self.targetsperrecce = newreccecount
--self:I({newreccecount})
return lasing
end
@ -507,13 +540,43 @@ function AUTOLASE:NotifyPilots(Message,Duration)
else
local m = MESSAGE:New(Message,Duration,"Autolase"):ToAll()
end
if self.debug then self:I(Message) end
return self
end
--- (Internal) Function to check if a unit is already lased.
-- @param #AUTOLASE self
-- @param #string unitname Name of the unit to check
-- @return #boolean outcome True or false
function AUTOLASE:CheckIsLased(unitname)
local outcome = false
for _,_laserspot in pairs(self.CurrentLasing) do
local spot = _laserspot -- #AUTOLASE.LaserSpot
if spot.unitname == unitname then
outcome = true
break
end
end
return outcome
end
-------------------------------------------------------------------
-- FSM Functions
-------------------------------------------------------------------
--- (Internal) FSM Function for monitoring
-- @param #AUTOLASE self
-- @param #string From The from state
-- @param #string Event The event
-- @param #string To The to state
-- @return #AUTOLASE self
function AUTOLASE:onbeforeMonitor(From, Event, To)
self:T({From, Event, To})
-- Check if group has detected any units.
self:UpdateIntel()
return self
end
--- (Internal) FSM Function for monitoring
-- @param #AUTOLASE self
-- @param #string From The from state
@ -522,7 +585,7 @@ end
-- @return #AUTOLASE self
function AUTOLASE:onafterMonitor(From, Event, To)
self:T({From, Event, To})
-- Housekeeping
local countlases = self:CleanCurrentLasing()
@ -541,13 +604,15 @@ function AUTOLASE:onafterMonitor(From, Event, To)
local reccename = contact.recce
local reccegrp = UNIT:FindByName(reccename)
local reccecoord = reccegrp:GetCoordinate()
local distance = math.floor(reccecoord:Get2DDistance(coord))
local text = string.format("%s of %s | Distance %d km | Threatlevel %d",contact.attribute, contact.groupname, distance/ 1000, contact.threatlevel)
local distance = math.floor(reccecoord:Get3DDistance(coord))
local text = string.format("%s of %s | Distance %d km | Threatlevel %d",contact.attribute, contact.groupname, math.floor(distance/1000), contact.threatlevel)
report:Add(text)
self:T(text)
if self.debug then self:I(text) end
lines = lines + 1
-- sort out groups beyond sight
if distance <= self.LaseDistance then
local lasedistance = self:GetLosFromUnit(reccegrp)
if grp:IsGround() and lasedistance >= distance then
table.insert(groupsbythreat,{contact.group,contact.threatlevel})
self.RecceNames[contact.groupname] = contact.recce
end
@ -565,20 +630,24 @@ function AUTOLASE:onafterMonitor(From, Event, To)
return aNum > bNum -- Return their comparisons, < for ascending, > for descending
end)
--self:T("Groups by Threat")
-- self:T("Groups by Threat")
--self:T({self.GroupsByThreat})
-- build table of Units
local unitsbythreat = {}
for _,_entry in ipairs(self.GroupsByThreat) do
for _,_entry in pairs(self.GroupsByThreat) do
local group = _entry[1] -- Wrapper.Group#GROUP
if group and group:IsAlive() then
local units = group:GetUnits()
local reccename = self.RecceNames[group:GetName()]
--local recceunit UNIT:FindByName(reccename)
--local reccecoord = recceunit:GetCoordinate()
for _,_unit in pairs(units) do
local unit = _unit -- Wrapper.Unit#UNIT
if unit and unit:IsAlive() then
local threat = unit:GetThreatLevel()
local coord = unit:GetCoordinate()
--local distance = math.floor(reccecoord:Get3DDistance(coord))
if threat > 0 then
local unitname = unit:GetName()
table.insert(unitsbythreat,{unit,threat})
@ -597,10 +666,13 @@ function AUTOLASE:onafterMonitor(From, Event, To)
return aNum > bNum -- Return their comparisons, < for ascending, > for descending
end)
-- self:I("Units by Threat")
-- self:I({self.UnitsByThreat})
local unitreport = REPORT:New("Detected Units")
local lines = 0
for _,_entry in ipairs(self.UnitsByThreat) do
for _,_entry in pairs(self.UnitsByThreat) do
local threat = _entry[2]
local unit = _entry[1]
local unitname = unit:GetName()
@ -608,6 +680,7 @@ function AUTOLASE:onafterMonitor(From, Event, To)
unitreport:Add(text)
lines = lines + 1
self:T(text)
if self.debug then self:I(text) end
end
if self.verbose > 2 and lines > 0 then
@ -621,8 +694,10 @@ function AUTOLASE:onafterMonitor(From, Event, To)
local unitname = unit:GetName()
local reccename = self.RecceUnitNames[unitname]
local recce = UNIT:FindByName(reccename)
if targets < self.maxlasing and unit:IsAlive() == true then
local reccecount = self.targetsperrecce[reccename] or 0
if (targets < self.maxlasing or reccecount < targets) and not self:CheckIsLased(unitname) and unit:IsAlive() == true then
targets = targets + 1
self.targetsperrecce[reccename] = reccecount + 1
local code = self:GetLaserCode(reccename)
local spot = SPOT:New(recce)
spot:LaseOn(unit,code,self.LaseDuration)