#Changes from Develop

This commit is contained in:
Applevangelist
2022-09-10 11:49:40 +02:00
parent c58e91b956
commit 7c22e9fe69
48 changed files with 7792 additions and 3739 deletions

View File

@@ -18,7 +18,7 @@
-- @module Functional.Shorad
-- @image Functional.Shorad.jpg
--
-- Date: July 2021
-- Date: Nov 2021
-------------------------------------------------------------------------
--- **SHORAD** class, extends Core.Base#BASE
@@ -41,6 +41,7 @@
-- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green.
-- @extends Core.Base#BASE
--- *Good friends are worth defending.* Mr Tushman, Wonder (the Movie)
--
-- Simple Class for a more intelligent Short Range Air Defense System
@@ -131,6 +132,7 @@ do
["Kh29"] = "Kh29",
["Kh31"] = "Kh31",
["Kh66"] = "Kh66",
--["BGM_109"] = "BGM_109",
}
--- Instantiates a new SHORAD object
@@ -138,13 +140,13 @@ do
-- @param #string Name Name of this SHORAD
-- @param #string ShoradPrefix Filter for the Shorad #SET_GROUP
-- @param Core.Set#SET_GROUP Samset The #SET_GROUP of SAM sites to defend
-- @param #number Radius Defense radius in meters, used to switch on groups
-- @param #number Radius Defense radius in meters, used to switch on SHORAD groups **within** this radius
-- @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 #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, FSM:New() )
self:T({Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition})
local GroupSet = SET_GROUP:New():FilterPrefixes(ShoradPrefix):FilterCoalitions(Coalition):FilterCategoryGround():FilterStart()
@@ -162,11 +164,17 @@ do
self.DefenseLowProb = 70 -- probability to detect a missile shot, low 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:I("*** SHORAD - Started Version 0.2.8")
self:I("*** SHORAD - Started Version 0.3.1")
-- Set the string id for output to DCS.log file.
self.lid=string.format("SHORAD %s | ", self.name)
self:_InitState()
self:HandleEvent(EVENTS.Shot, self.HandleEventShot)
-- Start State.
self:SetStartState("Running")
self:AddTransition("*", "WakeUpShorad", "*")
self:AddTransition("*", "CalculateHitZone", "*")
return self
end
@@ -310,7 +318,7 @@ do
local hit = false
if self.DefendHarms then
for _,_name in pairs (SHORAD.Harms) do
if string.find(WeaponName,_name,1) then hit = true end
if string.find(WeaponName,_name,1,true) then hit = true end
end
end
return hit
@@ -326,7 +334,7 @@ do
local hit = false
if self.DefendMavs then
for _,_name in pairs (SHORAD.Mavs) do
if string.find(WeaponName,_name,1) then hit = true end
if string.find(WeaponName,_name,1,true) then hit = true end
end
end
return hit
@@ -367,7 +375,7 @@ do
local returnname = false
for _,_groups in pairs (shoradset) do
local groupname = _groups:GetName()
if string.find(groupname, tgtgrp, 1) then
if string.find(groupname, tgtgrp, 1, true) then
returnname = true
--_groups:RelocateGroundRandomInRadius(7,100,false,false) -- be a bit evasive
end
@@ -388,7 +396,7 @@ do
local returnname = false
for _,_groups in pairs (shoradset) do
local groupname = _groups:GetName()
if string.find(groupname, tgtgrp, 1) then
if string.find(groupname, tgtgrp, 1, true) then
returnname = true
end
end
@@ -400,6 +408,7 @@ do
-- @return #boolean Returns true for a detection, else false
function SHORAD:_ShotIsDetected()
self:T(self.lid .. " _ShotIsDetected")
if self.debug then return true end
local IsDetected = false
local DetectionProb = math.random(self.DefenseLowProb, self.DefenseHighProb) -- reference value
local ActualDetection = math.random(1,100) -- value for this shot
@@ -423,7 +432,7 @@ do
-- 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, TargetCat)
function SHORAD:onafterWakeUpShorad(From, Event, To, TargetGroup, Radius, ActiveTimer, TargetCat)
self:T(self.lid .. " WakeUpShorad")
self:T({TargetGroup, Radius, ActiveTimer, TargetCat})
local targetcat = TargetCat or Object.Category.UNIT
@@ -477,6 +486,76 @@ do
return self
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
-- @param #SHORAD self
-- @param Core.Event#EVENTDATA EventData The event details table data set
@@ -504,13 +583,48 @@ do
if (self:_CheckHarms(ShootingWeaponName) or self:_CheckMavs(ShootingWeaponName)) and IsDetected then
-- get target data
local targetdata = EventData.Weapon:getTarget() -- Identify target
-- Is there target data?
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
self:T(string.format("Target Category (3=STATIC, 1=UNIT)= %s",tostring(targetcat)))
self:T({targetdata})
local targetunit = nil
if targetcat == Object.Category.UNIT then -- UNIT
targetunit = UNIT:Find(targetdata)
elseif targetcat == Object.Category.STATIC then -- STATIC
targetunit = STATIC:Find(targetdata)
--self:T("Static Target Data")
--self:T({targetdata:isExist()})
--self:T({targetdata:getPoint()})
local tgtcoord = COORDINATE:NewFromVec3(targetdata:getPoint())
--tgtcoord:MarkToAll("Missile Target",true)
local tgtgrp1 = self.Samset:FindNearestGroupFromPointVec2(tgtcoord)
local tgtcoord1 = tgtgrp1:GetCoordinate()
--tgtcoord1:MarkToAll("Close target SAM",true)
local tgtgrp2 = self.Groupset:FindNearestGroupFromPointVec2(tgtcoord)
local tgtcoord2 = tgtgrp2:GetCoordinate()
--tgtcoord2:MarkToAll("Close target SHORAD",true)
local dist1 = tgtcoord:Get2DDistance(tgtcoord1)
local dist2 = tgtcoord:Get2DDistance(tgtcoord2)
if dist1 < dist2 then
targetunit = tgtgrp1
targetcat = Object.Category.UNIT
else
targetunit = tgtgrp2
targetcat = Object.Category.UNIT
end
end
--local targetunitname = Unit.getName(targetdata) -- Unit name
if targetunit and targetunit:IsAlive() then
@@ -519,7 +633,11 @@ do
local targetgroup = nil
local targetgroupname = "none"
if targetcat == Object.Category.UNIT then
targetgroup = targetunit:GetGroup()
if targetunit.ClassName == "UNIT" then
targetgroup = targetunit:GetGroup()
elseif targetunit.ClassName == "GROUP" then
targetgroup = targetunit
end
targetgroupname = targetgroup:GetName() -- group name
elseif targetcat == Object.Category.STATIC then
targetgroup = targetunit
@@ -540,6 +658,7 @@ do
end
end
end
return self
end
--
end