mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
FLIGHTCONTROL v0.6.0
This commit is contained in:
parent
8926e06e44
commit
06d0bfadca
@ -52,7 +52,6 @@
|
|||||||
--- ATIS class.
|
--- ATIS class.
|
||||||
-- @type ATIS
|
-- @type ATIS
|
||||||
-- @field #string ClassName Name of the class.
|
-- @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 #string lid Class id string for output to DCS log file.
|
||||||
-- @field #string theatre DCS map name.
|
-- @field #string theatre DCS map name.
|
||||||
-- @field #string airbasename The name of the airbase.
|
-- @field #string airbasename The name of the airbase.
|
||||||
@ -309,7 +308,6 @@
|
|||||||
-- @field #ATIS
|
-- @field #ATIS
|
||||||
ATIS = {
|
ATIS = {
|
||||||
ClassName = "ATIS",
|
ClassName = "ATIS",
|
||||||
Debug = false,
|
|
||||||
lid = nil,
|
lid = nil,
|
||||||
theatre = nil,
|
theatre = nil,
|
||||||
airbasename = nil,
|
airbasename = nil,
|
||||||
@ -614,26 +612,26 @@ ATIS.version="0.9.6"
|
|||||||
|
|
||||||
--- Create a new ATIS class object for a specific aircraft carrier unit.
|
--- Create a new ATIS class object for a specific aircraft carrier unit.
|
||||||
-- @param #ATIS self
|
-- @param #ATIS self
|
||||||
-- @param #string airbasename Name of the airbase.
|
-- @param #string AirbaseName Name of the airbase.
|
||||||
-- @param #number frequency Radio frequency in MHz. Default 143.00 MHz.
|
-- @param #number Frequency Radio frequency in MHz. Default 143.00 MHz.
|
||||||
-- @param #number modulation Radio modulation: 0=AM, 1=FM. Default 0=AM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators
|
-- @param #number Modulation Radio modulation: 0=AM, 1=FM. Default 0=AM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators.
|
||||||
-- @return #ATIS self
|
-- @return #ATIS self
|
||||||
function ATIS:New(airbasename, frequency, modulation)
|
function ATIS:New(AirbaseName, Frequency, Modulation)
|
||||||
|
|
||||||
-- Inherit everything from FSM class.
|
-- Inherit everything from FSM class.
|
||||||
local self=BASE:Inherit(self, FSM:New()) -- #ATIS
|
local self=BASE:Inherit(self, FSM:New()) -- #ATIS
|
||||||
|
|
||||||
self.airbasename=airbasename
|
self.airbasename=AirbaseName
|
||||||
self.airbase=AIRBASE:FindByName(airbasename)
|
self.airbase=AIRBASE:FindByName(AirbaseName)
|
||||||
|
|
||||||
if self.airbase==nil then
|
if self.airbase==nil then
|
||||||
self:E("ERROR: Airbase %s for ATIS could not be found!", tostring(airbasename))
|
self:E("ERROR: Airbase %s for ATIS could not be found!", tostring(AirbaseName))
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Default freq and modulation.
|
-- Default freq and modulation.
|
||||||
self.frequency=frequency or 143.00
|
self.frequency=Frequency or 143.00
|
||||||
self.modulation=modulation or 0
|
self.modulation=Modulation or 0
|
||||||
|
|
||||||
-- Get map.
|
-- Get map.
|
||||||
self.theatre=env.mission.theatre
|
self.theatre=env.mission.theatre
|
||||||
@ -740,15 +738,6 @@ function ATIS:New(airbasename, frequency, modulation)
|
|||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
-- @param #string Text Report text.
|
-- @param #string Text Report text.
|
||||||
|
|
||||||
|
|
||||||
-- Debug trace.
|
|
||||||
if false then
|
|
||||||
self.Debug=true
|
|
||||||
BASE:TraceOnOff(true)
|
|
||||||
BASE:TraceClass(self.ClassName)
|
|
||||||
BASE:TraceLevel(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -809,6 +798,15 @@ function ATIS:SetRunwayLength()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Give information on runway length.
|
||||||
|
-- @param #ATIS self
|
||||||
|
-- @return #ATIS self
|
||||||
|
function ATIS:SetRunwayLength()
|
||||||
|
self.rwylength=true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Give information on airfield elevation
|
--- Give information on airfield elevation
|
||||||
-- @param #ATIS self
|
-- @param #ATIS self
|
||||||
-- @return #ATIS self
|
-- @return #ATIS self
|
||||||
@ -1395,7 +1393,8 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
--- Runway ---
|
--- Runway ---
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
local runway, rwyLeft=self:GetActiveRunway()
|
local runwayLanding, rwyLandingLeft=self:GetActiveRunway()
|
||||||
|
local runwayTakeoff, rwyTakeoffLeft=self:GetActiveRunway(true)
|
||||||
|
|
||||||
------------
|
------------
|
||||||
--- Time ---
|
--- Time ---
|
||||||
@ -2017,19 +2016,19 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
alltext=alltext..";\n"..subtitle
|
alltext=alltext..";\n"..subtitle
|
||||||
|
|
||||||
-- Active runway.
|
-- Active runway.
|
||||||
local subtitle=string.format("Active runway %s", runway)
|
local subtitle=string.format("Active runway %s", runwayLanding)
|
||||||
if rwyLeft==true then
|
if rwyLandingLeft==true then
|
||||||
subtitle=subtitle.." Left"
|
subtitle=subtitle.." Left"
|
||||||
elseif rwyLeft==false then
|
elseif rwyLandingLeft==false then
|
||||||
subtitle=subtitle.." Right"
|
subtitle=subtitle.." Right"
|
||||||
end
|
end
|
||||||
local _RUNACT=subtitle
|
local _RUNACT=subtitle
|
||||||
if not self.useSRS then
|
if not self.useSRS then
|
||||||
self:Transmission(ATIS.Sound.ActiveRunway, 1.0, subtitle)
|
self:Transmission(ATIS.Sound.ActiveRunway, 1.0, subtitle)
|
||||||
self.radioqueue:Number2Transmission(runway)
|
self.radioqueue:Number2Transmission(runwayLanding)
|
||||||
if rwyLeft==true then
|
if rwyLandingLeft==true then
|
||||||
self:Transmission(ATIS.Sound.Left, 0.2)
|
self:Transmission(ATIS.Sound.Left, 0.2)
|
||||||
elseif rwyLeft==false then
|
elseif rwyLandingLeft==false then
|
||||||
self:Transmission(ATIS.Sound.Right, 0.2)
|
self:Transmission(ATIS.Sound.Right, 0.2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -2141,7 +2140,7 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- ILS
|
-- ILS
|
||||||
local ils=self:GetNavPoint(self.ils, runway, rwyLeft)
|
local ils=self:GetNavPoint(self.ils, runwayLanding, rwyLandingLeft)
|
||||||
if ils then
|
if ils then
|
||||||
subtitle=string.format("ILS frequency %.2f MHz", ils.frequency)
|
subtitle=string.format("ILS frequency %.2f MHz", ils.frequency)
|
||||||
if not self.useSRS then
|
if not self.useSRS then
|
||||||
@ -2159,7 +2158,7 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Outer NDB
|
-- Outer NDB
|
||||||
local ndb=self:GetNavPoint(self.ndbouter, runway, rwyLeft)
|
local ndb=self:GetNavPoint(self.ndbouter, runwayLanding, rwyLandingLeft)
|
||||||
if ndb then
|
if ndb then
|
||||||
subtitle=string.format("Outer NDB frequency %.2f MHz", ndb.frequency)
|
subtitle=string.format("Outer NDB frequency %.2f MHz", ndb.frequency)
|
||||||
if not self.useSRS then
|
if not self.useSRS then
|
||||||
@ -2177,7 +2176,7 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Inner NDB
|
-- Inner NDB
|
||||||
local ndb=self:GetNavPoint(self.ndbinner, runway, rwyLeft)
|
local ndb=self:GetNavPoint(self.ndbinner, runwayLanding, rwyLandingLeft)
|
||||||
if ndb then
|
if ndb then
|
||||||
subtitle=string.format("Inner NDB frequency %.2f MHz", ndb.frequency)
|
subtitle=string.format("Inner NDB frequency %.2f MHz", ndb.frequency)
|
||||||
if not self.useSRS then
|
if not self.useSRS then
|
||||||
@ -2236,7 +2235,7 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- PRMG
|
-- PRMG
|
||||||
local ndb=self:GetNavPoint(self.prmg, runway, rwyLeft)
|
local ndb=self:GetNavPoint(self.prmg, runwayLanding, rwyLandingLeft)
|
||||||
if ndb then
|
if ndb then
|
||||||
subtitle=string.format("PRMG channel %d", ndb.frequency)
|
subtitle=string.format("PRMG channel %d", ndb.frequency)
|
||||||
if not self.useSRS then
|
if not self.useSRS then
|
||||||
@ -2363,39 +2362,19 @@ end
|
|||||||
|
|
||||||
--- Get active runway runway.
|
--- Get active runway runway.
|
||||||
-- @param #ATIS self
|
-- @param #ATIS self
|
||||||
|
-- @param #boolean Takeoff If `true`, get runway for takeoff. Default is for landing.
|
||||||
-- @return #string Active runway, e.g. "31" for 310 deg.
|
-- @return #string Active runway, e.g. "31" for 310 deg.
|
||||||
-- @return #boolean Use Left=true, Right=false, or nil.
|
-- @return #boolean Use Left=true, Right=false, or nil.
|
||||||
function ATIS:GetActiveRunway()
|
function ATIS:GetActiveRunway(Takeoff)
|
||||||
|
|
||||||
local coord=self.airbase:GetCoordinate()
|
local runway=nil --Wrapper.Airbase#AIRBASE.Runway
|
||||||
local height=coord:GetLandHeight()
|
if Takeoff then
|
||||||
|
runway=self.airbase:GetActiveRunwayTakeoff()
|
||||||
-- Get wind direction and speed in m/s.
|
else
|
||||||
local windFrom, windSpeed=coord:GetWind(height+10)
|
runway=self.airbase:GetActiveRunwayLanding()
|
||||||
|
|
||||||
-- Get active runway data based on wind direction.
|
|
||||||
local runact=self.airbase:GetActiveRunway(self.runwaym2t)
|
|
||||||
|
|
||||||
-- Active runway "31".
|
|
||||||
local runway=self:GetMagneticRunway(windFrom) or runact.idx
|
|
||||||
|
|
||||||
-- Left or right in case there are two runways with the same heading.
|
|
||||||
local rwyLeft=nil
|
|
||||||
|
|
||||||
-- Check if user explicitly specified a runway.
|
|
||||||
if self.activerunway then
|
|
||||||
|
|
||||||
-- Get explicit runway heading if specified.
|
|
||||||
local runwayno=self:GetRunwayWithoutLR(self.activerunway)
|
|
||||||
if runwayno~="" then
|
|
||||||
runway=runwayno
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Was "L"eft or "R"ight given?
|
|
||||||
rwyLeft=self:GetRunwayLR(self.activerunway)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return runway, rwyLeft
|
return runway.name, runway.isLeft
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get runway from user supplied magnetic heading.
|
--- Get runway from user supplied magnetic heading.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -143,6 +143,8 @@ FLIGHTGROUP = {
|
|||||||
menu = nil,
|
menu = nil,
|
||||||
isHelo = nil,
|
isHelo = nil,
|
||||||
RTBRecallCount = 0,
|
RTBRecallCount = 0,
|
||||||
|
playerSettings = {},
|
||||||
|
playerWarnings = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -183,21 +185,32 @@ FLIGHTGROUP.RadioMessage = {
|
|||||||
TAXIING={normal="Taxiing", enhanced="Taxiing"},
|
TAXIING={normal="Taxiing", enhanced="Taxiing"},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Player skill.
|
--- Skill level.
|
||||||
-- @type FLIGHTGROUP.PlayerSkill
|
-- @type FLIGHTGROUP.PlayerSkill
|
||||||
-- @field #string NOVICE Novice
|
-- @field #string STUDENT Flight Student. Shows tips and hints in important phases of the approach.
|
||||||
|
-- @field #string AVIATOR Naval aviator. Moderate number of hints but not really zip lip.
|
||||||
|
-- @field #string GRADUATE TOPGUN graduate. For people who know what they are doing. Nearly *ziplip*.
|
||||||
|
-- @field #string INSTRUCTOR TOPGUN instructor. For people who know what they are doing. Nearly *ziplip*.
|
||||||
FLIGHTGROUP.PlayerSkill = {
|
FLIGHTGROUP.PlayerSkill = {
|
||||||
NOVICE="Novice",
|
STUDENT = "Student",
|
||||||
|
AVIATOR = "Aviator",
|
||||||
|
GRADUATE = "Graduate",
|
||||||
|
INSTRUCTOR = "Instructor",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Player settings.
|
--- Player data.
|
||||||
-- @type FLIGHTGROUP.PlayerSettings
|
-- @type FLIGHTGROUP.PlayerData
|
||||||
|
-- @type #string name Player name.
|
||||||
-- @field #boolean subtitles Display subtitles.
|
-- @field #boolean subtitles Display subtitles.
|
||||||
-- @field #string skill Skill level.
|
-- @field #string skill Skill level.
|
||||||
|
|
||||||
|
--- FLIGHTGROUP players.
|
||||||
|
-- @field #table Players Player data.
|
||||||
|
FLIGHTGROUP.Players={}
|
||||||
|
|
||||||
--- FLIGHTGROUP class version.
|
--- FLIGHTGROUP class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
FLIGHTGROUP.version="0.7.9"
|
FLIGHTGROUP.version="0.8.0"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -309,17 +322,18 @@ function FLIGHTGROUP:New(group)
|
|||||||
-- TODO: Add pseudo functions.
|
-- TODO: Add pseudo functions.
|
||||||
|
|
||||||
-- Handle events:
|
-- Handle events:
|
||||||
self:HandleEvent(EVENTS.Birth, self.OnEventBirth)
|
self:HandleEvent(EVENTS.Birth, self.OnEventBirth)
|
||||||
self:HandleEvent(EVENTS.EngineStartup, self.OnEventEngineStartup)
|
self:HandleEvent(EVENTS.EngineStartup, self.OnEventEngineStartup)
|
||||||
self:HandleEvent(EVENTS.Takeoff, self.OnEventTakeOff)
|
self:HandleEvent(EVENTS.Takeoff, self.OnEventTakeOff)
|
||||||
self:HandleEvent(EVENTS.Land, self.OnEventLanding)
|
self:HandleEvent(EVENTS.Land, self.OnEventLanding)
|
||||||
self:HandleEvent(EVENTS.EngineShutdown, self.OnEventEngineShutdown)
|
self:HandleEvent(EVENTS.EngineShutdown, self.OnEventEngineShutdown)
|
||||||
self:HandleEvent(EVENTS.PilotDead, self.OnEventPilotDead)
|
self:HandleEvent(EVENTS.PilotDead, self.OnEventPilotDead)
|
||||||
self:HandleEvent(EVENTS.Ejection, self.OnEventEjection)
|
self:HandleEvent(EVENTS.Ejection, self.OnEventEjection)
|
||||||
self:HandleEvent(EVENTS.Crash, self.OnEventCrash)
|
self:HandleEvent(EVENTS.Crash, self.OnEventCrash)
|
||||||
self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit)
|
self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit)
|
||||||
self:HandleEvent(EVENTS.UnitLost, self.OnEventUnitLost)
|
self:HandleEvent(EVENTS.UnitLost, self.OnEventUnitLost)
|
||||||
self:HandleEvent(EVENTS.Kill, self.OnEventKill)
|
self:HandleEvent(EVENTS.Kill, self.OnEventKill)
|
||||||
|
self:HandleEvent(EVENTS.PlayerLeaveUnit, self.OnEventPlayerLeaveUnit)
|
||||||
|
|
||||||
-- Init waypoints.
|
-- Init waypoints.
|
||||||
self:_InitWaypoints()
|
self:_InitWaypoints()
|
||||||
@ -385,7 +399,7 @@ function FLIGHTGROUP:SetReadyForTakeoff(ReadyTO, Delay)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set the FLIGHTCONTROL controlling this flight group. Also updates the player menu after 0.5 sec.
|
--- Set the FLIGHTCONTROL controlling this flight group.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
-- @param Ops.FlightControl#FLIGHTCONTROL flightcontrol The FLIGHTCONTROL object.
|
-- @param Ops.FlightControl#FLIGHTCONTROL flightcontrol The FLIGHTCONTROL object.
|
||||||
-- @return #FLIGHTGROUP self
|
-- @return #FLIGHTGROUP self
|
||||||
@ -411,11 +425,6 @@ function FLIGHTGROUP:SetFlightControl(flightcontrol)
|
|||||||
table.insert(flightcontrol.flights, self)
|
table.insert(flightcontrol.flights, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Update flight's F10 menu.
|
|
||||||
if not self.isAI then
|
|
||||||
self:_UpdateMenu(0.5)
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -564,22 +573,34 @@ end
|
|||||||
|
|
||||||
--- Check if flight is parking.
|
--- Check if flight is parking.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
|
-- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element.
|
||||||
-- @return #boolean If true, flight is parking after spawned.
|
-- @return #boolean If true, flight is parking after spawned.
|
||||||
function FLIGHTGROUP:IsParking()
|
function FLIGHTGROUP:IsParking(Element)
|
||||||
|
if Element then
|
||||||
|
return Element.status==OPSGROUP.ElementStatus.PARKING
|
||||||
|
end
|
||||||
return self:Is("Parking")
|
return self:Is("Parking")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check if is taxiing to the runway.
|
--- Check if is taxiing to the runway.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
|
-- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element.
|
||||||
-- @return #boolean If true, flight is taxiing after engine start up.
|
-- @return #boolean If true, flight is taxiing after engine start up.
|
||||||
function FLIGHTGROUP:IsTaxiing()
|
function FLIGHTGROUP:IsTaxiing(Element)
|
||||||
|
if Element then
|
||||||
|
return Element.status==OPSGROUP.ElementStatus.TAXIING
|
||||||
|
end
|
||||||
return self:Is("Taxiing")
|
return self:Is("Taxiing")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check if flight is airborne or cruising.
|
--- Check if flight is airborne or cruising.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
|
-- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element.
|
||||||
-- @return #boolean If true, flight is airborne.
|
-- @return #boolean If true, flight is airborne.
|
||||||
function FLIGHTGROUP:IsAirborne()
|
function FLIGHTGROUP:IsAirborne(Element)
|
||||||
|
if Element then
|
||||||
|
return Element.status==OPSGROUP.ElementStatus.AIRBORNE
|
||||||
|
end
|
||||||
return self:Is("Airborne") or self:Is("Cruising")
|
return self:Is("Airborne") or self:Is("Cruising")
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -592,22 +613,34 @@ end
|
|||||||
|
|
||||||
--- Check if flight is landing.
|
--- Check if flight is landing.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
|
-- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element.
|
||||||
-- @return #boolean If true, flight is landing, i.e. on final approach.
|
-- @return #boolean If true, flight is landing, i.e. on final approach.
|
||||||
function FLIGHTGROUP:IsLanding()
|
function FLIGHTGROUP:IsLanding(Element)
|
||||||
|
if Element then
|
||||||
|
return Element.status==OPSGROUP.ElementStatus.LANDING
|
||||||
|
end
|
||||||
return self:Is("Landing")
|
return self:Is("Landing")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check if flight has landed and is now taxiing to its parking spot.
|
--- Check if flight has landed and is now taxiing to its parking spot.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
|
-- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element.
|
||||||
-- @return #boolean If true, flight has landed
|
-- @return #boolean If true, flight has landed
|
||||||
function FLIGHTGROUP:IsLanded()
|
function FLIGHTGROUP:IsLanded(Element)
|
||||||
|
if Element then
|
||||||
|
return Element.status==OPSGROUP.ElementStatus.LANDED
|
||||||
|
end
|
||||||
return self:Is("Landed")
|
return self:Is("Landed")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check if flight has arrived at its destination parking spot.
|
--- Check if flight has arrived at its destination parking spot.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
|
-- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element.
|
||||||
-- @return #boolean If true, flight has arrived at its destination and is parking.
|
-- @return #boolean If true, flight has arrived at its destination and is parking.
|
||||||
function FLIGHTGROUP:IsArrived()
|
function FLIGHTGROUP:IsArrived(Element)
|
||||||
|
if Element then
|
||||||
|
return Element.status==OPSGROUP.ElementStatus.ARRIVED
|
||||||
|
end
|
||||||
return self:Is("Arrived")
|
return self:Is("Arrived")
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -639,9 +672,9 @@ function FLIGHTGROUP:IsLandingAt()
|
|||||||
return self:Is("LandingAt")
|
return self:Is("LandingAt")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check if helo(!) flight is currently landed at a specific point.
|
--- Check if helo(!) flight has landed at a specific point.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
-- @return #boolean If true, group is currently landed at the assigned position and waiting until task is complete.
|
-- @return #boolean If true, has landed somewhere.
|
||||||
function FLIGHTGROUP:IsLandedAt()
|
function FLIGHTGROUP:IsLandedAt()
|
||||||
return self:Is("LandedAt")
|
return self:Is("LandedAt")
|
||||||
end
|
end
|
||||||
@ -745,6 +778,9 @@ function FLIGHTGROUP:ClearToLand(Delay)
|
|||||||
self:T(self.lid..string.format("Clear to land ==> setting holding flag to 1 (true)"))
|
self:T(self.lid..string.format("Clear to land ==> setting holding flag to 1 (true)"))
|
||||||
self.flaghold:Set(1)
|
self.flaghold:Set(1)
|
||||||
|
|
||||||
|
-- Not holding any more.
|
||||||
|
self.Tholding=nil
|
||||||
|
|
||||||
-- Clear holding stack.
|
-- Clear holding stack.
|
||||||
if self.stack then
|
if self.stack then
|
||||||
self.stack.flightgroup=nil
|
self.stack.flightgroup=nil
|
||||||
@ -1123,6 +1159,11 @@ function FLIGHTGROUP:OnEventEngineStartup(EventData)
|
|||||||
-- TODO: what?
|
-- TODO: what?
|
||||||
else
|
else
|
||||||
self:T3(self.lid..string.format("EVENT: Element %s started engines ==> taxiing (if AI)", element.name))
|
self:T3(self.lid..string.format("EVENT: Element %s started engines ==> taxiing (if AI)", element.name))
|
||||||
|
|
||||||
|
-- Element started engies.
|
||||||
|
self:ElementEngineOn(element)
|
||||||
|
|
||||||
|
--[[
|
||||||
-- TODO: could be that this element is part of a human flight group.
|
-- TODO: could be that this element is part of a human flight group.
|
||||||
-- Problem: when player starts hot, the AI does too and starts to taxi immidiately :(
|
-- Problem: when player starts hot, the AI does too and starts to taxi immidiately :(
|
||||||
-- when player starts cold, ?
|
-- when player starts cold, ?
|
||||||
@ -1134,6 +1175,7 @@ function FLIGHTGROUP:OnEventEngineStartup(EventData)
|
|||||||
self:ElementEngineOn(element)
|
self:ElementEngineOn(element)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
]]
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -1299,6 +1341,10 @@ function FLIGHTGROUP:onafterElementSpawned(From, Event, To, Element)
|
|||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(self.lid..string.format("Element spawned %s", Element.name))
|
self:T(self.lid..string.format("Element spawned %s", Element.name))
|
||||||
|
|
||||||
|
if Element.playerName then
|
||||||
|
self:_InitPlayerData(Element.playerName)
|
||||||
|
end
|
||||||
|
|
||||||
-- Set element status.
|
-- Set element status.
|
||||||
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.SPAWNED)
|
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.SPAWNED)
|
||||||
@ -1524,12 +1570,13 @@ end
|
|||||||
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
|
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
|
||||||
function FLIGHTGROUP:onafterElementDead(From, Event, To, Element)
|
function FLIGHTGROUP:onafterElementDead(From, Event, To, Element)
|
||||||
|
|
||||||
-- Call OPSGROUP function.
|
-- Check for flight control.
|
||||||
self:GetParent(self).onafterElementDead(self, From, Event, To, Element)
|
|
||||||
|
|
||||||
if self.flightcontrol and Element.parking then
|
if self.flightcontrol and Element.parking then
|
||||||
self.flightcontrol:SetParkingFree(Element.parking)
|
self.flightcontrol:SetParkingFree(Element.parking)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Call OPSGROUP function. This will remove the flightcontrol. Therefore, has to be after setting parking free.
|
||||||
|
self:GetParent(self).onafterElementDead(self, From, Event, To, Element)
|
||||||
|
|
||||||
-- Not parking any more.
|
-- Not parking any more.
|
||||||
Element.parking=nil
|
Element.parking=nil
|
||||||
@ -1628,8 +1675,6 @@ function FLIGHTGROUP:onafterSpawned(From, Event, To)
|
|||||||
self:__UpdateRoute(-0.5)
|
self:__UpdateRoute(-0.5)
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
env.info("FF Spawned update menu")
|
|
||||||
|
|
||||||
-- Set flightcontrol.
|
-- Set flightcontrol.
|
||||||
if self.currbase then
|
if self.currbase then
|
||||||
@ -1687,15 +1732,10 @@ function FLIGHTGROUP:onafterParking(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.isAI then
|
|
||||||
self:_UpdateMenu(0.5)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
self:E(self.lid.."ERROR: FF no flight control in onAfterParking!")
|
self:T3(self.lid.."INFO: No flight control in onAfterParking!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1719,9 +1759,6 @@ function FLIGHTGROUP:onafterTaxiing(From, Event, To)
|
|||||||
else
|
else
|
||||||
-- Human flights go to TAXI OUT queue. They will go to the ready for takeoff queue when they request it.
|
-- Human flights go to TAXI OUT queue. They will go to the ready for takeoff queue when they request it.
|
||||||
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.TAXIOUT)
|
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.TAXIOUT)
|
||||||
|
|
||||||
-- Update menu.
|
|
||||||
self:_UpdateMenu()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -1802,8 +1839,23 @@ end
|
|||||||
function FLIGHTGROUP:onafterLanding(From, Event, To)
|
function FLIGHTGROUP:onafterLanding(From, Event, To)
|
||||||
self:T(self.lid..string.format("Flight is landing"))
|
self:T(self.lid..string.format("Flight is landing"))
|
||||||
|
|
||||||
|
-- Everyone is landing now.
|
||||||
self:_SetElementStatusAll(OPSGROUP.ElementStatus.LANDING)
|
self:_SetElementStatusAll(OPSGROUP.ElementStatus.LANDING)
|
||||||
|
|
||||||
|
if self.flightcontrol and self.flightcontrol:IsControlling(self) then
|
||||||
|
-- Add flight to landing queue.
|
||||||
|
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.LANDING)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Not holding any more.
|
||||||
|
self.Tholding=nil
|
||||||
|
|
||||||
|
-- Clear holding stack.
|
||||||
|
if self.stack then
|
||||||
|
self.stack.flightgroup=nil
|
||||||
|
self.stack=nil
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -1816,7 +1868,7 @@ end
|
|||||||
function FLIGHTGROUP:onafterLanded(From, Event, To, airbase)
|
function FLIGHTGROUP:onafterLanded(From, Event, To, airbase)
|
||||||
self:T(self.lid..string.format("Flight landed at %s", airbase and airbase:GetName() or "unknown place"))
|
self:T(self.lid..string.format("Flight landed at %s", airbase and airbase:GetName() or "unknown place"))
|
||||||
|
|
||||||
if self.flightcontrol and airbase and self.flightcontrol.airbasename==airbase:GetName() then
|
if self.flightcontrol and self.flightcontrol:IsControlling(self) then
|
||||||
-- Add flight to taxiinb queue.
|
-- Add flight to taxiinb queue.
|
||||||
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.TAXIINB)
|
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.TAXIINB)
|
||||||
end
|
end
|
||||||
@ -2613,7 +2665,7 @@ function FLIGHTGROUP:_LandAtAirbase(airbase, SpeedTo, SpeedHold, SpeedLand)
|
|||||||
local h2=x2*math.tan(alpha)
|
local h2=x2*math.tan(alpha)
|
||||||
|
|
||||||
-- Get active runway.
|
-- Get active runway.
|
||||||
local runway=airbase:GetActiveRunway()
|
local runway=airbase:GetActiveRunwayLanding()
|
||||||
|
|
||||||
-- Set holding flag to 0=false.
|
-- Set holding flag to 0=false.
|
||||||
self.flaghold:Set(0)
|
self.flaghold:Set(0)
|
||||||
@ -2648,8 +2700,12 @@ function FLIGHTGROUP:_LandAtAirbase(airbase, SpeedTo, SpeedHold, SpeedLand)
|
|||||||
-- Airdrome
|
-- Airdrome
|
||||||
---
|
---
|
||||||
|
|
||||||
|
-- Call a function to tell everyone we are on final.
|
||||||
|
local TaskFinal = self.group:TaskFunction("FLIGHTGROUP._OnFinal", self)
|
||||||
|
|
||||||
|
-- Final approach waypoint.
|
||||||
local papp=airbase:GetCoordinate():Translate(x1, runway.heading-180):SetAltitude(h1)
|
local papp=airbase:GetCoordinate():Translate(x1, runway.heading-180):SetAltitude(h1)
|
||||||
wp[#wp+1]=papp:WaypointAirTurningPoint("BARO", UTILS.KnotsToKmph(SpeedLand), {}, "Final Approach")
|
wp[#wp+1]=papp:WaypointAirTurningPoint("BARO", UTILS.KnotsToKmph(SpeedLand), {TaskFinal}, "Final Approach")
|
||||||
|
|
||||||
-- Okay, it looks like it's best to specify the coordinates not at the airbase but a bit away. This causes a more direct landing approach.
|
-- Okay, it looks like it's best to specify the coordinates not at the airbase but a bit away. This causes a more direct landing approach.
|
||||||
local pland=airbase:GetCoordinate():Translate(x2, runway.heading-180):SetAltitude(h2)
|
local pland=airbase:GetCoordinate():Translate(x2, runway.heading-180):SetAltitude(h2)
|
||||||
@ -2855,13 +2911,9 @@ function FLIGHTGROUP:onafterHolding(From, Event, To)
|
|||||||
-- Add flight to waiting/holding queue.
|
-- Add flight to waiting/holding queue.
|
||||||
if self.flightcontrol then
|
if self.flightcontrol then
|
||||||
|
|
||||||
-- Set flight status to holding
|
-- Set flight status to holding.
|
||||||
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.HOLDING)
|
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.HOLDING)
|
||||||
|
|
||||||
if not self.isAI then
|
|
||||||
self:_UpdateMenu()
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif self.airboss then
|
elseif self.airboss then
|
||||||
|
|
||||||
if self.isHelo then
|
if self.isHelo then
|
||||||
@ -3112,6 +3164,20 @@ function FLIGHTGROUP._ClearedToLand(group, flightgroup)
|
|||||||
flightgroup:__Landing(-1)
|
flightgroup:__Landing(-1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Function called when flight is on final.
|
||||||
|
-- @param Wrapper.Group#GROUP group Group object.
|
||||||
|
-- @param #FLIGHTGROUP flightgroup Flight group object.
|
||||||
|
function FLIGHTGROUP._OnFinal(group, flightgroup)
|
||||||
|
flightgroup:T2(flightgroup.lid..string.format("Group on final approach"))
|
||||||
|
|
||||||
|
local fc=flightgroup.flightcontrol
|
||||||
|
|
||||||
|
if fc and fc:IsControlling(flightgroup) then
|
||||||
|
fc:_FlightOnFinal(flightgroup)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Function called when flight finished refuelling.
|
--- Function called when flight finished refuelling.
|
||||||
-- @param Wrapper.Group#GROUP group Group object.
|
-- @param Wrapper.Group#GROUP group Group object.
|
||||||
-- @param #FLIGHTGROUP flightgroup Flight group object.
|
-- @param #FLIGHTGROUP flightgroup Flight group object.
|
||||||
@ -3667,6 +3733,20 @@ function FLIGHTGROUP:GetPlayerElement()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get player element.
|
||||||
|
-- @param #FLIGHTGROUP self
|
||||||
|
-- @return #string Player name or `nil`.
|
||||||
|
function FLIGHTGROUP:GetPlayerName()
|
||||||
|
|
||||||
|
local playerElement=self:GetPlayerElement()
|
||||||
|
|
||||||
|
if playerElement then
|
||||||
|
return playerElement.playerName
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Set parking spot of element.
|
--- Set parking spot of element.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
-- @param Ops.OpsGroup#OPSGROUP.Element Element The element.
|
-- @param Ops.OpsGroup#OPSGROUP.Element Element The element.
|
||||||
@ -4181,65 +4261,75 @@ function FLIGHTGROUP:_UpdateMenu(delay)
|
|||||||
-- Delayed call.
|
-- Delayed call.
|
||||||
self:ScheduleOnce(delay, FLIGHTGROUP._UpdateMenu, self)
|
self:ScheduleOnce(delay, FLIGHTGROUP._UpdateMenu, self)
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Message to group.
|
|
||||||
MESSAGE:New("Updating MENU state="..self:GetState(), 5):ToGroup(self.group)
|
|
||||||
env.info(self.lid.."updating menu state="..self:GetState())
|
|
||||||
|
|
||||||
-- Player element.
|
-- Player element.
|
||||||
local player=self:GetPlayerElement()
|
local player=self:GetPlayerElement()
|
||||||
|
|
||||||
-- Get current position of player.
|
|
||||||
local position=self:GetCoordinate(nil, player.name)
|
|
||||||
|
|
||||||
-- Get all FLIGHTCONTROLS
|
|
||||||
local fc={}
|
|
||||||
for airbasename,_flightcontrol in pairs(_DATABASE.FLIGHTCONTROLS) do
|
|
||||||
local flightcontrol=_flightcontrol --Ops.FlightControl#FLIGHTCONTROL
|
|
||||||
|
|
||||||
-- Get coord of airbase.
|
|
||||||
local coord=flightcontrol:GetCoordinate()
|
|
||||||
|
|
||||||
-- Distance to flight.
|
|
||||||
local dist=coord:Get2DDistance(position)
|
|
||||||
|
|
||||||
-- Add to table.
|
|
||||||
table.insert(fc, {airbasename=airbasename, dist=dist})
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Sort table wrt distance to airbases.
|
|
||||||
local function _sort(a,b)
|
|
||||||
return a.dist<b.dist
|
|
||||||
end
|
|
||||||
table.sort(fc, _sort)
|
|
||||||
|
|
||||||
-- Remove all submenus.
|
if player and player.status~=OPSGROUP.ElementStatus.DEAD then
|
||||||
self.menu.atc.root:RemoveSubMenus()
|
|
||||||
|
-- Debug text.
|
||||||
|
local text=string.format("Updating MENU: State=%s, ATC=%s [%s]", self:GetState(),
|
||||||
|
self.flightcontrol and self.flightcontrol.airbasename or "None", self.flightcontrol and self.flightcontrol:GetFlightStatus(self) or "Unknown")
|
||||||
|
|
||||||
-- Create help menu.
|
-- Message to group.
|
||||||
self:_CreateMenuAtcHelp(self.menu.atc.root)
|
MESSAGE:New(text, 5):ToGroup(self.group)
|
||||||
|
self:I(self.lid..text)
|
||||||
|
|
||||||
-- Max menu entries.
|
-- Get current position of player.
|
||||||
local N=7
|
local position=self:GetCoordinate(nil, player.name)
|
||||||
|
|
||||||
-- If there is a designated FC, we put it first.
|
-- Get all FLIGHTCONTROLS
|
||||||
local gotairbase=nil
|
local fc={}
|
||||||
if self.flightcontrol then
|
for airbasename,_flightcontrol in pairs(_DATABASE.FLIGHTCONTROLS) do
|
||||||
self.flightcontrol:_CreatePlayerMenu(self, self.menu.atc.root)
|
local flightcontrol=_flightcontrol --Ops.FlightControl#FLIGHTCONTROL
|
||||||
gotairbase=self.flightcontrol.airbasename
|
|
||||||
N=N-1
|
-- Get coord of airbase.
|
||||||
end
|
local coord=flightcontrol:GetCoordinate()
|
||||||
|
|
||||||
-- Max 8 entries in F10 menu.
|
-- Distance to flight.
|
||||||
for i=1,math.min(#fc,N) do
|
local dist=coord:Get2DDistance(position)
|
||||||
local airbasename=fc[i].airbasename
|
|
||||||
if gotairbase==nil or airbasename~=gotairbase then
|
-- Add to table.
|
||||||
local flightcontrol=_DATABASE:GetFlightControl(airbasename)
|
table.insert(fc, {airbasename=airbasename, dist=dist})
|
||||||
flightcontrol:_CreatePlayerMenu(self, self.menu.atc.root)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Sort table wrt distance to airbases.
|
||||||
|
local function _sort(a,b)
|
||||||
|
return a.dist<b.dist
|
||||||
|
end
|
||||||
|
table.sort(fc, _sort)
|
||||||
|
|
||||||
|
-- Remove all submenus.
|
||||||
|
self.menu.atc.root:RemoveSubMenus()
|
||||||
|
|
||||||
|
-- Create help menu.
|
||||||
|
self:_CreateMenuAtcHelp(self.menu.atc.root)
|
||||||
|
|
||||||
|
-- Max menu entries.
|
||||||
|
local N=7
|
||||||
|
|
||||||
|
-- If there is a designated FC, we put it first.
|
||||||
|
local gotairbase=nil
|
||||||
|
if self.flightcontrol then
|
||||||
|
self.flightcontrol:_CreatePlayerMenu(self, self.menu.atc.root)
|
||||||
|
gotairbase=self.flightcontrol.airbasename
|
||||||
|
N=N-1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Max 8 entries in F10 menu.
|
||||||
|
for i=1,math.min(#fc,N) do
|
||||||
|
local airbasename=fc[i].airbasename
|
||||||
|
if gotairbase==nil or airbasename~=gotairbase then
|
||||||
|
local flightcontrol=_DATABASE:GetFlightControl(airbasename)
|
||||||
|
flightcontrol:_CreatePlayerMenu(self, self.menu.atc.root)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
self:E(self.lid.."ERROR: Player dead in update menu!")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Create player menu.
|
--- Create player menu.
|
||||||
@ -4257,14 +4347,15 @@ function FLIGHTGROUP:_CreateMenuAtcHelp(rootmenu)
|
|||||||
-- Skill level menu
|
-- Skill level menu
|
||||||
---
|
---
|
||||||
local skillmenu=MENU_GROUP:New(self.group, "Skill Level", helpmenu)
|
local skillmenu=MENU_GROUP:New(self.group, "Skill Level", helpmenu)
|
||||||
MENU_GROUP_COMMAND:New(self.group, "Beginner", skillmenu, self._MenuNotImplemented, self, groupname)
|
MENU_GROUP_COMMAND:New(self.group, "Student", skillmenu, self._PlayerSkill, self, FLIGHTGROUP.PlayerSkill.STUDENT)
|
||||||
MENU_GROUP_COMMAND:New(self.group, "Student", skillmenu, self._MenuNotImplemented, self, groupname)
|
MENU_GROUP_COMMAND:New(self.group, "Aviator", skillmenu, self._PlayerSkill, self, FLIGHTGROUP.PlayerSkill.AVIATOR)
|
||||||
MENU_GROUP_COMMAND:New(self.group, "Professional", skillmenu, self._MenuNotImplemented, self, groupname)
|
MENU_GROUP_COMMAND:New(self.group, "Graduate", skillmenu, self._PlayerSkill, self, FLIGHTGROUP.PlayerSkill.GRADUATE)
|
||||||
|
MENU_GROUP_COMMAND:New(self.group, "Instructor", skillmenu, self._PlayerSkill, self, FLIGHTGROUP.PlayerSkill.INSTRUCTOR)
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Commands
|
-- Commands
|
||||||
---
|
---
|
||||||
MENU_GROUP_COMMAND:New(self.group, "Subtitles On/Off", helpmenu, self._MenuNotImplemented, self, groupname)
|
MENU_GROUP_COMMAND:New(self.group, "Subtitles On/Off", helpmenu, self._PlayerSubtitles, self)
|
||||||
MENU_GROUP_COMMAND:New(self.group, "My Voice On/Off", helpmenu, self._MenuNotImplemented, self, groupname)
|
MENU_GROUP_COMMAND:New(self.group, "My Voice On/Off", helpmenu, self._MenuNotImplemented, self, groupname)
|
||||||
MENU_GROUP_COMMAND:New(self.group, "Update Menu", helpmenu, self._UpdateMenu, self, 0)
|
MENU_GROUP_COMMAND:New(self.group, "Update Menu", helpmenu, self._UpdateMenu, self, 0)
|
||||||
MENU_GROUP_COMMAND:New(self.group, "My Status", helpmenu, self._PlayerMyStatus, self, groupname)
|
MENU_GROUP_COMMAND:New(self.group, "My Status", helpmenu, self._PlayerMyStatus, self, groupname)
|
||||||
@ -4284,7 +4375,6 @@ function FLIGHTGROUP:_MenuNotImplemented(groupname)
|
|||||||
local text=string.format("Sorry, this feature is not implemented yet!")
|
local text=string.format("Sorry, this feature is not implemented yet!")
|
||||||
|
|
||||||
MESSAGE:New(text, 10, nil, true):ToGroup(flight.group)
|
MESSAGE:New(text, 10, nil, true):ToGroup(flight.group)
|
||||||
--self:TextMessageToFlight(text, flight)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -4292,32 +4382,123 @@ end
|
|||||||
|
|
||||||
--- Player status.
|
--- Player status.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
-- @param #string groupname Name of the flight group.
|
function FLIGHTGROUP:_PlayerMyStatus()
|
||||||
function FLIGHTGROUP:_PlayerMyStatus(groupname)
|
|
||||||
|
|
||||||
-- Get flight group.
|
-- Flight control.
|
||||||
local flight=_DATABASE:GetOpsGroup(groupname) --Ops.FlightGroup#FLIGHTGROUP
|
local fc=self.flightcontrol
|
||||||
|
|
||||||
if flight then
|
-- Player data.
|
||||||
|
local playerdata=self:_GetPlayerData()
|
||||||
|
|
||||||
|
-- Status text.
|
||||||
|
local text=string.format("My Status:")
|
||||||
|
text=text..string.format("\nPlayer Name: %s", tostring(playerdata.name))
|
||||||
|
text=text..string.format("\nCallsign: %s", tostring(self:GetCallsignName()))
|
||||||
|
text=text..string.format("\nFlight status: %s", tostring(self:GetState()))
|
||||||
|
text=text..string.format("\nFlight control: %s [%s]", tostring(fc and fc.airbasename or "N/A"), tostring(fc and fc:GetFlightStatus(self) or "N/A"))
|
||||||
|
text=text..string.format("\nSubtitles: %s", tostring(playerdata.subtitles))
|
||||||
|
text=text..string.format("\nMy Voice: %s", tostring(playerdata.myvoice))
|
||||||
|
|
||||||
|
-- Send message.
|
||||||
|
MESSAGE:New(text, 10, nil, true):ToGroup(self.group)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Player set subtitles.
|
||||||
|
-- @param #FLIGHTGROUP self
|
||||||
|
function FLIGHTGROUP:_PlayerSubtitles()
|
||||||
|
|
||||||
|
-- Get Player data.
|
||||||
|
local playerData=self:_GetPlayerData()
|
||||||
|
|
||||||
|
if playerData then
|
||||||
|
|
||||||
|
-- Switch setting.
|
||||||
|
playerData.subtitles=not playerData.subtitles
|
||||||
|
|
||||||
local fc=flight.flightcontrol
|
-- Display message.
|
||||||
|
MESSAGE:New(string.format("%s, subtitles are now %s", playerData.name, tostring(playerData.subtitles)), 10, nil, true):ToGroup(self.group)
|
||||||
-- Status text.
|
|
||||||
local text=string.format("My Status:")
|
|
||||||
text=text..string.format("\nCallsign: %s", tostring(flight:GetCallsignName()))
|
|
||||||
text=text..string.format("\nFlight status: %s", tostring(flight:GetState()))
|
|
||||||
text=text..string.format("\nFlight control: %s [%s]", tostring(fc and fc.airbasename or "N/A"), tostring(fc and fc:GetFlightStatus(flight) or "N/A"))
|
|
||||||
|
|
||||||
-- Send message.
|
|
||||||
--self:TextMessageToFlight(text, flight, 10, true)
|
|
||||||
MESSAGE:New(text, 10, nil, true):ToGroup(flight.group)
|
|
||||||
|
|
||||||
else
|
else
|
||||||
--TODO: Error
|
--TODO: Error
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Player set skill.
|
||||||
|
-- @param #FLIGHTGROUP self
|
||||||
|
-- @param #string Skill Skill.
|
||||||
|
function FLIGHTGROUP:_PlayerSkill(Skill)
|
||||||
|
|
||||||
|
-- Get Player data.
|
||||||
|
local playerData=self:_GetPlayerData()
|
||||||
|
|
||||||
|
if playerData then
|
||||||
|
|
||||||
|
-- Switch setting.
|
||||||
|
playerData.skill=Skill
|
||||||
|
|
||||||
|
-- Display message.
|
||||||
|
MESSAGE:New(string.format("%s, your skill is %s", playerData.name, tostring(playerData.skill)), 10, nil, true):ToGroup(self.group)
|
||||||
|
|
||||||
|
else
|
||||||
|
--TODO: Error
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Init player data.
|
||||||
|
-- @param #FLIGHTGROUP self
|
||||||
|
-- @param #string PlayerName Player name.
|
||||||
|
-- @return #FLIGHTGROUP.PlayerData Player data.
|
||||||
|
function FLIGHTGROUP:_InitPlayerData(PlayerName)
|
||||||
|
|
||||||
|
if PlayerName then
|
||||||
|
|
||||||
|
-- Check if data is already there.
|
||||||
|
local playerData=FLIGHTGROUP.Players[PlayerName] --#FLIGHTGROUP.PlayerData
|
||||||
|
|
||||||
|
if not playerData then
|
||||||
|
|
||||||
|
local playerData={} --#FLIGHTGROUP.PlayerData
|
||||||
|
playerData.name=PlayerName
|
||||||
|
playerData.skill=FLIGHTGROUP.PlayerSkill.STUDENT
|
||||||
|
playerData.subtitles=true
|
||||||
|
playerData.myvoice=true
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
self:T(self.lid..string.format("Init player data for %s", PlayerName))
|
||||||
|
|
||||||
|
-- Set data globally.
|
||||||
|
FLIGHTGROUP.Players[PlayerName]=playerData
|
||||||
|
end
|
||||||
|
|
||||||
|
return playerData
|
||||||
|
|
||||||
|
else
|
||||||
|
self:E(self.lid..string.format("ERROR: Player name is nil!"))
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get player data.
|
||||||
|
-- @param #FLIGHTGROUP self
|
||||||
|
-- @return #FLIGHTGROUP.PlayerData Player data.
|
||||||
|
function FLIGHTGROUP:_GetPlayerData()
|
||||||
|
|
||||||
|
-- Get player element.
|
||||||
|
local playerElement=self:GetPlayerElement()
|
||||||
|
|
||||||
|
if playerElement and playerElement.playerName then
|
||||||
|
return FLIGHTGROUP.Players[playerElement.playerName]
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@ -262,17 +262,17 @@ OPSGROUP = {
|
|||||||
-- @field #string ARRIVED Element arrived at its parking spot and shut down its engines.
|
-- @field #string ARRIVED Element arrived at its parking spot and shut down its engines.
|
||||||
-- @field #string DEAD Element is dead after it crashed, pilot ejected or pilot dead events.
|
-- @field #string DEAD Element is dead after it crashed, pilot ejected or pilot dead events.
|
||||||
OPSGROUP.ElementStatus={
|
OPSGROUP.ElementStatus={
|
||||||
INUTERO="inutero",
|
INUTERO="InUtero",
|
||||||
SPAWNED="spawned",
|
SPAWNED="Spawned",
|
||||||
PARKING="parking",
|
PARKING="Parking",
|
||||||
ENGINEON="engineon",
|
ENGINEON="Engine On",
|
||||||
TAXIING="taxiing",
|
TAXIING="Taxiing",
|
||||||
TAKEOFF="takeoff",
|
TAKEOFF="Takeoff",
|
||||||
AIRBORNE="airborne",
|
AIRBORNE="Airborne",
|
||||||
LANDING="landing",
|
LANDING="Landing",
|
||||||
LANDED="landed",
|
LANDED="Landed",
|
||||||
ARRIVED="arrived",
|
ARRIVED="Arrived",
|
||||||
DEAD="dead",
|
DEAD="Dead",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Status of group.
|
--- Status of group.
|
||||||
@ -3452,10 +3452,37 @@ function OPSGROUP:OnEventRemoveUnit(EventData)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Event function handling when a unit is removed from the game.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data.
|
||||||
|
function OPSGROUP:OnEventPlayerLeaveUnit(EventData)
|
||||||
|
|
||||||
|
-- Check that this is the right group.
|
||||||
|
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
|
||||||
|
self:T2(self.lid..string.format("EVENT: Player left Unit %s!", EventData.IniUnitName))
|
||||||
|
|
||||||
|
local unit=EventData.IniUnit
|
||||||
|
local group=EventData.IniGroup
|
||||||
|
local unitname=EventData.IniUnitName
|
||||||
|
|
||||||
|
-- Get element.
|
||||||
|
local element=self:GetElementByName(unitname)
|
||||||
|
|
||||||
|
if element and element.status~=OPSGROUP.ElementStatus.DEAD then
|
||||||
|
self:T(self.lid..string.format("EVENT: Player left Element %s ==> dead", element.name))
|
||||||
|
self:ElementDead(element)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Event function handling the event that a unit achieved a kill.
|
--- Event function handling the event that a unit achieved a kill.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param Core.Event#EVENTDATA EventData Event data.
|
-- @param Core.Event#EVENTDATA EventData Event data.
|
||||||
function OPSGROUP:OnEventKill(EventData)
|
function OPSGROUP:OnEventKill(EventData)
|
||||||
|
--self:I("FF event kill")
|
||||||
|
--self:I(EventData)
|
||||||
|
|
||||||
-- Check that this is the right group.
|
-- Check that this is the right group.
|
||||||
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
|
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
|
||||||
@ -7354,14 +7381,11 @@ function OPSGROUP:onafterDead(From, Event, To)
|
|||||||
-- All elements were destroyed ==> Asset group is gone.
|
-- All elements were destroyed ==> Asset group is gone.
|
||||||
self.cohort:DelGroup(self.groupname)
|
self.cohort:DelGroup(self.groupname)
|
||||||
end
|
end
|
||||||
if self.legion then
|
|
||||||
--self.legion:Get
|
|
||||||
--self.legion:AssetDead()
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
-- Not all assets were destroyed (despawn) ==> Add asset back to legion?
|
-- Not all assets were destroyed (despawn) ==> Add asset back to legion?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
if self.legion then
|
if self.legion then
|
||||||
if not self:IsInUtero() then
|
if not self:IsInUtero() then
|
||||||
|
|
||||||
@ -7377,6 +7401,10 @@ function OPSGROUP:onafterDead(From, Event, To)
|
|||||||
|
|
||||||
-- Stop in 5 sec to give possible respawn attempts a chance.
|
-- Stop in 5 sec to give possible respawn attempts a chance.
|
||||||
self:__Stop(-5)
|
self:__Stop(-5)
|
||||||
|
|
||||||
|
elseif not self.isAI then
|
||||||
|
-- Stop player flights.
|
||||||
|
self:__Stop(-1)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -11679,15 +11707,15 @@ function OPSGROUP:SwitchCallsign(CallsignName, CallsignNumber)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get callsign
|
--- Get callsign of the first element alive.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @return #string Callsign name, e.g. Uzi-1
|
-- @return #string Callsign name, e.g. Uzi11, or "Ghostrider11".
|
||||||
function OPSGROUP:GetCallsignName()
|
function OPSGROUP:GetCallsignName()
|
||||||
|
|
||||||
local element=self:GetElementAlive()
|
local element=self:GetElementAlive()
|
||||||
|
|
||||||
if element then
|
if element then
|
||||||
env.info("FF callsign "..tostring(element.callsign))
|
self:T2(self.lid..string.format("Callsign %s", tostring(element.callsign)))
|
||||||
return element.callsign
|
return element.callsign
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -11710,7 +11738,7 @@ function OPSGROUP:GetCallsignName()
|
|||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
return callsign
|
return "Ghostrider11"
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -12666,6 +12694,7 @@ function OPSGROUP:_AddElementByName(unitname)
|
|||||||
if element.skill=="Client" or element.skill=="Player" then
|
if element.skill=="Client" or element.skill=="Player" then
|
||||||
element.ai=false
|
element.ai=false
|
||||||
element.client=CLIENT:FindByName(unitname)
|
element.client=CLIENT:FindByName(unitname)
|
||||||
|
element.playerName=element.DCSunit:getPlayerName()
|
||||||
else
|
else
|
||||||
element.ai=true
|
element.ai=true
|
||||||
end
|
end
|
||||||
|
|||||||
@ -25,10 +25,11 @@
|
|||||||
-- @field #boolean isShip Airbase is a ship.
|
-- @field #boolean isShip Airbase is a ship.
|
||||||
-- @field #table parking Parking spot data.
|
-- @field #table parking Parking spot data.
|
||||||
-- @field #table parkingByID Parking spot data table with ID as key.
|
-- @field #table parkingByID Parking spot data table with ID as key.
|
||||||
-- @field #number activerwyno Active runway number (forced).
|
|
||||||
-- @field #table parkingWhitelist List of parking spot terminal IDs considered for spawning.
|
-- @field #table parkingWhitelist List of parking spot terminal IDs considered for spawning.
|
||||||
-- @field #table parkingBlacklist List of parking spot terminal IDs **not** considered for spawning.
|
-- @field #table parkingBlacklist List of parking spot terminal IDs **not** considered for spawning.
|
||||||
-- @field #table runways Runways of airdromes.
|
-- @field #table runways Runways of airdromes.
|
||||||
|
-- @field #AIRBASE.Runway runwayLanding Runway used for landing.
|
||||||
|
-- @field #AIRBASE.Runway runwayTakeoff Runway used for takeoff.
|
||||||
-- @extends Wrapper.Positionable#POSITIONABLE
|
-- @extends Wrapper.Positionable#POSITIONABLE
|
||||||
|
|
||||||
--- Wrapper class to handle the DCS Airbase objects:
|
--- Wrapper class to handle the DCS Airbase objects:
|
||||||
@ -70,7 +71,6 @@ AIRBASE = {
|
|||||||
[Airbase.Category.HELIPAD] = "Helipad",
|
[Airbase.Category.HELIPAD] = "Helipad",
|
||||||
[Airbase.Category.SHIP] = "Ship",
|
[Airbase.Category.SHIP] = "Ship",
|
||||||
},
|
},
|
||||||
activerwyno=nil,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Enumeration to identify the airbases in the Caucasus region.
|
--- Enumeration to identify the airbases in the Caucasus region.
|
||||||
@ -612,6 +612,9 @@ function AIRBASE:Register(AirbaseName)
|
|||||||
|
|
||||||
-- Init Runways.
|
-- Init Runways.
|
||||||
self:_InitRunways()
|
self:_InitRunways()
|
||||||
|
|
||||||
|
-- Set the active runways based on wind direction.
|
||||||
|
self:SetActiveRunway()
|
||||||
|
|
||||||
-- Init parking spots.
|
-- Init parking spots.
|
||||||
self:_InitParkingSpots()
|
self:_InitParkingSpots()
|
||||||
@ -1531,6 +1534,33 @@ function AIRBASE:GetRunways()
|
|||||||
return self.runways or {}
|
return self.runways or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get runway by its name.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @param #string Name Name of the runway, e.g. "31" or "21L".
|
||||||
|
-- @return #AIRBASE.Runway Runway data.
|
||||||
|
function AIRBASE:GetRunwayByName(Name)
|
||||||
|
|
||||||
|
if Name==nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if Name then
|
||||||
|
for _,_runway in pairs(self.runways) do
|
||||||
|
local runway=_runway --#AIRBASE.Runway
|
||||||
|
|
||||||
|
-- Name including L or R, e.g. "31L".
|
||||||
|
local name=self:GetRunwayName(runway)
|
||||||
|
|
||||||
|
if name==Name:upper() then
|
||||||
|
return runway
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self:E("ERROR: Could not find runway with name "..tostring(Name))
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Init runways.
|
--- Init runways.
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @param #boolean IncludeInverse If `true` or `nil`, include inverse runways.
|
-- @param #boolean IncludeInverse If `true` or `nil`, include inverse runways.
|
||||||
@ -1906,30 +1936,101 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
|||||||
return runways
|
return runways
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set the active runway in case it cannot be determined by the wind direction.
|
--- Set the active runway for landing and takeoff.
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @param #number iactive Number of the active runway in the runway data table.
|
-- @param #string Name Name of the runway, e.g. "31" or "02L" or "90R". If not given, the runway is determined from the wind direction.
|
||||||
function AIRBASE:SetActiveRunway(iactive)
|
-- @param #boolean PreferLeft If `true`, perfer the left runway. If `false`, prefer the right runway. If `nil` (default), do not care about left or right.
|
||||||
self.activerwyno=iactive
|
function AIRBASE:SetActiveRunway(Name, PreferLeft)
|
||||||
|
|
||||||
|
self:SetActiveRunwayTakeoff(Name, PreferLeft)
|
||||||
|
|
||||||
|
self:SetActiveRunwayLanding(Name,PreferLeft)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get the active runway based on current wind direction.
|
--- Set the active runway for landing.
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @param #number magvar (Optional) Magnetic variation in degrees.
|
-- @param #string Name Name of the runway, e.g. "31" or "02L" or "90R". If not given, the runway is determined from the wind direction.
|
||||||
-- @return #AIRBASE.Runway Active runway data table.
|
-- @param #boolean PreferLeft If `true`, perfer the left runway. If `false`, prefer the right runway. If `nil` (default), do not care about left or right.
|
||||||
function AIRBASE:GetActiveRunway(magvar)
|
-- @return #AIRBASE.Runway The active runway for landing.
|
||||||
|
function AIRBASE:SetActiveRunwayLanding(Name, PreferLeft)
|
||||||
|
|
||||||
-- Get runways data (initialize if necessary).
|
local runway=self:GetRunwayByName(Name)
|
||||||
--local runways=self:GetRunwayData(magvar)
|
|
||||||
|
if not runway then
|
||||||
|
runway=self:GetRunwayIntoWind(PreferLeft)
|
||||||
|
end
|
||||||
|
|
||||||
|
if runway then
|
||||||
|
self:I("Setting active runway for landing as "..self:GetRunwayName(runway))
|
||||||
|
else
|
||||||
|
self:E("ERROR: Could not set the runway for landing!")
|
||||||
|
end
|
||||||
|
|
||||||
|
self.runwayLanding=runway
|
||||||
|
|
||||||
|
return runway
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the active runways.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @return #AIRBASE.Runway The active runway for landing.
|
||||||
|
-- @return #AIRBASE.Runway The active runway for takeoff.
|
||||||
|
function AIRBASE:GetActiveRunway()
|
||||||
|
return self.runwayLanding, self.runwayTakeoff
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get the active runway for landing.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @return #AIRBASE.Runway The active runway for landing.
|
||||||
|
function AIRBASE:GetActiveRunwayLanding()
|
||||||
|
return self.runwayLanding
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the active runway for takeoff.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @return #AIRBASE.Runway The active runway for takeoff.
|
||||||
|
function AIRBASE:GetActiveRunwayTakeoff()
|
||||||
|
return self.runwayTakeoff
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Set the active runway for takeoff.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @param #string Name Name of the runway, e.g. "31" or "02L" or "90R". If not given, the runway is determined from the wind direction.
|
||||||
|
-- @param #boolean PreferLeft If `true`, perfer the left runway. If `false`, prefer the right runway. If `nil` (default), do not care about left or right.
|
||||||
|
-- @return #AIRBASE.Runway The active runway for landing.
|
||||||
|
function AIRBASE:SetActiveRunwayTakeoff(Name, PreferLeft)
|
||||||
|
|
||||||
|
local runway=self:GetRunwayByName(Name)
|
||||||
|
|
||||||
|
if not runway then
|
||||||
|
runway=self:GetRunwayIntoWind(PreferLeft)
|
||||||
|
end
|
||||||
|
|
||||||
|
if runway then
|
||||||
|
self:I("Setting active runway for takeoff as "..self:GetRunwayName(runway))
|
||||||
|
else
|
||||||
|
self:E("ERROR: Could not set the runway for takeoff!")
|
||||||
|
end
|
||||||
|
|
||||||
|
self.runwayTakeoff=runway
|
||||||
|
|
||||||
|
return runway
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get the runway where aircraft would be taking of or landing into the direction of the wind.
|
||||||
|
-- NOTE that this requires the wind to be non-zero as set in the mission editor.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @param #boolean PreferLeft If `true`, perfer the left runway. If `false`, prefer the right runway. If `nil` (default), do not care about left or right.
|
||||||
|
-- @return #AIRBASE.Runway Active runway data table.
|
||||||
|
function AIRBASE:GetRunwayIntoWind(PreferLeft)
|
||||||
|
|
||||||
-- Get runway data.
|
-- Get runway data.
|
||||||
local runways=self:GetRunways()
|
local runways=self:GetRunways()
|
||||||
|
|
||||||
-- Return user forced active runway if it was set.
|
|
||||||
if self.activerwyno then
|
|
||||||
return runways[self.activerwyno]
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get wind vector.
|
-- Get wind vector.
|
||||||
local Vwind=self:GetCoordinate():GetWindWithTurbulenceVec3()
|
local Vwind=self:GetCoordinate():GetWindWithTurbulenceVec3()
|
||||||
local norm=UTILS.VecNorm(Vwind)
|
local norm=UTILS.VecNorm(Vwind)
|
||||||
@ -1949,39 +2050,43 @@ function AIRBASE:GetActiveRunway(magvar)
|
|||||||
local dotmin=nil
|
local dotmin=nil
|
||||||
for i,_runway in pairs(runways) do
|
for i,_runway in pairs(runways) do
|
||||||
local runway=_runway --#AIRBASE.Runway
|
local runway=_runway --#AIRBASE.Runway
|
||||||
|
|
||||||
|
if PreferLeft==nil or PreferLeft==runway.isLeft then
|
||||||
|
|
||||||
-- Angle in rad.
|
-- Angle in rad.
|
||||||
local alpha=math.rad(runway.heading)
|
local alpha=math.rad(runway.heading)
|
||||||
|
|
||||||
-- Runway vector.
|
-- Runway vector.
|
||||||
local Vrunway={x=math.cos(alpha), y=0, z=math.sin(alpha)}
|
local Vrunway={x=math.cos(alpha), y=0, z=math.sin(alpha)}
|
||||||
|
|
||||||
-- Dot product: parallel component of the two vectors.
|
-- Dot product: parallel component of the two vectors.
|
||||||
local dot=UTILS.VecDot(Vwind, Vrunway)
|
local dot=UTILS.VecDot(Vwind, Vrunway)
|
||||||
|
|
||||||
-- New min?
|
-- New min?
|
||||||
if dotmin==nil or dot<dotmin then
|
if dotmin==nil or dot<dotmin then
|
||||||
dotmin=dot
|
dotmin=dot
|
||||||
iact=i
|
iact=i
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:E("WARNING: Norm of wind is zero! Cannot determine active runway based on wind direction.")
|
self:E("WARNING: Norm of wind is zero! Cannot determine runway based on wind direction")
|
||||||
end
|
end
|
||||||
|
|
||||||
return runways[iact]
|
return runways[iact]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get name of the runway, e.g. "31L".
|
--- Get name of a given runway, e.g. "31L".
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @param #AIRBASE.Runway Runway The runway. Default is the active runway.
|
-- @param #AIRBASE.Runway Runway The runway. Default is the active runway.
|
||||||
-- @return #AIRBASE.Runway Active runway data table.
|
-- @return #string Name of the runway or "XX" if it could not be found.
|
||||||
function AIRBASE:GetRunwayName(Runway)
|
function AIRBASE:GetRunwayName(Runway)
|
||||||
|
|
||||||
Runway=Runway or self:GetActiveRunway()
|
Runway=Runway or self:GetActiveRunway()
|
||||||
|
|
||||||
local name="Unknown"
|
local name="XX"
|
||||||
if Runway then
|
if Runway then
|
||||||
name=Runway.name
|
name=Runway.name
|
||||||
if Runway.isLeft==true then
|
if Runway.isLeft==true then
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user