mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
OPS
Enhanced OPERATION and FLIGHTCONTROL features.
This commit is contained in:
@@ -6311,7 +6311,7 @@ do -- SET_OPSGROUP
|
|||||||
|
|
||||||
--- Creates a new SET_OPSGROUP object, building a set of groups belonging to a coalitions, categories, countries, types or with defined prefix names.
|
--- Creates a new SET_OPSGROUP object, building a set of groups belonging to a coalitions, categories, countries, types or with defined prefix names.
|
||||||
-- @param #SET_OPSGROUP self
|
-- @param #SET_OPSGROUP self
|
||||||
-- @return #SET_OPSGROUP
|
-- @return #SET_OPSGROUP self
|
||||||
function SET_OPSGROUP:New()
|
function SET_OPSGROUP:New()
|
||||||
|
|
||||||
-- Inherit SET_BASE.
|
-- Inherit SET_BASE.
|
||||||
|
|||||||
@@ -2667,6 +2667,26 @@ function RANGE:_DisplayRangeInfo( _unitname )
|
|||||||
text = text .. string.format( "Max strafing alt AGL: %s\n", tstrafemaxalt )
|
text = text .. string.format( "Max strafing alt AGL: %s\n", tstrafemaxalt )
|
||||||
text = text .. string.format( "# of strafe targets: %d\n", self.nstrafetargets )
|
text = text .. string.format( "# of strafe targets: %d\n", self.nstrafetargets )
|
||||||
text = text .. string.format( "# of bomb targets: %d\n", self.nbombtargets )
|
text = text .. string.format( "# of bomb targets: %d\n", self.nbombtargets )
|
||||||
|
if self.instructor then
|
||||||
|
local alive = "N/A"
|
||||||
|
if self.instructorrelayname then
|
||||||
|
local relay = UNIT:FindByName( self.instructorrelayname )
|
||||||
|
if relay then
|
||||||
|
alive = tostring( relay:IsAlive() )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
text = text .. string.format( "Instructor %.3f MHz (Relay=%s)\n", self.instructorfreq, alive )
|
||||||
|
end
|
||||||
|
if self.rangecontrol then
|
||||||
|
local alive = "N/A"
|
||||||
|
if self.rangecontrolrelayname then
|
||||||
|
local relay = UNIT:FindByName( self.rangecontrolrelayname )
|
||||||
|
if relay then
|
||||||
|
alive = tostring( relay:IsAlive() )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
text = text .. string.format( "Control %.3f MHz (Relay=%s)\n", self.rangecontrolfreq, alive )
|
||||||
|
end
|
||||||
text = text .. texthit
|
text = text .. texthit
|
||||||
text = text .. textbomb
|
text = text .. textbomb
|
||||||
text = text .. textdelay
|
text = text .. textdelay
|
||||||
|
|||||||
@@ -1137,15 +1137,19 @@ end
|
|||||||
-- @param #number Port SRS port. Default 5002.
|
-- @param #number Port SRS port. Default 5002.
|
||||||
-- @return #ATIS self
|
-- @return #ATIS self
|
||||||
function ATIS:SetSRS(PathToSRS, Gender, Culture, Voice, Port)
|
function ATIS:SetSRS(PathToSRS, Gender, Culture, Voice, Port)
|
||||||
self.useSRS=true
|
if PathToSRS then
|
||||||
self.msrs=MSRS:New(PathToSRS, self.frequency, self.modulation)
|
self.useSRS=true
|
||||||
self.msrs:SetGender(Gender)
|
self.msrs=MSRS:New(PathToSRS, self.frequency, self.modulation)
|
||||||
self.msrs:SetCulture(Culture)
|
self.msrs:SetGender(Gender)
|
||||||
self.msrs:SetVoice(Voice)
|
self.msrs:SetCulture(Culture)
|
||||||
self.msrs:SetPort(Port)
|
self.msrs:SetVoice(Voice)
|
||||||
self.msrs:SetCoalition(self:GetCoalition())
|
self.msrs:SetPort(Port)
|
||||||
if self.dTQueueCheck<=10 then
|
self.msrs:SetCoalition(self:GetCoalition())
|
||||||
self:SetQueueUpdateTime(90)
|
if self.dTQueueCheck<=10 then
|
||||||
|
self:SetQueueUpdateTime(90)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:E(self.lid..string.format("ERROR: No SRS path specified!"))
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ function ARMYGROUP:New(group)
|
|||||||
|
|
||||||
self:AddTransition("*", "Rearm", "Rearm") -- Group is send to a coordinate and waits until ammo is refilled.
|
self:AddTransition("*", "Rearm", "Rearm") -- Group is send to a coordinate and waits until ammo is refilled.
|
||||||
self:AddTransition("Rearm", "Rearming", "Rearming") -- Group has arrived at the rearming coodinate and is waiting to be fully rearmed.
|
self:AddTransition("Rearm", "Rearming", "Rearming") -- Group has arrived at the rearming coodinate and is waiting to be fully rearmed.
|
||||||
self:AddTransition("Rearming", "Rearmed", "Cruising") -- Group was rearmed.
|
self:AddTransition("*", "Rearmed", "Cruising") -- Group was rearmed.
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
--- Pseudo Functions ---
|
--- Pseudo Functions ---
|
||||||
@@ -1382,8 +1382,21 @@ end
|
|||||||
function ARMYGROUP:onafterRearmed(From, Event, To)
|
function ARMYGROUP:onafterRearmed(From, Event, To)
|
||||||
self:T(self.lid.."Group rearmed")
|
self:T(self.lid.."Group rearmed")
|
||||||
|
|
||||||
-- Check group done.
|
-- Get Current mission.
|
||||||
self:_CheckGroupDone(1)
|
local mission=self:GetMissionCurrent()
|
||||||
|
|
||||||
|
-- Check if this is a rearming mission.
|
||||||
|
if mission and mission.type==AUFTRAG.Type.REARMING then
|
||||||
|
-- Rearmed ==> Mission Done! This also checks if the group is done.
|
||||||
|
self:MissionDone(mission)
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Check group done.
|
||||||
|
self:_CheckGroupDone(1)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On before "RTZ" event.
|
--- On before "RTZ" event.
|
||||||
|
|||||||
@@ -418,6 +418,7 @@ _AUFTRAGSNR=0
|
|||||||
-- @field #string AIRDEFENSE Air defense.
|
-- @field #string AIRDEFENSE Air defense.
|
||||||
-- @field #string EWR Early Warning Radar.
|
-- @field #string EWR Early Warning Radar.
|
||||||
-- @field #string RECOVERYTANKER Recovery tanker.
|
-- @field #string RECOVERYTANKER Recovery tanker.
|
||||||
|
-- @filed #string REARMING Rearming mission.
|
||||||
-- @field #string NOTHING Nothing.
|
-- @field #string NOTHING Nothing.
|
||||||
AUFTRAG.Type={
|
AUFTRAG.Type={
|
||||||
ANTISHIP="Anti Ship",
|
ANTISHIP="Anti Ship",
|
||||||
@@ -459,6 +460,7 @@ AUFTRAG.Type={
|
|||||||
AIRDEFENSE="Air Defence",
|
AIRDEFENSE="Air Defence",
|
||||||
EWR="Early Warning Radar",
|
EWR="Early Warning Radar",
|
||||||
RECOVERYTANKER="Recovery Tanker",
|
RECOVERYTANKER="Recovery Tanker",
|
||||||
|
REARMING="Rearming",
|
||||||
NOTHING="Nothing",
|
NOTHING="Nothing",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,6 +482,7 @@ AUFTRAG.Type={
|
|||||||
-- @field #string AIRDEFENSE Air defense.
|
-- @field #string AIRDEFENSE Air defense.
|
||||||
-- @field #string EWR Early Warning Radar.
|
-- @field #string EWR Early Warning Radar.
|
||||||
-- @field #string RECOVERYTANKER Recovery tanker.
|
-- @field #string RECOVERYTANKER Recovery tanker.
|
||||||
|
-- @field #string REARMING Rearming.
|
||||||
-- @field #string NOTHING Nothing.
|
-- @field #string NOTHING Nothing.
|
||||||
AUFTRAG.SpecialTask={
|
AUFTRAG.SpecialTask={
|
||||||
FORMATION="Formation",
|
FORMATION="Formation",
|
||||||
@@ -499,6 +502,7 @@ AUFTRAG.SpecialTask={
|
|||||||
AIRDEFENSE="Air Defense",
|
AIRDEFENSE="Air Defense",
|
||||||
EWR="Early Warning Radar",
|
EWR="Early Warning Radar",
|
||||||
RECOVERYTANKER="Recovery Tanker",
|
RECOVERYTANKER="Recovery Tanker",
|
||||||
|
REARMING="Rearming",
|
||||||
NOTHING="Nothing",
|
NOTHING="Nothing",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2009,6 +2013,30 @@ function AUFTRAG:NewFUELSUPPLY(Zone)
|
|||||||
return mission
|
return mission
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- **[GROUND]** Create a REARMING mission.
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @param Core.Zone#ZONE Zone The zone, where units go and look for ammo supply.
|
||||||
|
-- @return #AUFTRAG self
|
||||||
|
function AUFTRAG:NewREARMING(Zone)
|
||||||
|
|
||||||
|
local mission=AUFTRAG:New(AUFTRAG.Type.REARMING)
|
||||||
|
|
||||||
|
mission:_TargetFromObject(Zone)
|
||||||
|
|
||||||
|
mission.optionROE=ENUMS.ROE.WeaponHold
|
||||||
|
mission.optionAlarm=ENUMS.AlarmState.Auto
|
||||||
|
|
||||||
|
mission.missionFraction=1.0
|
||||||
|
|
||||||
|
mission.missionWaypointRadius=0
|
||||||
|
|
||||||
|
mission.categories={AUFTRAG.Category.GROUND}
|
||||||
|
|
||||||
|
mission.DCStask=mission:GetDCSMissionTask()
|
||||||
|
|
||||||
|
return mission
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- **[AIR]** Create an ALERT 5 mission. Aircraft will be spawned uncontrolled and wait for an assignment. You must specify **one** mission type which is performed.
|
--- **[AIR]** Create an ALERT 5 mission. Aircraft will be spawned uncontrolled and wait for an assignment. You must specify **one** mission type which is performed.
|
||||||
-- This determines the payload and the DCS mission task which are used when the aircraft is spawned.
|
-- This determines the payload and the DCS mission task which are used when the aircraft is spawned.
|
||||||
@@ -5710,6 +5738,24 @@ function AUFTRAG:GetDCSMissionTask()
|
|||||||
|
|
||||||
table.insert(DCStasks, DCStask)
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
|
elseif self.type==AUFTRAG.Type.AMMOSUPPLY then
|
||||||
|
|
||||||
|
----------------------
|
||||||
|
-- REARMING Mission --
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
local DCStask={}
|
||||||
|
|
||||||
|
DCStask.id=AUFTRAG.SpecialTask.REARMING
|
||||||
|
|
||||||
|
-- We create a "fake" DCS task and pass the parameters to the OPSGROUP.
|
||||||
|
local param={}
|
||||||
|
param.zone=self:GetObjective()
|
||||||
|
|
||||||
|
DCStask.params=param
|
||||||
|
|
||||||
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
elseif self.type==AUFTRAG.Type.ALERT5 then
|
elseif self.type==AUFTRAG.Type.ALERT5 then
|
||||||
|
|
||||||
---------------------
|
---------------------
|
||||||
|
|||||||
@@ -2117,7 +2117,7 @@ function CHIEF:CheckTargetQueue()
|
|||||||
self:T2(self.lid..string.format("Recruiting assets for mission type %s [performance=%d] of target %s", mp.MissionType, mp.Performance, target:GetName()))
|
self:T2(self.lid..string.format("Recruiting assets for mission type %s [performance=%d] of target %s", mp.MissionType, mp.Performance, target:GetName()))
|
||||||
|
|
||||||
-- Recruit assets.
|
-- Recruit assets.
|
||||||
local recruited, assets, legions=self:RecruitAssetsForTarget(target, mp.MissionType, NassetsMin, NassetsMax)
|
local recruited, assets, legions=self.commander:RecruitAssetsForTarget(target, mp.MissionType, NassetsMin, NassetsMax)
|
||||||
|
|
||||||
if recruited then
|
if recruited then
|
||||||
|
|
||||||
@@ -2649,29 +2649,6 @@ function CHIEF:_GetMissionTypeForGroupAttribute(Attribute)
|
|||||||
return missionperf
|
return missionperf
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Recruit assets for a given TARGET.
|
|
||||||
-- @param #CHIEF self
|
|
||||||
-- @param Ops.Target#TARGET Target The target.
|
|
||||||
-- @param #string MissionType Mission Type.
|
|
||||||
-- @param #number NassetsMin Min number of required assets.
|
|
||||||
-- @param #number NassetsMax Max number of required assets.
|
|
||||||
-- @return #boolean If `true` enough assets could be recruited.
|
|
||||||
-- @return #table Assets that have been recruited from all legions.
|
|
||||||
-- @return #table Legions that have recruited assets.
|
|
||||||
function CHIEF:RecruitAssetsForTarget(Target, MissionType, NassetsMin, NassetsMax)
|
|
||||||
|
|
||||||
-- Cohorts.
|
|
||||||
local Cohorts=self.commander:_GetCohorts()
|
|
||||||
|
|
||||||
-- Target position.
|
|
||||||
local TargetVec2=Target:GetVec2()
|
|
||||||
|
|
||||||
-- Recruite assets.
|
|
||||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, MissionType, nil, NassetsMin, NassetsMax, TargetVec2)
|
|
||||||
|
|
||||||
|
|
||||||
return recruited, assets, legions
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Recruit assets for a given OPS zone.
|
--- Recruit assets for a given OPS zone.
|
||||||
-- @param #CHIEF self
|
-- @param #CHIEF self
|
||||||
|
|||||||
@@ -787,7 +787,7 @@ end
|
|||||||
function COHORT:onafterStart(From, Event, To)
|
function COHORT:onafterStart(From, Event, To)
|
||||||
|
|
||||||
-- Short info.
|
-- Short info.
|
||||||
local text=string.format("Starting %s v%s %s", self.ClassName, self.version, self.name)
|
local text=string.format("Starting %s v%s %s [%s]", self.ClassName, self.version, self.name, self.attribute)
|
||||||
self:I(self.lid..text)
|
self:I(self.lid..text)
|
||||||
|
|
||||||
-- Start the status monitoring.
|
-- Start the status monitoring.
|
||||||
@@ -993,7 +993,7 @@ end
|
|||||||
-- @param #COHORT self
|
-- @param #COHORT self
|
||||||
-- @param #table MissionTypes (Optional) Count only assest that can perform certain mission type(s). Default is all types.
|
-- @param #table MissionTypes (Optional) Count only assest that can perform certain mission type(s). Default is all types.
|
||||||
-- @param #table Attributes (Optional) Count only assest that have a certain attribute(s), e.g. `WAREHOUSE.Attribute.AIR_BOMBER`.
|
-- @param #table Attributes (Optional) Count only assest that have a certain attribute(s), e.g. `WAREHOUSE.Attribute.AIR_BOMBER`.
|
||||||
-- @return Core.Set#SET_OPSGROUPS Ops groups set.
|
-- @return Core.Set#SET_OPSGROUP Ops groups set.
|
||||||
function COHORT:GetOpsGroups(MissionTypes, Attributes)
|
function COHORT:GetOpsGroups(MissionTypes, Attributes)
|
||||||
|
|
||||||
local set=SET_OPSGROUP:New()
|
local set=SET_OPSGROUP:New()
|
||||||
|
|||||||
@@ -1254,6 +1254,23 @@ function COMMANDER:CheckOpsQueue()
|
|||||||
|
|
||||||
if operation:IsRunning() then
|
if operation:IsRunning() then
|
||||||
|
|
||||||
|
-- Loop over missions.
|
||||||
|
for _,_mission in pairs(operation.missions or {}) do
|
||||||
|
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||||
|
|
||||||
|
if mission.phase==nil or (mission.phase and mission.phase==operation.phase) and mission:IsPlanned() then
|
||||||
|
self:AddMission(mission)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Loop over targets.
|
||||||
|
for _,_target in pairs(operation.targets or {}) do
|
||||||
|
local target=_target --Ops.Target#TARGET
|
||||||
|
|
||||||
|
if (target.phase==nil or (target.phase and target.phase==operation.phase)) and (not self:IsTarget(target)) then
|
||||||
|
self:AddTarget(target)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1352,6 +1369,9 @@ function COMMANDER:CheckTargetQueue()
|
|||||||
mission:SetRequiredAttribute(resource.Attributes)
|
mission:SetRequiredAttribute(resource.Attributes)
|
||||||
mission:SetRequiredProperty(resource.Properties)
|
mission:SetRequiredProperty(resource.Properties)
|
||||||
|
|
||||||
|
-- Set operation (if any).
|
||||||
|
mission.operation=target.operation
|
||||||
|
|
||||||
-- Set resource mission.
|
-- Set resource mission.
|
||||||
resource.mission=mission
|
resource.mission=mission
|
||||||
|
|
||||||
@@ -1651,6 +1671,30 @@ function COMMANDER:RecruitAssetsForEscort(Mission, Assets)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Recruit assets for a given TARGET.
|
||||||
|
-- @param #COMMANDER self
|
||||||
|
-- @param Ops.Target#TARGET Target The target.
|
||||||
|
-- @param #string MissionType Mission Type.
|
||||||
|
-- @param #number NassetsMin Min number of required assets.
|
||||||
|
-- @param #number NassetsMax Max number of required assets.
|
||||||
|
-- @return #boolean If `true` enough assets could be recruited.
|
||||||
|
-- @return #table Assets that have been recruited from all legions.
|
||||||
|
-- @return #table Legions that have recruited assets.
|
||||||
|
function COMMANDER:RecruitAssetsForTarget(Target, MissionType, NassetsMin, NassetsMax)
|
||||||
|
|
||||||
|
-- Cohorts.
|
||||||
|
local Cohorts=self:_GetCohorts()
|
||||||
|
|
||||||
|
-- Target position.
|
||||||
|
local TargetVec2=Target:GetVec2()
|
||||||
|
|
||||||
|
-- Recruite assets.
|
||||||
|
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, MissionType, nil, NassetsMin, NassetsMax, TargetVec2)
|
||||||
|
|
||||||
|
|
||||||
|
return recruited, assets, legions
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Transport Functions
|
-- Transport Functions
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -12,7 +12,15 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
-- ## Example Missions:
|
||||||
|
--
|
||||||
|
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20FlightControl).
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
-- ### Author: **funkyfranky**
|
-- ### Author: **funkyfranky**
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
-- @module OPS.FlightControl
|
-- @module OPS.FlightControl
|
||||||
-- @image OPS_FlightControl.png
|
-- @image OPS_FlightControl.png
|
||||||
|
|
||||||
@@ -62,7 +70,10 @@
|
|||||||
-- # The FLIGHTCONTROL Concept
|
-- # The FLIGHTCONTROL Concept
|
||||||
--
|
--
|
||||||
-- This class implements an ATC for human and AI controlled aircraft. It gives permission for take-off and landing based on a sophisticated queueing system.
|
-- This class implements an ATC for human and AI controlled aircraft. It gives permission for take-off and landing based on a sophisticated queueing system.
|
||||||
-- Therefore, it solves (or reduces) a lot of common problems with the DCS implementation (which is barly existing at this point).
|
-- Therefore, it solves (or reduces) a lot of common problems with the DCS implementation.
|
||||||
|
--
|
||||||
|
-- You might be familiar with the `AIRBOSS` class. This class is the analogue for land based airfields. One major difference is that no pre-recorded sound files are
|
||||||
|
-- necessary. The radio transmissions use the SRS text-to-speech feature.
|
||||||
--
|
--
|
||||||
-- ## Prerequisites
|
-- ## Prerequisites
|
||||||
--
|
--
|
||||||
@@ -77,7 +88,54 @@
|
|||||||
-- * Only one player/client per group as we can create menus only for a group and not for a specific unit.
|
-- * Only one player/client per group as we can create menus only for a group and not for a specific unit.
|
||||||
-- * Only FLIGHTGROUPS are controlled. This means some older classes, *e.g.* RAT are not supported (yet).
|
-- * Only FLIGHTGROUPS are controlled. This means some older classes, *e.g.* RAT are not supported (yet).
|
||||||
-- * So far only airdromes are handled, *i.e.* no FARPs or ships.
|
-- * So far only airdromes are handled, *i.e.* no FARPs or ships.
|
||||||
-- * Only fixed wing aircraft are handled until now, *i.e.* no helos.
|
-- * Helicopters are not treated differently from fixed wing aircraft until now.
|
||||||
|
-- * The active runway can only be determined by the wind direction. So at least set a very light wind speed in your mission.
|
||||||
|
--
|
||||||
|
-- # Basic Usage
|
||||||
|
--
|
||||||
|
-- A flight control for a given airdrome can be created with the @{#FLIGHTCONTROL.New}(*AirbaseName, Frequency, Modulation, PathToSRS*) function. You need to specify the name of the airbase, the
|
||||||
|
-- tower radio frequency, its modulation and the path, where SRS is located on the machine that is running this mission.
|
||||||
|
--
|
||||||
|
-- For the FC to be operating, it needs to be started with the @{#FLIGHTCONTROL.Start}() function.
|
||||||
|
--
|
||||||
|
-- ## Simple Script
|
||||||
|
--
|
||||||
|
-- The simplest script looks like
|
||||||
|
--
|
||||||
|
-- local FC_BATUMI=FLIGHTCONTROL:New(AIRBASE.Caucasus.Batumi, 251, nil, "D:\\SomeDirectory\\_SRS")
|
||||||
|
-- FC_BATUMI:Start()
|
||||||
|
--
|
||||||
|
-- This will start the FC for at the Batumi airbase with tower frequency 251 MHz AM. SRS needs to be in the given directory.
|
||||||
|
--
|
||||||
|
-- Like this, a default holding pattern (see below) is parallel to the direction of the active runway.
|
||||||
|
--
|
||||||
|
-- # Holding Patterns
|
||||||
|
--
|
||||||
|
-- Holding pattern are air spaces where incoming aircraft are guided to and have to hold until they get landing clearance.
|
||||||
|
--
|
||||||
|
-- You can add a holding pattern with the @{#FLIGHTCONTROL.AddHoldingPattern}(*ArrivalZone, Heading, Length, FlightlevelMin, FlightlevelMax, Prio*) function, where
|
||||||
|
--
|
||||||
|
-- * `ArrivalZone` is the zone where the aircraft enter the pattern.
|
||||||
|
-- * `Heading` is the direction into which the aircraft have to fly from the arrival zone.
|
||||||
|
-- * `Length` is the length of the pattern.
|
||||||
|
-- * `FlightLevelMin` is the lowest altitude at which aircraft can hold.
|
||||||
|
-- * `FlightLevelMax` is the highest altitude at which aircraft can hold.
|
||||||
|
-- * `Prio` is the priority of this holdig stacks. If multiple patterns are defined, patterns with higher prio will be filled first.
|
||||||
|
--
|
||||||
|
-- # Parking Guard
|
||||||
|
--
|
||||||
|
-- # Taxi Limits
|
||||||
|
--
|
||||||
|
-- You can define limits on how many aircraft are simultaniously landing and taking off. This avoids (DCS) problems where taxiing aircraft cause a "traffic jam" on the taxi way(s)
|
||||||
|
-- and bring the whole airbase effectively to a stand still.
|
||||||
|
--
|
||||||
|
-- ## Landing Limits
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- ## Takeoff Limits
|
||||||
|
--
|
||||||
|
-- Note that the limits here are only affecting AI aircraft groups. Human players are assumed to be a lot more well behaved and capable as they are able to taxi around obstacles, *e.g.*
|
||||||
|
-- other aircraft etc.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- @field #FLIGHTCONTROL
|
-- @field #FLIGHTCONTROL
|
||||||
@@ -102,7 +160,7 @@ FLIGHTCONTROL = {
|
|||||||
Nlanding = nil,
|
Nlanding = nil,
|
||||||
dTlanding = nil,
|
dTlanding = nil,
|
||||||
Nparkingspots = nil,
|
Nparkingspots = nil,
|
||||||
holdingpatterns = {},
|
holdingpatterns = {},
|
||||||
hpcounter = 0,
|
hpcounter = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,20 +228,20 @@ FLIGHTCONTROL.FlightStatus={
|
|||||||
|
|
||||||
--- FlightControl class version.
|
--- FlightControl class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
FLIGHTCONTROL.version="0.5.2"
|
FLIGHTCONTROL.version="0.5.3"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
|
|
||||||
-- TODO: Runway destroyed.
|
-- TODO: Runway destroyed.
|
||||||
-- TODO: Support airwings. Dont give clearance for Alert5 or if mission has not started.
|
|
||||||
-- TODO: Switch to enable/disable AI messages.
|
-- TODO: Switch to enable/disable AI messages.
|
||||||
-- TODO: Improve ATC TTS messages.
|
-- TODO: Improve ATC TTS messages.
|
||||||
-- TODO: Talk me down option.
|
-- TODO: Talk me down option.
|
||||||
-- TODO: ATIS option.
|
-- TODO: ATIS option.
|
||||||
-- TODO: Check runways and clean up.
|
-- TODO: Check runways and clean up.
|
||||||
-- TODO: Accept and forbit parking spots.
|
|
||||||
-- TODO: Add FARPS?
|
-- TODO: Add FARPS?
|
||||||
|
-- DONE: Accept and forbit parking spots. DONE via AIRBASE black/white lists and airwing features.
|
||||||
|
-- DONE: Support airwings. Dont give clearance for Alert5 or if mission has not started.
|
||||||
-- DONE: Define holding zone.
|
-- DONE: Define holding zone.
|
||||||
-- DONE: Basic ATC voice overs.
|
-- DONE: Basic ATC voice overs.
|
||||||
-- DONE: Add SRS TTS.
|
-- DONE: Add SRS TTS.
|
||||||
@@ -235,6 +293,9 @@ function FLIGHTCONTROL:New(AirbaseName, Frequency, Modulation, PathToSRS)
|
|||||||
-- 5 NM zone around the airbase.
|
-- 5 NM zone around the airbase.
|
||||||
self.zoneAirbase=ZONE_RADIUS:New("FC", self:GetCoordinate():GetVec2(), UTILS.NMToMeters(5))
|
self.zoneAirbase=ZONE_RADIUS:New("FC", self:GetCoordinate():GetVec2(), UTILS.NMToMeters(5))
|
||||||
|
|
||||||
|
-- Add backup holding pattern.
|
||||||
|
self:_AddHoldingPatternBackup()
|
||||||
|
|
||||||
-- Set alias.
|
-- Set alias.
|
||||||
self.alias=self.airbasename.." Tower"
|
self.alias=self.airbasename.." Tower"
|
||||||
|
|
||||||
@@ -332,6 +393,16 @@ function FLIGHTCONTROL:SetFrequency(Frequency, Modulation)
|
|||||||
self.frequency=Frequency or 305
|
self.frequency=Frequency or 305
|
||||||
self.modulation=Modulation or radio.modulation.AM
|
self.modulation=Modulation or radio.modulation.AM
|
||||||
|
|
||||||
|
if self.msrsPilot then
|
||||||
|
self.msrsPilot:SetFrequencies(Frequency)
|
||||||
|
self.msrsPilot:SetModulations(Modulation)
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.msrsTower then
|
||||||
|
self.msrsTower:SetFrequencies(Frequency)
|
||||||
|
self.msrsTower:SetModulations(Modulation)
|
||||||
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -398,8 +469,9 @@ end
|
|||||||
-- @param #number Length Length in nautical miles. Default 15 NM.
|
-- @param #number Length Length in nautical miles. Default 15 NM.
|
||||||
-- @param #number FlightlevelMin Min flight level. Default 5.
|
-- @param #number FlightlevelMin Min flight level. Default 5.
|
||||||
-- @param #number FlightlevelMax Max flight level. Default 15.
|
-- @param #number FlightlevelMax Max flight level. Default 15.
|
||||||
|
-- @param #number Prio Priority. Lower is higher. Default 50.
|
||||||
-- @return #FLIGHTCONTROL.HoldingPattern Holding pattern table.
|
-- @return #FLIGHTCONTROL.HoldingPattern Holding pattern table.
|
||||||
function FLIGHTCONTROL:AddHoldingPattern(ArrivalZone, Heading, Length, FlightlevelMin, FlightlevelMax)
|
function FLIGHTCONTROL:AddHoldingPattern(ArrivalZone, Heading, Length, FlightlevelMin, FlightlevelMax, Prio)
|
||||||
|
|
||||||
-- Get ZONE if passed as string.
|
-- Get ZONE if passed as string.
|
||||||
if type(ArrivalZone)=="string" then
|
if type(ArrivalZone)=="string" then
|
||||||
@@ -410,13 +482,14 @@ function FLIGHTCONTROL:AddHoldingPattern(ArrivalZone, Heading, Length, Flightlev
|
|||||||
self.hpcounter=self.hpcounter+1
|
self.hpcounter=self.hpcounter+1
|
||||||
|
|
||||||
local hp={} --#FLIGHTCONTROL.HoldingPattern
|
local hp={} --#FLIGHTCONTROL.HoldingPattern
|
||||||
hp.arrivalzone=ArrivalZone
|
|
||||||
hp.uid=self.hpcounter
|
hp.uid=self.hpcounter
|
||||||
|
hp.arrivalzone=ArrivalZone
|
||||||
hp.name=string.format("%s-%d", ArrivalZone:GetName(), hp.uid)
|
hp.name=string.format("%s-%d", ArrivalZone:GetName(), hp.uid)
|
||||||
hp.pos0=ArrivalZone:GetCoordinate()
|
hp.pos0=ArrivalZone:GetCoordinate()
|
||||||
hp.pos1=hp.pos0:Translate(UTILS.NMToMeters(Length or 15), Heading)
|
hp.pos1=hp.pos0:Translate(UTILS.NMToMeters(Length or 15), Heading)
|
||||||
hp.angelsmin=FlightlevelMin or 5
|
hp.angelsmin=FlightlevelMin or 5
|
||||||
hp.angelsmax=FlightlevelMax or 15
|
hp.angelsmax=FlightlevelMax or 15
|
||||||
|
hp.prio=Prio or 50
|
||||||
|
|
||||||
hp.stacks={}
|
hp.stacks={}
|
||||||
for i=hp.angelsmin, hp.angelsmax do
|
for i=hp.angelsmin, hp.angelsmax do
|
||||||
@@ -438,6 +511,50 @@ function FLIGHTCONTROL:AddHoldingPattern(ArrivalZone, Heading, Length, Flightlev
|
|||||||
hp.pos0:ArrowToAll(hp.pos1, nil, {1,0,0}, 1, {1,1,0}, 0.5, 2, true)
|
hp.pos0:ArrowToAll(hp.pos1, nil, {1,0,0}, 1, {1,1,0}, 0.5, 2, true)
|
||||||
ArrivalZone:DrawZone()
|
ArrivalZone:DrawZone()
|
||||||
|
|
||||||
|
local function _sort(a,b)
|
||||||
|
return a.prio<b.prio
|
||||||
|
end
|
||||||
|
table.sort(self.holdingpatterns, _sort)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add a holding pattern.
|
||||||
|
-- @param #FLIGHTCONTROL self
|
||||||
|
-- @return #FLIGHTCONTROL.HoldingPattern Holding pattern table.
|
||||||
|
function FLIGHTCONTROL:_AddHoldingPatternBackup()
|
||||||
|
|
||||||
|
local runway=self:GetActiveRunway()
|
||||||
|
|
||||||
|
local heading=runway.heading
|
||||||
|
|
||||||
|
local vec2=self.airbase:GetVec2()
|
||||||
|
|
||||||
|
local Vec2=UTILS.Vec2Translate(vec2, UTILS.NMToMeters(5), heading+90)
|
||||||
|
|
||||||
|
local ArrivalZone=ZONE_RADIUS:New("Arrival Zone", Vec2, 5000)
|
||||||
|
|
||||||
|
-- Add holding pattern with very low priority.
|
||||||
|
self.holdingBackup=self:AddHoldingPattern(ArrivalZone, heading, 15, 5, 25, 999)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove a holding pattern.
|
||||||
|
-- @param #FLIGHTCONTROL self
|
||||||
|
-- @param #FLIGHTCONTROL.HoldingPattern HoldingPattern Holding pattern to be removed.
|
||||||
|
-- @param #FLIGHTCONTROL self
|
||||||
|
function FLIGHTCONTROL:RemoveHoldingPattern(HoldingPattern)
|
||||||
|
|
||||||
|
for i,_holdingpattern in pairs(self.holdingpatterns) do
|
||||||
|
local hp=_holdingpattern --#FLIGHTCONTROL.HoldingPattern
|
||||||
|
|
||||||
|
if hp.uid==HoldingPattern.uid then
|
||||||
|
table.remove(self.holdingpatterns, i)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -470,6 +587,36 @@ function FLIGHTCONTROL:SetParkingGuardStatic(TemplateStaticName)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set ATIS.
|
||||||
|
-- @param #FLIGHTCONTROL self
|
||||||
|
-- @param Ops.Atis#ATIS Atis ATIS.
|
||||||
|
-- @return #FLIGHTCONTROL self
|
||||||
|
function FLIGHTCONTROL:SetATIS(Atis)
|
||||||
|
self.atis=Atis
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get coordinate of the airbase.
|
||||||
|
-- @param #FLIGHTCONTROL self
|
||||||
|
-- @return Core.Point#COORDINATE Coordinate of the airbase.
|
||||||
|
function FLIGHTCONTROL:GetCoordinate()
|
||||||
|
return self.airbase:GetCoordinate()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get coalition of the airbase.
|
||||||
|
-- @param #FLIGHTCONTROL self
|
||||||
|
-- @return #number Coalition ID.
|
||||||
|
function FLIGHTCONTROL:GetCoalition()
|
||||||
|
return self.airbase:GetCoalition()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get country of the airbase.
|
||||||
|
-- @param #FLIGHTCONTROL self
|
||||||
|
-- @return #number Country ID.
|
||||||
|
function FLIGHTCONTROL:GetCountry()
|
||||||
|
return self.airbase:GetCountry()
|
||||||
|
end
|
||||||
|
|
||||||
--- Is flight in queue of this flightcontrol.
|
--- Is flight in queue of this flightcontrol.
|
||||||
-- @param #FLIGHTCONTROL self
|
-- @param #FLIGHTCONTROL self
|
||||||
-- @param Ops.FlightGroup#FLIGHTGROUP Flight Flight group.
|
-- @param Ops.FlightGroup#FLIGHTGROUP Flight Flight group.
|
||||||
@@ -507,6 +654,7 @@ function FLIGHTCONTROL:onafterStart()
|
|||||||
self:HandleEvent(EVENTS.Land)
|
self:HandleEvent(EVENTS.Land)
|
||||||
self:HandleEvent(EVENTS.EngineShutdown)
|
self:HandleEvent(EVENTS.EngineShutdown)
|
||||||
self:HandleEvent(EVENTS.Crash)
|
self:HandleEvent(EVENTS.Crash)
|
||||||
|
self:HandleEvent(EVENTS.Kill)
|
||||||
|
|
||||||
-- Init status updates.
|
-- Init status updates.
|
||||||
self:__Status(-1)
|
self:__Status(-1)
|
||||||
@@ -2036,6 +2184,8 @@ function FLIGHTCONTROL:_PlayerInfoATIS(groupname)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
text=text.." Not defined"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Message to flight
|
-- Message to flight
|
||||||
@@ -2148,7 +2298,7 @@ function FLIGHTCONTROL:_PlayerRequestInbound(groupname)
|
|||||||
|
|
||||||
if dist<UTILS.NMToMeters(50) then
|
if dist<UTILS.NMToMeters(50) then
|
||||||
|
|
||||||
-- Call RTB event. This also sets the flight control and flight status to INBOUND and updates the menu.
|
-- Call RTB event. This only sets the FC for AI.
|
||||||
flight:RTB(self.airbase)
|
flight:RTB(self.airbase)
|
||||||
|
|
||||||
-- Get holding point.
|
-- Get holding point.
|
||||||
@@ -2177,7 +2327,21 @@ function FLIGHTCONTROL:_PlayerRequestInbound(groupname)
|
|||||||
-- Send message.
|
-- Send message.
|
||||||
self:TransmissionTower(text, flight, 15)
|
self:TransmissionTower(text, flight, 15)
|
||||||
|
|
||||||
|
-- Set flightcontrol for this flight. This also updates the menu.
|
||||||
|
flight:SetFlightControl(self)
|
||||||
|
|
||||||
|
-- Add flight to inbound queue.
|
||||||
|
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.INBOUND)
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
-- Message text.
|
||||||
|
local text=string.format("Negative, could not get a holding stack for you! Try again later...")
|
||||||
|
|
||||||
|
-- Send message.
|
||||||
|
self:TextMessageToFlight(text, flight, 10)
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
self:E(self.lid..string.format("WARNING: Could not get holding stack for flight %s", flight:GetName()))
|
self:E(self.lid..string.format("WARNING: Could not get holding stack for flight %s", flight:GetName()))
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3024,11 +3188,12 @@ function FLIGHTCONTROL:_RemoveFlight(Flight)
|
|||||||
flight:_UpdateMenu(0.5)
|
flight:_UpdateMenu(0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
-- Debug message.
|
||||||
self:E(self.lid..string.format("WARNING: Could NOT remove flight group %s from %s queue", flight.groupname, queuename))
|
self:E(self.lid..string.format("WARNING: Could NOT remove flight group %s", Flight.groupname))
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get flight from group.
|
--- Get flight from group.
|
||||||
@@ -3222,22 +3387,6 @@ end
|
|||||||
-- @return #FLIGHTCONTROL.HoldingStack Holding point.
|
-- @return #FLIGHTCONTROL.HoldingStack Holding point.
|
||||||
function FLIGHTCONTROL:_GetHoldingStack(flight)
|
function FLIGHTCONTROL:_GetHoldingStack(flight)
|
||||||
|
|
||||||
--[[
|
|
||||||
local holdingpattern={} --#FLIGHTCONTROL.HoldingPattern
|
|
||||||
|
|
||||||
local runway=self:GetActiveRunway()
|
|
||||||
|
|
||||||
local hdg=runway.heading+90
|
|
||||||
local dx=UTILS.NMToMeters(5)
|
|
||||||
local dz=UTILS.NMToMeters(1)
|
|
||||||
|
|
||||||
local angels=UTILS.FeetToMeters(math.random(6,10)*1000)
|
|
||||||
|
|
||||||
holdingpattern.pos0=runway.position:Translate(dx, hdg):SetAltitude(angels)
|
|
||||||
holdingpattern.pos1=holdingpattern.pos0:Translate(dz, runway.heading):SetAltitude(angels)
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
self:T(self.lid..string.format("Getting holding point for flight %s", flight:GetName()))
|
self:T(self.lid..string.format("Getting holding point for flight %s", flight:GetName()))
|
||||||
|
|
||||||
@@ -3416,27 +3565,6 @@ function FLIGHTCONTROL:RemoveParkingGuard(spot, delay)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get coordinate of the airbase.
|
|
||||||
-- @param #FLIGHTCONTROL self
|
|
||||||
-- @return Core.Point#COORDINATE Coordinate of the airbase.
|
|
||||||
function FLIGHTCONTROL:GetCoordinate()
|
|
||||||
return self.airbase:GetCoordinate()
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get coalition of the airbase.
|
|
||||||
-- @param #FLIGHTCONTROL self
|
|
||||||
-- @return #number Coalition ID.
|
|
||||||
function FLIGHTCONTROL:GetCoalition()
|
|
||||||
return self.airbase:GetCoalition()
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get country of the airbase.
|
|
||||||
-- @param #FLIGHTCONTROL self
|
|
||||||
-- @return #number Country ID.
|
|
||||||
function FLIGHTCONTROL:GetCountry()
|
|
||||||
return self.airbase:GetCountry()
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned.
|
--- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned.
|
||||||
-- @param #FLIGHTCONTROL self
|
-- @param #FLIGHTCONTROL self
|
||||||
-- @param #string unitName Name of the player unit.
|
-- @param #string unitName Name of the player unit.
|
||||||
|
|||||||
@@ -1695,7 +1695,7 @@ function FLIGHTGROUP:onafterParking(From, Event, To)
|
|||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
env.info("FF no flight control!")
|
self:E(self.lid.."ERROR: FF no flight control in onAfterParking!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2328,6 +2328,9 @@ end
|
|||||||
-- @param #number SpeedHold Holding speed in knots.
|
-- @param #number SpeedHold Holding speed in knots.
|
||||||
function FLIGHTGROUP:onbeforeRTB(From, Event, To, airbase, SpeedTo, SpeedHold)
|
function FLIGHTGROUP:onbeforeRTB(From, Event, To, airbase, SpeedTo, SpeedHold)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:T(self.lid..string.format("RTB: before event=%s: %s --> %s to %s", Event, From, To, airbase and airbase:GetName() or "None"))
|
||||||
|
|
||||||
if self:IsAlive() then
|
if self:IsAlive() then
|
||||||
|
|
||||||
local allowed=true
|
local allowed=true
|
||||||
@@ -4296,7 +4299,7 @@ function FLIGHTGROUP:_PlayerMyStatus(groupname)
|
|||||||
local text=string.format("My Status:")
|
local text=string.format("My Status:")
|
||||||
text=text..string.format("\nCallsign: %s", tostring(flight:GetCallsignName()))
|
text=text..string.format("\nCallsign: %s", tostring(flight:GetCallsignName()))
|
||||||
text=text..string.format("\nFlight status: %s", tostring(flight:GetState()))
|
text=text..string.format("\nFlight status: %s", tostring(flight:GetState()))
|
||||||
text=text..string.format("\nFlight control: %s status=%s", tostring(fc and fc.airbasename or "N/A"), tostring(fc and fc:GetFlightStatus(flight) or "N/A"))
|
text=text..string.format("\nFlight control: %s [%s]", tostring(fc and fc.airbasename or "N/A"), tostring(fc and fc:GetFlightStatus(flight) or "N/A"))
|
||||||
|
|
||||||
-- Send message.
|
-- Send message.
|
||||||
--self:TextMessageToFlight(text, flight, 10, true)
|
--self:TextMessageToFlight(text, flight, 10, true)
|
||||||
|
|||||||
@@ -1869,8 +1869,9 @@ function LEGION:GetOpsGroups(MissionTypes, Attributes)
|
|||||||
|
|
||||||
for _,_cohort in pairs(self.cohorts) do
|
for _,_cohort in pairs(self.cohorts) do
|
||||||
local cohort=_cohort --Ops.Cohort#COHORT
|
local cohort=_cohort --Ops.Cohort#COHORT
|
||||||
local setcohort=cohort:GetOpsGroups(MissionTypes, Attributes)
|
local setCohort=cohort:GetOpsGroups(MissionTypes, Attributes)
|
||||||
setLegion:AddSet(setcohort)
|
self:I(self.lid..string.format("Found %d opsgroups of cohort %s", setCohort:Count(), cohort.name))
|
||||||
|
setLegion:AddSet(setCohort)
|
||||||
end
|
end
|
||||||
|
|
||||||
return setLegion
|
return setLegion
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
-- @field #number counterPhase Running number counting the phases.
|
-- @field #number counterPhase Running number counting the phases.
|
||||||
-- @field #OPERATION.Phase phase Currently active phase (if any).
|
-- @field #OPERATION.Phase phase Currently active phase (if any).
|
||||||
-- @field #table targets Targets.
|
-- @field #table targets Targets.
|
||||||
|
-- @field #table missions Missions.
|
||||||
--
|
--
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
@@ -54,6 +55,7 @@ OPERATION = {
|
|||||||
phases = {},
|
phases = {},
|
||||||
counterPhase = 0,
|
counterPhase = 0,
|
||||||
targets = {},
|
targets = {},
|
||||||
|
missions = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Global mission counter.
|
--- Global mission counter.
|
||||||
@@ -136,16 +138,15 @@ function OPERATION:New(Name)
|
|||||||
--- Pseudo Functions ---
|
--- Pseudo Functions ---
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
--- Triggers the FSM event "StatusUpdate".
|
--- Triggers the FSM event "Start".
|
||||||
-- @function [parent=#OPERATION] StatusUpdate
|
-- @function [parent=#OPERATION] Start
|
||||||
-- @param #OPERATION self
|
-- @param #OPERATION self
|
||||||
|
|
||||||
--- Triggers the FSM event "Status" after a delay.
|
--- Triggers the FSM event "Start" after a delay.
|
||||||
-- @function [parent=#OPERATION] __StatusUpdate
|
-- @function [parent=#OPERATION] __Start
|
||||||
-- @param #OPERATION self
|
-- @param #OPERATION self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop".
|
--- Triggers the FSM event "Stop".
|
||||||
-- @function [parent=#OPERATION] Stop
|
-- @function [parent=#OPERATION] Stop
|
||||||
-- @param #OPERATION self
|
-- @param #OPERATION self
|
||||||
@@ -155,6 +156,15 @@ function OPERATION:New(Name)
|
|||||||
-- @param #OPERATION self
|
-- @param #OPERATION self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "StatusUpdate".
|
||||||
|
-- @function [parent=#OPERATION] StatusUpdate
|
||||||
|
-- @param #OPERATION self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Status" after a delay.
|
||||||
|
-- @function [parent=#OPERATION] __StatusUpdate
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "PhaseChange".
|
--- Triggers the FSM event "PhaseChange".
|
||||||
-- @function [parent=#OPERATION] PhaseChange
|
-- @function [parent=#OPERATION] PhaseChange
|
||||||
@@ -243,6 +253,36 @@ function OPERATION:AddPhase(Name)
|
|||||||
return phase
|
return phase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Add mission to operation.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param Ops.Auftrag#AUFTRAG Mission The mission to add.
|
||||||
|
-- @param #OPERATION.Phase Phase (Optional) The phase in which the mission should be executed. If no phase is given, it will be exectuted ASAP.
|
||||||
|
function OPERATION:AddMission(Mission, Phase)
|
||||||
|
|
||||||
|
Mission.phase=Phase
|
||||||
|
Mission.operation=self
|
||||||
|
|
||||||
|
table.insert(self.missions, Mission)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add Target to operation.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param Ops.Target#TARGET Target The target to add.
|
||||||
|
-- @param #OPERATION.Phase Phase (Optional) The phase in which the target should be attacked. If no phase is given, it will be attacked ASAP.
|
||||||
|
function OPERATION:AddTarget(Target, Phase)
|
||||||
|
|
||||||
|
Target.phase=Phase
|
||||||
|
Target.operation=self
|
||||||
|
|
||||||
|
table.insert(self.targets, Target)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Get a phase by its name.
|
--- Get a phase by its name.
|
||||||
-- @param #OPERATION self
|
-- @param #OPERATION self
|
||||||
-- @param #string Name Name of the phase. Default "Phase-01" where the last number is a running number.
|
-- @param #string Name Name of the phase. Default "Phase-01" where the last number is a running number.
|
||||||
@@ -310,6 +350,14 @@ function OPERATION:IsAssignedCohort(Cohort)
|
|||||||
self:T(self.lid..string.format("Cohort %s is assigned to this operation", Cohort.name))
|
self:T(self.lid..string.format("Cohort %s is assigned to this operation", Cohort.name))
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
|
|
||||||
|
-- Check if legion of this cohort was assigned.
|
||||||
|
local Legion=Cohort.legion
|
||||||
|
if Legion and self:IsAssignedLegion(Legion) then
|
||||||
|
self:T(self.lid..string.format("Legion %s of Cohort %s is assigned to this operation", Legion.alias, Cohort.name))
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
self:T(self.lid..string.format("Cohort %s is NOT assigned to this operation", Cohort.name))
|
self:T(self.lid..string.format("Cohort %s is NOT assigned to this operation", Cohort.name))
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -460,6 +508,22 @@ function OPERATION:GetPhaseActive()
|
|||||||
return self.phase
|
return self.phase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get name of a phase.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #OPERATION.Phase Phase The phase of which the name is returned.
|
||||||
|
-- @return #string The name of the phase.
|
||||||
|
function OPERATION:GetPhaseName(Phase)
|
||||||
|
|
||||||
|
Phase=Phase or self.phase
|
||||||
|
|
||||||
|
if Phase then
|
||||||
|
return Phase.name
|
||||||
|
else
|
||||||
|
return "None"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if a phase is the currently active one.
|
--- Check if a phase is the currently active one.
|
||||||
-- @param #OPERATION self
|
-- @param #OPERATION self
|
||||||
-- @param #OPERATION.Phase Phase The phase to check.
|
-- @param #OPERATION.Phase Phase The phase to check.
|
||||||
@@ -509,6 +573,24 @@ function OPERATION:CountPhases(Status)
|
|||||||
return N
|
return N
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Count targets alive.
|
||||||
|
-- @param #OPERATION self
|
||||||
|
-- @param #OPERATION.Phase Phase (Optional) Only count targets set for this phase.
|
||||||
|
-- @return #number Number of phases
|
||||||
|
function OPERATION:CountTargets(Phase)
|
||||||
|
|
||||||
|
local N=0
|
||||||
|
for _,_target in pairs(self.targets) do
|
||||||
|
local target=_target --Ops.Target#TARGET
|
||||||
|
|
||||||
|
if target:IsAlive() and (Phase==nil or target.phase==Phase) then
|
||||||
|
N=N+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return N
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if operation is in FSM state "Planned".
|
--- Check if operation is in FSM state "Planned".
|
||||||
-- @param #OPERATION self
|
-- @param #OPERATION self
|
||||||
-- @return #boolean If `true`, operation is "Planned".
|
-- @return #boolean If `true`, operation is "Planned".
|
||||||
|
|||||||
@@ -4163,6 +4163,17 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
|
|||||||
|
|
||||||
-- Just stay put and wait until something happens.
|
-- Just stay put and wait until something happens.
|
||||||
|
|
||||||
|
elseif Task.dcstask.id==AUFTRAG.SpecialTask.REARMING then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Task "Rearming"
|
||||||
|
---
|
||||||
|
|
||||||
|
-- Check if ammo is full.
|
||||||
|
|
||||||
|
local rearmed=self:_CheckAmmoFull()
|
||||||
|
|
||||||
|
|
||||||
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ALERT5 then
|
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ALERT5 then
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -4485,6 +4496,8 @@ function OPSGROUP:onafterTaskCancel(From, Event, To, Task)
|
|||||||
done=true
|
done=true
|
||||||
elseif Task.dcstask.id==AUFTRAG.SpecialTask.FUELSUPPLY then
|
elseif Task.dcstask.id==AUFTRAG.SpecialTask.FUELSUPPLY then
|
||||||
done=true
|
done=true
|
||||||
|
elseif Task.dcstask.id==AUFTRAG.SpecialTask.REARMING then
|
||||||
|
done=true
|
||||||
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ALERT5 then
|
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ALERT5 then
|
||||||
done=true
|
done=true
|
||||||
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ONGUARD or Task.dcstask.id==AUFTRAG.SpecialTask.ARMOREDGUARD then
|
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ONGUARD or Task.dcstask.id==AUFTRAG.SpecialTask.ARMOREDGUARD then
|
||||||
@@ -4944,7 +4957,12 @@ function OPSGROUP:onbeforeMissionStart(From, Event, To, Mission)
|
|||||||
|
|
||||||
-- Startup group if it is uncontrolled. Alert 5 aircraft will not be started though!
|
-- Startup group if it is uncontrolled. Alert 5 aircraft will not be started though!
|
||||||
if self:IsFlightgroup() and self:IsUncontrolled() and Mission.type~=AUFTRAG.Type.ALERT5 then
|
if self:IsFlightgroup() and self:IsUncontrolled() and Mission.type~=AUFTRAG.Type.ALERT5 then
|
||||||
self:StartUncontrolled(delay)
|
local fc=FLIGHTGROUP.GetFlightControl(self)
|
||||||
|
if fc and fc:IsControlling(self) then
|
||||||
|
FLIGHTGROUP.SetReadyForTakeoff(self, true)
|
||||||
|
else
|
||||||
|
self:StartUncontrolled(delay)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@@ -4972,9 +4990,9 @@ function OPSGROUP:onafterMissionStart(From, Event, To, Mission)
|
|||||||
Mission:__Started(3)
|
Mission:__Started(3)
|
||||||
|
|
||||||
-- Set ready for takeoff in case of FLIGHTCONTROL.
|
-- Set ready for takeoff in case of FLIGHTCONTROL.
|
||||||
if self.isFlightgroup and Mission.type~=AUFTRAG.Type.ALERT5 then
|
--if self.isFlightgroup and Mission.type~=AUFTRAG.Type.ALERT5 then
|
||||||
FLIGHTGROUP.SetReadyForTakeoff(self, true)
|
-- FLIGHTGROUP.SetReadyForTakeoff(self, true)
|
||||||
end
|
--end
|
||||||
|
|
||||||
-- Route group to mission zone.
|
-- Route group to mission zone.
|
||||||
if self.speedMax>3.6 or true then
|
if self.speedMax>3.6 or true then
|
||||||
@@ -5401,6 +5419,7 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
mission.type==AUFTRAG.Type.BARRAGE or
|
mission.type==AUFTRAG.Type.BARRAGE or
|
||||||
mission.type==AUFTRAG.Type.AMMOSUPPLY or
|
mission.type==AUFTRAG.Type.AMMOSUPPLY or
|
||||||
mission.type==AUFTRAG.Type.FUELSUPPLY or
|
mission.type==AUFTRAG.Type.FUELSUPPLY or
|
||||||
|
mission.type==AUFTRAG.Type.REARMING or
|
||||||
mission.type==AUFTRAG.Type.AIRDEFENSE or
|
mission.type==AUFTRAG.Type.AIRDEFENSE or
|
||||||
mission.type==AUFTRAG.Type.EWR then
|
mission.type==AUFTRAG.Type.EWR then
|
||||||
---
|
---
|
||||||
@@ -5540,8 +5559,6 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
|
|
||||||
if inRange then
|
if inRange then
|
||||||
|
|
||||||
env.info("FF in range!")
|
|
||||||
|
|
||||||
waypointcoord=self:GetCoordinate(true)
|
waypointcoord=self:GetCoordinate(true)
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ end
|
|||||||
-- Start & Status
|
-- Start & Status
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--[[
|
||||||
--- On after Start event. Starts the FLIGHTGROUP FSM and event handlers.
|
--- On after Start event. Starts the FLIGHTGROUP FSM and event handlers.
|
||||||
-- @param #PLATOON self
|
-- @param #PLATOON self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
@@ -114,6 +115,7 @@ function PLATOON:onafterStart(From, Event, To)
|
|||||||
-- Start the status monitoring.
|
-- Start the status monitoring.
|
||||||
self:__Status(-1)
|
self:__Status(-1)
|
||||||
end
|
end
|
||||||
|
]]
|
||||||
|
|
||||||
--- On after "Status" event.
|
--- On after "Status" event.
|
||||||
-- @param #PLATOON self
|
-- @param #PLATOON self
|
||||||
|
|||||||
Reference in New Issue
Block a user