mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-11 11:48:38 +00:00
Ops
This commit is contained in:
@@ -134,7 +134,7 @@ function CLEANUP_AIRBASE:New( AirbaseNames )
|
||||
for UnitName, Unit in pairs( _DATABASE.UNITS ) do
|
||||
local Unit = Unit -- Wrapper.Unit#UNIT
|
||||
if Unit:IsAlive() ~= nil then
|
||||
if self:IsInAirbase( Unit:GetVec2() ) then
|
||||
if self.__:IsInAirbase( Unit:GetVec2() ) then
|
||||
self:F( { UnitName = UnitName } )
|
||||
self.CleanUpList[UnitName] = {}
|
||||
self.CleanUpList[UnitName].CleanUpUnit = Unit
|
||||
@@ -187,6 +187,10 @@ function CLEANUP_AIRBASE:SetCleanMissiles( CleanMissiles )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Check whether a Vec2 is in any cleanup airbase.
|
||||
-- @param #CLEANUP_AIRBASE self
|
||||
-- @param DCS#VEC2 Vec2 2D vector.
|
||||
function CLEANUP_AIRBASE.__:IsInAirbase( Vec2 )
|
||||
|
||||
local InAirbase = false
|
||||
@@ -194,7 +198,7 @@ function CLEANUP_AIRBASE.__:IsInAirbase( Vec2 )
|
||||
local Airbase = Airbase -- Wrapper.Airbase#AIRBASE
|
||||
if Airbase:GetZone():IsVec2InZone( Vec2 ) then
|
||||
InAirbase = true
|
||||
break;
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
@@ -246,7 +250,7 @@ function CLEANUP_AIRBASE.__:OnEventBirth( EventData )
|
||||
self:F( { EventData } )
|
||||
|
||||
if EventData.IniUnit:IsAlive() ~= nil then
|
||||
if self:IsInAirbase( EventData.IniUnit:GetVec2() ) then
|
||||
if self.__:IsInAirbase( EventData.IniUnit:GetVec2() ) then
|
||||
self.CleanUpList[EventData.IniDCSUnitName] = {}
|
||||
self.CleanUpList[EventData.IniDCSUnitName].CleanUpUnit = EventData.IniUnit
|
||||
self.CleanUpList[EventData.IniDCSUnitName].CleanUpGroup = EventData.IniGroup
|
||||
@@ -291,7 +295,7 @@ function CLEANUP_AIRBASE.__:OnEventShot( Event )
|
||||
self:F( { Event } )
|
||||
|
||||
-- Test if the missile was fired within one of the CLEANUP_AIRBASE.AirbaseNames.
|
||||
if self:IsInAirbase( Event.IniUnit:GetVec2() ) then
|
||||
if self.__:IsInAirbase( Event.IniUnit:GetVec2() ) then
|
||||
-- Okay, the missile was fired within the CLEANUP_AIRBASE.AirbaseNames, destroy the fired weapon.
|
||||
self:DestroyMissile( Event.Weapon )
|
||||
end
|
||||
@@ -304,7 +308,7 @@ function CLEANUP_AIRBASE.__:OnEventHit( Event )
|
||||
self:F( { Event } )
|
||||
|
||||
if Event.IniUnit then
|
||||
if self:IsInAirbase( Event.IniUnit:GetVec2() ) then
|
||||
if self.__:IsInAirbase( Event.IniUnit:GetVec2() ) then
|
||||
self:T( { "Life: ", Event.IniDCSUnitName, ' = ', Event.IniUnit:GetLife(), "/", Event.IniUnit:GetLife0() } )
|
||||
if Event.IniUnit:GetLife() < Event.IniUnit:GetLife0() then
|
||||
self:T( "CleanUp: Destroy: " .. Event.IniDCSUnitName )
|
||||
@@ -314,7 +318,7 @@ function CLEANUP_AIRBASE.__:OnEventHit( Event )
|
||||
end
|
||||
|
||||
if Event.TgtUnit then
|
||||
if self:IsInAirbase( Event.TgtUnit:GetVec2() ) then
|
||||
if self.__:IsInAirbase( Event.TgtUnit:GetVec2() ) then
|
||||
self:T( { "Life: ", Event.TgtDCSUnitName, ' = ', Event.TgtUnit:GetLife(), "/", Event.TgtUnit:GetLife0() } )
|
||||
if Event.TgtUnit:GetLife() < Event.TgtUnit:GetLife0() then
|
||||
self:T( "CleanUp: Destroy: " .. Event.TgtDCSUnitName )
|
||||
@@ -356,7 +360,7 @@ function CLEANUP_AIRBASE.__:EventAddForCleanUp( Event )
|
||||
|
||||
if Event.IniDCSUnit and Event.IniCategory == Object.Category.UNIT then
|
||||
if self.CleanUpList[Event.IniDCSUnitName] == nil then
|
||||
if self:IsInAirbase( Event.IniUnit:GetVec2() ) then
|
||||
if self.__:IsInAirbase( Event.IniUnit:GetVec2() ) then
|
||||
self:AddForCleanUp( Event.IniUnit, Event.IniDCSUnitName )
|
||||
end
|
||||
end
|
||||
@@ -364,7 +368,7 @@ function CLEANUP_AIRBASE.__:EventAddForCleanUp( Event )
|
||||
|
||||
if Event.TgtDCSUnit and Event.TgtCategory == Object.Category.UNIT then
|
||||
if self.CleanUpList[Event.TgtDCSUnitName] == nil then
|
||||
if self:IsInAirbase( Event.TgtUnit:GetVec2() ) then
|
||||
if self.__:IsInAirbase( Event.TgtUnit:GetVec2() ) then
|
||||
self:AddForCleanUp( Event.TgtUnit, Event.TgtDCSUnitName )
|
||||
end
|
||||
end
|
||||
@@ -386,7 +390,7 @@ function CLEANUP_AIRBASE.__:CleanUpSchedule()
|
||||
|
||||
if CleanUpUnit:IsAlive() ~= nil then
|
||||
|
||||
if self:IsInAirbase( CleanUpUnit:GetVec2() ) then
|
||||
if self.__:IsInAirbase( CleanUpUnit:GetVec2() ) then
|
||||
|
||||
if _DATABASE:GetStatusGroup( CleanUpGroupName ) ~= "ReSpawn" then
|
||||
|
||||
|
||||
@@ -329,8 +329,9 @@ function AIRWING:AddAssetToSquadron(Squadron, Nassets)
|
||||
|
||||
if Group then
|
||||
|
||||
local text=string.format("FF Adding asset %s to squadron %s", Group:GetName(), Squadron.name)
|
||||
env.info(text)
|
||||
-- Debug text.
|
||||
local text=string.format("Adding asset %s to squadron %s", Group:GetName(), Squadron.name)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Add assets to airwing warehouse.
|
||||
self:AddAsset(Group, Nassets, nil, nil, nil, nil, Squadron.skill, Squadron.livery, Squadron.name)
|
||||
@@ -1338,11 +1339,16 @@ function AIRWING:IsAssetOnMission(asset, MissionTypes)
|
||||
for _,_mission in pairs(asset.flightgroup.missionqueue or {}) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
local status=mission:GetFlightStatus(asset.flightgroup)
|
||||
if mission:IsNotOver() then
|
||||
|
||||
-- Only if mission is started or executing.
|
||||
if (status==AUFTRAG.FlightStatus.STARTED or status==AUFTRAG.FlightStatus.EXECUTING) and self:CheckMissionType(mission.type, MissionTypes) then
|
||||
return true
|
||||
-- Get flight status.
|
||||
local status=mission:GetFlightStatus(asset.flightgroup)
|
||||
|
||||
-- Only if mission is started or executing.
|
||||
if (status==AUFTRAG.FlightStatus.STARTED or status==AUFTRAG.FlightStatus.EXECUTING) and self:CheckMissionType(mission.type, MissionTypes) then
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1642,7 +1648,6 @@ function AIRWING:ReportSquadrons()
|
||||
local nstock=0
|
||||
for _,_asset in pairs(squadron.assets) do
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
--env.info(string.format("Asset name=%s", asset.spawngroupname))
|
||||
|
||||
local n=asset.nunits
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
-- @field #number Tstart Mission start time in seconds.
|
||||
-- @field #number Tstop Mission stop time in seconds.
|
||||
-- @field #number duration Mission duration in seconds.
|
||||
-- @field #number marker F10 map marker ID.
|
||||
-- @field #number markerID F10 map marker ID.
|
||||
-- @field #table DCStask DCS task structure.
|
||||
-- @field #number Ntargets Number of mission targets.
|
||||
--
|
||||
@@ -118,6 +118,7 @@ AUFTRAG = {
|
||||
assets = {},
|
||||
missionFraction = 0.5,
|
||||
enrouteTasks = {},
|
||||
markerID = nil,
|
||||
}
|
||||
|
||||
--- Global mission counter.
|
||||
@@ -230,6 +231,7 @@ AUFTRAG.TargetType={
|
||||
-- @type AUFTRAG.TargetData
|
||||
-- @field Wrapper.Positionable#POSITIONABLE Target Target Object.
|
||||
-- @field #string Type Target type: "Group", "Unit", "Static", "Coordinate", "Airbase.
|
||||
-- @field #number Ninital Number of initial targets.
|
||||
|
||||
--- Mission success.
|
||||
-- @type AUFTRAG.Success
|
||||
@@ -257,11 +259,14 @@ AUFTRAG.version="0.0.9"
|
||||
|
||||
-- TODO: Mission success options damaged, destroyed.
|
||||
-- DONE: Mission ROE and ROT.
|
||||
-- TODO: Mission formation, etc.
|
||||
-- TODO: Mission frequency, formation, etc.
|
||||
-- DONE: FSM events.
|
||||
-- TODO: F10 marker functions that are updated on Status event.
|
||||
-- TODO: F10 marker for new missions.
|
||||
-- DONE: Evaluate mission result ==> SUCCESS/FAILURE
|
||||
-- DONE: NewAUTO() NewA2G NewA2A
|
||||
-- TODO: Transport mission.
|
||||
-- TODO: Recon mission.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
@@ -354,9 +359,10 @@ function AUFTRAG:NewANTISHIP(Target)
|
||||
local mission=AUFTRAG:New(AUFTRAG.Type.ANTISHIP)
|
||||
|
||||
mission.engageTarget=mission:_TargetFromObject(Target)
|
||||
mission.engageWeaponType=ENUMS.WeaponFlag.Auto
|
||||
|
||||
mission.missionTask=ENUMS.MissionTask.ANTISHIPSTRIKE
|
||||
mission.missionFraction=0.5
|
||||
mission.missionFraction=0.4
|
||||
mission.optionROE=ENUMS.ROE.OpenFire
|
||||
mission.optionROT=ENUMS.ROT.EvadeFire
|
||||
|
||||
@@ -600,6 +606,30 @@ function AUFTRAG:NewBAI(Target)
|
||||
return mission
|
||||
end
|
||||
|
||||
--- Create a SEAD mission.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Wrapper.Positionable#POSITIONABLE Target The target to attack. Can be a GROUP or UNIT object.
|
||||
-- @return #AUFTRAG self
|
||||
function AUFTRAG:NewSEAD(Target)
|
||||
|
||||
local mission=AUFTRAG:New(AUFTRAG.Type.SEAD)
|
||||
|
||||
mission.engageTarget=mission:_TargetFromObject(Target)
|
||||
mission.engageWeaponType=ENUMS.WeaponFlag.AnyAG
|
||||
mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL
|
||||
mission.engageAsGroup=true
|
||||
|
||||
mission.missionTask=ENUMS.MissionTask.SEAD
|
||||
mission.missionAltitude=nil
|
||||
mission.missionFraction=0.4
|
||||
mission.optionROE=ENUMS.ROE.OpenFire
|
||||
mission.optionROT=ENUMS.ROT.AllowAbortMission
|
||||
|
||||
mission.DCStask=mission:GetDCSMissionTask()
|
||||
|
||||
return mission
|
||||
end
|
||||
|
||||
--- Create a STRIKE mission. Flight will attack the closest map object to the specified coordinate.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Core.Point#COORDINATE Target The target coordinate. Can also be given as a GROUP, UNIT or STATIC object.
|
||||
@@ -754,20 +784,31 @@ function AUFTRAG:NewAUTO(EngageGroup)
|
||||
|
||||
if attribute==GROUP.Attribute.GROUND_AAA or attribute==GROUP.Attribute.GROUND_SAM then
|
||||
|
||||
--TODO: SEAD/DEAD
|
||||
-- SEAD/DEAD
|
||||
|
||||
-- TODO: Attack radars first? Attack launchers?
|
||||
|
||||
mission=AUFTRAG:NewSEAD(group)
|
||||
|
||||
elseif attribute==GROUP.Attribute.GROUND_ARTILLERY then
|
||||
|
||||
mission=AUFTRAG:NewBAI(group)
|
||||
|
||||
elseif attribute==GROUP.Attribute.GROUND_INFANTRY then
|
||||
|
||||
mission=AUFTRAG:NewBAI(group)
|
||||
|
||||
else
|
||||
|
||||
mission=AUFTRAG:NewBAI(group)
|
||||
|
||||
end
|
||||
|
||||
mission=AUFTRAG:NewBAI(group)
|
||||
|
||||
|
||||
elseif category==Group.Category.SHIP then
|
||||
|
||||
---
|
||||
-- NAVAL
|
||||
---
|
||||
|
||||
--TODO: ANTISHIP
|
||||
|
||||
mission=AUFTRAG:NewANTISHIP(group)
|
||||
|
||||
@@ -961,9 +1002,16 @@ end
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP FlightGroup The FLIGHTGROUP object.
|
||||
function AUFTRAG:DelFlightGroup(FlightGroup)
|
||||
self:I(self.lid..string.format("Removing flight group %s", FlightGroup.groupname))
|
||||
self:I(self.lid..string.format("Removing flight group %s", FlightGroup and FlightGroup.groupname or "nil (ERROR)!"))
|
||||
|
||||
self.flightdata[FlightGroup.groupname]=nil
|
||||
if FlightGroup then
|
||||
|
||||
-- Remove mission form flightgroup queue.
|
||||
FlightGroup:RemoveMission(self)
|
||||
|
||||
self.flightdata[FlightGroup.groupname]=nil
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1082,7 +1130,7 @@ function AUFTRAG:onafterStatus(From, Event, To)
|
||||
local targetname=self:GetTargetName() or "unknown"
|
||||
|
||||
local airwing=self.airwing and self.airwing.alias or "N/A"
|
||||
local commander=self.wingcommander and tosting(self.wingcommander.coalition) or "N/A"
|
||||
local commander=self.wingcommander and tostring(self.wingcommander.coalition) or "N/A"
|
||||
|
||||
-- Info message.
|
||||
self:I(self.lid..string.format("Status %s: Target=%s, T=%s-%s, assets=%d, flights=%d, targets=%d, wing=%s, commander=%s", self.status, targetname, Cstart, Cstop, #self.assets, Nflights, Ntargets, airwing, commander))
|
||||
@@ -1108,6 +1156,9 @@ function AUFTRAG:onafterStatus(From, Event, To)
|
||||
else
|
||||
self:__Status(-30)
|
||||
end
|
||||
|
||||
-- Update F10 marker.
|
||||
self:UpdateMarker()
|
||||
end
|
||||
|
||||
--- Evaluate mission outcome - success or failure.
|
||||
@@ -1181,7 +1232,9 @@ end
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group.
|
||||
-- @param #string status New status.
|
||||
function AUFTRAG:SetFlightStatus(flightgroup, status)
|
||||
self:I(self.lid..string.format("Setting flight %s to status %s", flightgroup and flightgroup.groupname or "nil", tostring(status)))
|
||||
|
||||
env.info("FF trying to get flight status in AUFTRAG:GetFlightStatus")
|
||||
if self:GetFlightStatus(flightgroup)==AUFTRAG.FlightStatus.CANCELLED and status==AUFTRAG.FlightStatus.DONE then
|
||||
-- Do not overwrite a CANCELLED status with a DONE status.
|
||||
else
|
||||
@@ -1189,7 +1242,7 @@ function AUFTRAG:SetFlightStatus(flightgroup, status)
|
||||
if flightdata then
|
||||
flightdata.status=status
|
||||
else
|
||||
self:E(self.lid.."WARNING: Could not SET flight data for flight group. Setting status to DONE.")
|
||||
self:E(self.lid.."WARNING: Could not SET flight data for flight group. Setting status to DONE")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1210,12 +1263,17 @@ end
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group.
|
||||
function AUFTRAG:GetFlightStatus(flightgroup)
|
||||
self:T3(self.lid..string.format("Trying to get Flight status for flight group %s", flightgroup and flightgroup.groupname or "nil"))
|
||||
|
||||
local flightdata=self:GetFlightData(flightgroup)
|
||||
|
||||
if flightdata then
|
||||
return flightdata.status
|
||||
else
|
||||
self:E(self.lid.."WARNING: Could not GET flightdata for flight group. Returning status DONE.")
|
||||
|
||||
self:E(self.lid..string.format("WARNING: Could not GET flightdata for flightgroup %s. Returning status DONE.", flightgroup and flightgroup.groupname or "nil"))
|
||||
return AUFTRAG.FlightStatus.DONE
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1471,8 +1529,14 @@ function AUFTRAG:onafterCancel(From, Event, To)
|
||||
|
||||
-- Debug info.
|
||||
self:I(self.lid..string.format("CANCELLING mission in status %s. Will wait for flights to report mission DONE before evaluation.", self.status))
|
||||
|
||||
if self.wingcommander then
|
||||
|
||||
env.info(string.format("FF calling CancelMission() for wingcommander"))
|
||||
|
||||
self.wingcommander:CancelMission(self)
|
||||
|
||||
if self.airwing then
|
||||
elseif self.airwing then
|
||||
|
||||
env.info(string.format("FF calling MissionCancel() for airwing %s", self.airwing.alias))
|
||||
|
||||
@@ -1489,6 +1553,12 @@ function AUFTRAG:onafterCancel(From, Event, To)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Special mission states.
|
||||
if self.status==AUFTRAG.Status.PLANNED then
|
||||
self:I(self.lid..string.format("Cancelled mission was in planned stage. Call it done!"))
|
||||
self:Done()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1536,8 +1606,10 @@ function AUFTRAG:onafterRepeat(From, Event, To)
|
||||
if self.wingcommander then
|
||||
|
||||
elseif self.airwing then
|
||||
|
||||
-- Already at the airwing ==> Queued()
|
||||
self:Queued(self.airwing)
|
||||
|
||||
else
|
||||
|
||||
end
|
||||
@@ -1546,6 +1618,14 @@ function AUFTRAG:onafterRepeat(From, Event, To)
|
||||
-- No mission assets.
|
||||
self.assets={}
|
||||
|
||||
for _,_flightdata in pairs(self.flightdata) do
|
||||
local flightdata=_flightdata --#AUFTRAG.FlightData
|
||||
local flightgroup=flightdata.flightgroup
|
||||
if flightgroup then
|
||||
self:DelFlightGroup(flightgroup)
|
||||
end
|
||||
|
||||
end
|
||||
-- No flight data.
|
||||
self.flightdata={}
|
||||
|
||||
@@ -1569,7 +1649,7 @@ function AUFTRAG:onafterStop(From, Event, To)
|
||||
-- TODO: Mission should be OVER! we dont want to remove running missions from any queues.
|
||||
|
||||
if self.wingcommander then
|
||||
|
||||
self.wingcommander:RemoveMission(self)
|
||||
end
|
||||
|
||||
if self.airwing then
|
||||
@@ -1656,19 +1736,42 @@ function AUFTRAG:CountMissionTargets()
|
||||
local N=0
|
||||
|
||||
if self.engageTarget then
|
||||
|
||||
if self.engageTarget.Type==AUFTRAG.TargetType.GROUP then
|
||||
|
||||
local target=self.engageTarget.Target --Wrapper.Group#GROUP
|
||||
N=N+target:CountAliveUnits()
|
||||
|
||||
local units=target:GetUnits()
|
||||
for _,_unit in pairs(units) do
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
|
||||
-- We check that unit is "alive" and has health >1. Somtimes units get heavily damanged but are still alive.
|
||||
-- TODO: here I could introduce and count that if units have only health < 50% if mission objective is to just "damage" the units.
|
||||
if unit and unit:IsAlive() and unit:GetLife()>1 then
|
||||
N=N+1
|
||||
end
|
||||
end
|
||||
|
||||
elseif self.engageTarget.Type==AUFTRAG.TargetType.UNIT then
|
||||
|
||||
local target=self.engageTarget.Target --Wrapper.Unit#UNIT
|
||||
if target and target:IsAlive() then
|
||||
|
||||
if target and target:IsAlive() and target:GetLife()>1 then
|
||||
N=N+1
|
||||
end
|
||||
|
||||
elseif self.engageTarget.Type==AUFTRAG.TargetType.STATIC then
|
||||
|
||||
local target=self.engageTarget.Target --Wrapper.Static#STATIC
|
||||
|
||||
if target and target:IsAlive() then
|
||||
N=N+1
|
||||
end
|
||||
|
||||
elseif self.engageTarget.Type==AUFTRAG.TargetType.AIRBASE then
|
||||
|
||||
-- TODO: any (good) way to tell whether an airbase was "destroyed" or at least damaged? Is :GetLive() working?
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1766,6 +1869,24 @@ function AUFTRAG:_SetLogID()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Update mission F10 map marker.
|
||||
-- @param #AUFTRAG self
|
||||
-- @return #AUFTRAG self
|
||||
function AUFTRAG:UpdateMarker()
|
||||
|
||||
local text=string.format("%s %s", self.name, self.status)
|
||||
text=text..string.format("Targets=%d", self:CountMissionTargets())
|
||||
|
||||
|
||||
if self.markerID then
|
||||
COORDINATE.RemoveMark(nil, self.markerID)
|
||||
end
|
||||
|
||||
self.markerID=self:GetTargetCoordinate():MarkToAll(text, true)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get DCS task table for the given mission.
|
||||
-- @param #AUFTRAG self
|
||||
-- @return DCS#Task The DCS task table. If multiple tasks are necessary, this is returned as a combo task.
|
||||
@@ -1917,6 +2038,8 @@ function AUFTRAG:GetDCSMissionTask()
|
||||
-- RECON Mission --
|
||||
-------------------
|
||||
|
||||
-- TODO: What?
|
||||
|
||||
elseif self.type==AUFTRAG.Type.SEAD then
|
||||
|
||||
------------------
|
||||
@@ -1955,6 +2078,8 @@ function AUFTRAG:GetDCSMissionTask()
|
||||
-- TRANSPORT Mission --
|
||||
-----------------------
|
||||
|
||||
-- TODO: What?
|
||||
|
||||
else
|
||||
self:E(self.lid..string.format("ERROR: Unknown mission task!"))
|
||||
return nil
|
||||
|
||||
@@ -1533,17 +1533,22 @@ function FLIGHTGROUP:onafterFlightStatus(From, Event, To)
|
||||
-- Fuel State
|
||||
---
|
||||
|
||||
local fuelmin=self:GetFuelMin()
|
||||
-- Only if group is in air.
|
||||
if self:IsAlive() and self.group:IsAirborne() then
|
||||
|
||||
-- Low fuel?
|
||||
if fuelmin<self.fuellowthresh and not self.fuellow then
|
||||
self:FuelLow()
|
||||
end
|
||||
local fuelmin=self:GetFuelMin()
|
||||
|
||||
-- Critical fuel?
|
||||
if fuelmin<self.fuelcriticalthresh and not self.fuelcritical then
|
||||
self:FuelCritical()
|
||||
end
|
||||
-- Low fuel?
|
||||
if fuelmin<self.fuellowthresh and not self.fuellow then
|
||||
self:FuelLow()
|
||||
end
|
||||
|
||||
-- Critical fuel?
|
||||
if fuelmin<self.fuelcriticalthresh and not self.fuelcritical then
|
||||
self:FuelCritical()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Next check in ~30 seconds.
|
||||
@@ -1688,6 +1693,7 @@ function FLIGHTGROUP:_GetNextMission()
|
||||
-- Look for first mission that is SCHEDULED.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
if mission:GetFlightStatus(self)==AUFTRAG.Status.SCHEDULED and time>=mission.Tstart then
|
||||
return mission
|
||||
end
|
||||
@@ -2389,10 +2395,8 @@ function FLIGHTGROUP:onbeforeUpdateRoute(From, Event, To, n)
|
||||
end
|
||||
|
||||
-- Not good, because mission will never start. Better only check if there is a current task!
|
||||
if self.currentmission then
|
||||
--self:I(self.lid.."FF update route denied because currentmission~=nil")
|
||||
--allowed=false
|
||||
end
|
||||
--if self.currentmission then
|
||||
--end
|
||||
|
||||
-- Debug info.
|
||||
self:T2(self.lid..string.format("Onbefore Updateroute allowed=%s state=%s repeat in %s", tostring(allowed), self:GetState(), tostring(trepeat)))
|
||||
@@ -2594,7 +2598,7 @@ function FLIGHTGROUP:_CheckFlightDone(delay)
|
||||
self:I(self.lid..string.format("Passed Final WP but still have current Tasks (%s) or Missions (%s) left to do", tostring(self.taskcurrent), tostring(self.currentmission)))
|
||||
end
|
||||
else
|
||||
self:I(self.lid.."Did NOT pass the final waypoint yet ==> update route")
|
||||
self:I(self.lid..string.format("Flight (status=%s) did NOT pass the final waypoint yet ==> update route", self:GetState()))
|
||||
self:__UpdateRoute(-1)
|
||||
end
|
||||
end
|
||||
@@ -2775,13 +2779,14 @@ function FLIGHTGROUP:onafterRTB(From, Event, To, airbase, SpeedTo, SpeedHold, Sp
|
||||
-- Respawn?
|
||||
if fc or world.event.S_EVENT_KILL then
|
||||
|
||||
-- Just route the group. Respawn will happen when going from holding to final.
|
||||
env.info("FF route (not repawn)")
|
||||
self:T(self.lid.."FF route (not repawn)")
|
||||
|
||||
-- Just route the group. Respawn might happen when going from holding to final.
|
||||
self:Route(wp, 1)
|
||||
|
||||
else
|
||||
|
||||
env.info("FF respawn (not route)")
|
||||
self:T(self.lid.."FF respawn (not route)")
|
||||
|
||||
-- Get group template.
|
||||
local Template=self.group:GetTemplate()
|
||||
@@ -3204,10 +3209,15 @@ function FLIGHTGROUP:CountRemainingMissison()
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
local status=mission:GetFlightStatus(self)
|
||||
if mission and mission:IsNotOver() then
|
||||
|
||||
if status~=AUFTRAG.FlightStatus.DONE and status~=AUFTRAG.FlightStatus.CANCELLED then
|
||||
N=N+1
|
||||
-- Get flight status.
|
||||
local status=mission:GetFlightStatus(self)
|
||||
|
||||
if status~=AUFTRAG.FlightStatus.DONE and status~=AUFTRAG.FlightStatus.CANCELLED then
|
||||
N=N+1
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3409,18 +3419,18 @@ function FLIGHTGROUP:onafterTaskDone(From, Event, To, Task)
|
||||
-- Check if this task was the task of the current mission ==> Mission Done!
|
||||
local Mission=self:GetMissionByTaskID(Task.id)
|
||||
|
||||
if Mission then
|
||||
if Mission and Mission:IsNotOver() then
|
||||
|
||||
local status=Mission:GetFlightStatus(self)
|
||||
|
||||
if status~=AUFTRAG.FlightStatus.PAUSED then
|
||||
env.info("FF Task Done ==> Mission Done!")
|
||||
self:I(self.lid.."FF Task Done ==> Mission Done!")
|
||||
self:MissionDone(Mission)
|
||||
else
|
||||
--Mission paused. Do nothing!
|
||||
end
|
||||
else
|
||||
env.info("FF Task Done but NO mission found ==> _CheckFlightDone in 1 sec")
|
||||
self:I(self.lid.."FF Task Done but NO mission found ==> _CheckFlightDone in 1 sec")
|
||||
self:_CheckFlightDone(1)
|
||||
end
|
||||
|
||||
@@ -3524,13 +3534,14 @@ function FLIGHTGROUP:onafterPauseMission(From, Event, To)
|
||||
|
||||
if Mission then
|
||||
|
||||
-- Set flight mission status to EXECUTING.
|
||||
-- Set flight mission status to PAUSED.
|
||||
Mission:SetFlightStatus(self, AUFTRAG.FlightStatus.PAUSED)
|
||||
|
||||
-- Get mission waypoint task.
|
||||
local Task=Mission:GetFlightWaypointTask(self)
|
||||
|
||||
env.info(string.format("FF pausing current mission %s. Task=%s", tostring(Mission.name), tostring(Task and Task.description or "WTF")))
|
||||
-- Debug message.
|
||||
self:I(self.lid..string.format("FF pausing current mission %s. Task=%s", tostring(Mission.name), tostring(Task and Task.description or "WTF")))
|
||||
|
||||
-- Cancelling the mission is actually cancelling the current task.
|
||||
self:TaskCancel(Task)
|
||||
@@ -3578,7 +3589,8 @@ function FLIGHTGROUP:onafterMissionCancel(From, Event, To, Mission)
|
||||
-- Get mission waypoint task.
|
||||
local Task=Mission:GetFlightWaypointTask(self)
|
||||
|
||||
env.info(string.format("FF Cancel current mission %s. Task=%s", tostring(Mission.name), tostring(Task and Task.description or "WTF")))
|
||||
-- Debug info.
|
||||
self:I(self.lid..string.format("FF Cancel current mission %s. Task=%s", tostring(Mission.name), tostring(Task and Task.description or "WTF")))
|
||||
|
||||
-- Cancelling the mission is actually cancelling the current task.
|
||||
-- Note that two things can happen.
|
||||
@@ -3650,7 +3662,6 @@ function FLIGHTGROUP:RouteToMission(mission, delay)
|
||||
-- Set altitude of mission waypoint.
|
||||
if mission.missionAltitude then
|
||||
waypointcoord.y=mission.missionAltitude
|
||||
env.info(string.format("FF mission altitude %d m = %d ft", waypointcoord.y, UTILS.MetersToFeet(waypointcoord.y)))
|
||||
end
|
||||
|
||||
-- Add enroute tasks.
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #boolean Debug Debug mode. Messages to all about status.
|
||||
-- @field #string lid Class id string for output to DCS log file.
|
||||
-- @field #number coalition Coalition side number, e.g. coalition.side.RED.
|
||||
-- @field #number coalition Coalition side number, e.g. `coalition.side.RED`.
|
||||
-- @field #string alias Name of the agency.
|
||||
-- @field #table filterCategory Category filters.
|
||||
-- @field Core.Set#SET_ZONE acceptzoneset Set of accept zones. If defined, only contacts in these zones are considered.
|
||||
-- @field Core.Set#SET_ZONE rejectzoneset Set of reject zones. Contacts in these zones are not considered, even if they are in accept zones.
|
||||
@@ -41,6 +42,7 @@ INTEL = {
|
||||
ClassName = "INTEL",
|
||||
Debug = nil,
|
||||
lid = nil,
|
||||
alias = nil,
|
||||
filterCategory = {},
|
||||
detectionset = nil,
|
||||
Contacts = {},
|
||||
@@ -100,17 +102,17 @@ function INTEL:New(DetectionSet, Coalition)
|
||||
self.coalition=Coalition or DetectionSet:CountAlive()>0 and DetectionSet:GetFirst():GetCoalition() or nil
|
||||
|
||||
-- Set alias.
|
||||
local alias="SPECTRE"
|
||||
self.alias="SPECTRE"
|
||||
if self.coalition then
|
||||
if self.coalition==coalition.side.RED then
|
||||
alias="KGB"
|
||||
self.alias="KGB"
|
||||
elseif self.coalition==coalition.side.BLUE then
|
||||
alias="CIA"
|
||||
self.alias="CIA"
|
||||
end
|
||||
end
|
||||
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("INTEL %s | ", alias)
|
||||
self.lid=string.format("INTEL %s | ", self.alias)
|
||||
|
||||
-- Start State.
|
||||
self:SetStartState("Stopped")
|
||||
|
||||
@@ -89,7 +89,7 @@ function WINGCOMMANDER:New(AgentSet, Coalition)
|
||||
AgentSet=AgentSet or SET_GROUP:New()
|
||||
|
||||
-- Inherit everything from INTEL class.
|
||||
local self=BASE:Inherit(self, INTEL:New(AgentSet)) --#WINGCOMMANDER
|
||||
local self=BASE:Inherit(self, INTEL:New(AgentSet, Coalition)) --#WINGCOMMANDER
|
||||
|
||||
-- Set some string id for output to DCS.log file.
|
||||
--self.lid=string.format("WINGCOMMANDER | ")
|
||||
@@ -99,6 +99,7 @@ function WINGCOMMANDER:New(AgentSet, Coalition)
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("*", "MissionAssign", "*") -- Mission was assigned to an AIRWING.
|
||||
self:AddTransition("*", "CancelMission", "*") -- Cancel mission.
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
@@ -168,6 +169,8 @@ end
|
||||
-- @return #WINGCOMMANDER self
|
||||
function WINGCOMMANDER:AddMission(Mission)
|
||||
|
||||
Mission.wingcommander=self
|
||||
|
||||
table.insert(self.missionqueue, Mission)
|
||||
|
||||
return self
|
||||
@@ -183,6 +186,7 @@ function WINGCOMMANDER:RemoveMission(Mission)
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
if mission.auftragsnummer==Mission.auftragsnummer then
|
||||
self:I(self.lid..string.format("Removing mission %s (%s) status=%s from queue", Mission.name, Mission.type, Mission.status))
|
||||
table.remove(self.missionqueue, i)
|
||||
break
|
||||
end
|
||||
@@ -210,9 +214,13 @@ end
|
||||
-- @param Core.Zone#ZONEBorderZone Add a zone to the accept zone set.
|
||||
-- @return #WINGCOMMANDER self
|
||||
function WINGCOMMANDER:AddBorderZone(BorderZone)
|
||||
|
||||
-- Add a border zone.
|
||||
self.borderzoneset:AddZone(BorderZone)
|
||||
|
||||
-- Set accept zone.
|
||||
self:AddAcceptZone(BorderZone)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -304,6 +312,18 @@ function WINGCOMMANDER:onafterStatus(From, Event, To)
|
||||
|
||||
-- Check mission queue and assign one PLANNED mission.
|
||||
self:CheckMissionQueue()
|
||||
|
||||
if #self.missionqueue>0 then
|
||||
local text="Mission queue:"
|
||||
for i,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
local target=mission:GetTargetName() or "unknown"
|
||||
|
||||
text=text..string.format("\n[%d] %s (%s): status=%s, target=%s", i, mission.name, mission.type, mission.status, target)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -320,10 +340,37 @@ end
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
function WINGCOMMANDER:onafterMissionAssign(From, Event, To, Airwing, Mission)
|
||||
|
||||
self:I(self.lid..string.format("Assigning mission %s (%s) to airwing %s", Mission.name, Mission.type, Airwing.alias))
|
||||
Airwing:AddMission(Mission)
|
||||
|
||||
end
|
||||
|
||||
--- On after "CancelMission" event.
|
||||
-- @param #WINGCOMMANDER self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
function WINGCOMMANDER:onafterCancelMission(From, Event, To, Mission)
|
||||
|
||||
self:I(self.lid..string.format("Cancelling mission %s (%s) in status %s", Mission.name, Mission.type, Mission.status))
|
||||
|
||||
if Mission.status==AUFTRAG.Status.PLANNED then
|
||||
|
||||
-- Mission is still in planning stage. Should not have an airbase assigned ==> Just remove it form the queue.
|
||||
self:RemoveMission(Mission)
|
||||
|
||||
else
|
||||
|
||||
-- Airwing will cancel mission.
|
||||
if Mission.airwing then
|
||||
Mission.airwing:MissionCancel(Mission)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Resources
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user