This commit is contained in:
Frank
2020-03-10 17:03:24 +01:00
parent a477fc78bc
commit 6305459056
6 changed files with 409 additions and 86 deletions
+59 -18
View File
@@ -417,18 +417,38 @@ function AIRWING:SetNumberAWACS(n)
end
--- Add a patrol Point for CAP missions.
--- Create a new generic patrol point.
-- @param #AIRWING self
-- @param Core.Zone#ZONE AcceptZone Add a zone to the CAP zone set.
-- @return #AIRWING self
function AIRWING:AddPatrolPointCAP(Coordinate, Heading, Leg, Speed)
-- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point.
-- @param #number Heading Heading in degrees.
-- @param #number LegLength Length of race-track orbit in NM.
-- @param #number Altitude Orbit altitude in feet.
-- @param #number Speed Orbit speed in knots.
-- @return #AIRWING.PatrolData Patrol point table.
function AIRWING:NewPatrolPoint(Coordinate, Heading, LegLength, Altitude, Speed)
local cappoint={} --#AIRWING.PatrolData
cappoint.coord=Coordinate
cappoint.heading=Heading or 090
cappoint.leg=Leg or 15
cappoint.leg=LegLength or 15
cappoint.altitude=Altitude
cappoint.speed=Speed or 350
return cappoint
end
--- Add a patrol Point for CAP missions.
-- @param #AIRWING self
-- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point.
-- @param #number Heading Heading in degrees.
-- @param #number LegLength Length of race-track orbit in NM.
-- @param #number Altitude Orbit altitude in feet.
-- @param #number Speed Orbit speed in knots.
-- @return #AIRWING self
function AIRWING:AddPatrolPointCAP(Coordinate, Heading, LegLength, Altitude, Speed)
local cappoint=self:NewPatrolPoint(Coordinate, Heading, LegLength, Speed, Altitude, LegLength)
table.insert(self.cappoints, cappoint)
return self
@@ -473,7 +493,7 @@ function AIRWING:onafterStatus(From, Event, To)
local fsmstate=self:GetState()
-- Check CAP missions.
--self:CheckCAP()
self:CheckCAP()
--self:CheckTANKER()
@@ -798,6 +818,9 @@ function AIRWING:onafterMissionCancel(From, Event, To, Mission)
if flightgroup then
flightgroup:MissionCancel(Mission)
end
-- Not requested any more (if it was).
asset.requested=nil
end
-- Remove queued request (if any).
@@ -890,7 +913,7 @@ function AIRWING:onafterAssetSpawned(From, Event, To, group, asset, request)
-- Add mission to flightgroup queue.
if mission then
-- Add mission to flightgroup queue.
-- Add mission to flightgroup queue.
asset.flightgroup:AddMission(mission)
end
@@ -916,7 +939,12 @@ function AIRWING:onafterAssetDead(From, Event, To, asset, request)
-- Add group to the detection set of the WINGCOMMANDER.
if self.wingcommander then
self.wingcommander.detectionset:RemoveGroupsByName({asset.spawngroupname})
end
end
--TODO: remove asset from mission.
--local mission=self:GetAssetCurrentMission(asset)
--TODO: remove asset from squadron.
end
@@ -1032,18 +1060,14 @@ end
-- @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
-- Assets available for this mission.
local assets={}
-- WARNING: This assumes that all assets of the squad can do the same mission types!
-- TODO: we could make the mission type as a parameter of the assets! Then we can have heterogenious squads as well!
local gotit=self:CheckMissionType(MissionType, Squadron.missiontypes)
local cando=self:CheckMissionType(MissionType, Squadron.missiontypes)
if not gotit then
-- This squad cannot do this mission.
cando=false
else
if cando then
for _,_asset in pairs(Squadron.assets) do
local asset=_asset --#AIRWING.SquadronAsset
@@ -1056,7 +1080,7 @@ function AIRWING:SquadronCanMission(Squadron, MissionType, Nassets)
---
--TODO: This only checks if it has an ORBIT mission. It could have others as well!
if self:IsAssetOnMission(asset, AUFTRAG.Type.ORBIT) and MissionType~=AUFTRAG.Type.ORBIT then
if self:IsAssetOnMission(asset, AUFTRAG.Type.PATROL) and MissionType~=AUFTRAG.Type.PATROL then
-- Check if the payload of this asset is compatible with the mission.
if self:CheckMissionType(MissionType, asset.payload.missiontypes) then
@@ -1137,6 +1161,23 @@ function AIRWING:IsAssetOnMission(asset, MissionTypes)
end
end
-- Alternative: run over all missions and compare to mission assets.
for _,_mission in pairs(self.missionqueue) do
local mission=_mission --Ops.Auftrag#AUFTRAG
if mission:IsNotOver() then
for _,_asset in pairs(mission.assets) do
local sqasset=_asset --#AIRWING.SquadronAsset
if sqasset.uid==asset.uid then
return true
end
end
end
end
return false
end
+253 -5
View File
@@ -64,6 +64,9 @@
--
-- @field #number missionAltitude Mission altitude in meters.
--
-- @field #number missionRepeated Number of times mission was repeated.
-- @field #number missionRepeatMax Number of times mission is repeated if failed.
--
-- @field #number optionROE ROE.
-- @field #number optionROT ROT.
-- @field #number optionCM Counter measures.
@@ -252,6 +255,9 @@ function AUFTRAG:New(Type)
self:SetPriority()
self:SetMissionTime()
self.missionRepeated=0
self.missionRepeatMax=1
-- FMS start state is PLANNED.
self:SetStartState(self.status)
@@ -269,12 +275,22 @@ function AUFTRAG:New(Type)
self:AddTransition("*", "Done", AUFTRAG.Status.DONE) -- All assets have reported that mission is done.
self:AddTransition("*", "Cancel", AUFTRAG.Status.CANCELLED) -- Command to cancel the mission.
self:AddTransition("*", "Accomplished", AUFTRAG.Status.SUCCESS)
self:AddTransition("*", "Success", AUFTRAG.Status.SUCCESS)
self:AddTransition("*", "Failed", AUFTRAG.Status.FAILED)
self:AddTransition("*", "Status", "*")
self:AddTransition("*", "Stop", "Stopped")
self:AddTransition("*", "Repeat", AUFTRAG.Status.PLANNED)
self:AddTransition("*", "AssetDead", "*")
--[[
self:HandleEvent(EVENTS.PilotDead, self._UnitDead)
self:HandleEvent(EVENTS.Ejection, self._UnitDead)
self:HandleEvent(EVENTS.Crash, self._UnitDead)
]]
self:__Status(-1)
return self
@@ -471,6 +487,69 @@ function AUFTRAG:NewBAI(TargetGroupSet)
return mission
end
--- Create a mission to attack a group. Mission type is automatically chosen from the group category.
-- @param #AUFTRAG self
-- @param Wrapper.Group#GROUP EngageGroup Group to be engaged.
-- @return #AUFTRAG self
function AUFTRAG:NewAUTO(EngageGroup)
local mission=nil --#AUFTRAG
local group=EngageGroup
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.HELICOPTER then
mission=AUFTRAG:NewINTERCEPT(group)
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
mission=AUFTRAG:NewBAI(group)
elseif category==Group.Category.SHIP then
--TODO: ANTISHIP
local TargetUnitSet=SET_UNIT:New()
for _,_unit in pairs(group:GetUnits()) do
local unit=_unit --Wrapper.Unit#UNIT
if unit and unit:IsAlive() and unit:GetThreatLevel()>0 then
TargetUnitSet:AddUnit(unit)
end
end
if TargetUnitSet:Count()>0 then
mission=AUFTRAG:NewANTISHIP(TargetUnitSet)
end
end
end
return mission
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- User API Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -545,6 +624,20 @@ function AUFTRAG:SetWeaponType(WeaponType)
return self
end
--- Set number of weapons to expend.
-- @param #AUFTRAG self
-- @param #number WeaponType Weapon type. Default is ENUMS.WeaponFlag.Auto
-- @return #AUFTRAG self
function AUFTRAG:SetWeaponExpend(WeaponExpend)
self.engageWeaponExpend=WeaponExpend or "Auto"
-- Update the DCS task parameter.
self.DCStask=self:GetDCSMissionTask()
return self
end
--- Set mission altitude.
-- @param #AUFTRAG self
-- @param #string Altitude Altitude in feet.
@@ -554,9 +647,9 @@ function AUFTRAG:SetMissionAltitude(Altitude)
return self
end
--- Set Rules of Engagement for this mission.
--- Set Rules of Engagement (ROE) for this mission.
-- @param #AUFTRAG self
-- @param #number roe ROE
-- @param #string roe Mision ROE.
-- @return #AUFTRAG self
function AUFTRAG:SetROE(roe)
@@ -566,6 +659,18 @@ function AUFTRAG:SetROE(roe)
end
--- Set Reaction on Threat (ROT) for this mission.
-- @param #AUFTRAG self
-- @param #string roe Mision ROT.
-- @return #AUFTRAG self
function AUFTRAG:SetROE(rot)
self.optionROT=rot
return self
end
--- Add a flight group to the mission.
-- @param #AUFTRAG self
-- @param Ops.FlightGroup#FLIGHTGROUP FlightGroup The FLIGHTGROUP object.
@@ -675,6 +780,10 @@ function AUFTRAG:onafterStatus(From, Event, To)
self:Cancel()
end
if self:IsNotOver() and #self.assets==0 then
self:Cancel()
end
-- Check if ALL flights are done with their mission.
if self:IsNotOver() and self:CheckFlightsDone() then
self:Done()
@@ -695,12 +804,13 @@ function AUFTRAG:onafterStatus(From, Event, To)
self:E(self.lid..string.format("ERROR: FSM state %s != %s mission status!", fsmstate, self.status))
end
-- Check if mission is OVER.
if self:IsOver() then
-- TODO: evaluate mission result. self.Ntargets>0 and Ntargets=?
-- TODO: if failed, repeat mission, i.e. set status to PLANNED? if success, stop and remove from ALL queues.
self:Stop()
--self:Stop()
self:Evaluate()
else
self:__Status(-30)
end
@@ -712,6 +822,12 @@ end
function AUFTRAG:Evaluate()
local Ntargets=self:CountMissionTargets()
if self.Ntargets>Ntargets then
self:Failed()
else
self:Success()
end
end
@@ -801,6 +917,34 @@ function AUFTRAG:CheckFlightsDone()
return done
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- EVENT Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Flightgroup event function handling the crash of a unit.
-- @param #FLIGHTGROUP self
-- @param Core.Event#EVENTDATA EventData Event data.
function AUFTRAG:OnEventCrash(EventData)
-- Check that this is the right group.
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
local unit=EventData.IniUnit
local group=EventData.IniGroup
local unitname=EventData.IniUnitName
-- Get element.
local element=self:GetElementByName(unitname)
if element then
self:T3(self.lid..string.format("EVENT: Element %s crashed ==> dead", element.name))
self:ElementDead(element)
end
end
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- FSM Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -879,6 +1023,35 @@ function AUFTRAG:onafterDone(From, Event, To)
self:I(self.lid..string.format("New mission status=%s", self.status))
end
--- On after "AssetDead" event.
-- @param #AUFTRAG self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Ops.AirWing#AIRWING.SquadronAsset
function AUFTRAG:onafterAssetDead(From, Event, To, Asset)
-- Delete asset from mission.
self:DelAsset(Asset)
-- All assets dead?
if #self.assets==0 then
if self:IsNotOver() then
-- Mission failed.
self:Failed()
else
self:Stop()
end
end
end
--- On after "Cancel" event. Cancells the mission.
-- @param #AUFTRAG self
-- @param #string From From state.
@@ -905,6 +1078,61 @@ function AUFTRAG:onafterCancel(From, Event, To)
end
--- On after "Failed" event.
-- @param #AUFTRAG self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function AUFTRAG:onafterFailed(From, Event, To)
self.status=AUFTRAG.Status.FAILED
self:I(self.lid..string.format("New mission status=%s", self.status))
if self.missionRepeated>=self.missionRepeatMax then
self:Stop()
else
-- Repeat mission.
self:Repeat()
end
end
--- On after "Repeat" event.
-- @param #AUFTRAG self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function AUFTRAG:onafterRepeat(From, Event, To)
-- Increase repeat counter.
self.missionRepeated=self.missionRepeated+1
if self.wingcommander then
elseif self.airwing then
end
end
--- On after "Success" event.
-- @param #AUFTRAG self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function AUFTRAG:onafterSuccess(From, Event, To)
self.status=AUFTRAG.Status.SUCCESS
self:I(self.lid..string.format("New mission status=%s", self.status))
end
--- On after "Stop" event. Remove mission from AIRWING and FLIGHTGROUP mission queues.
-- @param #AUFTRAG self
-- @param #string From From state.
@@ -914,6 +1142,8 @@ function AUFTRAG:onafterStop(From, Event, To)
-- TODO: remove missions from queues in WINGCOMMANDER, AIRWING and FLIGHGROUPS!
-- TODO: Mission should be OVER! we dont want to remove running missions from any queues.
if self.wingcommander then
end
@@ -966,6 +1196,24 @@ function AUFTRAG:DelAsset(Asset)
return self
end
--- Get asset by its spawn group name.
-- @param #AUFTRAG self
-- @param #string Name Asset spawn group name.
-- @return Ops.AirWing#AIRWING.SquadronAsset
function AUFTRAG:GetAssetByName(Name)
for i,_asset in pairs(self.assets or {}) do
local asset=_asset --Ops.AirWing#AIRWING.SquadronAsset
if asset.spawngroupname==Name then
return asset
end
end
return nil
end
--- Count alive mission targets.
-- @param #AUFTRAG self
+83 -2
View File
@@ -69,6 +69,12 @@
-- @field #number CallsignName Call sign name.
-- @field #number CallsignNumber Call sign number.
-- @field #boolean EPLRS If true, turn EPLRS data link on.
--
-- @field #string ROEdefault Default ROE setting.
-- @field #string ROTdefault Default ROT setting.
-- @field #string ROEcurrent Current ROE setting.
-- @field #string ROTcurrent Current ROT setting.
--
-- @extends Core.Fsm#FSM
--- *To invent an airplane is nothing. To build one is something. To fly is everything.* -- Otto Lilienthal
@@ -313,6 +319,34 @@ FLIGHTGROUP.TaskType={
-- @field #number WaypointIndex Waypoint number at which the enroute task is added.
--- Rules of Engagement (ROE).
-- @type FLIGHTGROUP.ROE
-- @field #string RETURNFIRE
-- @field #string WEAPONFREE
-- @field #string WEAPONHOLD
FLIGHTGROUP.ROE={
WEAPONFREE="weapon_free",
OPENFIREPRIO="open_fire_prio_designated",
OPENFIREDESIG="open_fire_only_designated",
RETURNFIRE="return_fire",
WEAPONHOLD="weapon_hold",
}
--- Reaction on Threat (ROT).
-- @type FLIGHTGROUP.ROT
-- @field #string NOREACT No defensive actions will take place to counter threats.
-- @field #string PASSIVE AI will use jammers and other countermeasures in an attempt to defeat the threat. AI will not attempt a maneuver to defeat a threat.
-- @field #string EVADE AI will react by performing defensive maneuvers against incoming threats, AI will also use passive defense.
-- @field #string BYPASS aI will attempt to avoid enemy threat zones all together. This includes attempting to fly above or around threats.
-- @field #string ABORT If a threat is deemed severe enough the AI will abort its mission and return to base.
FLIGHTGROUP.ROT={
NOREACT="no_reaction",
PASSIVE="weapon_free",
EVADE="return_fire",
BYPASS="bypass_and_escape",
ABORT="allow_abort_mission",
}
--- FLIGHTGROUP class version.
-- @field #string version
FLIGHTGROUP.version="0.3.4"
@@ -1980,7 +2014,12 @@ function FLIGHTGROUP:onafterFlightSpawned(From, Event, To)
self:T(self.lid..string.format("Flight spawned!"))
-- F10 menu.
if not self.ai then
if self.ai then
else
self.menu=self.menu or {}
self.menu.atc=self.menu.atc or {}
self.menu.atc.root=self.menu.atc.root or MENU_GROUP:New(self.group, "ATC")
@@ -2148,7 +2187,17 @@ function FLIGHTGROUP:onafterFlightDead(From, Event, To)
if self.flightcontrol then
self.flightcontrol:_RemoveFlight(self)
self.flightcontrol=nil
end
end
for _,_mission in pairs(self.missionqueue) do
local mission=_mission --Ops.Auftrag#AUFTRAG
local asset=mission:GetAssetByName(self.groupname)
if asset then
mission:AssetDead(asset)
end
end
-- Stop
self:Stop()
@@ -5186,6 +5235,38 @@ function FLIGHTGROUP:_GetTerminal(_attribute, _category)
return _terminal
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- OPTION FUNCTIONS
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Set ROE for a group.
-- @param #FLIGHTGROUP self
-- @param #string roe ROE of group. Default is FLIGHTGROUP.ROE.HOLDFIRE.
function FLIGHTGROUP:SetOptionROE(roe)
if roe==FLIGHTGROUP.ROE.RETURNFIRE then
self.group:OptionROEReturnFire()
elseif roe==FLIGHTGROUP.ROE.WEAPONFREE then
self.group:OptionROEWeaponFree()
else
self.group:OptionROEHoldFire()
end
self.ROEcurrent=roe
end
--- Set ROT for a group.
-- @param #FLIGHTGROUP self
-- @param #string rot ROT of group.
function FLIGHTGROUP:SetOptionROT(rot)
if rot==FLIGHTGROUP.ROT.PASSIVE then
self.group:OptionROTPassiveDefense()
elseif self.rot==FLIGHTGROUP.ROT.NOREACT then
self.group:OptionROTEvadeFire()
else
self.group:OptionROTNoReaction()
end
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- MENU FUNCTIONS
@@ -313,7 +313,6 @@ function INTEL:UpdateIntel()
end
-- TODO: Filter units from reject zones.
-- TODO: Filter unit types.
-- TODO: Filter detection methods?
local remove={}
for _,_unit in pairs(DetectedSet.Set) do
@@ -358,7 +357,6 @@ function INTEL:UpdateIntel()
for _,unitname in pairs(remove) do
DetectedSet:Remove(unitname, true)
end
--DetectedSet:RemoveUnitsByName(remove)
-- Create detected contacts.
self:CreateDetectedItems(DetectedSet)
+6 -4
View File
@@ -64,19 +64,21 @@ SQUADRON.version="0.0.2"
--- Create a new SQUADRON object and start the FSM.
-- @param #SQUADRON self
-- @param #string SquadName Name of the squadron, e.g. "VFA-37".
-- @param #table tasks Table of squadron tasks, e.g. `{SQUADRON.Task.INTERCEPT, SQUADRON.Task.SEAD}`.
-- @param #string SquadronName Name of the squadron, e.g. "VFA-37".
-- @param #string TemplateGroupName Name of the template group.
-- @return #SQUADRON self
function SQUADRON:New(SquadronName, TemplateGroupName)
-- Inherit everything from FSM class.
local self=BASE:Inherit(self, FSM:New()) -- #SQUADRON
self.templatename=TemplateGroupName
--self.flightgroup=AIGroup
self.name=tostring(SquadronName)
self.name=tostring(SquadronName or TemplateGroupName)
-- Set some string id for output to DCS.log file.
self.sid=string.format("SQUADRON %s | ", self.squadronname)
self.lid=string.format("SQUADRON %s | ", self.squadronname)
-- Start State.
self:SetStartState("Stopped")
+8 -55
View File
@@ -246,65 +246,18 @@ function WINGCOMMANDER:onafterStatus(From, Event, To)
local contact=_contact --#WINGCOMMANDER.Contact
local group=contact.group --Wrapper.Group#GROUP
if group and group:IsAlive() then
-- Create a mission based on group category.
local mission=AUFTRAG:NewAUTO(group)
local category=group:GetCategory()
local attribute=group:GetAttribute()
local threatlevel=group:GetThreatLevel()
local mission=nil --Ops.Auftrag#AUFTRAG
if category==Group.Category.AIRPLANE or category==Group.Category.HELICOPTER then
mission=AUFTRAG:NewINTERCEPT(group)
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
mission=AUFTRAG:NewBAI(group)
elseif category==Group.Category.SHIP then
--TODO: ANTISHIP
local TargetUnitSet=SET_UNIT:New()
for _,_unit in pairs(group:GetUnits()) do
local unit=_unit --Wrapper.Unit#UNIT
if unit and unit:IsAlive() and unit:GetThreatLevel()>0 then
TargetUnitSet:AddUnit(unit)
end
end
if TargetUnitSet:Count()>0 then
mission=AUFTRAG:NewANTISHIP(TargetUnitSet)
end
end
-- Add mission to queue.
if mission then
mission.nassets=1
contact.mission=mission
-- Add mission to queue.
if mission then
mission.nassets=1
contact.mission=mission
self:AddMission(mission)
end
self:AddMission(mission)
end
end