Skip to content

Commit

Permalink
Merge pull request #101 from walder/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
walder authored Dec 29, 2023
2 parents a332f67 + 1b928aa commit 8e481fd
Show file tree
Hide file tree
Showing 20 changed files with 959 additions and 650 deletions.
73 changes: 72 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,78 @@ If you like using it, please consider a donation:**

Table of Contents
=================

* [Skynet\-IADS](#skynet-iads)
* [Abstract](#abstract)
* [Quick start](#quick-start)
* [Skynet IADS Elements](#skynet-iads-elements)
* [IADS](#iads)
* [Track files](#track-files)
* [Comand Centers](#comand-centers)
* [SAM Sites](#sam-sites)
* [Early Warning Radars](#early-warning-radars)
* [Power Sources](#power-sources)
* [Connection Nodes](#connection-nodes)
* [AWACS (Airborne Early Warning and Control System)
](#awacs-airborne-early-warning-and-control-system)
* [Ships](#ships)
* [Tactics](#tactics)
* [HARM defence](#harm-defence)
* [HARM detection](#harm-detection)
* [HARM flight path analysis](#harm-flight-path-analysis)
* [HARM radar shutdown](#harm-radar-shutdown)
* [Point defence](#point-defence)
* [Electronic Warfare](#electronic-warfare)
* [Using Skynet in the mission editor](#using-skynet-in-the-mission-editor)
* [Placing units](#placing-units)
* [Preparing a SAM site](#preparing-a-sam-site)
* [Preparing an EW radar](#preparing-an-ew-radar)
* [Adding the Skynet code](#adding-the-skynet-code)
* [Adding the Skynet IADS](#adding-the-skynet-iads)
* [Advanced setup](#advanced-setup)
* [IADS configuration](#iads-configuration)
* [Adding a command center](#adding-a-command-center)
* [Power sources and connection nodes](#power-sources-and-connection-nodes)
* [Warm up the SAM sites of an IADS](#warm-up-the-sam-sites-of-an-iads)
* [Connecting Skynet to the MOOSE AI\_A2A\_DISPATCHER](#connecting-skynet-to-the-moose-ai_a2a_dispatcher)
* [SAM site configuration](#sam-site-configuration)
* [Adding SAM sites](#adding-sam-sites)
* [Add multiple SAM sites](#add-multiple-sam-sites)
* [Add a SAM site manually](#add-a-sam-site-manually)
* [Accessing SAM sites in the IADS](#accessing-sam-sites-in-the-iads)
* [Act as EW radar](#act-as-ew-radar)
* [Engagement zone](#engagement-zone)
* [Engagement zone options](#engagement-zone-options)
* [Engage air weapons](#engage-air-weapons)
* [Engage HARM](#engage-harm)
* [Add go live constraints](#add-go-live-constraints)
* [Use cases](#use-cases)
* [Contact](#contact)
* [EW radar configuration](#ew-radar-configuration)
* [Adding EW radars](#adding-ew-radars)
* [Add multiple EW radars](#add-multiple-ew-radars)
* [Add an EW radar manually](#add-an-ew-radar-manually)
* [Accessing EW radars in the IADS](#accessing-ew-radars-in-the-iads)
* [Options for SAM sites and EW radars](#options-for-sam-sites-and-ew-radars)
* [Setting an option](#setting-an-option)
* [Daisy chaining options](#daisy-chaining-options)
* [HARM Defence](#harm-defence-1)
* [Point defence](#point-defence-1)
* [Autonomous mode behaviour](#autonomous-mode-behaviour)
* [Autonomous mode options](#autonomous-mode-options)
* [Adding a jammer](#adding-a-jammer)
* [Advanced functions](#advanced-functions)
* [Setting debug information](#setting-debug-information)
* [Example Setup](#example-setup)
* [FAQ](#faq)
* [Does Skynet IADS have an impact on game performance?](#does-skynet-iads-have-an-impact-on-game-performance)
* [What air defence units shall I add to the Skynet IADS?](#what-air-defence-units-shall-i-add-to-the-skynet-iads)
* [Which SAM systems can engage HARMS?](#which-sam-systems-can-engage-harms)
* [What exactly does Skynet do with the SAMS?](#what-exactly-does-skynet-do-with-the-sams)
* [Are there known bugs?](#are-there-known-bugs)
* [How do I know if a SAM site is in range of an EW site or a SAM site in EW mode?](#how-do-i-know-if-a-sam-site-is-in-range-of-an-ew-site-or-a-sam-site-in-ew-mode)
* [How do I connect Skynet with the MOOSE AI\_A2A\_DISPATCHER and what are the benefits of that?](#how-do-i-connect-skynet-with-the-moose-ai_a2a_dispatcher-and-what-are-the-benefits-of-that)
* [Thanks](#thanks)


# Quick start
Tired of reading already? Download the [demo mission](/demo-missions/skynet-test-persian-gulf.miz) in the persian gulf map and see Skynet in action. More complex demo missions will follow soon.
Expand Down
Binary file modified build-tools/bin/gh-md-toc.exe
Binary file not shown.
Binary file not shown.
138 changes: 91 additions & 47 deletions demo-missions/skynet-iads-compiled.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
env.info("--- SKYNET VERSION: 3.1.0 | BUILD TIME: 09.02.2023 1925Z ---")
env.info("--- SKYNET VERSION: 3.2 | BUILD TIME: 29.12.2023 1919Z ---")
do
--this file contains the required units per sam type
samTypesDB = {
Expand Down Expand Up @@ -47,10 +47,19 @@ samTypesDB = {
['NATO'] = 'Big Bird',
},
},
['S-300PS 40B6MD sr_19J6'] = {
['name'] = {
['NATO'] = 'Tin Shield',
},
}
},
['trackingRadar'] = {
['S-300PS 40B6M tr'] = {
},

['S-300PS 5H63C 30H6_tr'] = {
}

},
['launchers'] = {
['S-300PS 5P85D ln'] = {
Expand Down Expand Up @@ -212,16 +221,18 @@ samTypesDB = {

},
['Roland ADS'] = {
['type'] = 'single',
['type'] = 'complex',
['searchRadar'] = {
['Roland ADS'] = {
['Roland Radar'] = {
['name'] = {
['NATO'] = 'Roland EWR',
},
},
},
['launchers'] = {
['Roland ADS'] = {
},
},

['name'] = {
['NATO'] = 'Roland ADS',
},
Expand Down Expand Up @@ -395,7 +406,7 @@ samTypesDB = {
},
['harm_detection_chance'] = 30
},
--- Start of EW radars:
--- Start of RED EW radars:
['1L13 EWR'] = {
['type'] = 'ewr',
['searchRadar'] = {
Expand Down Expand Up @@ -429,18 +440,29 @@ samTypesDB = {
},
['harm_detection_chance'] = 20
},
['Roland Radar'] = {
-- Start of BLUE EW radars:
['FPS-117 Dome'] = {
['type'] = 'ewr',
['searchRadar'] = {
['Roland Radar'] = {
['FPS-117 Dome'] = {
['name'] = {
['NATO'] = 'Roland EWR',
['NATO'] = 'FPS-117 Dome',
},
},
},

['harm_detection_chance'] = 60
},
['harm_detection_chance'] = 80
},
['FPS-117'] = {
['type'] = 'ewr',
['searchRadar'] = {
['FPS-117'] = {
['name'] = {
['NATO'] = 'FPS-117',
},
},
},
['harm_detection_chance'] = 80
}
}
end
do
Expand Down Expand Up @@ -1170,9 +1192,17 @@ function SkynetIADS:create(name)
iads.name = ""
end
iads.contactUpdateInterval = 5
world.addEventHandler(iads)
return iads
end

function SkynetIADS:onEvent(event)
if (event.id == world.event.S_EVENT_BIRTH ) then
env.info("New Object Spawned")
self:addSAMSite(event.initiator:getGroup():getName());
end
end

function SkynetIADS:setUpdateInterval(interval)
self.contactUpdateInterval = interval
end
Expand Down Expand Up @@ -1305,7 +1335,7 @@ function SkynetIADS:addSAMSitesByPrefix(prefix)
if pos and pos == 1 then
--mist returns groups, units and, StaticObjects
local dcsObject = Group.getByName(groupName)
if dcsObject then
if dcsObject and dcsObject:getUnits()[1]:isActive() then
self:addSAMSite(groupName)
end
end
Expand Down Expand Up @@ -1876,7 +1906,10 @@ end
function SkynetIADSAbstractDCSObjectWrapper:setDCSRepresentation(representation)
self.dcsRepresentation = representation
if self.dcsRepresentation then
self.dcsName = self:getDCSRepresentation():getName()
self.dcsName = self.dcsRepresentation:getName()
if (self.dcsName == nil or string.len(self.dcsName) == 0) and self.dcsRepresentation.id_ then
self.dcsName = self.dcsRepresentation.id_
end
end
end

Expand Down Expand Up @@ -2633,6 +2666,7 @@ function SkynetIADSAbstractRadarElement:goLive()
then
if self:isDestroyed() == false then
local cont = self:getController()
cont:setOnOff(true)
cont:setOption(AI.Option.Ground.id.ALARM_STATE, AI.Option.Ground.val.ALARM_STATE.RED)
cont:setOption(AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.WEAPON_FREE)
self:getDCSRepresentation():enableEmission(true)
Expand Down Expand Up @@ -2665,9 +2699,15 @@ function SkynetIADSAbstractRadarElement:goDark()
-- point defence will only go live if the Radar Emitting site it is protecting goes dark and this is due to a it defending against a HARM
if (self.harmSilenceID ~= nil) then
self:pointDefencesGoLive()
if self:isDestroyed() == false then
--if site goes dark due to HARM we turn off AI, this is due to a bug in DCS multiplayer where the harm will find its way to the radar emitter if just setEmissions is set to false
local controller = self:getController()
controller:setOnOff(false)
end
end
self.aiState = false
self:stopScanningForHARMs()
self.cachedTargets = {}
if self.iads:getDebugSettings().radarWentDark then
self.iads:printOutputToLog("GOING DARK: "..self:getDescription())
end
Expand Down Expand Up @@ -2910,22 +2950,24 @@ function SkynetIADSAbstractRadarElement:informOfHARM(harmContact)
local radars = self:getRadars()
for j = 1, #radars do
local radar = radars[j]
local distanceNM = mist.utils.metersToNM(self:getDistanceInMetersToContact(radar, harmContact:getPosition().p))
local harmToSAMHeading = mist.utils.toDegree(mist.utils.getHeadingPoints(harmContact:getPosition().p, radar:getPosition().p))
local harmToSAMAspect = self:calculateAspectInDegrees(harmContact:getMagneticHeading(), harmToSAMHeading)
local speedKT = harmContact:getGroundSpeedInKnots(0)
local secondsToImpact = self:getSecondsToImpact(distanceNM, speedKT)
--TODO: use tti instead of distanceNM?
-- when iterating through the radars, store shortest tti and work with that value??
if ( harmToSAMAspect < SkynetIADSAbstractRadarElement.HARM_TO_SAM_ASPECT and distanceNM < SkynetIADSAbstractRadarElement.HARM_LOOKAHEAD_NM ) then
self:addObjectIdentifiedAsHARM(harmContact)
if ( #self:getPointDefences() > 0 and self:pointDefencesGoLive() == true and self.iads:getDebugSettings().harmDefence ) then
self.iads:printOutputToLog("POINT DEFENCES GOING LIVE FOR: "..self:getDCSName().." | TTI: "..secondsToImpact)
end
--self.iads:printOutputToLog("Ignore HARM shutdown: "..tostring(self:shallIgnoreHARMShutdown()))
if ( self:getIsAPointDefence() == false and ( self:isDefendingHARM() == false or ( self:getHARMShutdownTime() < secondsToImpact ) ) and self:shallIgnoreHARMShutdown() == false) then
self:goSilentToEvadeHARM(secondsToImpact)
break
if radar:isExist() then
local distanceNM = mist.utils.metersToNM(self:getDistanceInMetersToContact(radar, harmContact:getPosition().p))
local harmToSAMHeading = mist.utils.toDegree(mist.utils.getHeadingPoints(harmContact:getPosition().p, radar:getPosition().p))
local harmToSAMAspect = self:calculateAspectInDegrees(harmContact:getMagneticHeading(), harmToSAMHeading)
local speedKT = harmContact:getGroundSpeedInKnots(0)
local secondsToImpact = self:getSecondsToImpact(distanceNM, speedKT)
--TODO: use tti instead of distanceNM?
-- when iterating through the radars, store shortest tti and work with that value??
if ( harmToSAMAspect < SkynetIADSAbstractRadarElement.HARM_TO_SAM_ASPECT and distanceNM < SkynetIADSAbstractRadarElement.HARM_LOOKAHEAD_NM ) then
self:addObjectIdentifiedAsHARM(harmContact)
if ( #self:getPointDefences() > 0 and self:pointDefencesGoLive() == true and self.iads:getDebugSettings().harmDefence ) then
self.iads:printOutputToLog("POINT DEFENCES GOING LIVE FOR: "..self:getDCSName().." | TTI: "..secondsToImpact)
end
--self.iads:printOutputToLog("Ignore HARM shutdown: "..tostring(self:shallIgnoreHARMShutdown()))
if ( self:getIsAPointDefence() == false and ( self:isDefendingHARM() == false or ( self:getHARMShutdownTime() < secondsToImpact ) ) and self:shallIgnoreHARMShutdown() == false) then
self:goSilentToEvadeHARM(secondsToImpact)
break
end
end
end
end
Expand Down Expand Up @@ -3131,9 +3173,11 @@ function SkynetIADSContact:getTypeName()
if self:isIdentifiedAsHARM() then
return SkynetIADSContact.HARM
end
local category = self:getDCSRepresentation():getCategory()
if category == Object.Category.UNIT then
return self.typeName
if self:getDCSRepresentation() ~= nil then
local category = self:getDCSRepresentation():getCategory()
if category == Object.Category.UNIT then
return self.typeName
end
end
return "UNKNOWN"
end
Expand Down Expand Up @@ -3797,31 +3841,31 @@ function SkynetIADSHARMDetection:cleanAgedContacts()
end

function SkynetIADSHARMDetection:getNewRadarsThatHaveDetectedContact(contact)
local newRadars = contact:getAbstractRadarElementsDetected()
local radars = self.contactRadarsEvaluated[contact]
if radars then
newRadars = {}
local contactRadars = contact:getAbstractRadarElementsDetected()
for i = 1, #contactRadars do
local contactRadar = contactRadars[i]
local newRadar = self:isElementInTable(radars, contactRadar)
if newRadar ~= nil then
table.insert(newRadars, newRadar)
end
local radarsFromContact = contact:getAbstractRadarElementsDetected()
local evaluatedRadars = self.contactRadarsEvaluated[contact]
local newRadars = {}
if evaluatedRadars == nil then
evaluatedRadars = {}
self.contactRadarsEvaluated[contact] = evaluatedRadars
end
for i = 1, #radarsFromContact do
local contactRadar = radarsFromContact[i]
if self:isElementInTable(evaluatedRadars, contactRadar) == false then
table.insert(evaluatedRadars, contactRadar)
table.insert(newRadars, contactRadar)
end
end
self.contactRadarsEvaluated[contact] = contact:getAbstractRadarElementsDetected()
return newRadars
end

function SkynetIADSHARMDetection:isElementInTable(tbl, element)
for i = 1, #tbl do
tblElement = tbl[i]
local tblElement = tbl[i]
if tblElement == element then
return nil
return true
end
end
return element
return false
end

function SkynetIADSHARMDetection:informRadarsOfHARM(contact)
Expand Down
Binary file modified demo-missions/skynet-test-persian-gulf-stress-test.miz
Binary file not shown.
Binary file modified demo-missions/skynet-test-persian-gulf.miz
Binary file not shown.
Loading

0 comments on commit 8e481fd

Please sign in to comment.