Slightly changed versions of Mantis, Sead and Shorad as the Emissions On/Off stuff ED introduced doesn't really work well.

This commit is contained in:
Applevangelist 2021-07-12 18:10:12 +02:00
parent 52e2ac7174
commit c0f4eef896
3 changed files with 254 additions and 277 deletions

View File

@ -191,7 +191,7 @@ MANTIS = {
ShoradLink = false, ShoradLink = false,
ShoradTime = 600, ShoradTime = 600,
ShoradActDistance = 15000, ShoradActDistance = 15000,
UseEmOnOff = true, UseEmOnOff = false,
} }
----------------------------------------------------------------------- -----------------------------------------------------------------------
@ -208,7 +208,7 @@ do
--@param #string coaltion Coalition side of your setup, e.g. "blue", "red" or "neutral" --@param #string coaltion Coalition side of your setup, e.g. "blue", "red" or "neutral"
--@param #boolean dynamic Use constant (true) filtering or just filter once (false, default) (optional) --@param #boolean dynamic Use constant (true) filtering or just filter once (false, default) (optional)
--@param #string awacs Group name of your Awacs (optional) --@param #string awacs Group name of your Awacs (optional)
--@param #boolean EmOnOff Make MANTIS switch Emissions on and off instead of changing the alarm state between RED and GREEN (optional, deault true) --@param #boolean EmOnOff Make MANTIS switch Emissions on and off instead of changing the alarm state between RED and GREEN
--@return #MANTIS self --@return #MANTIS self
--@usage Start up your MANTIS with a basic setting --@usage Start up your MANTIS with a basic setting
-- --
@ -267,6 +267,8 @@ do
if EmOnOff then if EmOnOff then
if EmOnOff == false then if EmOnOff == false then
self.UseEmOnOff = false self.UseEmOnOff = false
else
self.UseEmOnOff = true
end end
end end

View File

@ -1,26 +1,26 @@
--- **Functional** -- Make SAM sites execute evasive and defensive behaviour when being fired upon. --- **Functional** -- Make SAM sites execute evasive and defensive behaviour when being fired upon.
-- --
-- === -- ===
-- --
-- ## Features: -- ## Features:
-- --
-- * When SAM sites are being fired upon, the SAMs will take evasive action will reposition themselves when possible. -- * When SAM sites are being fired upon, the SAMs will take evasive action will reposition themselves when possible.
-- * When SAM sites are being fired upon, the SAMs will take defensive action by shutting down their radars. -- * When SAM sites are being fired upon, the SAMs will take defensive action by shutting down their radars.
-- --
-- === -- ===
-- --
-- ## Missions: -- ## Missions:
-- --
-- [SEV - SEAD Evasion](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SEV%20-%20SEAD%20Evasion) -- [SEV - SEAD Evasion](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SEV%20-%20SEAD%20Evasion)
-- --
-- === -- ===
-- --
-- ### Authors: **FlightControl**, **applevangelist** -- ### Authors: **FlightControl**, **applevangelist**
-- --
-- Last Update: April 2021 -- Last Update: Feb 2021
-- --
-- === -- ===
-- --
-- @module Functional.Sead -- @module Functional.Sead
-- @image SEAD.JPG -- @image SEAD.JPG
@ -28,49 +28,32 @@
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- Make SAM sites execute evasive and defensive behaviour when being fired upon. --- Make SAM sites execute evasive and defensive behaviour when being fired upon.
-- --
-- This class is very easy to use. Just setup a SEAD object by using @{#SEAD.New}() and SAMs will evade and take defensive action when being fired upon. -- This class is very easy to use. Just setup a SEAD object by using @{#SEAD.New}() and SAMs will evade and take defensive action when being fired upon.
-- --
-- # Constructor: -- # Constructor:
-- --
-- Use the @{#SEAD.New}() constructor to create a new SEAD object. -- Use the @{#SEAD.New}() constructor to create a new SEAD object.
-- --
-- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } ) -- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } )
-- --
-- @field #SEAD -- @field #SEAD
SEAD = { SEAD = {
ClassName = "SEAD", ClassName = "SEAD",
TargetSkill = { TargetSkill = {
Average = { Evade = 30, DelayOn = { 40, 60 } } , Average = { Evade = 30, DelayOn = { 40, 60 } } ,
Good = { Evade = 20, DelayOn = { 30, 50 } } , Good = { Evade = 20, DelayOn = { 30, 50 } } ,
High = { Evade = 15, DelayOn = { 20, 40 } } , High = { Evade = 15, DelayOn = { 20, 40 } } ,
Excellent = { Evade = 10, DelayOn = { 10, 30 } } Excellent = { Evade = 10, DelayOn = { 10, 30 } }
}, },
SEADGroupPrefixes = {}, SEADGroupPrefixes = {},
SuppressedGroups = {}, SuppressedGroups = {},
EngagementRange = 75 -- default 75% engagement range Feature Request #1355 EngagementRange = 75 -- default 75% engagement range Feature Request #1355
} }
-- TODO Complete list?
--- Missile enumerators --- Missile enumerators
-- @field Harms -- @field Harms
SEAD.Harms = { SEAD.Harms = {
--[[
["X58"] = "weapons.missiles.X_58", --Kh-58X anti-radiation missiles fired
["Kh25"] = "weapons.missiles.Kh25MP_PRGS1VP", --Kh-25MP anti-radiation missiles fired
["X25"] = "weapons.missiles.X_25MP", --Kh-25MPU anti-radiation missiles fired
["X28"] = "weapons.missiles.X_28", --Kh-28 anti-radiation missiles fired
["X31"] = "weapons.missiles.X_31P", --Kh-31P anti-radiation missiles fired
["AGM45A"] = "weapons.missiles.AGM_45A", --AGM-45A anti-radiation missiles fired
["AGM45"] = "weapons.missiles.AGM_45", --AGM-45B anti-radiation missiles fired
["AGM88"] = "weapons.missiles.AGM_88", --AGM-88C anti-radiation missiles fired
["AGM122"] = "weapons.missiles.AGM_122", --AGM-122 Sidearm anti-radiation missiles fired
["LD10"] = "weapons.missiles.LD-10", --LD-10 anti-radiation missiles fired
["ALARM"] = "weapons.missiles.ALARM", --ALARM anti-radiation missiles fired
["AGM84E"] = "weapons.missiles.AGM_84E", --AGM84 anti-radiation missiles fired
["AGM84A"] = "weapons.missiles.AGM_84A", --AGM84 anti-radiation missiles fired
["AGM84H"] = "weapons.missiles.AGM_84H", --AGM84 anti-radiation missiles fired
--]]
["AGM_88"] = "AGM_88", ["AGM_88"] = "AGM_88",
["AGM_45"] = "AGM_45", ["AGM_45"] = "AGM_45",
["AGM_122"] = "AGM_122", ["AGM_122"] = "AGM_122",
@ -84,7 +67,7 @@ SEAD = {
["X_31"] = "X_31", ["X_31"] = "X_31",
["Kh25"] = "Kh25", ["Kh25"] = "Kh25",
} }
--- Creates the main object which is handling defensive actions for SA sites or moving SA vehicles. --- Creates the main object which is handling defensive actions for SA sites or moving SA vehicles.
-- When an anti radiation missile is fired (KH-58, KH-31P, KH-31A, KH-25MPU, HARM missiles), the SA will shut down their radars and will take evasive actions... -- When an anti radiation missile is fired (KH-58, KH-31P, KH-31A, KH-25MPU, HARM missiles), the SA will shut down their radars and will take evasive actions...
-- Chances are big that the missile will miss. -- Chances are big that the missile will miss.
@ -97,20 +80,20 @@ SEAD = {
-- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } ) -- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } )
function SEAD:New( SEADGroupPrefixes ) function SEAD:New( SEADGroupPrefixes )
local self = BASE:Inherit( self, BASE:New() ) local self = BASE:Inherit( self, BASE:New() )
self:F( SEADGroupPrefixes ) self:F( SEADGroupPrefixes )
if type( SEADGroupPrefixes ) == 'table' then if type( SEADGroupPrefixes ) == 'table' then
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
self.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix self.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix
end end
else else
self.SEADGroupPrefixes[SEADGroupPrefixes] = SEADGroupPrefixes self.SEADGroupPrefixes[SEADGroupPrefixes] = SEADGroupPrefixes
end end
self:HandleEvent( EVENTS.Shot ) self:HandleEvent( EVENTS.Shot, self.HandleEventShot )
self:I("*** SEAD - Started Version 0.2.7") self:I("*** SEAD - Started Version 0.2.8")
return self return self
end end
--- Update the active SEAD Set --- Update the active SEAD Set
@ -120,7 +103,7 @@ end
function SEAD:UpdateSet( SEADGroupPrefixes ) function SEAD:UpdateSet( SEADGroupPrefixes )
self:F( SEADGroupPrefixes ) self:F( SEADGroupPrefixes )
if type( SEADGroupPrefixes ) == 'table' then if type( SEADGroupPrefixes ) == 'table' then
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
self.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix self.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix
@ -164,112 +147,83 @@ end
-- @see SEAD -- @see SEAD
-- @param #SEAD -- @param #SEAD
-- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
function SEAD:OnEventShot( EventData ) function SEAD:HandleEventShot( EventData )
self:T( { EventData } ) self:T( { EventData } )
local SEADUnit = EventData.IniDCSUnit local SEADUnit = EventData.IniDCSUnit
local SEADUnitName = EventData.IniDCSUnitName local SEADUnitName = EventData.IniDCSUnitName
local SEADWeapon = EventData.Weapon -- Identify the weapon fired local SEADWeapon = EventData.Weapon -- Identify the weapon fired
local SEADWeaponName = EventData.WeaponName -- return weapon type local SEADWeaponName = EventData.WeaponName -- return weapon type
self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName) self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName)
self:T({ SEADWeapon }) self:T({ SEADWeapon })
--[[check for SEAD missiles
if SEADWeaponName == "weapons.missiles.X_58" --Kh-58U anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.Kh25MP_PRGS1VP" --Kh-25MP anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.X_25MP" --Kh-25MPU anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.X_28" --Kh-28 anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.X_31P" --Kh-31P anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.AGM_45A" --AGM-45A anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.AGM_45" --AGM-45B anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.AGM_88" --AGM-88C anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.AGM_122" --AGM-122 Sidearm anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.LD-10" --LD-10 anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.ALARM" --ALARM anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.AGM_84E" --AGM84 anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.AGM_84A" --AGM84 anti-radiation missiles fired
or
SEADWeaponName == "weapons.missiles.AGM_84H" --AGM84 anti-radiation missiles fired
--]]
if self:_CheckHarms(SEADWeaponName) then if self:_CheckHarms(SEADWeaponName) then
local _targetskill = "Random" local _targetskill = "Random"
local _targetMimgroupName = "none" local _targetMimgroupName = "none"
local _evade = math.random (1,100) -- random number for chance of evading action local _evade = math.random (1,100) -- random number for chance of evading action
local _targetMim = EventData.Weapon:getTarget() -- Identify target local _targetMim = EventData.Weapon:getTarget() -- Identify target
local _targetUnit = UNIT:Find(_targetMim) -- Unit name by DCS Object local _targetUnit = UNIT:Find(_targetMim) -- Unit name by DCS Object
if _targetUnit and _targetUnit:IsAlive() then if _targetUnit and _targetUnit:IsAlive() then
local _targetMimgroup = _targetUnit:GetGroup() local _targetMimgroup = _targetUnit:GetGroup()
local _targetMimgroupName = _targetMimgroup:GetName() -- group name local _targetMimgroupName = _targetMimgroup:GetName() -- group name
--local _targetskill = _DATABASE.Templates.Units[_targetUnit].Template.skill --local _targetskill = _DATABASE.Templates.Units[_targetUnit].Template.skill
self:T( self.SEADGroupPrefixes ) self:T( self.SEADGroupPrefixes )
self:T( _targetMimgroupName ) self:T( _targetMimgroupName )
end end
-- see if we are shot at -- see if we are shot at
local SEADGroupFound = false local SEADGroupFound = false
for SEADGroupPrefixID, SEADGroupPrefix in pairs( self.SEADGroupPrefixes ) do for SEADGroupPrefixID, SEADGroupPrefix in pairs( self.SEADGroupPrefixes ) do
if string.find( _targetMimgroupName, SEADGroupPrefix, 1, true ) then if string.find( _targetMimgroupName, SEADGroupPrefix, 1, true ) then
SEADGroupFound = true SEADGroupFound = true
self:T( '*** SEAD - Group Found' ) self:T( '*** SEAD - Group Found' )
break break
end end
end end
if SEADGroupFound == true then -- yes we are being attacked if SEADGroupFound == true then -- yes we are being attacked
if _targetskill == "Random" then -- when skill is random, choose a skill if _targetskill == "Random" then -- when skill is random, choose a skill
local Skills = { "Average", "Good", "High", "Excellent" } local Skills = { "Average", "Good", "High", "Excellent" }
_targetskill = Skills[ math.random(1,4) ] _targetskill = Skills[ math.random(1,4) ]
end end
self:T( _targetskill ) self:T( _targetskill )
if self.TargetSkill[_targetskill] then if self.TargetSkill[_targetskill] then
if (_evade > self.TargetSkill[_targetskill].Evade) then if (_evade > self.TargetSkill[_targetskill].Evade) then
self:T( string.format("*** SEAD - Evading, target skill " ..string.format(_targetskill)) )
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(SEADWeapon))
local _targetMimcont= _targetMimgroup:getController()
routines.groupRandomDistSelf(_targetMimgroup,300,'Diamond',250,20) -- move randomly
--tracker ID table to switch groups off and on again
local id = {
groupName = _targetMimgroup,
ctrl = _targetMimcont
}
self:T( string.format("*** SEAD - Evading, target skill " ..string.format(_targetskill)) ) local function SuppressionEnd(id) --switch group back on
local range = self.EngagementRange -- Feature Request #1355
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(SEADWeapon)) self:T(string.format("*** SEAD - Engagement Range is %d", range))
local _targetMimcont= _targetMimgroup:getController() id.ctrl:setOption(AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.RED)
--id.groupName:enableEmission(true)
routines.groupRandomDistSelf(_targetMimgroup,300,'Diamond',250,20) -- move randomly id.ctrl:setOption(AI.Option.Ground.id.AC_ENGAGEMENT_RANGE_RESTRICTION,range) --Feature Request #1355
self.SuppressedGroups[id.groupName] = nil --delete group id from table when done
--tracker ID table to switch groups off and on again end
local id = { -- randomize switch-on time
groupName = _targetMimgroup, local delay = math.random(self.TargetSkill[_targetskill].DelayOn[1], self.TargetSkill[_targetskill].DelayOn[2])
ctrl = _targetMimcont local SuppressionEndTime = timer.getTime() + delay
} --create entry
if self.SuppressedGroups[id.groupName] == nil then --no timer entry for this group yet
local function SuppressionEnd(id) --switch group back on self.SuppressedGroups[id.groupName] = {
local range = self.EngagementRange -- Feature Request #1355 SuppressionEndTime = delay
self:T(string.format("*** SEAD - Engagement Range is %d", range)) }
id.ctrl:setOption(AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.RED) Controller.setOption(_targetMimcont, AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.GREEN)
--id.groupName:enableEmission(true) --_targetMimgroup:enableEmission(false)
id.ctrl:setOption(AI.Option.Ground.id.AC_ENGAGEMENT_RANGE_RESTRICTION,range) --Feature Request #1355 timer.scheduleFunction(SuppressionEnd, id, SuppressionEndTime) --Schedule the SuppressionEnd() function
self.SuppressedGroups[id.groupName] = nil --delete group id from table when done end
end end
-- randomize switch-on time end
local delay = math.random(self.TargetSkill[_targetskill].DelayOn[1], self.TargetSkill[_targetskill].DelayOn[2]) end
local SuppressionEndTime = timer.getTime() + delay end
--create entry
if self.SuppressedGroups[id.groupName] == nil then --no timer entry for this group yet
self.SuppressedGroups[id.groupName] = {
SuppressionEndTime = delay
}
Controller.setOption(_targetMimcont, AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.GREEN)
--_targetMimgroup:enableEmission(false)
timer.scheduleFunction(SuppressionEnd, id, SuppressionEndTime) --Schedule the SuppressionEnd() function
end
end
end
end
end
end end

View File

@ -1,24 +1,24 @@
--- **Functional** -- Short Range Air Defense System --- **Functional** -- Short Range Air Defense System
-- --
-- === -- ===
-- --
-- **SHORAD** - Short Range Air Defense System -- **SHORAD** - Short Range Air Defense System
-- Controls a network of short range air/missile defense groups. -- Controls a network of short range air/missile defense groups.
-- --
-- === -- ===
-- --
-- ## Missions: -- ## Missions:
-- --
-- ### [SHORAD - Short Range Air Defense](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SRD%20-%20SHORAD%20Defense) -- ### [SHORAD - Short Range Air Defense](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SRD%20-%20SHORAD%20Defense)
-- --
-- === -- ===
-- --
-- ### Author : **applevangelist** -- ### Author : **applevangelist **
-- --
-- @module Functional.Shorad -- @module Functional.Shorad
-- @image Functional.Shorad.jpg -- @image Functional.Shorad.jpg
-- --
-- Date: May 2021 -- Date: July 2021
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **SHORAD** class, extends Core.Base#BASE --- **SHORAD** class, extends Core.Base#BASE
@ -26,7 +26,7 @@
-- @field #string ClassName -- @field #string ClassName
-- @field #string name Name of this Shorad -- @field #string name Name of this Shorad
-- @field #boolean debug Set the debug state -- @field #boolean debug Set the debug state
-- @field #string Prefixes String to be used to build the @{#Core.Set#SET_GROUP} -- @field #string Prefixes String to be used to build the @{#Core.Set#SET_GROUP}
-- @field #number Radius Shorad defense radius in meters -- @field #number Radius Shorad defense radius in meters
-- @field Core.Set#SET_GROUP Groupset The set of Shorad groups -- @field Core.Set#SET_GROUP Groupset The set of Shorad groups
-- @field Core.Set#SET_GROUP Samset The set of SAM groups to defend -- @field Core.Set#SET_GROUP Samset The set of SAM groups to defend
@ -41,10 +41,10 @@
-- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green. -- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green.
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- *Good friends are worth defending.* Mr Tushman, Wonder (the Movie) --- *Good friends are worth defending.* Mr Tushman, Wonder (the Movie)
-- --
-- Simple Class for a more intelligent Short Range Air Defense System -- Simple Class for a more intelligent Short Range Air Defense System
-- --
-- #SHORAD -- #SHORAD
-- Moose derived missile intercepting short range defense system. -- Moose derived missile intercepting short range defense system.
-- Protects a network of SAM sites. Uses events to switch on the defense groups closest to the enemy. -- Protects a network of SAM sites. Uses events to switch on the defense groups closest to the enemy.
@ -52,26 +52,26 @@
-- --
-- ## Usage -- ## Usage
-- --
-- Set up a #SET_GROUP for the SAM sites to be protected: -- Set up a #SET_GROUP for the SAM sites to be protected:
-- --
-- `local SamSet = SET_GROUP:New():FilterPrefixes("Red SAM"):FilterCoalitions("red"):FilterStart()` -- `local SamSet = SET_GROUP:New():FilterPrefixes("Red SAM"):FilterCoalitions("red"):FilterStart()`
-- --
-- By default, SHORAD will defense against both HARMs and AG-Missiles with short to medium range. The default defense probability is 70-90%. -- By default, SHORAD will defense against both HARMs and AG-Missiles with short to medium range. The default defense probability is 70-90%.
-- When a missile is detected, SHORAD will activate defense groups in the given radius around the target for 10 minutes. It will *not* react to friendly fire. -- When a missile is detected, SHORAD will activate defense groups in the given radius around the target for 10 minutes. It will *not* react to friendly fire.
-- --
-- ### Start a new SHORAD system, parameters are: -- ### Start a new SHORAD system, parameters are:
--
-- * Name: Name of this SHORAD.
-- * ShoradPrefix: Filter for the Shorad #SET_GROUP.
-- * Samset: The #SET_GROUP of SAM sites to defend.
-- * Radius: Defense radius in meters.
-- * ActiveTimer: Determines how many seconds the systems stay on red alert after wake-up call.
-- * Coalition: Coalition, i.e. "blue", "red", or "neutral".*
--
-- `myshorad = SHORAD:New("RedShorad", "Red SHORAD", SamSet, 25000, 600, "red")`
-- --
-- * Name: Name of this SHORAD. -- ## Customize options
-- * ShoradPrefix: Filter for the Shorad #SET_GROUP. --
-- * Samset: The #SET_GROUP of SAM sites to defend.
-- * Radius: Defense radius in meters.
-- * ActiveTimer: Determines how many seconds the systems stay on red alert after wake-up call.
-- * Coalition: Coalition, i.e. "blue", "red", or "neutral".*
--
-- `myshorad = SHORAD:New("RedShorad", "Red SHORAD", SamSet, 25000, 600, "red")`
--
-- ## Customize options
--
-- * SHORAD:SwitchDebug(debug) -- * SHORAD:SwitchDebug(debug)
-- * SHORAD:SwitchHARMDefense(onoff) -- * SHORAD:SwitchHARMDefense(onoff)
-- * SHORAD:SwitchAGMDefense(onoff) -- * SHORAD:SwitchAGMDefense(onoff)
@ -94,9 +94,9 @@ SHORAD = {
lid = "", lid = "",
DefendHarms = true, DefendHarms = true,
DefendMavs = true, DefendMavs = true,
DefenseLowProb = 75, DefenseLowProb = 70,
DefenseHighProb = 90, DefenseHighProb = 90,
UseEmOnOff = false, UseEmOnOff = false,
} }
----------------------------------------------------------------------- -----------------------------------------------------------------------
@ -108,22 +108,6 @@ do
--- Missile enumerators --- Missile enumerators
-- @field Harms -- @field Harms
SHORAD.Harms = { SHORAD.Harms = {
--[[
["X58"] = "weapons.missiles.X_58", --Kh-58X anti-radiation missiles fired
["Kh25"] = "weapons.missiles.Kh25MP_PRGS1VP", --Kh-25MP anti-radiation missiles fired
["X25"] = "weapons.missiles.X_25MP", --Kh-25MPU anti-radiation missiles fired
["X28"] = "weapons.missiles.X_28", --Kh-28 anti-radiation missiles fired
["X31"] = "weapons.missiles.X_31P", --Kh-31P anti-radiation missiles fired
["AGM45A"] = "weapons.missiles.AGM_45A", --AGM-45A anti-radiation missiles fired
["AGM45"] = "weapons.missiles.AGM_45", --AGM-45B anti-radiation missiles fired
["AGM88"] = "weapons.missiles.AGM_88", --AGM-88C anti-radiation missiles fired
["AGM122"] = "weapons.missiles.AGM_122", --AGM-122 Sidearm anti-radiation missiles fired
["LD10"] = "weapons.missiles.LD-10", --LD-10 anti-radiation missiles fired
["ALARM"] = "weapons.missiles.ALARM", --ALARM anti-radiation missiles fired
["AGM84E"] = "weapons.missiles.AGM_84E", --AGM84 anti-radiation missiles fired
["AGM84A"] = "weapons.missiles.AGM_84A", --AGM84 anti-radiation missiles fired
["AGM84H"] = "weapons.missiles.AGM_84H", --AGM84 anti-radiation missiles fired
--]]
["AGM_88"] = "AGM_88", ["AGM_88"] = "AGM_88",
["AGM_45"] = "AGM_45", ["AGM_45"] = "AGM_45",
["AGM_122"] = "AGM_122", ["AGM_122"] = "AGM_122",
@ -137,7 +121,7 @@ do
["X_31"] = "X_31", ["X_31"] = "X_31",
["Kh25"] = "Kh25", ["Kh25"] = "Kh25",
} }
--- TODO complete list? --- TODO complete list?
-- @field Mavs -- @field Mavs
SHORAD.Mavs = { SHORAD.Mavs = {
@ -148,7 +132,7 @@ do
["Kh31"] = "Kh31", ["Kh31"] = "Kh31",
["Kh66"] = "Kh66", ["Kh66"] = "Kh66",
} }
--- Instantiates a new SHORAD object --- Instantiates a new SHORAD object
-- @param #SHORAD self -- @param #SHORAD self
-- @param #string Name Name of this SHORAD -- @param #string Name Name of this SHORAD
@ -157,10 +141,12 @@ do
-- @param #number Radius Defense radius in meters, used to switch on groups -- @param #number Radius Defense radius in meters, used to switch on groups
-- @param #number ActiveTimer Determines how many seconds the systems stay on red alert after wake-up call -- @param #number ActiveTimer Determines how many seconds the systems stay on red alert after wake-up call
-- @param #string Coalition Coalition, i.e. "blue", "red", or "neutral" -- @param #string Coalition Coalition, i.e. "blue", "red", or "neutral"
function SHORAD:New(Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition) -- @param #boolean UseEmOnOff Use Emissions On/Off rather than Alarm State Red/Green (default: use Emissions switch)
-- @retunr #SHORAD self
function SHORAD:New(Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition, UseEmOnOff)
local self = BASE:Inherit( self, BASE:New() ) local self = BASE:Inherit( self, BASE:New() )
self:T({Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition}) self:I({Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition})
local GroupSet = SET_GROUP:New():FilterPrefixes(ShoradPrefix):FilterCoalitions(Coalition):FilterCategoryGround():FilterStart() local GroupSet = SET_GROUP:New():FilterPrefixes(ShoradPrefix):FilterCoalitions(Coalition):FilterCategoryGround():FilterStart()
self.name = Name or "MyShorad" self.name = Name or "MyShorad"
@ -171,81 +157,101 @@ do
self.ActiveTimer = ActiveTimer or 600 self.ActiveTimer = ActiveTimer or 600
self.ActiveGroups = {} self.ActiveGroups = {}
self.Groupset = GroupSet self.Groupset = GroupSet
self:HandleEvent( EVENTS.Shot )
self.DefendHarms = true self.DefendHarms = true
self.DefendMavs = true self.DefendMavs = true
self.DefenseLowProb = 70 -- probability to detect a missile shot, low margin self.DefenseLowProb = 70 -- probability to detect a missile shot, low margin
self.DefenseHighProb = 90 -- probability to detect a missile shot, high margin self.DefenseHighProb = 90 -- probability to detect a missile shot, high margin
self.UseEmOnOff = true -- Decide if we are using Emission on/off (default) or AlarmState red/green self.UseEmOnOff = UseEmOnOff or false -- Decide if we are using Emission on/off (default) or AlarmState red/green
self:I("*** SHORAD - Started Version 0.2.5") self:I("*** SHORAD - Started Version 0.2.8")
-- Set the string id for output to DCS.log file. -- Set the string id for output to DCS.log file.
self.lid=string.format("SHORAD %s | ", self.name) self.lid=string.format("SHORAD %s | ", self.name)
self:_InitState() self:_InitState()
self:HandleEvent(EVENTS.Shot, self.HandleEventShot)
return self return self
end end
--- Initially set all groups to alarm state GREEN --- Initially set all groups to alarm state GREEN
-- @param #SHORAD self -- @param #SHORAD self
function SHORAD:_InitState() function SHORAD:_InitState()
self:I(self.lid .. " _InitState")
local table = {} local table = {}
local set = self.Groupset local set = self.Groupset
self:T({set = set}) self:I({set = set})
local aliveset = set:GetAliveSet() --#table local aliveset = set:GetAliveSet() --#table
for _,_group in pairs (aliveset) do for _,_group in pairs (aliveset) do
if self.UseEmOnOff then if self.UseEmOnOff then
--_group:SetAIOff() --_group:SetAIOff()
_group:EnableEmission(false) _group:EnableEmission(false)
_group:OptionAlarmStateRed() --Wrapper.Group#GROUP
else else
_group:OptionAlarmStateGreen() --Wrapper.Group#GROUP _group:OptionAlarmStateGreen() --Wrapper.Group#GROUP
end end
_group:OptionDisperseOnAttack(30)
end end
-- gather entropy -- gather entropy
for i=1,10 do for i=1,100 do
math.random() math.random()
end end
return self
end end
--- Switch debug state --- Switch debug state on
-- @param #SHORAD self -- @param #SHORAD self
-- @param #boolean debug Switch debug on (true) or off (false) -- @param #boolean debug Switch debug on (true) or off (false)
function SHORAD:SwitchDebug(debug) function SHORAD:SwitchDebug(onoff)
self:T( { debug } ) self:I( { onoff } )
local onoff = debug or false if onoff then
if debug then self:SwitchDebugOn()
self.debug = true
--tracing
BASE:TraceOn()
BASE:TraceClass("SHORAD")
else else
self.debug = false self.SwitchDebugOff()
BASE:TraceOff()
end end
return self
end end
--- Switch debug state on
-- @param #SHORAD self
function SHORAD:SwitchDebugOn()
self.debug = true
--tracing
BASE:TraceOn()
BASE:TraceClass("SHORAD")
return self
end
--- Switch debug state off
-- @param #SHORAD self
function SHORAD:SwitchDebugOff()
self.debug = false
BASE:TraceOff()
return self
end
--- Switch defense for HARMs --- Switch defense for HARMs
-- @param #SHORAD self -- @param #SHORAD self
-- @param #boolean onoff -- @param #boolean onoff
function SHORAD:SwitchHARMDefense(onoff) function SHORAD:SwitchHARMDefense(onoff)
self:T( { onoff } ) self:I( { onoff } )
local onoff = onoff or true local onoff = onoff or true
self.DefendHarms = onoff self.DefendHarms = onoff
return self
end end
--- Switch defense for AGMs --- Switch defense for AGMs
-- @param #SHORAD self -- @param #SHORAD self
-- @param #boolean onoff -- @param #boolean onoff
function SHORAD:SwitchAGMDefense(onoff) function SHORAD:SwitchAGMDefense(onoff)
self:T( { onoff } ) self:I( { onoff } )
local onoff = onoff or true local onoff = onoff or true
self.DefendMavs = onoff self.DefendMavs = onoff
return self
end end
--- Set defense probability limits --- Set defense probability limits
-- @param #SHORAD self -- @param #SHORAD self
-- @param #number low Minimum detection limit, integer 1-100 -- @param #number low Minimum detection limit, integer 1-100
-- @param #number high Maximum detection limit integer 1-100 -- @param #number high Maximum detection limit integer 1-100
function SHORAD:SetDefenseLimits(low,high) function SHORAD:SetDefenseLimits(low,high)
self:T( { low, high } ) self:I( { low, high } )
local low = low or 70 local low = low or 70
local high = high or 90 local high = high or 90
if (low < 0) or (low > 100) or (low > high) then if (low < 0) or (low > 100) or (low > high) then
@ -256,43 +262,51 @@ do
end end
self.DefenseLowProb = low self.DefenseLowProb = low
self.DefenseHighProb = high self.DefenseHighProb = high
return self
end end
--- Set the number of seconds a SHORAD site will stay active --- Set the number of seconds a SHORAD site will stay active
-- @param #SHORAD self -- @param #SHORAD self
-- @param #number seconds Number of seconds systems stay active -- @param #number seconds Number of seconds systems stay active
function SHORAD:SetActiveTimer(seconds) function SHORAD:SetActiveTimer(seconds)
self:I(self.lid .. " SetActiveTimer")
local timer = seconds or 600 local timer = seconds or 600
if timer < 0 then if timer < 0 then
timer = 600 timer = 600
end end
self.ActiveTimer = timer self.ActiveTimer = timer
return self
end end
--- Set the number of meters for the SHORAD defense zone --- Set the number of meters for the SHORAD defense zone
-- @param #SHORAD self -- @param #SHORAD self
-- @param #number meters Radius of the defense search zone in meters. #SHORADs in this range around a targeted group will go active -- @param #number meters Radius of the defense search zone in meters. #SHORADs in this range around a targeted group will go active
function SHORAD:SetDefenseRadius(meters) function SHORAD:SetDefenseRadius(meters)
self:I(self.lid .. " SetDefenseRadius")
local radius = meters or 20000 local radius = meters or 20000
if radius < 0 then if radius < 0 then
radius = 20000 radius = 20000
end end
self.Radius = radius self.Radius = radius
return self
end end
--- Set using Emission on/off instead of changing alarm state --- Set using Emission on/off instead of changing alarm state
-- @param #SHORAD self -- @param #SHORAD self
-- @param #boolean switch Decide if we are changing alarm state or AI state -- @param #boolean switch Decide if we are changing alarm state or AI state
function SHORAD:SetUsingEmOnOff(switch) function SHORAD:SetUsingEmOnOff(switch)
self:I(self.lid .. " SetUsingEmOnOff")
self.UseEmOnOff = switch or false self.UseEmOnOff = switch or false
return self
end end
--- Check if a HARM was fired --- Check if a HARM was fired
-- @param #SHORAD self -- @param #SHORAD self
-- @param #string WeaponName -- @param #string WeaponName
-- @return #boolean Returns true for a match -- @return #boolean Returns true for a match
function SHORAD:_CheckHarms(WeaponName) function SHORAD:_CheckHarms(WeaponName)
self:T( { WeaponName } ) self:I(self.lid .. " _CheckHarms")
self:I( { WeaponName } )
local hit = false local hit = false
if self.DefendHarms then if self.DefendHarms then
for _,_name in pairs (SHORAD.Harms) do for _,_name in pairs (SHORAD.Harms) do
@ -301,13 +315,14 @@ do
end end
return hit return hit
end end
--- Check if an AGM was fired --- Check if an AGM was fired
-- @param #SHORAD self -- @param #SHORAD self
-- @param #string WeaponName -- @param #string WeaponName
-- @return #boolean Returns true for a match -- @return #boolean Returns true for a match
function SHORAD:_CheckMavs(WeaponName) function SHORAD:_CheckMavs(WeaponName)
self:T( { WeaponName } ) self:I(self.lid .. " _CheckMavs")
self:I( { WeaponName } )
local hit = false local hit = false
if self.DefendMavs then if self.DefendMavs then
for _,_name in pairs (SHORAD.Mavs) do for _,_name in pairs (SHORAD.Mavs) do
@ -316,34 +331,36 @@ do
end end
return hit return hit
end end
--- Check the coalition of the attacker --- Check the coalition of the attacker
-- @param #SHORAD self -- @param #SHORAD self
-- @param #string Coalition name -- @param #string Coalition name
-- @return #boolean Returns false for a match -- @return #boolean Returns false for a match
function SHORAD:_CheckCoalition(Coalition) function SHORAD:_CheckCoalition(Coalition)
self:I(self.lid .. " _CheckCoalition")
local owncoalition = self.Coalition local owncoalition = self.Coalition
local othercoalition = "" local othercoalition = ""
if Coalition == 0 then if Coalition == 0 then
othercoalition = "neutral" othercoalition = "neutral"
elseif Coalition == 1 then elseif Coalition == 1 then
othercoalition = "red" othercoalition = "red"
else else
othercoalition = "blue" othercoalition = "blue"
end end
self:T({owncoalition = owncoalition, othercoalition = othercoalition}) self:I({owncoalition = owncoalition, othercoalition = othercoalition})
if owncoalition ~= othercoalition then if owncoalition ~= othercoalition then
return true return true
else else
return false return false
end end
end end
--- Check if the missile is aimed at a SHORAD --- Check if the missile is aimed at a SHORAD
-- @param #SHORAD self -- @param #SHORAD self
-- @param #string TargetGroupName Name of the target group -- @param #string TargetGroupName Name of the target group
-- @return #boolean Returns true for a match, else false -- @return #boolean Returns true for a match, else false
function SHORAD:_CheckShotAtShorad(TargetGroupName) function SHORAD:_CheckShotAtShorad(TargetGroupName)
self:I(self.lid .. " _CheckShotAtShorad")
local tgtgrp = TargetGroupName local tgtgrp = TargetGroupName
local shorad = self.Groupset local shorad = self.Groupset
local shoradset = shorad:GetAliveSet() --#table local shoradset = shorad:GetAliveSet() --#table
@ -352,17 +369,18 @@ do
local groupname = _groups:GetName() local groupname = _groups:GetName()
if string.find(groupname, tgtgrp, 1) then if string.find(groupname, tgtgrp, 1) then
returnname = true returnname = true
_groups:RelocateGroundRandomInRadius(7,100,false,false) -- be a bit evasive --_groups:RelocateGroundRandomInRadius(7,100,false,false) -- be a bit evasive
end end
end end
return returnname return returnname
end end
--- Check if the missile is aimed at a SAM site --- Check if the missile is aimed at a SAM site
-- @param #SHORAD self -- @param #SHORAD self
-- @param #string TargetGroupName Name of the target group -- @param #string TargetGroupName Name of the target group
-- @return #boolean Returns true for a match, else false -- @return #boolean Returns true for a match, else false
function SHORAD:_CheckShotAtSams(TargetGroupName) function SHORAD:_CheckShotAtSams(TargetGroupName)
self:I(self.lid .. " _CheckShotAtSams")
local tgtgrp = TargetGroupName local tgtgrp = TargetGroupName
local shorad = self.Samset local shorad = self.Samset
--local shoradset = shorad:GetAliveSet() --#table --local shoradset = shorad:GetAliveSet() --#table
@ -376,11 +394,12 @@ do
end end
return returnname return returnname
end end
--- Calculate if the missile shot is detected --- Calculate if the missile shot is detected
-- @param #SHORAD self -- @param #SHORAD self
-- @return #boolean Returns true for a detection, else false -- @return #boolean Returns true for a detection, else false
function SHORAD:_ShotIsDetected() function SHORAD:_ShotIsDetected()
self:I(self.lid .. " _ShotIsDetected")
local IsDetected = false local IsDetected = false
local DetectionProb = math.random(self.DefenseLowProb, self.DefenseHighProb) -- reference value local DetectionProb = math.random(self.DefenseLowProb, self.DefenseHighProb) -- reference value
local ActualDetection = math.random(1,100) -- value for this shot local ActualDetection = math.random(1,100) -- value for this shot
@ -389,15 +408,15 @@ do
end end
return IsDetected return IsDetected
end end
--- Wake up #SHORADs in a zone with diameter Radius for ActiveTimer seconds --- Wake up #SHORADs in a zone with diameter Radius for ActiveTimer seconds
-- @param #SHORAD self -- @param #SHORAD self
-- @param #string TargetGroup Name of the target group used to build the #ZONE -- @param #string TargetGroup Name of the target group used to build the #ZONE
-- @param #number Radius Radius of the #ZONE -- @param #number Radius Radius of the #ZONE
-- @param #number ActiveTimer Number of seconds to stay active -- @param #number ActiveTimer Number of seconds to stay active
-- @param #number TargetCat (optional) Category, i.e. Object.Category.UNIT or Object.Category.STATIC -- @param #number TargetCat (optional) Category, i.e. Object.Category.UNIT or Object.Category.STATIC
-- @usage Use this function to integrate with other systems, example -- @usage Use this function to integrate with other systems, example
-- --
-- local SamSet = SET_GROUP:New():FilterPrefixes("Blue SAM"):FilterCoalitions("blue"):FilterStart() -- local SamSet = SET_GROUP:New():FilterPrefixes("Blue SAM"):FilterCoalitions("blue"):FilterStart()
-- myshorad = SHORAD:New("BlueShorad", "Blue SHORAD", SamSet, 22000, 600, "blue") -- myshorad = SHORAD:New("BlueShorad", "Blue SHORAD", SamSet, 22000, 600, "blue")
-- myshorad:SwitchDebug(true) -- myshorad:SwitchDebug(true)
@ -405,7 +424,8 @@ do
-- mymantis:AddShorad(myshorad,720) -- mymantis:AddShorad(myshorad,720)
-- mymantis:Start() -- mymantis:Start()
function SHORAD:WakeUpShorad(TargetGroup, Radius, ActiveTimer, TargetCat) function SHORAD:WakeUpShorad(TargetGroup, Radius, ActiveTimer, TargetCat)
self:T({TargetGroup, Radius, ActiveTimer, TargetCat}) self:I(self.lid .. " WakeUpShorad")
self:I({TargetGroup, Radius, ActiveTimer, TargetCat})
local targetcat = TargetCat or Object.Category.UNIT local targetcat = TargetCat or Object.Category.UNIT
local targetgroup = TargetGroup local targetgroup = TargetGroup
local targetvec2 = nil local targetvec2 = nil
@ -432,17 +452,17 @@ do
group:OptionAlarmStateGreen() group:OptionAlarmStateGreen()
end end
local text = string.format("Sleeping SHORAD %s", group:GetName()) local text = string.format("Sleeping SHORAD %s", group:GetName())
self:T(text) self:I(text)
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug) local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
end end
-- go through set and find the one(s) to activate -- go through set and find the one(s) to activate
for _,_group in pairs (shoradset) do for _,_group in pairs (shoradset) do
if _group:IsAnyInZone(targetzone) then if _group:IsAnyInZone(targetzone) then
local text = string.format("Waking up SHORAD %s", _group:GetName()) local text = string.format("Waking up SHORAD %s", _group:GetName())
self:T(text) self:I(text)
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug) local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
if self.UseEmOnOff then if self.UseEmOnOff then
_group:SetAIOn() --_group:SetAIOn()
_group:EnableEmission(true) _group:EnableEmission(true)
end end
_group:OptionAlarmStateRed() _group:OptionAlarmStateRed()
@ -454,14 +474,15 @@ do
end end
end end
end end
return self
end end
--- Main function - work on the EventData --- Main function - work on the EventData
-- @param #SHORAD self -- @param #SHORAD self
-- @param Core.Event#EVENTDATA EventData The event details table data set -- @param Core.Event#EVENTDATA EventData The event details table data set
function SHORAD:OnEventShot( EventData ) function SHORAD:HandleEventShot( EventData )
self:T( { EventData } ) self:I( { EventData } )
self:I(self.lid .. " HandleEventShot")
--local ShootingUnit = EventData.IniDCSUnit --local ShootingUnit = EventData.IniDCSUnit
--local ShootingUnitName = EventData.IniDCSUnitName --local ShootingUnitName = EventData.IniDCSUnitName
local ShootingWeapon = EventData.Weapon -- Identify the weapon fired local ShootingWeapon = EventData.Weapon -- Identify the weapon fired
@ -473,24 +494,24 @@ do
local IsDetected = self:_ShotIsDetected() local IsDetected = self:_ShotIsDetected()
-- convert to text -- convert to text
local DetectedText = "false" local DetectedText = "false"
if IsDetected then if IsDetected then
DetectedText = "true" DetectedText = "true"
end end
local text = string.format("%s Missile Launched = %s | Detected probability state is %s", self.lid, ShootingWeaponName, DetectedText) local text = string.format("%s Missile Launched = %s | Detected probability state is %s", self.lid, ShootingWeaponName, DetectedText)
self:T( text ) self:I( text )
local m = MESSAGE:New(text,10,"Info"):ToAllIf(self.debug) local m = MESSAGE:New(text,10,"Info"):ToAllIf(self.debug)
-- --
if (self:_CheckHarms(ShootingWeaponName) or self:_CheckMavs(ShootingWeaponName)) and IsDetected then if (self:_CheckHarms(ShootingWeaponName) or self:_CheckMavs(ShootingWeaponName)) and IsDetected then
-- get target data -- get target data
local targetdata = EventData.Weapon:getTarget() -- Identify target local targetdata = EventData.Weapon:getTarget() -- Identify target
local targetcat = targetdata:getCategory() -- Identify category local targetcat = targetdata:getCategory() -- Identify category
self:T(string.format("Target Category (3=STATIC, 1=UNIT)= %s",tostring(targetcat))) self:I(string.format("Target Category (3=STATIC, 1=UNIT)= %s",tostring(targetcat)))
local targetunit = nil local targetunit = nil
if targetcat == Object.Category.UNIT then -- UNIT if targetcat == Object.Category.UNIT then -- UNIT
targetunit = UNIT:Find(targetdata) targetunit = UNIT:Find(targetdata)
elseif targetcat == Object.Category.STATIC then -- STATIC elseif targetcat == Object.Category.STATIC then -- STATIC
targetunit = STATIC:Find(targetdata) targetunit = STATIC:Find(targetdata)
end end
--local targetunitname = Unit.getName(targetdata) -- Unit name --local targetunitname = Unit.getName(targetdata) -- Unit name
if targetunit and targetunit:IsAlive() then if targetunit and targetunit:IsAlive() then
local targetunitname = targetunit:GetName() local targetunitname = targetunit:GetName()
@ -505,23 +526,23 @@ do
targetgroupname = targetunitname targetgroupname = targetunitname
end end
local text = string.format("%s Missile Target = %s", self.lid, tostring(targetgroupname)) local text = string.format("%s Missile Target = %s", self.lid, tostring(targetgroupname))
self:T( text ) self:I( text )
local m = MESSAGE:New(text,10,"Info"):ToAllIf(self.debug) local m = MESSAGE:New(text,10,"Info"):ToAllIf(self.debug)
-- check if we or a SAM site are the target -- check if we or a SAM site are the target
--local TargetGroup = EventData.TgtGroup -- Wrapper.Group#GROUP --local TargetGroup = EventData.TgtGroup -- Wrapper.Group#GROUP
local shotatus = self:_CheckShotAtShorad(targetgroupname) --#boolean local shotatus = self:_CheckShotAtShorad(targetgroupname) --#boolean
local shotatsams = self:_CheckShotAtSams(targetgroupname) --#boolean local shotatsams = self:_CheckShotAtSams(targetgroupname) --#boolean
-- if being shot at, find closest SHORADs to activate -- if being shot at, find closest SHORADs to activate
if shotatsams or shotatus then if shotatsams or shotatus then
self:T({shotatsams=shotatsams,shotatus=shotatus}) self:I({shotatsams=shotatsams,shotatus=shotatus})
self:WakeUpShorad(targetgroupname, self.Radius, self.ActiveTimer, targetcat) self:WakeUpShorad(targetgroupname, self.Radius, self.ActiveTimer, targetcat)
end end
end end
end end
end end
end end
-- --
end end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- SHORAD end -- SHORAD end
----------------------------------------------------------------------- -----------------------------------------------------------------------