mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-08 09:18:06 +00:00
Ops
This commit is contained in:
@@ -1102,7 +1102,7 @@ do -- COORDINATE
|
||||
--RoutePoint.formation_template=""
|
||||
|
||||
-- Debug.
|
||||
self:I({RoutePoint=RoutePoint})
|
||||
self:T({RoutePoint=RoutePoint})
|
||||
|
||||
-- Return waypoint.
|
||||
return RoutePoint
|
||||
|
||||
@@ -5605,6 +5605,7 @@ function WAREHOUSE:_SpawnAssetAircraft(alias, asset, request, parking, uncontrol
|
||||
-- Debug info.
|
||||
self:T2({airtemplate=template})
|
||||
|
||||
-- Create a flight group.
|
||||
FLIGHTGROUP:New(template.name)
|
||||
|
||||
-- Spawn group.
|
||||
@@ -8597,10 +8598,12 @@ function WAREHOUSE:_GetFlightplan(asset, departure, destination)
|
||||
wp[#wp+1]=Pdescent:WaypointAir("BARO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, VxDescent*3.6, true, nil, nil, "Descent")
|
||||
|
||||
--- Holding point
|
||||
Pholding.y=H_holding+h_holding
|
||||
c[#c+1]=Pholding
|
||||
wp[#wp+1]=Pholding:WaypointAir("BARO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, VxHolding*3.6, true, nil, nil, "Holding")
|
||||
|
||||
if not _DATABASE:GetFlightControl(destination:GetName()) then
|
||||
Pholding.y=H_holding+h_holding
|
||||
c[#c+1]=Pholding
|
||||
wp[#wp+1]=Pholding:WaypointAir("BARO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, VxHolding*3.6, true, nil, nil, "Holding")
|
||||
end
|
||||
|
||||
--- Final destination.
|
||||
c[#c+1]=Pdestination
|
||||
wp[#wp+1]=Pdestination:WaypointAir("RADIO", COORDINATE.WaypointType.Land, COORDINATE.WaypointAction.Landing, VxFinal*3.6, true, destination, nil, "Final Destination")
|
||||
|
||||
@@ -268,7 +268,13 @@ function ATIS:onafterBroadcast(From, Event, To)
|
||||
|
||||
-- TODO add zulu time correction.
|
||||
if self.theatre==DCSMAP.Caucasus then
|
||||
time=time-4*60*60 -- Caucasus i UTC+4 hours
|
||||
time=time-4*60*60 -- Caucasus i UTC+4 hours
|
||||
elseif self.theatre==DCSMAP.PersianGulf then
|
||||
time=time-4*60*60 -- Abu Dhabi UTC+4 hours
|
||||
elseif self.theatre==DCSMAP.NTTR then
|
||||
time=time+7*60*60 -- Las Vegas UTC-7 hours
|
||||
elseif self.theatre==DCSMAP.Normandy then
|
||||
time=time-1*60*60 -- Calais UTC+1 hour
|
||||
end
|
||||
|
||||
local clock=UTILS.SecondsToClock(time)
|
||||
@@ -302,7 +308,6 @@ function ATIS:onafterBroadcast(From, Event, To)
|
||||
|
||||
local VISIBILITY=string.format("%d", UTILS.Round(UTILS.MetersToNM(visibilitymin)))
|
||||
|
||||
|
||||
--------------
|
||||
--- Clouds ---
|
||||
--------------
|
||||
|
||||
@@ -65,6 +65,7 @@ FLIGHTCONTROL = {
|
||||
activerwyno = 1,
|
||||
atcfreq = nil,
|
||||
atcradio = nil,
|
||||
atcradiounitname = nil,
|
||||
}
|
||||
|
||||
--- Holding point
|
||||
@@ -123,6 +124,15 @@ function FLIGHTCONTROL:New(airbasename)
|
||||
|
||||
self.airbase=AIRBASE:FindByName(airbasename)
|
||||
|
||||
if not self.airbase then
|
||||
self:E(string.format("ERROR: Could not find airbase %s!", tostring(airbasename)))
|
||||
return nil
|
||||
end
|
||||
if self.airbase:GetAirbaseCategory()~=Airbase.Category.AIRDROME then
|
||||
self:E(string.format("ERROR: Airbase %s is not an AIRDROMOE! Script does not handle FARPS or ships.", tostring(airbasename)))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Name of the airbase.
|
||||
self.airbasename=airbasename
|
||||
|
||||
@@ -255,7 +265,7 @@ function FLIGHTCONTROL:onafterStatus()
|
||||
local nfree=self:_GetFreeParkingSpots()
|
||||
|
||||
-- Info text.
|
||||
local text=string.format("State %s - Active Runway %03d - Free Parking %d", self:GetState(), runway.direction, nfree)
|
||||
local text=string.format("State %s - Active Runway %s - Free Parking %d", self:GetState(), runway.idx, nfree)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Next status update in ~30 seconds.
|
||||
@@ -518,16 +528,15 @@ function FLIGHTCONTROL:_GetNextFightParking()
|
||||
end
|
||||
|
||||
-- Sort flights parking time.
|
||||
local function _sortByTholding(a, b)
|
||||
local function _sortByTparking(a, b)
|
||||
local flightA=a --Ops.FlightGroup#FLIGHTGROUP
|
||||
local flightB=b --Ops.FlightGroup#FLIGHTGROUP
|
||||
return flightA.Tparking<flightB.Tparking
|
||||
end
|
||||
|
||||
-- Return flight waiting longest.
|
||||
table.sort(self.Qwaiting, _sortByTholding)
|
||||
table.sort(self.Qparking, _sortByTparking)
|
||||
return self.Qparking[1]
|
||||
|
||||
end
|
||||
|
||||
--- Print queue.
|
||||
@@ -541,30 +550,33 @@ function FLIGHTCONTROL:_PrintQueue(queue, name)
|
||||
-- Queue is empty.
|
||||
text=text.." empty."
|
||||
else
|
||||
|
||||
local time=timer.getAbsTime()
|
||||
|
||||
-- Loop over all flights in queue.
|
||||
for i,_flight in ipairs(queue) do
|
||||
local flight=_flight --Ops.FlightGroup#FLIGHTGROUP
|
||||
|
||||
-- Gather info.
|
||||
local clock="0:0" --UTILS.SecondsToClock(timer.getAbsTime()-flight.time)
|
||||
local fuel=flight.group:GetFuelMin()*100
|
||||
local ai=tostring(flight.ai)
|
||||
local actype=tostring(flight.actype)
|
||||
local holding=tostring(flight.holding)
|
||||
local holding=flight.Tholding and UTILS.SecondsToClock(flight.Tholding-time, true) or "X"
|
||||
local parking=flight.Tparking and UTILS.SecondsToClock(flight.Tparking-time, true) or "X"
|
||||
|
||||
local nunits=flight.nunits or 1
|
||||
|
||||
-- Main info.
|
||||
text=text..string.format("\n[%d] %s (%s*%d): ai=%s, timestamp=%s, fuel=%d, inzone=%s, holding=%s",
|
||||
i, flight.groupname, actype, nunits, ai, clock, fuel, tostring(flight.inzone), holding)
|
||||
text=text..string.format("\n[%d] %s (%s*%d): status=%s, ai=%s, fuel=%d, holding=%s, parking=%s",
|
||||
i, flight.groupname, actype, nunits, flight:GetState(), ai, fuel, holding, parking)
|
||||
|
||||
-- Elements info.
|
||||
for j,_element in pairs(flight.elements) do
|
||||
local element=_element --Ops.FlightGroup#FLIGHTGROUP.Element
|
||||
local life=element.unit:GetLife()
|
||||
local life0=element.unit:GetLife0()
|
||||
text=text..string.format("\n (%d) %s (%s): ai=%s, status=%s,, airborne=%s life=%.1f/%.1f",
|
||||
j, tostring(element.modex), element.name, tostring(element.ai) ,tostring(element.status), tostring(element.unit:InAir()), life, life0)
|
||||
text=text..string.format("\n (%d) %s (%s): status=%s, ai=%s, airborne=%s life=%.1f/%.1f",
|
||||
j, tostring(element.modex), element.name, tostring(element.status), tostring(element.ai), tostring(element.unit:InAir()), life, life0)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -706,117 +718,14 @@ end
|
||||
--- Initialize data of runways.
|
||||
-- @param #FLIGHTCONTROL self
|
||||
function FLIGHTCONTROL:_InitRunwayData()
|
||||
|
||||
-- Get spawn points on runway.
|
||||
local runwaycoords=self.airbase:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
||||
|
||||
self:E(self.lid..string.format("Runway coords # = %d", #runwaycoords))
|
||||
|
||||
for i=1,#runwaycoords,2 do
|
||||
|
||||
-- Assuming each runway has two points.
|
||||
local j=(i+1)/2
|
||||
|
||||
-- Coordinates of the two runway points.
|
||||
local c1=runwaycoords[i] --Core.Point#COORDINATES
|
||||
local c2=runwaycoords[i+1] --Core.Point#COORDINATES
|
||||
|
||||
-- Debug mark
|
||||
c1:MarkToAll("Runway Point 1")
|
||||
c2:MarkToAll("Runway Point 2")
|
||||
|
||||
-- Heading of runway.
|
||||
local hdg=c1:HeadingTo(c2)
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Runway %d heading=%03d", j, hdg))
|
||||
|
||||
-- Runway table.
|
||||
local runway={} --#FLIGHTCONTROL.Runway
|
||||
runway.direction=hdg
|
||||
runway.length=c1:Get2DDistance(c2)
|
||||
runway.position=c1
|
||||
|
||||
self:I(self.lid..string.format("Adding runway #%d: heading=%03d, lendth=%d m", #self.runways+1, runway.direction, runway.length))
|
||||
|
||||
-- Add runway.
|
||||
table.insert(self.runways, runway)
|
||||
|
||||
-- Inverse runway.
|
||||
local runway={} --#FLIGHTCONTROL.Runway
|
||||
local hdg=hdg-180
|
||||
if hdg<0 then
|
||||
hdg=hdg+360
|
||||
end
|
||||
runway.direction=hdg
|
||||
runway.length=c1:Get2DDistance(c2)
|
||||
runway.position=c2
|
||||
|
||||
self:I(self.lid..string.format("Adding runway #%d: heading=%03d, lendth=%d m", #self.runways+1, runway.direction, runway.length))
|
||||
|
||||
-- Add inverse runway.
|
||||
table.insert(self.runways, runway)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Get wind.
|
||||
-- @param #FLIGHTCONTROL self
|
||||
-- @return #FLIGHTCONTROL.Runway Active runway.
|
||||
function FLIGHTCONTROL:GetWindVector(altitude)
|
||||
|
||||
self.runways=self.airbase:GetRunwayData()
|
||||
end
|
||||
|
||||
--- Get the active runway based on current wind direction.
|
||||
-- @param #FLIGHTCONTROL self
|
||||
-- @return #FLIGHTCONTROL.Runway Active runway.
|
||||
-- @return Wrapper.Airbase#AIRBASE.Runway Active runway.
|
||||
function FLIGHTCONTROL:GetActiveRunway()
|
||||
|
||||
-- TODO: get runway.
|
||||
local iact=math.max(self.activerwyno, #self.runways)
|
||||
|
||||
-- Get wind vector.
|
||||
local Vwind=self:GetCoordinate():GetWindWithTurbulenceVec3()
|
||||
local norm=UTILS.VecNorm(Vwind)
|
||||
|
||||
-- Check if wind is blowing (norm>0).
|
||||
if norm>0 then
|
||||
|
||||
-- Normalize wind (not necessary).
|
||||
Vwind.x=Vwind.x/norm
|
||||
Vwind.y=0
|
||||
Vwind.z=Vwind.z/norm
|
||||
|
||||
-- Debug.
|
||||
self:T3({Vwind=Vwind})
|
||||
|
||||
-- Loop over runways.
|
||||
local dotmin=nil
|
||||
for i,_runway in pairs(self.runways) do
|
||||
local runway=_runway --#FLIGHTCONTROL.Runway
|
||||
|
||||
-- Angle in rad.
|
||||
local alpha=math.rad(runway.direction)
|
||||
|
||||
-- Runway vector.
|
||||
local Vrunway={x=math.cos(alpha), y=0, z=math.sin(alpha)}
|
||||
|
||||
-- Dot product: parallel component of the two vectors.
|
||||
local dot=UTILS.VecDot(Vwind, Vrunway)
|
||||
|
||||
-- Debug.
|
||||
env.info(string.format("runway=%03d° dot=%.3f", runway.direction, dot))
|
||||
|
||||
-- New min?
|
||||
if dotmin==nil or dot<dotmin then
|
||||
dotmin=dot
|
||||
iact=i
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
return self.runways[iact]
|
||||
return self.airbase:GetActiveRunway()
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1285,14 +1194,14 @@ function FLIGHTCONTROL:_GetHoldingpoint(flight)
|
||||
|
||||
local runway=self:GetActiveRunway()
|
||||
|
||||
local hdg=runway.direction+90
|
||||
local hdg=runway.heading+90
|
||||
local dx=UTILS.NMToMeters(5)
|
||||
local dz=UTILS.NMToMeters(1)
|
||||
|
||||
local angels=UTILS.FeetToMeters(math.random(6,10)*1000)
|
||||
|
||||
holdingpoint.pos0=runway.position:Translate(dx, hdg):SetAltitude(angels)
|
||||
holdingpoint.pos1=holdingpoint.pos0:Translate(dz, runway.direction):SetAltitude(angels)
|
||||
holdingpoint.pos1=holdingpoint.pos0:Translate(dz, runway.heading):SetAltitude(angels)
|
||||
|
||||
return holdingpoint
|
||||
end
|
||||
|
||||
@@ -32,6 +32,11 @@
|
||||
-- @field Core.Set#SET_UNIT detectedunits Set of detected units.
|
||||
-- @field Wrapper.Airbase#AIRBASE homebase The home base of the flight group.
|
||||
-- @field Wrapper.Airbase#AIRBASE destination The destination base of the flight group.
|
||||
-- @field #string actype Type name of the aircraft.
|
||||
-- @field #number speedmax Max speed in km/h.
|
||||
-- @field #number range Range of the aircraft in km.
|
||||
-- @field #number ceiling Max altitude the aircraft can fly at in meters.
|
||||
-- @field #boolean ai If true, flight is purely AI. If false, flight contains at least one human player.
|
||||
-- @field #boolean fuellow Fuel low switch.
|
||||
-- @field #number fuellowthresh Low fuel threshold in percent.
|
||||
-- @field #boolean fuellowrtb RTB on low fuel switch.
|
||||
@@ -61,7 +66,7 @@ FLIGHTGROUP = {
|
||||
Debug = nil,
|
||||
sid = nil,
|
||||
groupname = nil,
|
||||
flightgroup = nil,
|
||||
group = nil,
|
||||
grouptemplate = nil,
|
||||
type = nil,
|
||||
waypoints = nil,
|
||||
@@ -73,9 +78,10 @@ FLIGHTGROUP = {
|
||||
detectedunits = {},
|
||||
homebase = nil,
|
||||
destination = nil,
|
||||
actype = nil,
|
||||
speedmax = nil,
|
||||
range = nil,
|
||||
altmax = nil,
|
||||
ceiling = nil,
|
||||
fuellow = false,
|
||||
fuellowthresh = nil,
|
||||
fuellowrtb = nil,
|
||||
@@ -214,6 +220,13 @@ FLIGHTGROUP.version="0.1.2"
|
||||
-- @return #FLIGHTGROUP self
|
||||
function FLIGHTGROUP:New(groupname)
|
||||
|
||||
-- First check if we already have a flight group for this group.
|
||||
local fg=_DATABASE:GetFlightGroup(groupname)
|
||||
if fg then
|
||||
fg:I(fg.sid..string.format("WARNING: Flight group %s already exists in data base!", groupname))
|
||||
return fg
|
||||
end
|
||||
|
||||
-- Inherit everything from WAREHOUSE class.
|
||||
local self=BASE:Inherit(self, FSM:New()) -- #FLIGHTGROUP
|
||||
|
||||
@@ -271,7 +284,7 @@ function FLIGHTGROUP:New(groupname)
|
||||
self:AddTransition("*", "ElementParking", "*") -- An element was spawned.
|
||||
self:AddTransition("*", "ElementTaxiing", "*") -- An element spooled up the engines.
|
||||
self:AddTransition("*", "ElementTakeoff", "*") -- An element took off.
|
||||
self:AddTransition("*", "ElementAirborne", "*") -- An element took off.
|
||||
self:AddTransition("*", "ElementAirborne", "*") -- An element is airborne.
|
||||
self:AddTransition("*", "ElementLanded", "*") -- An element landed.
|
||||
self:AddTransition("*", "ElementArrived", "*") -- An element arrived.
|
||||
self:AddTransition("*", "ElementDead", "*") -- An element crashed, ejected, or pilot dead.
|
||||
@@ -320,7 +333,7 @@ function FLIGHTGROUP:New(groupname)
|
||||
|
||||
|
||||
-- Debug trace.
|
||||
if false then
|
||||
if true then
|
||||
self.Debug=true
|
||||
BASE:TraceOnOff(true)
|
||||
BASE:TraceClass(self.ClassName)
|
||||
@@ -349,7 +362,7 @@ end
|
||||
-- User functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Add scheduled task.
|
||||
--- Add a *scheduled* task.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string description Brief text describing the task, e.g. "Attack SAM".
|
||||
-- @param #table task DCS task table stucture.
|
||||
@@ -392,7 +405,7 @@ function FLIGHTGROUP:AddTask(description, task, prio, clock, duration)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add waypoint task.
|
||||
--- Add a *waypoint* task.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string description Brief text describing the task, e.g. "Attack SAM".
|
||||
-- @param #table task DCS task table stucture.
|
||||
@@ -823,7 +836,7 @@ function FLIGHTGROUP:OnEventBirth(EventData)
|
||||
if not self:_IsElement(unitname) then
|
||||
local element=self:AddElementByName(unitname)
|
||||
|
||||
self:I(self.sid..string.format("EVENT: Element %s born ==> spawned", element.name))
|
||||
self:T3(self.sid..string.format("EVENT: Element %s born ==> spawned", element.name))
|
||||
|
||||
self:ElementSpawned(element)
|
||||
end
|
||||
@@ -849,7 +862,7 @@ function FLIGHTGROUP:OnEventEngineStartup(EventData)
|
||||
if element then
|
||||
if self:IsAirborne() or self:IsHolding() then
|
||||
else
|
||||
self:I(self.sid..string.format("EVENT: Element %s started engines ==> taxiing", element.name))
|
||||
self:T3(self.sid..string.format("EVENT: Element %s started engines ==> taxiing", element.name))
|
||||
self:ElementTaxiing(element)
|
||||
end
|
||||
end
|
||||
@@ -873,7 +886,7 @@ function FLIGHTGROUP:OnEventTakeOff(EventData)
|
||||
local element=self:GetElementByName(unitname)
|
||||
|
||||
if element then
|
||||
self:I(self.sid..string.format("EVENT: Element %s took off ==> airborne", element.name))
|
||||
self:T3(self.sid..string.format("EVENT: Element %s took off ==> airborne", element.name))
|
||||
self:ElementTakeoff(element, EventData.Place)
|
||||
end
|
||||
|
||||
@@ -903,7 +916,7 @@ function FLIGHTGROUP:OnEventLanding(EventData)
|
||||
end
|
||||
|
||||
if element then
|
||||
self:I(self.sid..string.format("EVENT: Element %s landed at %s ==> landed", element.name, airbasename))
|
||||
self:T3(self.sid..string.format("EVENT: Element %s landed at %s ==> landed", element.name, airbasename))
|
||||
self:ElementLanded(element, airbase)
|
||||
end
|
||||
|
||||
@@ -937,15 +950,15 @@ function FLIGHTGROUP:OnEventEngineShutdown(EventData)
|
||||
|
||||
if dist and dist<10 and unit:InAir()==false then
|
||||
self:ElementArrived(element, airbase, parking)
|
||||
self:I(self.sid..string.format("EVENT: Element %s shut down engines ==> arrived", element.name))
|
||||
self:T3(self.sid..string.format("EVENT: Element %s shut down engines ==> arrived", element.name))
|
||||
else
|
||||
self:I(self.sid..string.format("EVENT: Element %s shut down engines (in air) ==> dead", element.name))
|
||||
self:T3(self.sid..string.format("EVENT: Element %s shut down engines (in air) ==> dead", element.name))
|
||||
self:ElementDead(element)
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
self:I(self.sid..string.format("EVENT: Element %s shut down engines but is NOT alive ==> waiting for crash event (==> dead)", element.name))
|
||||
self:T(self.sid..string.format("EVENT: Element %s shut down engines but is NOT alive ==> waiting for crash event (==> dead)", element.name))
|
||||
|
||||
end
|
||||
|
||||
@@ -972,7 +985,7 @@ function FLIGHTGROUP:OnEventCrash(EventData)
|
||||
local element=self:GetElementByName(unitname)
|
||||
|
||||
if element then
|
||||
self:I(self.sid..string.format("EVENT: Element %s crashed ==> dead", element.name))
|
||||
self:T3(self.sid..string.format("EVENT: Element %s crashed ==> dead", element.name))
|
||||
self:ElementDead(element)
|
||||
end
|
||||
|
||||
@@ -1034,7 +1047,7 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param #FLIGHTGROUP.Element Element The flight group element.
|
||||
function FLIGHTGROUP:onafterElementTaxiing(From, Event, To, Element)
|
||||
self:I(self.sid..string.format("Element taxiing %s.", Element.name))
|
||||
self:T2(self.sid..string.format("Element taxiing %s.", Element.name))
|
||||
|
||||
-- Not parking any more.
|
||||
Element.parking=nil
|
||||
@@ -1051,13 +1064,13 @@ end
|
||||
-- @param #FLIGHTGROUP.Element Element The flight group element.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase if applicable or nil.
|
||||
function FLIGHTGROUP:onafterElementTakeoff(From, Event, To, Element, airbase)
|
||||
self:I(self.sid..string.format("Element airborne %s.", Element.name))
|
||||
self:T(self.sid..string.format("Element takeoff %s at %s airbase.", Element.name, airbase and airbase:GetName() or "unknown"))
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, FLIGHTGROUP.ElementStatus.TAKEOFF, airbase)
|
||||
|
||||
-- Trigger element airborne event.
|
||||
self:__ElementAirborne(1, Element)
|
||||
self:__ElementAirborne(10, Element)
|
||||
end
|
||||
|
||||
--- On after "ElementAirborne" event.
|
||||
@@ -1067,7 +1080,7 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param #FLIGHTGROUP.Element Element The flight group element.
|
||||
function FLIGHTGROUP:onafterElementAirborne(From, Event, To, Element)
|
||||
self:I(self.sid..string.format("Element airborne %s.", Element.name))
|
||||
self:T2(self.sid..string.format("Element airborne %s", Element.name))
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, FLIGHTGROUP.ElementStatus.AIRBORNE)
|
||||
@@ -1081,7 +1094,7 @@ end
|
||||
-- @param #FLIGHTGROUP.Element Element The flight group element.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase if applicable or nil.
|
||||
function FLIGHTGROUP:onafterElementLanded(From, Event, To, Element, airbase)
|
||||
self:I(self.sid..string.format("Element landed %s at %s", Element.name, airbase and airbase:GetName() or "unknown"))
|
||||
self:T2(self.sid..string.format("Element landed %s at %s airbase", Element.name, airbase and airbase:GetName() or "unknown"))
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, FLIGHTGROUP.ElementStatus.LANDED, airbase)
|
||||
@@ -1094,7 +1107,7 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param #FLIGHTGROUP.Element Element The flight group element.
|
||||
function FLIGHTGROUP:onafterElementArrived(From, Event, To, Element)
|
||||
self:I(self.sid..string.format("Element arrived %s.", Element.name))
|
||||
self:T2(self.sid..string.format("Element arrived %s.", Element.name))
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, FLIGHTGROUP.ElementStatus.ARRIVED)
|
||||
@@ -1107,7 +1120,7 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param #FLIGHTGROUP.Element Element The flight group element.
|
||||
function FLIGHTGROUP:onafterElementDead(From, Event, To, Element)
|
||||
self:I(self.sid..string.format("Element dead %s.", Element.name))
|
||||
self:T2(self.sid..string.format("Element dead %s.", Element.name))
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, FLIGHTGROUP.ElementStatus.DEAD)
|
||||
@@ -1127,6 +1140,22 @@ function FLIGHTGROUP:onafterFlightSpawned(From, Event, To)
|
||||
|
||||
-- Max speed in km/h.
|
||||
self.speedmax=self.group:GetSpeedMax()
|
||||
|
||||
local unit=self.group:GetUnit(1)
|
||||
|
||||
self.descriptors=unit:GetDesc()
|
||||
|
||||
self.actype=unit:GetTypeName()
|
||||
|
||||
self.ceiling=self.descriptors.Hmax
|
||||
|
||||
self.ai=self:_IsHuman(self.group)
|
||||
|
||||
for _,_element in pairs(self.elements) do
|
||||
local element=_element --#FLIGHTGROUP.Element
|
||||
element.ai=self:_IsHumanUnit(element.unit)
|
||||
|
||||
end
|
||||
|
||||
-- Init waypoints.
|
||||
if not self.waypoints then
|
||||
@@ -1172,7 +1201,7 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FLIGHTGROUP:onafterFlightTaxiing(From, Event, To)
|
||||
self:I(self.sid..string.format("Flight is taxiing %s.", self.groupname))
|
||||
self:T(self.sid..string.format("Flight is taxiing %s.", self.groupname))
|
||||
|
||||
-- Parking over.
|
||||
self.Tparking=nil
|
||||
@@ -1197,7 +1226,7 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase the flight landed.
|
||||
function FLIGHTGROUP:onafterFlightTakeoff(From, Event, To, airbase)
|
||||
self:I(self.sid..string.format("Flight takeoff %s at %s.", self.groupname, airbase and airbase:GetName() or "unknown airbase"))
|
||||
self:T(self.sid..string.format("Flight takeoff %s at %s.", self.groupname, airbase and airbase:GetName() or "unknown airbase"))
|
||||
|
||||
if self.flightcontrol and airbase and self.flightcontrol.airbasename==airbase:GetName() then
|
||||
self.flightcontrol:_RemoveFlightFromQueue(self.flightcontrol.Qtakeoff, self, "takeoff")
|
||||
@@ -1215,7 +1244,7 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase the flight landed.
|
||||
function FLIGHTGROUP:onafterFlightAirborne(From, Event, To, airbase)
|
||||
self:I(self.sid..string.format("Flight airborne %s at %s.", self.groupname,airbase and airbase:GetName() or "unknown airbase"))
|
||||
self:T(self.sid..string.format("Flight airborne %s at %s.", self.groupname,airbase and airbase:GetName() or "unknown airbase"))
|
||||
|
||||
-- Remove flight from FC takeoff queue.
|
||||
if self.flightcontrol and airbase and self.flightcontrol.airbasename==airbase:GetName() then
|
||||
@@ -1233,7 +1262,7 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FLIGHTGROUP:onafterFlightLanding(From, Event, To)
|
||||
self:I(self.sid..string.format("Flight landing %s", self.groupname))
|
||||
self:T(self.sid..string.format("Flight landing %s", self.groupname))
|
||||
|
||||
self:_SetElementStatusAll(FLIGHTGROUP.ElementStatus.LANDING)
|
||||
|
||||
@@ -1246,7 +1275,7 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase the flight landed.
|
||||
function FLIGHTGROUP:onafterFlightLanded(From, Event, To, airbase)
|
||||
self:I(self.sid..string.format("Flight landed %s at %s.", self.groupname, airbase and airbase:GetName() or "unknown airbase"))
|
||||
self:T(self.sid..string.format("Flight landed %s at %s.", self.groupname, airbase and airbase:GetName() or "unknown airbase"))
|
||||
|
||||
if self.flightcontrol and airbase and self.flightcontrol.airbasename==airbase:GetName() then
|
||||
self.flightcontrol:_RemoveFlightFromQueue(self.flightcontrol.Qlanding, self, "landing")
|
||||
@@ -1261,9 +1290,9 @@ end
|
||||
-- @param #number n Waypoint number passed.
|
||||
-- @param #number N Final waypoint number.
|
||||
function FLIGHTGROUP:onafterPassingWaypoint(From, Event, To, n, N)
|
||||
local text=string.format("Group %s passed waypoint %d/%d", self.groupname, n, N)
|
||||
self:I(self.sid..text)
|
||||
MESSAGE:New(text, 20, "DEBUG"):ToAllIf(self.Debug)
|
||||
local text=string.format("Flight %s passed waypoint %d/%d", self.groupname, n, N)
|
||||
self:T(self.sid..text)
|
||||
MESSAGE:New(text, 30, "DEBUG"):ToAllIf(self.Debug)
|
||||
end
|
||||
|
||||
--- On after "FuelLow" event.
|
||||
@@ -1275,7 +1304,7 @@ function FLIGHTGROUP:onafterFuelLow(From, Event, To)
|
||||
|
||||
-- Debug message.
|
||||
local text=string.format("Low fuel for flight group %s", self.groupname)
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
MESSAGE:New(text, 30, "DEBUG"):ToAllIf(self.Debug)
|
||||
self:I(self.sid..text)
|
||||
|
||||
-- Set switch to true.
|
||||
@@ -1298,7 +1327,7 @@ function FLIGHTGROUP:onafterFuelCritical(From, Event, To)
|
||||
|
||||
-- Debug message.
|
||||
local text=string.format("Critical fuel for flight group %s", self.groupname)
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
MESSAGE:New(text, 30, "DEBUG"):ToAllIf(self.Debug)
|
||||
self:I(self.sid..text)
|
||||
|
||||
-- Set switch to true.
|
||||
@@ -1323,7 +1352,7 @@ function FLIGHTGROUP:onafterRTB(From, Event, To, airbase)
|
||||
|
||||
-- Debug message.
|
||||
local text=string.format("Flight group returning to airbase %s.", airbase:GetName())
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
MESSAGE:New(text, 30, "DEBUG"):ToAllIf(self.Debug)
|
||||
self:I(self.sid..text)
|
||||
|
||||
-- Route helo back home. It is respawned! But this is the only way to ensure that it actually lands at the airbase.
|
||||
@@ -1342,7 +1371,7 @@ function FLIGHTGROUP:onafterOrbit(From, Event, To, Coord, Altitude, Speed)
|
||||
|
||||
-- Debug message.
|
||||
local text=string.format("Flight group set to orbit at altitude %d m and speed %.1f km/h", Altitude, Speed)
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
MESSAGE:New(text, 30, "DEBUG"):ToAllIf(self.Debug)
|
||||
self:I(self.sid..text)
|
||||
|
||||
--TODO: set ROE passive. introduce roe event/state/variable.
|
||||
@@ -1428,14 +1457,14 @@ function FLIGHTGROUP:onafterHold(From, Event, To, airbase, SpeedTo, SpeedHold, S
|
||||
local runway=fc:GetActiveRunway()
|
||||
|
||||
-- Approach point: 10 NN in direction of runway.
|
||||
local papp=airbase:GetCoordinate():Translate(x1, runway.direction-180):SetAltitude(h1)
|
||||
local papp=airbase:GetCoordinate():Translate(x1, runway.heading-180):SetAltitude(h1)
|
||||
papp:MarkToAll(string.format("Final Approach: d=%d m, h=%d m", x1, h1))
|
||||
wpap=papp:WaypointAirTurningPoint(nil, UTILS.KnotsToKmph(SpeedLand), {}, "Final Approach")
|
||||
|
||||
-- TODO: make dependend on AC type helos etc.
|
||||
|
||||
-- Approach point: 10 NN in direction of runway.
|
||||
pland=airbase:GetCoordinate():Translate(x2, runway.direction-180):SetAltitude(h2)
|
||||
pland=airbase:GetCoordinate():Translate(x2, runway.heading-180):SetAltitude(h2)
|
||||
pland:MarkToAll(string.format("Landing: d=%d m, h=%d m", x2, h2))
|
||||
|
||||
-- Set flightcontrol for this flight.
|
||||
@@ -1525,9 +1554,20 @@ function FLIGHTGROUP:onafterTaskExecute(From, Event, To, Task)
|
||||
|
||||
-- Task done.
|
||||
local TaskDone=self.group:TaskFunction("FLIGHTGROUP._TaskDone", self, Task)
|
||||
|
||||
local DCStasks={}
|
||||
if Task.dcstask.id=='ComboTask' then
|
||||
-- Loop over all combo tasks.
|
||||
for TaskID, Task in ipairs( Task.dcstask.params.tasks ) do
|
||||
table.insert(DCStasks, Task)
|
||||
end
|
||||
else
|
||||
table.insert(DCStasks, Task.dcstask)
|
||||
end
|
||||
table.insert(DCStasks, TaskDone)
|
||||
|
||||
-- Combo task.
|
||||
local TaskCombo=self.group:TaskCombo({Task.dcstask, TaskDone})
|
||||
local TaskCombo=self.group:TaskCombo(DCStasks)
|
||||
|
||||
-- Set task for group.
|
||||
self.group:SetTask(TaskCombo)
|
||||
@@ -1800,7 +1840,7 @@ end
|
||||
function FLIGHTGROUP:RouteRTB(RTBAirbase, Speed, Altitude, TaskOverhead)
|
||||
|
||||
-- If speed is not given take 80% of max speed.
|
||||
local Speed=Speed or self.group:GetSpeedMax()*0.8
|
||||
Speed=Speed or self.speedmax*0.8
|
||||
|
||||
-- Curent (from) waypoint.
|
||||
local coord=self.group:GetCoordinate()
|
||||
@@ -1863,7 +1903,7 @@ end
|
||||
function FLIGHTGROUP:RouteOrbit(CoordOrbit, Speed, Altitude, CoordRaceTrack)
|
||||
|
||||
-- If speed is not given take 80% of max speed.
|
||||
local Speed=Speed or self.group:GetSpeedMax()*0.6
|
||||
Speed=Speed or self.group:GetSpeedMax()*0.6
|
||||
|
||||
-- Altitude.
|
||||
local altitude=Altitude or UTILS.FeetToMeters(10000)
|
||||
@@ -2278,13 +2318,29 @@ end
|
||||
-- @return #boolean If true, all elements have a similar status.
|
||||
function FLIGHTGROUP:_AllSimilarStatus(status)
|
||||
|
||||
local similar=true
|
||||
-- Check if all are dead.
|
||||
if status==FLIGHTGROUP.ElementStatus.DEAD then
|
||||
for _,_element in pairs(self.elements) do
|
||||
local element=_element --#FLIGHTGROUP.Element
|
||||
if element.status~=FLIGHTGROUP.ElementStatus.DEAD then
|
||||
-- At least one is still alive.
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
for _,_element in pairs(self.elements) do
|
||||
local element=_element --#FLIGHTGROUP.Element
|
||||
|
||||
self:I(string.format("FF status=%s, element %s status=%s", status, element.name, element.status))
|
||||
|
||||
-- Dead units dont count.
|
||||
-- Dead units dont count ==> We wont return false for those.
|
||||
if element.status~=FLIGHTGROUP.ElementStatus.DEAD then
|
||||
|
||||
----------
|
||||
-- ALIVE
|
||||
----------
|
||||
|
||||
if status==FLIGHTGROUP.ElementStatus.SPAWNED then
|
||||
|
||||
@@ -2305,8 +2361,8 @@ function FLIGHTGROUP:_AllSimilarStatus(status)
|
||||
|
||||
-- Element TAXIING: Check that the other are not stil SPAWNED or PARKING
|
||||
if element.status~=status and
|
||||
element.status==FLIGHTGROUP.ElementStatus.SPAWNED or
|
||||
element.status==FLIGHTGROUP.ElementStatus.PARKING then
|
||||
(element.status==FLIGHTGROUP.ElementStatus.SPAWNED or
|
||||
element.status==FLIGHTGROUP.ElementStatus.PARKING) then
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -2314,9 +2370,10 @@ function FLIGHTGROUP:_AllSimilarStatus(status)
|
||||
|
||||
-- Element TAKEOFF: Check that the other are not stil SPAWNED, PARKING or TAXIING
|
||||
if element.status~=status and
|
||||
element.status==FLIGHTGROUP.ElementStatus.SPAWNED or
|
||||
(element.status==FLIGHTGROUP.ElementStatus.SPAWNED or
|
||||
element.status==FLIGHTGROUP.ElementStatus.PARKING or
|
||||
element.status==FLIGHTGROUP.ElementStatus.TAXIING then
|
||||
element.status==FLIGHTGROUP.ElementStatus.TAXIING) then
|
||||
self:I(string.format("FF status=%s, element %s status=%s ==> returning FALSE", status, element.name, element.status))
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -2324,43 +2381,44 @@ function FLIGHTGROUP:_AllSimilarStatus(status)
|
||||
|
||||
-- Element AIRBORNE: Check that the other are not stil SPAWNED, PARKING, TAXIING or TAKEOFF
|
||||
if element.status~=status and
|
||||
element.status==FLIGHTGROUP.ElementStatus.SPAWNED or
|
||||
(element.status==FLIGHTGROUP.ElementStatus.SPAWNED or
|
||||
element.status==FLIGHTGROUP.ElementStatus.PARKING or
|
||||
element.status==FLIGHTGROUP.ElementStatus.TAXIING or
|
||||
element.status==FLIGHTGROUP.ElementStatus.TAKEOFF then
|
||||
element.status==FLIGHTGROUP.ElementStatus.TAKEOFF) then
|
||||
return false
|
||||
end
|
||||
|
||||
elseif status==FLIGHTGROUP.ElementStatus.LANDED then
|
||||
|
||||
-- Element LANDED: check that the others are not stil AIRBORNE
|
||||
-- Element LANDED: check that the others are not stil AIRBORNE or LANDING
|
||||
if element.status~=status and
|
||||
element.status==FLIGHTGROUP.ElementStatus.AIRBORNE then
|
||||
(element.status==FLIGHTGROUP.ElementStatus.AIRBORNE or
|
||||
element.status==FLIGHTGROUP.ElementStatus.LANDING) then
|
||||
return false
|
||||
end
|
||||
|
||||
elseif status==FLIGHTGROUP.ElementStatus.ARRIVED then
|
||||
|
||||
-- Element ARRIVED: check that the others are not stil AIRBORNE or TAXIING
|
||||
-- Element ARRIVED: check that the others are not stil AIRBORNE, LANDING, or LANDED (taxiing).
|
||||
if element.status~=status and
|
||||
element.status==FLIGHTGROUP.ElementStatus.AIRBORNE or
|
||||
element.status==FLIGHTGROUP.ElementStatus.TAXIING then
|
||||
(element.status==FLIGHTGROUP.ElementStatus.AIRBORNE or
|
||||
element.status==FLIGHTGROUP.ElementStatus.LANDING or
|
||||
element.status==FLIGHTGROUP.ElementStatus.LANDED) then
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if element.status==FLIGHTGROUP.ElementStatus.DEAD then
|
||||
-- Do nothing. Element is already dead and does not count.
|
||||
elseif element.status~=status then
|
||||
-- At least this element has a different status.
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
-- Element is dead. We don't care unless all are dead.
|
||||
end --DEAD
|
||||
|
||||
end
|
||||
|
||||
self:I(string.format("FF status=%s ==> returning TRUE", status))
|
||||
if status==FLIGHTGROUP.ElementStatus.TAKEOFF then
|
||||
--self:I(string.format("FF returning true"))
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -2827,6 +2885,29 @@ function FLIGHTGROUP:GetParkingSpot(element)
|
||||
return spot, dist
|
||||
end
|
||||
|
||||
--- Get holding time.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @return #number Holding time in seconds or 0 if flight is not holding.
|
||||
function FLIGHTGROUP:GetHoldingTime()
|
||||
if self.Tholding then
|
||||
return timer.getAbsTime()-self.Tholding
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
--- Get parking time.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @return #number Holding time in seconds or 0 if flight is not holding.
|
||||
function FLIGHTGROUP:GetParkingTime()
|
||||
if self.Tparking then
|
||||
return timer.getAbsTime()-self.Tparking
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -659,8 +659,9 @@ end
|
||||
|
||||
--- Convert time in seconds to hours, minutes and seconds.
|
||||
-- @param #number seconds Time in seconds, e.g. from timer.getAbsTime() function.
|
||||
-- @param #boolean short (Optional) If true, use short output, i.e. (HH:)MM:SS without day.
|
||||
-- @return #string Time in format Hours:Minutes:Seconds+Days (HH:MM:SS+D).
|
||||
function UTILS.SecondsToClock(seconds)
|
||||
function UTILS.SecondsToClock(seconds, short)
|
||||
|
||||
-- Nil check.
|
||||
if seconds==nil then
|
||||
@@ -680,7 +681,15 @@ function UTILS.SecondsToClock(seconds)
|
||||
local mins = string.format("%02.f", math.floor(_seconds/60 - (hours*60)))
|
||||
local secs = string.format("%02.f", math.floor(_seconds - hours*3600 - mins *60))
|
||||
local days = string.format("%d", seconds/(60*60*24))
|
||||
return hours..":"..mins..":"..secs.."+"..days
|
||||
local clock=hours..":"..mins..":"..secs.."+"..days
|
||||
if short then
|
||||
if hours=="00" then
|
||||
clock=mins..":"..secs
|
||||
else
|
||||
clock=hours..":"..mins..":"..secs
|
||||
end
|
||||
end
|
||||
return clock
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -478,8 +478,7 @@ end
|
||||
|
||||
--- Returns the Unit's ammunition.
|
||||
-- @param #UNIT self
|
||||
-- @return DCS#Unit.Ammo
|
||||
-- @return #nil The DCS Unit is not existing or alive.
|
||||
-- @return DCS#Unit.Ammo Table with ammuntion of the unit (or nil). This can be a complex table!
|
||||
function UNIT:GetAmmo()
|
||||
self:F2( self.UnitName )
|
||||
|
||||
|
||||
Reference in New Issue
Block a user