Capture Zone
This commit is contained in:
Frank 2022-12-30 02:44:16 +01:00
parent 30e6542887
commit 3011d625b2
6 changed files with 436 additions and 36 deletions

View File

@ -1919,6 +1919,41 @@ do -- SET_GROUP
end
end
--- Get the closest group of the set with respect to a given reference coordinate. Optionally, only groups of given coalitions are considered in the search.
-- @param #SET_GROUP self
-- @param Core.Point#COORDINATE Coordinate Reference Coordinate from which the closest group is determined.
-- @return Wrapper.Group#GROUP The closest group (if any).
-- @return #number Distance in meters to the closest group.
function SET_GROUP:GetClosestGroup(Coordinate, Coalitions)
local Set = self:GetSet()
local dmin=math.huge
local gmin=nil
for GroupID, GroupData in pairs( Set ) do -- For each GROUP in SET_GROUP
local group=GroupData --Wrapper.Group#GROUP
if Coalitions==nil or UTILS.IsAnyInTable(Coalitions, group:GetCoalition()) then
local coord=group:GetCoord()
-- Distance between ref. coordinate and group coordinate.
local d=UTILS.VecDist3D(Coordinate, coord)
if d<dmin then
dmin=d
gmin=group
end
end
end
return gmin, dmin
end
end
do -- SET_UNIT

View File

@ -720,6 +720,32 @@ function ARMYGROUP:Status()
end
end
end
-- Get current mission (if any).
local mission=self:GetMissionCurrent()
-- If mission, check if DCS task needs to be updated.
if mission and mission.updateDCSTask and mission:GetGroupStatus(self)==AUFTRAG.GroupStatus.EXECUTING then
if mission.type==AUFTRAG.Type.CAPTUREZONE then
-- Get task.
local Task=self:GetTaskByID(mission.auftragsnummer)
local opszone=Task.target --Ops.OpsZone#OPSZONE
env.info(string.format("FF Opszone %s owner=%s, engaging=%s", opszone:GetName(), opszone:GetOwnerName(), tostring(self:IsEngaging())))
-- Update task: Engage or get new zone.
self:_UpdateTask(Task, mission)
end
end
else
-- Check damage of elements and group.
@ -1721,10 +1747,11 @@ function ARMYGROUP:onbeforeEngageTarget(From, Event, To, Target, Speed, Formatio
return false
end
-- Pause current mission.
-- Get current mission.
local mission=self:GetMissionCurrent()
if mission and mission.type~=AUFTRAG.Type.GROUNDATTACK then
-- Pause current mission unless it uses the EngageTarget command.
if mission and mission.type~=AUFTRAG.Type.GROUNDATTACK and mission.type~=AUFTRAG.Type.CAPTUREZONE then
self:T(self.lid.."Engage command but have current mission ==> Pausing mission!")
self:PauseMission()
dt=-0.1
@ -1804,8 +1831,8 @@ function ARMYGROUP:_UpdateEngageTarget()
-- Distance to last known position of target.
local dist=UTILS.VecDist3D(vec3, self.engage.Coordinate:GetVec3())
-- Check if target moved more than 100 meters.
if dist>100 then
-- Check if target moved more than 100 meters or we do not have line of sight.
if dist>100 or not self:HasLoS(self.engage.Target:GetCoordinate()) then
--env.info("FF Update Engage Target Moved "..self.engage.Target:GetName())
@ -1824,7 +1851,7 @@ function ARMYGROUP:_UpdateEngageTarget()
self.engage.Waypoint=self:AddWaypoint(intercoord, self.engage.Speed, uid, self.engage.Formation, true)
-- Set if we want to resume route after reaching the detour waypoint.
self.engage.Waypoint.detour=0
self.engage.Waypoint.detour=0
end

View File

@ -422,7 +422,8 @@ _AUFTRAGSNR=0
-- @field #string AIRDEFENSE Air defense.
-- @field #string EWR Early Warning Radar.
-- @field #string RECOVERYTANKER Recovery tanker.
-- @filed #string REARMING Rearming mission.
-- @field #string REARMING Rearming mission.
-- @field #string CAPTUREZONE Capture zone mission.
-- @field #string NOTHING Nothing.
AUFTRAG.Type={
ANTISHIP="Anti Ship",
@ -465,6 +466,7 @@ AUFTRAG.Type={
EWR="Early Warning Radar",
RECOVERYTANKER="Recovery Tanker",
REARMING="Rearming",
CAPTUREZONE="Capture Zone",
NOTHING="Nothing",
}
@ -487,6 +489,7 @@ AUFTRAG.Type={
-- @field #string EWR Early Warning Radar.
-- @field #string RECOVERYTANKER Recovery tanker.
-- @field #string REARMING Rearming.
-- @field #string CAPTUREZONE Capture OPS zone.
-- @field #string NOTHING Nothing.
AUFTRAG.SpecialTask={
FORMATION="Formation",
@ -507,6 +510,7 @@ AUFTRAG.SpecialTask={
EWR="Early Warning Radar",
RECOVERYTANKER="Recovery Tanker",
REARMING="Rearming",
CAPTUREZONE="Capture Zone",
NOTHING="Nothing",
}
@ -1964,6 +1968,51 @@ function AUFTRAG:NewPATROLZONE(Zone, Speed, Altitude, Formation)
return mission
end
--- **[AIR, GROUND, NAVAL]** Create a CAPTUREZONE mission. Group(s) will go to the zone and patrol it randomly.
-- @param #AUFTRAG self
-- @param Ops.OpsZone#OPSZONE OpsZone The OPS zone to capture.
-- @param #number Coalition The coalition which should capture the zone for the mission to be successful.
-- @param #number Speed Speed in knots.
-- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL.
-- @param #string Formation Formation used by ground units during patrol. Default "Off Road".
-- @return #AUFTRAG self
function AUFTRAG:NewCAPTUREZONE(OpsZone, Coalition, Speed, Altitude, Formation)
local mission=AUFTRAG:New(AUFTRAG.Type.CAPTUREZONE)
mission:_TargetFromObject(OpsZone)
mission.coalition=Coalition
mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.CAPTUREZONE)
mission.optionROE=ENUMS.ROE.OpenFire
mission.optionROT=ENUMS.ROT.PassiveDefense
mission.optionAlarm=ENUMS.AlarmState.Auto
mission.missionFraction=1.0
mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or nil
mission.missionAltitude=Altitude and UTILS.FeetToMeters(Altitude) or nil
mission.categories={AUFTRAG.Category.ALL}
mission.DCStask=mission:GetDCSMissionTask()
mission.updateDCSTask=true
local params={}
params.formation=Formation or "Off Road"
params.zone=mission:GetObjective()
params.altitude=mission.missionAltitude
params.speed=mission.missionSpeed
mission.DCStask.params=params
return mission
end
--- **[OBSOLETE]** Create a ARMORATTACK mission.
-- ** Note that this is actually creating a GROUNDATTACK mission!**
@ -4947,8 +4996,11 @@ function AUFTRAG:CountMissionTargets()
local N=0
-- Count specific coalitions.
local Coalitions=self.coalition and UTILS.GetCoalitionEnemy(self.coalition, true) or nil
if self.engageTarget then
N=self.engageTarget:CountTargets()
N=self.engageTarget:CountTargets(Coalitions)
end
return N
@ -5013,9 +5065,13 @@ end
--- Get mission objective object. Could be many things depending on the mission type.
-- @param #AUFTRAG self
-- @param Core.Point#COORDINATE RefCoordinate (Optional) Reference coordinate from which the closest target is determined.
-- @param #table Coalitions (Optional) Only consider targets of the given coalition(s).
-- @return Wrapper.Positionable#POSITIONABLE The target object. Could be many things.
function AUFTRAG:GetObjective()
local objective=self:GetTargetData():GetObject()
function AUFTRAG:GetObjective(RefCoordinate, Coalitions)
local objective=self:GetTargetData():GetObject(RefCoordinate, Coalitions)
return objective
end
@ -5753,6 +5809,22 @@ function AUFTRAG:GetDCSMissionTask()
DCStask.params=param
table.insert(DCStasks, DCStask)
elseif self.type==AUFTRAG.Type.CAPTUREZONE then
--------------------------
-- CAPTURE ZONE Mission --
--------------------------
local DCStask={}
DCStask.id=AUFTRAG.SpecialTask.CAPTUREZONE
-- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP.
local param={}
DCStask.params=param
table.insert(DCStasks, DCStask)
elseif self.type==AUFTRAG.Type.CASENHANCED then

View File

@ -335,6 +335,7 @@ OPSGROUP.TaskType={
-- @field #number waypoint Waypoint index if task is a waypoint task.
-- @field Core.UserFlag#USERFLAG stopflag If flag is set to 1 (=true), the task is stopped.
-- @field #number backupROE Rules of engagement that are restored once the task is over.
-- @field Ops.Target#TARGET target Target object.
--- Option data.
-- @type OPSGROUP.Option
@ -4091,12 +4092,13 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
end
--- Push task.
--- Update (DCS) task.
-- @param #OPSGROUP self
-- @param Ops.OpsGroup#OPSGROUP.Task Task The task.
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
function OPSGROUP:_UpdateTask(Task, Mission)
local Mission=Mission or self:GetMissionByTaskID(self.taskcurrent)
Mission=Mission or self:GetMissionByTaskID(self.taskcurrent)
if Task.dcstask.id==AUFTRAG.SpecialTask.FORMATION then
@ -4378,6 +4380,64 @@ function OPSGROUP:_UpdateTask(Task, Mission)
end
wp.missionUID=Mission and Mission.auftragsnummer or nil
elseif Task.dcstask.id==AUFTRAG.SpecialTask.CAPTUREZONE then
---
-- Task "CaptureZone" Mission.
---
env.info("FF Update Task Capture zone")
-- Find the closest enemy group and engage!
-- Not enganging already.
if self:IsEngaging() then
self:T(self.lid..string.format("Engaging currently!"))
else
local Coalitions=UTILS.GetCoalitionEnemy(self:GetCoalition(), false)
local zoneCurr=Task.target --Ops.OpsZone#OPSZONE
if zoneCurr then
self:T(self.lid..string.format("Current target zone=%s", zoneCurr:GetName()))
if zoneCurr:GetOwner()==self:GetCoalition() then
-- Current zone captured ==> Find next zone or call it a day!
self:T(self.lid..string.format("Zone %s captured ==> Task DONE!", zoneCurr:GetName()))
self:TaskDone(Task)
else
-- Current zone NOT captured yet ==> Find Target
if Mission:GetGroupStatus(self)==AUFTRAG.GroupStatus.EXECUTING then
-- Get closest target.
local targetgroup=zoneCurr:GetScannedGroupSet():GetClosestGroup(self.coordinate, Coalitions)
if targetgroup then
self:EngageTarget(targetgroup)
else
-- Error Message.
self:E(self.lid..string.format("ERROR: Current zone not captured but no target group could be found. This should NOT happen!"))
end
end
end
else
self:T(self.lid..string.format("NO Current target zone=%s"))
end
end
else
@ -4662,9 +4722,18 @@ function OPSGROUP:onafterTaskDone(From, Event, To, Task)
-- Check if mission is paused.
if status~=AUFTRAG.GroupStatus.PAUSED then
---
-- Mission is NOT over ==> trigger done
-- Mission is NOT over ==> trigger DONE
---
if Mission.type==AUFTRAG.Type.CAPTUREZONE and Mission:CountMissionTargets()>0 then
env.info("FF task done route to mission 1000")
self:RouteToMission(Mission)
return
end
-- Get egress waypoint uid.
local EgressUID=Mission:GetGroupEgressWaypointUID(self)
@ -5496,6 +5565,13 @@ function OPSGROUP:RouteToMission(mission, delay)
surfacetypes={land.SurfaceType.WATER, land.SurfaceType.SHALLOW_WATER}
end
-- Get target object.
local targetobject=mission:GetObjective(currentcoord, UTILS.GetCoalitionEnemy(self:GetCoalition(), true))
if targetobject then
self:T(self.lid..string.format("Route to mission target object %s", targetobject:GetName()))
end
-- Get ingress waypoint.
if mission.opstransport and not mission.opstransport:IsCargoDelivered(self.groupname) then
@ -5526,7 +5602,7 @@ function OPSGROUP:RouteToMission(mission, delay)
---
-- Get the zone.
targetzone=mission.engageTarget:GetObject() --Core.Zone#ZONE
targetzone=targetobject --Core.Zone#ZONE
-- Random coordinate.
waypointcoord=targetzone:GetRandomCoordinate(nil , nil, surfacetypes)
@ -5545,7 +5621,7 @@ function OPSGROUP:RouteToMission(mission, delay)
---
-- Get the zone.
targetzone=mission.engageTarget:GetObject() --Core.Zone#ZONE
targetzone=targetobject --Core.Zone#ZONE
-- Random coordinate.
waypointcoord=targetzone:GetRandomCoordinate(nil , nil, surfacetypes)
@ -5555,7 +5631,8 @@ function OPSGROUP:RouteToMission(mission, delay)
-- Hover
---
local zone=mission.engageTarget:GetObject() --Core.Zone#ZONE
local zone=targetobject --Core.Zone#ZONE
waypointcoord=zone:GetCoordinate()
elseif mission.type==AUFTRAG.Type.RELOCATECOHORT then
@ -5580,6 +5657,15 @@ function OPSGROUP:RouteToMission(mission, delay)
-- Navy group: Route into direction of the target.
waypointcoord=currentcoord:GetIntermediateCoordinate(ToCoordinate, 0.05)
end
elseif mission.type==AUFTRAG.Type.CAPTUREZONE then
-- Get the zone.
targetzone=targetobject:GetZone()
-- Random coordinate.
waypointcoord=targetzone:GetRandomCoordinate(nil , nil, surfacetypes)
else
---
@ -5706,6 +5792,8 @@ function OPSGROUP:RouteToMission(mission, delay)
-- Add waypoint task. UpdateRoute is called inside.
local waypointtask=self:AddTaskWaypoint(mission.DCStask, waypoint, mission.name, mission.prio, mission.duration)
waypointtask.ismission=true
waypointtask.target=targetobject
-- Set waypoint task.
mission:SetGroupWaypointTask(self, waypointtask)
@ -5766,7 +5854,7 @@ function OPSGROUP:RouteToMission(mission, delay)
---
-- Mission Specific Settings
---
self:_SetMissionOptions(mission)
self:_SetMissionOptions(mission)
end
end

View File

@ -84,6 +84,7 @@ TARGET = {
-- @field #string COORDINATE Target is a COORDINATE.
-- @field #string AIRBASE Target is an AIRBASE.
-- @field #string ZONE Target is a ZONE object.
-- @field #string OPSZONE Target is an OPSZONE object.
TARGET.ObjectType={
GROUP="Group",
UNIT="Unit",
@ -92,6 +93,7 @@ TARGET.ObjectType={
COORDINATE="Coordinate",
AIRBASE="Airbase",
ZONE="Zone",
OPSZONE="OpsZone"
}
@ -312,12 +314,18 @@ end
-- * SET_SCENERY
-- * SET_OPSGROUP
-- * SET_ZONE
-- * SET_OPSZONE
--
-- @param #TARGET self
-- @param Wrapper.Positionable#POSITIONABLE Object The target UNIT, GROUP, STATIC, SCENERY, AIRBASE, COORDINATE, ZONE, SET_GROUP, SET_UNIT, SET_STATIC, SET_SCENERY, SET_ZONE
function TARGET:AddObject(Object)
if Object:IsInstanceOf("SET_GROUP") or Object:IsInstanceOf("SET_UNIT") or Object:IsInstanceOf("SET_STATIC") or Object:IsInstanceOf("SET_SCENERY") or Object:IsInstanceOf("SET_OPSGROUP") then
if Object:IsInstanceOf("SET_GROUP") or
Object:IsInstanceOf("SET_UNIT") or
Object:IsInstanceOf("SET_STATIC") or
Object:IsInstanceOf("SET_SCENERY") or
Object:IsInstanceOf("SET_OPSGROUP") or
Object:IsInstanceOf("SET_OPSZONE") then
---
-- Sets
@ -981,6 +989,22 @@ function TARGET:_AddObject(Object)
target.Life0=1
target.Life=1
elseif Object:IsInstanceOf("OPSZONE") then
local zone=Object --Ops.OpsZone#OPSZONE
Object=zone
target.Type=TARGET.ObjectType.OPSZONE
target.Name=zone:GetName()
target.Coordinate=zone:GetCoordinate()
target.N0=target.N0+1
target.Life0=1
target.Life=1
else
self:E(self.lid.."ERROR: Unknown object type!")
@ -1097,7 +1121,7 @@ function TARGET:GetTargetLife(Target)
return 1
elseif Target.Type==TARGET.ObjectType.ZONE then
elseif Target.Type==TARGET.ObjectType.ZONE or Target.Type==TARGET.ObjectType.OPSZONE then
return 1
@ -1305,6 +1329,13 @@ function TARGET:GetTargetVec3(Target, Average)
local vec3=object:GetVec3()
return vec3
elseif Target.Type==TARGET.ObjectType.OPSZONE then
local object=Target.Object --Ops.OpsZone#OPSZONE
local vec3=object:GetZone():GetVec3()
return vec3
end
@ -1382,7 +1413,7 @@ function TARGET:GetTargetHeading(Target)
-- A coordinate has no heading. Return 0.
return 0
elseif Target.Type==TARGET.ObjectType.ZONE then
elseif Target.Type==TARGET.ObjectType.ZONE or Target.Type==TARGET.ObjectType.OPSZONE then
local object=Target.Object --Core.Zone#ZONE
@ -1660,6 +1691,10 @@ function TARGET:GetTargetCategory(Target)
elseif Target.Type==TARGET.ObjectType.ZONE then
return TARGET.Category.ZONE
elseif Target.Type==TARGET.ObjectType.OPSZONE then
return TARGET.Category.OPSZONE
else
self:E("ERROR: unknown target category!")
@ -1669,6 +1704,71 @@ function TARGET:GetTargetCategory(Target)
end
--- Get coalition of target object. If an object has no coalition (*e.g.* a coordinate) it is returned as neutral.
-- @param #TARGET self
-- @param #TARGET.Object Target Target object.
-- @return #number Coalition number.
function TARGET:GetTargetCoalition(Target)
-- We take neutral for objects that do not have a coalition.
local coal=coalition.side.NEUTRAL
if Target.Type==TARGET.ObjectType.GROUP then
if Target.Object and Target.Object:IsAlive()~=nil then
local object=Target.Object --Wrapper.Group#GROUP
coal=object:GetCoalition()
end
elseif Target.Type==TARGET.ObjectType.UNIT then
if Target.Object and Target.Object:IsAlive()~=nil then
local object=Target.Object --Wrapper.Unit#UNIT
coal=object:GetCoalition()
end
elseif Target.Type==TARGET.ObjectType.STATIC then
local object=Target.Object --Wrapper.Static#STATIC
coal=object:GetCoalition()
elseif Target.Type==TARGET.ObjectType.SCENERY then
-- Scenery has no coalition.
elseif Target.Type==TARGET.ObjectType.AIRBASE then
local object=Target.Object --Wrapper.Airbase#AIRBASE
coal=object:GetCoalition()
elseif Target.Type==TARGET.ObjectType.COORDINATE then
-- Coordinate has no coalition.
elseif Target.Type==TARGET.ObjectType.ZONE then
-- Zone has no coalition.
elseif Target.Type==TARGET.ObjectType.OPSZONE then
local object=Target.Object --Ops.OpsZone#OPSZONE
coal=object:GetOwner()
else
self:E("ERROR: unknown target category!")
end
return coal
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Misc Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -1692,14 +1792,45 @@ end
--- Get the first target objective alive.
-- @param #TARGET self
-- @param Core.Point#COORDINATE RefCoordinate (Optional) Reference coordinate to determine the closest target objective.
-- @param #table Coalitions (Optional) Only consider targets of the given coalition(s).
-- @return #TARGET.Object The target objective.
function TARGET:GetObjective()
function TARGET:GetObjective(RefCoordinate, Coalitions)
for _,_target in pairs(self.targets) do
local target=_target --#TARGET.Object
if target.Status~=TARGET.ObjectStatus.DEAD then
return target
if RefCoordinate then
local dmin=math.huge
local tmin=nil --#TARGET.Object
for _,_target in pairs(self.targets) do
local target=_target --#TARGET.Object
if target.Status~=TARGET.ObjectStatus.DEAD and (Coalitions==nil or UTILS.IsInTable(UTILS.EnsureTable(Coalitions), self:GetTargetCoalition(target))) then
local vec3=self:GetTargetVec3(target)
local d=UTILS.VecDist3D(vec3, RefCoordinate)
if d<dmin then
dmin=d
tmin=target
end
end
end
return tmin
else
for _,_target in pairs(self.targets) do
local target=_target --#TARGET.Object
if target.Status~=TARGET.ObjectStatus.DEAD and (Coalitions==nil or UTILS.IsInTable(UTILS.EnsureTable(Coalitions), self:GetTargetCoalition(target))) then
return target
end
end
end
return nil
@ -1707,10 +1838,13 @@ end
--- Get the first target object alive.
-- @param #TARGET self
-- @param Core.Point#COORDINATE RefCoordinate Reference coordinate to determine the closest target objective.
-- @param #table Coalitions (Optional) Only consider targets of the given coalition(s).
-- @return Wrapper.Positionable#POSITIONABLE The target object or nil.
function TARGET:GetObject()
function TARGET:GetObject(RefCoordinate, Coalitions)
local target=self:GetObjective()
local target=self:GetObjective(RefCoordinate, Coalitions)
if target then
return target.Object
end
@ -1721,8 +1855,9 @@ end
--- Count alive objects.
-- @param #TARGET self
-- @param #TARGET.Object Target Target objective.
-- @param #table Coalitions (Optional) Only count targets of the given coalition(s).
-- @return #number Number of alive target objects.
function TARGET:CountObjectives(Target)
function TARGET:CountObjectives(Target, Coalitions)
local N=0
@ -1735,7 +1870,9 @@ function TARGET:CountObjectives(Target)
for _,_unit in pairs(units or {}) do
local unit=_unit --Wrapper.Unit#UNIT
if unit and unit:IsAlive()~=nil and unit:GetLife()>1 then
N=N+1
if Coalitions==nil or UTILS.IsInTable(UTILS.EnsureTable(Coalitions), unit:GetCoalition()) then
N=N+1
end
end
end
@ -1744,7 +1881,9 @@ function TARGET:CountObjectives(Target)
local target=Target.Object --Wrapper.Unit#UNIT
if target and target:IsAlive()~=nil and target:GetLife()>1 then
N=N+1
if Coalitions==nil or UTILS.IsInTable(Coalitions, target:GetCoalition()) then
N=N+1
end
end
elseif Target.Type==TARGET.ObjectType.STATIC then
@ -1752,7 +1891,9 @@ function TARGET:CountObjectives(Target)
local target=Target.Object --Wrapper.Static#STATIC
if target and target:IsAlive() then
N=N+1
if Coalitions==nil or UTILS.IsInTable(Coalitions, target:GetCoalition()) then
N=N+1
end
end
elseif Target.Type==TARGET.ObjectType.SCENERY then
@ -1763,8 +1904,12 @@ function TARGET:CountObjectives(Target)
elseif Target.Type==TARGET.ObjectType.AIRBASE then
local target=Target.Object --Wrapper.Airbase#AIRBASE
if Target.Status==TARGET.ObjectStatus.ALIVE then
N=N+1
if Coalitions==nil or UTILS.IsInTable(Coalitions, target:GetCoalition()) then
N=N+1
end
end
elseif Target.Type==TARGET.ObjectType.COORDINATE then
@ -1774,7 +1919,15 @@ function TARGET:CountObjectives(Target)
elseif Target.Type==TARGET.ObjectType.ZONE then
-- No target we can check!
elseif Target.Type==TARGET.ObjectType.OPSZONE then
local target=Target.Object --Ops.OpsZone#OPSZONE
if Coalitions==nil or UTILS.IsInTable(Coalitions, target:GetOwner()) then
N=N+1
end
else
self:E(self.lid.."ERROR: Unknown target type! Cannot count targets")
end
@ -1784,15 +1937,16 @@ end
--- Count alive targets.
-- @param #TARGET self
-- @param #table Coalitions (Optional) Only count targets of the given coalition(s).
-- @return #number Number of alive target objects.
function TARGET:CountTargets()
function TARGET:CountTargets(Coalitions)
local N=0
for _,_target in pairs(self.targets) do
local Target=_target --#TARGET.Object
N=N+self:CountObjectives(Target)
N=N+self:CountObjectives(Target, Coalitions)
end

View File

@ -1061,8 +1061,8 @@ function UTILS.Vec2Norm(a)
end
--- Calculate the distance between two 2D vectors.
-- @param DCS#Vec2 a Vector in 3D with x, y components.
-- @param DCS#Vec2 b Vector in 3D with x, y components.
-- @param DCS#Vec2 a Vector in 2D with x, y components.
-- @param DCS#Vec2 b Vector in 2D with x, y components.
-- @return #number Distance between the vectors.
function UTILS.VecDist2D(a, b)
@ -1446,6 +1446,30 @@ function UTILS.GetCoalitionName(Coalition)
end
--- Get the enemy coalition for a given coalition.
-- @param #number Coalition The coalition ID.
-- @param #boolean Neutral Include neutral as enemy.
-- @return #table Enemy coalition table.
function UTILS.GetCoalitionEnemy(Coalition, Neutral)
local Coalitions={}
if Coalition then
if Coalition==coalition.side.RED then
Coalitions={coalition.side.BLUE}
elseif Coalition==coalition.side.BLUE then
Coalitions={coalition.side.RED}
elseif Coalition==coalition.side.NEUTRAL then
Coalitions={coalition.side.RED, coalition.side.BLUE}
end
end
if Neutral then
table.insert(Coalitions, coalition.side.NEUTRAL)
end
return Coalitions
end
--- Get the modulation name from its numerical value.
-- @param #number Modulation The modulation enumerator number. Can be either 0 or 1.
-- @return #string The modulation name, i.e. "AM"=0 or "FM"=1. Anything else will return "Unknown".