This commit is contained in:
Frank
2020-02-14 16:51:49 +01:00
parent 0da53c794e
commit 2e49b72ab4
5 changed files with 389 additions and 230 deletions
+130 -196
View File
@@ -15,10 +15,12 @@
-- @type AIRWING
-- @field #string ClassName Name of the class.
-- @field #boolean Debug Debug mode. Messages to all about status.
-- @field #string sid Class id string for output to DCS log file.
-- @field #string carriername The name of the carrier unit.
-- @field #string wid Class id string for output to DCS log file.
-- @field #string warehousename The name of the warehouse unit/static.
-- @field #table menu Table of menu items.
-- @field #table squadrons Table of squadrons.
-- @field #table missionqueue Mission queue table.
-- @field #table missioncounter Running index counting the added missions.
-- @extends Functional.Warehouse#WAREHOUSE
--- Be surprised!
@@ -34,57 +36,49 @@
-- @field #AIRWING
AIRWING = {
ClassName = "AIRWING",
sid = nil,
carriername = nil,
wid = nil,
warehousename = nil,
menu = nil,
squadrons = nil,
taskqueue = {},
missionqueue = {},
missioncounter = nil,
}
--- Squadron data.
-- @type AIRWING.Squadron
-- @field #string name Name of the squadron.
-- @field #table assets Assets of the squadron.
-- @field #table tasks Task(s) of the squadron.
-- @field #table capabilities Mission types that the squadron can do.
-- @field #string livery Livery of the squadron.
-- @field DCS#Coalition.Side coalition Coalition side.
-- @field #number threadlevel Thread level of intruder.
-- @field #string threadtext Thread text.
-- @field #number category Group category.
-- @field #string categoryname Group category name.
-- @field #string typename Type name of group.
-- @field #table menu The squadron menu entries.
--- Squadron asset.
-- @type AIRWING.SquadronAsset
-- @field #boolean assigned Assigned to mission.
-- @field #AIRWING.Missiondata mission The assigned mission.
-- @field Ops.FlightGroup#FLIGHTGROUP flightgroup The flightgroup object.
-- @extends Functional.Warehouse#WAREHOUSE.Assetitem
--- Mission types.
-- @type AIRWING.MissionType
-- @extends Ops.FlightGroup#FLIGHTGROUP.MissionType
--- Mission data.
-- @type AIRWING.Mission
-- @field #string type Mission type.
-- @type AIRWING.Missiondata
-- @field #string squadname Name of the assigned squadron.
-- @field #number nassets Number of required assets.
-- @field #string status Mission status.
-- @extends Ops.FlightGroup#FLIGHTGROUP.Mission
--- AIRWING class version.
-- @field #string version
AIRWING.version="0.0.5"
AIRWING.version="0.1.0"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Add squadrons to warehouse.
-- DONE: Add squadrons to warehouse.
-- TODO: Make special request to transfer squadrons to anther airwing (or warehouse).
-- TODO: Build mission queue.
-- TODO: Find way to start missions.
-- TODO: Check if missions are accomplished.
-- TODO: Paylods as assets.
-- TODO: Cargo as assets.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
@@ -111,7 +105,7 @@ function AIRWING:New(warehousename, airwingname)
-- Set some string id for output to DCS.log file.
self.sid=string.format("AIRWING %s |", airwingname)
self.wid=string.format("AIRWING %s |", airwingname)
-- Add FSM transitions.
-- From State --> Event --> To State
@@ -119,10 +113,7 @@ function AIRWING:New(warehousename, airwingname)
self:AddTransition("*", "AddMission", "*") -- Add a new mission.
self:AddTransition("*", "RequestCAP", "*") -- Request CAP flight.
self:AddTransition("*", "RequestIntercept", "*") -- Request Intercept.
self:AddTransition("*", "RequestCAS", "*") -- Request CAS.
self:AddTransition("*", "RequestSEAD", "*") -- Request SEAD.
self:AddTransition("*", "RequestMission", "*") -- Request CAP flight.
------------------------
--- Pseudo Functions ---
@@ -154,18 +145,6 @@ function AIRWING:New(warehousename, airwingname)
-- @param #AIRWING self
-- @param #number delay Delay in seconds.
--- Triggers the FSM event "RequestCAP".
-- @function [parent=#AIRWING] RequestCAP
-- @param #AIRWING self
-- @param Core.Point#COORDINATE coordinate
-- @param #number altitude Altitude
-- @param #number leg Race track length.
-- @param #number heading Heading in degrees.
-- @param #number speed Speed in knots.
-- @param #AIRWING.Squadron squadron Explicitly request a specific squadron.
-- Debug trace.
if true then
self.Debug=true
@@ -245,11 +224,11 @@ 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.Squaron Squadron The Squadron.
-- @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 #number Number of available assets.
-- @return #number Number of available assets that dont have a mission assigned.
function AIRWING:SquadronCanMission(Squadron, MissionType, Nassets)
local cando=false
@@ -272,12 +251,12 @@ function AIRWING:SquadronCanMission(Squadron, MissionType, Nassets)
for _,_asset in pairs(Squadron.assets) do
local asset=_asset --#AIRWING.SquadronAsset
-- TODO: Check if on mission etc.
if not asset.spawned then
-- Check if has already a mission assigned.
if asset.mission==nil then
n=n+1
end
end
end
end
@@ -322,6 +301,49 @@ function AIRWING:CanMission(MissionType, Nassets)
return Can, N
end
--- Create a CAP mission.
-- @param #AIRWING self
-- @param #number Altitude Orbit altitude in feet. Default 10000 ft.
-- @param #number SpeedOrbit Orbit speed in knots. Default 350 kts.
-- @param #number Heading Heading in degrees. Default 270° (East to West).
-- @param #number Leg Length of race-track in NM. Default 10 NM.
-- @return #AIRWING.MissionCAP The CAP mission table.
function AIRWING:CreateMissionCAP(Altitude, SpeedOrbit, Heading, Leg)
local mission={} --#AIRWING.Missiondata
mission.type=FLIGHTGROUP.MissionType.CAP
mission.altitude=UTILS.FeetToMeters(Altitude or 10000)
mission.speedOrbit=UTILS.KnotsToMps(SpeedOrbit or 350)
mission.heading=Heading or 270
mission.leg=UTILS.NMToMeters(Leg or 10)
mission.waypoint=1
return mission
end
--- Add mission to queue.
-- @param #AIRWING self
-- @param AIRWING.Missiondata Mission for this group.
-- @param Core.Zone#ZONE Zone The mission zone.
-- @param #number WaypointIndex The waypoint index.
-- @param #string ClockStart Time the mission is started, e.g. "05:00" for 5 am. If specified as a #number, it will be relative (in seconds) to the current mission time. Default is 5 seconds after mission was added.
-- @param #string ClockStop Time the mission is stopped, e.g. "13:00" for 1 pm. If mission could not be started at that time, it will be removed from the queue. If specified as a #number it will be relative (in seconds) to the current mission time.
-- @param #number Prio Priority of the mission, i.e. a number between 1 and 100. Default 50.
-- @param #string Name Mission name. Default "Aerial Refueling #00X", where "#00X" is a running mission counter index starting at "#001".
-- @return #AIRWING.Missiondata The mission table.
function AIRWING:AddMission(Mission, Zone, WaypointIndex, ClockStart, ClockStop, Prio, Name)
-- TODO: need to check that this call increases the correct mission counter and adds it to the mission queue.
local mission=FLIGHTGROUP.AddMission(self, Zone, WaypointIndex, ClockStart, ClockStop, Prio, Name, Mission)
-- Mission needs the correct MID.
mission.MID=self.missioncounter
return mission
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Start & Status
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -334,7 +356,7 @@ function AIRWING:onafterStart(From, Event, To)
self:GetParent(self).onafterStart(self, From, Event, To)
-- Info.
self:I(self.sid..string.format("Starting AIRWING v%s %s (%s)", AIRWING.version, self.alias, self.warehousename))
self:I(self.wid..string.format("Starting AIRWING v%s %s (%s)", AIRWING.version, self.alias, self.warehousename))
-- Add F10 radio menu.
self:_SetMenuCoalition()
@@ -356,7 +378,7 @@ function AIRWING:onafterAirwingStatus(From, Event, To)
-- Info text.
local text=string.format("State %s", fsmstate)
self:I(self.sid..text)
self:I(self.wid..text)
local text="Squadrons:"
for i,_squadron in pairs(self.squadrons) do
@@ -387,16 +409,18 @@ function AIRWING:onafterAirwingStatus(From, Event, To)
end
end
self:I(self.sid..text)
self:I(self.wid..text)
--------------
-- Mission ---
--------------
-- Get next mission.
local mission=self:_GetNextMission()
-- Request mission execution.
if mission then
if mission.type==AIRWING.MissionType.CAP then
self:RequestCAP(coordinate,altitude,leg,heading,speed,squadron)
end
self:RequestMission(mission)
end
self:__AirwingStatus(-30)
@@ -408,7 +432,7 @@ end
function AIRWING:_GetNextMission()
-- Number of missions.
local Nmissions=#self.Qmissions
local Nmissions=#self.missionqueue
-- Treat special cases.
if Nmissions==0 then
@@ -419,16 +443,17 @@ function AIRWING:_GetNextMission()
local function _sort(a, b)
local taskA=a --#AIRWING.Mission
local taskB=b --#AIRWING.Mission
--TODO: probably sort by prio first and then by time as only missions for T>Tstart are executed. That would ensure that the highest prio mission is carried ot first!
return (taskA.Tstart<taskB.Tstart) or (taskA.Tstart==taskB.Tstart and taskA.prio<taskB.prio)
end
table.sort(self.Qmissions, _sort)
table.sort(self.missionqueue, _sort)
-- Current time.
local time=timer.getAbsTime()
-- Look for first task that is not accomplished.
for _,_mission in pairs(self.Qmissions) do
local mission=_mission --#AIRWING.Mission
for _,_mission in pairs(self.missionqueue) do
local mission=_mission --#AIRWING.Missiondata
-- Check that mission is still scheduled, time has passed and enough assets are available.
if mission.status==AIRWING.MissionStatus.SCHEDULED and time>=mission.Tstart and self:CanMission(mission.type, mission.nassets) then
@@ -498,10 +523,49 @@ end
function AIRWING:onafterAddMission(From, Event, To, Mission)
-- Add Mission to queue.
table.insert(self.Qmission, Mission)
table.insert(self.missionqueue, Mission)
end
--- On after "RequestMission" event.
-- @param #AIRWING self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #AIRWING.Missiondata Mission The requested mission.
function AIRWING:onafterRequestMission(From, Event, To, Mission)
--TODO: request descriptor/attribute for given mission type! AWACS, Tankers, Fighters.
--TODO: also check that mission prio is same as warehouse prio (small=high or the other way around).
self:AddRequest(self, WAREHOUSE.Descriptor.ATTRIBUTE, GROUP.Attribute.AIR_FIGHTER, Mission.nassets, nil, nil, Mission.prio, tostring(Mission.mid))
end
--- On after "AssetSpawned" event triggered when an asset group is spawned into the cruel world.
-- @param #AIRWING self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Wrapper.Group#GROUP group The group spawned.
-- @param #AIRWING.SquadronAsset asset The asset that was spawned.
-- @param Functional.Warehouse#WAREHOUSE.Pendingitem request The request of the dead asset.
function AIRWING:onafterAssetSpawned(From, Event, To, group, asset, request)
-- Call parent warehouse function first.
self:GetParent(self).onafterAssetSpawned(self, From, Event, To, group, asset, request)
local mid=tonumber(request.assignment)
-- Set mission.
asset.mission=self:GetMissionByID(mid)
-- Create flightgroup.
asset.flightgroup=FLIGHTGROUP:New(group:GetName())
-- Add mission to flightgroup queue.
asset.flightgroup:AddMission(asset.mission)
end
--- On after "SelfRequest" event.
-- @param #AIRWING self
@@ -514,83 +578,24 @@ function AIRWING:onafterSelfRequest(From, Event, To, groupset, request)
-- Call parent warehouse function first.
self:GetParent(self).onafterSelfRequest(self, From, Event, To, groupset, request)
local mid=tonumber(request.assignment)
local mission=self:GetMissionByID(mid)
for _,_asset in pairs(request.assets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
local a=asset.cargobay
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
end
if request.assignment==AIRWING.Task.CAP then
for _,_group in pairs(groupset:GetSet()) do
local group=_group --Wrapper.Group#GROUP
for _,_group in pairs(groupset:GetSet()) do
local group=_group --Wrapper.Group#GROUP
local fg=FLIGHTGROUP:New(group:GetName())
fg:AddMission(request.mission)
--self:LaunchCAP(group, coordinate, altitude, leg, speed, heading)
end
end
end
--- Request CAP.
-- @param #AIRWING self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE coordinate
-- @param #number altitude Altitude
-- @param #number leg Race track length.
-- @param #number heading Heading in degrees.
-- @param #number speed Speed in knots.
-- @param #AIRWING.Squadron squadron Explicitly request a specific squadron.
function AIRWING:onafterRequestCAP(From, Event, To, coordinate, altitude, leg, heading, speed, squadron)
local n=self:GetNumberOfAssets(WAREHOUSE.Descriptor.ASSIGNMENT, squadron.name, false)
if n>0 then
self:AddRequest(self, WAREHOUSE.Descriptor.ASSIGNMENT, squadron.name, 1, nil, nil, nil, AIRWING.Task.CAP)
else
MESSAGE:New("No CAP planes currently available", 5, "AIRWING"):ToCoalition(self:GetCoalition())
self:__RequestCAP(-30, coordinate, altitude, leg, heading, speed, squadron)
end
end
--- Launch a CAP flight.
-- @param #AIRWING self
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup Flight group.
-- @param Core.Point#COORDINATE capcoord Coordinate of CAP.
-- @param #number alt Altitude in feet. Default 20000 ft.
-- @param #number leg Length of race track pattern leg. Default 15 NM.
-- @param #number heading Heading of race track in degrees. Default 180° i.e. from North to South.
-- @param #number speed Speed in knots.
function AIRWING:LaunchCAP(flightgroup, capcoord, alt, leg, heading, speed)
alt=UTILS.FeetToMeters(alt or 20000)
speed=speed or 350
leg=leg or 15
-- Task orbit.
local taskOrbit=flightgroup.group:TaskOrbit(capcoord, alt, UTILS.KnotsToMps(speed+50), capcoord:Translate(UTILS.NMToMeters(leg), heading))
flightgroup:AddWaypointAir(capcoord, 2, speed)
flightgroup:AddTaskWaypoint(taskOrbit, 2, "Orbit", 50, 60*60)
--TODO: flightcontrol would start up the aircraft.
flightgroup:StartUncontrolled(5)
end
--- Create a new task name.
-- @param #AIRWING self
-- @param #string task Task of type @{#AIRWING.Task}.
@@ -604,77 +609,6 @@ function AIRWING:_NewTaskName(task)
return taskname
end
--- Request Intercept.
-- @param #AIRWING self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Wrapper.Group#GROUP bandits Group of bandits to intercept.
-- @param #AIRWING.Squadron squadron Explicitly request a specific squadron.
function AIRWING:onafterRequestIntercept(From, Event, To, bandits, squadron)
local n=self:GetNumberOfAssets(WAREHOUSE.Descriptor.ASSIGNMENT, squadron.name, false)
if n>0 then
self:__AddRequest(1, self, WAREHOUSE.Descriptor.ASSIGNMENT, squadron.name, 1, nil, nil, nil, AIRWING.Task.INTERCEPT)
function self:OnAfterSelfRequest(From,Event,To,Groupset,Request)
local request=Request --Functional.Warehouse#WAREHOUSE.Pendingitem
local groupset=Groupset --Core.Set#SET_GROUP
if Request.assignment==AIRWING.Task.INTERCEPT then
for _,_group in pairs(groupset:GetSet()) do
local group=_group --Wrapper.Group#GROUP
self:LaunchIntercept(group)
end
end
end
else
MESSAGE:New("No INTERCEPT fighters currently available", 5, "AIRWING"):ToCoalition(self:GetCoalition())
end
end
--- Launch a flight group to intercept an intruder.
-- @param #AIRWING self
-- @param Wrapper.Group#GROUP group Interceptor flight group.
-- @param Wrapper.Group#GROUP bandits Bandit group.
function AIRWING:LaunchIntercept(group, bandit)
-- Task orbit.
local tasks={}
for _,unit in pairs(bandit:GetUnits()) do
tasks[#tasks+1]=group:TaskAttackUnit(unit)
end
local speed=group:GetSpeedMax()
local altitude=bandit:GetAltitude()
-- Create waypoints.
local wp={}
wp[1]=self:GetCoordinate():WaypointAirTakeOffParking()
wp[2]=self:GetCoordinate():SetAltitude(altitude):WaypointAirTurningPoint(COORDINATE.WaypointAltType.BARO, speed, {tasks}, "Intercept")
-- Start uncontrolled group.
group:StartUncontrolled()
--airboss:SetExcludeAI()
-- Route group
group:Route(wp)
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Misc Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -761,7 +695,7 @@ function AIRWING:ReportSquadrons()
end
self:I(self.sid..text)
self:I(self.wid..text)
MESSAGE:New(text, 10, "AIRWING", true):ToCoalition(self:GetCoalition())
end
+20 -11
View File
@@ -305,13 +305,17 @@ FLIGHTGROUP.TaskType={
--- Mission types.
-- @type FLIGHTGROUP.MissionType
-- @param #string INTERCEPT Intercept task.
-- @param #string CAP Combat Air Patrol task.
-- @param #string BAI Battlefield Air Interdiction task.
-- @param #string INTERCEPT Intercept.
-- @param #string CAP Combat Air Patrol.
-- @param #string BAI Battlefield Air Interdiction.
-- @param #string SEAD Suppression/destruction of enemy air defences.
-- @param #string STRIKE Strike task.
-- @param #string AWACS AWACS task.
-- @param #string TANKER Tanker task.
-- @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",
@@ -323,18 +327,20 @@ FLIGHTGROUP.MissionType={
TANKER="Tanker",
RECON="Recon",
TRANSPORT="Transport",
FERRY="Ferry Flight",
ANTISHIP="Anti Ship"
}
--- Mission status.
-- @type FLIGHTGROUP.MissionStatus
-- @field #string SCHEDULED Mission is scheduled.
-- @field #string EXECUTING Mission is being executed.
-- @field #string ASSIGNED Mission was assigned.
-- @field #string EXECUTING Mission is being executed.
-- @field #string ACCOMPLISHED Mission is accomplished.
FLIGHTGROUP.MissionStatus={
SCHEDULED="scheduled",
ASSIGNED="assigned",
EXECUTING="executing",
ASSIGNED="assigned",
ACCOMPLISHED="accomplished",
FAILED="failed",
}
@@ -364,7 +370,7 @@ FLIGHTGROUP.MissionStatus={
--- FLIGHTGROUP class version.
-- @field #string version
FLIGHTGROUP.version="0.2.6"
FLIGHTGROUP.version="0.3.0"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@@ -1119,12 +1125,14 @@ function FLIGHTGROUP:CreateMissionCAP(Altitude, SpeedOrbit, Heading, Leg)
mission.heading=Heading or 270
mission.leg=UTILS.NMToMeters(Leg or 10)
mission.type="bla"
return mission
end
--- Add mission to queue.
-- @param #FLIGHTGROUP self
-- @param FLIGHTGROUP.Mission Mission for this group.
-- @param #FLIGHTGROUP.Mission Mission Mission for this group.
-- @param Core.Zone#ZONE Zone The mission zone.
-- @param #number WaypointIndex The waypoint index.
-- @param #string ClockStart Time the mission is started, e.g. "05:00" for 5 am. If specified as a #number, it will be relative (in seconds) to the current mission time. Default is 5 seconds after mission was added.
@@ -1189,7 +1197,8 @@ function FLIGHTGROUP:AddMission(Mission, Zone, WaypointIndex, ClockStart, ClockS
table.insert(self.missionqueue, mission)
local text=string.format("Added %s mission %s at zone %s. Starting at %s. Stopping at %s", mission.type, mission.name, mission.zone:GetName(), UTILS.SecondsToClock(mission.Tstart, true), mission.Tstop and UTILS.SecondsToClock(mission.Tstop, true) or "never")
self:I(self.lid..text)
--self:I(self.lid..text)
self:I(text)
return mission
end
+1 -3
View File
@@ -73,7 +73,7 @@ function INTEL:New(DetectionSet)
self.detectionset=DetectionSet
-- Set some string id for output to DCS.log file.
self.lid=string.format("INTEL %s | ", self.squadronname)
self.lid=string.format("INTEL %s | ", "KGB")
-- Start State.
self:SetStartState("Stopped")
@@ -219,8 +219,6 @@ function INTEL:_UpdateIntel()
local detectedlost=self.detectedunits:GetSetComplement(DetectedSet)
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+71 -20
View File
@@ -15,9 +15,8 @@
-- @type WINGCOMMANDER
-- @field #string ClassName Name of the class.
-- @field #boolean Debug Debug mode. Messages to all about status.
-- @field #string sid Class id string for output to DCS log file.
-- @field #string livery Livery of the squadron.
-- @field #table flights Table of flight groups.
-- @field #string ,id Class id string for output to DCS log file.
-- @field #table airwings Table of airwings.
-- @extends Core.Fsm#FSM
--- Be surprised!
@@ -38,10 +37,21 @@ WINGCOMMANDER = {
airwings = {},
}
--- Flight group element.
-- @type WINGCOMMANDER.Flight
-- @field Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group object.
-- @field #string mission Mission assigned to the flight.
--- Mission capability.
-- @type WINGCOMMANDER.Capability
-- @field #string missiontype Mission Type.
-- @field #number Ntot Total number of assets for this task.
-- @field #number Navail Number of available assets
-- @field #number Nonmission Number of assets currently on mission.
--- Mission resources.
-- @type WINGCOMMANDER.Recourses
-- @field #string missiontype Mission Type.
-- @field #number Ntot Total number of assets for this task.
-- @field #number Navail Number of available assets
-- @field #number Nonmission Number of assets currently on mission.
--- WINGCOMMANDER class version.
-- @field #string version
@@ -52,7 +62,7 @@ WINGCOMMANDER.version="0.0.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Add tasks.
-- TODO:
-- TODO:
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
@@ -72,10 +82,6 @@ function WINGCOMMANDER:New(AgentSet)
-- Start State.
self:SetStartState("Stopped")
-- TODO Tasks?
self.tasks=tasks or {}
-- Add FSM transitions.
-- From State --> Event --> To State
@@ -138,6 +144,8 @@ end
-- @return #WINGCOMMANDER self
function WINGCOMMANDER:SetLivery(liveryname)
self.livery=liveryname
return self
end
@@ -161,7 +169,7 @@ function WINGCOMMANDER:onafterStart(From, Event, To)
self:__SitRep(-1)
end
--- On after "FlightStatus" event.
--- On after "Sitrep" event.
-- @param #WINGCOMMANDER self
-- @param Wrapper.Group#GROUP Group Flight group.
-- @param #string From From state.
@@ -172,8 +180,18 @@ function WINGCOMMANDER:onafterSitrep(From, Event, To)
-- FSM state.
local fsmstate=self:GetState()
-- Short info.
local text=string.format("No activities")
local capabilities=self:CheckResources()
-- Number of assets total, on mission, available
-- Number of assets available of each mission type.
self:I(self.sid..text)
if DetectedGroupsUnknown then
@@ -184,14 +202,37 @@ function WINGCOMMANDER:onafterSitrep(From, Event, To)
if group and group:IsAlive() then
local category=group:GetCategory()
local attribute=group:GetAttribute()
local threatlevel=group:GetThreatLevel()
if category==Group.Category.AIRPLANE or category==Group.Category.AIRPLANE then
if category==Group.Category.AIRPLANE or category==Group.Category.HELICOPTER then
if capability.INTERCEPT.Navail>0 then
--TODO: Something like get closest AIRWING or squadron?
-- Launch even from multiple airwings? Currently Navail is like this.
end
elseif category==Group.Category.GROUND then
--TODO: action depends on type
-- AA/SAM ==> SEAD
-- Tanks ==>
-- Artillery ==>
-- Infantry ==>
--
if attribute==GROUP.Attribute.GROUND_AAA or attribute==GROUP.Attribute.GROUND_SAM then
--TODO: SEAD/DEAD
end
elseif category==Group.Category.SHIP then
--TODO: ANTISHIP
end
@@ -211,17 +252,27 @@ end
--- Check resources.
-- @param #WINGCOMMANDER self
-- @return #table
function WINGCOMMANDER:CheckResources()
for _,_airwing in pairs(self.airwings) do
local airwing=_airwing --Ops.AirWing#AIRWING
airwing:GetFlightsWhoCan()
local capabilities={}
for _,MissionType in pairs(FLIGHTGROUP.MissionType) do
capabilities[MissionType]=0
for _,_airwing in pairs(self.airwings) do
local airwing=_airwing --Ops.AirWing#AIRWING
-- Get Number of assets that can do this type of missions.
local _,nassets=airwing:CanMission(MissionType)
-- Add up airwing resources.
capabilities[MissionType]=capabilities[MissionType]+nassets
end
end
return capabilities
end
+167
View File
@@ -173,6 +173,62 @@ GROUPTEMPLATE.Takeoff = {
[GROUP.Takeoff.Cold] = { "TakeOffParking", "From Parking Area" }
}
--- Generalized group attributes. See [DCS attributes](https://wiki.hoggitworld.com/view/DCS_enum_attributes) on hoggit.
-- @type GROUP.Attribute
-- @field #string AIR_TRANSPORTPLANE Airplane with transport capability. This can be used to transport other assets.
-- @field #string AIR_AWACS Airborne Early Warning and Control System.
-- @field #string AIR_FIGHTER Fighter, interceptor, ... airplane.
-- @field #string AIR_BOMBER Aircraft which can be used for strategic bombing.
-- @field #string AIR_TANKER Airplane which can refuel other aircraft.
-- @field #string AIR_TRANSPORTHELO Helicopter with transport capability. This can be used to transport other assets.
-- @field #string AIR_ATTACKHELO Attack helicopter.
-- @field #string AIR_UAV Unpiloted Aerial Vehicle, e.g. drones.
-- @field #string AIR_OTHER Any airborne unit that does not fall into any other airborne category.
-- @field #string GROUND_APC Infantry carriers, in particular Amoured Personell Carrier. This can be used to transport other assets.
-- @field #string GROUND_TRUCK Unarmed ground vehicles, which has the DCS "Truck" attribute.
-- @field #string GROUND_INFANTRY Ground infantry assets.
-- @field #string GROUND_ARTILLERY Artillery assets.
-- @field #string GROUND_TANK Tanks (modern or old).
-- @field #string GROUND_TRAIN Trains. Not that trains are **not** yet properly implemented in DCS and cannot be used currently.
-- @field #string GROUND_EWR Early Warning Radar.
-- @field #string GROUND_AAA Anti-Aircraft Artillery.
-- @field #string GROUND_SAM Surface-to-Air Missile system or components.
-- @field #string GROUND_OTHER Any ground unit that does not fall into any other ground category.
-- @field #string NAVAL_AIRCRAFTCARRIER Aircraft carrier.
-- @field #string NAVAL_WARSHIP War ship, i.e. cruisers, destroyers, firgates and corvettes.
-- @field #string NAVAL_ARMEDSHIP Any armed ship that is not an aircraft carrier, a cruiser, destroyer, firgatte or corvette.
-- @field #string NAVAL_UNARMEDSHIP Any unarmed naval vessel.
-- @field #string NAVAL_OTHER Any naval unit that does not fall into any other naval category.
-- @field #string OTHER_UNKNOWN Anything that does not fall into any other category.
GROUP.Attribute = {
AIR_TRANSPORTPLANE="Air_TransportPlane",
AIR_AWACS="Air_AWACS",
AIR_FIGHTER="Air_Fighter",
AIR_BOMBER="Air_Bomber",
AIR_TANKER="Air_Tanker",
AIR_TRANSPORTHELO="Air_TransportHelo",
AIR_ATTACKHELO="Air_AttackHelo",
AIR_UAV="Air_UAV",
AIR_OTHER="Air_OtherAir",
GROUND_APC="Ground_APC",
GROUND_TRUCK="Ground_Truck",
GROUND_INFANTRY="Ground_Infantry",
GROUND_ARTILLERY="Ground_Artillery",
GROUND_TANK="Ground_Tank",
GROUND_TRAIN="Ground_Train",
GROUND_EWR="Ground_EWR",
GROUND_AAA="Ground_AAA",
GROUND_SAM="Ground_SAM",
GROUND_OTHER="Ground_OtherGround",
NAVAL_AIRCRAFTCARRIER="Naval_AircraftCarrier",
NAVAL_WARSHIP="Naval_WarShip",
NAVAL_ARMEDSHIP="Naval_ArmedShip",
NAVAL_UNARMEDSHIP="Naval_UnarmedShip",
NAVAL_OTHER="Naval_OtherNaval",
OTHER_UNKNOWN="Other_Unknown",
}
--- Create a new GROUP from a given GroupTemplate as a parameter.
-- Note that the GroupTemplate is NOT spawned into the mission.
-- It is merely added to the @{Core.Database}.
@@ -2114,6 +2170,117 @@ function GROUP:GetDCSDesc(n)
return nil
end
--- Get the generalized attribute of a self.
-- Note that for a heterogenious self, the attribute is determined from the attribute of the first unit!
-- @param #GROUP self
-- @return #string Generalized attribute of the self.
function GROUP:GetAttribute()
-- Default
local attribute=GROUP.Attribute.OTHER_UNKNOWN --#GROUP.Attribute
if self then
-----------
--- Air ---
-----------
-- Planes
local transportplane=self:HasAttribute("Transports") and self:HasAttribute("Planes")
local awacs=self:HasAttribute("AWACS")
local fighter=self:HasAttribute("Fighters") or self:HasAttribute("Interceptors") or self:HasAttribute("Multirole fighters") or (self:HasAttribute("Bombers") and not self:HasAttribute("Strategic bombers"))
local bomber=self:HasAttribute("Strategic bombers")
local tanker=self:HasAttribute("Tankers")
local uav=self:HasAttribute("UAVs")
-- Helicopters
local transporthelo=self:HasAttribute("Transport helicopters")
local attackhelicopter=self:HasAttribute("Attack helicopters")
--------------
--- Ground ---
--------------
-- Ground
local apc=self:HasAttribute("Infantry carriers")
local truck=self:HasAttribute("Trucks") and self:GetCategory()==Group.Category.GROUND
local infantry=self:HasAttribute("Infantry")
local artillery=self:HasAttribute("Artillery")
local tank=self:HasAttribute("Old Tanks") or self:HasAttribute("Modern Tanks")
local aaa=self:HasAttribute("AAA")
local ewr=self:HasAttribute("EWR")
local sam=self:HasAttribute("SAM elements") and (not self:HasAttribute("AAA"))
-- Train
local train=self:GetCategory()==Group.Category.TRAIN
-------------
--- Naval ---
-------------
-- Ships
local aircraftcarrier=self:HasAttribute("Aircraft Carriers")
local warship=self:HasAttribute("Heavy armed ships")
local armedship=self:HasAttribute("Armed ships")
local unarmedship=self:HasAttribute("Unarmed ships")
-- Define attribute. Order is important.
if transportplane then
attribute=GROUP.Attribute.AIR_TRANSPORTPLANE
elseif awacs then
attribute=GROUP.Attribute.AIR_AWACS
elseif fighter then
attribute=GROUP.Attribute.AIR_FIGHTER
elseif bomber then
attribute=GROUP.Attribute.AIR_BOMBER
elseif tanker then
attribute=GROUP.Attribute.AIR_TANKER
elseif transporthelo then
attribute=GROUP.Attribute.AIR_TRANSPORTHELO
elseif attackhelicopter then
attribute=GROUP.Attribute.AIR_ATTACKHELO
elseif uav then
attribute=GROUP.Attribute.AIR_UAV
elseif apc then
attribute=GROUP.Attribute.GROUND_APC
elseif infantry then
attribute=GROUP.Attribute.GROUND_INFANTRY
elseif artillery then
attribute=GROUP.Attribute.GROUND_ARTILLERY
elseif tank then
attribute=GROUP.Attribute.GROUND_TANK
elseif aaa then
attribute=GROUP.Attribute.GROUND_AAA
elseif ewr then
attribute=GROUP.Attribute.GROUND_EWR
elseif sam then
attribute=GROUP.Attribute.GROUND_SAM
elseif truck then
attribute=GROUP.Attribute.GROUND_TRUCK
elseif train then
attribute=GROUP.Attribute.GROUND_TRAIN
elseif aircraftcarrier then
attribute=GROUP.Attribute.NAVAL_AIRCRAFTCARRIER
elseif warship then
attribute=GROUP.Attribute.NAVAL_WARSHIP
elseif armedship then
attribute=GROUP.Attribute.NAVAL_ARMEDSHIP
elseif unarmedship then
attribute=GROUP.Attribute.NAVAL_UNARMEDSHIP
else
if self:IsGround() then
attribute=GROUP.Attribute.GROUND_OTHER
elseif self:IsShip() then
attribute=GROUP.Attribute.NAVAL_OTHER
elseif self:IsAir() then
attribute=GROUP.Attribute.AIR_OTHER
else
attribute=GROUP.Attribute.OTHER_UNKNOWN
end
end
end
return attribute
end
do -- Route methods
--- (AIR) Return the Group to an @{Wrapper.Airbase#AIRBASE}.