Merge branch 'develop' into FF/Ops

This commit is contained in:
Frank
2022-03-25 11:00:17 +01:00
25 changed files with 1744 additions and 693 deletions

View File

@@ -674,25 +674,27 @@ end
function AUTOLASE:CanLase(Recce,Unit)
local canlase = false
-- cooldown?
local name = Recce:GetName()
local cooldown = self.RecceUnits[name].cooldown and self.forcecooldown
if cooldown then
local Tdiff = timer.getAbsTime() - self.RecceUnits[name].timestamp
if Tdiff < self.cooldowntime then
return false
else
self.RecceUnits[name].cooldown = false
if Recce and Recce:IsAlive() == true then
local name = Recce:GetName()
local cooldown = self.RecceUnits[name].cooldown and self.forcecooldown
if cooldown then
local Tdiff = timer.getAbsTime() - self.RecceUnits[name].timestamp
if Tdiff < self.cooldowntime then
return false
else
self.RecceUnits[name].cooldown = false
end
end
-- calculate LOS
local reccecoord = Recce:GetCoordinate()
local unitcoord = Unit:GetCoordinate()
local islos = reccecoord:IsLOS(unitcoord,2.5)
-- calculate distance
local distance = math.floor(reccecoord:Get3DDistance(unitcoord))
local lasedistance = self:GetLosFromUnit(Recce)
if distance <= lasedistance and islos then
canlase = true
end
end
-- calculate LOS
local reccecoord = Recce:GetCoordinate()
local unitcoord = Unit:GetCoordinate()
local islos = reccecoord:IsLOS(unitcoord,2.5)
-- calculate distance
local distance = math.floor(reccecoord:Get3DDistance(unitcoord))
local lasedistance = self:GetLosFromUnit(Recce)
if distance <= lasedistance and islos then
canlase = true
end
return canlase
end

View File

@@ -98,6 +98,7 @@
-- * Patriot
-- * Rapier
-- * Roland
-- * Silkworm (though strictly speaking this is a surface to ship missile)
-- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19
-- * and from HDS (see note below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2
--
@@ -356,6 +357,7 @@ MANTIS.SamData = {
["Avenger"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Avenger" },
["Chaparrel"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Linebacker" },
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
-- units from HDS Mod, multi launcher options is tricky
["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B"},
["SA-17"] = { Range=50, Blindspot=3, Height=30, Type="Medium", Radar="SA-17" },

View File

@@ -1704,7 +1704,7 @@ function SCORING:ReportScoreGroupDetailed( PlayerGroup )
self:F( { ReportMissions, ScoreMissions, PenaltyMissions } )
local PlayerScore = ScoreHits + ScoreDestroys + ScoreCoalitionChanges + ScoreGoals + ScoreMissions
local PlayerPenalty = PenaltyHits + PenaltyDestroys + PenaltyCoalitionChanges + ScoreGoals + PenaltyMissions
local PlayerPenalty = PenaltyHits + PenaltyDestroys + PenaltyCoalitionChanges + PenaltyGoals + PenaltyMissions
PlayerMessage =
string.format( "Player '%s' Score = %d ( %d Score, -%d Penalties )%s%s%s%s%s",
@@ -1760,7 +1760,7 @@ function SCORING:ReportScoreAllSummary( PlayerGroup )
self:F( { ReportMissions, ScoreMissions, PenaltyMissions } )
local PlayerScore = ScoreHits + ScoreDestroys + ScoreCoalitionChanges + ScoreGoals + ScoreMissions
local PlayerPenalty = PenaltyHits + PenaltyDestroys + PenaltyCoalitionChanges + ScoreGoals + PenaltyMissions
local PlayerPenalty = PenaltyHits + PenaltyDestroys + PenaltyCoalitionChanges + PenaltyGoals + PenaltyMissions
PlayerMessage =
string.format( "Player '%s' Score = %d ( %d Score, -%d Penalties )",

View File

@@ -19,7 +19,7 @@
--
-- ### Authors: **FlightControl**, **applevangelist**
--
-- Last Update: Nov 2021
-- Last Update: Feb 2022
--
-- ===
--
@@ -33,7 +33,7 @@
--- 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, SEADwill shut down the radars of the attacked SAM site and take evasive action by moving the SAM
-- 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.
@@ -79,6 +79,7 @@ SEAD = {
["Kh25"] = "Kh25",
["BGM_109"] = "BGM_109",
["AGM_154"] = "AGM_154",
["HY-2"] = "HY-2",
}
--- Missile enumerators - from DCS ME and Wikipedia
@@ -98,6 +99,7 @@ SEAD = {
["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.
@@ -141,7 +143,7 @@ function SEAD:New( SEADGroupPrefixes, Padding )
self:AddTransition("*", "ManageEvasion", "*")
self:AddTransition("*", "CalculateHitZone", "*")
self:I("*** SEAD - Started Version 0.4.2")
self:I("*** SEAD - Started Version 0.4.3")
return self
end
@@ -267,9 +269,10 @@ end
-- @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)
self:T("**** Calculating hit zone")
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()
@@ -285,6 +288,9 @@ function SEAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADG
-- 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
@@ -459,14 +465,15 @@ function SEAD:HandleEventShot( EventData )
local _targetskill = "Random"
local _targetgroupname = "none"
local _target = EventData.Weapon:getTarget() -- Identify target
if not _target or self.debug then -- AGM-88 w/o target data
if string.find(SEADWeaponName,"AGM_88",1,true) then
self:I("**** Tracking AGM-88 with no target data.")
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)
return self
self:__CalculateHitZone(20,SEADWeapon,pos0,fheight,SEADGroup,SEADWeaponName)
end
return self
end
local targetcat = _target:getCategory() -- Identify category
local _targetUnit = nil -- Wrapper.Unit#UNIT

View File

@@ -4039,7 +4039,7 @@ function WAREHOUSE:onafterAddAsset(From, Event, To, group, ngroups, forceattribu
self:_DebugMessage(string.format("Removing group %s", group:GetName()), 5)
local opsgroup=_DATABASE:GetOpsGroup(group:GetName())
if opsgroup then
if opsgroup then
opsgroup:Despawn(0, true)
opsgroup:__Stop(-0.01)
else
@@ -4107,6 +4107,7 @@ function WAREHOUSE:_RegisterAsset(group, ngroups, forceattribute, forcecargobay,
local cargobay={}
local cargobaytot=0
local cargobaymax=0
local weights={}
for _i,_unit in pairs(group:GetUnits()) do
local unit=_unit --Wrapper.Unit#UNIT
local Desc=unit:GetDesc()
@@ -4115,8 +4116,9 @@ function WAREHOUSE:_RegisterAsset(group, ngroups, forceattribute, forcecargobay,
local unitweight=forceweight or Desc.massEmpty
if unitweight then
weight=weight+unitweight
weights[_i]=unitweight
end
local cargomax=0
local massfuel=Desc.fuelMassMax or 0
local massempty=Desc.massEmpty or 0
@@ -4165,6 +4167,7 @@ function WAREHOUSE:_RegisterAsset(group, ngroups, forceattribute, forcecargobay,
asset.speedmax=SpeedMax
asset.size=smax
asset.weight=weight
asset.weights=weights
asset.DCSdesc=Descriptors
asset.attribute=attribute
asset.cargobay=cargobay
@@ -5449,9 +5452,59 @@ end
-- @param #WAREHOUSE.Assetitem asset The asset that is dead.
-- @param #WAREHOUSE.Pendingitem request The request of the dead asset.
function WAREHOUSE:onafterAssetDead(From, Event, To, asset, request)
-- Debug message.
local text=string.format("Asset %s from request id=%d is dead!", asset.templatename, request.uid)
self:T(self.lid..text)
self:_DebugMessage(text)
-- Here I need to get rid of the #CARGO at the end to obtain the original name again!
local groupname=asset.spawngroupname --self:_GetNameWithOut(group)
-- Dont trigger a Remove event for the group sets.
local NoTriggerEvent=true
if request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
---
-- Easy case: Group can simply be removed from the cargogroupset.
---
-- Remove dead group from cargo group set.
request.cargogroupset:Remove(groupname, NoTriggerEvent)
self:T(self.lid..string.format("Removed selfpropelled cargo %s: ncargo=%d.", groupname, request.cargogroupset:Count()))
else
---
-- Complicated case: Dead unit could be:
-- 1.) A Cargo unit (e.g. waiting to be picked up).
-- 2.) A Transport unit which itself holds cargo groups.
---
-- Check if this a cargo or transport group.
local istransport=not asset.iscargo --self:_GroupIsTransport(group, request)
if istransport==true then
-- Whole carrier group is dead. Remove it from the carrier group set.
request.transportgroupset:Remove(groupname, NoTriggerEvent)
self:T(self.lid..string.format("Removed transport %s: ntransport=%d", groupname, request.transportgroupset:Count()))
elseif istransport==false then
-- This must have been an alive cargo group that was killed outside the carrier, e.g. waiting to be transported or waiting to be put back.
-- Remove dead group from cargo group set.
request.cargogroupset:Remove(groupname, NoTriggerEvent)
self:T(self.lid..string.format("Removed transported cargo %s outside carrier: ncargo=%d", groupname, request.cargogroupset:Count()))
-- This as well?
--request.transportcargoset:RemoveCargosByName(RemoveCargoNames)
else
--self:E(self.lid..string.format("ERROR: Group %s is neither cargo nor transport!", group:GetName()))
end
end
end
@@ -6556,7 +6609,8 @@ function WAREHOUSE:_OnEventCrashOrDead(EventData)
end
end
--self:I(self.lid..string.format("Warehouse %s captured event dead or crash or unit %s.", self.alias, tostring(EventData.IniUnitName)))
-- Debug info.
self:T2(self.lid..string.format("Warehouse %s captured event dead or crash or unit %s", self.alias, tostring(EventData.IniUnitName)))
-- Check if an asset unit was destroyed.
if EventData.IniGroup then
@@ -6571,7 +6625,7 @@ function WAREHOUSE:_OnEventCrashOrDead(EventData)
if wid==self.uid then
-- Debug message.
self:T(self.lid..string.format("Warehouse %s captured event dead or crash of its asset unit %s.", self.alias, EventData.IniUnitName))
self:T(self.lid..string.format("Warehouse %s captured event dead or crash of its asset unit %s", self.alias, EventData.IniUnitName))
-- Loop over all pending requests and get the one belonging to this unit.
for _,request in pairs(self.pending) do
@@ -6581,7 +6635,7 @@ function WAREHOUSE:_OnEventCrashOrDead(EventData)
if request.uid==rid then
-- Update cargo and transport group sets of this request. We need to know if this job is finished.
self:_UnitDead(EventData.IniUnit, request)
self:_UnitDead(EventData.IniUnit, EventData.IniGroup, request)
end
end
@@ -6594,38 +6648,46 @@ end
-- This is important in order to determine if a job is done and can be removed from the (pending) queue.
-- @param #WAREHOUSE self
-- @param Wrapper.Unit#UNIT deadunit Unit that died.
-- @param Wrapper.Group#GROUP deadgroup Group of unit that died.
-- @param #WAREHOUSE.Pendingitem request Request that needs to be updated.
function WAREHOUSE:_UnitDead(deadunit, request)
function WAREHOUSE:_UnitDead(deadunit, deadgroup, request)
self:F(self.lid.."FF unit dead "..deadunit:GetName())
-- Flare unit.
if self.Debug then
deadunit:FlareRed()
-- Find opsgroup.
local opsgroup=_DATABASE:FindOpsGroup(deadgroup)
-- Check if we have an opsgroup.
if opsgroup then
-- Handled in OPSGROUP:onafterDead() now.
return nil
end
-- Group the dead unit belongs to.
local group=deadunit:GetGroup()
-- Number of alive units in group.
local nalive=group:CountAliveUnits()
local nalive=deadgroup:CountAliveUnits()
-- Whole group is dead?
local groupdead=true
local groupdead=false
if nalive>0 then
groupdead=false
else
groupdead=true
end
-- Find asset.
local asset=self:FindAssetInDB(deadgroup)
-- Here I need to get rid of the #CARGO at the end to obtain the original name again!
local unitname=self:_GetNameWithOut(deadunit)
local groupname=self:_GetNameWithOut(group)
local groupname=self:_GetNameWithOut(deadgroup)
-- Group is dead!
if groupdead then
self:T(self.lid..string.format("Group %s (transport=%s) is dead!", groupname, tostring(self:_GroupIsTransport(group,request))))
-- Debug output.
self:T(self.lid..string.format("Group %s (transport=%s) is dead!", groupname, tostring(self:_GroupIsTransport(deadgroup,request))))
if self.Debug then
group:SmokeWhite()
deadgroup:SmokeWhite()
end
-- Trigger AssetDead event.
local asset=self:FindAssetInDB(group)
-- Trigger AssetDead event.
self:AssetDead(asset, request)
end
@@ -6633,19 +6695,7 @@ function WAREHOUSE:_UnitDead(deadunit, request)
-- Dont trigger a Remove event for the group sets.
local NoTriggerEvent=true
if request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
---
-- Easy case: Group can simply be removed from the cargogroupset.
---
-- Remove dead group from cargo group set.
if groupdead==true then
request.cargogroupset:Remove(groupname, NoTriggerEvent)
self:T(self.lid..string.format("Removed selfpropelled cargo %s: ncargo=%d.", groupname, request.cargogroupset:Count()))
end
else
if not request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
---
-- Complicated case: Dead unit could be:
@@ -6653,10 +6703,7 @@ function WAREHOUSE:_UnitDead(deadunit, request)
-- 2.) A Transport unit which itself holds cargo groups.
---
-- Check if this a cargo or transport group.
local istransport=self:_GroupIsTransport(group,request)
if istransport==true then
if not asset.iscargo then
-- Get the carrier unit table holding the cargo groups inside this carrier.
local cargogroupnames=request.carriercargo[unitname]
@@ -6671,25 +6718,8 @@ function WAREHOUSE:_UnitDead(deadunit, request)
end
-- Whole carrier group is dead. Remove it from the carrier group set.
if groupdead then
request.transportgroupset:Remove(groupname, NoTriggerEvent)
self:T(self.lid..string.format("Removed transport %s: ntransport=%d", groupname, request.transportgroupset:Count()))
end
elseif istransport==false then
-- This must have been an alive cargo group that was killed outside the carrier, e.g. waiting to be transported or waiting to be put back.
-- Remove dead group from cargo group set.
if groupdead==true then
request.cargogroupset:Remove(groupname, NoTriggerEvent)
self:T(self.lid..string.format("Removed transported cargo %s outside carrier: ncargo=%d", groupname, request.cargogroupset:Count()))
-- This as well?
--request.transportcargoset:RemoveCargosByName(RemoveCargoNames)
end
else
self:E(self.lid..string.format("ERROR: Group %s is neither cargo nor transport!", group:GetName()))
self:E(self.lid..string.format("ERROR: Group %s is neither cargo nor transport!", deadgroup:GetName()))
end
end
@@ -8065,57 +8095,12 @@ end
-- @return #number Request ID.
function WAREHOUSE:_GetIDsFromGroup(group)
---@param #string text The text to analyse.
local function analyse(text)
-- Get rid of #0001 tail from spawn.
local unspawned=UTILS.Split(text, "#")[1]
-- Split keywords.
local keywords=UTILS.Split(unspawned, "_")
local _wid=nil -- warehouse UID
local _aid=nil -- asset UID
local _rid=nil -- request UID
-- Loop over keys.
for _,keys in pairs(keywords) do
local str=UTILS.Split(keys, "-")
local key=str[1]
local val=str[2]
if key:find("WID") then
_wid=tonumber(val)
elseif key:find("AID") then
_aid=tonumber(val)
elseif key:find("RID") then
_rid=tonumber(val)
end
end
return _wid,_aid,_rid
end
if group then
-- Group name
local name=group:GetName()
-- Get asset id from group name.
local wid,aid,rid=analyse(name)
-- Get Asset.
local asset=self:GetAssetByID(aid)
-- Get warehouse and request id from asset table.
if asset then
wid=asset.wid
rid=asset.rid
end
-- Debug info
self:T3(self.lid..string.format("Group Name = %s", tostring(name)))
self:T3(self.lid..string.format("Warehouse ID = %s", tostring(wid)))
self:T3(self.lid..string.format("Asset ID = %s", tostring(aid)))
self:T3(self.lid..string.format("Request ID = %s", tostring(rid)))
local groupname=group:GetName()
local wid, aid, rid=self:_GetIDsFromGroupName(groupname)
return wid,aid,rid
else
@@ -8124,14 +8109,13 @@ function WAREHOUSE:_GetIDsFromGroup(group)
end
--- Get warehouse id, asset id and request id from group name (alias).
-- @param #WAREHOUSE self
-- @param Wrapper.Group#GROUP group The group from which the info is gathered.
-- @param #string groupname Name of the group from which the info is gathered.
-- @return #number Warehouse ID.
-- @return #number Asset ID.
-- @return #number Request ID.
function WAREHOUSE:_GetIDsFromGroupOLD(group)
function WAREHOUSE:_GetIDsFromGroupName(groupname)
---@param #string text The text to analyse.
local function analyse(text)
@@ -8162,25 +8146,26 @@ function WAREHOUSE:_GetIDsFromGroupOLD(group)
return _wid,_aid,_rid
end
if group then
-- Group name
local name=group:GetName()
-- Get asset id from group name.
local wid,aid,rid=analyse(groupname)
-- Get ids
local wid,aid,rid=analyse(name)
-- Get Asset.
local asset=self:GetAssetByID(aid)
-- Debug info
self:T3(self.lid..string.format("Group Name = %s", tostring(name)))
self:T3(self.lid..string.format("Warehouse ID = %s", tostring(wid)))
self:T3(self.lid..string.format("Asset ID = %s", tostring(aid)))
self:T3(self.lid..string.format("Request ID = %s", tostring(rid)))
return wid,aid,rid
else
self:E("WARNING: Group not found in GetIDsFromGroup() function!")
-- Get warehouse and request id from asset table.
if asset then
wid=asset.wid
rid=asset.rid
end
-- Debug info
self:T3(self.lid..string.format("Group Name = %s", tostring(groupname)))
self:T3(self.lid..string.format("Warehouse ID = %s", tostring(wid)))
self:T3(self.lid..string.format("Asset ID = %s", tostring(aid)))
self:T3(self.lid..string.format("Request ID = %s", tostring(rid)))
return wid,aid,rid
end
--- Filter stock assets by descriptor and attribute.