mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
755 lines
24 KiB
Lua
755 lines
24 KiB
Lua
--- **Functional** - Autolase targets in the field.
|
|
--
|
|
-- ===
|
|
--
|
|
-- **AUOTLASE** - Autolase targets in the field.
|
|
--
|
|
-- ===
|
|
--
|
|
-- ## Missions:
|
|
--
|
|
-- ### [Autolase](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/)
|
|
--
|
|
-- ===
|
|
--
|
|
-- **Main Features:**
|
|
--
|
|
-- * Detect and lase contacts automatically
|
|
-- * Targets are lased by threat priority order
|
|
-- * Use FSM events to link functionality into your scripts
|
|
-- * Easy setup
|
|
--
|
|
-- ===
|
|
--
|
|
-- ### Author: **applevangelist**
|
|
-- @module Functional.Autolase
|
|
-- @image Designation.JPG
|
|
|
|
-- Date: Oct 2021
|
|
|
|
---
|
|
--- Class AUTOLASE
|
|
-- @type AUTOLASE
|
|
-- @field #string ClassName
|
|
-- @field #string lid
|
|
-- @field #number verbose
|
|
-- @field #string alias
|
|
-- @field #boolean debug
|
|
-- @field #string version
|
|
-- @extends Ops.Intel#INTEL
|
|
|
|
--- Spot on!
|
|
--
|
|
-- ===
|
|
--
|
|
-- # 1 Autolase concept
|
|
--
|
|
-- * Detect and lase contacts automatically
|
|
-- * Targets are lased by threat priority order
|
|
-- * Use FSM events to link functionality into your scripts
|
|
-- * Easy set-up
|
|
-- * Targets are lased by threat priority order
|
|
--
|
|
-- # 2 Basic usage
|
|
--
|
|
-- ## 2.2 Set up a group of Recce Units:
|
|
--
|
|
-- local FoxSet = SET_GROUP:New():FilterPrefixes("Recce"):FilterCoalitions("blue"):FilterStart()
|
|
--
|
|
-- ## 2.3 (Optional) Set up a group of pilots, this will drive who sees the F10 menu entry:
|
|
--
|
|
-- local Pilotset = SET_CLIENT:New():FilterCoalitions("blue"):FilterActive(true):FilterStart()
|
|
--
|
|
-- ## 2.4 Set up and start Autolase:
|
|
--
|
|
-- local autolaser = AUTOLASE:New(FoxSet,coalition.side.BLUE,"Wolfpack",Pilotset)
|
|
--
|
|
-- ## 2.5 Example - Using a fixed laser code for a specific Recce unit:
|
|
--
|
|
-- local recce = SPAWN:New("Reaper")
|
|
-- :InitDelayOff()
|
|
-- :OnSpawnGroup(
|
|
-- function (group)
|
|
-- local name = group:GetName()
|
|
-- autolaser:SetRecceLaserCode(name,1688)
|
|
-- end
|
|
-- )
|
|
-- :InitCleanUp(60)
|
|
-- :InitLimit(1,0)
|
|
-- :SpawnScheduled(30,0.5)
|
|
--
|
|
-- ## 2.6 Example - Inform pilots about events:
|
|
--
|
|
-- autolaser:SetNotifyPilots(true) -- defaults to true, also shown if debug == true
|
|
-- -- Note - message are shown to pilots in the #SET_CLIENT only if using the pilotset option, else to the coalition.
|
|
--
|
|
-- @field #AUTOLASE
|
|
AUTOLASE = {
|
|
ClassName = "AUTOLASE",
|
|
lid = "",
|
|
verbose = 0,
|
|
alias = "",
|
|
debug = false,
|
|
}
|
|
|
|
---Laser spot info
|
|
-- @type AUTOLASE.LaserSpot
|
|
-- @field Core.Spot#SPOT laserspot
|
|
-- @field Wrapper.Unit#UNIT lasedunit
|
|
-- @field Wrapper.Unit#UNIT lasingunit
|
|
-- @field #number lasercode
|
|
-- @field #string location
|
|
-- @field #number timestamp
|
|
-- @field #string unitname
|
|
-- @field #string reccename
|
|
-- @field #string unittype
|
|
|
|
--- AUTOLASE class version.
|
|
-- @field #string version
|
|
AUTOLASE.version = "0.0.2"
|
|
|
|
-------------------------------------------------------------------
|
|
-- Begin Functional.Autolase.lua
|
|
-------------------------------------------------------------------
|
|
|
|
--- Constructor for a new Autolase instance.
|
|
-- @param #AUTOLASE self
|
|
-- @param Core.Set#SET_GROUP RecceSet Set of detecting and lasing units
|
|
-- @param #number Coalition Coalition side. Can also be passed as a string "red", "blue" or "neutral".
|
|
-- @param #string Alias (Optional) An alias how this object is called in the logs etc.
|
|
-- @param Core.Set#SET_CLIENT PilotSet (Optional) Set of clients for precision bombing, steering menu creation. Leave nil for a coalition-wide F10 entry and display.
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
|
|
BASE:T({RecceSet, Coalition, Alias, PilotSet})
|
|
|
|
-- Inherit everything from BASE class.
|
|
local self=BASE:Inherit(self, BASE:New()) -- #AUTOLASE
|
|
|
|
if Coalition and type(Coalition)=="string" then
|
|
if Coalition=="blue" then
|
|
self.coalition=coalition.side.BLUE
|
|
elseif Coalition=="red" then
|
|
self.coalition=coalition.side.RED
|
|
elseif Coalition=="neutral" then
|
|
self.coalition=coalition.side.NEUTRAL
|
|
else
|
|
self:E("ERROR: Unknown coalition in AUTOLASE!")
|
|
end
|
|
end
|
|
|
|
-- Set alias.
|
|
if Alias then
|
|
self.alias=tostring(Alias)
|
|
else
|
|
self.alias="Lion"
|
|
if self.coalition then
|
|
if self.coalition==coalition.side.RED then
|
|
self.alias="Wolf"
|
|
elseif self.coalition==coalition.side.BLUE then
|
|
self.alias="Fox"
|
|
end
|
|
end
|
|
end
|
|
|
|
-- inherit from INTEL
|
|
local self=BASE:Inherit(self, INTEL:New(RecceSet, Coalition, Alias)) -- #AUTOLASE
|
|
|
|
self.DetectVisual = true
|
|
self.DetectOptical = true
|
|
self.DetectRadar = false
|
|
self.DetectIRST = true
|
|
self.DetectRWR = false
|
|
self.DetectDLINK = true
|
|
self.LaserCodes = UTILS.GenerateLaserCodes()
|
|
self.LaseDistance = 4000
|
|
self.LaseDuration = 120
|
|
self.GroupsByThreat = {}
|
|
self.UnitsByThreat = {}
|
|
self.RecceNames = {}
|
|
self.RecceLaserCode = {}
|
|
self.RecceUnitNames= {}
|
|
self.maxlasing = 4
|
|
self.CurrentLasing = {}
|
|
self.lasingindex = 0
|
|
self.deadunitnotes = {}
|
|
self.usepilotset = false
|
|
self.reporttimeshort = 10
|
|
self.reporttimelong = 30
|
|
self.smoketargets = false
|
|
self.smokecolor = SMOKECOLOR.Red
|
|
self.notifypilots = true
|
|
|
|
-- 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")
|
|
|
|
-- Add FSM transitions.
|
|
-- From State --> Event --> To State
|
|
self:AddTransition("*", "Monitor", "*") -- Start FSM
|
|
self:AddTransition("*", "Lasing", "*") -- Lasing target
|
|
self:AddTransition("*", "TargetLost", "*") -- Lost target
|
|
self:AddTransition("*", "TargetDestroyed", "*") -- Target destroyed
|
|
self:AddTransition("*", "RecceKIA", "*") -- Recce KIA
|
|
self:AddTransition("*", "LaserTimeout", "*") -- Laser timed out
|
|
self:AddTransition("*", "Cancel", "*") -- Stop Autolase
|
|
|
|
-- Menu Entry
|
|
if not PilotSet then
|
|
self.Menu = MENU_COALITION_COMMAND:New(self.coalition,"Autolase",nil,self.ShowStatus,self)
|
|
else
|
|
self.usepilotset = true
|
|
self.pilotset = PilotSet
|
|
self:HandleEvent(EVENTS.PlayerEnterAircraft)
|
|
self:SetPilotMenu()
|
|
end
|
|
|
|
self:SetClusterAnalysis(false, false)
|
|
|
|
self:__Start(2)
|
|
self:__Monitor(math.random(5,10))
|
|
|
|
return self
|
|
|
|
------------------------
|
|
--- Pseudo Functions ---
|
|
------------------------
|
|
|
|
--- Triggers the FSM event "Monitor".
|
|
-- @function [parent=#AUTOLASE] Status
|
|
-- @param #AUTOLASE self
|
|
|
|
--- Triggers the FSM event "Monitor" after a delay.
|
|
-- @function [parent=#AUTOLASE] __Status
|
|
-- @param #AUTOLASE self
|
|
-- @param #number delay Delay in seconds.
|
|
|
|
--- Triggers the FSM event "Cancel".
|
|
-- @function [parent=#AUTOLASE] Cancel
|
|
-- @param #AUTOLASE self
|
|
|
|
--- Triggers the FSM event "Cancel" after a delay.
|
|
-- @function [parent=#AUTOLASE] __Cancel
|
|
-- @param #AUTOLASE self
|
|
-- @param #number delay Delay in seconds.
|
|
|
|
--- On After "RecceKIA" event.
|
|
-- @function [parent=#AUTOLASE] OnAfterRecceKIA
|
|
-- @param #AUTOLASE self
|
|
-- @param #string From The from state
|
|
-- @param #string Event The event
|
|
-- @param #string To The to state
|
|
-- @param #string RecceName The lost Recce
|
|
|
|
--- On After "TargetDestroyed" event.
|
|
-- @function [parent=#AUTOLASE] OnAfterTargetDestroyed
|
|
-- @param #AUTOLASE self
|
|
-- @param #string From The from state
|
|
-- @param #string Event The event
|
|
-- @param #string To The to state
|
|
-- @param #string UnitName The destroyed unit\'s name
|
|
-- @param #string RecceName The Recce name lasing
|
|
|
|
--- On After "TargetLost" event.
|
|
-- @function [parent=#AUTOLASE] OnAfterTargetLost
|
|
-- @param #AUTOLASE self
|
|
-- @param #string From The from state
|
|
-- @param #string Event The event
|
|
-- @param #string To The to state
|
|
-- @param #string UnitName The lost unit\'s name
|
|
-- @param #string RecceName The Recce name lasing
|
|
|
|
--- On After "LaserTimeout" event.
|
|
-- @function [parent=#AUTOLASE] OnAfterLaserTimeout
|
|
-- @param #AUTOLASE self
|
|
-- @param #string From The from state
|
|
-- @param #string Event The event
|
|
-- @param #string To The to state
|
|
-- @param #string UnitName The lost unit\'s name
|
|
-- @param #string RecceName The Recce name lasing
|
|
|
|
--- On After "Lasing" event.
|
|
-- @function [parent=#AUTOLASE] OnAfterLasing
|
|
-- @param #AUTOLASE self
|
|
-- @param #string From The from state
|
|
-- @param #string Event The event
|
|
-- @param #string To The to state
|
|
-- @param Functional.Autolase#AUTOLASE.LaserSpot LaserSpot The LaserSpot data table
|
|
|
|
end
|
|
|
|
-------------------------------------------------------------------
|
|
-- Helper Functions
|
|
-------------------------------------------------------------------
|
|
|
|
--- (Internal) Function to set pilot menu.
|
|
-- @param #AUTOLASE self
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:SetPilotMenu()
|
|
local pilottable = self.pilotset:GetSetObjects() or {}
|
|
for _,_unit in pairs (pilottable) do
|
|
local Unit = _unit -- Wrapper.Unit#UNIT
|
|
if Unit and Unit:IsAlive() then
|
|
local Group = Unit:GetGroup()
|
|
local lasemenu = MENU_GROUP_COMMAND:New(Group,"Autolase Status",nil,self.ShowStatus,self,Group)
|
|
lasemenu:Refresh()
|
|
end
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- (Internal) Event function for new pilots.
|
|
-- @param #AUTOLASE self
|
|
-- @param Core.Event#EVENTDATA EventData
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:OnEventPlayerEnterAircraft(EventData)
|
|
self:SetPilotMenu()
|
|
return self
|
|
end
|
|
|
|
--- Function to get a laser code by recce name
|
|
-- @param #AUTOLASE self
|
|
-- @param #string RecceName Name of the Recce
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:GetLaserCode(RecceName)
|
|
local code = 1688
|
|
if self.RecceLaserCode[RecceName] == nil then
|
|
code = self.LaserCodes[math.random(#self.LaserCodes)]
|
|
self.RecceLaserCode[RecceName] = code
|
|
else
|
|
code = self.RecceLaserCode[RecceName]
|
|
end
|
|
return code
|
|
end
|
|
|
|
--- Function set max lasing targets
|
|
-- @param #AUTOLASE self
|
|
-- @param #number Number Max number of targets to lase at once
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:SetMaxLasingTargets(Number)
|
|
self.maxlasing = Number or 4
|
|
return self
|
|
end
|
|
|
|
--- Function set notify pilots on events
|
|
-- @param #AUTOLASE self
|
|
-- @param #boolean OnOff Switch messaging on (true) or off (false)
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:SetNotifyPilots(OnOff)
|
|
self.notifypilots = OnOff and true
|
|
return self
|
|
end
|
|
|
|
--- (User) Function to set a specific code to a Recce.
|
|
-- @param #AUTOLASE self
|
|
-- @param #string RecceName Name of the Recce
|
|
-- @param #number Code The lase code
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:SetRecceLaserCode(RecceName, Code)
|
|
local code = Code or 1688
|
|
self.RecceLaserCode[RecceName] = code
|
|
return self
|
|
end
|
|
|
|
--- (User) Function to set message show times.
|
|
-- @param #AUTOLASE self
|
|
-- @param #number long Longer show time
|
|
-- @param #number short Shorter show time
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:SetReportingTimes(long, short)
|
|
self.reporttimeshort = short or 10
|
|
self.reporttimelong = long or 30
|
|
return self
|
|
end
|
|
|
|
--- (User) Function to set lasing distance in meters and duration in seconds
|
|
-- @param #AUTOLASE self
|
|
-- @param #number Distance (Max) distance for lasing in meters
|
|
-- @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
|
|
return self
|
|
end
|
|
|
|
--- (User) Function to set smoking of targets.
|
|
-- @param #AUTOLASE self
|
|
-- @param #boolean OnOff Switch smoking on or off
|
|
-- @param #number Color Smokecolor, e.g. SMOKECOLOR.Red
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:SetSmokeTargets(OnOff,Color)
|
|
self.smoketargets = OnOff
|
|
self.smokecolor = Color or SMOKECOLOR.Red
|
|
return self
|
|
end
|
|
|
|
--- (Internal) Function to check on lased targets.
|
|
-- @param #AUTOLASE self
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:CleanCurrentLasing()
|
|
local lasingtable = self.CurrentLasing
|
|
local newtable = {}
|
|
local lasing = 0
|
|
|
|
for _ind,_entry in pairs(lasingtable) do
|
|
local entry = _entry -- #AUTOLASE.LaserSpot
|
|
local valid = 0
|
|
local reccedead = false
|
|
local unitdead = false
|
|
local lostsight = false
|
|
local Tnow = timer.getAbsTime()
|
|
-- check recce dead
|
|
local recce = entry.lasingunit
|
|
if recce and recce:IsAlive() then
|
|
valid = valid + 1
|
|
else
|
|
reccedead = true
|
|
--local text = string.format("Recce %s KIA!",entry.reccename)
|
|
--local m = MESSAGE:New(text,15,"Autolase"):ToAll()
|
|
self:__RecceKIA(2,entry.reccename)
|
|
end
|
|
-- check entry dead
|
|
local unit = entry.lasedunit
|
|
if unit and unit:IsAlive() == true then
|
|
valid = valid + 1
|
|
else
|
|
unitdead = true
|
|
if not self.deadunitnotes[entry.unitname] then
|
|
--local text = string.format("Unit %s destroyed! Good job!",entry.unitname)
|
|
--local m = MESSAGE:New(text,15,"Autolase"):ToAll()
|
|
self.deadunitnotes[entry.unitname] = true
|
|
self:__TargetDestroyed(2,entry.unitname,entry.reccename)
|
|
end
|
|
end
|
|
-- check entry out of sight
|
|
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
|
|
valid = valid + 1
|
|
else
|
|
lostsight = true
|
|
entry.laserspot:LaseOff()
|
|
--local text = string.format("Lost sight of unit %s.",entry.unitname)
|
|
--local m = MESSAGE:New(text,15,"Autolase"):ToAll()
|
|
self:__TargetLost(2,entry.unitname,entry.reccename)
|
|
end
|
|
end
|
|
-- check timed out
|
|
local timestamp = entry.timestamp
|
|
if Tnow - timestamp < self.LaseDuration then
|
|
valid = valid + 1
|
|
else
|
|
lostsight = true
|
|
entry.laserspot:LaseOff()
|
|
--local text = string.format("Lost sight of unit %s.",entry.unitname)
|
|
--local m = MESSAGE:New(text,15,"Autolase"):ToAll()
|
|
self:__LaserTimeout(2,entry.unitname,entry.reccename)
|
|
end
|
|
if valid == 4 then
|
|
self.lasingindex = self.lasingindex + 1
|
|
newtable[self.lasingindex] = entry
|
|
lasing = lasing + 1
|
|
end
|
|
end
|
|
self.CurrentLasing = newtable
|
|
return lasing
|
|
end
|
|
|
|
--- (Internal) Function to show status.
|
|
-- @param #AUTOLASE self
|
|
-- @param Wrapper.Group#GROUP Group (Optional) show to a certain group
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:ShowStatus(Group)
|
|
local report = REPORT:New("Autolase")
|
|
local lines = 0
|
|
for _ind,_entry in pairs(self.CurrentLasing) do
|
|
local entry = _entry -- #AUTOLASE.LaserSpot
|
|
local reccename = entry.reccename
|
|
local typename = entry.unittype
|
|
local code = entry.lasercode
|
|
local locationstring = entry.location
|
|
local text = string.format("%s lasing %s code %d\nat %s",reccename,typename,code,locationstring)
|
|
report:AddIndent(text,"|")
|
|
lines = lines + 1
|
|
end
|
|
if lines == 0 then
|
|
report:AddIndent("No targets!","|")
|
|
end
|
|
local reporttime = self.reporttimelong
|
|
if lines == 0 then reporttime = self.reporttimeshort end
|
|
if Group and Group:IsAlive() then
|
|
local m = MESSAGE:New(report:Text(),reporttime,"Info"):ToGroup(Group)
|
|
else
|
|
local m = MESSAGE:New(report:Text(),reporttime,"Info"):ToCoalition(self.coalition)
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- (Internal) Function to show messages.
|
|
-- @param #AUTOLASE self
|
|
-- @param #string Message The message to be sent
|
|
-- @param #number Duration Duration in seconds
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:NotifyPilots(Message,Duration)
|
|
if self.usepilotset then
|
|
local pilotset = self.pilotset:GetSetObjects() --#table
|
|
for _,_pilot in pairs(pilotset) do
|
|
local pilot = _pilot -- Wrapper.Unit#UNIT
|
|
if pilot and pilot:IsAlive() then
|
|
local Group = pilot:GetGroup()
|
|
local m = MESSAGE:New(Message,Duration,"Autolase"):ToGroup(Group)
|
|
end
|
|
end
|
|
elseif not self.debug then
|
|
local m = MESSAGE:New(Message,Duration,"Autolase"):ToCoalition(self.coalition)
|
|
else
|
|
local m = MESSAGE:New(Message,Duration,"Autolase"):ToAll()
|
|
end
|
|
return self
|
|
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:onafterMonitor(From, Event, To)
|
|
self:T({From, Event, To})
|
|
|
|
-- Housekeeping
|
|
local countlases = self:CleanCurrentLasing()
|
|
|
|
self:SetPilotMenu()
|
|
|
|
local detecteditems = self.Contacts or {} -- #table of Ops.Intelligence#INTEL.Contact
|
|
local groupsbythreat = {}
|
|
--self:T("Detected Items:")
|
|
--self:T({detecteditems})
|
|
local report = REPORT:New("Detections")
|
|
local lines = 0
|
|
for _,_contact in pairs(detecteditems) do
|
|
local contact = _contact -- Ops.Intelligence#INTEL.Contact
|
|
local grp = contact.group
|
|
local coord = contact.position
|
|
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)
|
|
report:Add(text)
|
|
self:T(text)
|
|
lines = lines + 1
|
|
-- sort out groups beyond sight
|
|
if distance <= self.LaseDistance then
|
|
table.insert(groupsbythreat,{contact.group,contact.threatlevel})
|
|
self.RecceNames[contact.groupname] = contact.recce
|
|
end
|
|
end
|
|
|
|
self.GroupsByThreat = groupsbythreat
|
|
|
|
if self.verbose > 2 and lines > 0 then
|
|
local m=MESSAGE:New(report:Text(),self.reporttimeshort,"Autolase"):ToAll()
|
|
end
|
|
|
|
table.sort(self.GroupsByThreat, function(a,b)
|
|
local aNum = a[2] -- Coin value of a
|
|
local bNum = b[2] -- Coin value of b
|
|
return aNum > bNum -- Return their comparisons, < for ascending, > for descending
|
|
end)
|
|
|
|
--self:T("Groups by Threat")
|
|
--self:T({self.GroupsByThreat})
|
|
|
|
-- build table of Units
|
|
local unitsbythreat = {}
|
|
for _,_entry in ipairs(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()]
|
|
for _,_unit in pairs(units) do
|
|
local unit = _unit -- Wrapper.Unit#UNIT
|
|
if unit and unit:IsAlive() then
|
|
local threat = unit:GetThreatLevel()
|
|
if threat > 0 then
|
|
local unitname = unit:GetName()
|
|
table.insert(unitsbythreat,{unit,threat})
|
|
self.RecceUnitNames[unitname] = reccename
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
self.UnitsByThreat = unitsbythreat
|
|
|
|
table.sort(self.UnitsByThreat, function(a,b)
|
|
local aNum = a[2] -- Coin value of a
|
|
local bNum = b[2] -- Coin value of b
|
|
return aNum > bNum -- Return their comparisons, < for ascending, > for descending
|
|
end)
|
|
|
|
local unitreport = REPORT:New("Detected Units")
|
|
|
|
local lines = 0
|
|
for _,_entry in ipairs(self.UnitsByThreat) do
|
|
local threat = _entry[2]
|
|
local unit = _entry[1]
|
|
local unitname = unit:GetName()
|
|
local text = string.format("Unit %s | Threatlevel %d | Detected by %s",unitname,threat,self.RecceUnitNames[unitname])
|
|
unitreport:Add(text)
|
|
lines = lines + 1
|
|
self:T(text)
|
|
end
|
|
|
|
if self.verbose > 2 and lines > 0 then
|
|
local m=MESSAGE:New(unitreport:Text(),self.reporttimeshort,"Autolase"):ToAll()
|
|
end
|
|
|
|
-- lase targets
|
|
local targets = countlases or 0
|
|
for _,_entry in pairs(self.UnitsByThreat) do
|
|
local unit = _entry[1] -- Wrapper.Unit#UNIT
|
|
local unitname = unit:GetName()
|
|
local reccename = self.RecceUnitNames[unitname]
|
|
local recce = UNIT:FindByName(reccename)
|
|
if targets < self.maxlasing and unit:IsAlive() == true then
|
|
targets = targets + 1
|
|
local code = self:GetLaserCode(reccename)
|
|
local spot = SPOT:New(recce)
|
|
spot:LaseOn(unit,code,self.LaseDuration)
|
|
local locationstring = unit:GetCoordinate():ToStringLLDDM()
|
|
--local text = string.format("%s is lasing %s code %d\nat %s",reccename,unit:GetTypeName(),code,locationstring)
|
|
--local m = MESSAGE:New(text,15,"Autolase"):ToAllIf(self.debug)
|
|
local laserspot = { -- #AUTOLASE.LaserSpot
|
|
laserspot = spot,
|
|
lasedunit = unit,
|
|
lasingunit = recce,
|
|
lasercode = code,
|
|
location = locationstring,
|
|
timestamp = timer.getAbsTime(),
|
|
unitname = unitname,
|
|
reccename = reccename,
|
|
unittype = unit:GetTypeName(),
|
|
}
|
|
if self.smoketargets then
|
|
local coord = unit:GetCoordinate()
|
|
coord:Smoke(self.smokecolor)
|
|
end
|
|
self.lasingindex = self.lasingindex + 1
|
|
self.CurrentLasing[self.lasingindex] = laserspot
|
|
self:__Lasing(2,laserspot)
|
|
end
|
|
end
|
|
|
|
self:__Monitor(-30)
|
|
return self
|
|
end
|
|
|
|
--- (Internal) FSM Function onbeforeRecceKIA
|
|
-- @param #AUTOLASE self
|
|
-- @param #string From The from state
|
|
-- @param #string Event The event
|
|
-- @param #string To The to state
|
|
-- @param #string RecceName The lost Recce
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:onbeforeRecceKIA(From,Event,To,RecceName)
|
|
self:T({From, Event, To, RecceName})
|
|
if self.notifypilots or self.debug then
|
|
local text = string.format("Recce %s KIA!",RecceName)
|
|
self:NotifyPilots(text,self.reporttimeshort)
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- (Internal) FSM Function onbeforeTargetDestroyed
|
|
-- @param #AUTOLASE self
|
|
-- @param #string From The from state
|
|
-- @param #string Event The event
|
|
-- @param #string To The to state
|
|
-- @param #string UnitName The destroyed unit\'s name
|
|
-- @param #string RecceName The Recce name lasing
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:onbeforeTargetDestroyed(From,Event,To,UnitName,RecceName)
|
|
self:T({From, Event, To, UnitName, RecceName})
|
|
if self.notifypilots or self.debug then
|
|
local text = string.format("Unit %s destroyed! Good job!",UnitName)
|
|
self:NotifyPilots(text,self.reporttimeshort)
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- (Internal) FSM Function onbeforeTargetLost
|
|
-- @param #AUTOLASE self
|
|
-- @param #string From The from state
|
|
-- @param #string Event The event
|
|
-- @param #string To The to state
|
|
-- @param #string UnitName The lost unit\'s name
|
|
-- @param #string RecceName The Recce name lasing
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:onbeforeTargetLost(From,Event,To,UnitName,RecceName)
|
|
self:T({From, Event, To, UnitName,RecceName})
|
|
if self.notifypilots or self.debug then
|
|
local text = string.format("%s lost sight of unit %s.",RecceName,UnitName)
|
|
self:NotifyPilots(text,self.reporttimeshort)
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- (Internal) FSM Function onbeforeLaserTimeout
|
|
-- @param #AUTOLASE self
|
|
-- @param #string From The from state
|
|
-- @param #string Event The event
|
|
-- @param #string To The to state
|
|
-- @param #string UnitName The lost unit\'s name
|
|
-- @param #string RecceName The Recce name lasing
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:onbeforeLaserTimeout(From,Event,To,UnitName,RecceName)
|
|
self:T({From, Event, To, UnitName,RecceName})
|
|
if self.notifypilots or self.debug then
|
|
local text = string.format("%s laser timeout on unit %s.",RecceName,UnitName)
|
|
self:NotifyPilots(text,self.reporttimeshort)
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- (Internal) FSM Function onbeforeLasing
|
|
-- @param #AUTOLASE self
|
|
-- @param #string From The from state
|
|
-- @param #string Event The event
|
|
-- @param #string To The to state
|
|
-- @param Functional.Autolase#AUTOLASE.LaserSpot LaserSpot The LaserSpot data table
|
|
-- @return #AUTOLASE self
|
|
function AUTOLASE:onbeforeLasing(From,Event,To,LaserSpot)
|
|
self:T({From, Event, To, LaserSpot.unittype})
|
|
if self.notifypilots or self.debug then
|
|
local laserspot = LaserSpot -- #AUTOLASE.LaserSpot
|
|
local text = string.format("%s is lasing %s code %d\nat %s",laserspot.reccename,laserspot.unittype,laserspot.lasercode,laserspot.location)
|
|
self:NotifyPilots(text,self.reporttimeshort)
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- (Internal) FSM Function onbeforeCancel
|
|
-- @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:onbeforeCancel(From,Event,To)
|
|
self:UnHandleEvent(EVENTS.PlayerEnterAircraft)
|
|
self:__Stop(2)
|
|
return self
|
|
end
|
|
|
|
-------------------------------------------------------------------
|
|
-- End Functional.Autolase.lua
|
|
-------------------------------------------------------------------
|