This commit is contained in:
Frank
2020-05-06 01:13:39 +02:00
parent 7f0f7cee0c
commit df2dbed441
4 changed files with 121 additions and 67 deletions
+24
View File
@@ -464,6 +464,30 @@ do -- COORDINATE
return set return set
end end
--- Find the closest unit to the COORDINATE within a certain radius.
-- @param #COORDINATE self
-- @param #number radius Scan radius in meters. Default 100 m.
-- @return Wrapper.Unit#UNIT The closest unit or #nil if no unit is inside the given radius.
function COORDINATE:FindClosestUnit(radius)
local units=self:ScanUnits(radius)
local umin=nil --Wrapper.Unit#UNIT
local dmin=math.huge
for _,_unit in pairs(units.Set) do
local unit=_unit --Wrapper.Unit#UNIT
local coordinate=unit:GetCoordinate()
local d=self:Get2DDistance(coordinate)
if d<dmin then
dmin=d
umin=unit
end
end
return umin
end
--- Calculate the distance from a reference @{#COORDINATE}. --- Calculate the distance from a reference @{#COORDINATE}.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE PointVec2Reference The reference @{#COORDINATE}. -- @param #COORDINATE PointVec2Reference The reference @{#COORDINATE}.
+31 -20
View File
@@ -40,7 +40,6 @@
-- @field #number activerwyno Number of active runway. -- @field #number activerwyno Number of active runway.
-- @field #number atcfreq ATC radio frequency. -- @field #number atcfreq ATC radio frequency.
-- @field Core.RadioQueue#RADIOQUEUE atcradio ATC radio queue. -- @field Core.RadioQueue#RADIOQUEUE atcradio ATC radio queue.
-- @field #table playermenu Player Menu.
-- @field #number Nlanding Max number of aircraft groups in the landing pattern. -- @field #number Nlanding Max number of aircraft groups in the landing pattern.
-- @field #number dTlanding Time interval in seconds between landing clearance. -- @field #number dTlanding Time interval in seconds between landing clearance.
-- @field #number Nparkingspots Total number of parking spots. -- @field #number Nparkingspots Total number of parking spots.
@@ -87,7 +86,6 @@ FLIGHTCONTROL = {
atcfreq = nil, atcfreq = nil,
atcradio = nil, atcradio = nil,
atcradiounitname = nil, atcradiounitname = nil,
playermenu = nil,
Nlanding = nil, Nlanding = nil,
dTlanding = nil, dTlanding = nil,
Nparkingspots = nil, Nparkingspots = nil,
@@ -155,12 +153,13 @@ FLIGHTCONTROL.Sound = {
--- FlightControl class version. --- FlightControl class version.
-- @field #string version -- @field #string version
FLIGHTCONTROL.version="0.3.0" FLIGHTCONTROL.version="0.4.0"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- DONE: Add parking guard.
-- TODO: Accept and forbit parking spots. -- TODO: Accept and forbit parking spots.
-- NOGO: Add FARPS? -- NOGO: Add FARPS?
-- TODO: Add helos. -- TODO: Add helos.
@@ -213,7 +212,7 @@ function FLIGHTCONTROL:New(airbasename)
-- 5 NM zone around the airbase. -- 5 NM zone around the airbase.
self.zoneAirbase=ZONE_RADIUS:New("FC", self:GetCoordinate():GetVec2(), UTILS.NMToMeters(5)) self.zoneAirbase=ZONE_RADIUS:New("FC", self:GetCoordinate():GetVec2(), UTILS.NMToMeters(5))
-- Defaults -- Defaults:
self:SetLandingMax() self:SetLandingMax()
self:SetLandingInterval() self:SetLandingInterval()
@@ -221,11 +220,6 @@ function FLIGHTCONTROL:New(airbasename)
-- Init runways. -- Init runways.
self:_InitRunwayData() self:_InitRunwayData()
-- Init parking spots.
self:_InitParkingSpots()
self.playermenu={}
-- Start State. -- Start State.
self:SetStartState("Stopped") self:SetStartState("Stopped")
@@ -334,6 +328,9 @@ function FLIGHTCONTROL:onafterStart()
-- Events are handled my MOOSE. -- Events are handled my MOOSE.
self:I(self.lid..string.format("Starting FLIGHTCONTROL v%s for airbase %s of type %d on map %s", FLIGHTCONTROL.version, self.airbasename, self.airbasetype, self.theatre)) self:I(self.lid..string.format("Starting FLIGHTCONTROL v%s for airbase %s of type %d on map %s", FLIGHTCONTROL.version, self.airbasename, self.airbasetype, self.theatre))
-- Init parking spots.
self:_InitParkingSpots()
-- Handle events. -- Handle events.
self:HandleEvent(EVENTS.Birth) self:HandleEvent(EVENTS.Birth)
self:HandleEvent(EVENTS.EngineStartup) self:HandleEvent(EVENTS.EngineStartup)
@@ -387,7 +384,7 @@ function FLIGHTCONTROL:onafterStatus()
local Nresv=self:CountParking(AIRBASE.SpotStatus.RESERVED) local Nresv=self:CountParking(AIRBASE.SpotStatus.RESERVED)
if Nfree+Noccu+Nresv~=self.Nparkingspots then if Nfree+Noccu+Nresv~=self.Nparkingspots then
self:E(self.lid..string.format("WARNING: Number of parking spots does not match! Nfree=%d, Noccu=%d, Nreserved=%d %d != %d total"), Nfree, Noccu, Nresv, self.Nparkingspots) self:E(self.lid..string.format("WARNING: Number of parking spots does not match! Nfree=%d, Noccu=%d, Nreserved=%d != %d total", Nfree, Noccu, Nresv, self.Nparkingspots))
end end
-- Info text. -- Info text.
@@ -444,7 +441,7 @@ function FLIGHTCONTROL:OnEventBirth(EventData)
-- Coordinate. -- Coordinate.
local coordinate=unit:GetCoordinate() local coordinate=unit:GetCoordinate()
self:ScheduleOnce(0.1, self._CreateFlightGroup, self, EventData.IniGroup) self:ScheduleOnce(0.5, self._CreateFlightGroup, self, EventData.IniGroup)
self:SpawnParkingGuard(unit) self:SpawnParkingGuard(unit)
@@ -777,6 +774,7 @@ end
-- @return Ops.FlightGroup#FLIGHTGROUP Marshal flight next in line and ready to enter the pattern. Or nil if no flight is ready. -- @return Ops.FlightGroup#FLIGHTGROUP Marshal flight next in line and ready to enter the pattern. Or nil if no flight is ready.
function FLIGHTCONTROL:_GetNextFightParking() function FLIGHTCONTROL:_GetNextFightParking()
-- Get flights taxiing to runway for takeoff.
local Qtaxiout=self:GetFlights(FLIGHTCONTROL.FlightStatus.TAXIOUT) local Qtaxiout=self:GetFlights(FLIGHTCONTROL.FlightStatus.TAXIOUT)
-- First check human players. -- First check human players.
@@ -786,10 +784,9 @@ function FLIGHTCONTROL:_GetNextFightParking()
-- First come, first serve. -- First come, first serve.
return Qtaxiout[1] return Qtaxiout[1]
else
return nil
end end
-- Get flights parking.
local Qparking=self:GetFlights(FLIGHTCONTROL.FlightStatus.PARKING) local Qparking=self:GetFlights(FLIGHTCONTROL.FlightStatus.PARKING)
-- Check special cases where only up to one flight is waiting for takeoff. -- Check special cases where only up to one flight is waiting for takeoff.
@@ -1065,15 +1062,22 @@ function FLIGHTCONTROL:_InitParkingSpots()
-- Add to table. -- Add to table.
self.parking[spot.TerminalID]=spot self.parking[spot.TerminalID]=spot
spot.Marker=MARKER:New(spot.Coordinate, "Spot"):ReadOnly()
spot.Marker.tocoaliton=true
spot.Marker.coalition=self:GetCoalition()
-- Set spot to occupied. -- Set spot to occupied.
if spot.Free then if spot.Free then
self:SetParkingFree(spot) self:SetParkingFree(spot)
else else
self:SetParkingOccupied(spot, "unknown") local unit=spot.Coordinate:FindClosestUnit(20)
if unit and unit:IsAlive() then
local unitname=unit and unit:GetName() or "unknown"
self:SetParkingOccupied(spot, unitname)
self:SpawnParkingGuard(unit)
end
end end
--TODO: scan spot for objects.
-- Increase counter -- Increase counter
self.Nparkingspots=self.Nparkingspots+1 self.Nparkingspots=self.Nparkingspots+1
end end
@@ -1319,7 +1323,7 @@ function FLIGHTCONTROL:_CreatePlayerMenu(flight, atcmenu)
local groupname=flight.groupname local groupname=flight.groupname
local gid=group:GetID() local gid=group:GetID()
self:I(self.lid..string.format("Creating ATC player menu for flight group %s (ID=%d)", tostring(flight.groupname), gid)) self:I(self.lid..string.format("Creating ATC player menu for flight group %s (ID=%d) in state=%s", tostring(flight.groupname), gid, flight:GetState()))
local airbasename=self.airbasename local airbasename=self.airbasename
@@ -1352,7 +1356,7 @@ function FLIGHTCONTROL:_CreatePlayerMenu(flight, atcmenu)
elseif flight:IsAirborne() then elseif flight:IsAirborne() then
end end
if flight:IsInbound() or flight:IsHolding() or flight:IsLanding() or flight:IsLanded() or true then if flight:IsInbound() or flight:IsHolding() or flight:IsLanding() or flight:IsLanded() then
MENU_GROUP_COMMAND_DELAYED:New(group, "Request Parking", rootmenu, self._PlayerRequestParking, self, groupname):SetTime(Tnow):SetTag(Tag) MENU_GROUP_COMMAND_DELAYED:New(group, "Request Parking", rootmenu, self._PlayerRequestParking, self, groupname):SetTime(Tnow):SetTag(Tag)
end end
else else
@@ -1600,6 +1604,10 @@ function FLIGHTCONTROL:_PlayerRequestTaxi(groupname)
for _,_element in pairs(flight.elements) do for _,_element in pairs(flight.elements) do
local element=_element --Ops.FlightGroup#FLIGHTGROUP.Element local element=_element --Ops.FlightGroup#FLIGHTGROUP.Element
if element.parking then
local spot=self:GetParkingSpotByID(element.parking.TerminalID)
self:RemoveParkingGuard(spot)
end
flight:ElementTaxiing(element) flight:ElementTaxiing(element)
end end
@@ -1954,6 +1962,7 @@ function FLIGHTCONTROL:SpawnParkingGuard(unit)
if unit and self.parkingGuard then if unit and self.parkingGuard then
-- Position of the unit.
local coordinate=unit:GetCoordinate() local coordinate=unit:GetCoordinate()
-- Parking spot. -- Parking spot.
@@ -1963,10 +1972,12 @@ function FLIGHTCONTROL:SpawnParkingGuard(unit)
local heading=unit:GetHeading() local heading=unit:GetHeading()
-- Length of the unit + 3 meters. -- Length of the unit + 3 meters.
local _,distance=unit:GetObjectSize()+3 local size, x, y, z=unit:GetObjectSize()
self:I(self.lid..string.format("Parking guard for %s: heading=%d, distance size=%s x=%s y=%s z=%s", unit:GetName(), heading, tostring(size), tostring(x), tostring(y), tostring(z)))
-- Coordinate for the guard. -- Coordinate for the guard.
local Coordinate=coordinate:Translate(distance, heading) local Coordinate=coordinate:Translate(x+3, heading)
-- Let him face the aircraft. -- Let him face the aircraft.
local lookat=heading-180 local lookat=heading-180
+51 -36
View File
@@ -850,7 +850,7 @@ function FLIGHTGROUP:SetFlightControl(flightcontrol)
-- Update flight's F10 menu. -- Update flight's F10 menu.
if self.ai==false then if self.ai==false then
self:_UpdateMenu() self:_UpdateMenu(0.5)
end end
return self return self
@@ -2395,9 +2395,6 @@ function FLIGHTGROUP:onafterFlightSpawned(From, Event, To)
else else
-- F10 other menu. -- F10 other menu.
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")
self:_UpdateMenu() self:_UpdateMenu()
end end
@@ -2410,7 +2407,7 @@ end
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
function FLIGHTGROUP:onafterFlightParking(From, Event, To) function FLIGHTGROUP:onafterFlightParking(From, Event, To)
self:T(self.lid..string.format("Flight is parking")) self:I(self.lid..string.format("Flight is parking"))
local airbase=self.group:GetCoordinate():GetClosestAirbase() local airbase=self.group:GetCoordinate():GetClosestAirbase()
@@ -2432,6 +2429,11 @@ function FLIGHTGROUP:onafterFlightParking(From, Event, To)
-- Set flight status. -- Set flight status.
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.PARKING) self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.PARKING)
-- Update player menu.
if not self.ai then
self:_UpdateMenu(0.5)
end
end end
end end
end end
@@ -4297,6 +4299,14 @@ function FLIGHTGROUP:_InitGroup()
end end
end end
self.ai=not self:_IsHuman(self.group)
if not self.ai then
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")
end
self:SwitchFormation(self.formationDefault) self:SwitchFormation(self.formationDefault)
-- Get first unit. This is used to extract other parameters. -- Get first unit. This is used to extract other parameters.
@@ -4315,8 +4325,6 @@ function FLIGHTGROUP:_InitGroup()
self.tankertype=select(2, unit:IsTanker()) self.tankertype=select(2, unit:IsTanker())
self.refueltype=select(2, unit:IsRefuelable()) self.refueltype=select(2, unit:IsRefuelable())
self.ai=not self:_IsHuman(self.group)
-- Init waypoints. -- Init waypoints.
if not self.waypoints then if not self.waypoints then
self:InitWaypoints() self:InitWaypoints()
@@ -6371,45 +6379,52 @@ end
--- Get the proper terminal type based on generalized attribute of the group. --- Get the proper terminal type based on generalized attribute of the group.
--@param #FLIGHTGROUP self --@param #FLIGHTGROUP self
function FLIGHTGROUP:_UpdateMenu() --@param #number delay Delay in seconds.
self:I(self.lid.."FF updating menu") function FLIGHTGROUP:_UpdateMenu(delay)
-- Get current position of group. if delay and delay>0 then
local position=self.group:GetCoordinate() self:ScheduleOnce(delay, FLIGHTGROUP._UpdateMenu, self)
else
-- Get all FLIGHTCONTROLS self:I(self.lid.."FF updating menu")
local fc={}
for airbasename,_flightcontrol in pairs(_DATABASE.FLIGHTCONTROLS) do
local airbase=AIRBASE:FindByName(airbasename) -- Get current position of group.
local position=self.group:GetCoordinate()
local coord=airbase:GetCoordinate() -- Get all FLIGHTCONTROLS
local fc={}
for airbasename,_flightcontrol in pairs(_DATABASE.FLIGHTCONTROLS) do
local dist=coord:Get2DDistance(position) local airbase=AIRBASE:FindByName(airbasename)
local fcitem={airbasename=airbasename, dist=dist} local coord=airbase:GetCoordinate()
table.insert(fc, fcitem) local dist=coord:Get2DDistance(position)
end
-- Sort table wrt distance to airbases. local fcitem={airbasename=airbasename, dist=dist}
local function _sort(a,b)
return a.dist<b.dist
end
table.sort(fc, _sort)
-- If there is a designated FC, we put it first. table.insert(fc, fcitem)
local N=8 end
if self.flightcontrol then
self.flightcontrol:_CreatePlayerMenu(self, self.menu.atc)
N=7
end
-- Max 8 entries in F10 menu. -- Sort table wrt distance to airbases.
for i=1,math.min(#fc,N) do local function _sort(a,b)
local airbasename=fc[i].airbasename return a.dist<b.dist
local flightcontrol=_DATABASE:GetFlightControl(airbasename) end
flightcontrol:_CreatePlayerMenu(self, self.menu.atc) table.sort(fc, _sort)
-- If there is a designated FC, we put it first.
local N=8
if self.flightcontrol then
self.flightcontrol:_CreatePlayerMenu(self, self.menu.atc)
N=7
end
-- Max 8 entries in F10 menu.
for i=1,math.min(#fc,N) do
local airbasename=fc[i].airbasename
local flightcontrol=_DATABASE:GetFlightControl(airbasename)
flightcontrol:_CreatePlayerMenu(self, self.menu.atc)
end
end end
end end
+8 -4
View File
@@ -552,7 +552,7 @@ end
--- Remove a marker. --- Remove a marker.
-- @param #MARKER self -- @param #MARKER self
-- @param #number Delay (Optional) Delay in seconds, before the marker is created. -- @param #number Delay (Optional) Delay in seconds, before the marker is removed.
-- @return #MARKER self -- @return #MARKER self
function MARKER:Remove(Delay) function MARKER:Remove(Delay)
@@ -560,8 +560,12 @@ function MARKER:Remove(Delay)
self:ScheduleOnce(Delay, MARKER.Remove, self) self:ScheduleOnce(Delay, MARKER.Remove, self)
else else
-- Call DCS function. if self.shown then
trigger.action.removeMark(self.mid)
-- Call DCS function.
trigger.action.removeMark(self.mid)
end
end end
@@ -587,7 +591,7 @@ end
-- @param #string Text Marker text. -- @param #string Text Marker text.
-- @return #MARKER self -- @return #MARKER self
function MARKER:SetText(Text) function MARKER:SetText(Text)
self.text=tostring(Text) self.text=Text and tostring(Text) or ""
return self return self
end end