This commit is contained in:
Frank
2020-02-20 12:31:42 +01:00
parent 02c63850a1
commit 7d697dc584
2 changed files with 308 additions and 129 deletions
+148 -108
View File
@@ -124,8 +124,6 @@ function AIRWING:New(warehousename, airwingname)
-- Add FSM transitions.
-- From State --> Event --> To State
self:AddTransition("*", "AirwingStatus", "*") -- AIRWING status update.
self:AddTransition("*", "MissionNew", "*") -- Add a new mission.
self:AddTransition("*", "MissionRequest", "*") -- Add a (mission) request to the warehouse.
@@ -150,14 +148,6 @@ function AIRWING:New(warehousename, airwingname)
-- @param #AIRWING self
-- @param #number delay Delay in seconds.
--- Triggers the FSM event "AirwingStatus".
-- @function [parent=#AIRWING] AirwingStatus
-- @param #AIRWING self
--- Triggers the FSM event "AirwingStatus" after a delay.
-- @function [parent=#AIRWING] __AirwingStatus
-- @param #AIRWING self
-- @param #number delay Delay in seconds.
-- Debug trace.
if false then
@@ -266,7 +256,7 @@ function AIRWING:AddAssetToSquadron(SquadronName, Group, Ngroups)
local text=string.format("FF Adding asset %s to squadron %s", Group:GetName(), squadron.name)
env.info(text)
self:AddAsset(Group, Ngroups, nil, nil, nil, nil, AI.Skill.EXCELLENT, squadron.livery, squadron.name)
self:AddAsset(Group, Ngroups, nil, nil, nil, nil, squadron.skill, squadron.livery, squadron.name)
else
self:E("ERROR: Group does not exist!")
@@ -282,92 +272,12 @@ end
--- Get squadron by name.
-- @param #AIRWING self
-- @param #string SquadronName Name of the squadron, e.g. "VFA-37".
-- @return #AIRWING self or nil.
-- @return #AIRWING.Squadron Squadron table.
function AIRWING:GetSquadron(SquadronName)
return self.squadrons[SquadronName]
end
--- Check if there is a squadron that can execute a given mission type. Optionally, the number of required assets can be specified.
-- @param #AIRWING self
-- @param #AIRWING.Squadron Squadron The Squadron.
-- @param #string MissionType Type of mission.
-- @param #number Nassets Number of required assets for the mission. Use *nil* or 0 for none. Then only the general capability is checked.
-- @return #boolean If true, Squadron can do that type of mission. Available assets are not checked.
-- @return #table Assets that can do the required mission.
function AIRWING:SquadronCanMission(Squadron, MissionType, Nassets)
local cando=true
local assets={}
local gotit=false
for _,canmission in pairs(Squadron.missiontypes) do
if canmission==MissionType then
gotit=true
break
end
end
if not gotit then
-- This squad cannot do this mission.
cando=false
else
for _,_asset in pairs(Squadron.assets) do
local asset=_asset --#AIRWING.SquadronAsset
-- Check if has already a mission assigned.
if asset.mission==nil then
table.insert(assets, asset)
end
end
end
-- Check if required assets are present.
if Nassets and Nassets > #assets then
cando=false
end
return cando, assets
end
--- Check if assets for a given mission type are available.
-- @param #AIRWING self
-- @param #string MissionType Type of mission.
-- @param #number Nassets Amount of assets required for the mission. Default 1.
-- @return #boolean If true, enough assets are available.
-- @return #table Assets that can do the required mission.
function AIRWING:CanMission(MissionType, Nassets)
-- Assume we CANNOT and NO assets are available.
local Can=false
local Assets={}
for squadname,_squadron in pairs(self.squadrons) do
local squadron=_squadron --#AIRWING.Squadron
-- Check if this squadron can.
local can, assets=self:SquadronCanMission(squadron, MissionType, Nassets)
-- Debug output.
local text=string.format("Mission=%s, squadron=%s, can=%s, assets=%d/%d", MissionType, squadron.name, tostring(can), #assets, Nassets)
self:I(self.lid..text)
-- If anyone can, we Can.
if can then
Can=true
end
-- Total number.
for _,asset in pairs(assets) do
table.insert(Assets, asset)
end
end
return Can, Assets
end
--- Create a CAP mission.
-- @param #AIRWING self
@@ -430,12 +340,15 @@ function AIRWING:onafterStart(From, Event, To)
end
-- Init status updates.
self:__AirwingStatus(-1)
--self:__AirwingStatus(-1)
end
--- Update status.
-- @param #AIRWING self
function AIRWING:onafterAirwingStatus(From, Event, To)
function AIRWING:onafterStatus(From, Event, To)
-- Status of parent Warehouse.
self:GetParent(self).onafterStatus(self, From, Event, To)
local fsmstate=self:GetState()
@@ -486,7 +399,7 @@ function AIRWING:onafterAirwingStatus(From, Event, To)
self:MissionRequest(mission)
end
self:__AirwingStatus(-30)
--self:__AirwingStatus(-30)
end
--- Get next mission.
@@ -652,19 +565,7 @@ function AIRWING:onafterAssetSpawned(From, Event, To, group, asset, request)
-- Set mission.
asset.mission=self:GetMissionByID(mid)
-- Create flightgroup.
local flightgroup=FLIGHTGROUP:New(group:GetName())
asset.flightgroup=flightgroup
flightgroup:SetAirwing(self)
-- Add mission to flightgroup queue.
if asset.mission then
local Cstart=UTILS.SecondsToClock(asset.mission.Tstart)
local Cstop=asset.mission.Tstop and UTILS.SecondsToClock(asset.mission.Tstop) or nil
asset.flightgroup:AddMission(asset.mission, asset.mission.zone, asset.mission.waypoint, Cstart, Cstop, asset.mission.name)
end
end
@@ -701,6 +602,145 @@ end
-- Misc Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a new flight group after an asset was spawned.
-- @param #AIRWING self
-- @param Wrapper.Group#GROUP group The group.
-- @param #AIRWING.SquadronAsset asset The asset.
function AIRWING:_CreateFlightGroup(group, asset)
-- Create flightgroup.
local flightgroup=FLIGHTGROUP:New(group:GetName())
asset.flightgroup=flightgroup
flightgroup:SetAirwing(self)
--- Check if out of missiles. For A2A missions ==> RTB.
function flightgroup:OnAfterOutOfMissiles()
local airwing=self:GetAirWing()
end
--- Check if out of missiles. For A2G missions ==> RTB. But need to check A2G missiles, rockets as well.
function flightgroup:OnAfterOutOfBombs()
local airwing=self:GetAirWing()
end
--- Mission started.
function flightgroup:OnAfterMissionStart(From, Event, To, Mission)
local airwing=self:GetAirWing()
-- TODO: Add event? Set mission status!
--airwing:MissionStart(Mission)
end
--- Flight is DEAD.
function flightgroup:OnAfterFlightDead(From, Event, To)
local airwing=self:GetAirWing()
-- TODO
-- Mission failed ==> launch new mission?
end
-- Add mission to flightgroup queue.
if asset.mission then
local Cstart=UTILS.SecondsToClock(asset.mission.Tstart)
local Cstop=asset.mission.Tstop and UTILS.SecondsToClock(asset.mission.Tstop) or nil
asset.flightgroup:AddMission(asset.mission, asset.mission.zone, asset.mission.waypoint, Cstart, Cstop, asset.mission.name)
end
end
--- Check if there is a squadron that can execute a given mission type. Optionally, the number of required assets can be specified.
-- @param #AIRWING self
-- @param #AIRWING.Squadron Squadron The Squadron.
-- @param #string MissionType Type of mission.
-- @param #number Nassets Number of required assets for the mission. Use *nil* or 0 for none. Then only the general capability is checked.
-- @return #boolean If true, Squadron can do that type of mission. Available assets are not checked.
-- @return #table Assets that can do the required mission.
function AIRWING:SquadronCanMission(Squadron, MissionType, Nassets)
local cando=true
local assets={}
local gotit=false
for _,canmission in pairs(Squadron.missiontypes) do
if canmission==MissionType then
gotit=true
break
end
end
if not gotit then
-- This squad cannot do this mission.
cando=false
else
for _,_asset in pairs(Squadron.assets) do
local asset=_asset --#AIRWING.SquadronAsset
-- Check if has already a mission assigned.
if asset.mission==nil then
table.insert(assets, asset)
end
end
end
-- Check if required assets are present.
if Nassets and Nassets > #assets then
cando=false
end
return cando, assets
end
--- Check if assets for a given mission type are available.
-- @param #AIRWING self
-- @param #string MissionType Type of mission.
-- @param #number Nassets Amount of assets required for the mission. Default 1.
-- @return #boolean If true, enough assets are available.
-- @return #table Assets that can do the required mission.
function AIRWING:CanMission(MissionType, Nassets)
-- Assume we CANNOT and NO assets are available.
local Can=false
local Assets={}
for squadname,_squadron in pairs(self.squadrons) do
local squadron=_squadron --#AIRWING.Squadron
-- Check if this squadron can.
local can, assets=self:SquadronCanMission(squadron, MissionType, Nassets)
-- Debug output.
local text=string.format("Mission=%s, squadron=%s, can=%s, assets=%d/%d", MissionType, squadron.name, tostring(can), #assets, Nassets)
self:I(self.lid..text)
-- If anyone can, we Can.
if can then
Can=true
end
-- Total number.
for _,asset in pairs(assets) do
table.insert(Assets, asset)
end
end
return Can, Assets
end
--- Returns the mission for a given mission ID (MID).
-- @param #AIRWING self
-- @param #number mid Mission ID.
+160 -21
View File
@@ -125,6 +125,14 @@
--
-- ## Waypoint Tasks
--
-- # Missions
--
-- ## Anti-ship
--
-- ## AWACS
--
-- ## INTERCEPT
--
--
-- # Examples
--
@@ -196,8 +204,7 @@ FLIGHTGROUP = {
checkzones = nil,
inzones = nil,
groupinitialized = nil,
beacon = nil,
beacon = nil,
}
@@ -305,30 +312,37 @@ FLIGHTGROUP.TaskType={
--- Mission types.
-- @type FLIGHTGROUP.MissionType
-- @param #string INTERCEPT Intercept.
-- @param #string CAP Combat Air Patrol.
-- @param #string ANTISHIP Anti-ship mission.
-- @param #string AWACS AWACS mission.
-- @param #string BAI Battlefield Air Interdiction.
-- @param #string BOMBING Bombing mission.
-- @param #string CAP Combat Air Patrol.
-- @param #string CAS Close Air Support.
-- @param #string ESCORT Escort mission.
-- @param #string FACA Forward AirController airborne mission.
-- @param #string FERRY Ferry flight mission.
-- @param #string INTERCEPT Intercept mission.
-- @param #string RECON Recon mission.
-- @param #string SEAD Suppression/destruction of enemy air defences.
-- @param #string STRIKE Strike mission.
-- @param #string AWACS AWACS mission.
-- @param #string TANKER Tanker mission.
-- @param #string RECON Recon mission.
-- @param #string TRANSPORT Transport mission.
-- @param #string FERRY Ferry flight mission.
-- @param #string ANTISHIP Anti-ship mission.
FLIGHTGROUP.MissionType={
INTERCEPT="Intercept",
CAP="CAP",
ANTISHIP="Anti Ship",
AWACS="AWACS",
BAI="BAI",
BOMBING="Bombing",
CAP="CAP",
CAS="CAS",
ESCORT="Escort",
FACA="FAC-A",
FERRY="Ferry Flight",
INTERCEPT="Intercept",
RECON="Recon",
SEAD="SEAD",
STRIKE="Strike",
CAS="CAS",
AWACS="AWACS",
TANKER="Tanker",
RECON="Recon",
TRANSPORT="Transport",
FERRY="Ferry Flight",
ANTISHIP="Anti Ship"
}
--- Mission status.
@@ -469,15 +483,17 @@ function FLIGHTGROUP:New(groupname, autostart)
self:AddTransition("*", "OutOfRockets", "*") -- Group is out of rockets.
self:AddTransition("*", "OutOfBombs", "*") -- Group is out of bombs.
self:AddTransition("*", "OutOfMissiles", "*") -- Group is out of missiles.
self:AddTransition("*", "OutOfMissilesA2A", "*") -- Group is out of A2A missiles.
self:AddTransition("*", "OutOfMissilesA2G", "*") -- Group is out of A2G missiles.
self:AddTransition("*", "TaskExecute", "*") -- Group will execute a task.
self:AddTransition("*", "TaskDone", "*") -- Group finished a task.
self:AddTransition("*", "TaskCancel", "*") -- Cancel current task.
self:AddTransition("*", "TaskPause", "*") -- Pause current task.
self:AddTransition("*", "MissionStart", "OnMission") -- Tanker is on station and ready to refuel.
self:AddTransition("OnMission", "MissionDone", "Airborne") -- Tanker is on station and ready to refuel.
self:AddTransition("OnMission", "MissionAbort", "Airborne") -- Tanker is on station and ready to refuel.
self:AddTransition("*", "MissionStart", "OnMission") -- Tanker is on station and ready to refuel.
self:AddTransition("OnMission", "MissionDone", "Airborne") -- Tanker is on station and ready to refuel.
self:AddTransition("OnMission", "MissionAbort", "Airborne") -- Tanker is on station and ready to refuel.
self:AddTransition("*", "ElementSpawned", "*") -- An element was spawned.
self:AddTransition("*", "ElementParking", "*") -- An element is parking.
@@ -1141,6 +1157,33 @@ function FLIGHTGROUP:CreateMissionCAP(Altitude, SpeedOrbit, Heading, Leg)
return mission
end
--- Create an INTERCEPT mission.
-- @param #FLIGHTGROUP self
-- @param Core.Set#SET_GROUP TargetGroupSet The set of target groups to intercept.
function FLIGHTGROUP:CreateMissionINTERCEPT(TargetGroupSet)
local mission={} --#FLIGHTGROUP.MissionINTERCEPT
mission.type=FLIGHTGROUP.MissionType.INTERCEPT
mission.targetgroups=TargetGroupSet
return mission
end
--- Create an INTERCEPT mission.
-- @param #FLIGHTGROUP self
-- @param Core.Set#SET_GROUP TargetGroupSet The set of target groups to intercept.
function FLIGHTGROUP:CreateMissionINTERCEPT(TargetGroupSet)
local mission={} --#FLIGHTGROUP.MissionINTERCEPT
mission.type=FLIGHTGROUP.MissionType.INTERCEPT
mission.targetgroups=TargetGroupSet
return mission
end
--- Add mission to queue.
-- @param #FLIGHTGROUP self
-- @param #FLIGHTGROUP.Mission Mission Mission for this group.
@@ -1191,7 +1234,33 @@ function FLIGHTGROUP:AddMission(Mission, Zone, WaypointIndex, ClockStart, ClockS
mission.task=nil
mission.waypoint=WaypointIndex
if mission.type==FLIGHTGROUP.MissionType.CAP then
if mission.type==FLIGHTGROUP.MissionType.ANTISHIP then
----------------------
-- ANTISHIP Mission --
----------------------
mission.DCStask=CONTROLLABLE.TaskAttackUnit(self.group, AttackUnit, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType)
elseif mission.type==FLIGHTGROUP.MissionType.AWACS then
-------------------
-- AWACS Mission --
-------------------
elseif mission.type==FLIGHTGROUP.MissionType.BAI then
-----------------
-- BAI Mission --
-----------------
mission.DCStask=CONTROLLABLE.TaskAttackGroup(self.group, TargetGroup, ENUMS.WeaponFlag.Auto, WeaponExpend,AttackQty,Direction,Altitude,AttackQtyLimit)
elseif mission.type==FLIGHTGROUP.MissionType.CAP then
-----------------
-- CAP Mission --
-----------------
local Coord=mission.zone:GetRandomCoordinate()
@@ -1199,7 +1268,73 @@ function FLIGHTGROUP:AddMission(Mission, Zone, WaypointIndex, ClockStart, ClockS
mission.DCStask=CONTROLLABLE.TaskOrbit(self.group, Coord, mission.altitude, mission.speed, CoordRaceTrack)
mission.name=Name or string.format("CAP mission ID%03d", mission.mid)
mission.name=Name or string.format("CAP mission ID%03d", mission.mid)
elseif mission.type==FLIGHTGROUP.MissionType.CAS then
-----------------
-- CAS Mission --
-----------------
local Coord=mission.zone:GetRandomCoordinate()
local CoordRaceTrack=Coord:Translate(mission.leg, mission.heading, true)
mission.DCStask=CONTROLLABLE.TaskOrbit(self.group, Coord, mission.altitude, mission.speed, CoordRaceTrack)
self:AddTaskEnrouteEngageTargetsInZone(mission.zone, mission.targettypes, mission.prio)
elseif mission.type==FLIGHTGROUP.MissionType.ESCORT then
--------------------
-- ESCORT Mission --
--------------------
mission.DCStask=CONTROLLABLE.TaskEscort(self.group, FollowControllable, Vec3, LastWaypointIndex, EngagementDistance, TargetTypes)
elseif mission.type==FLIGHTGROUP.MissionType.FACA then
-----------------
-- FAC Mission --
-----------------
mission.DCStask=CONTROLLABLE.TaskFAC_AttackGroup(self.group, AttackGroup, WeaponType, Designation, Datalink)
elseif mission.type==FLIGHTGROUP.MissionType.FERRY then
-------------------
-- FERRY Mission --
-------------------
elseif mission.type==FLIGHTGROUP.MissionType.INTERCEPT then
-----------------------
-- INTERCEPT Mission --
-----------------------
mission.DCStask=CONTROLLABLE.TaskAttackGroup(self.group, TargetGroup, ENUMS.WeaponFlag.Auto, WeaponExpend,AttackQty,Direction,Altitude,AttackQtyLimit)
elseif mission.type==FLIGHTGROUP.MissionType.RECON then
-------------------
-- RECON Mission --
-------------------
elseif mission.type==FLIGHTGROUP.MissionType.STRIKE then
-------------------
-- STIKE Mission --
-------------------
mission.DCStask=CONTROLLABLE.TaskAttackMapObject(self.group, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType)
elseif mission.type==FLIGHTGROUP.MissionType.TANKER then
--------------------
-- TANKER Mission --
--------------------
elseif mission.type==FLIGHTGROUP.MissionType.TRANSPORT then
end
@@ -2904,7 +3039,11 @@ function FLIGHTGROUP:onafterTaskDone(From, Event, To, Task)
-- Task status done.
Task.status=FLIGHTGROUP.TaskStatus.ACCOMPLISHED
-- Update route. This is necessary because of the route task beeing overwritten. But we want to fly to the remaining waypoints.
if self.currentmission and self.currentmission.task and self.currentmission.task then
end
-- Update route. This is necessary because of the route task being overwritten. But we want to fly to the remaining waypoints.
self:__UpdateRoute(-1)
end