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