mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Improve the consistency of the module intros to the most commonly used version (single dash). Add missing module information (abbreviated where none existed previously). Fix broken documentation links Make module names correspond to filenames (and fix links). Fix typos.
521 lines
19 KiB
Lua
521 lines
19 KiB
Lua
--- **Functional** - Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
|
--
|
|
-- ===
|
|
--
|
|
-- ## 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 defensive action by shutting down their radars.
|
|
-- * SEAD calculates the time it takes for a HARM to reach the target - and will attempt to minimize the shut-down time.
|
|
-- * Detection and evasion of shots has a random component based on the skill level of the SAM groups.
|
|
--
|
|
-- ===
|
|
--
|
|
-- ## Missions:
|
|
--
|
|
-- [SEV - SEAD Evasion](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SEV%20-%20SEAD%20Evasion)
|
|
--
|
|
-- ===
|
|
--
|
|
-- ### Authors: **FlightControl**, **applevangelist**
|
|
--
|
|
-- Last Update: Feb 2022
|
|
--
|
|
-- ===
|
|
--
|
|
-- @module Functional.Sead
|
|
-- @image SEAD.JPG
|
|
|
|
---
|
|
-- @type SEAD
|
|
-- @extends Core.Base#BASE
|
|
|
|
--- 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.
|
|
-- Once a HARM attack is detected, SEAD will shut down the radars of the attacked SAM site and take evasive action by moving the SAM
|
|
-- vehicles around (*if* they are drivable, that is). There's a component of randomness in detection and evasion, which is based on the
|
|
-- skill set of the SAM set (the higher the skill, the more likely). When a missile is fired from far away, the SAM will stay active for a
|
|
-- period of time to stay defensive, before it takes evasive actions.
|
|
--
|
|
-- # Constructor:
|
|
--
|
|
-- 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' } )
|
|
--
|
|
-- @field #SEAD
|
|
SEAD = {
|
|
ClassName = "SEAD",
|
|
TargetSkill = {
|
|
Average = { Evade = 30, DelayOn = { 40, 60 } } ,
|
|
Good = { Evade = 20, DelayOn = { 30, 50 } } ,
|
|
High = { Evade = 15, DelayOn = { 20, 40 } } ,
|
|
Excellent = { Evade = 10, DelayOn = { 10, 30 } }
|
|
},
|
|
SEADGroupPrefixes = {},
|
|
SuppressedGroups = {},
|
|
EngagementRange = 75, -- default 75% engagement range Feature Request #1355
|
|
Padding = 10,
|
|
CallBack = nil,
|
|
UseCallBack = false,
|
|
debug = false,
|
|
}
|
|
|
|
--- Missile enumerators
|
|
-- @field Harms
|
|
SEAD.Harms = {
|
|
["AGM_88"] = "AGM_88",
|
|
["AGM_45"] = "AGM_45",
|
|
["AGM_122"] = "AGM_122",
|
|
["AGM_84"] = "AGM_84",
|
|
["AGM_45"] = "AGM_45",
|
|
["ALARM"] = "ALARM",
|
|
["LD-10"] = "LD-10",
|
|
["X_58"] = "X_58",
|
|
["X_28"] = "X_28",
|
|
["X_25"] = "X_25",
|
|
["X_31"] = "X_31",
|
|
["Kh25"] = "Kh25",
|
|
["BGM_109"] = "BGM_109",
|
|
["AGM_154"] = "AGM_154",
|
|
["HY-2"] = "HY-2",
|
|
}
|
|
|
|
--- Missile enumerators - from DCS ME and Wikipedia
|
|
-- @field HarmData
|
|
SEAD.HarmData = {
|
|
-- km and mach
|
|
["AGM_88"] = { 150, 3},
|
|
["AGM_45"] = { 12, 2},
|
|
["AGM_122"] = { 16.5, 2.3},
|
|
["AGM_84"] = { 280, 0.8},
|
|
["ALARM"] = { 45, 2},
|
|
["LD-10"] = { 60, 4},
|
|
["X_58"] = { 70, 4},
|
|
["X_28"] = { 80, 2.5},
|
|
["X_25"] = { 25, 0.76},
|
|
["X_31"] = {150, 3},
|
|
["Kh25"] = {25, 0.8},
|
|
["BGM_109"] = {460, 0.705}, --in-game ~465kn
|
|
["AGM_154"] = {130, 0.61},
|
|
["HY-2"] = {90,1},
|
|
}
|
|
|
|
--- 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...
|
|
-- Chances are big that the missile will miss.
|
|
-- @param #SEAD self
|
|
-- @param #table SEADGroupPrefixes Table of #string entries or single #string, which is a table of Prefixes of the SA Groups in the DCS mission editor on which evasive actions need to be taken.
|
|
-- @param #number Padding (Optional) Extra number of seconds to add to radar switch-back-on time
|
|
-- @return #SEAD self
|
|
-- @usage
|
|
-- -- CCCP SEAD Defenses
|
|
-- -- Defends the Russian SA installations from SEAD attacks.
|
|
-- 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, Padding )
|
|
|
|
local self = BASE:Inherit( self, FSM:New() )
|
|
self:T( SEADGroupPrefixes )
|
|
|
|
if type( SEADGroupPrefixes ) == 'table' then
|
|
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
|
|
self.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix
|
|
end
|
|
else
|
|
self.SEADGroupPrefixes[SEADGroupPrefixes] = SEADGroupPrefixes
|
|
end
|
|
|
|
local padding = Padding or 10
|
|
if padding < 10 then padding = 10 end
|
|
self.Padding = padding
|
|
self.UseEmissionsOnOff = true
|
|
|
|
self.debug = false
|
|
|
|
self.CallBack = nil
|
|
self.UseCallBack = false
|
|
|
|
self:HandleEvent( EVENTS.Shot, self.HandleEventShot )
|
|
|
|
-- Start State.
|
|
self:SetStartState("Running")
|
|
self:AddTransition("*", "ManageEvasion", "*")
|
|
self:AddTransition("*", "CalculateHitZone", "*")
|
|
|
|
self:I("*** SEAD - Started Version 0.4.3")
|
|
return self
|
|
end
|
|
|
|
--- Update the active SEAD Set (while running)
|
|
-- @param #SEAD self
|
|
-- @param #table SEADGroupPrefixes The prefixes to add, note: can also be a single #string
|
|
-- @return #SEAD self
|
|
function SEAD:UpdateSet( SEADGroupPrefixes )
|
|
|
|
self:T( SEADGroupPrefixes )
|
|
|
|
if type( SEADGroupPrefixes ) == 'table' then
|
|
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
|
|
self.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix
|
|
end
|
|
else
|
|
self.SEADGroupPrefixes[SEADGroupPrefixes] = SEADGroupPrefixes
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Sets the engagement range of the SAMs. Defaults to 75% to make it more deadly. Feature Request #1355
|
|
-- @param #SEAD self
|
|
-- @param #number range Set the engagement range in percent, e.g. 55 (default 75)
|
|
-- @return #SEAD self
|
|
function SEAD:SetEngagementRange(range)
|
|
self:T( { range } )
|
|
range = range or 75
|
|
if range < 0 or range > 100 then
|
|
range = 75
|
|
end
|
|
self.EngagementRange = range
|
|
self:T(string.format("*** SEAD - Engagement range set to %s",range))
|
|
return self
|
|
end
|
|
|
|
--- Set the padding in seconds, which extends the radar off time calculated by SEAD
|
|
-- @param #SEAD self
|
|
-- @param #number Padding Extra number of seconds to add for the switch-on (default 10 seconds)
|
|
-- @return #SEAD self
|
|
function SEAD:SetPadding(Padding)
|
|
self:T( { Padding } )
|
|
local padding = Padding or 10
|
|
if padding < 10 then padding = 10 end
|
|
self.Padding = padding
|
|
return self
|
|
end
|
|
|
|
--- Set SEAD to use emissions on/off in addition to alarm state.
|
|
-- @param #SEAD self
|
|
-- @param #boolean Switch True for on, false for off.
|
|
-- @return #SEAD self
|
|
function SEAD:SwitchEmissions(Switch)
|
|
self:T({Switch})
|
|
self.UseEmissionsOnOff = Switch
|
|
return self
|
|
end
|
|
|
|
--- Add an object to call back when going evasive.
|
|
-- @param #SEAD self
|
|
-- @param #table Object The object to call. Needs to have object functions as follows:
|
|
-- `:SeadSuppressionPlanned(Group, Name, SuppressionStartTime, SuppressionEndTime)`
|
|
-- `:SeadSuppressionStart(Group, Name)`,
|
|
-- `:SeadSuppressionEnd(Group, Name)`,
|
|
-- @return #SEAD self
|
|
function SEAD:AddCallBack(Object)
|
|
self:T({Class=Object.ClassName})
|
|
self.CallBack = Object
|
|
self.UseCallBack = true
|
|
return self
|
|
end
|
|
|
|
--- (Internal) Check if a known HARM was fired
|
|
-- @param #SEAD self
|
|
-- @param #string WeaponName
|
|
-- @return #boolean Returns true for a match
|
|
-- @return #string name Name of hit in table
|
|
function SEAD:_CheckHarms(WeaponName)
|
|
self:T( { WeaponName } )
|
|
local hit = false
|
|
local name = ""
|
|
for _,_name in pairs (SEAD.Harms) do
|
|
if string.find(WeaponName,_name,1,true) then
|
|
hit = true
|
|
name = _name
|
|
break
|
|
end
|
|
end
|
|
return hit, name
|
|
end
|
|
|
|
--- (Internal) Return distance in meters between two coordinates or -1 on error.
|
|
-- @param #SEAD self
|
|
-- @param Core.Point#COORDINATE _point1 Coordinate one
|
|
-- @param Core.Point#COORDINATE _point2 Coordinate two
|
|
-- @return #number Distance in meters
|
|
function SEAD:_GetDistance(_point1, _point2)
|
|
self:T("_GetDistance")
|
|
if _point1 and _point2 then
|
|
local distance1 = _point1:Get2DDistance(_point2)
|
|
local distance2 = _point1:DistanceFromPointVec2(_point2)
|
|
--self:T({dist1=distance1, dist2=distance2})
|
|
if distance1 and type(distance1) == "number" then
|
|
return distance1
|
|
elseif distance2 and type(distance2) == "number" then
|
|
return distance2
|
|
else
|
|
self:E("*****Cannot calculate distance!")
|
|
self:E({_point1,_point2})
|
|
return -1
|
|
end
|
|
else
|
|
self:E("******Cannot calculate distance!")
|
|
self:E({_point1,_point2})
|
|
return -1
|
|
end
|
|
end
|
|
|
|
--- (Internal) Calculate hit zone of an AGM-88
|
|
-- @param #SEAD self
|
|
-- @param #table SEADWeapon DCS.Weapon object
|
|
-- @param Core.Point#COORDINATE pos0 Position of the plane when it fired
|
|
-- @param #number height Height when the missile was fired
|
|
-- @param Wrapper.Group#GROUP SEADGroup Attacker group
|
|
-- @param #string SEADWeaponName Weapon Name
|
|
-- @return #SEAD self
|
|
function SEAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADGroup,SEADWeaponName)
|
|
self:T("**** Calculating hit zone for " .. (SEADWeaponName or "None"))
|
|
if SEADWeapon and SEADWeapon:isExist() then
|
|
--local pos = SEADWeapon:getPoint()
|
|
|
|
-- postion and height
|
|
local position = SEADWeapon:getPosition()
|
|
local mheight = height
|
|
-- heading
|
|
local wph = math.atan2(position.x.z, position.x.x)
|
|
if wph < 0 then
|
|
wph=wph+2*math.pi
|
|
end
|
|
wph=math.deg(wph)
|
|
|
|
-- velocity
|
|
local wpndata = SEAD.HarmData["AGM_88"]
|
|
if string.find(SEADWeaponName,"154",1) then
|
|
wpndata = SEAD.HarmData["AGM_154"]
|
|
end
|
|
local mveloc = math.floor(wpndata[2] * 340.29)
|
|
local c1 = (2*mheight*9.81)/(mveloc^2)
|
|
local c2 = (mveloc^2) / 9.81
|
|
local Ropt = c2 * math.sqrt(c1+1)
|
|
if height <= 5000 then
|
|
Ropt = Ropt * 0.72
|
|
elseif height <= 7500 then
|
|
Ropt = Ropt * 0.82
|
|
elseif height <= 10000 then
|
|
Ropt = Ropt * 0.87
|
|
elseif height <= 12500 then
|
|
Ropt = Ropt * 0.98
|
|
end
|
|
|
|
-- look at a couple of zones across the trajectory
|
|
for n=1,3 do
|
|
local dist = Ropt - ((n-1)*20000)
|
|
local predpos= pos0:Translate(dist,wph)
|
|
if predpos then
|
|
|
|
local targetzone = ZONE_RADIUS:New("Target Zone",predpos:GetVec2(),20000)
|
|
|
|
if self.debug then
|
|
predpos:MarkToAll(string.format("height=%dm | heading=%d | velocity=%ddeg | Ropt=%dm",mheight,wph,mveloc,Ropt),false)
|
|
targetzone:DrawZone(coalition.side.BLUE,{0,0,1},0.2,nil,nil,3,true)
|
|
end
|
|
|
|
local seadset = SET_GROUP:New():FilterPrefixes(self.SEADGroupPrefixes):FilterZones({targetzone}):FilterOnce()
|
|
local tgtcoord = targetzone:GetRandomPointVec2()
|
|
--if tgtcoord and tgtcoord.ClassName == "COORDINATE" then
|
|
--local tgtgrp = seadset:FindNearestGroupFromPointVec2(tgtcoord)
|
|
local tgtgrp = seadset:GetRandom()
|
|
local _targetgroup = nil
|
|
local _targetgroupname = "none"
|
|
local _targetskill = "Random"
|
|
if tgtgrp and tgtgrp:IsAlive() then
|
|
_targetgroup = tgtgrp
|
|
_targetgroupname = tgtgrp:GetName() -- group name
|
|
_targetskill = tgtgrp:GetUnit(1):GetSkill()
|
|
self:T("*** Found Target = ".. _targetgroupname)
|
|
self:ManageEvasion(_targetskill,_targetgroup,pos0,"AGM_88",SEADGroup, 20)
|
|
end
|
|
--end
|
|
end
|
|
end
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- (Internal) Handle Evasion
|
|
-- @param #SEAD self
|
|
-- @param #string _targetskill
|
|
-- @param Wrapper.Group#GROUP _targetgroup
|
|
-- @param Core.Point#COORDINATE SEADPlanePos
|
|
-- @param #string SEADWeaponName
|
|
-- @param Wrapper.Group#GROUP SEADGroup Attacker Group
|
|
-- @param #number timeoffset Offset for tti calc
|
|
-- @return #SEAD self
|
|
function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,timeoffset)
|
|
local timeoffset = timeoffset or 0
|
|
if _targetskill == "Random" then -- when skill is random, choose a skill
|
|
local Skills = { "Average", "Good", "High", "Excellent" }
|
|
_targetskill = Skills[ math.random(1,4) ]
|
|
end
|
|
--self:T( _targetskill )
|
|
if self.TargetSkill[_targetskill] then
|
|
local _evade = math.random (1,100) -- random number for chance of evading action
|
|
if (_evade > self.TargetSkill[_targetskill].Evade) then
|
|
self:T("*** SEAD - Evading")
|
|
-- calculate distance of attacker
|
|
local _targetpos = _targetgroup:GetCoordinate()
|
|
local _distance = self:_GetDistance(SEADPlanePos, _targetpos)
|
|
-- weapon speed
|
|
local hit, data = self:_CheckHarms(SEADWeaponName)
|
|
local wpnspeed = 666 -- ;)
|
|
local reach = 10
|
|
if hit then
|
|
local wpndata = SEAD.HarmData[data]
|
|
reach = wpndata[1] * 1,1
|
|
local mach = wpndata[2]
|
|
wpnspeed = math.floor(mach * 340.29)
|
|
end
|
|
-- time to impact
|
|
local _tti = math.floor(_distance / wpnspeed) - timeoffset -- estimated impact time
|
|
if _distance > 0 then
|
|
_distance = math.floor(_distance / 1000) -- km
|
|
else
|
|
_distance = 0
|
|
end
|
|
|
|
self:T( string.format("*** SEAD - target skill %s, distance %dkm, reach %dkm, tti %dsec", _targetskill, _distance,reach,_tti ))
|
|
|
|
if reach >= _distance then
|
|
self:T("*** SEAD - Shot in Reach")
|
|
|
|
local function SuppressionStart(args)
|
|
self:T(string.format("*** SEAD - %s Radar Off & Relocating",args[2]))
|
|
local grp = args[1] -- Wrapper.Group#GROUP
|
|
local name = args[2] -- #string Group Name
|
|
local attacker = args[3] -- Wrapper.Group#GROUP
|
|
if self.UseEmissionsOnOff then
|
|
grp:EnableEmission(false)
|
|
end
|
|
grp:OptionAlarmStateGreen() -- needed else we cannot move around
|
|
grp:RelocateGroundRandomInRadius(20,300,false,false,"Diamond")
|
|
if self.UseCallBack then
|
|
local object = self.CallBack
|
|
object:SeadSuppressionStart(grp,name,attacker)
|
|
end
|
|
end
|
|
|
|
local function SuppressionStop(args)
|
|
self:T(string.format("*** SEAD - %s Radar On",args[2]))
|
|
local grp = args[1] -- Wrapper.Group#GROUP
|
|
local name = args[2] -- #string Group Nam
|
|
if self.UseEmissionsOnOff then
|
|
grp:EnableEmission(true)
|
|
end
|
|
grp:OptionAlarmStateRed()
|
|
grp:OptionEngageRange(self.EngagementRange)
|
|
self.SuppressedGroups[name] = false
|
|
if self.UseCallBack then
|
|
local object = self.CallBack
|
|
object:SeadSuppressionEnd(grp,name)
|
|
end
|
|
end
|
|
|
|
-- randomize switch-on time
|
|
local delay = math.random(self.TargetSkill[_targetskill].DelayOn[1], self.TargetSkill[_targetskill].DelayOn[2])
|
|
if delay > _tti then delay = delay / 2 end -- speed up
|
|
if _tti > 600 then delay = _tti - 90 end -- shot from afar, 600 is default shorad ontime
|
|
|
|
local SuppressionStartTime = timer.getTime() + delay
|
|
local SuppressionEndTime = timer.getTime() + _tti + self.Padding
|
|
local _targetgroupname = _targetgroup:GetName()
|
|
if not self.SuppressedGroups[_targetgroupname] then
|
|
self:T(string.format("*** SEAD - %s | Parameters TTI %ds | Switch-Off in %ds",_targetgroupname,_tti,delay))
|
|
timer.scheduleFunction(SuppressionStart,{_targetgroup,_targetgroupname, SEADGroup},SuppressionStartTime)
|
|
timer.scheduleFunction(SuppressionStop,{_targetgroup,_targetgroupname},SuppressionEndTime)
|
|
self.SuppressedGroups[_targetgroupname] = true
|
|
if self.UseCallBack then
|
|
local object = self.CallBack
|
|
object:SeadSuppressionPlanned(_targetgroup,_targetgroupname,SuppressionStartTime,SuppressionEndTime, SEADGroup)
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- (Internal) Detects if an SAM site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
|
|
-- @param #SEAD self
|
|
-- @param Core.Event#EVENTDATA EventData
|
|
-- @return #SEAD self
|
|
function SEAD:HandleEventShot( EventData )
|
|
self:T( { EventData.id } )
|
|
local SEADPlane = EventData.IniUnit -- Wrapper.Unit#UNIT
|
|
local SEADGroup = EventData.IniGroup -- Wrapper.Group#GROUP
|
|
local SEADPlanePos = SEADPlane:GetCoordinate() -- Core.Point#COORDINATE
|
|
local SEADUnit = EventData.IniDCSUnit
|
|
local SEADUnitName = EventData.IniDCSUnitName
|
|
local SEADWeapon = EventData.Weapon -- Identify the weapon fired
|
|
local SEADWeaponName = EventData.WeaponName -- return weapon type
|
|
|
|
self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName)
|
|
--self:T({ SEADWeapon })
|
|
|
|
if self:_CheckHarms(SEADWeaponName) then
|
|
self:T( '*** SEAD - Weapon Match' )
|
|
local _targetskill = "Random"
|
|
local _targetgroupname = "none"
|
|
local _target = EventData.Weapon:getTarget() -- Identify target
|
|
if not _target or self.debug then -- AGM-88 or 154 w/o target data
|
|
self:E("***** SEAD - No target data for " .. (SEADWeaponName or "None"))
|
|
if string.find(SEADWeaponName,"AGM_88",1,true) or string.find(SEADWeaponName,"AGM_154",1,true) then
|
|
self:I("**** Tracking AGM-88/154 with no target data.")
|
|
local pos0 = SEADPlane:GetCoordinate()
|
|
local fheight = SEADPlane:GetHeight()
|
|
self:__CalculateHitZone(20,SEADWeapon,pos0,fheight,SEADGroup,SEADWeaponName)
|
|
end
|
|
return self
|
|
end
|
|
local targetcat = _target:getCategory() -- Identify category
|
|
local _targetUnit = nil -- Wrapper.Unit#UNIT
|
|
local _targetgroup = nil -- Wrapper.Group#GROUP
|
|
self:T(string.format("*** Targetcat = %d",targetcat))
|
|
if targetcat == Object.Category.UNIT then -- UNIT
|
|
self:T("*** Target Category UNIT")
|
|
_targetUnit = UNIT:Find(_target) -- Wrapper.Unit#UNIT
|
|
if _targetUnit and _targetUnit:IsAlive() then
|
|
_targetgroup = _targetUnit:GetGroup()
|
|
_targetgroupname = _targetgroup:GetName() -- group name
|
|
local _targetUnitName = _targetUnit:GetName()
|
|
_targetUnit:GetSkill()
|
|
_targetskill = _targetUnit:GetSkill()
|
|
end
|
|
elseif targetcat == Object.Category.STATIC then
|
|
self:T("*** Target Category STATIC")
|
|
local seadset = SET_GROUP:New():FilterPrefixes(self.SEADGroupPrefixes):FilterOnce()
|
|
local targetpoint = _target:getPoint() or {x=0,y=0,z=0}
|
|
local tgtcoord = COORDINATE:NewFromVec3(targetpoint)
|
|
local tgtgrp = seadset:FindNearestGroupFromPointVec2(tgtcoord)
|
|
if tgtgrp and tgtgrp:IsAlive() then
|
|
_targetgroup = tgtgrp
|
|
_targetgroupname = tgtgrp:GetName() -- group name
|
|
_targetskill = tgtgrp:GetUnit(1):GetSkill()
|
|
self:T("*** Found Target = ".. _targetgroupname)
|
|
end
|
|
end
|
|
-- see if we are shot at
|
|
local SEADGroupFound = false
|
|
for SEADGroupPrefixID, SEADGroupPrefix in pairs( self.SEADGroupPrefixes ) do
|
|
self:T("Target = ".. _targetgroupname .. " | Prefix = " .. SEADGroupPrefix )
|
|
if string.find( _targetgroupname, SEADGroupPrefix,1,true ) then
|
|
SEADGroupFound = true
|
|
self:T( '*** SEAD - Group Match Found' )
|
|
break
|
|
end
|
|
end
|
|
if SEADGroupFound == true then -- yes we are being attacked
|
|
self:ManageEvasion(_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup)
|
|
end
|
|
end
|
|
return self
|
|
end
|