mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge branch 'develop' into FF/Ops
This commit is contained in:
commit
bab097958f
@ -33,7 +33,7 @@
|
||||
--
|
||||
-- ## Infantry health.
|
||||
--
|
||||
-- When infantry is unboarded from the APCs, the infantry is actually respawned into the battlefield.
|
||||
-- When infantry is unboarded from the helicopters, the infantry is actually respawned into the battlefield.
|
||||
-- As a result, the unboarding infantry is very _healthy_ every time it unboards.
|
||||
-- This is due to the limitation of the DCS simulator, which is not able to specify the health of new spawned units as a parameter.
|
||||
-- However, infantry that was destroyed when unboarded, won't be respawned again. Destroyed is destroyed.
|
||||
@ -67,18 +67,6 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
|
||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||
--[[
|
||||
self:AddTransition( { "Unloaded", "Loading" }, "Load", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Board", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Loaded", "Loaded" )
|
||||
self:AddTransition( "Boarding", "PickedUp", "Loaded" )
|
||||
self:AddTransition( "Boarding", "Deploy", "Loaded" )
|
||||
self:AddTransition( "Loaded", "Unload", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unloaded", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Deployed", "Unloaded" )
|
||||
self:AddTransition( "Unboarding", "Pickup", "Unloaded" )
|
||||
--]]
|
||||
self:AddTransition( "*", "Loaded", "Loaded" )
|
||||
self:AddTransition( "Unboarding", "Pickup", "Unloaded" )
|
||||
self:AddTransition( "Unloaded", "Unboard", "Unloaded" )
|
||||
@ -107,13 +95,31 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Speed Speed in km/h to fly to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- PickedUp Handler OnAfter for AI_CARGO_HELICOPTER - Cargo set has been picked up, ready to deploy
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] OnAfterPickedUp
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter The helicopter #GROUP object
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT Unit The helicopter #UNIT object
|
||||
|
||||
--- Unloaded Handler OnAfter for AI_CARGO_HELICOPTER - Cargo unloaded, carrier is empty
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] OnAfterUnloaded
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Cargo.CargoGroup#CARGO_GROUP Cargo The #CARGO_GROUP object.
|
||||
-- @param Wrapper.Unit#UNIT Unit The helicopter #UNIT object
|
||||
|
||||
--- Pickup Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] Pickup
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Speed Speed in km/h to fly to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Pickup Asynchronous Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] __Pickup
|
||||
@ -129,7 +135,7 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate Place at which cargo is deployed.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Speed Speed in km/h to fly to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @return #boolean
|
||||
|
||||
--- Deploy Handler OnAfter for AI_CARGO_HELICOPTER
|
||||
@ -139,21 +145,42 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Speed Speed in km/h to fly to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Deployed Handler OnAfter for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] OnAfterDeployed
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
|
||||
--- Deploy Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] Deploy
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Core.Point#COORDINATE Coordinate Place at which the cargo is deployed.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Speed Speed in km/h to fly to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Deploy Asynchronous Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] __Deploy
|
||||
-- @param #number Delay Delay in seconds.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Core.Point#COORDINATE Coordinate Place at which the cargo is deployed.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Speed Speed in km/h to fly to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Home Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] Home
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Core.Point#COORDINATE Coordinate Place to which the helicopter will go.
|
||||
-- @param #number Speed (optional) Speed in km/h to fly to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height (optional) Height the Helicopter should be flying at.
|
||||
|
||||
--- Home Asynchronous Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] __Home
|
||||
-- @param #number Delay Delay in seconds.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Core.Point#COORDINATE Coordinate Place to which the helicopter will go.
|
||||
-- @param #number Speed (optional) Speed in km/h to fly to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height (optional) Height the Helicopter should be flying at.
|
||||
|
||||
-- We need to capture the Crash events for the helicopters.
|
||||
-- The helicopter reference is used in the semaphore AI_CARGO_QUEUE.
|
||||
@ -235,7 +262,7 @@ end
|
||||
-- @param Event
|
||||
-- @param To
|
||||
function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
|
||||
|
||||
self:F({From, Event, To})
|
||||
Helicopter:F( { Name = Helicopter:GetName() } )
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
@ -276,7 +303,7 @@ end
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordinate, Speed, DeployZone )
|
||||
|
||||
self:F({From, Event, To, Coordinate, Speed, DeployZone})
|
||||
local HelicopterInZone = false
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() == true then
|
||||
@ -359,7 +386,8 @@ end
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_HELICOPTER:onafterOrbit( Helicopter, From, Event, To, Coordinate )
|
||||
|
||||
self:F({From, Event, To, Coordinate})
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
|
||||
local Route = {}
|
||||
@ -394,7 +422,7 @@ end
|
||||
-- @param #boolean Deployed Cargo is deployed.
|
||||
-- @return #boolean True if all cargo has been unloaded.
|
||||
function AI_CARGO_HELICOPTER:onafterDeployed( Helicopter, From, Event, To, DeployZone )
|
||||
self:F( { Helicopter, From, Event, To, DeployZone = DeployZone } )
|
||||
self:F( { From, Event, To, DeployZone = DeployZone } )
|
||||
|
||||
self:Orbit( Helicopter:GetCoordinate(), 50 )
|
||||
|
||||
@ -416,7 +444,7 @@ end
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate Pickup place.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Speed Speed in km/h to fly to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height Height in meters to move to the pickup coordinate. This parameter is ignored for APCs.
|
||||
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
|
||||
function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordinate, Speed, Height, PickupZone )
|
||||
@ -485,10 +513,10 @@ end
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate Place at which the cargo is deployed.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Speed Speed in km/h to fly to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height Height in meters to move to the deploy coordinate.
|
||||
function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordinate, Speed, Height, DeployZone )
|
||||
|
||||
self:F({From, Event, To, Coordinate, Speed, Height, DeployZone})
|
||||
if Helicopter and Helicopter:IsAlive() ~= nil then
|
||||
|
||||
self.RouteDeploy = true
|
||||
@ -550,11 +578,12 @@ end
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate Home place.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Speed Speed in km/h to fly to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height Height in meters to move to the home coordinate.
|
||||
-- @param Core.Zone#ZONE HomeZone The zone wherein the carrier will return when all cargo has been transported. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
|
||||
function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinate, Speed, Height, HomeZone )
|
||||
|
||||
self:F({From, Event, To, Coordinate, Speed, Height})
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() ~= nil then
|
||||
|
||||
self.RouteHome = true
|
||||
@ -563,7 +592,8 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
|
||||
|
||||
--- Calculate the target route point.
|
||||
|
||||
Coordinate.y = Height
|
||||
--Coordinate.y = Height
|
||||
Height = Height or 50
|
||||
|
||||
Speed = Speed or Helicopter:GetSpeedMax()*0.5
|
||||
|
||||
@ -576,7 +606,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
|
||||
--- Create a route point of type air.
|
||||
local CoordinateTo = Coordinate
|
||||
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
||||
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
|
||||
CoordinateTo.y = landheight + Height -- flight height should be 50m above ground
|
||||
|
||||
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, Speed, true)
|
||||
|
||||
@ -589,12 +619,11 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
|
||||
|
||||
Tasks[#Tasks+1] = Helicopter:TaskLandAtVec2( CoordinateTo:GetVec2() )
|
||||
Route[#Route].task = Helicopter:TaskCombo( Tasks )
|
||||
|
||||
|
||||
Route[#Route+1] = WaypointTo
|
||||
|
||||
-- Now route the helicopter
|
||||
Helicopter:Route(Route, 0)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -361,9 +361,9 @@ do -- COORDINATE
|
||||
|
||||
-- Adjust height
|
||||
if altitude==nil then
|
||||
_coord.y=altitude
|
||||
else
|
||||
_coord.y=self:GetLandHeight()
|
||||
else
|
||||
_coord.y=altitude
|
||||
end
|
||||
|
||||
return _coord
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
-- @module Functional.Mantis
|
||||
-- @image Functional.Mantis.jpg
|
||||
|
||||
-- Date: Jan 2021
|
||||
-- Date: Feb 2021
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
--- **MANTIS** class, extends #Core.Base#BASE
|
||||
@ -31,7 +31,7 @@
|
||||
-- @field Core.Set#SET_GROUP SAM_Group The SAM #SET_GROUP
|
||||
-- @field #string EWR_Templates_Prefix Prefix to build the #SET_GROUP for EWR group
|
||||
-- @field Core.Set#SET_GROUP EWR_Group The EWR #SET_GROUP
|
||||
-- @field #Core.Set#SET_GROUP Adv_EWR_Group The EWR #SET_GROUP used for advanced mode
|
||||
-- @field Core.Set#SET_GROUP Adv_EWR_Group The EWR #SET_GROUP used for advanced mode
|
||||
-- @field #string HQ_Template_CC The ME name of the HQ object
|
||||
-- @field Wrapper.Group#GROUP HQ_CC The #GROUP object of the HQ
|
||||
-- @field #table SAM_Table Table of SAM sites
|
||||
@ -54,6 +54,7 @@
|
||||
-- @field Functional.Shorad#SHORAD Shorad SHORAD Object, if available
|
||||
-- @field #boolean ShoradLink If true, #MANTIS has #SHORAD enabled
|
||||
-- @field #number ShoradTime Timer in seconds, how long #SHORAD will be active after a detection inside of the defense range
|
||||
-- @field #number ShoradActDistance Distance of an attacker in meters from a Mantis SAM site, on which Shorad will be switched on. Useful to not give away Shorad sites too early. Default 15km. Should be smaller than checkradius.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
@ -127,7 +128,7 @@
|
||||
-- * grouping = 5000 (meters) - Detection (EWR) will group enemy flights to areas of 5km for tracking - `MANTIS:SetEWRGrouping(radius)`
|
||||
-- * acceptrange = 80000 (meters) - Detection (EWR) will on consider flights inside a 80km radius - `MANTIS:SetEWRRange(radius)`
|
||||
-- * detectinterval = 30 (seconds) - MANTIS will decide every 30 seconds which SAM to activate - `MANTIS:SetDetectInterval(interval)`
|
||||
-- * engagerange = 75 (percent) - SAMs will only fire if flights are inside of a 75% radius of their max firerange - `MANTIS:SetSAMRange(range)`
|
||||
-- * engagerange = 85 (percent) - SAMs will only fire if flights are inside of a 85% radius of their max firerange - `MANTIS:SetSAMRange(range)`
|
||||
-- * dynamic = false - Group filtering is set to once, i.e. newly added groups will not be part of the setup by default - `MANTIS:New(name,samprefix,ewrprefix,hq,coaltion,dynamic)`
|
||||
-- * autorelocate = false - HQ and (mobile) EWR system will not relocate in random intervals between 30mins and 1 hour - `MANTIS:SetAutoRelocate(hq, ewr)`
|
||||
-- * debug = false - Debugging reports on screen are set to off - `MANTIS:Debug(onoff)`
|
||||
@ -135,8 +136,26 @@
|
||||
-- # 4. Advanced Mode
|
||||
--
|
||||
-- Advanced mode will *decrease* reactivity of MANTIS, if HQ and/or EWR network dies. Awacs is counted as one EWR unit. It will set SAMs to RED state if both are dead. Requires usage of an **HQ** object and the **dynamic** option.
|
||||
-- E.g. `mymantis:SetAdvancedMode( true, 90 )`
|
||||
--
|
||||
-- E.g. `mymantis:SetAdvancedMode( true, 90 )`
|
||||
--
|
||||
-- Use this option if you want to make use of or allow advanced SEAD tactics.
|
||||
--
|
||||
-- # 5. Integrate SHORAD
|
||||
--
|
||||
-- You can also choose to integrate Mantis with @{Functional.Shorad#SHORAD} for protection against HARMs and AGMs. When SHORAD detects a missile fired at one of MANTIS' SAM sites, it will activate SHORAD systems in
|
||||
-- the given defense checkradius around that SAM site. Create a SHORAD object first, then integrate with MANTIS like so:
|
||||
--
|
||||
-- `local SamSet = SET_GROUP:New():FilterPrefixes("Blue SAM"):FilterCoalitions("blue"):FilterStart()`
|
||||
-- `myshorad = SHORAD:New("BlueShorad", "Blue SHORAD", SamSet, 22000, 600, "blue")`
|
||||
-- `-- now set up MANTIS`
|
||||
-- `mymantis = MANTIS:New("BlueMantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")`
|
||||
-- `mymantis:AddShorad(myshorad,720)`
|
||||
-- `mymantis:Start()`
|
||||
--
|
||||
-- and (optionally) remove the link later on with
|
||||
--
|
||||
-- `mymantis:RemoveShorad()`
|
||||
--
|
||||
-- @field #MANTIS
|
||||
MANTIS = {
|
||||
@ -169,7 +188,8 @@ MANTIS = {
|
||||
awacsrange = 250000,
|
||||
Shorad = nil,
|
||||
ShoradLink = false,
|
||||
ShoradTime = 600,
|
||||
ShoradTime = 600,
|
||||
ShoradActDistance = 15000,
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
@ -235,19 +255,20 @@ do
|
||||
self.verbose = false
|
||||
self.Adv_EWR_Group = nil
|
||||
self.AWACS_Prefix = awacs or nil
|
||||
self.awacsrange = 250000 --TODO: 250km, User Function to change
|
||||
self.awacsrange = 250000 --DONE: 250km, User Function to change
|
||||
self.Shorad = nil
|
||||
self.ShoradLink = false
|
||||
self.ShoradTime = 600
|
||||
self.ShoradTime = 600
|
||||
self.ShoradActDistance = 15000
|
||||
|
||||
if type(awacs) == "string" then
|
||||
self.advAwacs = true
|
||||
else
|
||||
self.advAwacs = false
|
||||
end
|
||||
|
||||
-- @field #string version
|
||||
self.version="0.3.6"
|
||||
env.info(string.format("***** Starting MANTIS Version %s *****", self.version))
|
||||
-- Inherit everything from BASE class.
|
||||
local self = BASE:Inherit(self, BASE:New()) -- #MANTIS
|
||||
|
||||
-- Set the string id for output to DCS.log file.
|
||||
self.lid=string.format("MANTIS %s | ", self.name)
|
||||
@ -276,8 +297,10 @@ do
|
||||
if self.HQ_Template_CC then
|
||||
self.HQ_CC = GROUP:FindByName(self.HQ_Template_CC)
|
||||
end
|
||||
-- Inherit everything from BASE class.
|
||||
local self = BASE:Inherit(self, BASE:New()) -- #MANTIS
|
||||
|
||||
-- @field #string version
|
||||
self.version="0.3.7"
|
||||
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
|
||||
|
||||
return self
|
||||
end
|
||||
@ -379,6 +402,14 @@ do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Function to set AWACS detection range. Defaults to 250.000m (250km) - use **before** starting your Mantis!
|
||||
-- @param #MANTIS self
|
||||
-- @param #number range Detection range of the AWACS group
|
||||
function MANTIS:SetAwacsRange(range)
|
||||
local range = range or 250000
|
||||
self.awacsrange = range
|
||||
end
|
||||
|
||||
--- Function to set the HQ object for further use
|
||||
-- @param #MANTIS self
|
||||
@ -569,6 +600,7 @@ do
|
||||
-- @param #table dectset Table of coordinates of detected items
|
||||
-- @param samcoordinate Core.Point#COORDINATE Coordinate object.
|
||||
-- @return #boolean True if in any zone, else false
|
||||
-- @return #number Distance Target distance in meters or zero when no object is in zone
|
||||
function MANTIS:CheckObjectInZone(dectset, samcoordinate)
|
||||
self:F(self.lid.."CheckObjectInZone Called")
|
||||
-- check if non of the coordinate is in the given defense zone
|
||||
@ -585,10 +617,10 @@ do
|
||||
if self.verbose then env.info(self.lid..text) end
|
||||
-- end output to cross-check
|
||||
if targetdistance <= radius then
|
||||
return true
|
||||
return true, targetdistance
|
||||
end
|
||||
end
|
||||
return false
|
||||
return false, 0
|
||||
end
|
||||
|
||||
--- (Internal) Function to start the detection via EWR groups
|
||||
@ -658,7 +690,7 @@ do
|
||||
-- @param #MANTIS self
|
||||
-- @return #MANTIS self
|
||||
function MANTIS:SetSAMStartState()
|
||||
-- TODO: if using dynamic filtering, update SAM_Table and the (active) SEAD groups, pull req #1405/#1406
|
||||
-- DONE: if using dynamic filtering, update SAM_Table and the (active) SEAD groups, pull req #1405/#1406
|
||||
self:F(self.lid.."Setting SAM Start States")
|
||||
-- get SAM Group
|
||||
local SAM_SET = self.SAM_Group
|
||||
@ -769,13 +801,14 @@ do
|
||||
local samcoordinate = _data[2]
|
||||
local name = _data[1]
|
||||
local samgroup = GROUP:FindByName(name)
|
||||
if self:CheckObjectInZone(detset, samcoordinate) then --check any target in zone
|
||||
local IsInZone, Distance = self:CheckObjectInZone(detset, samcoordinate)
|
||||
if IsInZone then --check any target in zone
|
||||
if samgroup:IsAlive() then
|
||||
-- switch off SAM
|
||||
samgroup:OptionAlarmStateRed()
|
||||
-- link in to SHORAD if available
|
||||
-- TODO Test integration fully
|
||||
if self.ShoradLink then
|
||||
-- DONE: Test integration fully
|
||||
if self.ShoradLink and Distance < self.ShoradActDistance then -- don't give SHORAD position away too early
|
||||
local Shorad = self.Shorad
|
||||
local radius = self.checkradius
|
||||
local ontime = self.ShoradTime
|
||||
|
||||
@ -378,7 +378,14 @@ do
|
||||
-- @param #string TargetGroup Name of the target group used to build the #ZONE
|
||||
-- @param #number Radius Radius of the #ZONE
|
||||
-- @param #number ActiveTimer Number of seconds to stay active
|
||||
-- @usage Use this function to integrate with other systems.
|
||||
-- @usage Use this function to integrate with other systems, example
|
||||
--
|
||||
-- local SamSet = SET_GROUP:New():FilterPrefixes("Blue SAM"):FilterCoalitions("blue"):FilterStart()
|
||||
-- myshorad = SHORAD:New("BlueShorad", "Blue SHORAD", SamSet, 22000, 600, "blue")
|
||||
-- myshorad:SwitchDebug(true)
|
||||
-- mymantis = MANTIS:New("BlueMantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")
|
||||
-- mymantis:AddShorad(myshorad,720)
|
||||
-- mymantis:Start()
|
||||
function SHORAD:WakeUpShorad(TargetGroup, Radius, ActiveTimer)
|
||||
self:F({TargetGroup, Radius, ActiveTimer})
|
||||
local targetgroup = GROUP:FindByName(TargetGroup)
|
||||
|
||||
@ -966,7 +966,7 @@ function AIRWING:CheckTANKER()
|
||||
|
||||
local altitude=patrol.altitude+1000*patrol.noccupied
|
||||
|
||||
local mission=AUFTRAG:NewTANKER(patrol.coord, altitude, patrol.speed, patrol.heading, patrol.leg, 0)
|
||||
local mission=AUFTRAG:NewTANKER(patrol.coord, altitude, patrol.speed, patrol.heading, patrol.leg, 1)
|
||||
|
||||
mission.patroldata=patrol
|
||||
|
||||
@ -984,7 +984,7 @@ function AIRWING:CheckTANKER()
|
||||
|
||||
local altitude=patrol.altitude+1000*patrol.noccupied
|
||||
|
||||
local mission=AUFTRAG:NewTANKER(patrol.coord, altitude, patrol.speed, patrol.heading, patrol.leg, 1)
|
||||
local mission=AUFTRAG:NewTANKER(patrol.coord, altitude, patrol.speed, patrol.heading, patrol.leg, 0)
|
||||
|
||||
mission.patroldata=patrol
|
||||
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
-- * [F-14A/B Tomcat](https://forums.eagle.ru/forumdisplay.php?f=395) (Player & AI)
|
||||
-- * [A-4E Skyhawk Community Mod](https://forums.eagle.ru/showthread.php?t=224989) (Player & AI)
|
||||
-- * [AV-8B N/A Harrier](https://forums.eagle.ru/forumdisplay.php?f=555) (Player & AI) [**WIP**]
|
||||
-- * [T-45C Goshawk (VNAO)(Player & AI)]
|
||||
-- * F/A-18C Hornet (AI)
|
||||
-- * F-14A Tomcat (AI)
|
||||
-- * E-2D Hawkeye (AI)
|
||||
@ -1271,6 +1272,7 @@ AIRBOSS.AircraftCarrier={
|
||||
F14B="F-14B",
|
||||
F14A_AI="F-14A",
|
||||
FA18C="F/A-18C",
|
||||
T45C="T-45",
|
||||
S3B="S-3B",
|
||||
S3BTANKER="S-3B Tanker",
|
||||
E2D="E-2C",
|
||||
@ -1705,7 +1707,7 @@ AIRBOSS.MenuF10Root=nil
|
||||
|
||||
--- Airboss class version.
|
||||
-- @field #string version
|
||||
AIRBOSS.version="1.1.5"
|
||||
AIRBOSS.version="1.1.6"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@ -1939,7 +1941,7 @@ function AIRBOSS:New(carriername, alias)
|
||||
|
||||
-- Welcome players.
|
||||
self:SetWelcomePlayers(true)
|
||||
|
||||
|
||||
-- Coordinates
|
||||
self.landingcoord=COORDINATE:New(0,0,0) --Core.Point#COORDINATE
|
||||
self.sterncoord=COORDINATE:New(0, 0, 0) --Core.Point#COORDINATE
|
||||
@ -1951,11 +1953,11 @@ function AIRBOSS:New(carriername, alias)
|
||||
elseif self.carriertype==AIRBOSS.CarrierType.ROOSEVELT then
|
||||
self:_InitNimitz()
|
||||
elseif self.carriertype==AIRBOSS.CarrierType.LINCOLN then
|
||||
self:_InitNimitz()
|
||||
elseif self.carriertype==AIRBOSS.CarrierType.WASHINGTON then
|
||||
self:_InitNimitz()
|
||||
elseif self.carriertype==AIRBOSS.CarrierType.TRUMAN then
|
||||
self:_InitNimitz()
|
||||
elseif self.carriertype==AIRBOSS.CarrierType.WASHINGTON then
|
||||
self:_InitNimitz()
|
||||
elseif self.carriertype==AIRBOSS.CarrierType.TRUMAN then
|
||||
self:_InitNimitz()
|
||||
elseif self.carriertype==AIRBOSS.CarrierType.VINSON then
|
||||
-- TODO: Carl Vinson parameters.
|
||||
self:_InitStennis()
|
||||
@ -1993,7 +1995,7 @@ function AIRBOSS:New(carriername, alias)
|
||||
self:_GetZoneGroove():SmokeZone(SMOKECOLOR.Red, 5)
|
||||
self:_GetZoneLineup():SmokeZone(SMOKECOLOR.Green, 5)
|
||||
self:_GetZoneBullseye(case):SmokeZone(SMOKECOLOR.White, 45)
|
||||
self:_GetZoneDirtyUp(case):SmokeZone(SMOKECOLOR.Orange, 45)
|
||||
self:_GetZoneDirtyUp(case):SmokeZone(SMOKECOLOR.Orange, 45)
|
||||
self:_GetZoneArcIn(case):SmokeZone(SMOKECOLOR.Blue, 45)
|
||||
self:_GetZoneArcOut(case):SmokeZone(SMOKECOLOR.Blue, 45)
|
||||
self:_GetZonePlatform(case):SmokeZone(SMOKECOLOR.Blue, 45)
|
||||
@ -2033,7 +2035,7 @@ function AIRBOSS:New(carriername, alias)
|
||||
|
||||
-- Bow
|
||||
bow:FlareYellow()
|
||||
|
||||
|
||||
-- Runway half width = 10 m.
|
||||
local r1=stern:Translate(self.carrierparam.rwywidth*0.5, FB+90)
|
||||
local r2=stern:Translate(self.carrierparam.rwywidth*0.5, FB-90)
|
||||
@ -2646,6 +2648,15 @@ function AIRBOSS:SetRecoveryTurnTime(interval)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set multiplayer environment wire correction.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number Dcorr Correction distance in meters. Default 8.7 m.
|
||||
-- @return #AIRBOSS self
|
||||
function AIRBOSS:SetMPWireCorrection(Dcorr)
|
||||
self.mpWireCorrection=Dcorr or 8.7
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set time interval for updating queues and other stuff.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number interval Time interval in seconds. Default 30 sec.
|
||||
@ -3284,7 +3295,7 @@ function AIRBOSS:GetNextRecoveryTime(InSeconds)
|
||||
if InSeconds then
|
||||
return self.recoverywindow.START, self.recoverywindow.STOP
|
||||
else
|
||||
return UTILS.SecondsToClock(self.recoverywindow.START), UTILS.SecondsToClock(self.recoverywindow.STOP)
|
||||
return UTILS.SecondsToClock(self.recoverywindow.START), UTILS.SecondsToClock(self.recoverywindow.STOP)
|
||||
end
|
||||
else
|
||||
if InSeconds then
|
||||
@ -3398,7 +3409,7 @@ function AIRBOSS:onafterStart(From, Event, To)
|
||||
|
||||
--self.StatusScheduler=SCHEDULER:New(self)
|
||||
--self.StatusScheduler:Schedule(self, self._Status, {}, 1, 0.5)
|
||||
|
||||
|
||||
self.StatusTimer=TIMER:New(self._Status, self):Start(2, 0.5)
|
||||
|
||||
-- Start status check in 1 second.
|
||||
@ -3484,9 +3495,9 @@ function AIRBOSS:onafterStatus(From, Event, To)
|
||||
-- Disable turn into the wind for this window so that we do not do this all over again.
|
||||
self.recoverywindow.WIND=false
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -3582,9 +3593,9 @@ function AIRBOSS:_CheckAIStatus()
|
||||
|
||||
-- Get lineup and distance to carrier.
|
||||
local lineup=self:_Lineup(unit, true)
|
||||
|
||||
|
||||
local unitcoord=unit:GetCoord()
|
||||
|
||||
|
||||
local dist=unitcoord:Get2DDistance(self:GetCoord())
|
||||
|
||||
-- Distance in NM.
|
||||
@ -4145,7 +4156,7 @@ end
|
||||
-- @param #string To To state.
|
||||
function AIRBOSS:onafterStop(From, Event, To)
|
||||
self:I(self.lid..string.format("Stopping airboss script."))
|
||||
|
||||
|
||||
-- Unhandle events.
|
||||
self:UnHandleEvent(EVENTS.Birth)
|
||||
self:UnHandleEvent(EVENTS.Land)
|
||||
@ -4169,7 +4180,7 @@ function AIRBOSS:_InitStennis()
|
||||
|
||||
-- Carrier Parameters.
|
||||
self.carrierparam.sterndist =-153
|
||||
self.carrierparam.deckheight = 19
|
||||
self.carrierparam.deckheight = 19.06
|
||||
|
||||
-- Total size of the carrier (approx as rectangle).
|
||||
self.carrierparam.totlength=310 -- Wiki says 332.8 meters overall length.
|
||||
@ -4177,7 +4188,7 @@ function AIRBOSS:_InitStennis()
|
||||
self.carrierparam.totwidthstarboard=30
|
||||
|
||||
-- Landing runway.
|
||||
self.carrierparam.rwyangle = -9
|
||||
self.carrierparam.rwyangle = -9.1359
|
||||
self.carrierparam.rwylength = 225
|
||||
self.carrierparam.rwywidth = 20
|
||||
|
||||
@ -4320,7 +4331,7 @@ function AIRBOSS:_InitNimitz()
|
||||
|
||||
-- Carrier Parameters.
|
||||
self.carrierparam.sterndist =-164
|
||||
self.carrierparam.deckheight = 20
|
||||
self.carrierparam.deckheight = 20.1494 --DCS World OpenBeta\CoreMods\tech\USS_Nimitz\Database\USS_CVN_7X.lua
|
||||
|
||||
-- Total size of the carrier (approx as rectangle).
|
||||
self.carrierparam.totlength=332.8 -- Wiki says 332.8 meters overall length.
|
||||
@ -4328,7 +4339,7 @@ function AIRBOSS:_InitNimitz()
|
||||
self.carrierparam.totwidthstarboard=35
|
||||
|
||||
-- Landing runway.
|
||||
self.carrierparam.rwyangle = -9
|
||||
self.carrierparam.rwyangle = -9.1359 --DCS World OpenBeta\CoreMods\tech\USS_Nimitz\scripts\USS_Nimitz_RunwaysAndRoutes.lua
|
||||
self.carrierparam.rwylength = 250
|
||||
self.carrierparam.rwywidth = 25
|
||||
|
||||
@ -5471,6 +5482,7 @@ function AIRBOSS:_GetAircraftAoA(playerData)
|
||||
|
||||
-- Get AC type.
|
||||
local hornet=playerData.actype==AIRBOSS.AircraftCarrier.HORNET
|
||||
local goshawk=playerData.actype==AIRBOSS.AircraftCarrier.T45C
|
||||
local skyhawk=playerData.actype==AIRBOSS.AircraftCarrier.A4EC
|
||||
local harrier=playerData.actype==AIRBOSS.AircraftCarrier.AV8B
|
||||
local tomcat=playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B
|
||||
@ -5497,6 +5509,15 @@ function AIRBOSS:_GetAircraftAoA(playerData)
|
||||
aoa.OnSpeedMin = self:_AoAUnit2Deg(playerData, 14.5) --14.17 --14.5 units
|
||||
aoa.Fast = self:_AoAUnit2Deg(playerData, 14.0) --13.33 --14.0 units
|
||||
aoa.FAST = self:_AoAUnit2Deg(playerData, 13.0) --11.67 --13.0 units
|
||||
elseif goshawk then
|
||||
-- T-45C Goshawk parameters.
|
||||
aoa.SLOW = 8.00 --19
|
||||
aoa.Slow = 7.75 --18
|
||||
aoa.OnSpeedMax = 7.25 --17.5
|
||||
aoa.OnSpeed = 7.00 --17
|
||||
aoa.OnSpeedMin = 6.75 --16.5
|
||||
aoa.Fast = 6.25 --16
|
||||
aoa.FAST = 6.00 --15
|
||||
elseif skyhawk then
|
||||
-- A-4E-C Skyhawk parameters from https://forums.eagle.ru/showpost.php?p=3703467&postcount=390
|
||||
-- Note that these are arbitrary UNITS and not degrees. We need a conversion formula!
|
||||
@ -5681,6 +5702,9 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(600)
|
||||
speed=UTILS.KnotsToMps(250)
|
||||
elseif goshawk then
|
||||
alt=UTILS.FeetToMeters(800)
|
||||
speed=UTILS.KnotsToMps(300)
|
||||
end
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.BREAKENTRY then
|
||||
@ -5691,11 +5715,14 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(600)
|
||||
speed=UTILS.KnotsToMps(250)
|
||||
elseif goshawk then
|
||||
alt=UTILS.FeetToMeters(800)
|
||||
speed=UTILS.KnotsToMps(300)
|
||||
end
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.EARLYBREAK then
|
||||
|
||||
if hornet or tomcat or harrier then
|
||||
if hornet or tomcat or harrier or goshawk then
|
||||
alt=UTILS.FeetToMeters(800)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(600)
|
||||
@ -5703,7 +5730,7 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.LATEBREAK then
|
||||
|
||||
if hornet or tomcat or harrier then
|
||||
if hornet or tomcat or harrier or goshawk then
|
||||
alt=UTILS.FeetToMeters(800)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(600)
|
||||
@ -5711,7 +5738,7 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.ABEAM then
|
||||
|
||||
if hornet or tomcat or harrier then
|
||||
if hornet or tomcat or harrier or goshawk then
|
||||
alt=UTILS.FeetToMeters(600)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(500)
|
||||
@ -5726,10 +5753,19 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
|
||||
dist=UTILS.NMToMeters(1.2)
|
||||
end
|
||||
|
||||
if goshawk then
|
||||
-- 0.9 to 1.1 NM per natops ch.4 page 48
|
||||
dist=UTILS.NMToMeters(0.9)
|
||||
else
|
||||
dist=UTILS.NMToMeters(1.1)
|
||||
end
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.NINETY then
|
||||
|
||||
if hornet or tomcat then
|
||||
alt=UTILS.FeetToMeters(500)
|
||||
elseif goshawk then
|
||||
alt=UTILS.FeetToMeters(450)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(500)
|
||||
elseif harrier then
|
||||
@ -5740,7 +5776,7 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.WAKE then
|
||||
|
||||
if hornet then
|
||||
if hornet or goshawk then
|
||||
alt=UTILS.FeetToMeters(370)
|
||||
elseif tomcat then
|
||||
alt=UTILS.FeetToMeters(430) -- Tomcat should be a bit higher as it intercepts the GS a bit higher.
|
||||
@ -5753,7 +5789,7 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.FINAL then
|
||||
|
||||
if hornet then
|
||||
if hornet or goshawk then
|
||||
alt=UTILS.FeetToMeters(300)
|
||||
elseif tomcat then
|
||||
alt=UTILS.FeetToMeters(360)
|
||||
@ -6086,7 +6122,7 @@ function AIRBOSS:_ScanCarrierZone()
|
||||
|
||||
-- Get flight group.
|
||||
local flight=_DATABASE:GetFlightGroup(groupname)
|
||||
|
||||
|
||||
if flight and flight:IsInbound() and flight.destbase:GetName()==self.carrier:GetName() then
|
||||
if flight.ishelo then
|
||||
else
|
||||
@ -6123,7 +6159,7 @@ function AIRBOSS:_ScanCarrierZone()
|
||||
-- Break the loop to not have all flights at once! Spams the message screen.
|
||||
break
|
||||
|
||||
end -- Closed in or tanker/AWACS
|
||||
end -- Closed in or tanker/AWACS
|
||||
|
||||
end
|
||||
|
||||
@ -6229,7 +6265,7 @@ function AIRBOSS:_MarshalPlayer(playerData, stack)
|
||||
|
||||
-- Set stack flag.
|
||||
flight.flag=stack
|
||||
|
||||
|
||||
-- Trigger Marshal event.
|
||||
self:Marshal(flight)
|
||||
end
|
||||
@ -6488,7 +6524,7 @@ function AIRBOSS:_MarshalAI(flight, nstack, respawn)
|
||||
|
||||
-- Route group.
|
||||
flight.group:Route(wp, 1)
|
||||
|
||||
|
||||
-- Trigger Marshal event.
|
||||
self:Marshal(flight)
|
||||
|
||||
@ -7024,7 +7060,7 @@ function AIRBOSS:_GetFreeStack(ai, case, empty)
|
||||
|
||||
-- Recovery case.
|
||||
case=case or self.case
|
||||
|
||||
|
||||
if case==1 then
|
||||
return self:_GetFreeStack_Old(ai, case, empty)
|
||||
end
|
||||
@ -7040,7 +7076,7 @@ function AIRBOSS:_GetFreeStack(ai, case, empty)
|
||||
for i=1,nmaxstacks do
|
||||
stack[i]=self.NmaxStack -- Number of human flights per stack.
|
||||
end
|
||||
|
||||
|
||||
local nmax=1
|
||||
|
||||
-- Loop over all flights in marshal stack.
|
||||
@ -7052,7 +7088,7 @@ function AIRBOSS:_GetFreeStack(ai, case, empty)
|
||||
|
||||
-- Get stack of flight.
|
||||
local n=flight.flag
|
||||
|
||||
|
||||
if n>nmax then
|
||||
nmax=n
|
||||
end
|
||||
@ -7069,7 +7105,7 @@ function AIRBOSS:_GetFreeStack(ai, case, empty)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local nfree=nil
|
||||
if stack[nmax]==0 then
|
||||
-- Max occupied stack is completely full!
|
||||
@ -7085,7 +7121,7 @@ function AIRBOSS:_GetFreeStack(ai, case, empty)
|
||||
-- Case II/III return next stack
|
||||
nfree=nmax+1
|
||||
end
|
||||
|
||||
|
||||
elseif stack[nmax]==self.NmaxStack then
|
||||
-- Max occupied stack is completely empty! This should happen only when there is no other flight in the marshal queue.
|
||||
self:E(self.lid..string.format("ERROR: Max occupied stack is empty. Should not happen! Nmax=%d, stack[nmax]=%d", nmax, stack[nmax]))
|
||||
@ -7097,7 +7133,7 @@ function AIRBOSS:_GetFreeStack(ai, case, empty)
|
||||
else
|
||||
nfree=nmax
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
self:I(self.lid..string.format("Returning free stack %s", tostring(nfree)))
|
||||
@ -10370,7 +10406,7 @@ function AIRBOSS:_GetSternCoord()
|
||||
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(7, FB+90, true, true)
|
||||
else
|
||||
-- Nimitz SC: translate 8 meters starboard wrt Final bearing.
|
||||
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(8.5, FB+90, true, true)
|
||||
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(9.5, FB+90, true, true)
|
||||
end
|
||||
|
||||
-- Set altitude.
|
||||
@ -10400,6 +10436,11 @@ function AIRBOSS:_GetWire(Lcoord, dc)
|
||||
|
||||
-- Corrected landing distance wrt to stern. Landing distance needs to be reduced due to delayed landing event for human players.
|
||||
local d=Ldist-dc
|
||||
|
||||
-- Multiplayer wire correction.
|
||||
if self.mpWireCorrection then
|
||||
d=d-self.mpWireCorrection
|
||||
end
|
||||
|
||||
-- Shift wires from stern to their correct position.
|
||||
local w1=self.carrierparam.wire1
|
||||
@ -10491,6 +10532,9 @@ function AIRBOSS:_Trapped(playerData)
|
||||
elseif playerData.actype==AIRBOSS.AircraftCarrier.A4EC then
|
||||
-- A-4E gets slowed down much faster the the F/A-18C!
|
||||
dcorr=56
|
||||
elseif playerData.actype==AIRBOSS.AircraftCarrier.T45C then
|
||||
-- T-45 also gets slowed down much faster the the F/A-18C.
|
||||
dcorr=56
|
||||
end
|
||||
|
||||
-- Get wire.
|
||||
@ -10617,7 +10661,7 @@ function AIRBOSS:_GetZoneInitial(case)
|
||||
|
||||
-- Polygon zone.
|
||||
--local zone=ZONE_POLYGON_BASE:New("Zone CASE I/II Initial", vec2)
|
||||
|
||||
|
||||
self.zoneInitial:UpdateFromVec2(vec2)
|
||||
|
||||
--return zone
|
||||
@ -10646,13 +10690,13 @@ function AIRBOSS:_GetZoneLineup()
|
||||
|
||||
-- Vec2 array.
|
||||
local vec2={c1:GetVec2(), c2:GetVec2(), c3:GetVec2(), c4:GetVec2(), c5:GetVec2()}
|
||||
|
||||
|
||||
self.zoneLineup:UpdateFromVec2(vec2)
|
||||
|
||||
-- Polygon zone.
|
||||
--local zone=ZONE_POLYGON_BASE:New("Zone Lineup", vec2)
|
||||
--return zone
|
||||
|
||||
|
||||
return self.zoneLineup
|
||||
end
|
||||
|
||||
@ -10687,13 +10731,13 @@ function AIRBOSS:_GetZoneGroove(l, w, b)
|
||||
|
||||
-- Vec2 array.
|
||||
local vec2={c1:GetVec2(), c2:GetVec2(), c3:GetVec2(), c4:GetVec2(), c5:GetVec2(), c6:GetVec2()}
|
||||
|
||||
|
||||
self.zoneGroove:UpdateFromVec2(vec2)
|
||||
|
||||
-- Polygon zone.
|
||||
--local zone=ZONE_POLYGON_BASE:New("Zone Groove", vec2)
|
||||
--return zone
|
||||
|
||||
|
||||
return self.zoneGroove
|
||||
end
|
||||
|
||||
@ -10719,7 +10763,7 @@ function AIRBOSS:_GetZoneBullseye(case)
|
||||
-- Create zone.
|
||||
local zone=ZONE_RADIUS:New("Zone Bullseye", vec2, radius)
|
||||
return zone
|
||||
|
||||
|
||||
--self.zoneBullseye=self.zoneBullseye or ZONE_RADIUS:New("Zone Bullseye", vec2, radius)
|
||||
end
|
||||
|
||||
@ -10948,9 +10992,9 @@ function AIRBOSS:_GetZoneCarrierBox()
|
||||
-- Create polygon zone.
|
||||
--local zone=ZONE_POLYGON_BASE:New("Carrier Box Zone", vec2)
|
||||
--return zone
|
||||
|
||||
|
||||
self.zoneCarrierbox:UpdateFromVec2(vec2)
|
||||
|
||||
|
||||
return self.zoneCarrierbox
|
||||
end
|
||||
|
||||
@ -10985,9 +11029,9 @@ function AIRBOSS:_GetZoneRunwayBox()
|
||||
-- Create polygon zone.
|
||||
--local zone=ZONE_POLYGON_BASE:New("Landing Runway Zone", vec2)
|
||||
--return zone
|
||||
|
||||
|
||||
self.zoneRunwaybox:UpdateFromVec2(vec2)
|
||||
|
||||
|
||||
return self.zoneRunwaybox
|
||||
end
|
||||
|
||||
@ -11118,7 +11162,7 @@ function AIRBOSS:_GetZoneHolding(case, stack)
|
||||
-- Square zone length=7NM width=6 NM behind the carrier starting at angels+15 NM behind the carrier.
|
||||
-- So stay 0-5 NM (+1 NM error margin) port of carrier.
|
||||
self.zoneHolding=self.zoneHolding or ZONE_POLYGON_BASE:New("CASE II/III Holding Zone")
|
||||
|
||||
|
||||
self.zoneHolding:UpdateFromVec2(p)
|
||||
end
|
||||
|
||||
@ -11164,12 +11208,12 @@ function AIRBOSS:_GetZoneCommence(case, stack)
|
||||
|
||||
-- Create holding zone.
|
||||
self.zoneCommence=self.zoneCommence or ZONE_RADIUS:New("CASE I Commence Zone")
|
||||
|
||||
|
||||
self.zoneCommence:UpdateFromVec2(Three:GetVec2(), R)
|
||||
|
||||
else
|
||||
-- Case II/III
|
||||
|
||||
|
||||
stack=stack or 1
|
||||
|
||||
-- Start point at 21 NM for stack=1.
|
||||
@ -11197,7 +11241,7 @@ function AIRBOSS:_GetZoneCommence(case, stack)
|
||||
|
||||
-- Zone polygon.
|
||||
self.zoneCommence=self.zoneCommence or ZONE_POLYGON_BASE:New("CASE II/III Commence Zone")
|
||||
|
||||
|
||||
self.zoneCommence:UpdateFromVec2(p)
|
||||
|
||||
end
|
||||
@ -11445,7 +11489,7 @@ end
|
||||
-- @param #AIRBOSS self
|
||||
-- @return Core.Point#COORDINATE Optimal landing coordinate.
|
||||
function AIRBOSS:_GetOptLandingCoordinate()
|
||||
|
||||
|
||||
-- Start with stern coordiante.
|
||||
self.landingcoord:UpdateFromCoordinate(self:_GetSternCoord())
|
||||
|
||||
@ -12001,15 +12045,15 @@ function AIRBOSS:_EvalGrooveTime(playerData)
|
||||
|
||||
local grade=""
|
||||
if t<9 then
|
||||
grade="--"
|
||||
elseif t<12 then
|
||||
grade="(OK)"
|
||||
elseif t<22 then
|
||||
grade="OK"
|
||||
grade="_NESA_"
|
||||
elseif t<15 then
|
||||
grade="NESA"
|
||||
elseif t<19 then
|
||||
grade="OK Groove"
|
||||
elseif t<=24 then
|
||||
grade="(OK)"
|
||||
grade="(LIG)"
|
||||
else
|
||||
grade="--"
|
||||
grade="LIG"
|
||||
end
|
||||
|
||||
-- The unicorn!
|
||||
@ -12050,7 +12094,7 @@ function AIRBOSS:_LSOgrade(playerData)
|
||||
|
||||
-- Groove time 16-18 sec for a unicorn.
|
||||
local Tgroove=playerData.Tgroove
|
||||
local TgrooveUnicorn=Tgroove and (Tgroove>=16.0 and Tgroove<=18.0) or false
|
||||
local TgrooveUnicorn=Tgroove and (Tgroove>=15.0 and Tgroove<=18.99) or false
|
||||
|
||||
local grade
|
||||
local points
|
||||
@ -14080,6 +14124,8 @@ function AIRBOSS:_GetACNickname(actype)
|
||||
local nickname="unknown"
|
||||
if actype==AIRBOSS.AircraftCarrier.A4EC then
|
||||
nickname="Skyhawk"
|
||||
elseif actype==AIRBOSS.AircraftCarrier.T45C then
|
||||
nickname="Goshawk"
|
||||
elseif actype==AIRBOSS.AircraftCarrier.AV8B then
|
||||
nickname="Harrier"
|
||||
elseif actype==AIRBOSS.AircraftCarrier.E2D then
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
-- @field #boolean clustermarkers If true, create cluster markers on F10 map.
|
||||
-- @field #number clustercounter Running number of clusters.
|
||||
-- @field #number dTforget Time interval in seconds before a known contact which is not detected any more is forgotten.
|
||||
-- @field #number clusterradius Radius im kilometers in which groups/units are considered to belong to a cluster
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- Top Secret!
|
||||
@ -46,7 +47,7 @@
|
||||
-- @field #INTEL
|
||||
INTEL = {
|
||||
ClassName = "INTEL",
|
||||
verbose = 2,
|
||||
verbose = 0,
|
||||
lid = nil,
|
||||
alias = nil,
|
||||
filterCategory = {},
|
||||
@ -56,6 +57,7 @@ INTEL = {
|
||||
ContactsUnknown = {},
|
||||
Clusters = {},
|
||||
clustercounter = 1,
|
||||
clusterradius = 15,
|
||||
}
|
||||
|
||||
--- Detected item info.
|
||||
@ -74,6 +76,8 @@ INTEL = {
|
||||
-- @field #boolean isship
|
||||
-- @field #boolean ishelo
|
||||
-- @field #boolean isgrund
|
||||
-- @field Ops.Auftrag#AUFTRAG mission The current Auftrag attached to this contact
|
||||
-- @field #string recce The name of the recce unit that detected this contact
|
||||
|
||||
--- Cluster info.
|
||||
-- @type INTEL.Cluster
|
||||
@ -85,11 +89,12 @@ INTEL = {
|
||||
-- @field #number threatlevelAve Average of threat levels.
|
||||
-- @field Core.Point#COORDINATE coordinate Coordinate of the cluster.
|
||||
-- @field Wrapper.Marker#MARKER marker F10 marker.
|
||||
-- @field Ops.Auftrag#AUFTRAG mission The current Auftrag attached to this cluster
|
||||
|
||||
|
||||
--- INTEL class version.
|
||||
-- @field #string version
|
||||
INTEL.version="0.1.0"
|
||||
INTEL.version="0.2.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
@ -175,6 +180,8 @@ function INTEL:New(DetectionSet, Coalition, Alias)
|
||||
self:AddTransition("*", "NewContact", "*") -- New contact has been detected.
|
||||
self:AddTransition("*", "LostContact", "*") -- Contact could not be detected any more.
|
||||
|
||||
self:AddTransition("*", "NewCluster", "*") -- New cluster has been detected.
|
||||
self:AddTransition("*", "LostCluster", "*") -- Cluster could not be detected any more.
|
||||
|
||||
-- Defaults
|
||||
self:SetForgetTime()
|
||||
@ -210,10 +217,43 @@ function INTEL:New(DetectionSet, Coalition, Alias)
|
||||
-- @function [parent=#INTEL] __Status
|
||||
-- @param #INTEL self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- On After "NewContact" event.
|
||||
-- @function [parent=#INTEL] OnAfterNewContact
|
||||
-- @param #INTEL self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #INTEL.Contact Contact Detected contact.
|
||||
|
||||
--- On After "LostContact" event.
|
||||
-- @function [parent=#INTEL] OnAfterLostContact
|
||||
-- @param #INTEL self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #INTEL.Contact Contact Lost contact.
|
||||
|
||||
--- On After "NewCluster" event.
|
||||
-- @function [parent=#INTEL] OnAfterNewCluster
|
||||
-- @param #INTEL self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #INTEL.Contact Contact Detected contact.
|
||||
-- @param #INTEL.Cluster Cluster Detected cluster
|
||||
|
||||
--- On After "LostCluster" event.
|
||||
-- @function [parent=#INTEL] OnAfterLostCluster
|
||||
-- @param #INTEL self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #INTEL.Cluster Cluster Lost cluster
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The Auftrag connected with this cluster or nil
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -307,7 +347,7 @@ function INTEL:SetFilterCategory(Categories)
|
||||
for _,category in pairs(self.filterCategory) do
|
||||
text=text..string.format("%d,", category)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
self:T(self.lid..text)
|
||||
|
||||
return self
|
||||
end
|
||||
@ -334,7 +374,7 @@ function INTEL:FilterCategoryGroup(GroupCategories)
|
||||
for _,category in pairs(self.filterCategoryGroup) do
|
||||
text=text..string.format("%d,", category)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
self:T(self.lid..text)
|
||||
|
||||
return self
|
||||
end
|
||||
@ -351,6 +391,49 @@ function INTEL:SetClusterAnalysis(Switch, Markers)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set verbosity level for debugging.
|
||||
-- @param #INTEL self
|
||||
-- @param #number Verbosity The higher, the noisier, e.g. 0=off, 2=debug
|
||||
-- @return #INTEL self
|
||||
function INTEL:SetVerbosity(Verbosity)
|
||||
self.verbose=Verbosity or 2
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a Mission (Auftrag) to a contact for tracking.
|
||||
-- @param #INTEL self
|
||||
-- @param #INTEL.Contact Contact The contact
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission connected with this contact
|
||||
-- @return #INTEL self
|
||||
function INTEL:AddMissionToContact(Contact, Mission)
|
||||
if Mission and Contact then
|
||||
Contact.mission = Mission
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a Mission (Auftrag) to a cluster for tracking.
|
||||
-- @param #INTEL self
|
||||
-- @param #INTEL.Cluster Cluster The cluster
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission connected with this cluster
|
||||
-- @return #INTEL self
|
||||
function INTEL:AddMissionToCluster(Cluster, Mission)
|
||||
if Mission and Cluster then
|
||||
Cluster.mission = Mission
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Change radius of the Clusters
|
||||
-- @param #INTEL self
|
||||
-- @param #number radius The radius of the clusters
|
||||
-- @return #INTEL self
|
||||
function INTEL:SetClusterRadius(radius)
|
||||
local radius = radius or 15
|
||||
self.clusterradius = radius
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Start & Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -389,10 +472,11 @@ function INTEL:onafterStatus(From, Event, To)
|
||||
|
||||
-- Number of total contacts.
|
||||
local Ncontacts=#self.Contacts
|
||||
local Nclusters=#self.Clusters
|
||||
|
||||
-- Short info.
|
||||
if self.verbose>=1 then
|
||||
local text=string.format("Status %s [Agents=%s]: Contacts=%d, New=%d, Lost=%d", fsmstate, self.detectionset:CountAlive(), Ncontacts, #self.ContactsUnknown, #self.ContactsLost)
|
||||
local text=string.format("Status %s [Agents=%s]: Contacts=%d, Clusters=%d, New=%d, Lost=%d", fsmstate, self.detectionset:CountAlive(), Ncontacts, Nclusters, #self.ContactsUnknown, #self.ContactsLost)
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
@ -421,7 +505,8 @@ function INTEL:UpdateIntel()
|
||||
|
||||
-- Set of all detected units.
|
||||
local DetectedUnits={}
|
||||
|
||||
-- Set of which units was detected by which recce
|
||||
local RecceDetecting = {}
|
||||
-- Loop over all units providing intel.
|
||||
for _,_group in pairs(self.detectionset.Set or {}) do
|
||||
local group=_group --Wrapper.Group#GROUP
|
||||
@ -432,7 +517,7 @@ function INTEL:UpdateIntel()
|
||||
local recce=_recce --Wrapper.Unit#UNIT
|
||||
|
||||
-- Get detected units.
|
||||
self:GetDetectedUnits(recce, DetectedUnits)
|
||||
self:GetDetectedUnits(recce, DetectedUnits, RecceDetecting)
|
||||
|
||||
end
|
||||
|
||||
@ -489,7 +574,7 @@ function INTEL:UpdateIntel()
|
||||
end
|
||||
end
|
||||
if not keepit then
|
||||
self:I(self.lid..string.format("Removing unit %s category=%d", unitname, unit:GetCategory()))
|
||||
self:T(self.lid..string.format("Removing unit %s category=%d", unitname, unit:GetCategory()))
|
||||
table.insert(remove, unitname)
|
||||
end
|
||||
end
|
||||
@ -502,17 +587,20 @@ function INTEL:UpdateIntel()
|
||||
end
|
||||
|
||||
-- Create detected groups.
|
||||
local DetectedGroups={}
|
||||
local DetectedGroups={}
|
||||
local RecceGroups={}
|
||||
for unitname,_unit in pairs(DetectedUnits) do
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
local group=unit:GetGroup()
|
||||
if group then
|
||||
DetectedGroups[group:GetName()]=group
|
||||
local groupname = group:GetName()
|
||||
DetectedGroups[groupname]=group
|
||||
RecceGroups[groupname]=RecceDetecting[unitname]
|
||||
end
|
||||
end
|
||||
|
||||
-- Create detected contacts.
|
||||
self:CreateDetectedItems(DetectedGroups)
|
||||
self:CreateDetectedItems(DetectedGroups, RecceGroups)
|
||||
|
||||
-- Paint a picture of the battlefield.
|
||||
if self.clusteranalysis then
|
||||
@ -528,8 +616,9 @@ end
|
||||
--- Create detected items.
|
||||
-- @param #INTEL self
|
||||
-- @param #table DetectedGroups Table of detected Groups
|
||||
function INTEL:CreateDetectedItems(DetectedGroups)
|
||||
|
||||
-- @param #table RecceDetecting Table of detecting recce names
|
||||
function INTEL:CreateDetectedItems(DetectedGroups, RecceDetecting)
|
||||
self:F({RecceDetecting=RecceDetecting})
|
||||
-- Current time.
|
||||
local Tnow=timer.getAbsTime()
|
||||
|
||||
@ -569,7 +658,8 @@ function INTEL:CreateDetectedItems(DetectedGroups)
|
||||
item.position=group:GetCoordinate()
|
||||
item.velocity=group:GetVelocityVec3()
|
||||
item.speed=group:GetVelocityMPS()
|
||||
|
||||
item.recce=RecceDetecting[groupname]
|
||||
self:T(string.format("%s group detect by %s/%s", groupname, RecceDetecting[groupname] or "unknonw", item.recce or "unknown"))
|
||||
-- Add contact to table.
|
||||
self:AddContact(item)
|
||||
|
||||
@ -602,17 +692,20 @@ end
|
||||
-- If no detection method is given, the detection will use all the available methods by default.
|
||||
-- @param #INTEL self
|
||||
-- @param Wrapper.Unit#UNIT Unit The unit detecting.
|
||||
-- @param #table DetectedUnits Table of detected units to be filled
|
||||
-- @param #table RecceDetecting Table of recce per unit to be filled
|
||||
-- @param #boolean DetectVisual (Optional) If *false*, do not include visually detected targets.
|
||||
-- @param #boolean DetectOptical (Optional) If *false*, do not include optically detected targets.
|
||||
-- @param #boolean DetectRadar (Optional) If *false*, do not include targets detected by radar.
|
||||
-- @param #boolean DetectIRST (Optional) If *false*, do not include targets detected by IRST.
|
||||
-- @param #boolean DetectRWR (Optional) If *false*, do not include targets detected by RWR.
|
||||
-- @param #boolean DetectDLINK (Optional) If *false*, do not include targets detected by data link.
|
||||
function INTEL:GetDetectedUnits(Unit, DetectedUnits, DetectVisual, DetectOptical, DetectRadar, DetectIRST, DetectRWR, DetectDLINK)
|
||||
function INTEL:GetDetectedUnits(Unit, DetectedUnits, RecceDetecting, DetectVisual, DetectOptical, DetectRadar, DetectIRST, DetectRWR, DetectDLINK)
|
||||
|
||||
-- Get detected DCS units.
|
||||
local detectedtargets=Unit:GetDetectedTargets(DetectVisual, DetectOptical, DetectRadar, DetectIRST, DetectRWR, DetectDLINK)
|
||||
|
||||
local reccename = Unit:GetName()
|
||||
|
||||
for DetectionObjectID, Detection in pairs(detectedtargets or {}) do
|
||||
local DetectedObject=Detection.object -- DCS#Object
|
||||
|
||||
@ -625,7 +718,8 @@ function INTEL:GetDetectedUnits(Unit, DetectedUnits, DetectVisual, DetectOptical
|
||||
local unitname=unit:GetName()
|
||||
|
||||
DetectedUnits[unitname]=unit
|
||||
|
||||
RecceDetecting[unitname]=reccename
|
||||
self:T(string.format("Unit %s detect by %s", unitname, reccename))
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -643,7 +737,7 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param #INTEL.Contact Contact Detected contact.
|
||||
function INTEL:onafterNewContact(From, Event, To, Contact)
|
||||
self:I(self.lid..string.format("NEW contact %s", Contact.groupname))
|
||||
self:F(self.lid..string.format("NEW contact %s", Contact.groupname))
|
||||
table.insert(self.ContactsUnknown, Contact)
|
||||
end
|
||||
|
||||
@ -654,10 +748,37 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param #INTEL.Contact Contact Detected contact.
|
||||
function INTEL:onafterLostContact(From, Event, To, Contact)
|
||||
self:I(self.lid..string.format("LOST contact %s", Contact.groupname))
|
||||
self:F(self.lid..string.format("LOST contact %s", Contact.groupname))
|
||||
table.insert(self.ContactsLost, Contact)
|
||||
end
|
||||
|
||||
--- On after "NewCluster" event.
|
||||
-- @param #INTEL self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #INTEL.Contact Contact Detected contact.
|
||||
-- @param #INTEL.Cluster Cluster Detected cluster
|
||||
function INTEL:onafterNewCluster(From, Event, To, Contact, Cluster)
|
||||
self:F(self.lid..string.format("NEW cluster %d size %d with contact %s", Cluster.index, Cluster.size, Contact.groupname))
|
||||
end
|
||||
|
||||
--- On after "LostCluster" event.
|
||||
-- @param #INTEL self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #INTEL.Cluster Cluster Lost cluster
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The Auftrag connected with this cluster or nil
|
||||
function INTEL:onafterLostCluster(From, Event, To, Cluster, Mission)
|
||||
local text = self.lid..string.format("LOST cluster %d", Cluster.index)
|
||||
if Mission then
|
||||
local mission=Mission --Ops.Auftrag#AUFTRAG
|
||||
text=text..string.format(" mission name=%s type=%s target=%s", mission.name, mission.type, mission:GetTargetName() or "unkown")
|
||||
end
|
||||
self:T(text)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Misc Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -752,11 +873,27 @@ function INTEL:PaintPicture()
|
||||
self:RemoveContactFromCluster(contact, cluster)
|
||||
end
|
||||
end
|
||||
|
||||
-- clean up cluster table
|
||||
local ClusterSet = {}
|
||||
for _i,_cluster in pairs(self.Clusters) do
|
||||
if (_cluster.size > 0) and (self:ClusterCountUnits(_cluster) > 0) then
|
||||
table.insert(ClusterSet,_cluster)
|
||||
else
|
||||
local mission = _cluster.mission or nil
|
||||
local marker = _cluster.marker
|
||||
if marker then
|
||||
marker:Remove()
|
||||
end
|
||||
self:LostCluster(_cluster, mission)
|
||||
end
|
||||
end
|
||||
self.Clusters = ClusterSet
|
||||
-- update positions
|
||||
self:_UpdateClusterPositions()
|
||||
|
||||
for _,_contact in pairs(self.Contacts) do
|
||||
local contact=_contact --#INTEL.Contact
|
||||
|
||||
self:T(string.format("Paint Picture: checking for %s",contact.groupname))
|
||||
-- Check if this contact is in any cluster.
|
||||
local isincluster=self:CheckContactInClusters(contact)
|
||||
|
||||
@ -764,7 +901,7 @@ function INTEL:PaintPicture()
|
||||
local currentcluster=self:GetClusterOfContact(contact)
|
||||
|
||||
if currentcluster then
|
||||
|
||||
--self:I(string.format("Paint Picture: %s has current cluster",contact.groupname))
|
||||
---
|
||||
-- Contact is currently part of a cluster.
|
||||
---
|
||||
@ -772,8 +909,8 @@ function INTEL:PaintPicture()
|
||||
-- Check if the contact is still connected to the cluster.
|
||||
local isconnected=self:IsContactConnectedToCluster(contact, currentcluster)
|
||||
|
||||
if not isconnected then
|
||||
|
||||
if (not isconnected) and (currentcluster.size > 1) then
|
||||
--self:I(string.format("Paint Picture: %s has LOST current cluster",contact.groupname))
|
||||
local cluster=self:IsContactPartOfAnyClusters(contact)
|
||||
|
||||
if cluster then
|
||||
@ -782,6 +919,7 @@ function INTEL:PaintPicture()
|
||||
|
||||
local newcluster=self:CreateCluster(contact.position)
|
||||
self:AddContactToCluster(contact, newcluster)
|
||||
self:NewCluster(contact, newcluster)
|
||||
end
|
||||
|
||||
end
|
||||
@ -792,7 +930,7 @@ function INTEL:PaintPicture()
|
||||
---
|
||||
-- Contact is not in any cluster yet.
|
||||
---
|
||||
|
||||
--self:I(string.format("Paint Picture: %s has NO current cluster",contact.groupname))
|
||||
local cluster=self:IsContactPartOfAnyClusters(contact)
|
||||
|
||||
if cluster then
|
||||
@ -801,6 +939,7 @@ function INTEL:PaintPicture()
|
||||
|
||||
local newcluster=self:CreateCluster(contact.position)
|
||||
self:AddContactToCluster(contact, newcluster)
|
||||
self:NewCluster(contact, newcluster)
|
||||
end
|
||||
|
||||
end
|
||||
@ -810,16 +949,17 @@ function INTEL:PaintPicture()
|
||||
|
||||
|
||||
-- Update F10 marker text if cluster has changed.
|
||||
for _,_cluster in pairs(self.Clusters) do
|
||||
local cluster=_cluster --#INTEL.Cluster
|
||||
|
||||
local coordinate=self:GetClusterCoordinate(cluster)
|
||||
|
||||
|
||||
-- Update F10 marker.
|
||||
self:UpdateClusterMarker(cluster)
|
||||
if self.clustermarkers then
|
||||
for _,_cluster in pairs(self.Clusters) do
|
||||
local cluster=_cluster --#INTEL.Cluster
|
||||
|
||||
local coordinate=self:GetClusterCoordinate(cluster)
|
||||
|
||||
|
||||
-- Update F10 marker.
|
||||
self:UpdateClusterMarker(cluster)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Create a new cluster.
|
||||
@ -976,9 +1116,11 @@ function INTEL:IsContactConnectedToCluster(contact, cluster)
|
||||
|
||||
if Contact.groupname~=contact.groupname then
|
||||
|
||||
local dist=Contact.position:Get2DDistance(contact.position)
|
||||
--local dist=Contact.position:Get2DDistance(contact.position)
|
||||
local dist=Contact.position:DistanceFromPointVec2(contact.position)
|
||||
|
||||
if dist<10*1000 then
|
||||
local radius = self.clusterradius or 15
|
||||
if dist<radius*1000 then
|
||||
return true
|
||||
end
|
||||
|
||||
@ -1032,7 +1174,6 @@ end
|
||||
-- @param #INTEL.Cluster cluster The cluster.
|
||||
-- @return Core.Point#COORDINATE The coordinate of this cluster.
|
||||
function INTEL:GetClusterCoordinate(cluster)
|
||||
|
||||
-- Init.
|
||||
local x=0 ; local y=0 ; local z=0 ; local n=0
|
||||
|
||||
@ -1058,12 +1199,14 @@ end
|
||||
--- Get the coordinate of a cluster.
|
||||
-- @param #INTEL self
|
||||
-- @param #INTEL.Cluster cluster The cluster.
|
||||
-- @param Core.Point#COORDINATE coordinate (Optional) Coordinate of the new cluster. Default is to calculate the current coordinate.
|
||||
-- @param Core.Point#COORDINATE coordinate (Optional) Coordinate of the new cluster. Default is to calculate the current coordinate.
|
||||
-- @return #boolean
|
||||
function INTEL:CheckClusterCoordinateChanged(cluster, coordinate)
|
||||
|
||||
coordinate=coordinate or self:GetClusterCoordinate(cluster)
|
||||
|
||||
local dist=cluster.coordinate:Get2DDistance(coordinate)
|
||||
--local dist=cluster.coordinate:Get2DDistance(coordinate)
|
||||
local dist=cluster.coordinate:DistanceFromPointVec2(coordinate)
|
||||
|
||||
if dist>1000 then
|
||||
return true
|
||||
@ -1073,6 +1216,27 @@ function INTEL:CheckClusterCoordinateChanged(cluster, coordinate)
|
||||
|
||||
end
|
||||
|
||||
--- Update coordinates of the known clusters.
|
||||
-- @param #INTEL self
|
||||
function INTEL:_UpdateClusterPositions()
|
||||
for _,_cluster in pairs (self.Clusters) do
|
||||
local coord = self:GetClusterCoordinate(_cluster)
|
||||
_cluster.coordinate = coord
|
||||
self:T(self.lid..string.format("Cluster size: %s", _cluster.size))
|
||||
end
|
||||
end
|
||||
|
||||
--- Count number of units in cluster
|
||||
-- @param #INTEL self
|
||||
-- @param #INTEL.Cluster Cluster The cluster
|
||||
-- @return #number unitcount
|
||||
function INTEL:ClusterCountUnits(Cluster)
|
||||
local unitcount = 0
|
||||
for _,_group in pairs (Cluster.Contacts) do -- get Wrapper.GROUP#GROUP _group
|
||||
unitcount = unitcount + _group.group:CountAliveUnits()
|
||||
end
|
||||
return unitcount
|
||||
end
|
||||
|
||||
--- Update cluster F10 marker.
|
||||
-- @param #INTEL self
|
||||
@ -1081,7 +1245,8 @@ end
|
||||
function INTEL:UpdateClusterMarker(cluster)
|
||||
|
||||
-- Create a marker.
|
||||
local text=string.format("Cluster #%d. Size %d, TLsum=%d", cluster.index, cluster.size, cluster.threatlevelSum)
|
||||
local unitcount = self:ClusterCountUnits(cluster)
|
||||
local text=string.format("Cluster #%d. Size %d, Units %d, TLsum=%d", cluster.index, cluster.size, unitcount, cluster.threatlevelSum)
|
||||
|
||||
if not cluster.marker then
|
||||
cluster.marker=MARKER:New(cluster.coordinate, text):ToAll()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user