SEAD/SHORAD - Add AGM-88 player modes handling

This commit is contained in:
Applevangelist 2021-11-22 11:37:10 +01:00
parent ab4411e5bb
commit aec6dd1246
2 changed files with 121 additions and 31 deletions

View File

@ -133,16 +133,15 @@ function SEAD:New( SEADGroupPrefixes, Padding )
self.CallBack = nil self.CallBack = nil
self.UseCallBack = false self.UseCallBack = false
self:AddTransition("*", "ManageEvasion", "*")
self:AddTransition("*", "CalculateHitZone", "*")
self:HandleEvent( EVENTS.Shot, self.HandleEventShot ) self:HandleEvent( EVENTS.Shot, self.HandleEventShot )
-- Start State. -- Start State.
self:SetStartState("Running") self:SetStartState("Running")
self:AddTransition("*", "ManageEvasion", "*")
self:AddTransition("*", "CalculateHitZone", "*")
self:I("*** SEAD - Started Version 0.4.2")
self:I("*** SEAD - Started Version 0.4.1")
return self return self
end end
@ -300,28 +299,32 @@ function SEAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADG
Ropt = Ropt * 0.98 Ropt = Ropt * 0.98
end end
local predpos= pos0:Translate(Ropt,wph) -- look at a couple of zones across the trajectory
if predpos then 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) local targetzone = ZONE_RADIUS:New("Target Zone",predpos:GetVec2(),20000)
if self.debug then if self.debug then
predpos:MarkToAll(string.format("height=%dm | heading=%d | velocity=%d | Ropt=%dm",mheight,wph,mveloc,Ropt),false) 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) targetzone:DrawZone(coalition.side.BLUE,{0,0,1},0.2,nil,nil,3,true)
end end
local seadset = SET_GROUP:New():FilterPrefixes(self.SEADGroupPrefixes):FilterOnce() local seadset = SET_GROUP:New():FilterPrefixes(self.SEADGroupPrefixes):FilterOnce()
local tgtcoord = targetzone:GetRandomPointVec2() local tgtcoord = targetzone:GetRandomPointVec2()
local tgtgrp = seadset:FindNearestGroupFromPointVec2(tgtcoord) local tgtgrp = seadset:FindNearestGroupFromPointVec2(tgtcoord)
local _targetgroup = nil local _targetgroup = nil
local _targetgroupname = "none" local _targetgroupname = "none"
local _targetskill = "Random" local _targetskill = "Random"
if tgtgrp and tgtgrp:IsAlive() then if tgtgrp and tgtgrp:IsAlive() then
_targetgroup = tgtgrp _targetgroup = tgtgrp
_targetgroupname = tgtgrp:GetName() -- group name _targetgroupname = tgtgrp:GetName() -- group name
_targetskill = tgtgrp:GetUnit(1):GetSkill() _targetskill = tgtgrp:GetUnit(1):GetSkill()
self:T("*** Found Target = ".. _targetgroupname) self:T("*** Found Target = ".. _targetgroupname)
self:ManageEvasion(_targetskill,_targetgroup,pos0,"AGM_88",SEADGroup, 20) self:ManageEvasion(_targetskill,_targetgroup,pos0,"AGM_88",SEADGroup, 20)
end
end end
end end
end end
@ -453,8 +456,9 @@ function SEAD:HandleEventShot( EventData )
local _targetskill = "Random" local _targetskill = "Random"
local _targetgroupname = "none" local _targetgroupname = "none"
local _target = EventData.Weapon:getTarget() -- Identify target local _target = EventData.Weapon:getTarget() -- Identify target
if not _target then if not _target or self.debug then -- AGM-88 w/o target data
if string.find(SEADWeaponName,"AGM_88",1,true) then if string.find(SEADWeaponName,"AGM_88",1,true) then
self:I("**** Tracking AGM-88 with no target data.")
local pos0 = SEADPlane:GetCoordinate() local pos0 = SEADPlane:GetCoordinate()
local fheight = SEADPlane:GetHeight() local fheight = SEADPlane:GetHeight()
self:__CalculateHitZone(20,SEADWeapon,pos0,fheight,SEADGroup) self:__CalculateHitZone(20,SEADWeapon,pos0,fheight,SEADGroup)

View File

@ -146,7 +146,7 @@ do
-- @param #boolean UseEmOnOff Use Emissions On/Off rather than Alarm State Red/Green (default: use Emissions switch) -- @param #boolean UseEmOnOff Use Emissions On/Off rather than Alarm State Red/Green (default: use Emissions switch)
-- @retunr #SHORAD self -- @retunr #SHORAD self
function SHORAD:New(Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition, UseEmOnOff) function SHORAD:New(Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition, UseEmOnOff)
local self = BASE:Inherit( self, BASE:New() ) local self = BASE:Inherit( self, FSM:New() )
self:T({Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition}) self:T({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()
@ -164,11 +164,17 @@ do
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 = UseEmOnOff or false -- 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.10") self:I("*** SHORAD - Started Version 0.3.1")
-- 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) self:HandleEvent(EVENTS.Shot, self.HandleEventShot)
-- Start State.
self:SetStartState("Running")
self:AddTransition("*", "WakeUpShorad", "*")
self:AddTransition("*", "CalculateHitZone", "*")
return self return self
end end
@ -402,6 +408,7 @@ do
-- @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:T(self.lid .. " _ShotIsDetected") self:T(self.lid .. " _ShotIsDetected")
if self.debug then return true end
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
@ -425,7 +432,7 @@ do
-- mymantis = MANTIS:New("BlueMantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs") -- mymantis = MANTIS:New("BlueMantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")
-- mymantis:AddShorad(myshorad,720) -- mymantis:AddShorad(myshorad,720)
-- mymantis:Start() -- mymantis:Start()
function SHORAD:WakeUpShorad(TargetGroup, Radius, ActiveTimer, TargetCat) function SHORAD:onafterWakeUpShorad(From, Event, To, TargetGroup, Radius, ActiveTimer, TargetCat)
self:T(self.lid .. " WakeUpShorad") self:T(self.lid .. " WakeUpShorad")
self:T({TargetGroup, Radius, ActiveTimer, TargetCat}) self:T({TargetGroup, Radius, ActiveTimer, TargetCat})
local targetcat = TargetCat or Object.Category.UNIT local targetcat = TargetCat or Object.Category.UNIT
@ -479,6 +486,76 @@ do
return self return self
end end
--- (Internal) Calculate hit zone of an AGM-88
-- @param #SHORAD 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
-- @return #SHORAD self
function SHORAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADGroup)
self:T("**** Calculating hit zone")
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"]
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 = self.Groupset
local tgtcoord = targetzone:GetRandomPointVec2()
local tgtgrp = seadset:FindNearestGroupFromPointVec2(tgtcoord)
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:WakeUpShorad(_targetgroupname, self.Radius, self.ActiveTimer, Object.Category.UNIT)
end
end
end
end
return self
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
@ -507,7 +584,15 @@ do
-- get target data -- get target data
local targetdata = EventData.Weapon:getTarget() -- Identify target local targetdata = EventData.Weapon:getTarget() -- Identify target
-- Is there target data? -- Is there target data?
if not targetdata then return end if not targetdata or self.debug then
if string.find(ShootingWeaponName,"AGM_88",1,true) then
self:I("**** Tracking AGM-88 with no target data.")
local pos0 = EventData.IniUnit:GetCoordinate()
local fheight = EventData.IniUnit:GetHeight()
self:__CalculateHitZone(20,ShootingWeapon,pos0,fheight,EventData.IniGroup)
end
return self
end
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:T(string.format("Target Category (3=STATIC, 1=UNIT)= %s",tostring(targetcat)))
@ -573,6 +658,7 @@ do
end end
end end
end end
return self
end end
-- --
end end