- Added rearming zones
- Improved rearming
This commit is contained in:
Frank 2021-09-27 16:11:03 +02:00
parent 994689f05a
commit be0558849c
13 changed files with 823 additions and 200 deletions

View File

@ -8100,10 +8100,10 @@ function WAREHOUSE:_GetIDsFromGroup(group)
end end
-- Debug info -- Debug info
self:T(self.lid..string.format("Group Name = %s", tostring(name))) self:T3(self.lid..string.format("Group Name = %s", tostring(name)))
self:T(self.lid..string.format("Warehouse ID = %s", tostring(wid))) self:T3(self.lid..string.format("Warehouse ID = %s", tostring(wid)))
self:T(self.lid..string.format("Asset ID = %s", tostring(aid))) self:T3(self.lid..string.format("Asset ID = %s", tostring(aid)))
self:T(self.lid..string.format("Request ID = %s", tostring(rid))) self:T3(self.lid..string.format("Request ID = %s", tostring(rid)))
return wid,aid,rid return wid,aid,rid
else else

View File

@ -787,6 +787,20 @@ function AIRWING:onafterStatus(From, Event, To)
-- Check Rescue Helo missions. -- Check Rescue Helo missions.
self:CheckRescuhelo() self:CheckRescuhelo()
----------------
-- Transport ---
----------------
-- Check transport queue.
self:CheckTransportQueue()
--------------
-- Mission ---
--------------
-- Check mission queue.
self:CheckMissionQueue()
-- General info: -- General info:
if self.verbose>=1 then if self.verbose>=1 then
@ -843,36 +857,6 @@ function AIRWING:onafterStatus(From, Event, To)
self:I(self.lid..text) self:I(self.lid..text)
end end
----------------
-- Transport ---
----------------
-- Check if any transports should be cancelled.
--self:_CheckTransports()
-- Get next mission.
local transport=self:_GetNextTransport()
-- Request mission execution.
if transport then
self:TransportRequest(transport)
end
--------------
-- Mission ---
--------------
-- Check if any missions should be cancelled.
self:_CheckMissions()
-- Get next mission.
local mission=self:_GetNextMission()
-- Request mission execution.
if mission then
self:MissionRequest(mission)
end
end end
--- Get patrol data. --- Get patrol data.

View File

@ -812,6 +812,44 @@ function ARMYGROUP:onafterDetour(From, Event, To, Coordinate, Speed, Formation,
end end
--- On before "Rearm" event.
-- @param #ARMYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Core.Point#COORDINATE Coordinate Coordinate where to rearm.
-- @param #number Formation Formation of the group.
function ARMYGROUP:onbeforeRearm(From, Event, To, Coordinate, Formation)
local dt=nil
local allowed=true
-- Pause current mission.
if self.currentmission and self.currentmission>0 then
self:T(self.lid.."Rearm command but have current mission ==> Pausing mission!")
self:PauseMission()
dt=-0.1
allowed=false
end
-- Disengage.
if self:IsEngaging() then
self:T(self.lid.."Rearm command but currently engaging ==> Disengage!")
self:Disengage()
dt=-0.1
allowed=false
end
-- Try again...
if dt then
self:T(self.lid..string.format("Trying Rearm again in %.2f sec", dt))
self:__Rearm(dt, Coordinate, Formation)
allowed=false
end
return allowed
end
--- On after "Rearm" event. --- On after "Rearm" event.
-- @param #ARMYGROUP self -- @param #ARMYGROUP self
-- @param #string From From state. -- @param #string From From state.
@ -821,6 +859,9 @@ end
-- @param #number Formation Formation of the group. -- @param #number Formation Formation of the group.
function ARMYGROUP:onafterRearm(From, Event, To, Coordinate, Formation) function ARMYGROUP:onafterRearm(From, Event, To, Coordinate, Formation)
-- Debug info.
self:I(self.lid..string.format("Group send to rearm"))
-- ID of current waypoint. -- ID of current waypoint.
local uid=self:GetWaypointCurrent().uid local uid=self:GetWaypointCurrent().uid
@ -832,6 +873,18 @@ function ARMYGROUP:onafterRearm(From, Event, To, Coordinate, Formation)
end end
--- On after "Rearmed" event.
-- @param #ARMYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function ARMYGROUP:onafterRearmed(From, Event, To)
self:I(self.lid.."Group rearmed")
-- Check group done.
self:_CheckGroupDone(1)
end
--- On after "RTZ" event. --- On after "RTZ" event.
-- @param #ARMYGROUP self -- @param #ARMYGROUP self
-- @param #string From From state. -- @param #string From From state.
@ -991,14 +1044,32 @@ end
-- @param Wrapper.Group#GROUP Group the group to be engaged. -- @param Wrapper.Group#GROUP Group the group to be engaged.
function ARMYGROUP:onbeforeEngageTarget(From, Event, To, Target) function ARMYGROUP:onbeforeEngageTarget(From, Event, To, Target)
local dt=nil
local allowed=true
local ammo=self:GetAmmoTot() local ammo=self:GetAmmoTot()
if ammo.Total==0 then if ammo.Total==0 then
self:E(self.lid.."WARNING: Cannot engage TARGET because no ammo left!") self:E(self.lid.."WARNING: Cannot engage TARGET because no ammo left!")
return false return false
end end
-- Pause current mission.
if self.currentmission and self.currentmission>0 then
self:T(self.lid.."Engage command but have current mission ==> Pausing mission!")
self:PauseMission()
dt=-0.1
allowed=false
end
return true -- Try again...
if dt then
self:T(self.lid..string.format("Trying Engage again in %.2f sec", dt))
self:__EngageTarget(dt, Target)
allowed=false
end
return allowed
end end
--- On after "EngageTarget" event. --- On after "EngageTarget" event.
@ -1015,9 +1086,14 @@ function ARMYGROUP:onafterEngageTarget(From, Event, To, Target)
else else
self.engage.Target=TARGET:New(Target) self.engage.Target=TARGET:New(Target)
end end
-- Target coordinate. -- Target coordinate.
self.engage.Coordinate=UTILS.DeepCopy(self.engage.Target:GetCoordinate()) self.engage.Coordinate=UTILS.DeepCopy(self.engage.Target:GetCoordinate())
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9)
-- Backup ROE and alarm state. -- Backup ROE and alarm state.
self.engage.roe=self:GetROE() self.engage.roe=self:GetROE()
@ -1031,7 +1107,7 @@ function ARMYGROUP:onafterEngageTarget(From, Event, To, Target)
local uid=self:GetWaypointCurrent().uid local uid=self:GetWaypointCurrent().uid
-- Add waypoint after current. -- Add waypoint after current.
self.engage.Waypoint=self:AddWaypoint(self.engage.Coordinate, nil, uid, Formation, true) self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true)
-- Set if we want to resume route after reaching the detour waypoint. -- Set if we want to resume route after reaching the detour waypoint.
self.engage.Waypoint.detour=1 self.engage.Waypoint.detour=1
@ -1063,9 +1139,11 @@ function ARMYGROUP:_UpdateEngageTarget()
-- Remove current waypoint -- Remove current waypoint
self:RemoveWaypointByID(self.engage.Waypoint.uid) self:RemoveWaypointByID(self.engage.Waypoint.uid)
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9)
-- Add waypoint after current. -- Add waypoint after current.
self.engage.Waypoint=self:AddWaypoint(self.engage.Coordinate, nil, uid, Formation, true) self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true)
-- Set if we want to resume route after reaching the detour waypoint. -- Set if we want to resume route after reaching the detour waypoint.
self.engage.Waypoint.detour=0 self.engage.Waypoint.detour=0
@ -1102,19 +1180,6 @@ function ARMYGROUP:onafterDisengage(From, Event, To)
self:_CheckGroupDone(1) self:_CheckGroupDone(1)
end end
--- On after "Rearmed" event.
-- @param #ARMYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function ARMYGROUP:onafterRearmed(From, Event, To)
self:I(self.lid.."Group rearmed")
-- Check group done.
self:_CheckGroupDone(1)
end
--- On after "DetourReached" event. --- On after "DetourReached" event.
-- @param #ARMYGROUP self -- @param #ARMYGROUP self
-- @param #string From From state. -- @param #string From From state.
@ -1334,7 +1399,48 @@ end
-- Misc Functions -- Misc Functions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Find the neares ammo supply group within a given radius.
-- @param #ARMYGROUP self
-- @param #number Radius Search radius in NM. Default 30 NM.
-- @return Wrapper.Group#GROUP Closest ammo supplying group or `nil` if no group is in the given radius.
function ARMYGROUP:FindNearestAmmoSupply(Radius)
-- Radius in meters.
Radius=UTILS.NMToMeters(Radius or 30)
-- Current positon.
local coord=self:GetCoordinate()
-- Scanned units.
local units=coord:ScanUnits(Radius)
-- Find closest
local dmin=math.huge
local truck=nil --Wrapper.Unit#UNIT
for _,_unit in pairs(units.Set) do
local unit=_unit --Wrapper.Unit#UNIT
-- Check coaliton and if unit can supply ammo.
if unit:GetCoalition()==self:GetCoalition() and unit:IsAmmoSupply() then
-- Distance.
local d=unit:GetCoordinate():Get2DDistance(coord)
-- Check if distance is smaller.
if d<dmin then
dmin=d
truck=unit
end
end
end
if truck then
return truck:GetGroup()
end
return nil
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -37,7 +37,7 @@
-- @field #table legions Assigned legions. -- @field #table legions Assigned legions.
-- @field #table statusLegion Mission status of all assigned LEGIONs. -- @field #table statusLegion Mission status of all assigned LEGIONs.
-- @field #string statusCommander Mission status of the COMMANDER. -- @field #string statusCommander Mission status of the COMMANDER.
-- @field #string statusChief Mission status of the CHIF. -- @field #string statusChief Mission status of the CHIEF.
-- @field #table groupdata Group specific data. -- @field #table groupdata Group specific data.
-- @field #string name Mission name. -- @field #string name Mission name.
-- @field #number prio Mission priority. -- @field #number prio Mission priority.
@ -97,7 +97,6 @@
-- @field #number NcarriersMax Max number of required carrier assets. -- @field #number NcarriersMax Max number of required carrier assets.
-- @field Core.Zone#ZONE transportDeployZone Deploy zone of an OPSTRANSPORT. -- @field Core.Zone#ZONE transportDeployZone Deploy zone of an OPSTRANSPORT.
-- @field Core.Zone#ZONE transportDisembarkZone Disembark zone of an OPSTRANSPORT. -- @field Core.Zone#ZONE transportDisembarkZone Disembark zone of an OPSTRANSPORT.
-- @field #table transportLegions Legions explicitly requested for providing carrier assets.
-- --
-- @field #number artyRadius Radius in meters. -- @field #number artyRadius Radius in meters.
-- @field #number artyShots Number of shots fired. -- @field #number artyShots Number of shots fired.
@ -115,12 +114,16 @@
-- @field #table NassetsLegMin Number of required warehouse assets for each assigned legion. -- @field #table NassetsLegMin Number of required warehouse assets for each assigned legion.
-- @field #table NassetsLegMax Number of required warehouse assets for each assigned legion. -- @field #table NassetsLegMax Number of required warehouse assets for each assigned legion.
-- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the mission was cancelled before the request is processed. -- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the mission was cancelled before the request is processed.
-- @field #table specialLegions User specified legions assigned for this mission. Only these will be considered for the job!
-- @field #table specialCohorts User specified cohorts assigned for this mission. Only these will be considered for the job!
-- @field #table squadrons User specified airwing squadrons assigned for this mission. Only these will be considered for the job!
-- @field #table payloads User specified airwing payloads for this mission. Only these will be considered for the job! -- @field #table payloads User specified airwing payloads for this mission. Only these will be considered for the job!
-- @field Ops.AirWing#AIRWING.PatrolData patroldata Patrol data. -- @field Ops.AirWing#AIRWING.PatrolData patroldata Patrol data.
-- --
-- @field #table specialLegions User specified legions assigned for this mission. Only these will be considered for the job!
-- @field #table specialCohorts User specified cohorts assigned for this mission. Only these will be considered for the job!
-- @field #table transportLegions Legions explicitly requested for providing transport carrier assets.
-- @field #table transportCohorts Cohorts explicitly requested for providing transport carrier assets.
-- @field #table escortLegions Legions explicitly requested for providing escorting assets.
-- @field #table escortCohorts Cohorts explicitly requested for providing escorting assets.
--
-- @field #string missionTask Mission task. See `ENUMS.MissionTask`. -- @field #string missionTask Mission task. See `ENUMS.MissionTask`.
-- @field #number missionAltitude Mission altitude in meters. -- @field #number missionAltitude Mission altitude in meters.
-- @field #number missionSpeed Mission speed in km/h. -- @field #number missionSpeed Mission speed in km/h.
@ -671,6 +674,13 @@ function AUFTRAG:New(Type)
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
--- On after "Planned" event.
-- @function [parent=#AUFTRAG] OnAfterPlanned
-- @param #AUFTRAG self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- Triggers the FSM event "Queued". --- Triggers the FSM event "Queued".
-- @function [parent=#AUFTRAG] Queued -- @function [parent=#AUFTRAG] Queued
@ -681,6 +691,13 @@ function AUFTRAG:New(Type)
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
--- On after "Queued" event.
-- @function [parent=#AUFTRAG] OnAfterQueued
-- @param #AUFTRAG self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- Triggers the FSM event "Requested". --- Triggers the FSM event "Requested".
-- @function [parent=#AUFTRAG] Requested -- @function [parent=#AUFTRAG] Requested
@ -691,6 +708,13 @@ function AUFTRAG:New(Type)
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
--- On after "Requested" event.
-- @function [parent=#AUFTRAG] OnAfterRequested
-- @param #AUFTRAG self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- Triggers the FSM event "Scheduled". --- Triggers the FSM event "Scheduled".
-- @function [parent=#AUFTRAG] Scheduled -- @function [parent=#AUFTRAG] Scheduled
@ -701,6 +725,13 @@ function AUFTRAG:New(Type)
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
--- On after "Scheduled" event.
-- @function [parent=#AUFTRAG] OnAfterScheduled
-- @param #AUFTRAG self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- Triggers the FSM event "Started". --- Triggers the FSM event "Started".
-- @function [parent=#AUFTRAG] Started -- @function [parent=#AUFTRAG] Started
@ -711,6 +742,13 @@ function AUFTRAG:New(Type)
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
--- On after "Started" event.
-- @function [parent=#AUFTRAG] OnAfterStarted
-- @param #AUFTRAG self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- Triggers the FSM event "Executing". --- Triggers the FSM event "Executing".
-- @function [parent=#AUFTRAG] Executing -- @function [parent=#AUFTRAG] Executing
@ -721,6 +759,13 @@ function AUFTRAG:New(Type)
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
--- On after "Executing" event.
-- @function [parent=#AUFTRAG] OnAfterExecuting
-- @param #AUFTRAG self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- Triggers the FSM event "Cancel". --- Triggers the FSM event "Cancel".
-- @function [parent=#AUFTRAG] Cancel -- @function [parent=#AUFTRAG] Cancel
@ -1361,7 +1406,7 @@ end
--- **[AIR]** Create an ESCORT (or FOLLOW) mission. Flight will escort another group and automatically engage certain target types. --- **[AIR]** Create an ESCORT (or FOLLOW) mission. Flight will escort another group and automatically engage certain target types.
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param Wrapper.Group#GROUP EscortGroup The group to escort. -- @param Wrapper.Group#GROUP EscortGroup The group to escort.
-- @param DCS#Vec3 OffsetVector A table with x, y and z components specifying the offset of the flight to the escorted group. Default {x=-100, y=0, z=200} for z=200 meters to the right, same alitude, x=100 meters behind. -- @param DCS#Vec3 OffsetVector A table with x, y and z components specifying the offset of the flight to the escorted group. Default {x=-100, y=0, z=200} for z=200 meters to the right, same alitude (y=0), x=-100 meters behind.
-- @param #number EngageMaxDistance Max engage distance of targets in nautical miles. Default auto (*nil*). -- @param #number EngageMaxDistance Max engage distance of targets in nautical miles. Default auto (*nil*).
-- @param #table TargetTypes Types of targets to engage automatically. Default is {"Air"}, i.e. all enemy airborne units. Use an empty set {} for a simple "FOLLOW" mission. -- @param #table TargetTypes Types of targets to engage automatically. Default is {"Air"}, i.e. all enemy airborne units. Use an empty set {} for a simple "FOLLOW" mission.
-- @return #AUFTRAG self -- @return #AUFTRAG self
@ -1386,7 +1431,7 @@ function AUFTRAG:NewESCORT(EscortGroup, OffsetVector, EngageMaxDistance, TargetT
mission.missionTask=ENUMS.MissionTask.ESCORT mission.missionTask=ENUMS.MissionTask.ESCORT
mission.missionFraction=0.1 mission.missionFraction=0.1
mission.missionAltitude=1000 mission.missionAltitude=1000
mission.optionROE=ENUMS.ROE.OpenFire -- TODO: what's the best ROE here? Make dependent on ESCORT or FOLLOW! mission.optionROE=ENUMS.ROE.OpenFireWeaponFree -- TODO: what's the best ROE here? Make dependent on ESCORT or FOLLOW!
mission.optionROT=ENUMS.ROT.PassiveDefense mission.optionROT=ENUMS.ROT.PassiveDefense
mission.categories={AUFTRAG.Category.AIRCRAFT} mission.categories={AUFTRAG.Category.AIRCRAFT}
@ -2241,10 +2286,60 @@ function AUFTRAG:SetRequiredCarriers(NcarriersMin, NcarriersMax)
return self return self
end end
--- Add a transport Legion.
--- Assign a legion cohort to the mission. Only these cohorts will be considered for the job.
-- @param #AUFTRAG self
-- @param Ops.Cohort#COHORT Cohort The cohort.
-- @return #AUFTRAG self
function AUFTRAG:AssignCohort(Cohort)
self.specialCohorts=self.specialCohorts or {}
self:T3(self.lid..string.format("Assigning cohort %s", tostring(Cohort.name)))
-- Add cohort to table.
table.insert(self.specialCohorts, Cohort)
return self
end
--- Assign a legion to the mission. Only cohorts of this legion will be considered for the job. You can assign multiple legions.
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param Ops.Legion#LEGION Legion The legion. -- @param Ops.Legion#LEGION Legion The legion.
function AUFTRAG:AddTransportLegion(Legion) -- @return #AUFTRAG self
function AUFTRAG:AssignLegion(Legion)
self.specialLegions=self.specialLegions or {}
self:T3(self.lid..string.format("Assigning Legion %s", tostring(Legion.alias)))
-- Add Legion to table.
table.insert(self.specialLegions, Legion)
return self
end
--- Assign airwing squadron(s) to the mission. Only these squads will be considered for the job.
-- @param #AUFTRAG self
-- @param #table Squadrons A table of SQUADRON(s). **Has to be a table {}** even if a single squad is given.
-- @return #AUFTRAG self
function AUFTRAG:AssignSquadrons(Squadrons)
for _,_squad in pairs(Squadrons) do
local squadron=_squad --Ops.Squadron#SQUADRON
self:I(self.lid..string.format("Assigning squadron %s", tostring(squadron.name)))
self:AssignCohort(squadron)
end
return self
end
--- Assign a transport Legion.
-- @param #AUFTRAG self
-- @param Ops.Legion#LEGION Legion The legion.
function AUFTRAG:AssignTransportLegion(Legion)
self.transportLegions=self.transportLegions or {} self.transportLegions=self.transportLegions or {}
@ -2253,6 +2348,45 @@ function AUFTRAG:AddTransportLegion(Legion)
return self return self
end end
--- Assign a transport cohort.
-- @param #AUFTRAG self
-- @param Ops.Cohort#Cohort Cohort The cohort.
function AUFTRAG:AssignTransportCohort(Cohort)
self.transportCohorts=self.transportCohorts or {}
table.insert(self.transportCohorts, Cohort)
return self
end
--- Add an escort Legion.
-- @param #AUFTRAG self
-- @param Ops.Legion#LEGION Legion The legion.
function AUFTRAG:AssignEscortLegion(Legion)
self.escortLegions=self.escortLegions or {}
table.insert(self.escortLegions, Legion)
return self
end
--- Assign an escort cohort.
-- @param #AUFTRAG self
-- @param Ops.Cohort#Cohort Cohort The cohort.
function AUFTRAG:AssignEscortCohort(Cohort)
self.escortCohorts=self.escortCohorts or {}
table.insert(self.escortCohorts, Cohort)
return self
end
--- Set Rules of Engagement (ROE) for this mission. --- Set Rules of Engagement (ROE) for this mission.
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param #string roe Mission ROE. -- @param #string roe Mission ROE.
@ -2498,38 +2632,6 @@ function AUFTRAG:AddConditionPush(ConditionFunction, ...)
return self return self
end end
--- Assign a legion cohort to the mission. Only these cohorts will be considered for the job.
-- @param #AUFTRAG self
-- @param Ops.Cohort#COHORT Cohort The cohort.
-- @return #AUFTRAG self
function AUFTRAG:_AssignCohort(Cohort)
self.squadrons=self.squadrons or {}
self:T3(self.lid..string.format("Assigning cohort %s", tostring(Cohort.name)))
-- Add cohort to table.
table.insert(self.squadrons, Cohort)
return self
end
--- Assign airwing squadron(s) to the mission. Only these squads will be considered for the job.
-- @param #AUFTRAG self
-- @param #table Squadrons A table of SQUADRON(s). **Has to be a table {}** even if a single squad is given.
-- @return #AUFTRAG self
function AUFTRAG:AssignSquadrons(Squadrons)
for _,_squad in pairs(Squadrons) do
local squadron=_squad --Ops.Squadron#SQUADRON
self:I(self.lid..string.format("Assigning squadron %s", tostring(squadron.name)))
self:_AssignCohort(squadron)
end
return self
end
--- Add a required payload for this mission. Only these payloads will be used for this mission. If they are not available, the mission cannot start. Only available for use with an AIRWING. --- Add a required payload for this mission. Only these payloads will be used for this mission. If they are not available, the mission cannot start. Only available for use with an AIRWING.
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param Ops.AirWing#AIRWING.Payload Payload Required payload. -- @param Ops.AirWing#AIRWING.Payload Payload Required payload.

View File

@ -28,7 +28,7 @@
-- --
-- # The BRIGADE Concept -- # The BRIGADE Concept
-- --
-- An BRIGADE consists of multiple PLATOONS. These platoons "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed. -- An BRIGADE consists of one or multiple PLATOONs. These platoons "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed.
-- --
-- --
-- @field #BRIGADE -- @field #BRIGADE
@ -42,6 +42,7 @@ BRIGADE = {
-- @type BRIGADE.RearmingZone -- @type BRIGADE.RearmingZone
-- @field Core.Zone#ZONE zone The zone. -- @field Core.Zone#ZONE zone The zone.
-- @field #boolean occupied If `true`, a rearming truck is present in the zone. -- @field #boolean occupied If `true`, a rearming truck is present in the zone.
-- @field Ops.Auftrag#AUFTRAG mission Mission assigned to supply ammo.
-- @field Wrapper.Marker#MARKER marker F10 marker. -- @field Wrapper.Marker#MARKER marker F10 marker.
--- BRIGADE class version. --- BRIGADE class version.
@ -221,21 +222,22 @@ function BRIGADE:GetRetreatZones()
return self.retreatZones return self.retreatZones
end end
--- Add a patrol Point for CAP missions. --- Add a rearming zone.
-- @param #BRIGADE self -- @param #BRIGADE self
-- @param Core.Zone#ZONE Rearming zone. -- @param Core.Zone#ZONE RearmingZone Rearming zone.
-- @return #BRIGADE self -- @return #BRIGADE.RearmingZone The rearming zone data.
function BRIGADE:AddRearmingZone(RearmingZone) function BRIGADE:AddRearmingZone(RearmingZone)
local rearmingzone={} --#BRIGADE.RearmingZone local rearmingzone={} --#BRIGADE.RearmingZone
rearmingzone.zone=RearmingZone rearmingzone.zone=RearmingZone
rearmingzone.occupied=false rearmingzone.occupied=false
rearmingzone.mission=nil
rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Rearming Zone"):ToCoalition(self:GetCoalition()) rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Rearming Zone"):ToCoalition(self:GetCoalition())
table.insert(self.rearmingZones, rearmingzone) table.insert(self.rearmingZones, rearmingzone)
return self return rearmingzone
end end
@ -292,6 +294,36 @@ function BRIGADE:onafterStatus(From, Event, To)
-- FSM state. -- FSM state.
local fsmstate=self:GetState() local fsmstate=self:GetState()
----------------
-- Transport ---
----------------
self:CheckTransportQueue()
--------------
-- Mission ---
--------------
-- Check if any missions should be cancelled.
self:CheckMissionQueue()
---------------------
-- Rearming Zones ---
---------------------
for i,_rearmingzone in pairs(self.rearmingZones) do
local rearmingzone=_rearmingzone --#BRIGADE.RearmingZone
if (not rearmingzone.mission) or rearmingzone.mission:IsOver() then
rearmingzone.mission=AUFTRAG:NewAMMOSUPPLY(rearmingzone.zone)
self:AddMission(rearmingzone.mission)
end
end
-----------
-- Info ---
-----------
-- General info: -- General info:
if self.verbose>=1 then if self.verbose>=1 then
@ -361,34 +393,21 @@ function BRIGADE:onafterStatus(From, Event, To)
self:I(self.lid..text) self:I(self.lid..text)
end end
---------------- -------------------
-- Transport --- -- Rearming Info --
---------------- -------------------
if self.verbose>=0 then
local text="Rearming Zones:"
for i,_rearmingzone in pairs(self.rearmingZones) do
local rearmingzone=_rearmingzone --#BRIGADE.RearmingZone
local name=rearmingzone.zone:GetName()
-- Check if any transports should be cancelled. -- Platoon text.
--self:_CheckTransports() text=text..string.format("\n* %s: Mission status=%s, suppliers=%d", name, rearmingzone.mission:GetState(), rearmingzone.mission:CountOpsGroups())
-- Get next mission. end
local transport=self:_GetNextTransport() self:I(self.lid..text)
-- Request mission execution.
if transport then
self:TransportRequest(transport)
end
--------------
-- Mission ---
--------------
-- Check if any missions should be cancelled.
self:_CheckMissions()
-- Get next mission.
local mission=self:_GetNextMission()
-- Request mission execution.
if mission then
self:MissionRequest(mission)
end end
end end

View File

@ -567,6 +567,18 @@ function CHIEF:AddOpsZone(OpsZone)
return self return self
end end
--- Add a rearming zone.
-- @param #CHIEF self
-- @param Core.Zone#ZONE RearmingZone Rearming zone.
-- @return Ops.Brigade#BRIGADE.RearmingZone The rearming zone data.
function CHIEF:AddRearmingZone(RearmingZone)
-- Hand over to commander.
local rearmingzone=self.commander:AddRearmingZone(RearmingZone)
return rearmingzone
end
--- Set border zone set. --- Set border zone set.
-- @param #CHIEF self -- @param #CHIEF self

View File

@ -20,6 +20,7 @@
-- @field #table legions Table of legions which are commanded. -- @field #table legions Table of legions which are commanded.
-- @field #table missionqueue Mission queue. -- @field #table missionqueue Mission queue.
-- @field #table transportqueue Transport queue. -- @field #table transportqueue Transport queue.
-- @field #table rearmingZones Rearming zones. Each element is of type `#BRIGADE.RearmingZone`.
-- @field Ops.Chief#CHIEF chief Chief of staff. -- @field Ops.Chief#CHIEF chief Chief of staff.
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
@ -39,6 +40,7 @@ COMMANDER = {
legions = {}, legions = {},
missionqueue = {}, missionqueue = {},
transportqueue = {}, transportqueue = {},
rearmingZones = {},
} }
--- COMMANDER class version. --- COMMANDER class version.
@ -330,6 +332,24 @@ function COMMANDER:RemoveTransport(Transport)
return self return self
end end
--- Add a rearming zone.
-- @param #COMMANDER self
-- @param Core.Zone#ZONE RearmingZone Rearming zone.
-- @return Ops.Brigade#BRIGADE.RearmingZone The rearming zone data.
function COMMANDER:AddRearmingZone(RearmingZone)
local rearmingzone={} --Ops.Brigade#BRIGADE.RearmingZone
rearmingzone.zone=RearmingZone
rearmingzone.occupied=false
rearmingzone.mission=nil
rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Rearming Zone"):ToCoalition(self:GetCoalition())
table.insert(self.rearmingZones, rearmingzone)
return rearmingzone
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Start & Status -- Start & Status
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -370,14 +390,25 @@ function COMMANDER:onafterStatus(From, Event, To)
-- Status. -- Status.
if self.verbose>=1 then if self.verbose>=1 then
local text=string.format("Status %s: Legions=%d, Missions=%d", fsmstate, #self.legions, #self.missionqueue) local text=string.format("Status %s: Legions=%d, Missions=%d, Transports", fsmstate, #self.legions, #self.missionqueue, #self.transportqueue)
self:I(self.lid..text) self:I(self.lid..text)
end end
-- Check mission queue and assign one PLANNED mission. -- Check mission queue and assign one PLANNED mission.
self:CheckMissionQueue() self:CheckMissionQueue()
-- Check mission queue and assign one PLANNED mission -- Check transport queue and assign one PLANNED transport.
self:CheckTransportQueue()
-- Check rearming zones.
for _,_rearmingzone in pairs(self.rearmingZones) do
local rearmingzone=_rearmingzone --#BRIGADE.RearmingZone
-- Check if mission is nil or over.
if (not rearmingzone.mission) or rearmingzone.mission:IsOver() then
rearmingzone.mission=AUFTRAG:NewAMMOSUPPLY(rearmingzone.zone)
self:AddMission(rearmingzone.mission)
end
end
--- ---
-- LEGIONS -- LEGIONS
@ -769,20 +800,31 @@ function COMMANDER:RecruitAssetsForMission(Mission)
-- Debug info. -- Debug info.
env.info(string.format("FF recruiting assets for mission %s [%s]", Mission:GetName(), Mission:GetType())) env.info(string.format("FF recruiting assets for mission %s [%s]", Mission:GetName(), Mission:GetType()))
-- Cohorts. -- Cohorts.
local Cohorts=Mission.squadrons local Cohorts={}
if not Cohorts then for _,_legion in pairs(Mission.specialLegions or {}) do
Cohorts={} local legion=_legion --Ops.Legion#LEGION
for _,_legion in pairs(Mission.specialLegions or self.legions) do for _,_cohort in pairs(legion.cohorts) do
local legion=_legion --Ops.Legion#LEGION local cohort=_cohort --Ops.Cohort#COHORT
-- Loops over cohorts. table.insert(Cohorts, cohort)
end
end
for _,_cohort in pairs(Mission.specialCohorts or {}) do
local cohort=_cohort --Ops.Cohort#COHORT
table.insert(Cohorts, cohort)
end
-- No special mission legions/cohorts found ==> take own legions.
if #Cohorts==0 then
for _,_legion in pairs(self.legions) do
local legion=_legion --Ops.Legion#LEGION
for _,_cohort in pairs(legion.cohorts) do for _,_cohort in pairs(legion.cohorts) do
local cohort=_cohort --Ops.Cohort#COHORT local cohort=_cohort --Ops.Cohort#COHORT
table.insert(Cohorts, cohort) table.insert(Cohorts, cohort)
end end
end end
end end
-- Number of required assets. -- Number of required assets.
local NreqMin, NreqMax=Mission:GetRequiredAssets() local NreqMin, NreqMax=Mission:GetRequiredAssets()
@ -810,18 +852,30 @@ function COMMANDER:RecruitAssetsForEscort(Mission, Assets)
if Mission.NescortMin and Mission.NescortMax and (Mission.NescortMin>0 or Mission.NescortMax>0) then if Mission.NescortMin and Mission.NescortMax and (Mission.NescortMin>0 or Mission.NescortMax>0) then
-- Cohorts. -- Cohorts.
local Cohorts=Mission.squadrons local Cohorts={}
if not Cohorts then for _,_legion in pairs(Mission.escortLegions or {}) do
Cohorts={} local legion=_legion --Ops.Legion#LEGION
for _,_legion in pairs(Mission.specialLegions or self.legions) do for _,_cohort in pairs(legion.cohorts) do
local legion=_legion --Ops.Legion#LEGION local cohort=_cohort --Ops.Cohort#COHORT
-- Loops over cohorts. table.insert(Cohorts, cohort)
end
end
for _,_cohort in pairs(Mission.escortCohorts or {}) do
local cohort=_cohort --Ops.Cohort#COHORT
table.insert(Cohorts, cohort)
end
-- No special escort legions/cohorts found ==> take own legions.
if #Cohorts==0 then
for _,_legion in pairs(self.legions) do
local legion=_legion --Ops.Legion#LEGION
for _,_cohort in pairs(legion.cohorts) do for _,_cohort in pairs(legion.cohorts) do
local cohort=_cohort --Ops.Cohort#COHORT local cohort=_cohort --Ops.Cohort#COHORT
table.insert(Cohorts, cohort) table.insert(Cohorts, cohort)
end end
end end
end end
-- Call LEGION function but provide COMMANDER as self. -- Call LEGION function but provide COMMANDER as self.
local assigned=LEGION.AssignAssetsForEscort(self, Cohorts, Assets, Mission.NescortMin, Mission.NescortMin) local assigned=LEGION.AssignAssetsForEscort(self, Cohorts, Assets, Mission.NescortMin, Mission.NescortMin)

View File

@ -3148,13 +3148,13 @@ function FLIGHTGROUP:FindNearestTanker(Radius)
local istanker, refuelsystem=unit:IsTanker() local istanker, refuelsystem=unit:IsTanker()
if istanker and self.refueltype==refuelsystem then if istanker and self.refueltype==refuelsystem and unit:GetCoalition()==self:GetCoalition() then
-- Distance. -- Distance.
local d=unit:GetCoordinate():Get2DDistance(coord) local d=unit:GetCoordinate():Get2DDistance(coord)
if d<dmin then if d<dmin then
d=dmin dmin=d
tanker=unit tanker=unit
end end

View File

@ -443,11 +443,18 @@ function LEGION:onafterStart(From, Event, To)
end end
--- Check mission queue and assign ONE mission.
--- Check if mission is not over and ready to cancel.
-- @param #LEGION self -- @param #LEGION self
function LEGION:_CheckMissions() -- @return #boolean If `true`, a mission was found and requested.
function LEGION:CheckMissionQueue()
-- Number of missions.
local Nmissions=#self.missionqueue
-- Treat special cases.
if Nmissions==0 then
return nil
end
-- Loop over missions in queue. -- Loop over missions in queue.
for _,_mission in pairs(self.missionqueue) do for _,_mission in pairs(self.missionqueue) do
@ -458,21 +465,6 @@ function LEGION:_CheckMissions()
end end
end end
end
--- Get next mission.
-- @param #LEGION self
-- @return Ops.Auftrag#AUFTRAG Next mission or `#nil`.
function LEGION:_GetNextMission()
-- Number of missions.
local Nmissions=#self.missionqueue
-- Treat special cases.
if Nmissions==0 then
return nil
end
-- Sort results table wrt prio and start time. -- Sort results table wrt prio and start time.
local function _sort(a, b) local function _sort(a, b)
local taskA=a --Ops.Auftrag#AUFTRAG local taskA=a --Ops.Auftrag#AUFTRAG
@ -533,8 +525,9 @@ function LEGION:_GetNextMission()
end end
if EscortAvail and TransportAvail then if EscortAvail and TransportAvail then
-- Got a missin. -- Got a mission.
return mission self:MissionRequest(mission)
return true
else else
-- Recruited assets but no requested escort available. Unrecruit assets! -- Recruited assets but no requested escort available. Unrecruit assets!
LEGION.UnRecruitAssets(assets, mission) LEGION.UnRecruitAssets(assets, mission)
@ -548,10 +541,10 @@ function LEGION:_GetNextMission()
return nil return nil
end end
--- Get next transport. --- Check transport queue and assign ONE transport.
-- @param #LEGION self -- @param #LEGION self
-- @return Ops.OpsTransport#OPSTRANSPORT Next transport or `#nil`. -- @return #boolean If `true`, a transport was found and requested.
function LEGION:_GetNextTransport() function LEGION:CheckTransportQueue()
-- Number of missions. -- Number of missions.
local Ntransports=#self.transportqueue local Ntransports=#self.transportqueue
@ -561,6 +554,8 @@ function LEGION:_GetNextTransport()
return nil return nil
end end
-- TODO: Remove transports that are over!
-- Sort results table wrt prio and start time. -- Sort results table wrt prio and start time.
local function _sort(a, b) local function _sort(a, b)
local taskA=a --Ops.Auftrag#AUFTRAG local taskA=a --Ops.Auftrag#AUFTRAG
@ -598,7 +593,9 @@ function LEGION:_GetNextTransport()
transport:AddAsset(asset) transport:AddAsset(asset)
end end
return transport -- Got transport ==> Request and return.
self:TransportRequest(transport)
return true
end end
end end
@ -1736,9 +1733,25 @@ function LEGION:RecruitAssetsForMission(Mission)
-- Payloads. -- Payloads.
local Payloads=Mission.payloads local Payloads=Mission.payloads
-- Cohorts. -- Get special escort legions and/or cohorts.
local Cohorts=Mission.squadrons or self.cohorts local Cohorts={}
for _,_legion in pairs(Mission.specialLegions or {}) do
local legion=_legion --Ops.Legion#LEGION
for _,_cohort in pairs(legion.cohorts) do
local cohort=_cohort --Ops.Cohort#COHORT
table.insert(Cohorts, cohort)
end
end
for _,_cohort in pairs(Mission.specialCohorts or {}) do
local cohort=_cohort --Ops.Cohort#COHORT
table.insert(Cohorts, cohort)
end
-- No escort cohorts/legions given ==> take own cohorts.
if #Cohorts==0 then
Cohorts=self.cohorts
end
-- Recuit assets. -- Recuit assets.
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads, Mission.engageRange, Mission.refuelSystem, nil) local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads, Mission.engageRange, Mission.refuelSystem, nil)
@ -1776,6 +1789,8 @@ function LEGION:RecruitAssetsForTransport(Transport)
end end
-- TODO: Special transport cohorts/legions.
-- Target is the deploy zone. -- Target is the deploy zone.
local TargetVec2=Transport:GetDeployZone():GetVec2() local TargetVec2=Transport:GetDeployZone():GetVec2()
@ -1802,10 +1817,27 @@ function LEGION:RecruitAssetsForEscort(Mission, Assets)
-- Debug info. -- Debug info.
self:I(self.lid..string.format("Reqested escort for mission %s [%s]. Required assets=%d-%d", Mission:GetName(), Mission:GetType(), Mission.NescortMin,Mission.NescortMax)) self:I(self.lid..string.format("Reqested escort for mission %s [%s]. Required assets=%d-%d", Mission:GetName(), Mission:GetType(), Mission.NescortMin,Mission.NescortMax))
--TODO: Maybe add escortCohorts as mission option? -- Get special escort legions and/or cohorts.
local Cohorts={}
for _,_legion in pairs(Mission.escortLegions or {}) do
local legion=_legion --Ops.Legion#LEGION
for _,_cohort in pairs(legion.cohorts) do
local cohort=_cohort --Ops.Cohort#COHORT
table.insert(Cohorts, cohort)
end
end
for _,_cohort in pairs(Mission.escortCohorts or {}) do
local cohort=_cohort --Ops.Cohort#COHORT
table.insert(Cohorts, cohort)
end
-- No escort cohorts/legions given ==> take own cohorts.
if #Cohorts==0 then
Cohorts=self.cohorts
end
-- Call LEGION function but provide COMMANDER as self. -- Call LEGION function but provide COMMANDER as self.
local assigned=LEGION.AssignAssetsForEscort(self, self.cohorts, Assets, Mission.NescortMin, Mission.NescortMin) local assigned=LEGION.AssignAssetsForEscort(self, Cohorts, Assets, Mission.NescortMin, Mission.NescortMin)
return assigned return assigned
end end
@ -2047,15 +2079,17 @@ function LEGION:AssignAssetsForEscort(Cohorts, Assets, NescortMin, NescortMax)
-- We want airplanes for airplanes and helos for everything else. -- We want airplanes for airplanes and helos for everything else.
local Categories={Group.Category.HELICOPTER} local Categories={Group.Category.HELICOPTER}
local TargetTypes={"Ground Units"}
if asset.category==Group.Category.AIRPLANE then if asset.category==Group.Category.AIRPLANE then
Categories={Group.Category.AIRPLANE} Categories={Group.Category.AIRPLANE}
TargetTypes={"Air"}
end end
-- Recruit escort asset for the mission asset. -- Recruit escort asset for the mission asset.
local Erecruited, eassets, elegions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.ESCORT, nil, NescortMin, NescortMax, TargetVec2, nil, nil, nil, nil, Categories) local Erecruited, eassets, elegions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.ESCORT, nil, NescortMin, NescortMax, TargetVec2, nil, nil, nil, nil, Categories)
if Erecruited then if Erecruited then
Escorts[asset.spawngroupname]={EscortLegions=elegions, EscortAssets=eassets} Escorts[asset.spawngroupname]={EscortLegions=elegions, EscortAssets=eassets, ecategory=asset.category, TargetTypes=TargetTypes}
else else
-- Could not find escort for this asset ==> Escort not possible ==> Break the loop. -- Could not find escort for this asset ==> Escort not possible ==> Break the loop.
EscortAvail=false EscortAvail=false
@ -2071,12 +2105,22 @@ function LEGION:AssignAssetsForEscort(Cohorts, Assets, NescortMin, NescortMax)
local Elegions=value.EscortLegions local Elegions=value.EscortLegions
local Eassets=value.EscortAssets local Eassets=value.EscortAssets
local ecategory=value.ecategory
for _,_legion in pairs(Elegions) do for _,_legion in pairs(Elegions) do
local legion=_legion --Ops.Legion#LEGION local legion=_legion --Ops.Legion#LEGION
local OffsetVector=nil --DCS#Vec3
if ecategory==Group.Category.GROUND then
-- Overhead
OffsetVector={}
OffsetVector.x=0
OffsetVector.y=UTILS.FeetToMeters(1000)
OffsetVector.z=0
end
-- Create and ESCORT mission for this asset. -- Create and ESCORT mission for this asset.
local escort=AUFTRAG:NewESCORT(groupname) local escort=AUFTRAG:NewESCORT(groupname, OffsetVector, nil, value.TargetTypes)
-- Reserve assts and add to mission. -- Reserve assts and add to mission.
for _,_asset in pairs(Eassets) do for _,_asset in pairs(Eassets) do

View File

@ -5,7 +5,7 @@
-- * Let the group steam into the wind -- * Let the group steam into the wind
-- * Command a full stop -- * Command a full stop
-- * Patrol waypoints *ad infinitum* -- * Patrol waypoints *ad infinitum*
-- * Collision warning, if group is heading towards a land mass -- * Collision warning, if group is heading towards a land mass or another obstacle
-- * Automatic pathfinding, e.g. around islands -- * Automatic pathfinding, e.g. around islands
-- * Let a submarine dive and surface -- * Let a submarine dive and surface
-- * Manage TACAN and ICLS beacons -- * Manage TACAN and ICLS beacons
@ -48,9 +48,7 @@
--- *Something must be left to chance; nothing is sure in a sea fight above all.* -- Horatio Nelson --- *Something must be left to chance; nothing is sure in a sea fight above all.* -- Horatio Nelson
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Presentations\OPS\NavyGroup\_Main.png)
--
-- # The NAVYGROUP Concept -- # The NAVYGROUP Concept
-- --
-- This class enhances naval groups. -- This class enhances naval groups.
@ -88,6 +86,9 @@ NAVYGROUP.version="0.7.0"
-- TODO list -- TODO list
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Add RTZ.
-- TODO: Add Retreat.
-- TODO: Add EngageTarget.
-- TODO: Submaries. -- TODO: Submaries.
-- TODO: Extend, shorten turn into wind windows. -- TODO: Extend, shorten turn into wind windows.
-- TODO: Skipper menu. -- TODO: Skipper menu.
@ -132,6 +133,20 @@ function NAVYGROUP:New(group)
-- From State --> Event --> To State -- From State --> Event --> To State
self:AddTransition("*", "FullStop", "Holding") -- Hold position. self:AddTransition("*", "FullStop", "Holding") -- Hold position.
self:AddTransition("*", "Cruise", "Cruising") -- Hold position. self:AddTransition("*", "Cruise", "Cruising") -- Hold position.
self:AddTransition("*", "RTZ", "Returning") -- Group is returning to (home) zone.
self:AddTransition("Returning", "Returned", "Returned") -- Group is returned to (home) zone.
self:AddTransition("*", "Detour", "Cruising") -- Make a detour to a coordinate and resume route afterwards.
self:AddTransition("*", "DetourReached", "*") -- Group reached the detour coordinate.
self:AddTransition("*", "Retreat", "Retreating") -- Order a retreat.
self:AddTransition("Retreating", "Retreated", "Retreated") -- Group retreated.
self:AddTransition("Cruising", "EngageTarget", "Engaging") -- Engage a target from Cruising state
self:AddTransition("Holding", "EngageTarget", "Engaging") -- Engage a target from Holding state
self:AddTransition("OnDetour", "EngageTarget", "Engaging") -- Engage a target from OnDetour state
self:AddTransition("Engaging", "Disengage", "Cruising") -- Disengage and back to cruising.
self:AddTransition("*", "TurnIntoWind", "Cruising") -- Command the group to turn into the wind. self:AddTransition("*", "TurnIntoWind", "Cruising") -- Command the group to turn into the wind.
self:AddTransition("*", "TurnedIntoWind", "*") -- Group turned into wind. self:AddTransition("*", "TurnedIntoWind", "*") -- Group turned into wind.
@ -141,9 +156,6 @@ function NAVYGROUP:New(group)
self:AddTransition("*", "TurningStarted", "*") -- Group started turning. self:AddTransition("*", "TurningStarted", "*") -- Group started turning.
self:AddTransition("*", "TurningStopped", "*") -- Group stopped turning. self:AddTransition("*", "TurningStopped", "*") -- Group stopped turning.
self:AddTransition("*", "Detour", "Cruising") -- Make a detour to a coordinate and resume route afterwards.
self:AddTransition("*", "DetourReached", "*") -- Group reached the detour coordinate.
self:AddTransition("*", "CollisionWarning", "*") -- Collision warning. self:AddTransition("*", "CollisionWarning", "*") -- Collision warning.
self:AddTransition("*", "ClearAhead", "*") -- Clear ahead. self:AddTransition("*", "ClearAhead", "*") -- Clear ahead.
@ -154,15 +166,190 @@ function NAVYGROUP:New(group)
--- Pseudo Functions --- --- Pseudo Functions ---
------------------------ ------------------------
--- Triggers the FSM event "Stop". Stops the NAVYGROUP and all its event handlers. --- Triggers the FSM event "TurnIntoWind".
-- @function [parent=#NAVYGROUP] TurnIntoWind
-- @param #NAVYGROUP self -- @param #NAVYGROUP self
-- @param #NAVYGROUP.IntoWind Into wind parameters.
--- Triggers the FSM event "Stop" after a delay. Stops the NAVYGROUP and all its event handlers. --- Triggers the FSM event "TurnIntoWind" after a delay.
-- @function [parent=#NAVYGROUP] __Stop -- @function [parent=#NAVYGROUP] __TurnIntoWind
-- @param #NAVYGROUP self -- @param #NAVYGROUP self
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
-- @param #NAVYGROUP.IntoWind Into wind parameters.
-- TODO: Add pseudo functions.
--- On after "TurnIntoWind" event.
-- @function [parent=#NAVYGROUP] OnAfterTurnIntoWind
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #NAVYGROUP.IntoWind Into wind parameters.
--- Triggers the FSM event "TurnedIntoWind".
-- @function [parent=#NAVYGROUP] TurnedIntoWind
-- @param #NAVYGROUP self
--- Triggers the FSM event "TurnedIntoWind" after a delay.
-- @function [parent=#NAVYGROUP] __TurnedIntoWind
-- @param #NAVYGROUP self
-- @param #number delay Delay in seconds.
--- On after "TurnedIntoWind" event.
-- @function [parent=#NAVYGROUP] OnAfterTurnedIntoWind
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- Triggers the FSM event "TurnIntoWindStop".
-- @function [parent=#NAVYGROUP] TurnIntoWindStop
-- @param #NAVYGROUP self
--- Triggers the FSM event "TurnIntoWindStop" after a delay.
-- @function [parent=#NAVYGROUP] __TurnIntoWindStop
-- @param #NAVYGROUP self
-- @param #number delay Delay in seconds.
--- On after "TurnIntoWindStop" event.
-- @function [parent=#NAVYGROUP] OnAfterTurnIntoWindStop
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- Triggers the FSM event "TurnIntoWindOver".
-- @function [parent=#NAVYGROUP] TurnIntoWindOver
-- @param #NAVYGROUP self
-- @param #NAVYGROUP.IntoWind IntoWindData Data table.
--- Triggers the FSM event "TurnIntoWindOver" after a delay.
-- @function [parent=#NAVYGROUP] __TurnIntoWindOver
-- @param #NAVYGROUP self
-- @param #number delay Delay in seconds.
-- @param #NAVYGROUP.IntoWind IntoWindData Data table.
--- On after "TurnIntoWindOver" event.
-- @function [parent=#NAVYGROUP] OnAfterTurnIntoWindOver
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #NAVYGROUP.IntoWind IntoWindData Data table.
--- Triggers the FSM event "TurningStarted".
-- @function [parent=#NAVYGROUP] TurningStarted
-- @param #NAVYGROUP self
--- Triggers the FSM event "TurningStarted" after a delay.
-- @function [parent=#NAVYGROUP] __TurningStarted
-- @param #NAVYGROUP self
-- @param #number delay Delay in seconds.
--- On after "TurningStarted" event.
-- @function [parent=#NAVYGROUP] OnAfterTurningStarted
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- Triggers the FSM event "TurningStopped".
-- @function [parent=#NAVYGROUP] TurningStopped
-- @param #NAVYGROUP self
--- Triggers the FSM event "TurningStopped" after a delay.
-- @function [parent=#NAVYGROUP] __TurningStopped
-- @param #NAVYGROUP self
-- @param #number delay Delay in seconds.
--- On after "TurningStopped" event.
-- @function [parent=#NAVYGROUP] OnAfterTurningStopped
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- Triggers the FSM event "CollisionWarning".
-- @function [parent=#NAVYGROUP] CollisionWarning
-- @param #NAVYGROUP self
--- Triggers the FSM event "CollisionWarning" after a delay.
-- @function [parent=#NAVYGROUP] __CollisionWarning
-- @param #NAVYGROUP self
-- @param #number delay Delay in seconds.
--- On after "CollisionWarning" event.
-- @function [parent=#NAVYGROUP] OnAfterCollisionWarning
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- Triggers the FSM event "ClearAhead".
-- @function [parent=#NAVYGROUP] ClearAhead
-- @param #NAVYGROUP self
--- Triggers the FSM event "ClearAhead" after a delay.
-- @function [parent=#NAVYGROUP] __ClearAhead
-- @param #NAVYGROUP self
-- @param #number delay Delay in seconds.
--- On after "ClearAhead" event.
-- @function [parent=#NAVYGROUP] OnAfterClearAhead
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
--- Triggers the FSM event "Dive".
-- @function [parent=#NAVYGROUP] Dive
-- @param #NAVYGROUP self
-- @param #number Depth Dive depth in meters. Default 50 meters.
-- @param #number Speed Speed in knots until next waypoint is reached.
--- Triggers the FSM event "Dive" after a delay.
-- @function [parent=#NAVYGROUP] __Dive
-- @param #NAVYGROUP self
-- @param #number delay Delay in seconds.
-- @param #number Depth Dive depth in meters. Default 50 meters.
-- @param #number Speed Speed in knots until next waypoint is reached.
--- On after "Dive" event.
-- @function [parent=#NAVYGROUP] OnAfterDive
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #number Depth Dive depth in meters. Default 50 meters.
-- @param #number Speed Speed in knots until next waypoint is reached.
--- Triggers the FSM event "Surface".
-- @function [parent=#NAVYGROUP] Surface
-- @param #NAVYGROUP self
-- @param #number Speed Speed in knots until next waypoint is reached.
--- Triggers the FSM event "Surface" after a delay.
-- @function [parent=#NAVYGROUP] __Surface
-- @param #NAVYGROUP self
-- @param #number delay Delay in seconds.
-- @param #number Speed Speed in knots until next waypoint is reached.
--- On after "Surface" event.
-- @function [parent=#NAVYGROUP] OnAfterSurface
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #number Speed Speed in knots until next waypoint is reached.
-- Init waypoints. -- Init waypoints.
@ -385,7 +572,6 @@ function NAVYGROUP:RemoveTurnIntoWind(IntoWindData)
-- Check if this is a window currently open. -- Check if this is a window currently open.
if self.intowind and self.intowind.Id==IntoWindData.Id then if self.intowind and self.intowind.Id==IntoWindData.Id then
--env.info("FF stop in remove")
self:TurnIntoWindStop() self:TurnIntoWindStop()
return return
end end

View File

@ -393,7 +393,7 @@ OPSGROUP.TaskType={
-- @field #string name Waypoint description. Shown in the F10 map. -- @field #string name Waypoint description. Shown in the F10 map.
-- @field #number x Waypoint x-coordinate. -- @field #number x Waypoint x-coordinate.
-- @field #number y Waypoint y-coordinate. -- @field #number y Waypoint y-coordinate.
-- @field #boolean detour If true, this waypoint is not part of the normal route. -- @field #number detour Signifies that this waypoint is not part of the normal route: 0=Hold, 1=Resume Route.
-- @field #boolean intowind If true, this waypoint is a turn into wind route point. -- @field #boolean intowind If true, this waypoint is a turn into wind route point.
-- @field #boolean astar If true, this waypint was found by A* pathfinding algorithm. -- @field #boolean astar If true, this waypint was found by A* pathfinding algorithm.
-- @field #boolean temp If true, this is a temporary waypoint and will be deleted when passed. Also the passing waypoint FSM event is not triggered. -- @field #boolean temp If true, this is a temporary waypoint and will be deleted when passed. Also the passing waypoint FSM event is not triggered.
@ -2693,7 +2693,7 @@ end
-- @return #number Expected speed in m/s. -- @return #number Expected speed in m/s.
function OPSGROUP:GetExpectedSpeed() function OPSGROUP:GetExpectedSpeed()
if self:IsHolding() then if self:IsHolding() or self:Is("Rearming") or self:IsWaiting() or self:IsRetreated() then
return 0 return 0
else else
return self.speedWp or 0 return self.speedWp or 0
@ -2723,6 +2723,12 @@ end
function OPSGROUP:RemoveWaypoint(wpindex) function OPSGROUP:RemoveWaypoint(wpindex)
if self.waypoints then if self.waypoints then
-- The waypoitn to be removed.
local wp=self:GetWaypoint(wpindex)
-- Is this a temporary waypoint.
local istemp=wp.temp or wp.detour or wp.astar or wp.missionUID
-- Number of waypoints before delete. -- Number of waypoints before delete.
local N=#self.waypoints local N=#self.waypoints
@ -2740,7 +2746,6 @@ function OPSGROUP:RemoveWaypoint(wpindex)
end end
-- Remove waypoint marker. -- Remove waypoint marker.
local wp=self:GetWaypoint(wpindex)
if wp and wp.marker then if wp and wp.marker then
wp.marker:Remove() wp.marker:Remove()
end end
@ -2752,7 +2757,7 @@ function OPSGROUP:RemoveWaypoint(wpindex)
local n=#self.waypoints local n=#self.waypoints
-- Debug info. -- Debug info.
self:T(self.lid..string.format("Removing waypoint index %d, current wp index %d. N %d-->%d", wpindex, self.currentwp, N, n)) self:T(self.lid..string.format("Removing waypoint UID=%d [temp=%s]: index=%d [currentwp=%d]. N %d-->%d", wp.uid, tostring(istemp), wpindex, self.currentwp, N, n))
-- Waypoint was not reached yet. -- Waypoint was not reached yet.
if wpindex > self.currentwp then if wpindex > self.currentwp then
@ -2764,7 +2769,7 @@ function OPSGROUP:RemoveWaypoint(wpindex)
-- TODO: patrol adinfinitum. Not sure this is handled correctly. If patrol adinfinitum and we have now only one WP left, we should at least go back. -- TODO: patrol adinfinitum. Not sure this is handled correctly. If patrol adinfinitum and we have now only one WP left, we should at least go back.
-- Could be that the waypoint we are currently moving to was the LAST waypoint. Then we now passed the final waypoint. -- Could be that the waypoint we are currently moving to was the LAST waypoint. Then we now passed the final waypoint.
if self.currentwp>=n and not self.adinfinitum then if self.currentwp>=n and not (self.adinfinitum or istemp) then
self:_PassedFinalWaypoint(true, "Removed FUTURE waypoint we are currently moving to and that was the LAST waypoint") self:_PassedFinalWaypoint(true, "Removed FUTURE waypoint we are currently moving to and that was the LAST waypoint")
end end
@ -2990,6 +2995,20 @@ function OPSGROUP:PushTask(DCSTask)
if self:IsAlive() then if self:IsAlive() then
-- Inject enroute tasks.
if self.taskenroute and #self.taskenroute>0 then
if tostring(DCSTask.id)=="ComboTask" then
for _,task in pairs(self.taskenroute) do
table.insert(DCSTask.params.tasks, 1, task)
end
else
local tasks=UTILS.DeepCopy(self.taskenroute)
table.insert(tasks, DCSTask)
DCSTask=self.group.TaskCombo(self, tasks)
end
end
-- Push task. -- Push task.
self.controller:pushTask(DCSTask) self.controller:pushTask(DCSTask)
@ -3762,6 +3781,7 @@ function OPSGROUP:onafterTaskDone(From, Event, To, Task)
if self.currentmission and self.currentmission==Mission.auftragsnummer then if self.currentmission and self.currentmission==Mission.auftragsnummer then
self.currentmission=nil self.currentmission=nil
end end
env.info("Remove mission waypoints")
self:_RemoveMissionWaypoints(Mission, false) self:_RemoveMissionWaypoints(Mission, false)
end end
@ -5964,6 +5984,15 @@ function OPSGROUP:onafterStop(From, Event, To)
self:I(self.lid.."STOPPED! Unhandled events, cleared scheduler and removed from _DATABASE") self:I(self.lid.."STOPPED! Unhandled events, cleared scheduler and removed from _DATABASE")
end end
--- On after "OutOfAmmo" event.
-- @param #OPSGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function OPSGROUP:onafterOutOfAmmo(From, Event, To)
self:T(self.lid..string.format("Group is out of ammo at t=%.3f", timer.getTime()))
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Cargo Functions -- Cargo Functions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -8091,32 +8120,54 @@ end
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
function OPSGROUP:_CheckGroupDone(delay) function OPSGROUP:_CheckGroupDone(delay)
-- FSM state.
local fsmstate=self:GetState()
if self:IsAlive() and self.isAI then if self:IsAlive() and self.isAI then
if delay and delay>0 then if delay and delay>0 then
-- Debug info.
self:T(self.lid..string.format("Check OPSGROUP [state=%s] done in %.3f seconds...", fsmstate, delay))
-- Delayed call. -- Delayed call.
self:ScheduleOnce(delay, self._CheckGroupDone, self) self:ScheduleOnce(delay, self._CheckGroupDone, self)
else else
-- Debug info. -- Debug info.
self:T(self.lid.."Check OPSGROUP done?") self:T(self.lid..string.format("Check OSGROUP [state=%s] done?", fsmstate))
-- Group is engaging something. -- Group is engaging something.
if self:IsEngaging() then if self:IsEngaging() then
self:T(self.lid.."Engaging! Group NOT done ==> UpdateRoute()")
self:UpdateRoute() self:UpdateRoute()
return return
end end
-- Group is returning -- Group is returning
if self:IsReturning() then if self:IsReturning() then
self:T(self.lid.."Returning! Group NOT done...")
return return
end end
-- Group is returning
if self:IsRearming() then
self:T(self.lid.."Rearming! Group NOT done...")
return
end
-- Group is waiting. We deny all updates. -- Group is waiting. We deny all updates.
if self:IsWaiting() then if self:IsWaiting() then
-- If group is waiting, we assume that is the way it is meant to be. -- If group is waiting, we assume that is the way it is meant to be.
self:T(self.lid.."Waiting! Group NOT done...")
return return
end end
-- First check if there is a paused mission that
if self.missionpaused then
self:T(self.lid..string.format("Found paused mission %s [%s]. Unpausing mission...", self.missionpaused.name, self.missionpaused.type))
self:UnpauseMission()
return
end
-- Get current waypoint. -- Get current waypoint.
local waypoint=self:GetWaypoint(self.currentwp) local waypoint=self:GetWaypoint(self.currentwp)
@ -8226,7 +8277,7 @@ function OPSGROUP:_CheckStuck()
local speed=self:GetVelocity() local speed=self:GetVelocity()
-- Check speed. -- Check speed.
if speed<0.5 then if speed<0.1 then
if ExpectedSpeed>0 and not self.stuckTimestamp then if ExpectedSpeed>0 and not self.stuckTimestamp then
self:T2(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected", speed, ExpectedSpeed)) self:T2(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected", speed, ExpectedSpeed))
@ -8824,9 +8875,9 @@ function OPSGROUP._PassingWaypoint(opsgroup, uid)
end end
-- Check if final waypoint was reached. -- Check if final waypoint was reached.
if opsgroup.currentwp==#opsgroup.waypoints and not opsgroup.adinfinitum then if opsgroup.currentwp==#opsgroup.waypoints and not (opsgroup.adinfinitum or wpistemp) then
-- Set passed final waypoint. -- Set passed final waypoint.
opsgroup:_PassedFinalWaypoint(true, "_PassingWaypoint currentwp==#waypoints and NOT adinfinitum") opsgroup:_PassedFinalWaypoint(true, "_PassingWaypoint currentwp==#waypoints and NOT adinfinitum and NOT a temporary waypoint")
end end
-- Trigger PassingWaypoint event. -- Trigger PassingWaypoint event.
@ -8934,7 +8985,8 @@ function OPSGROUP._PassingWaypoint(opsgroup, uid)
elseif opsgroup:IsEngaging() then elseif opsgroup:IsEngaging() then
-- Nothing to do really. -- Nothing to do really.
opsgroup:T(opsgroup.lid.."Passing engaging waypoint")
else else
-- Trigger DetourReached event. -- Trigger DetourReached event.
@ -9574,6 +9626,7 @@ function OPSGROUP:SwitchRadio(Frequency, Modulation)
Modulation=Modulation or self.radioDefault.Modu Modulation=Modulation or self.radioDefault.Modu
if self:IsFlightgroup() and not self.radio.On then if self:IsFlightgroup() and not self.radio.On then
env.info("FF radio OFF")
self.group:SetOption(AI.Option.Air.id.SILENCE, false) self.group:SetOption(AI.Option.Air.id.SILENCE, false)
end end

View File

@ -48,6 +48,8 @@
-- @field #number Ncargo Total number of cargo groups. -- @field #number Ncargo Total number of cargo groups.
-- @field #number Ncarrier Total number of assigned carriers. -- @field #number Ncarrier Total number of assigned carriers.
-- @field #number Ndelivered Total number of cargo groups delivered. -- @field #number Ndelivered Total number of cargo groups delivered.
-- @field #number NcarrierDead Total number of dead carrier groups
-- @field #number NcargoDead Totalnumber of dead cargo groups.
-- --
-- @field Ops.Auftrag#AUFTRAG mission The mission attached to this transport. -- @field Ops.Auftrag#AUFTRAG mission The mission attached to this transport.
-- @field #table assets Warehouse assets assigned for this transport. -- @field #table assets Warehouse assets assigned for this transport.
@ -192,6 +194,7 @@ OPSTRANSPORT.version="0.5.0"
-- TODO list -- TODO list
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Special transport cohorts/legions. Similar to mission.
-- TODO: Stop/abort transport. -- TODO: Stop/abort transport.
-- DONE: Allow multiple pickup/depoly zones. -- DONE: Allow multiple pickup/depoly zones.
-- DONE: Add start conditions. -- DONE: Add start conditions.
@ -232,6 +235,8 @@ function OPSTRANSPORT:New(CargoGroups, PickupZone, DeployZone)
self.Ncargo=0 self.Ncargo=0
self.Ncarrier=0 self.Ncarrier=0
self.Ndelivered=0 self.Ndelivered=0
self.NcargoDead=0
self.NcarrierDead=0
-- Set default TZC. -- Set default TZC.
self.tzcDefault=self:AddTransportZoneCombo(PickupZone, DeployZone, CargoGroups) self.tzcDefault=self:AddTransportZoneCombo(PickupZone, DeployZone, CargoGroups)
@ -1648,6 +1653,7 @@ end
function OPSTRANSPORT:onafterDeadCarrierGroup(From, Event, To, OpsGroup) function OPSTRANSPORT:onafterDeadCarrierGroup(From, Event, To, OpsGroup)
self:I(self.lid..string.format("Carrier OPSGROUP %s dead!", OpsGroup:GetName())) self:I(self.lid..string.format("Carrier OPSGROUP %s dead!", OpsGroup:GetName()))
-- Remove group from carrier list/table. -- Remove group from carrier list/table.
self.NdeadCarrier=self.NdeadCarrier+1
self:_DelCarrier(OpsGroup) self:_DelCarrier(OpsGroup)
end end

View File

@ -524,6 +524,63 @@ function UNIT:IsTanker()
return tanker, system return tanker, system
end end
--- Check if the unit can supply ammo. Currently, we have
--
-- * M 818
-- * Ural-375
-- * ZIL-135
--
-- This list needs to be extended, if DCS adds other units capable of supplying ammo.
--
-- @param #UNIT self
-- @return #boolean If `true`, unit can supply ammo.
function UNIT:IsAmmoSupply()
-- Type name is the only thing we can check. There is no attribute (Sep. 2021) which would tell us.
local typename=self:GetTypeName()
if typename=="M 818" then
-- Blue ammo truck.
return true
elseif typename=="Ural-375" then
-- Red ammo truck.
return true
elseif typename=="ZIL-135" then
-- Red ammo truck. Checked that it can also provide ammo.
return true
end
return false
end
--- Check if the unit can supply fuel. Currently, we have
--
-- * M978 HEMTT Tanker
-- * ATMZ-5
-- * ATMZ-10
-- * ATZ-5
--
-- This list needs to be extended, if DCS adds other units capable of supplying fuel.
--
-- @param #UNIT self
-- @return #boolean If `true`, unit can supply fuel.
function UNIT:IsFuelSupply()
-- Type name is the only thing we can check. There is no attribute (Sep. 2021) which would tell us.
local typename=self:GetTypeName()
if typename=="M978 HEMTT Tanker" then
return true
elseif typename=="ATMZ-5" then
return true
elseif typename=="ATMZ-10" then
return true
elseif typename=="ATZ-5" then
return true
end
return false
end
--- Returns the unit's group if it exist and nil otherwise. --- Returns the unit's group if it exist and nil otherwise.
-- @param Wrapper.Unit#UNIT self -- @param Wrapper.Unit#UNIT self