**AUFTRAG**
- Added PATROLZONE type. Works for all OPSGROUPs (air, ground and sea).

**FLIGHTGROUP**
- Improved EngageTarget
- Added option to automatically engage detected targets.

**TARGET**
- Improved Zone type
This commit is contained in:
Frank 2021-01-15 23:29:16 +01:00
parent f3a2cf7284
commit 8f56299380
6 changed files with 158 additions and 56 deletions

View File

@ -101,6 +101,7 @@ function ARMYGROUP:New(Group)
self.lid=string.format("ARMYGROUP %s | ", self.groupname)
-- Defaults
self.isArmygroup=true
self:SetDefaultROE()
self:SetDefaultAlarmstate()
self:SetDetection()

View File

@ -101,6 +101,7 @@
--
-- @field #string missionTask Mission task. See `ENUMS.MissionTask`.
-- @field #number missionAltitude Mission altitude in meters.
-- @field #number missionSpeed Mission speed in km/h.
-- @field #number missionFraction Mission coordiante fraction. Default is 0.5.
-- @field #number missionRange Mission range in meters. Used in AIRWING class.
-- @field Core.Point#COORDINATE missionWaypointCoord Mission waypoint coordinate.
@ -441,7 +442,7 @@ AUFTRAG.TargetType={
--- AUFTRAG class version.
-- @field #string version
AUFTRAG.version="0.5.0"
AUFTRAG.version="0.6.0"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@ -1196,8 +1197,10 @@ end
--- Create a PATROLZONE mission. Group(s) will go to the zone and patrol it randomly.
-- @param #AUFTRAG self
-- @param Core.Zone#ZONE Zone The patrol zone.
-- @param #number Speed Speed in knots.
-- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL.
-- @return #AUFTRAG self
function AUFTRAG:NewPATROLZONE(Zone)
function AUFTRAG:NewPATROLZONE(Zone, Speed, Altitude)
local mission=AUFTRAG:New(AUFTRAG.Type.PATROLZONE)
@ -1208,6 +1211,8 @@ function AUFTRAG:NewPATROLZONE(Zone)
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.DCStask=mission:GetDCSMissionTask()
@ -3425,9 +3430,9 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
-- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP.
local param={}
param.zonename=self:GetTargetName()
param.zone=self:GetObjective()
param.altitude=70
param.altitude=self.missionAltitude
param.speed=self.missionSpeed
DCStask.params=param

View File

@ -251,6 +251,7 @@ function FLIGHTGROUP:New(group)
self:SetDefaultROE()
self:SetDefaultROT()
self:SetDetection()
self.isFlightgroup=true
-- Holding flag.
self.flaghold=USERFLAG:New(string.format("%s_FlagHold", self.groupname))
@ -277,10 +278,9 @@ function FLIGHTGROUP:New(group)
self:AddTransition("*", "OutOfMissilesAG", "*") -- Group is out of A2G missiles. Not implemented yet!
self:AddTransition("*", "OutOfMissilesAS", "*") -- Group is out of A2G missiles. Not implemented yet!
self:AddTransition("Airborne", "EngageTargets", "Engaging") -- Engage targets.
self:AddTransition("Airborne", "EngageTarget", "Engaging") -- Engage targets.
self:AddTransition("Engaging", "Disengage", "Airborne") -- Engagement over.
self:AddTransition("*", "ElementParking", "*") -- An element is parking.
self:AddTransition("*", "ElementEngineOn", "*") -- An element spooled up the engines.
self:AddTransition("*", "ElementTaxiing", "*") -- An element is taxiing to the runway.
@ -291,7 +291,6 @@ function FLIGHTGROUP:New(group)
self:AddTransition("*", "ElementOutOfAmmo", "*") -- An element is completely out of ammo.
self:AddTransition("*", "Parking", "Parking") -- The whole flight group is parking.
self:AddTransition("*", "Taxiing", "Taxiing") -- The whole flight group is taxiing.
self:AddTransition("*", "Takeoff", "Airborne") -- The whole flight group is airborne.
@ -514,13 +513,14 @@ end
--- Enable to automatically engage detected targets.
-- @param #FLIGHTGROUP self
-- @param #number RangeMax Max range in NM. Only detected targets within this radius will be engaged. Default is 25 NM.
-- @param #number RangeMax Max range in NM. Only detected targets within this radius from the group will be engaged. Default is 25 NM.
-- @param #table TargetTypes Types of target attributes that will be engaged. See [DCS enum attributes](https://wiki.hoggitworld.com/view/DCS_enum_attributes). Default "All".
-- @param Core.Set#SET_ZONE EngageZoneSet Set of zones in which targets are engaged. Default is anywhere.
-- @param Core.Set#SET_ZONE NoEngageZoneSet Set of zones in which targets are *not* engaged. Default is nowhere.
-- @return #OPSGROUP self
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SetEngageDetectedOn(RangeMax, TargetTypes, EngageZoneSet, NoEngageZoneSet)
-- Ensure table.
if TargetTypes then
if type(TargetTypes)~="table" then
TargetTypes={TargetTypes}
@ -529,12 +529,26 @@ function FLIGHTGROUP:SetEngageDetectedOn(RangeMax, TargetTypes, EngageZoneSet, N
TargetTypes={"All"}
end
-- Ensure SET_ZONE if ZONE is provided.
if EngageZoneSet and EngageZoneSet:IsInstanceOf("ZONE_BASE") then
local zoneset=SET_ZONE:New():AddZone(EngageZoneSet)
EngageZoneSet=zoneset
end
if NoEngageZoneSet and NoEngageZoneSet:IsInstanceOf("ZONE_BASE") then
local zoneset=SET_ZONE:New():AddZone(NoEngageZoneSet)
NoEngageZoneSet=zoneset
end
-- Set parameters.
self.engagedetectedOn=true
self.engagedetectedRmax=UTILS.NMToMeters(RangeMax or 25)
self.engagedetectedTypes=TargetTypes
self.engagedetectedEngageZones=EngageZoneSet
self.engagedetectedNoEngageZones=NoEngageZoneSet
-- Ensure detection is ON or it does not make any sense.
self:SetDetection(true)
return self
end
@ -543,10 +557,10 @@ end
-- @return #OPSGROUP self
function FLIGHTGROUP:SetEngageDetectedOff()
self.engagedetectedOn=false
return self
end
--- Enable that the group is despawned after landing. This can be useful to avoid DCS taxi issues with other AI or players or jamming taxiways.
-- @param #FLIGHTGROUP self
-- @return #FLIGHTGROUP self
@ -1014,8 +1028,7 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
if self:IsAirborne() and self.detectionOn and self.engagedetectedOn then
env.info("FF check detected:")
-- Target.
local targetgroup=nil --Wrapper.Group#GROUP
local targetdist=math.huge
@ -1023,8 +1036,6 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
for _,_group in pairs(self.detectedgroups:GetSet()) do
local group=_group --Wrapper.Group#GROUP
env.info("group "..group:GetName())
if group and group:IsAlive() then
local targetcoord=group:GetCoordinate()
@ -1077,7 +1088,6 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
if insideEngage and not insideNoEngage then
targetdist=distance
targetgroup=group
env.info("targetgroup "..group:GetName())
end
end
@ -1087,8 +1097,7 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
end
if targetgroup then
env.info("engage target! "..targetgroup:GetName())
self:EngageTargets(targetgroup)
self:EngageTarget(targetgroup)
end
end
@ -1911,9 +1920,15 @@ function FLIGHTGROUP:onbeforeUpdateRoute(From, Event, To, n)
end
if self.taskcurrent>0 then
local task=self:GetTaskCurrent()
if task.dcstask.id=="PatrolZone" then
-- For patrol zone, we need to allow the update.
else
self:E(self.lid.."Update route denied because taskcurrent>0")
allowed=false
end
end
-- Not good, because mission will never start. Better only check if there is a current task!
--if self.currentmission then
@ -2036,6 +2051,11 @@ function FLIGHTGROUP:_CheckGroupDone(delay)
return
end
-- Group is currently engaging.
if self:IsEngaging() then
return
end
-- Number of tasks remaining.
local nTasks=self:CountRemainingTasks()
@ -2493,24 +2513,24 @@ function FLIGHTGROUP:onafterHolding(From, Event, To)
end
--- On after "EngageTargets" event. Order to engage a set of units.
--- On after "EngageTarget" event.
-- @param #FLIGHTGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Core.Set#SET_UNIT TargetUnitSet
function FLIGHTGROUP:onafterEngageTargets(From, Event, To, Target)
env.info("FF engage targets")
-- @param #table Target Target object. Can be a UNIT, STATIC, GROUP, SET_UNIT or SET_GROUP object.
function FLIGHTGROUP:onafterEngageTarget(From, Event, To, Target)
-- DCS task.
local DCStask=nil
if Target:IsInstanceOf("UNIT") then
-- Check target object.
if Target:IsInstanceOf("UNIT") or Target:IsInstanceOf("STATIC") then
DCStask=self:GetGroup():TaskAttackUnit(Target, true)
elseif Target:IsInstanceOf("GROUP") then
env.info("FF engage targets GROUP!")
DCStask=self:GetGroup():TaskAttackGroup(Target, nil, nil, nil, nil, nil, nil, true)
elseif Target:IsInstanceOf("SET_UNIT") then
@ -2528,12 +2548,24 @@ function FLIGHTGROUP:onafterEngageTargets(From, Event, To, Target)
elseif Target:IsInstanceOf("SET_GROUP") then
else
local DCSTasks={}
for _,_unit in pairs(Target:GetSet()) do --detected by =HRP= Zero
local unit=_unit --Wrapper.Unit#UNIT
local task=self:GetGroup():TaskAttackGroup(Target, nil, nil, nil, nil, nil, nil, true)
table.insert(DCSTasks)
end
-- Create new task.The description "Task_Engage" is checked.
local Task=self:NewTaskScheduled(DCStask, 1, "Task_Engage", 0)
-- Task combo.
DCStask=self:GetGroup():TaskCombo(DCSTasks)
else
self:E("ERROR: unknown Target in EngageTarget! Needs to be a UNIT, STATIC, GROUP, SET_UNIT or SET_GROUP")
return
end
-- Create new task.The description "Engage_Target" is checked so do not change that lightly.
local Task=self:NewTaskScheduled(DCStask, 1, "Engage_Target", 0)
-- Backup ROE setting.
Task.backupROE=self:GetROE()
@ -2541,6 +2573,12 @@ function FLIGHTGROUP:onafterEngageTargets(From, Event, To, Target)
-- Switch ROE to open fire
self:SwitchROE(ENUMS.ROE.OpenFire)
-- Pause current mission.
local mission=self:GetMissionCurrent()
if mission then
self:PauseMission()
end
-- Execute task.
self:TaskExecute(Task)
@ -2553,9 +2591,7 @@ end
-- @param #string To To state.
-- @param Core.Set#SET_UNIT TargetUnitSet
function FLIGHTGROUP:onafterDisengage(From, Event, To)
env.info("FF disengage targets")
self:T(self.lid.."Disengage target")
end
--- On before "LandAt" event. Check we have a helo group.

View File

@ -123,6 +123,7 @@ function NAVYGROUP:New(GroupName)
self:SetDefaultAlarmstate()
self:SetPatrolAdInfinitum(true)
self:SetPathfinding(false)
self.isNavygroup=true
-- Add FSM transitions.
-- From State --> Event --> To State

View File

@ -22,6 +22,9 @@
-- @field #table template Template of the group.
-- @field #boolean isLateActivated Is the group late activated.
-- @field #boolean isUncontrolled Is the group uncontrolled.
-- @field #boolean isFlightgroup Is a FLIGHTGROUP.
-- @field #boolean isArmygroup Is an ARMYGROUP.
-- @field #boolean isNavygroup Is a NAVYGROUP.
-- @field #table elements Table of elements, i.e. units of the group.
-- @field #boolean isAI If true, group is purely AI.
-- @field #boolean isAircraft If true, group is airplane or helicopter.
@ -327,7 +330,7 @@ OPSGROUP.TaskType={
--- NavyGroup version.
-- @field #string version
OPSGROUP.version="0.7.0"
OPSGROUP.version="0.7.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@ -2169,9 +2172,24 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
elseif Task.dcstask.id=="PatrolZone" then
local Coordinate=Task.dcstask.params.zone:GetCoordinate()
---
-- Task patrol zone.
---
-- Parameters.
local zone=Task.dcstask.params.zone --Core.Zone#ZONE
local Coordinate=zone:GetRandomCoordinate()
local Speed=UTILS.KmphToKnots(Task.dcstask.params.speed or self.speedCruise)
local Altitude=Task.dcstask.params.altitude and UTILS.MetersToFeet(Task.dcstask.params.altitude) or nil
-- New waypoint.
if self.isFlightgroup then
FLIGHTGROUP.AddWaypoint(self, Coordinate, Speed, AfterWaypointWithID, Altitude)
elseif self.isNavygroup then
ARMYGROUP.AddWaypoint(self, Coordinate, Speed, AfterWaypointWithID, Formation)
elseif self.isArmygroup then
NAVYGROUP.AddWaypoint(self, Coordinate, Speed, AfterWaypointWithID, Altitude)
end
else
@ -2252,6 +2270,8 @@ function OPSGROUP:onafterTaskCancel(From, Event, To, Task)
if Task.dcstask.id=="Formation" then
Task.formation:Stop()
done=true
elseif Task.dcstask.id=="PatrolZone" then
done=true
elseif stopflag==1 or (not self:IsAlive()) or self:IsDead() or self:IsStopped() then
-- Manual call TaskDone if setting flag to one was not successful.
done=true
@ -2307,7 +2327,7 @@ function OPSGROUP:onafterTaskDone(From, Event, To, Task)
-- Debug message.
local text=string.format("Task done: %s ID=%d", Task.description, Task.id)
self:T(self.lid..text)
self:I(self.lid..text)
-- No current task.
if Task.id==self.taskcurrent then
@ -2873,6 +2893,8 @@ function OPSGROUP:RouteToMission(mission, delay)
end
elseif mission.type==AUFTRAG.Type.PATROLZONE then
end
local formation=nil
@ -3005,13 +3027,24 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
-- Get the current task.
local task=self:GetTaskCurrent()
if task and task.id=="PatrolZone" then
if task and task.dcstask.id=="PatrolZone" then
-- Remove old waypoint.
self:RemoveWaypointByID(Waypoint.uid)
local zone=task.dcstask.params.zone --Core.Zone#ZONE
local Coordinate=zone:GetRandomCoordinate()
local Speed=UTILS.KmphToKnots(task.dcstask.params.speed or self.speedCruise)
local Altitude=task.dcstask.params.altitude and UTILS.MetersToFeet(task.dcstask.params.altitude) or nil
if self.isFlightgroup then
FLIGHTGROUP.AddWaypoint(self, Coordinate, Speed, AfterWaypointWithID, Altitude)
elseif self.isNavygroup then
ARMYGROUP.AddWaypoint(self, Coordinate, Speed, AfterWaypointWithID, Formation)
elseif self.isArmygroup then
NAVYGROUP.AddWaypoint(self, Coordinate, Speed, AfterWaypointWithID, Altitude)
end
FLIGHTGROUP.AddWaypoint(self,Coordinate, Speed, AfterWaypointWithID, Altitude, Updateroute)
else
@ -4208,7 +4241,6 @@ function OPSGROUP:_CheckAmmoStatus()
self.outofAmmo=false
end
if ammo.Total==0 and not self.outofAmmo then
env.info("FF out of ammo")
self.outofAmmo=true
self:OutOfAmmo()
end

View File

@ -72,6 +72,7 @@ TARGET = {
-- @field #string SCENERY Target is a SCENERY object.
-- @field #string COORDINATE Target is a COORDINATE.
-- @field #string AIRBASE Target is an AIRBASE.
-- @field #string ZONE Target is a ZONE object.
TARGET.ObjectType={
GROUP="Group",
UNIT="Unit",
@ -79,6 +80,7 @@ TARGET.ObjectType={
SCENERY="Scenery",
COORDINATE="Coordinate",
AIRBASE="Airbase",
ZONE="Zone",
}
@ -89,12 +91,14 @@ TARGET.ObjectType={
-- @field #string NAVAL
-- @field #string AIRBASE
-- @field #string COORDINATE
-- @field #string ZONE
TARGET.Category={
AIRCRAFT="Aircraft",
GROUND="Ground",
NAVAL="Naval",
AIRBASE="Airbase",
COORDINATE="Coordinate",
ZONE="Zone",
}
--- Object status.
@ -124,7 +128,7 @@ _TARGETID=0
--- TARGET class version.
-- @field #string version
TARGET.version="0.3.0"
TARGET.version="0.3.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@ -658,12 +662,12 @@ function TARGET:_AddObject(Object)
elseif Object:IsInstanceOf("ZONE_BASE") then
local zone=Object --Core.Zone#ZONE_BASE
Object=zone:GetCoordinate()
Object=zone --:GetCoordinate()
target.Type=TARGET.ObjectType.COORDINATE
target.Type=TARGET.ObjectType.ZONE
target.Name=zone:GetName()
target.Coordinate=Object
target.Coordinate=zone:GetCoordinate()
target.Life0=1
target.Life=1
@ -774,6 +778,12 @@ function TARGET:GetTargetLife(Target)
return 1
elseif Target.Type==TARGET.ObjectType.ZONE then
return 1
else
self:E("ERROR: unknown target object type in GetTargetLife!")
end
end
@ -865,6 +875,13 @@ function TARGET:GetTargetVec3(Target)
local vec3={x=object.x, y=object.y, z=object.z}
return vec3
elseif Target.Type==TARGET.ObjectType.ZONE then
local object=Target.Object --Core.Zone#ZONE
local vec3=object:GetVec3()
return vec3
end
self:E(self.lid.."ERROR: Unknown TARGET type! Cannot get Vec3")
@ -1033,6 +1050,12 @@ function TARGET:GetTargetCategory(Target)
return TARGET.Category.COORDINATE
elseif Target.Type==TARGET.ObjectType.ZONE then
return TARGET.Category.ZONE
else
self:E("ERROR: unknown target category!")
end
return category
@ -1141,6 +1164,10 @@ function TARGET:CountObjectives(Target)
-- No target we can check!
elseif Target.Type==TARGET.ObjectType.ZONE then
-- No target we can check!
else
self:E(self.lid.."ERROR: Unknown target type! Cannot count targets")
end