mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-07-21 06:04:49 +00:00
FC
This commit is contained in:
@@ -26,7 +26,9 @@
|
||||
-- @field #table parking Parking spots table.
|
||||
-- @field #table runways Runway table.
|
||||
-- @field #table flights All flights table.
|
||||
-- @field #table Qwaiting Queue of aircraft waiting for landing permission.
|
||||
-- @field #table clients Table with all clients spawning at this airbase.
|
||||
-- @field #table Qinbound Queue of aircraft inbound and traveling to the holding position.
|
||||
-- @field #table Qholding Queue of aircraft waiting for landing permission.
|
||||
-- @field #table Qlanding Queue of aircraft currently on final approach.
|
||||
-- @field #table Qtaxiinb Queue of aircraft taxiing to parking after landing.
|
||||
-- @field #table Qarrived Queue of aircraft that have arrived at their parking spot after landing
|
||||
@@ -69,7 +71,9 @@ FLIGHTCONTROL = {
|
||||
parking = {},
|
||||
runways = {},
|
||||
flights = {},
|
||||
Qwaiting = {},
|
||||
clients = {},
|
||||
Qinbound = {},
|
||||
Qholding = {},
|
||||
Qlanding = {},
|
||||
Qtaxiinb = {},
|
||||
Qarrived = {},
|
||||
@@ -115,7 +119,7 @@ FLIGHTCONTROL = {
|
||||
|
||||
--- FlightControl class version.
|
||||
-- @field #string version
|
||||
FLIGHTCONTROL.version="0.1.4"
|
||||
FLIGHTCONTROL.version="0.1.5"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -321,15 +325,15 @@ function FLIGHTCONTROL:onafterStatus()
|
||||
local NQreadyto=#self.Qreadyto
|
||||
local NQtakeoff=#self.Qtakeoff
|
||||
--local NQtravel2=#self.Qtravel2
|
||||
local NQwaiting=#self.Qwaiting
|
||||
local NQholding=#self.Qholding
|
||||
local NQlanding=#self.Qlanding
|
||||
local NQtaxiinb=#self.Qtaxiinb
|
||||
local NQarrived=#self.Qarrived
|
||||
local Nqueues=NQparking+NQtaxiout+NQreadyto+NQtakeoff+NQwaiting+NQlanding+NQtaxiinb+NQarrived
|
||||
local Nqueues=NQparking+NQtaxiout+NQreadyto+NQtakeoff+NQholding+NQlanding+NQtaxiinb+NQarrived
|
||||
|
||||
-- Info text.
|
||||
local text=string.format("State %s - Runway %s - Parking %d/%d - Flights=%s: Qpark=%d Qtxout=%d Qready=%d Qto=%d | Qhold=%d Qland=%d Qtxinb=%d Qarr=%d",
|
||||
self:GetState(), runway.idx, nfree, self.Nparkingspots, #self.flights, #self.Qparking, #self.Qtaxiout, #self.Qreadyto, #self.Qtakeoff, #self.Qwaiting, #self.Qlanding, #self.Qtaxiinb, #self.Qarrived)
|
||||
self:GetState(), runway.idx, nfree, self.Nparkingspots, #self.flights, #self.Qparking, #self.Qtaxiout, #self.Qreadyto, #self.Qtakeoff, #self.Qholding, #self.Qlanding, #self.Qtaxiinb, #self.Qarrived)
|
||||
self:I(self.lid..text)
|
||||
|
||||
if Nflights==Nqueues then
|
||||
@@ -478,14 +482,15 @@ function FLIGHTCONTROL:_CheckQueues()
|
||||
self:_PrintQueue(self.Qtaxiout, "TaxiOut")
|
||||
self:_PrintQueue(self.Qreadyto, "ReadyTO")
|
||||
self:_PrintQueue(self.Qtakeoff, "Takeoff")
|
||||
self:_PrintQueue(self.Qwaiting, "Holding")
|
||||
self:_PrintQueue(self.Qinbound, "Inbound")
|
||||
self:_PrintQueue(self.Qholding, "Holding")
|
||||
self:_PrintQueue(self.Qlanding, "Landing")
|
||||
self:_PrintQueue(self.Qtaxiinb, "TaxiInb")
|
||||
self:_PrintQueue(self.Qarrived, "Arrived")
|
||||
end
|
||||
|
||||
-- Number of holding groups.
|
||||
local nholding=#self.Qwaiting
|
||||
local nholding=#self.Qholding
|
||||
|
||||
-- Number of groups landing.
|
||||
local nlanding=#self.Qlanding
|
||||
@@ -634,10 +639,10 @@ end
|
||||
-- @return Ops.FlightGroup#FLIGHTGROUP Marshal flight next in line and ready to enter the pattern. Or nil if no flight is ready.
|
||||
function FLIGHTCONTROL:_GetNextFightHolding()
|
||||
|
||||
if #self.Qwaiting==0 then
|
||||
if #self.Qholding==0 then
|
||||
return nil
|
||||
elseif #self.Qwaiting==1 then
|
||||
return self.Qwaiting[1]
|
||||
elseif #self.Qholding==1 then
|
||||
return self.Qholding[1]
|
||||
end
|
||||
|
||||
-- Sort flights by low fuel.
|
||||
@@ -658,10 +663,10 @@ function FLIGHTCONTROL:_GetNextFightHolding()
|
||||
|
||||
|
||||
-- Sort flights by fuel.
|
||||
table.sort(self.Qwaiting, _sortByFuel)
|
||||
table.sort(self.Qholding, _sortByFuel)
|
||||
|
||||
-- Loop over all marshal flights.
|
||||
for _,_flight in pairs(self.Qwaiting) do
|
||||
-- Loop over all holding flights.
|
||||
for _,_flight in pairs(self.Qholding) do
|
||||
local flight=_flight --Ops.FlightGroup#FLIGHTGROUP
|
||||
|
||||
-- Return flight that is lowest on fuel.
|
||||
@@ -673,9 +678,9 @@ function FLIGHTCONTROL:_GetNextFightHolding()
|
||||
|
||||
|
||||
-- Return flight waiting longest.
|
||||
table.sort(self.Qwaiting, _sortByTholding)
|
||||
table.sort(self.Qholding, _sortByTholding)
|
||||
|
||||
return self.Qwaiting[1]
|
||||
return self.Qholding[1]
|
||||
end
|
||||
|
||||
|
||||
@@ -812,12 +817,12 @@ end
|
||||
function FLIGHTCONTROL:_AddFlightToHoldingQueue(flight)
|
||||
|
||||
-- Check if already in queue.
|
||||
if self:_InQueue(self.Qwaiting, flight.group) then
|
||||
if self:_InQueue(self.Qholding, flight.group) then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Add flight to table.
|
||||
table.insert(self.Qwaiting, flight)
|
||||
table.insert(self.Qholding, flight)
|
||||
|
||||
-- Flight is not holding any more.
|
||||
flight.Tholding=timer.getAbsTime()
|
||||
@@ -860,7 +865,7 @@ function FLIGHTCONTROL:_AddFlightToParkingQueue(flight)
|
||||
-- Add flight to table.
|
||||
table.insert(self.Qparking, flight)
|
||||
|
||||
-- Flight is not holding any more.
|
||||
-- Set parking time stamp. This is also done in FLIGHTGROUP onafterFlightParking function.
|
||||
flight.Tparking=timer.getAbsTime()
|
||||
|
||||
return true
|
||||
@@ -995,7 +1000,10 @@ function FLIGHTCONTROL:_InitParkingSpots()
|
||||
local spot=_spot --Wrapper.Airbase#AIRBASE.ParkingSpot
|
||||
|
||||
local parking=spot --#FLIGHTCONTROL.ParkingSpot
|
||||
parking.reserved="none"
|
||||
|
||||
--TODO: reserve client spots.
|
||||
--TODO: scan spot for objects.
|
||||
|
||||
|
||||
-- Mark position.
|
||||
local text=string.format("ID=%d, Terminal=%d, Free=%s, Reserved=%s, Dist=%.1f", parking.TerminalID, parking.TerminalType, tostring(parking.Free), tostring(parking.reserved), parking.DistToRwy)
|
||||
@@ -1022,7 +1030,7 @@ function FLIGHTCONTROL:_GetFreeParkingSpots(terminal)
|
||||
for _,_parking in pairs(self.parking) do
|
||||
local parking=_parking --#FLIGHTCONTROL.ParkingSpot
|
||||
|
||||
if parking.Free and parking.TOAC==false and parking.reserved=="none" then
|
||||
if parking.Free and parking.TOAC==false and not parking.reserved then
|
||||
if terminal==nil or terminal==parking.terminal then
|
||||
n=n+1
|
||||
table.insert(freespots, parking)
|
||||
@@ -1097,6 +1105,39 @@ function FLIGHTCONTROL:IsParkingReserved(spot)
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get closest parking spot.
|
||||
-- @param #FLIGHTCONTROL self
|
||||
-- @param Core.Point#COORDINATE coordinate Reference coordinate.
|
||||
-- @param #number terminaltype (Optional) Check only this terminal type.
|
||||
-- @param #boolean free (Optional) If true, check only free spots.
|
||||
-- @return Wrapper.Airbase#AIRBASE.ParkingSpot Closest parking spot.
|
||||
function FLIGHTCONTROL:GetClosestParkingSpot(coord, terminaltype, free)
|
||||
|
||||
local distmin=math.huge
|
||||
local spotmin=nil
|
||||
|
||||
for TerminalID, Spot in pairs(self.parking) do
|
||||
local spot=Spot --Wrapper.Airbase#AIRBASE.ParkingSpot
|
||||
|
||||
if (not free) or free==true and not (self:IsParkingReserved(spot) or spot.Reserved) then
|
||||
if terminaltype==nil or terminaltype==spot.TerminalType then
|
||||
|
||||
-- Get distance from coordinate to spot.
|
||||
local dist=coord:Get2DDistance(spot.Coordinate)
|
||||
|
||||
-- Check if distance is smaller.
|
||||
if dist<distmin then
|
||||
distmin=dist
|
||||
spotmin=spot
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return spotmin
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ATIS Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1178,17 +1219,25 @@ function FLIGHTCONTROL:_PlayerRequestParking(groupname)
|
||||
|
||||
local group=flight:GetGroup()
|
||||
local coord=flight:GetGroup():GetCoordinate()
|
||||
local spotcoord, TerminalID, _spot=coord:GetClosestParkingSpot(self.airbase, AIRBASE.TerminalType.FighterAircraft, true)
|
||||
|
||||
local spot=_spot --Wrapper.Airbase#AIRBASE.ParkingSpot
|
||||
|
||||
--TODO: terminal type for helos!
|
||||
local spot=self:GetClosestParkingSpot(coord, AIRBASE.TerminalType.FighterAircraft, true)
|
||||
|
||||
--TODO: voice over.
|
||||
local text=string.format("Flight XYZ, tower, your assigned parking position is terminal ID %d.\nCheck your F10 map for details.", spot.TerminalID)
|
||||
MESSAGE:New(text, 10, "FLIGHCONTROL", true):ToAll()
|
||||
|
||||
|
||||
spot.markID=spot.Coordinate:MarkToGroup("Your assigned parking spot!", group)
|
||||
-- Create mark on F10 map.
|
||||
if spot.MarkerID then
|
||||
coord:RemoveMark(spot.MarkerID)
|
||||
end
|
||||
spot.MarkerID=spot.Coordinate:MarkToGroup("Your assigned parking spot!", group)
|
||||
|
||||
local element=flight.elements[1] --Ops.FlightGroup#FLIGHTGROUP.Element
|
||||
|
||||
-- TODO: get element of human player.
|
||||
local element=flight.elements[1] --Ops.FlightGroup#FLIGHTGROUP.Element
|
||||
element.parking=spot
|
||||
|
||||
-- TODO: what about AI wingmen? I guess there is no way to set parking for those, right?!
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1207,7 +1256,7 @@ function FLIGHTCONTROL:_PlayerRequestInfo(groupname)
|
||||
local text=string.format("Airbase %s Status:", self.airbasename)
|
||||
text=text..string.format("\nFlights %d", #self.flights)
|
||||
text=text..string.format("\nQlanding %d", #self.Qlanding)
|
||||
text=text..string.format("\nQholding %d", #self.Qwaiting)
|
||||
text=text..string.format("\nQholding %d", #self.Qholding)
|
||||
text=text..string.format("\nQparking %d", #self.Qparking)
|
||||
text=text..string.format("\nQtakeoff %d", #self.Qtakeoff)
|
||||
text=text..string.format("\nRunway %s", self:GetActiveRunwayText())
|
||||
@@ -1411,7 +1460,7 @@ end
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP flight The flight to be removed.
|
||||
function FLIGHTCONTROL:_RemoveFlight(flight)
|
||||
|
||||
self:_RemoveFlightFromQueue(self.Qwaiting, flight, "holding")
|
||||
self:_RemoveFlightFromQueue(self.Qholding, flight, "holding")
|
||||
self:_RemoveFlightFromQueue(self.Qlanding, flight, "landing")
|
||||
self:_RemoveFlightFromQueue(self.Qtaxiinb, flight, "taxiINB")
|
||||
self:_RemoveFlightFromQueue(self.Qparking, flight, "parking")
|
||||
@@ -1629,7 +1678,7 @@ function FLIGHTCONTROL:_LandAI(flight, parking)
|
||||
self:_AddFlightToLandingQueue(flight)
|
||||
|
||||
-- Remove flight from waiting queue.
|
||||
self:_RemoveFlightFromQueue(self.Qwaiting, flight, "holding")
|
||||
self:_RemoveFlightFromQueue(self.Qholding, flight, "holding")
|
||||
|
||||
-- Altitude above ground for a glide slope of 3�.
|
||||
local alpha=math.rad(3)
|
||||
|
||||
@@ -338,7 +338,8 @@ function FLIGHTGROUP:New(groupname)
|
||||
self:AddTransition("*", "UpdateRoute", "*") -- Update route of group. Only if airborne.
|
||||
self:AddTransition("*", "RTB", "Returning") -- Group is returning to base.
|
||||
self:AddTransition("*", "Orbit", "Orbiting") -- Group is holding position.
|
||||
self:AddTransition("*", "Hold", "Holding") -- Group is holding position.
|
||||
self:AddTransition("*", "Hold", "Inbound") -- Group is holding position.
|
||||
self:AddTransition("Inbound", "Holding", "Holding") -- Group is holding position.
|
||||
|
||||
self:AddTransition("*", "PassingWaypoint", "*") -- Group passed a waypoint.
|
||||
|
||||
@@ -1084,6 +1085,11 @@ function FLIGHTGROUP:OnEventEngineStartup(EventData)
|
||||
-- when player starts cold, ?
|
||||
if self.ai then
|
||||
self:ElementTaxiing(element)
|
||||
else
|
||||
if element.ai then
|
||||
-- AI wingmen will start taxiing even if the player/client is still starting up his engines :(
|
||||
self:ElementTaxiing(element)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1260,6 +1266,7 @@ function FLIGHTGROUP:onafterElementSpawned(From, Event, To, Element)
|
||||
if spot then
|
||||
|
||||
Element.parking=spot
|
||||
|
||||
|
||||
self:ElementParking(Element)
|
||||
else
|
||||
@@ -1277,6 +1284,7 @@ end
|
||||
function FLIGHTGROUP:onafterElementParking(From, Event, To, Element)
|
||||
self:T(self.sid..string.format("Element parking %s at spot %s.", Element.name, tostring(Element.parking.TerminalID)))
|
||||
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, FLIGHTGROUP.ElementStatus.PARKING)
|
||||
end
|
||||
@@ -1642,12 +1650,6 @@ function FLIGHTGROUP:onafterUpdateRoute(From, Event, To, n)
|
||||
table.insert(wp, w)
|
||||
end
|
||||
|
||||
-- Get destination airbase from waypoints.
|
||||
self.homebase=self:GetHomebaseFromWaypoints() or self.homebase
|
||||
|
||||
-- Get destination airbase from waypoints.
|
||||
self.destination=self:GetDestinationFromWaypoints() or self.destination
|
||||
|
||||
if self.destination and #wp>0 and _DATABASE:GetFlightControl(self.destination:GetName()) then
|
||||
|
||||
-- Task to hold.
|
||||
@@ -1940,6 +1942,25 @@ function FLIGHTGROUP:onafterHold(From, Event, To, airbase, SpeedTo, SpeedHold, S
|
||||
|
||||
end
|
||||
|
||||
--- On after "Holding" event. Flight arrived at the holding point.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FLIGHTGROUP:onafterHolding(From, Event, To)
|
||||
|
||||
|
||||
self.flaghold:Set(666)
|
||||
|
||||
-- Add flight to waiting/holding queue.
|
||||
if self.flightcontrol then
|
||||
-- Add flight to all flights.
|
||||
--table.insert(flightgroup.flightcontrol.flights, flightgroup)
|
||||
self.flightcontrol:_AddFlightToHoldingQueue(self)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On after TaskExecute event.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
@@ -2268,14 +2289,7 @@ function FLIGHTGROUP._ReachedHolding(group, flightgroup)
|
||||
group:GetCoordinate():MarkToAll("Holding Point Reached")
|
||||
end
|
||||
|
||||
flightgroup.flaghold:Set(666)
|
||||
|
||||
-- Add flight to waiting/holding queue.
|
||||
if flightgroup.flightcontrol then
|
||||
-- Add flight to all flights.
|
||||
--table.insert(flightgroup.flightcontrol.flights, flightgroup)
|
||||
flightgroup.flightcontrol:_AddFlightToHoldingQueue(flightgroup)
|
||||
end
|
||||
flightgroup:__Holding(1)
|
||||
end
|
||||
|
||||
--- Update route of group, e.g after new waypoints and/or waypoint tasks have been added.
|
||||
@@ -2682,6 +2696,8 @@ function FLIGHTGROUP:InitWaypoints(waypoints)
|
||||
-- Set current waypoint. Counting starts a one.
|
||||
self.currentwp=1
|
||||
|
||||
|
||||
|
||||
-- Update route.
|
||||
if #self.waypoints>0 then
|
||||
self:__UpdateRoute(-0.1, 1)
|
||||
|
||||
@@ -294,6 +294,9 @@ AIRBASE.PersianGulf = {
|
||||
-- @field #boolean Free This spot is currently free, i.e. there is no alive aircraft on it at the present moment.
|
||||
-- @field #number TerminalID0 Unknown what this means. If you know, please tell us!
|
||||
-- @field #number DistToRwy Distance to runway in meters. Currently bugged and giving the same number as the TerminalID.
|
||||
-- @field #string AirbaseName Name of the airbase.
|
||||
-- @field #number MarkerID Numerical ID of marker placed at parking spot.
|
||||
-- @field #boolean Reserved If true, parking spot is reserved for an aircraft.
|
||||
|
||||
--- Terminal Types of parking spots. See also https://wiki.hoggitworld.com/view/DCS_func_getParking
|
||||
--
|
||||
@@ -331,7 +334,7 @@ AIRBASE.TerminalType = {
|
||||
--- Runway data.
|
||||
-- @type AIRBASE.Runway
|
||||
-- @field #number heading Heading of the runway in degrees.
|
||||
-- @field #string idx Runway ID: heading 070° ==> idx="07".
|
||||
-- @field #string idx Runway ID: heading 070� ==> idx="07".
|
||||
-- @field #number length Length of runway in meters.
|
||||
-- @field Core.Point#COORDINATE position Position of runway start.
|
||||
-- @field Core.Point#COORDINATE endpoint End point of runway.
|
||||
@@ -592,7 +595,7 @@ function AIRBASE:GetParkingSpotsTable(termtype)
|
||||
self:T2({_spot=_spot})
|
||||
local _free=_isfree(_spot)
|
||||
local _coord=COORDINATE:NewFromVec3(_spot.vTerminalPos)
|
||||
table.insert(spots, {Coordinate=_coord, TerminalID=_spot.Term_Index, TerminalType=_spot.Term_Type, TOAC=_spot.TO_AC, Free=_free, TerminalID0=_spot.Term_Index_0, DistToRwy=_spot.fDistToRW})
|
||||
table.insert(spots, {AirbaseName=self.AirbaseName, Coordinate=_coord, TerminalID=_spot.Term_Index, TerminalType=_spot.Term_Type, TOAC=_spot.TO_AC, Free=_free, TerminalID0=_spot.Term_Index_0, DistToRwy=_spot.fDistToRW})
|
||||
end
|
||||
end
|
||||
|
||||
@@ -617,7 +620,7 @@ function AIRBASE:GetFreeParkingSpotsTable(termtype, allowTOAC)
|
||||
if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) and _spot.Term_Index>0 then
|
||||
if (allowTOAC and allowTOAC==true) or _spot.TO_AC==false then
|
||||
local _coord=COORDINATE:NewFromVec3(_spot.vTerminalPos)
|
||||
table.insert(freespots, {Coordinate=_coord, TerminalID=_spot.Term_Index, TerminalType=_spot.Term_Type, TOAC=_spot.TO_AC, Free=true, TerminalID0=_spot.Term_Index_0, DistToRwy=_spot.fDistToRW})
|
||||
table.insert(freespots, {AirbaseName=self.AirbaseName, Coordinate=_coord, TerminalID=_spot.Term_Index, TerminalType=_spot.Term_Type, TOAC=_spot.TO_AC, Free=true, TerminalID0=_spot.Term_Index_0, DistToRwy=_spot.fDistToRW})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -692,7 +695,7 @@ function AIRBASE:MarkParkingSpots(termtype, mark)
|
||||
self:I(_text)
|
||||
end
|
||||
|
||||
return markers
|
||||
return self.parkingmarks
|
||||
end
|
||||
|
||||
--- Place markers of parking spots on the F10 map and update regularly.
|
||||
@@ -700,10 +703,7 @@ end
|
||||
-- @param #AIRBASE.TerminalType termtype Terminal type for which marks should be placed.
|
||||
-- @param #boolean mark If false, do not place markers but only give output to DCS.log file. Default true.
|
||||
function AIRBASE:MonitorParkingSpots(termtype, mark)
|
||||
|
||||
local sched,shedid=SCHEDULER:New(self, self.MarkParkingSpots, {self,termtype,mark}, 5, 5)
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -1081,7 +1081,7 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
||||
-- Heading of runway.
|
||||
local hdg=c1:HeadingTo(c2)
|
||||
|
||||
-- Runway ID: heading=070° ==> idx="07"
|
||||
-- Runway ID: heading=070� ==> idx="07"
|
||||
local idx=string.format("%02d", UTILS.Round((hdg-magvar)/10, 0))
|
||||
|
||||
-- Runway table.
|
||||
@@ -1191,7 +1191,7 @@ function AIRBASE:GetActiveRunway(magvar)
|
||||
local dot=UTILS.VecDot(Vwind, Vrunway)
|
||||
|
||||
-- Debug.
|
||||
--env.info(string.format("runway=%03d° dot=%.3f", runway.heading, dot))
|
||||
--env.info(string.format("runway=%03d� dot=%.3f", runway.heading, dot))
|
||||
|
||||
-- New min?
|
||||
if dotmin==nil or dot<dotmin then
|
||||
|
||||
Reference in New Issue
Block a user