mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-18 13:16:03 +00:00
Merge branch 'develop' into FF/Fox2
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
--- **Ops** - (R2.5) - Automatic Terminal Information Service (ATIS).
|
--- **Ops** - (R2.5) - Automatic Terminal Information Service (ATIS).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- **Main Features:**
|
-- **Main Features:**
|
||||||
@@ -28,9 +28,9 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Missions: Example missions will be added later.
|
-- ## Missions: Example missions will be added later.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Sound files: Check out the pinned messages in the Moose discord #ops-atis channel.
|
-- ## Sound files: Check out the pinned messages in the Moose discord #ops-atis channel.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
-- @field #number subduration Duration how long subtitles are displayed in seconds.
|
-- @field #number subduration Duration how long subtitles are displayed in seconds.
|
||||||
-- @field #boolean metric If true, use metric units. If false, use imperial (default).
|
-- @field #boolean metric If true, use metric units. If false, use imperial (default).
|
||||||
-- @field #boolean PmmHg If true, give pressure in millimeters of Mercury. Default is inHg for imperial and hecto Pascal (=mili Bars) for metric units.
|
-- @field #boolean PmmHg If true, give pressure in millimeters of Mercury. Default is inHg for imperial and hecto Pascal (=mili Bars) for metric units.
|
||||||
-- @field #boolean TDegF If true, give temperature in degrees Fahrenheit. Default is in degrees Celsius independent of chosen unit system.
|
-- @field #boolean TDegF If true, give temperature in degrees Fahrenheit. Default is in degrees Celsius independent of chosen unit system.
|
||||||
-- @field #number zuludiff Time difference local vs. zulu in hours.
|
-- @field #number zuludiff Time difference local vs. zulu in hours.
|
||||||
-- @field #number magvar Magnetic declination/variation at the airport in degrees.
|
-- @field #number magvar Magnetic declination/variation at the airport in degrees.
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
@@ -75,108 +75,110 @@
|
|||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- # The ATIS Concept
|
-- # The ATIS Concept
|
||||||
--
|
--
|
||||||
-- Automatic terminal information service, or ATIS, is a continuous broadcast of recorded aeronautical information in busier terminal areas, i.e. airports and their immediate surroundings.
|
-- Automatic terminal information service, or ATIS, is a continuous broadcast of recorded aeronautical information in busier terminal areas, i.e. airports and their immediate surroundings.
|
||||||
-- ATIS broadcasts contain essential information, such as current weather information, active runways, and any other information required by the pilots.
|
-- ATIS broadcasts contain essential information, such as current weather information, active runways, and any other information required by the pilots.
|
||||||
--
|
--
|
||||||
-- # DCS Limitations
|
-- # DCS Limitations
|
||||||
--
|
--
|
||||||
-- Unfortunately, the DCS API only allow to get the temperature, pressure as well as wind direction and speed. Therefore, some other information such as cloud coverage, base and ceiling are not available
|
-- Unfortunately, the DCS API only allow to get the temperature, pressure as well as wind direction and speed. Therefore, some other information such as cloud coverage, base and ceiling are not available
|
||||||
-- when dynamic weather is used.
|
-- when dynamic weather is used.
|
||||||
--
|
--
|
||||||
-- # Scripting
|
-- # Scripting
|
||||||
--
|
--
|
||||||
-- The lua script to create an ATIS at an airport is pretty easy:
|
-- The lua script to create an ATIS at an airport is pretty easy:
|
||||||
--
|
--
|
||||||
-- -- ATIS at Batumi Airport on 143.00 MHz AM.
|
-- -- ATIS at Batumi Airport on 143.00 MHz AM.
|
||||||
-- atisBatumi=ATIS:New("Batumi", 143.00)
|
-- atisBatumi=ATIS:New("Batumi", 143.00)
|
||||||
-- atisBatumi:Start()
|
-- atisBatumi:Start()
|
||||||
--
|
--
|
||||||
-- The @{#ATIS.New}(*airbasename*, *frequency*) creates a new ATIS object. The parameter *airbasename* is the name of the airbase or airport. Note that this has to be spelled exactly as in the DCS mission editor.
|
-- The @{#ATIS.New}(*airbasename*, *frequency*) creates a new ATIS object. The parameter *airbasename* is the name of the airbase or airport. Note that this has to be spelled exactly as in the DCS mission editor.
|
||||||
-- The parameter *frequency* is the frequency the ATIS broadcasts in MHz.
|
-- The parameter *frequency* is the frequency the ATIS broadcasts in MHz.
|
||||||
--
|
--
|
||||||
-- Broadcasting is started via the @{#ATIS.Start}() function. The start can be delayed by useing @{#ATIS.__Start}(*delay*), where *delay* is the delay in seconds.
|
-- Broadcasting is started via the @{#ATIS.Start}() function. The start can be delayed by useing @{#ATIS.__Start}(*delay*), where *delay* is the delay in seconds.
|
||||||
--
|
--
|
||||||
-- ## Subtitles
|
-- ## Subtitles
|
||||||
--
|
--
|
||||||
-- Currently, DCS allows for displaying subtitles of radio transmissions only from airborne units, i.e. airplanes and helicopters. Therefore, if you want to have subtitles, it is necessary to place an
|
-- Currently, DCS allows for displaying subtitles of radio transmissions only from airborne units, i.e. airplanes and helicopters. Therefore, if you want to have subtitles, it is necessary to place an
|
||||||
-- additonal aircraft on the ATIS airport and set it to uncontrolled. This unit can then function as a radio relay to transmit messages with subtitles. These subtitles will only be displayed, if the
|
-- additonal aircraft on the ATIS airport and set it to uncontrolled. This unit can then function as a radio relay to transmit messages with subtitles. These subtitles will only be displayed, if the
|
||||||
-- player has tuned in the correct ATIS frequency.
|
-- player has tuned in the correct ATIS frequency.
|
||||||
--
|
--
|
||||||
-- Radio transmissions via an airborne unit can be set via the @{#ATIS.SetRadioRelayUnitName}(*unitname*) function, where the parameter *unitname* is the name of the unit passed as string, e.g.
|
-- Radio transmissions via an airborne unit can be set via the @{#ATIS.SetRadioRelayUnitName}(*unitname*) function, where the parameter *unitname* is the name of the unit passed as string, e.g.
|
||||||
--
|
--
|
||||||
-- atisBatumi:SetRadioRelayUnitName("Radio Relay Batumi")
|
-- atisBatumi:SetRadioRelayUnitName("Radio Relay Batumi")
|
||||||
--
|
--
|
||||||
-- With a unit set in the mission editor with name "Radio Relay Batumi".
|
-- With a unit set in the mission editor with name "Radio Relay Batumi".
|
||||||
--
|
--
|
||||||
-- By default, subtitles are displayed for 10 seconds. This can be changed using @{#ATIS.SetSubtitleDuration}(*duration*) with *duration* being the duration in seconds.
|
-- By default, subtitles are displayed for 10 seconds. This can be changed using @{#ATIS.SetSubtitleDuration}(*duration*) with *duration* being the duration in seconds.
|
||||||
--
|
--
|
||||||
-- ## Active Runway
|
-- ## Active Runway
|
||||||
--
|
--
|
||||||
-- By default, the currently active runway is determined automatically by analysing the wind direction. However, there are special cases, where this does not yield the correct result.
|
-- By default, the currently active runway is determined automatically by analysing the wind direction. Therefore, you should obviously set the wind speed to be greater zero in your mission.
|
||||||
-- Also, there are airports with more than one runway facing in the same direction (usually denoted left and right). In this case, there is obviously no *unique* result depending on the wind vector.
|
--
|
||||||
--
|
-- Note however, there are a few special cases, where automatic detection does not yield the correct or desired result.
|
||||||
|
-- For example, there are airports with more than one runway facing in the same direction (usually denoted left and right). In this case, there is obviously no *unique* result depending on the wind vector.
|
||||||
|
--
|
||||||
-- If the automatic runway detection fails, the active runway can be specified manually in the script via the @{#ATIS.SetActiveRunway}(*runway*) function.
|
-- If the automatic runway detection fails, the active runway can be specified manually in the script via the @{#ATIS.SetActiveRunway}(*runway*) function.
|
||||||
-- The parameter *runway* is a string which can be used to specify the runway heading and, if applicable, whether the left or right runway is in use.
|
-- The parameter *runway* is a string which can be used to specify the runway heading and, if applicable, whether the left or right runway is in use.
|
||||||
--
|
--
|
||||||
-- For example, setting runway 21L would be
|
-- For example, setting runway 21L would be
|
||||||
--
|
--
|
||||||
-- atisNellis:SetActiveRunway("21L")
|
-- atisNellis:SetActiveRunway("21L")
|
||||||
--
|
--
|
||||||
-- The script will examine the string and search for the characters "L" (left) and "R" (right).
|
-- The script will examine the string and search for the characters "L" (left) and "R" (right).
|
||||||
--
|
--
|
||||||
-- If only left or right should be set and the direction determined by the wind vector, the runway heading can be left out, e.g.
|
-- If only left or right should be set and the direction determined by the wind vector, the runway heading can be left out, e.g.
|
||||||
--
|
--
|
||||||
-- atisAbuDhabi:SetActiveRunway("L")
|
-- atisAbuDhabi:SetActiveRunway("L")
|
||||||
--
|
--
|
||||||
-- The first two digits of the runway are determined by converting the *true* runway heading into its magnetic heading. The magnetic declination (or variation) is assumed to be constant on the given map.
|
-- The first two digits of the runway are determined by converting the *true* runway heading into its magnetic heading. The magnetic declination (or variation) is assumed to be constant on the given map.
|
||||||
-- The magnatic declinatin can also be specified for the specific airport using the @{#ATIS.SetMagneticDeclination}(*magvar*).
|
-- The magnatic declinatin can also be specified for the specific airport using the @{#ATIS.SetMagneticDeclination}(*magvar*).
|
||||||
--
|
--
|
||||||
-- ## Tower Frequencies
|
-- ## Tower Frequencies
|
||||||
--
|
--
|
||||||
-- The tower frequency (or frequencies) can also be included in the ATIS information. However, there is no way to get these automatically. Therefore, it is necessary to manually specify them in the script via the
|
-- The tower frequency (or frequencies) can also be included in the ATIS information. However, there is no way to get these automatically. Therefore, it is necessary to manually specify them in the script via the
|
||||||
-- @{#ATIS.SetTowerFrequencies}(*frequencies*) function. The parameter *frequencies* can be a plain number if only one frequency is necessary or it can be a table of frequencies.
|
-- @{#ATIS.SetTowerFrequencies}(*frequencies*) function. The parameter *frequencies* can be a plain number if only one frequency is necessary or it can be a table of frequencies.
|
||||||
--
|
--
|
||||||
-- ## Unit System
|
-- ## Unit System
|
||||||
--
|
--
|
||||||
-- By default, information is given in imperial units, i.e. wind speed in knots, pressure in inches of mercury, visibility in Nautical miles, etc.
|
-- By default, information is given in imperial units, i.e. wind speed in knots, pressure in inches of mercury, visibility in Nautical miles, etc.
|
||||||
--
|
--
|
||||||
-- If you prefer metric units, you can enable this via the @{#ATIS.SetMetricUnits}() function,
|
-- If you prefer metric units, you can enable this via the @{#ATIS.SetMetricUnits}() function,
|
||||||
--
|
--
|
||||||
-- atisBatumi:SetMetricUnits()
|
-- atisBatumi:SetMetricUnits()
|
||||||
--
|
--
|
||||||
-- With this, wind speed is given in meters per second, pressure in hecto Pascal (mbar), visibility in kilometers etc.
|
-- With this, wind speed is given in meters per second, pressure in hecto Pascal (mbar), visibility in kilometers etc.
|
||||||
--
|
--
|
||||||
-- # Sound Files
|
-- # Sound Files
|
||||||
--
|
--
|
||||||
-- More than 180 individual sound files have been created using a text-to-speech program. All ATIS information is given with en-US accent.
|
-- More than 180 individual sound files have been created using a text-to-speech program. All ATIS information is given with en-US accent.
|
||||||
--
|
--
|
||||||
-- Check out the pinned messages in the Moose discord #ops-atis channel.
|
-- Check out the pinned messages in the Moose discord #ops-atis channel.
|
||||||
--
|
--
|
||||||
-- To include the files, open the mission (.miz) file with, e.g., 7-zip. Then just drag-n-drop the file into the miz.
|
-- To include the files, open the mission (.miz) file with, e.g., 7-zip. Then just drag-n-drop the file into the miz.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- **Note** that the default folder name is *ATIS Soundfiles/*. If you want to change it, you can use the @{#ATIS.SetSoundfilesPath}(*path*), where *path* is the path of the directory. This must end with a slash "/"!
|
-- **Note** that the default folder name is *ATIS Soundfiles/*. If you want to change it, you can use the @{#ATIS.SetSoundfilesPath}(*path*), where *path* is the path of the directory. This must end with a slash "/"!
|
||||||
--
|
--
|
||||||
-- # Examples
|
-- # Examples
|
||||||
--
|
--
|
||||||
-- ## Caucasus: Batumi
|
-- ## Caucasus: Batumi
|
||||||
--
|
--
|
||||||
-- -- ATIS Batumi Airport on 143.00 MHz AM.
|
-- -- ATIS Batumi Airport on 143.00 MHz AM.
|
||||||
-- atisBatumi=ATIS:New(AIRBASE.Caucasus.Batumi, 143.00)
|
-- atisBatumi=ATIS:New(AIRBASE.Caucasus.Batumi, 143.00)
|
||||||
-- atisBatumi:SetRadioRelayUnitName("Radio Relay Batumi")
|
-- atisBatumi:SetRadioRelayUnitName("Radio Relay Batumi")
|
||||||
-- atisBatumi:Start()
|
-- atisBatumi:Start()
|
||||||
--
|
--
|
||||||
-- ## Nevada: Nellis AFB
|
-- ## Nevada: Nellis AFB
|
||||||
--
|
--
|
||||||
-- -- ATIS Nellis AFB on 270.100 MHz AM.
|
-- -- ATIS Nellis AFB on 270.100 MHz AM.
|
||||||
-- atisNellis=ATIS:New(AIRBASE.Nevada.Nellis_AFB, 270.100)
|
-- atisNellis=ATIS:New(AIRBASE.Nevada.Nellis_AFB, 270.100)
|
||||||
-- atisNellis:SetRadioRelayUnitName("Radio Relay Nellis")
|
-- atisNellis:SetRadioRelayUnitName("Radio Relay Nellis")
|
||||||
-- atisNellis:SetActiveRunway("21L")
|
-- atisNellis:SetActiveRunway("21L")
|
||||||
-- atisNellis:SetTowerFrequencies({327.000, 132.550})
|
-- atisNellis:SetTowerFrequencies({327.000, 132.550})
|
||||||
-- atisNellis:Start()
|
-- atisNellis:Start()
|
||||||
--
|
--
|
||||||
-- ## Persian Gulf: Abu Dhabi International Airport
|
-- ## Persian Gulf: Abu Dhabi International Airport
|
||||||
--
|
--
|
||||||
-- atisAbuDhabi=ATIS:New(AIRBASE.PersianGulf.Abu_Dhabi_International_Airport, 125.1)
|
-- atisAbuDhabi=ATIS:New(AIRBASE.PersianGulf.Abu_Dhabi_International_Airport, 125.1)
|
||||||
@@ -184,7 +186,7 @@
|
|||||||
-- atisAbuDhabi:SetMetricUnits()
|
-- atisAbuDhabi:SetMetricUnits()
|
||||||
-- atisAbuDhabi:SetActiveRunway("L")
|
-- atisAbuDhabi:SetActiveRunway("L")
|
||||||
-- atisAbuDhabi:Start()
|
-- atisAbuDhabi:Start()
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- @field #ATIS
|
-- @field #ATIS
|
||||||
ATIS = {
|
ATIS = {
|
||||||
@@ -271,24 +273,24 @@ function ATIS:New(airbasename, frequency, modulation)
|
|||||||
|
|
||||||
-- Inherit everything from WAREHOUSE class.
|
-- Inherit everything from WAREHOUSE 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))
|
||||||
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
|
||||||
|
|
||||||
-- Set some string id for output to DCS.log file.
|
-- Set some string id for output to DCS.log file.
|
||||||
self.lid=string.format("ATIS %s | ", self.airbasename)
|
self.lid=string.format("ATIS %s | ", self.airbasename)
|
||||||
|
|
||||||
-- Defaults:
|
-- Defaults:
|
||||||
self:SetSoundfilesPath()
|
self:SetSoundfilesPath()
|
||||||
self:SetSubtitleDuration()
|
self:SetSubtitleDuration()
|
||||||
@@ -302,7 +304,7 @@ function ATIS:New(airbasename, frequency, modulation)
|
|||||||
self:AddTransition("*", "Status", "*") -- Update status.
|
self:AddTransition("*", "Status", "*") -- Update status.
|
||||||
self:AddTransition("*", "Broadcast", "*") -- Broadcast ATIS message.
|
self:AddTransition("*", "Broadcast", "*") -- Broadcast ATIS message.
|
||||||
self:AddTransition("*", "CheckQueue", "*") -- Check if radio queue is empty.
|
self:AddTransition("*", "CheckQueue", "*") -- Check if radio queue is empty.
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
--- Pseudo Functions ---
|
--- Pseudo Functions ---
|
||||||
------------------------
|
------------------------
|
||||||
@@ -367,7 +369,7 @@ end
|
|||||||
function ATIS:SetTowerFrequencies(freqs)
|
function ATIS:SetTowerFrequencies(freqs)
|
||||||
if type(freqs)=="table" then
|
if type(freqs)=="table" then
|
||||||
-- nothing to do
|
-- nothing to do
|
||||||
else
|
else
|
||||||
freqs={freqs}
|
freqs={freqs}
|
||||||
end
|
end
|
||||||
self.towerfrequency=freqs
|
self.towerfrequency=freqs
|
||||||
@@ -410,7 +412,7 @@ function ATIS:SetImperialUnits()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Set pressure unit to millimeters of mercury (mmHg).
|
--- Set pressure unit to millimeters of mercury (mmHg).
|
||||||
-- Default is inHg for imperial and hPa (=mBar) for metric units.
|
-- Default is inHg for imperial and hPa (=mBar) for metric units.
|
||||||
-- @param #ATIS self
|
-- @param #ATIS self
|
||||||
-- @return #ATIS self
|
-- @return #ATIS self
|
||||||
function ATIS:SetPressureMillimetersMercury()
|
function ATIS:SetPressureMillimetersMercury()
|
||||||
@@ -427,14 +429,14 @@ function ATIS:SetTemperatureFahrenheit()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Set magnetic declination/variation at the airport.
|
--- Set magnetic declination/variation at the airport.
|
||||||
--
|
--
|
||||||
-- Default is per map:
|
-- Default is per map:
|
||||||
--
|
--
|
||||||
-- * Caucasus +6 (East), year ~ 2011
|
-- * Caucasus +6 (East), year ~ 2011
|
||||||
-- * NTTR +12 (East), year ~ 2011
|
-- * NTTR +12 (East), year ~ 2011
|
||||||
-- * Normandy -10 (West), year ~ 1944
|
-- * Normandy -10 (West), year ~ 1944
|
||||||
-- * Persian Gulf +2 (East), year ~ 2011
|
-- * Persian Gulf +2 (East), year ~ 2011
|
||||||
--
|
--
|
||||||
-- @param #ATIS self
|
-- @param #ATIS self
|
||||||
-- @param #number magvar Magnetic variation in degrees.
|
-- @param #number magvar Magnetic variation in degrees.
|
||||||
-- @return #ATIS self
|
-- @return #ATIS self
|
||||||
@@ -445,12 +447,12 @@ end
|
|||||||
|
|
||||||
--- Set time local difference with respect to Zulu time.
|
--- Set time local difference with respect to Zulu time.
|
||||||
-- Default is per map:
|
-- Default is per map:
|
||||||
--
|
--
|
||||||
-- * Caucasus +4
|
-- * Caucasus +4
|
||||||
-- * Nevada -7
|
-- * Nevada -7
|
||||||
-- * Normandy +1
|
-- * Normandy +1
|
||||||
-- * Persian Gulf +4
|
-- * Persian Gulf +4
|
||||||
--
|
--
|
||||||
-- @param #ATIS self
|
-- @param #ATIS self
|
||||||
-- @param #number delta Time difference in hours.
|
-- @param #number delta Time difference in hours.
|
||||||
-- @return #ATIS self
|
-- @return #ATIS self
|
||||||
@@ -469,16 +471,16 @@ function ATIS:onafterStart(From, Event, To)
|
|||||||
|
|
||||||
-- Info.
|
-- Info.
|
||||||
self:I(self.lid..string.format("Starting ATIS v%s for airbase %s on %.3f MHz Modulation=%d", ATIS.version, self.airbasename, self.frequency, self.modulation))
|
self:I(self.lid..string.format("Starting ATIS v%s for airbase %s on %.3f MHz Modulation=%d", ATIS.version, self.airbasename, self.frequency, self.modulation))
|
||||||
|
|
||||||
-- Start radio queue.
|
-- Start radio queue.
|
||||||
self.radioqueue=RADIOQUEUE:New(self.frequency, self.modulation)
|
self.radioqueue=RADIOQUEUE:New(self.frequency, self.modulation)
|
||||||
|
|
||||||
-- Send coordinate is airbase coord.
|
-- Send coordinate is airbase coord.
|
||||||
self.radioqueue:SetSenderCoordinate(self.airbase:GetCoordinate())
|
self.radioqueue:SetSenderCoordinate(self.airbase:GetCoordinate())
|
||||||
|
|
||||||
-- Set relay unit if we have one.
|
-- Set relay unit if we have one.
|
||||||
self.radioqueue:SetSenderUnitName(self.relayunitname)
|
self.radioqueue:SetSenderUnitName(self.relayunitname)
|
||||||
|
|
||||||
-- Init numbers.
|
-- Init numbers.
|
||||||
self.radioqueue:SetDigit(0, "N-0.ogg", 0.55, self.soundpath)
|
self.radioqueue:SetDigit(0, "N-0.ogg", 0.55, self.soundpath)
|
||||||
self.radioqueue:SetDigit(1, "N-1.ogg", 0.40, self.soundpath)
|
self.radioqueue:SetDigit(1, "N-1.ogg", 0.40, self.soundpath)
|
||||||
@@ -490,7 +492,7 @@ function ATIS:onafterStart(From, Event, To)
|
|||||||
self.radioqueue:SetDigit(7, "N-7.ogg", 0.42, self.soundpath)
|
self.radioqueue:SetDigit(7, "N-7.ogg", 0.42, self.soundpath)
|
||||||
self.radioqueue:SetDigit(8, "N-8.ogg", 0.37, self.soundpath)
|
self.radioqueue:SetDigit(8, "N-8.ogg", 0.37, self.soundpath)
|
||||||
self.radioqueue:SetDigit(9, "N-9.ogg", 0.38, self.soundpath)
|
self.radioqueue:SetDigit(9, "N-9.ogg", 0.38, self.soundpath)
|
||||||
|
|
||||||
-- Start radio queue.
|
-- Start radio queue.
|
||||||
self.radioqueue:Start(1, 0.1)
|
self.radioqueue:Start(1, 0.1)
|
||||||
|
|
||||||
@@ -505,11 +507,11 @@ function ATIS:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
-- Get FSM state.
|
-- Get FSM state.
|
||||||
local fsmstate=self:GetState()
|
local fsmstate=self:GetState()
|
||||||
|
|
||||||
-- Info text.
|
-- Info text.
|
||||||
local text=string.format("State %s", fsmstate)
|
local text=string.format("State %s", fsmstate)
|
||||||
self:I(self.lid..text)
|
self:I(self.lid..text)
|
||||||
|
|
||||||
self:__Status(30)
|
self:__Status(30)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -527,7 +529,7 @@ function ATIS:onafterCheckQueue(From, Event, To)
|
|||||||
else
|
else
|
||||||
self:T2(self.lid..string.format("Radio queue %d transmissions queued.", #self.radioqueue.queue))
|
self:T2(self.lid..string.format("Radio queue %d transmissions queued.", #self.radioqueue.queue))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check back in 5 seconds.
|
-- Check back in 5 seconds.
|
||||||
self:__CheckQueue(5)
|
self:__CheckQueue(5)
|
||||||
end
|
end
|
||||||
@@ -538,29 +540,29 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
|
|
||||||
-- Get current coordinate.
|
-- Get current coordinate.
|
||||||
local coord=self.airbase:GetCoordinate()
|
local coord=self.airbase:GetCoordinate()
|
||||||
|
|
||||||
-- Get elevation.
|
-- Get elevation.
|
||||||
local height=coord:GetLandHeight()+10
|
local height=coord:GetLandHeight()+10
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
--- Pressure ---
|
--- Pressure ---
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
-- Pressure in hPa.
|
-- Pressure in hPa.
|
||||||
local qfe=coord:GetPressure(height)
|
local qfe=coord:GetPressure(height)
|
||||||
local qnh=coord:GetPressure(0)
|
local qnh=coord:GetPressure(0)
|
||||||
|
|
||||||
-- Convert to inHg.
|
-- Convert to inHg.
|
||||||
if self.PmmHg then
|
if self.PmmHg then
|
||||||
qfe=UTILS.hPa2mmHg(qfe)
|
qfe=UTILS.hPa2mmHg(qfe)
|
||||||
qnh=UTILS.hPa2mmHg(qnh)
|
qnh=UTILS.hPa2mmHg(qnh)
|
||||||
else
|
else
|
||||||
if not self.metric then
|
if not self.metric then
|
||||||
qfe=UTILS.hPa2inHg(qfe)
|
qfe=UTILS.hPa2inHg(qfe)
|
||||||
qnh=UTILS.hPa2inHg(qnh)
|
qnh=UTILS.hPa2inHg(qnh)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local QFE=UTILS.Split(string.format("%.2f", qfe), ".")
|
local QFE=UTILS.Split(string.format("%.2f", qfe), ".")
|
||||||
local QNH=UTILS.Split(string.format("%.2f", qnh), ".")
|
local QNH=UTILS.Split(string.format("%.2f", qnh), ".")
|
||||||
|
|
||||||
@@ -573,18 +575,18 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
QNH=UTILS.Split(string.format("%.1f", qnh), ".")
|
QNH=UTILS.Split(string.format("%.1f", qnh), ".")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------
|
--------------
|
||||||
--- Runway ---
|
--- Runway ---
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
-- Get runway based on wind direction.
|
-- Get runway based on wind direction.
|
||||||
local runway=self.airbase:GetActiveRunway(self.magvar).idx
|
local runway=self.airbase:GetActiveRunway(self.magvar).idx
|
||||||
|
|
||||||
-- Left or right in case there are two runways with the same heading.
|
-- Left or right in case there are two runways with the same heading.
|
||||||
local rleft=false
|
local rleft=false
|
||||||
local rright=false
|
local rright=false
|
||||||
|
|
||||||
-- Check if user explicitly specified a runway.
|
-- Check if user explicitly specified a runway.
|
||||||
if self.activerunway then
|
if self.activerunway then
|
||||||
local runwayno=self.activerunway:gsub("%D+", "")
|
local runwayno=self.activerunway:gsub("%D+", "")
|
||||||
@@ -594,27 +596,27 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
rleft=self.activerunway:lower():find("l")
|
rleft=self.activerunway:lower():find("l")
|
||||||
rright=self.activerunway:lower():find("r")
|
rright=self.activerunway:lower():find("r")
|
||||||
end
|
end
|
||||||
|
|
||||||
------------
|
------------
|
||||||
--- Wind ---
|
--- Wind ---
|
||||||
------------
|
------------
|
||||||
|
|
||||||
-- Get wind direction and speed in m/s.
|
-- Get wind direction and speed in m/s.
|
||||||
local windFrom, windSpeed=coord:GetWind(height)
|
local windFrom, windSpeed=coord:GetWind(height)
|
||||||
|
|
||||||
|
|
||||||
local WINDFROM=string.format("%03d", windFrom)
|
local WINDFROM=string.format("%03d", windFrom)
|
||||||
local WINDSPEED=string.format("%d", UTILS.MpsToKnots(windSpeed))
|
local WINDSPEED=string.format("%d", UTILS.MpsToKnots(windSpeed))
|
||||||
|
|
||||||
if self.metric then
|
if self.metric then
|
||||||
WINDSPEED=string.format("%d", windSpeed)
|
WINDSPEED=string.format("%d", windSpeed)
|
||||||
end
|
end
|
||||||
|
|
||||||
------------
|
------------
|
||||||
--- Time ---
|
--- Time ---
|
||||||
------------
|
------------
|
||||||
local time=timer.getAbsTime()
|
local time=timer.getAbsTime()
|
||||||
|
|
||||||
-- Conversion to Zulu time.
|
-- Conversion to Zulu time.
|
||||||
if self.zuludiff then
|
if self.zuludiff then
|
||||||
-- User specified.
|
-- User specified.
|
||||||
@@ -630,43 +632,43 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
time=time-1*60*60 -- Calais UTC+1 hour
|
time=time-1*60*60 -- Calais UTC+1 hour
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local clock=UTILS.SecondsToClock(time)
|
local clock=UTILS.SecondsToClock(time)
|
||||||
local zulu=UTILS.Split(clock, ":")
|
local zulu=UTILS.Split(clock, ":")
|
||||||
local ZULU=string.format("%s%s", zulu[1], zulu[2])
|
local ZULU=string.format("%s%s", zulu[1], zulu[2])
|
||||||
|
|
||||||
|
|
||||||
-- NATO time stamp. 0=Alfa, 1=Bravo, 2=Charlie, etc.
|
-- NATO time stamp. 0=Alfa, 1=Bravo, 2=Charlie, etc.
|
||||||
local NATO=ATIS.Alphabet[tonumber(zulu[1])+1]
|
local NATO=ATIS.Alphabet[tonumber(zulu[1])+1]
|
||||||
|
|
||||||
-- Debug.
|
-- Debug.
|
||||||
self:T3({nato=NATO})
|
self:T3({nato=NATO})
|
||||||
|
|
||||||
-------------------
|
-------------------
|
||||||
--- Temperature ---
|
--- Temperature ---
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
-- Temperature in °C.
|
-- Temperature in �C.
|
||||||
local temperature=coord:GetTemperature(height)
|
local temperature=coord:GetTemperature(height)
|
||||||
|
|
||||||
local TEMPERATURE=string.format("%d", temperature)
|
local TEMPERATURE=string.format("%d", temperature)
|
||||||
|
|
||||||
if self.TDegF then
|
if self.TDegF then
|
||||||
TEMPERATURE=string.format("%d", UTILS.CelciusToFarenheit(temperature))
|
TEMPERATURE=string.format("%d", UTILS.CelciusToFarenheit(temperature))
|
||||||
end
|
end
|
||||||
|
|
||||||
---------------
|
---------------
|
||||||
--- Weather ---
|
--- Weather ---
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
-- Get mission weather info. Most of this is static.
|
-- Get mission weather info. Most of this is static.
|
||||||
local clouds, visibility, turbulence, fog, dust, static=self:GetMissionWeather()
|
local clouds, visibility, turbulence, fog, dust, static=self:GetMissionWeather()
|
||||||
|
|
||||||
-- Check that fog is actually "thick" enough to reach the airport. If an airport is in the mountains, fog might not affect it as it is measured from sea level.
|
-- Check that fog is actually "thick" enough to reach the airport. If an airport is in the mountains, fog might not affect it as it is measured from sea level.
|
||||||
if fog and fog.thickness<height then
|
if fog and fog.thickness<height then
|
||||||
fog=nil
|
fog=nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Dust only up to 1500 ft = 457 m ASL.
|
-- Dust only up to 1500 ft = 457 m ASL.
|
||||||
if dust and height>UTILS.FeetToMeters(1500) then
|
if dust and height>UTILS.FeetToMeters(1500) then
|
||||||
dust=nil
|
dust=nil
|
||||||
@@ -675,63 +677,63 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
------------------
|
------------------
|
||||||
--- Visibility ---
|
--- Visibility ---
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
-- Get min visibility.
|
-- Get min visibility.
|
||||||
local visibilitymin=visibility
|
local visibilitymin=visibility
|
||||||
|
|
||||||
if fog then
|
if fog then
|
||||||
if fog.visibility<visibilitymin then
|
if fog.visibility<visibilitymin then
|
||||||
visibilitymin=fog.visibility
|
visibilitymin=fog.visibility
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if dust then
|
if dust then
|
||||||
if dust<visibilitymin then
|
if dust<visibilitymin then
|
||||||
visibilitymin=dust
|
visibilitymin=dust
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Visibility in NM.
|
-- Visibility in NM.
|
||||||
local VISIBILITY=string.format("%d", UTILS.Round(UTILS.MetersToNM(visibilitymin)))
|
local VISIBILITY=string.format("%d", UTILS.Round(UTILS.MetersToNM(visibilitymin)))
|
||||||
|
|
||||||
-- Visibility in km.
|
-- Visibility in km.
|
||||||
if self.metric then
|
if self.metric then
|
||||||
VISIBILITY=string.format("%d", UTILS.Round(visibilitymin/1000))
|
VISIBILITY=string.format("%d", UTILS.Round(visibilitymin/1000))
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------
|
--------------
|
||||||
--- Clouds ---
|
--- Clouds ---
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
local cloudbase=clouds.base
|
local cloudbase=clouds.base
|
||||||
local cloudceil=clouds.base+clouds.thickness
|
local cloudceil=clouds.base+clouds.thickness
|
||||||
local clouddens=clouds.density
|
local clouddens=clouds.density
|
||||||
|
|
||||||
-- Precepitation: 0=None, 1=Rain, 2=Thunderstorm.
|
-- Precepitation: 0=None, 1=Rain, 2=Thunderstorm.
|
||||||
local precepitation=tonumber(clouds.iprecptns)
|
local precepitation=tonumber(clouds.iprecptns)
|
||||||
|
|
||||||
local CLOUDBASE=string.format("%d", UTILS.MetersToFeet(cloudbase))
|
local CLOUDBASE=string.format("%d", UTILS.MetersToFeet(cloudbase))
|
||||||
local CLOUDCEIL=string.format("%d", UTILS.MetersToFeet(cloudceil))
|
local CLOUDCEIL=string.format("%d", UTILS.MetersToFeet(cloudceil))
|
||||||
|
|
||||||
if self.metric then
|
if self.metric then
|
||||||
CLOUDBASE=string.format("%d", cloudbase)
|
CLOUDBASE=string.format("%d", cloudbase)
|
||||||
CLOUDCEIL=string.format("%d", cloudceil)
|
CLOUDCEIL=string.format("%d", cloudceil)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Cloud base/ceiling in thousands and hundrets of ft/meters.
|
-- Cloud base/ceiling in thousands and hundrets of ft/meters.
|
||||||
local CLOUDBASE1000, CLOUDBASE0100=self:_GetThousandsAndHundreds(UTILS.MetersToFeet(cloudbase))
|
local CLOUDBASE1000, CLOUDBASE0100=self:_GetThousandsAndHundreds(UTILS.MetersToFeet(cloudbase))
|
||||||
local CLOUDCEIL1000, CLOUDCEIL0100=self:_GetThousandsAndHundreds(UTILS.MetersToFeet(cloudceil))
|
local CLOUDCEIL1000, CLOUDCEIL0100=self:_GetThousandsAndHundreds(UTILS.MetersToFeet(cloudceil))
|
||||||
|
|
||||||
if self.metric then
|
if self.metric then
|
||||||
CLOUDBASE1000, CLOUDBASE0100=self:_GetThousandsAndHundreds(cloudbase)
|
CLOUDBASE1000, CLOUDBASE0100=self:_GetThousandsAndHundreds(cloudbase)
|
||||||
CLOUDCEIL1000, CLOUDCEIL0100=self:_GetThousandsAndHundreds(cloudceil)
|
CLOUDCEIL1000, CLOUDCEIL0100=self:_GetThousandsAndHundreds(cloudceil)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- No cloud info for dynamic weather.
|
-- No cloud info for dynamic weather.
|
||||||
local CLOUDSogg="CloudsNotAvailable.ogg"
|
local CLOUDSogg="CloudsNotAvailable.ogg"
|
||||||
local CLOUDSsub="Cloud coverage information not available"
|
local CLOUDSsub="Cloud coverage information not available"
|
||||||
local CLOUDSdur=2.40
|
local CLOUDSdur=2.40
|
||||||
|
|
||||||
-- Only valid for static weather.
|
-- Only valid for static weather.
|
||||||
if static then
|
if static then
|
||||||
if clouddens>=9 then
|
if clouddens>=9 then
|
||||||
@@ -763,31 +765,31 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
CLOUDSdur=1.00
|
CLOUDSdur=1.00
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------
|
--------------------
|
||||||
--- Transmission ---
|
--- Transmission ---
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
local subduration=self.subduration
|
local subduration=self.subduration
|
||||||
local subtitle=""
|
local subtitle=""
|
||||||
|
|
||||||
--Airbase name
|
--Airbase name
|
||||||
subtitle=string.format("%s", self.airbasename)
|
subtitle=string.format("%s", self.airbasename)
|
||||||
if self.airbasename:find("AFB")==nil and self.airbasename:find("Airport")==nil and self.airbasename:find("Airstrip")==nil and self.airbasename:find("airfield")==nil and self.airbasename:find("AB")==nil then
|
if self.airbasename:find("AFB")==nil and self.airbasename:find("Airport")==nil and self.airbasename:find("Airstrip")==nil and self.airbasename:find("airfield")==nil and self.airbasename:find("AB")==nil then
|
||||||
subtitle=subtitle.." Airport"
|
subtitle=subtitle.." Airport"
|
||||||
end
|
end
|
||||||
self.radioqueue:NewTransmission(string.format("%s/%s.ogg", self.theatre, self.airbasename), 3.0, self.soundpath, nil, nil, subtitle, subduration)
|
self.radioqueue:NewTransmission(string.format("%s/%s.ogg", self.theatre, self.airbasename), 3.0, self.soundpath, nil, nil, subtitle, subduration)
|
||||||
|
|
||||||
-- Information tag
|
-- Information tag
|
||||||
subtitle=string.format("Information %s", NATO)
|
subtitle=string.format("Information %s", NATO)
|
||||||
self.radioqueue:NewTransmission("Information.ogg", 0.85, self.soundpath, nil, 0.5, subtitle, subduration)
|
self.radioqueue:NewTransmission("Information.ogg", 0.85, self.soundpath, nil, 0.5, subtitle, subduration)
|
||||||
self.radioqueue:NewTransmission(string.format("NATO Alphabet/%s.ogg", NATO), 0.75, self.soundpath)
|
self.radioqueue:NewTransmission(string.format("NATO Alphabet/%s.ogg", NATO), 0.75, self.soundpath)
|
||||||
|
|
||||||
-- Zulu Time
|
-- Zulu Time
|
||||||
subtitle=string.format("%s Zulu Time", ZULU)
|
subtitle=string.format("%s Zulu Time", ZULU)
|
||||||
self.radioqueue:Number2Transmission(ZULU, nil, 0.5)
|
self.radioqueue:Number2Transmission(ZULU, nil, 0.5)
|
||||||
self.radioqueue:NewTransmission("TimeZulu.ogg", 0.89, self.soundpath, nil, 0.2, subtitle, subduration)
|
self.radioqueue:NewTransmission("TimeZulu.ogg", 0.89, self.soundpath, nil, 0.2, subtitle, subduration)
|
||||||
|
|
||||||
-- Visibility
|
-- Visibility
|
||||||
if self.metric then
|
if self.metric then
|
||||||
subtitle=string.format("Visibility %s km", VISIBILITY)
|
subtitle=string.format("Visibility %s km", VISIBILITY)
|
||||||
@@ -799,9 +801,9 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
if self.metric then
|
if self.metric then
|
||||||
self.radioqueue:NewTransmission("Kilometers.ogg", 0.78, self.soundpath, nil, 0.2)
|
self.radioqueue:NewTransmission("Kilometers.ogg", 0.78, self.soundpath, nil, 0.2)
|
||||||
else
|
else
|
||||||
self.radioqueue:NewTransmission("NauticalMiles.ogg", 1.05, self.soundpath, nil, 0.2)
|
self.radioqueue:NewTransmission("NauticalMiles.ogg", 1.05, self.soundpath, nil, 0.2)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Cloud base
|
-- Cloud base
|
||||||
self.radioqueue:NewTransmission(CLOUDSogg, CLOUDSdur, self.soundpath, nil, 1.0, CLOUDSsub, subduration)
|
self.radioqueue:NewTransmission(CLOUDSogg, CLOUDSdur, self.soundpath, nil, 1.0, CLOUDSsub, subduration)
|
||||||
if CLOUDBASE and static then
|
if CLOUDBASE and static then
|
||||||
@@ -815,7 +817,7 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
if tonumber(CLOUDBASE1000)>0 then
|
if tonumber(CLOUDBASE1000)>0 then
|
||||||
self.radioqueue:Number2Transmission(CLOUDBASE1000)
|
self.radioqueue:Number2Transmission(CLOUDBASE1000)
|
||||||
self.radioqueue:NewTransmission("Thousand.ogg", 0.55, self.soundpath, nil, 0.1)
|
self.radioqueue:NewTransmission("Thousand.ogg", 0.55, self.soundpath, nil, 0.1)
|
||||||
end
|
end
|
||||||
if tonumber(CLOUDBASE0100)>0 then
|
if tonumber(CLOUDBASE0100)>0 then
|
||||||
self.radioqueue:Number2Transmission(CLOUDBASE0100)
|
self.radioqueue:Number2Transmission(CLOUDBASE0100)
|
||||||
self.radioqueue:NewTransmission("Hundred.ogg", 0.47, self.soundpath, nil, 0.1)
|
self.radioqueue:NewTransmission("Hundred.ogg", 0.47, self.soundpath, nil, 0.1)
|
||||||
@@ -825,7 +827,7 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
if tonumber(CLOUDCEIL1000)>0 then
|
if tonumber(CLOUDCEIL1000)>0 then
|
||||||
self.radioqueue:Number2Transmission(CLOUDCEIL1000)
|
self.radioqueue:Number2Transmission(CLOUDCEIL1000)
|
||||||
self.radioqueue:NewTransmission("Thousand.ogg", 0.55, self.soundpath, nil, 0.1)
|
self.radioqueue:NewTransmission("Thousand.ogg", 0.55, self.soundpath, nil, 0.1)
|
||||||
end
|
end
|
||||||
if tonumber(CLOUDCEIL0100)>0 then
|
if tonumber(CLOUDCEIL0100)>0 then
|
||||||
self.radioqueue:Number2Transmission(CLOUDCEIL0100)
|
self.radioqueue:Number2Transmission(CLOUDCEIL0100)
|
||||||
self.radioqueue:NewTransmission("Hundred.ogg", 0.47, self.soundpath, nil, 0.1)
|
self.radioqueue:NewTransmission("Hundred.ogg", 0.47, self.soundpath, nil, 0.1)
|
||||||
@@ -836,7 +838,7 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
self.radioqueue:NewTransmission("Feet.ogg", 0.45, self.soundpath, nil, 0.1)
|
self.radioqueue:NewTransmission("Feet.ogg", 0.45, self.soundpath, nil, 0.1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Weather phenomena
|
-- Weather phenomena
|
||||||
local wp=false
|
local wp=false
|
||||||
local wpsub=""
|
local wpsub=""
|
||||||
@@ -853,16 +855,16 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
if fog then
|
if fog then
|
||||||
if wp then
|
if wp then
|
||||||
wpsub=wpsub..","
|
wpsub=wpsub..","
|
||||||
end
|
end
|
||||||
wpsub=wpsub.." fog"
|
wpsub=wpsub.." fog"
|
||||||
wp=true
|
wp=true
|
||||||
end
|
end
|
||||||
if dust then
|
if dust then
|
||||||
if wp then
|
if wp then
|
||||||
wpsub=wpsub..","
|
wpsub=wpsub..","
|
||||||
end
|
end
|
||||||
wpsub=wpsub.." dust"
|
wpsub=wpsub.." dust"
|
||||||
wp=true
|
wp=true
|
||||||
end
|
end
|
||||||
-- Actual output
|
-- Actual output
|
||||||
if wp then
|
if wp then
|
||||||
@@ -876,14 +878,14 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
self.radioqueue:NewTransmission("Fog.ogg", 0.81, self.soundpath, nil, 0.5)
|
self.radioqueue:NewTransmission("Fog.ogg", 0.81, self.soundpath, nil, 0.5)
|
||||||
end
|
end
|
||||||
if dust then
|
if dust then
|
||||||
self.radioqueue:NewTransmission("Dust.ogg", 0.81, self.soundpath, nil, 0.5)
|
self.radioqueue:NewTransmission("Dust.ogg", 0.81, self.soundpath, nil, 0.5)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Altimeter QNH/QFE.
|
-- Altimeter QNH/QFE.
|
||||||
if self.PmmHg then
|
if self.PmmHg then
|
||||||
subtitle=string.format("Altimeter QNH %s.%s, QFE %s.%s mmHg", QNH[1], QNH[2], QFE[1], QFE[2])
|
subtitle=string.format("Altimeter QNH %s.%s, QFE %s.%s mmHg", QNH[1], QNH[2], QFE[1], QFE[2])
|
||||||
else
|
else
|
||||||
if self.metric then
|
if self.metric then
|
||||||
subtitle=string.format("Altimeter QNH %s.%s, QFE %s.%s hPa", QNH[1], QNH[2], QFE[1], QFE[2])
|
subtitle=string.format("Altimeter QNH %s.%s, QFE %s.%s hPa", QNH[1], QNH[2], QFE[1], QFE[2])
|
||||||
else
|
else
|
||||||
@@ -908,7 +910,7 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
self.radioqueue:NewTransmission("InchesOfMercury.ogg", 1.16, self.soundpath, nil, 0.1)
|
self.radioqueue:NewTransmission("InchesOfMercury.ogg", 1.16, self.soundpath, nil, 0.1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Temperature
|
-- Temperature
|
||||||
if self.TDegF then
|
if self.TDegF then
|
||||||
subtitle=string.format("Temperature %s °F", TEMPERATURE)
|
subtitle=string.format("Temperature %s °F", TEMPERATURE)
|
||||||
@@ -922,7 +924,7 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
else
|
else
|
||||||
self.radioqueue:NewTransmission("DegreesCelsius.ogg", 1.28, self.soundpath, nil, 0.2)
|
self.radioqueue:NewTransmission("DegreesCelsius.ogg", 1.28, self.soundpath, nil, 0.2)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Wind
|
-- Wind
|
||||||
if self.metric then
|
if self.metric then
|
||||||
subtitle=string.format("Wind from %s at %s m/s", WINDFROM, WINDSPEED)
|
subtitle=string.format("Wind from %s at %s m/s", WINDFROM, WINDSPEED)
|
||||||
@@ -944,7 +946,7 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
if turbulence>0 then
|
if turbulence>0 then
|
||||||
self.radioqueue:NewTransmission("Gusting.ogg", 0.55, self.soundpath, nil, 0.2)
|
self.radioqueue:NewTransmission("Gusting.ogg", 0.55, self.soundpath, nil, 0.2)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Active runway.
|
-- Active runway.
|
||||||
local subtitle=string.format("Active runway %s", runway)
|
local subtitle=string.format("Active runway %s", runway)
|
||||||
if rleft then
|
if rleft then
|
||||||
@@ -959,7 +961,7 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
elseif rright then
|
elseif rright then
|
||||||
self.radioqueue:NewTransmission("Right.ogg", 0.43, self.soundpath, nil, 0.2)
|
self.radioqueue:NewTransmission("Right.ogg", 0.43, self.soundpath, nil, 0.2)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Tower frequency.
|
-- Tower frequency.
|
||||||
if self.towerfrequency then
|
if self.towerfrequency then
|
||||||
local freqs=""
|
local freqs=""
|
||||||
@@ -972,14 +974,14 @@ function ATIS:onafterBroadcast(From, Event, To)
|
|||||||
self.radioqueue:NewTransmission("TowerFrequency.ogg", 1.19, self.soundpath, nil, 1.0, string.format("Tower frequency %s", freqs), subduration)
|
self.radioqueue:NewTransmission("TowerFrequency.ogg", 1.19, self.soundpath, nil, 1.0, string.format("Tower frequency %s", freqs), subduration)
|
||||||
for _,freq in pairs(self.towerfrequency) do
|
for _,freq in pairs(self.towerfrequency) do
|
||||||
local f=string.format("%.3f", freq)
|
local f=string.format("%.3f", freq)
|
||||||
f=UTILS.Split(f, ".")
|
f=UTILS.Split(f, ".")
|
||||||
self.radioqueue:Number2Transmission(f[1], nil, 0.5)
|
self.radioqueue:Number2Transmission(f[1], nil, 0.5)
|
||||||
self.radioqueue:NewTransmission("Decimal.ogg", 0.58, self.soundpath, nil, 0.2)
|
self.radioqueue:NewTransmission("Decimal.ogg", 0.58, self.soundpath, nil, 0.2)
|
||||||
self.radioqueue:Number2Transmission(f[2])
|
self.radioqueue:Number2Transmission(f[2])
|
||||||
self.radioqueue:NewTransmission("MegaHertz.ogg", 0.86, self.soundpath, nil, 0.2)
|
self.radioqueue:NewTransmission("MegaHertz.ogg", 0.86, self.soundpath, nil, 0.2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -990,7 +992,7 @@ end
|
|||||||
-- @param #ATIS self
|
-- @param #ATIS self
|
||||||
-- @return #table Clouds table which has entries "thickness", "density", "base", "iprecptns".
|
-- @return #table Clouds table which has entries "thickness", "density", "base", "iprecptns".
|
||||||
-- @return #number Visibility distance in meters.
|
-- @return #number Visibility distance in meters.
|
||||||
-- @return #number Ground turbulence in m/s.
|
-- @return #number Ground turbulence in m/s.
|
||||||
-- @return #table Fog table, which has entries "thickness", "visibility" or nil if fog is disabled in the mission.
|
-- @return #table Fog table, which has entries "thickness", "visibility" or nil if fog is disabled in the mission.
|
||||||
-- @return #number Dust density or nil if dust is disabled in the mission.
|
-- @return #number Dust density or nil if dust is disabled in the mission.
|
||||||
-- @return #boolean static If true, static weather is used. If false, dynamic weather is used.
|
-- @return #boolean static If true, static weather is used. If false, dynamic weather is used.
|
||||||
@@ -1010,13 +1012,13 @@ function ATIS:GetMissionWeather()
|
|||||||
}, -- end of ["clouds"]
|
}, -- end of ["clouds"]
|
||||||
]]
|
]]
|
||||||
local clouds=weather.clouds
|
local clouds=weather.clouds
|
||||||
|
|
||||||
-- 0=static, 1=dynamic
|
-- 0=static, 1=dynamic
|
||||||
local static=weather.atmosphere_type==0
|
local static=weather.atmosphere_type==0
|
||||||
|
|
||||||
-- Visibilty distance in meters.
|
-- Visibilty distance in meters.
|
||||||
local visibility=weather.visibility.distance
|
local visibility=weather.visibility.distance
|
||||||
|
|
||||||
-- Ground turbulence.
|
-- Ground turbulence.
|
||||||
local turbulence=weather.groundTurbulence
|
local turbulence=weather.groundTurbulence
|
||||||
|
|
||||||
@@ -1063,12 +1065,12 @@ end
|
|||||||
function ATIS:_GetThousandsAndHundreds(n)
|
function ATIS:_GetThousandsAndHundreds(n)
|
||||||
|
|
||||||
local N=UTILS.Round(n/1000, 1)
|
local N=UTILS.Round(n/1000, 1)
|
||||||
|
|
||||||
local S=UTILS.Split(string.format("%.1f", N), ".")
|
local S=UTILS.Split(string.format("%.1f", N), ".")
|
||||||
|
|
||||||
local t=S[1]
|
local t=S[1]
|
||||||
local h=S[2]
|
local h=S[2]
|
||||||
|
|
||||||
return t, h
|
return t, h
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
--- **Wrapper** -- AIRBASE is a wrapper class to handle the DCS Airbase objects.
|
--- **Wrapper** -- AIRBASE is a wrapper class to handle the DCS Airbase objects.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
--
|
--
|
||||||
-- ### Contributions: **funkyfranky**
|
-- ### Contributions: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Wrapper.Airbase
|
-- @module Wrapper.Airbase
|
||||||
-- @image Wrapper_Airbase.JPG
|
-- @image Wrapper_Airbase.JPG
|
||||||
|
|
||||||
@@ -19,40 +19,40 @@
|
|||||||
-- @extends Wrapper.Positionable#POSITIONABLE
|
-- @extends Wrapper.Positionable#POSITIONABLE
|
||||||
|
|
||||||
--- Wrapper class to handle the DCS Airbase objects:
|
--- Wrapper class to handle the DCS Airbase objects:
|
||||||
--
|
--
|
||||||
-- * Support all DCS Airbase APIs.
|
-- * Support all DCS Airbase APIs.
|
||||||
-- * Enhance with Airbase specific APIs not in the DCS Airbase API set.
|
-- * Enhance with Airbase specific APIs not in the DCS Airbase API set.
|
||||||
--
|
--
|
||||||
-- ## AIRBASE reference methods
|
-- ## AIRBASE reference methods
|
||||||
--
|
--
|
||||||
-- For each DCS Airbase object alive within a running mission, a AIRBASE wrapper object (instance) will be created within the _@{DATABASE} object.
|
-- For each DCS Airbase object alive within a running mission, a AIRBASE wrapper object (instance) will be created within the _@{DATABASE} object.
|
||||||
-- This is done at the beginning of the mission (when the mission starts).
|
-- This is done at the beginning of the mission (when the mission starts).
|
||||||
--
|
--
|
||||||
-- The AIRBASE class **does not contain a :New()** method, rather it provides **:Find()** methods to retrieve the object reference
|
-- The AIRBASE class **does not contain a :New()** method, rather it provides **:Find()** methods to retrieve the object reference
|
||||||
-- using the DCS Airbase or the DCS AirbaseName.
|
-- using the DCS Airbase or the DCS AirbaseName.
|
||||||
--
|
--
|
||||||
-- Another thing to know is that AIRBASE objects do not "contain" the DCS Airbase object.
|
-- Another thing to know is that AIRBASE objects do not "contain" the DCS Airbase object.
|
||||||
-- The AIRBASE methods will reference the DCS Airbase object by name when it is needed during API execution.
|
-- The AIRBASE methods will reference the DCS Airbase object by name when it is needed during API execution.
|
||||||
-- If the DCS Airbase object does not exist or is nil, the AIRBASE methods will return nil and log an exception in the DCS.log file.
|
-- If the DCS Airbase object does not exist or is nil, the AIRBASE methods will return nil and log an exception in the DCS.log file.
|
||||||
--
|
--
|
||||||
-- The AIRBASE class provides the following functions to retrieve quickly the relevant AIRBASE instance:
|
-- The AIRBASE class provides the following functions to retrieve quickly the relevant AIRBASE instance:
|
||||||
--
|
--
|
||||||
-- * @{#AIRBASE.Find}(): Find a AIRBASE instance from the _DATABASE object using a DCS Airbase object.
|
-- * @{#AIRBASE.Find}(): Find a AIRBASE instance from the _DATABASE object using a DCS Airbase object.
|
||||||
-- * @{#AIRBASE.FindByName}(): Find a AIRBASE instance from the _DATABASE object using a DCS Airbase name.
|
-- * @{#AIRBASE.FindByName}(): Find a AIRBASE instance from the _DATABASE object using a DCS Airbase name.
|
||||||
--
|
--
|
||||||
-- IMPORTANT: ONE SHOULD NEVER SANATIZE these AIRBASE OBJECT REFERENCES! (make the AIRBASE object references nil).
|
-- IMPORTANT: ONE SHOULD NEVER SANATIZE these AIRBASE OBJECT REFERENCES! (make the AIRBASE object references nil).
|
||||||
--
|
--
|
||||||
-- ## DCS Airbase APIs
|
-- ## DCS Airbase APIs
|
||||||
--
|
--
|
||||||
-- The DCS Airbase APIs are used extensively within MOOSE. The AIRBASE class has for each DCS Airbase API a corresponding method.
|
-- The DCS Airbase APIs are used extensively within MOOSE. The AIRBASE class has for each DCS Airbase API a corresponding method.
|
||||||
-- To be able to distinguish easily in your code the difference between a AIRBASE API call and a DCS Airbase API call,
|
-- To be able to distinguish easily in your code the difference between a AIRBASE API call and a DCS Airbase API call,
|
||||||
-- the first letter of the method is also capitalized. So, by example, the DCS Airbase method @{DCSWrapper.Airbase#Airbase.getName}()
|
-- the first letter of the method is also capitalized. So, by example, the DCS Airbase method @{DCSWrapper.Airbase#Airbase.getName}()
|
||||||
-- is implemented in the AIRBASE class as @{#AIRBASE.GetName}().
|
-- is implemented in the AIRBASE class as @{#AIRBASE.GetName}().
|
||||||
--
|
--
|
||||||
-- @field #AIRBASE AIRBASE
|
-- @field #AIRBASE AIRBASE
|
||||||
AIRBASE = {
|
AIRBASE = {
|
||||||
ClassName="AIRBASE",
|
ClassName="AIRBASE",
|
||||||
CategoryName = {
|
CategoryName = {
|
||||||
[Airbase.Category.AIRDROME] = "Airdrome",
|
[Airbase.Category.AIRDROME] = "Airdrome",
|
||||||
[Airbase.Category.HELIPAD] = "Helipad",
|
[Airbase.Category.HELIPAD] = "Helipad",
|
||||||
[Airbase.Category.SHIP] = "Ship",
|
[Airbase.Category.SHIP] = "Ship",
|
||||||
@@ -61,9 +61,9 @@ AIRBASE = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- Enumeration to identify the airbases in the Caucasus region.
|
--- Enumeration to identify the airbases in the Caucasus region.
|
||||||
--
|
--
|
||||||
-- These are all airbases of Caucasus:
|
-- These are all airbases of Caucasus:
|
||||||
--
|
--
|
||||||
-- * AIRBASE.Caucasus.Gelendzhik
|
-- * AIRBASE.Caucasus.Gelendzhik
|
||||||
-- * AIRBASE.Caucasus.Krasnodar_Pashkovsky
|
-- * AIRBASE.Caucasus.Krasnodar_Pashkovsky
|
||||||
-- * AIRBASE.Caucasus.Sukhumi_Babushara
|
-- * AIRBASE.Caucasus.Sukhumi_Babushara
|
||||||
@@ -85,7 +85,7 @@ AIRBASE = {
|
|||||||
-- * AIRBASE.Caucasus.Nalchik
|
-- * AIRBASE.Caucasus.Nalchik
|
||||||
-- * AIRBASE.Caucasus.Mozdok
|
-- * AIRBASE.Caucasus.Mozdok
|
||||||
-- * AIRBASE.Caucasus.Beslan
|
-- * AIRBASE.Caucasus.Beslan
|
||||||
--
|
--
|
||||||
-- @field Caucasus
|
-- @field Caucasus
|
||||||
AIRBASE.Caucasus = {
|
AIRBASE.Caucasus = {
|
||||||
["Gelendzhik"] = "Gelendzhik",
|
["Gelendzhik"] = "Gelendzhik",
|
||||||
@@ -112,7 +112,7 @@ AIRBASE.Caucasus = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- These are all airbases of Nevada:
|
--- These are all airbases of Nevada:
|
||||||
--
|
--
|
||||||
-- * AIRBASE.Nevada.Creech_AFB
|
-- * AIRBASE.Nevada.Creech_AFB
|
||||||
-- * AIRBASE.Nevada.Groom_Lake_AFB
|
-- * AIRBASE.Nevada.Groom_Lake_AFB
|
||||||
-- * AIRBASE.Nevada.McCarran_International_Airport
|
-- * AIRBASE.Nevada.McCarran_International_Airport
|
||||||
@@ -131,7 +131,7 @@ AIRBASE.Caucasus = {
|
|||||||
-- * AIRBASE.Nevada.Pahute_Mesa_Airstrip
|
-- * AIRBASE.Nevada.Pahute_Mesa_Airstrip
|
||||||
-- * AIRBASE.Nevada.Tonopah_Airport
|
-- * AIRBASE.Nevada.Tonopah_Airport
|
||||||
-- * AIRBASE.Nevada.Tonopah_Test_Range_Airfield
|
-- * AIRBASE.Nevada.Tonopah_Test_Range_Airfield
|
||||||
-- @field Nevada
|
-- @field Nevada
|
||||||
AIRBASE.Nevada = {
|
AIRBASE.Nevada = {
|
||||||
["Creech_AFB"] = "Creech AFB",
|
["Creech_AFB"] = "Creech AFB",
|
||||||
["Groom_Lake_AFB"] = "Groom Lake AFB",
|
["Groom_Lake_AFB"] = "Groom Lake AFB",
|
||||||
@@ -154,7 +154,7 @@ AIRBASE.Nevada = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- These are all airbases of Normandy:
|
--- These are all airbases of Normandy:
|
||||||
--
|
--
|
||||||
-- * AIRBASE.Normandy.Saint_Pierre_du_Mont
|
-- * AIRBASE.Normandy.Saint_Pierre_du_Mont
|
||||||
-- * AIRBASE.Normandy.Lignerolles
|
-- * AIRBASE.Normandy.Lignerolles
|
||||||
-- * AIRBASE.Normandy.Cretteville
|
-- * AIRBASE.Normandy.Cretteville
|
||||||
@@ -264,7 +264,7 @@ AIRBASE.PersianGulf = {
|
|||||||
["Bandar_Abbas_Intl"] = "Bandar Abbas Intl",
|
["Bandar_Abbas_Intl"] = "Bandar Abbas Intl",
|
||||||
["Bandar_Lengeh"] = "Bandar Lengeh",
|
["Bandar_Lengeh"] = "Bandar Lengeh",
|
||||||
["Bandar_e_Jask_airfield"] = "Bandar-e-Jask airfield",
|
["Bandar_e_Jask_airfield"] = "Bandar-e-Jask airfield",
|
||||||
["Dubai_Intl"] = "Dubai Intl",
|
["Dubai_Intl"] = "Dubai Intl",
|
||||||
["Fujairah_Intl"] = "Fujairah Intl",
|
["Fujairah_Intl"] = "Fujairah Intl",
|
||||||
["Havadarya"] = "Havadarya",
|
["Havadarya"] = "Havadarya",
|
||||||
["Jiroft_Airport"] = "Jiroft Airport",
|
["Jiroft_Airport"] = "Jiroft Airport",
|
||||||
@@ -284,7 +284,7 @@ AIRBASE.PersianGulf = {
|
|||||||
["Tunb_Island_AFB"] = "Tunb Island AFB",
|
["Tunb_Island_AFB"] = "Tunb Island AFB",
|
||||||
["Tunb_Kochak"] = "Tunb Kochak",
|
["Tunb_Kochak"] = "Tunb Kochak",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
|
--- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
|
||||||
-- @type AIRBASE.ParkingSpot
|
-- @type AIRBASE.ParkingSpot
|
||||||
-- @field Core.Point#COORDINATE Coordinate Coordinate of the parking spot.
|
-- @field Core.Point#COORDINATE Coordinate Coordinate of the parking spot.
|
||||||
@@ -294,11 +294,11 @@ AIRBASE.PersianGulf = {
|
|||||||
-- @field #boolean Free This spot is currently free, i.e. there is no alive aircraft on it at the present moment.
|
-- @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 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 #number DistToRwy Distance to runway in meters. Currently bugged and giving the same number as the TerminalID.
|
||||||
|
|
||||||
--- Terminal Types of parking spots. See also https://wiki.hoggitworld.com/view/DCS_func_getParking
|
--- Terminal Types of parking spots. See also https://wiki.hoggitworld.com/view/DCS_func_getParking
|
||||||
--
|
--
|
||||||
-- Supported types are:
|
-- Supported types are:
|
||||||
--
|
--
|
||||||
-- * AIRBASE.TerminalType.Runway = 16: Valid spawn points on runway.
|
-- * AIRBASE.TerminalType.Runway = 16: Valid spawn points on runway.
|
||||||
-- * AIRBASE.TerminalType.HelicopterOnly = 40: Special spots for Helicopers.
|
-- * AIRBASE.TerminalType.HelicopterOnly = 40: Special spots for Helicopers.
|
||||||
-- * AIRBASE.TerminalType.Shelter = 68: Hardened Air Shelter. Currently only on Caucaus map.
|
-- * AIRBASE.TerminalType.Shelter = 68: Hardened Air Shelter. Currently only on Caucaus map.
|
||||||
@@ -307,7 +307,7 @@ AIRBASE.PersianGulf = {
|
|||||||
-- * AIRBASE.TerminalType.OpenMedOrBig = 176: Combines OpenMed and OpenBig spots.
|
-- * AIRBASE.TerminalType.OpenMedOrBig = 176: Combines OpenMed and OpenBig spots.
|
||||||
-- * AIRBASE.TerminalType.HelicopterUnsable = 216: Combines HelicopterOnly, OpenMed and OpenBig.
|
-- * AIRBASE.TerminalType.HelicopterUnsable = 216: Combines HelicopterOnly, OpenMed and OpenBig.
|
||||||
-- * AIRBASE.TerminalType.FighterAircraft = 244: Combines Shelter. OpenMed and OpenBig spots. So effectively all spots usable by fixed wing aircraft.
|
-- * AIRBASE.TerminalType.FighterAircraft = 244: Combines Shelter. OpenMed and OpenBig spots. So effectively all spots usable by fixed wing aircraft.
|
||||||
--
|
--
|
||||||
-- @type AIRBASE.TerminalType
|
-- @type AIRBASE.TerminalType
|
||||||
-- @field #number Runway 16: Valid spawn points on runway.
|
-- @field #number Runway 16: Valid spawn points on runway.
|
||||||
-- @field #number HelicopterOnly 40: Special spots for Helicopers.
|
-- @field #number HelicopterOnly 40: Special spots for Helicopers.
|
||||||
@@ -331,13 +331,13 @@ AIRBASE.TerminalType = {
|
|||||||
--- Runway data.
|
--- Runway data.
|
||||||
-- @type AIRBASE.Runway
|
-- @type AIRBASE.Runway
|
||||||
-- @field #number heading Heading of the runway in degrees.
|
-- @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 #number length Length of runway in meters.
|
||||||
-- @field Core.Point#COORDINATE position Position of runway start.
|
-- @field Core.Point#COORDINATE position Position of runway start.
|
||||||
-- @field Core.Point#COORDINATE endpoint End point of runway.
|
-- @field Core.Point#COORDINATE endpoint End point of runway.
|
||||||
|
|
||||||
-- Registration.
|
-- Registration.
|
||||||
|
|
||||||
--- Create a new AIRBASE from DCSAirbase.
|
--- Create a new AIRBASE from DCSAirbase.
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @param #string AirbaseName The name of the airbase.
|
-- @param #string AirbaseName The name of the airbase.
|
||||||
@@ -368,7 +368,7 @@ end
|
|||||||
-- @param #string AirbaseName The Airbase Name.
|
-- @param #string AirbaseName The Airbase Name.
|
||||||
-- @return #AIRBASE self
|
-- @return #AIRBASE self
|
||||||
function AIRBASE:FindByName( AirbaseName )
|
function AIRBASE:FindByName( AirbaseName )
|
||||||
|
|
||||||
local AirbaseFound = _DATABASE:FindAirbase( AirbaseName )
|
local AirbaseFound = _DATABASE:FindAirbase( AirbaseName )
|
||||||
return AirbaseFound
|
return AirbaseFound
|
||||||
end
|
end
|
||||||
@@ -378,18 +378,18 @@ end
|
|||||||
-- @param #number id Airbase ID.
|
-- @param #number id Airbase ID.
|
||||||
-- @return #AIRBASE self
|
-- @return #AIRBASE self
|
||||||
function AIRBASE:FindByID(id)
|
function AIRBASE:FindByID(id)
|
||||||
|
|
||||||
for name,_airbase in pairs(_DATABASE.AIRBASES) do
|
for name,_airbase in pairs(_DATABASE.AIRBASES) do
|
||||||
local airbase=_airbase --#AIRBASE
|
local airbase=_airbase --#AIRBASE
|
||||||
|
|
||||||
local aid=tonumber(airbase:GetID())
|
local aid=tonumber(airbase:GetID())
|
||||||
|
|
||||||
if aid==id then
|
if aid==id then
|
||||||
return airbase
|
return airbase
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -398,11 +398,11 @@ end
|
|||||||
-- @return DCS#Airbase DCS airbase object.
|
-- @return DCS#Airbase DCS airbase object.
|
||||||
function AIRBASE:GetDCSObject()
|
function AIRBASE:GetDCSObject()
|
||||||
local DCSAirbase = Airbase.getByName( self.AirbaseName )
|
local DCSAirbase = Airbase.getByName( self.AirbaseName )
|
||||||
|
|
||||||
if DCSAirbase then
|
if DCSAirbase then
|
||||||
return DCSAirbase
|
return DCSAirbase
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -418,7 +418,7 @@ end
|
|||||||
-- @param #number category (Optional) Return only airbases of a certain category, e.g. Airbase.Category.FARP
|
-- @param #number category (Optional) Return only airbases of a certain category, e.g. Airbase.Category.FARP
|
||||||
-- @return #table Table containing all airbase objects of the current map.
|
-- @return #table Table containing all airbase objects of the current map.
|
||||||
function AIRBASE.GetAllAirbases(coalition, category)
|
function AIRBASE.GetAllAirbases(coalition, category)
|
||||||
|
|
||||||
local airbases={}
|
local airbases={}
|
||||||
for _,_airbase in pairs(_DATABASE.AIRBASES) do
|
for _,_airbase in pairs(_DATABASE.AIRBASES) do
|
||||||
local airbase=_airbase --#AIRBASE
|
local airbase=_airbase --#AIRBASE
|
||||||
@@ -428,28 +428,28 @@ function AIRBASE.GetAllAirbases(coalition, category)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return airbases
|
return airbases
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Returns a table of parking data for a given airbase. If the optional parameter *available* is true only available parking will be returned, otherwise all parking at the base is returned. Term types have the following enumerated values:
|
--- Returns a table of parking data for a given airbase. If the optional parameter *available* is true only available parking will be returned, otherwise all parking at the base is returned. Term types have the following enumerated values:
|
||||||
--
|
--
|
||||||
-- * 16 : Valid spawn points on runway
|
-- * 16 : Valid spawn points on runway
|
||||||
-- * 40 : Helicopter only spawn
|
-- * 40 : Helicopter only spawn
|
||||||
-- * 68 : Hardened Air Shelter
|
-- * 68 : Hardened Air Shelter
|
||||||
-- * 72 : Open/Shelter air airplane only
|
-- * 72 : Open/Shelter air airplane only
|
||||||
-- * 104: Open air spawn
|
-- * 104: Open air spawn
|
||||||
--
|
--
|
||||||
-- Note that only Caucuses will return 68 as it is the only map currently with hardened air shelters.
|
-- Note that only Caucuses will return 68 as it is the only map currently with hardened air shelters.
|
||||||
-- 104 are also generally larger, but does not guarantee a large aircraft like the B-52 or a C-130 are capable of spawning there.
|
-- 104 are also generally larger, but does not guarantee a large aircraft like the B-52 or a C-130 are capable of spawning there.
|
||||||
--
|
--
|
||||||
-- Table entries:
|
-- Table entries:
|
||||||
--
|
--
|
||||||
-- * Term_index is the id for the parking
|
-- * Term_index is the id for the parking
|
||||||
-- * vTerminal pos is its vec3 position in the world
|
-- * vTerminal pos is its vec3 position in the world
|
||||||
-- * fDistToRW is the distance to the take-off position for the active runway from the parking.
|
-- * fDistToRW is the distance to the take-off position for the active runway from the parking.
|
||||||
--
|
--
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @param #boolean available If true, only available parking spots will be returned.
|
-- @param #boolean available If true, only available parking spots will be returned.
|
||||||
-- @return #table Table with parking data. See https://wiki.hoggitworld.com/view/DCS_func_getParking
|
-- @return #table Table with parking data. See https://wiki.hoggitworld.com/view/DCS_func_getParking
|
||||||
@@ -458,13 +458,13 @@ function AIRBASE:GetParkingData(available)
|
|||||||
|
|
||||||
-- Get DCS airbase object.
|
-- Get DCS airbase object.
|
||||||
local DCSAirbase=self:GetDCSObject()
|
local DCSAirbase=self:GetDCSObject()
|
||||||
|
|
||||||
-- Get parking data.
|
-- Get parking data.
|
||||||
local parkingdata=nil
|
local parkingdata=nil
|
||||||
if DCSAirbase then
|
if DCSAirbase then
|
||||||
parkingdata=DCSAirbase:getParking(available)
|
parkingdata=DCSAirbase:getParking(available)
|
||||||
end
|
end
|
||||||
|
|
||||||
self:T2({parkingdata=parkingdata})
|
self:T2({parkingdata=parkingdata})
|
||||||
return parkingdata
|
return parkingdata
|
||||||
end
|
end
|
||||||
@@ -477,27 +477,27 @@ function AIRBASE:GetParkingSpotsNumber(termtype)
|
|||||||
|
|
||||||
-- Get free parking spots data.
|
-- Get free parking spots data.
|
||||||
local parkingdata=self:GetParkingData(false)
|
local parkingdata=self:GetParkingData(false)
|
||||||
|
|
||||||
local nspots=0
|
local nspots=0
|
||||||
for _,parkingspot in pairs(parkingdata) do
|
for _,parkingspot in pairs(parkingdata) do
|
||||||
if AIRBASE._CheckTerminalType(parkingspot.Term_Type, termtype) then
|
if AIRBASE._CheckTerminalType(parkingspot.Term_Type, termtype) then
|
||||||
nspots=nspots+1
|
nspots=nspots+1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return nspots
|
return nspots
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get number of free parking spots at an airbase.
|
--- Get number of free parking spots at an airbase.
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @param #AIRBASE.TerminalType termtype Terminal type.
|
-- @param #AIRBASE.TerminalType termtype Terminal type.
|
||||||
-- @param #boolean allowTOAC If true, spots are considered free even though TO_AC is true. Default is off which is saver to avoid spawning aircraft on top of each other. Option might be enabled for FARPS and ships.
|
-- @param #boolean allowTOAC If true, spots are considered free even though TO_AC is true. Default is off which is saver to avoid spawning aircraft on top of each other. Option might be enabled for FARPS and ships.
|
||||||
-- @return #number Number of free parking spots at this airbase.
|
-- @return #number Number of free parking spots at this airbase.
|
||||||
function AIRBASE:GetFreeParkingSpotsNumber(termtype, allowTOAC)
|
function AIRBASE:GetFreeParkingSpotsNumber(termtype, allowTOAC)
|
||||||
|
|
||||||
-- Get free parking spots data.
|
-- Get free parking spots data.
|
||||||
local parkingdata=self:GetParkingData(true)
|
local parkingdata=self:GetParkingData(true)
|
||||||
|
|
||||||
local nfree=0
|
local nfree=0
|
||||||
for _,parkingspot in pairs(parkingdata) do
|
for _,parkingspot in pairs(parkingdata) do
|
||||||
-- Spots on runway are not counted unless explicitly requested.
|
-- Spots on runway are not counted unless explicitly requested.
|
||||||
@@ -507,7 +507,7 @@ function AIRBASE:GetFreeParkingSpotsNumber(termtype, allowTOAC)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return nfree
|
return nfree
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -520,7 +520,7 @@ function AIRBASE:GetFreeParkingSpotsCoordinates(termtype, allowTOAC)
|
|||||||
|
|
||||||
-- Get free parking spots data.
|
-- Get free parking spots data.
|
||||||
local parkingdata=self:GetParkingData(true)
|
local parkingdata=self:GetParkingData(true)
|
||||||
|
|
||||||
-- Put coordinates of free spots into table.
|
-- Put coordinates of free spots into table.
|
||||||
local spots={}
|
local spots={}
|
||||||
for _,parkingspot in pairs(parkingdata) do
|
for _,parkingspot in pairs(parkingdata) do
|
||||||
@@ -531,7 +531,7 @@ function AIRBASE:GetFreeParkingSpotsCoordinates(termtype, allowTOAC)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return spots
|
return spots
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -543,23 +543,23 @@ function AIRBASE:GetParkingSpotsCoordinates(termtype)
|
|||||||
|
|
||||||
-- Get all parking spots data.
|
-- Get all parking spots data.
|
||||||
local parkingdata=self:GetParkingData(false)
|
local parkingdata=self:GetParkingData(false)
|
||||||
|
|
||||||
-- Put coordinates of free spots into table.
|
-- Put coordinates of free spots into table.
|
||||||
local spots={}
|
local spots={}
|
||||||
for _,parkingspot in ipairs(parkingdata) do
|
for _,parkingspot in ipairs(parkingdata) do
|
||||||
|
|
||||||
-- Coordinates on runway are not returned unless explicitly requested.
|
-- Coordinates on runway are not returned unless explicitly requested.
|
||||||
if AIRBASE._CheckTerminalType(parkingspot.Term_Type, termtype) then
|
if AIRBASE._CheckTerminalType(parkingspot.Term_Type, termtype) then
|
||||||
|
|
||||||
-- Get coordinate from Vec3 terminal position.
|
-- Get coordinate from Vec3 terminal position.
|
||||||
local _coord=COORDINATE:NewFromVec3(parkingspot.vTerminalPos)
|
local _coord=COORDINATE:NewFromVec3(parkingspot.vTerminalPos)
|
||||||
|
|
||||||
-- Add to table.
|
-- Add to table.
|
||||||
table.insert(spots, _coord)
|
table.insert(spots, _coord)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return spots
|
return spots
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -570,11 +570,11 @@ end
|
|||||||
-- @return #table Table free parking spots. Table has the elements ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
|
-- @return #table Table free parking spots. Table has the elements ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
|
||||||
function AIRBASE:GetParkingSpotsTable(termtype)
|
function AIRBASE:GetParkingSpotsTable(termtype)
|
||||||
|
|
||||||
-- Get parking data of all spots (free or occupied)
|
-- Get parking data of all spots (free or occupied)
|
||||||
local parkingdata=self:GetParkingData(false)
|
local parkingdata=self:GetParkingData(false)
|
||||||
-- Get parking data of all free spots.
|
-- Get parking data of all free spots.
|
||||||
local parkingfree=self:GetParkingData(true)
|
local parkingfree=self:GetParkingData(true)
|
||||||
|
|
||||||
-- Function to ckeck if any parking spot is free.
|
-- Function to ckeck if any parking spot is free.
|
||||||
local function _isfree(_tocheck)
|
local function _isfree(_tocheck)
|
||||||
for _,_spot in pairs(parkingfree) do
|
for _,_spot in pairs(parkingfree) do
|
||||||
@@ -584,7 +584,7 @@ function AIRBASE:GetParkingSpotsTable(termtype)
|
|||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Put coordinates of parking spots into table.
|
-- Put coordinates of parking spots into table.
|
||||||
local spots={}
|
local spots={}
|
||||||
for _,_spot in pairs(parkingdata) do
|
for _,_spot in pairs(parkingdata) do
|
||||||
@@ -595,22 +595,22 @@ function AIRBASE:GetParkingSpotsTable(termtype)
|
|||||||
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, {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
|
||||||
end
|
end
|
||||||
|
|
||||||
self:T2({ spots = spots } )
|
self:T2({ spots = spots } )
|
||||||
|
|
||||||
return spots
|
return spots
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase.
|
--- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase.
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @param #AIRBASE.TerminalType termtype Terminal type.
|
-- @param #AIRBASE.TerminalType termtype Terminal type.
|
||||||
-- @param #boolean allowTOAC If true, spots are considered free even though TO_AC is true. Default is off which is saver to avoid spawning aircraft on top of each other. Option might be enabled for FARPS and ships.
|
-- @param #boolean allowTOAC If true, spots are considered free even though TO_AC is true. Default is off which is saver to avoid spawning aircraft on top of each other. Option might be enabled for FARPS and ships.
|
||||||
-- @return #table Table free parking spots. Table has the elements ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
|
-- @return #table Table free parking spots. Table has the elements ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
|
||||||
function AIRBASE:GetFreeParkingSpotsTable(termtype, allowTOAC)
|
function AIRBASE:GetFreeParkingSpotsTable(termtype, allowTOAC)
|
||||||
|
|
||||||
-- Get parking data of all free spots.
|
-- Get parking data of all free spots.
|
||||||
local parkingfree=self:GetParkingData(true)
|
local parkingfree=self:GetParkingData(true)
|
||||||
|
|
||||||
-- Put coordinates of free spots into table.
|
-- Put coordinates of free spots into table.
|
||||||
local freespots={}
|
local freespots={}
|
||||||
for _,_spot in pairs(parkingfree) do
|
for _,_spot in pairs(parkingfree) do
|
||||||
@@ -621,7 +621,7 @@ function AIRBASE:GetFreeParkingSpotsTable(termtype, allowTOAC)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return freespots
|
return freespots
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -634,10 +634,10 @@ function AIRBASE:GetParkingSpotData(TerminalID)
|
|||||||
|
|
||||||
-- Get parking data.
|
-- Get parking data.
|
||||||
local parkingdata=self:GetParkingSpotsTable()
|
local parkingdata=self:GetParkingSpotsTable()
|
||||||
|
|
||||||
-- Debug output.
|
-- Debug output.
|
||||||
self:T2({parkingdata=parkingdata})
|
self:T2({parkingdata=parkingdata})
|
||||||
|
|
||||||
for _,_spot in pairs(parkingdata) do
|
for _,_spot in pairs(parkingdata) do
|
||||||
local spot=_spot --#AIRBASE.ParkingSpot
|
local spot=_spot --#AIRBASE.ParkingSpot
|
||||||
self:T({TerminalID=spot.TerminalID,TerminalType=spot.TerminalType})
|
self:T({TerminalID=spot.TerminalID,TerminalType=spot.TerminalType})
|
||||||
@@ -645,7 +645,7 @@ function AIRBASE:GetParkingSpotData(TerminalID)
|
|||||||
return spot
|
return spot
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:E("ERROR: Could not find spot with Terminal ID="..tostring(TerminalID))
|
self:E("ERROR: Could not find spot with Terminal ID="..tostring(TerminalID))
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -667,18 +667,18 @@ function AIRBASE:MarkParkingSpots(termtype, mark)
|
|||||||
-- Get airbase name.
|
-- Get airbase name.
|
||||||
local airbasename=self:GetName()
|
local airbasename=self:GetName()
|
||||||
self:E(string.format("Parking spots at %s for termial type %s:", airbasename, tostring(termtype)))
|
self:E(string.format("Parking spots at %s for termial type %s:", airbasename, tostring(termtype)))
|
||||||
|
|
||||||
for _,_spot in pairs(parkingdata) do
|
for _,_spot in pairs(parkingdata) do
|
||||||
|
|
||||||
-- Mark text.
|
-- Mark text.
|
||||||
local _text=string.format("Term Index=%d, Term Type=%d, Free=%s, TOAC=%s, Term ID0=%d, Dist2Rwy=%.1f m",
|
local _text=string.format("Term Index=%d, Term Type=%d, Free=%s, TOAC=%s, Term ID0=%d, Dist2Rwy=%.1f m",
|
||||||
_spot.TerminalID, _spot.TerminalType,tostring(_spot.Free),tostring(_spot.TOAC),_spot.TerminalID0,_spot.DistToRwy)
|
_spot.TerminalID, _spot.TerminalType,tostring(_spot.Free),tostring(_spot.TOAC),_spot.TerminalID0,_spot.DistToRwy)
|
||||||
|
|
||||||
-- Create mark on the F10 map.
|
-- Create mark on the F10 map.
|
||||||
if mark then
|
if mark then
|
||||||
_spot.Coordinate:MarkToAll(_text)
|
_spot.Coordinate:MarkToAll(_text)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Info to DCS.log file.
|
-- Info to DCS.log file.
|
||||||
local _text=string.format("%s, Term Index=%3d, Term Type=%03d, Free=%5s, TOAC=%5s, Term ID0=%3d, Dist2Rwy=%.1f m",
|
local _text=string.format("%s, Term Index=%3d, Term Type=%03d, Free=%5s, TOAC=%5s, Term ID0=%3d, Dist2Rwy=%.1f m",
|
||||||
airbasename, _spot.TerminalID, _spot.TerminalType,tostring(_spot.Free),tostring(_spot.TOAC),_spot.TerminalID0,_spot.DistToRwy)
|
airbasename, _spot.TerminalID, _spot.TerminalType,tostring(_spot.Free),tostring(_spot.TOAC),_spot.TerminalID0,_spot.DistToRwy)
|
||||||
@@ -696,7 +696,7 @@ end
|
|||||||
-- @param #boolean scanstatics (Optional) Scan for statics as obstacles. Default true.
|
-- @param #boolean scanstatics (Optional) Scan for statics as obstacles. Default true.
|
||||||
-- @param #boolean scanscenery (Optional) Scan for scenery as obstacles. Default false. Can cause problems with e.g. shelters.
|
-- @param #boolean scanscenery (Optional) Scan for scenery as obstacles. Default false. Can cause problems with e.g. shelters.
|
||||||
-- @param #boolean verysafe (Optional) If true, wait until an aircraft has taken off until the parking spot is considered to be free. Defaul false.
|
-- @param #boolean verysafe (Optional) If true, wait until an aircraft has taken off until the parking spot is considered to be free. Defaul false.
|
||||||
-- @param #number nspots (Optional) Number of freeparking spots requested. Default is the number of aircraft in the group.
|
-- @param #number nspots (Optional) Number of freeparking spots requested. Default is the number of aircraft in the group.
|
||||||
-- @param #table parkingdata (Optional) Parking spots data table. If not given it is automatically derived from the GetParkingSpotsTable() function.
|
-- @param #table parkingdata (Optional) Parking spots data table. If not given it is automatically derived from the GetParkingSpotsTable() function.
|
||||||
-- @return #table Table of coordinates and terminal IDs of free parking spots. Each table entry has the elements .Coordinate and .TerminalID.
|
-- @return #table Table of coordinates and terminal IDs of free parking spots. Each table entry has the elements .Coordinate and .TerminalID.
|
||||||
function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius, scanunits, scanstatics, scanscenery, verysafe, nspots, parkingdata)
|
function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius, scanunits, scanstatics, scanscenery, verysafe, nspots, parkingdata)
|
||||||
@@ -714,8 +714,8 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
|
|||||||
end
|
end
|
||||||
if verysafe==nil then
|
if verysafe==nil then
|
||||||
verysafe=false
|
verysafe=false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Function calculating the overlap of two (square) objects.
|
-- Function calculating the overlap of two (square) objects.
|
||||||
local function _overlap(object1, object2, dist)
|
local function _overlap(object1, object2, dist)
|
||||||
local pos1=object1 --Wrapper.Positionable#POSITIONABLE
|
local pos1=object1 --Wrapper.Positionable#POSITIONABLE
|
||||||
@@ -723,107 +723,107 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
|
|||||||
local r1=pos1:GetBoundingRadius()
|
local r1=pos1:GetBoundingRadius()
|
||||||
local r2=pos2:GetBoundingRadius()
|
local r2=pos2:GetBoundingRadius()
|
||||||
if r1 and r2 then
|
if r1 and r2 then
|
||||||
local safedist=(r1+r2)*1.1
|
local safedist=(r1+r2)*1.1
|
||||||
local safe = (dist > safedist)
|
local safe = (dist > safedist)
|
||||||
self:T2(string.format("r1=%.1f r2=%.1f s=%.1f d=%.1f ==> safe=%s", r1, r2, safedist, dist, tostring(safe)))
|
self:T2(string.format("r1=%.1f r2=%.1f s=%.1f d=%.1f ==> safe=%s", r1, r2, safedist, dist, tostring(safe)))
|
||||||
return safe
|
return safe
|
||||||
else
|
else
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get airport name.
|
-- Get airport name.
|
||||||
local airport=self:GetName()
|
local airport=self:GetName()
|
||||||
|
|
||||||
-- Get parking spot data table. This contains free and "non-free" spots.
|
-- Get parking spot data table. This contains free and "non-free" spots.
|
||||||
-- Note that there are three major issues with the DCS getParking() function:
|
-- Note that there are three major issues with the DCS getParking() function:
|
||||||
-- 1. A spot is considered as NOT free until an aircraft that is present has finally taken off. This might be a bit long especiall at smaller airports.
|
-- 1. A spot is considered as NOT free until an aircraft that is present has finally taken off. This might be a bit long especiall at smaller airports.
|
||||||
-- 2. A "free" spot does not take the aircraft size into accound. So if two big aircraft are spawned on spots next to each other, they might overlap and get destroyed.
|
-- 2. A "free" spot does not take the aircraft size into accound. So if two big aircraft are spawned on spots next to each other, they might overlap and get destroyed.
|
||||||
-- 3. The routine return a free spot, if there a static objects placed on the spot.
|
-- 3. The routine return a free spot, if there a static objects placed on the spot.
|
||||||
parkingdata=parkingdata or self:GetParkingSpotsTable(terminaltype)
|
parkingdata=parkingdata or self:GetParkingSpotsTable(terminaltype)
|
||||||
|
|
||||||
-- Get the aircraft size, i.e. it's longest side of x,z.
|
-- Get the aircraft size, i.e. it's longest side of x,z.
|
||||||
local aircraft=group:GetUnit(1)
|
local aircraft=group:GetUnit(1)
|
||||||
local _aircraftsize, ax,ay,az=aircraft:GetObjectSize()
|
local _aircraftsize, ax,ay,az=aircraft:GetObjectSize()
|
||||||
|
|
||||||
-- Number of spots we are looking for. Note that, e.g. grouping can require a number different from the group size!
|
-- Number of spots we are looking for. Note that, e.g. grouping can require a number different from the group size!
|
||||||
local _nspots=nspots or group:GetSize()
|
local _nspots=nspots or group:GetSize()
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:E(string.format("%s: Looking for %d parking spot(s) for aircraft of size %.1f m (x=%.1f,y=%.1f,z=%.1f) at termial type %s.", airport, _nspots, _aircraftsize, ax, ay, az, tostring(terminaltype)))
|
self:E(string.format("%s: Looking for %d parking spot(s) for aircraft of size %.1f m (x=%.1f,y=%.1f,z=%.1f) at termial type %s.", airport, _nspots, _aircraftsize, ax, ay, az, tostring(terminaltype)))
|
||||||
|
|
||||||
-- Table of valid spots.
|
-- Table of valid spots.
|
||||||
local validspots={}
|
local validspots={}
|
||||||
local nvalid=0
|
local nvalid=0
|
||||||
|
|
||||||
-- Test other stuff if no parking spot is available.
|
-- Test other stuff if no parking spot is available.
|
||||||
local _test=false
|
local _test=false
|
||||||
if _test then
|
if _test then
|
||||||
return validspots
|
return validspots
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Mark all found obstacles on F10 map for debugging.
|
-- Mark all found obstacles on F10 map for debugging.
|
||||||
local markobstacles=false
|
local markobstacles=false
|
||||||
|
|
||||||
-- Loop over all known parking spots
|
-- Loop over all known parking spots
|
||||||
for _,parkingspot in pairs(parkingdata) do
|
for _,parkingspot in pairs(parkingdata) do
|
||||||
|
|
||||||
-- Coordinate of the parking spot.
|
-- Coordinate of the parking spot.
|
||||||
local _spot=parkingspot.Coordinate -- Core.Point#COORDINATE
|
local _spot=parkingspot.Coordinate -- Core.Point#COORDINATE
|
||||||
local _termid=parkingspot.TerminalID
|
local _termid=parkingspot.TerminalID
|
||||||
|
|
||||||
self:T2({_termid=_termid})
|
self:T2({_termid=_termid})
|
||||||
|
|
||||||
if AIRBASE._CheckTerminalType(parkingspot.TerminalType, terminaltype) then
|
if AIRBASE._CheckTerminalType(parkingspot.TerminalType, terminaltype) then
|
||||||
|
|
||||||
-- Very safe uses the DCS getParking() info to check if a spot is free. Unfortunately, the function returns free=false until the aircraft has actually taken-off.
|
-- Very safe uses the DCS getParking() info to check if a spot is free. Unfortunately, the function returns free=false until the aircraft has actually taken-off.
|
||||||
if verysafe and (parkingspot.Free==false or parkingspot.TOAC==true) then
|
if verysafe and (parkingspot.Free==false or parkingspot.TOAC==true) then
|
||||||
|
|
||||||
-- DCS getParking() routine returned that spot is not free.
|
-- DCS getParking() routine returned that spot is not free.
|
||||||
self:T(string.format("%s: Parking spot id %d NOT free (or aircraft has not taken off yet). Free=%s, TOAC=%s.", airport, parkingspot.TerminalID, tostring(parkingspot.Free), tostring(parkingspot.TOAC)))
|
self:T(string.format("%s: Parking spot id %d NOT free (or aircraft has not taken off yet). Free=%s, TOAC=%s.", airport, parkingspot.TerminalID, tostring(parkingspot.Free), tostring(parkingspot.TOAC)))
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Scan a radius of 50 meters around the spot.
|
-- Scan a radius of 50 meters around the spot.
|
||||||
local _,_,_,_units,_statics,_sceneries=_spot:ScanObjects(scanradius, scanunits, scanstatics, scanscenery)
|
local _,_,_,_units,_statics,_sceneries=_spot:ScanObjects(scanradius, scanunits, scanstatics, scanscenery)
|
||||||
|
|
||||||
-- Loop over objects within scan radius.
|
-- Loop over objects within scan radius.
|
||||||
local occupied=false
|
local occupied=false
|
||||||
|
|
||||||
-- Check all units.
|
-- Check all units.
|
||||||
for _,unit in pairs(_units) do
|
for _,unit in pairs(_units) do
|
||||||
local _coord=unit:GetCoordinate()
|
local _coord=unit:GetCoordinate()
|
||||||
local _dist=_coord:Get2DDistance(_spot)
|
local _dist=_coord:Get2DDistance(_spot)
|
||||||
local _safe=_overlap(aircraft, unit, _dist)
|
local _safe=_overlap(aircraft, unit, _dist)
|
||||||
|
|
||||||
if markobstacles then
|
if markobstacles then
|
||||||
local l,x,y,z=unit:GetObjectSize()
|
local l,x,y,z=unit:GetObjectSize()
|
||||||
_coord:MarkToAll(string.format("Unit %s\nx=%.1f y=%.1f z=%.1f\nl=%.1f d=%.1f\nspot %d safe=%s", unit:GetName(),x,y,z,l,_dist, _termid, tostring(_safe)))
|
_coord:MarkToAll(string.format("Unit %s\nx=%.1f y=%.1f z=%.1f\nl=%.1f d=%.1f\nspot %d safe=%s", unit:GetName(),x,y,z,l,_dist, _termid, tostring(_safe)))
|
||||||
end
|
end
|
||||||
|
|
||||||
if scanunits and not _safe then
|
if scanunits and not _safe then
|
||||||
occupied=true
|
occupied=true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check all statics.
|
-- Check all statics.
|
||||||
for _,static in pairs(_statics) do
|
for _,static in pairs(_statics) do
|
||||||
local _static=STATIC:Find(static)
|
local _static=STATIC:Find(static)
|
||||||
local _vec3=static:getPoint()
|
local _vec3=static:getPoint()
|
||||||
local _coord=COORDINATE:NewFromVec3(_vec3)
|
local _coord=COORDINATE:NewFromVec3(_vec3)
|
||||||
local _dist=_coord:Get2DDistance(_spot)
|
local _dist=_coord:Get2DDistance(_spot)
|
||||||
local _safe=_overlap(aircraft,_static,_dist)
|
local _safe=_overlap(aircraft,_static,_dist)
|
||||||
|
|
||||||
if markobstacles then
|
if markobstacles then
|
||||||
local l,x,y,z=_static:GetObjectSize()
|
local l,x,y,z=_static:GetObjectSize()
|
||||||
_coord:MarkToAll(string.format("Static %s\nx=%.1f y=%.1f z=%.1f\nl=%.1f d=%.1f\nspot %d safe=%s", static:getName(),x,y,z,l,_dist, _termid, tostring(_safe)))
|
_coord:MarkToAll(string.format("Static %s\nx=%.1f y=%.1f z=%.1f\nl=%.1f d=%.1f\nspot %d safe=%s", static:getName(),x,y,z,l,_dist, _termid, tostring(_safe)))
|
||||||
end
|
end
|
||||||
|
|
||||||
if scanstatics and not _safe then
|
if scanstatics and not _safe then
|
||||||
occupied=true
|
occupied=true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check all scenery.
|
-- Check all scenery.
|
||||||
for _,scenery in pairs(_sceneries) do
|
for _,scenery in pairs(_sceneries) do
|
||||||
local _scenery=SCENERY:Register(scenery:getTypeName(), scenery)
|
local _scenery=SCENERY:Register(scenery:getTypeName(), scenery)
|
||||||
@@ -831,17 +831,17 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
|
|||||||
local _coord=COORDINATE:NewFromVec3(_vec3)
|
local _coord=COORDINATE:NewFromVec3(_vec3)
|
||||||
local _dist=_coord:Get2DDistance(_spot)
|
local _dist=_coord:Get2DDistance(_spot)
|
||||||
local _safe=_overlap(aircraft,_scenery,_dist)
|
local _safe=_overlap(aircraft,_scenery,_dist)
|
||||||
|
|
||||||
if markobstacles then
|
if markobstacles then
|
||||||
local l,x,y,z=scenery:GetObjectSize(scenery)
|
local l,x,y,z=scenery:GetObjectSize(scenery)
|
||||||
_coord:MarkToAll(string.format("Scenery %s\nx=%.1f y=%.1f z=%.1f\nl=%.1f d=%.1f\nspot %d safe=%s", scenery:getTypeName(),x,y,z,l,_dist, _termid, tostring(_safe)))
|
_coord:MarkToAll(string.format("Scenery %s\nx=%.1f y=%.1f z=%.1f\nl=%.1f d=%.1f\nspot %d safe=%s", scenery:getTypeName(),x,y,z,l,_dist, _termid, tostring(_safe)))
|
||||||
end
|
end
|
||||||
|
|
||||||
if scanscenery and not _safe then
|
if scanscenery and not _safe then
|
||||||
occupied=true
|
occupied=true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Now check the already given spots so that we do not put a large aircraft next to one we already assigned a nearby spot.
|
-- Now check the already given spots so that we do not put a large aircraft next to one we already assigned a nearby spot.
|
||||||
for _,_takenspot in pairs(validspots) do
|
for _,_takenspot in pairs(validspots) do
|
||||||
local _dist=_takenspot.Coordinate:Get2DDistance(_spot)
|
local _dist=_takenspot.Coordinate:Get2DDistance(_spot)
|
||||||
@@ -850,7 +850,7 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
|
|||||||
occupied=true
|
occupied=true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--_spot:MarkToAll(string.format("Parking spot %d free=%s", parkingspot.TerminalID, tostring(not occupied)))
|
--_spot:MarkToAll(string.format("Parking spot %d free=%s", parkingspot.TerminalID, tostring(not occupied)))
|
||||||
if occupied then
|
if occupied then
|
||||||
self:I(string.format("%s: Parking spot id %d occupied.", airport, _termid))
|
self:I(string.format("%s: Parking spot id %d occupied.", airport, _termid))
|
||||||
@@ -862,16 +862,16 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
|
|||||||
nvalid=nvalid+1
|
nvalid=nvalid+1
|
||||||
self:I(string.format("%s: Parking spot id %d free. Nfree=%d/%d.", airport, _termid, nvalid,_nspots))
|
self:I(string.format("%s: Parking spot id %d free. Nfree=%d/%d.", airport, _termid, nvalid,_nspots))
|
||||||
end
|
end
|
||||||
|
|
||||||
end -- loop over units
|
end -- loop over units
|
||||||
|
|
||||||
-- We found enough spots.
|
-- We found enough spots.
|
||||||
if nvalid>=_nspots then
|
if nvalid>=_nspots then
|
||||||
return validspots
|
return validspots
|
||||||
end
|
end
|
||||||
end -- check terminal type
|
end -- check terminal type
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Retrun spots we found, even if there were not enough.
|
-- Retrun spots we found, even if there were not enough.
|
||||||
return validspots
|
return validspots
|
||||||
end
|
end
|
||||||
@@ -880,54 +880,54 @@ end
|
|||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @param Wrapper.Group#GROUP group Group to be checked.
|
-- @param Wrapper.Group#GROUP group Group to be checked.
|
||||||
-- @param #number radius Radius around the spawn point to be checked. Default is 50 m.
|
-- @param #number radius Radius around the spawn point to be checked. Default is 50 m.
|
||||||
-- @param #boolean despawn If true, the group is destroyed.
|
-- @param #boolean despawn If true, the group is destroyed.
|
||||||
-- @return #boolean True if group is within radius around spawn points on runway.
|
-- @return #boolean True if group is within radius around spawn points on runway.
|
||||||
function AIRBASE:CheckOnRunWay(group, radius, despawn)
|
function AIRBASE:CheckOnRunWay(group, radius, despawn)
|
||||||
|
|
||||||
-- Default radius.
|
-- Default radius.
|
||||||
radius=radius or 50
|
radius=radius or 50
|
||||||
|
|
||||||
-- We only check at real airbases (not FARPS or ships).
|
-- We only check at real airbases (not FARPS or ships).
|
||||||
if self:GetDesc().category~=Airbase.Category.AIRDROME then
|
if self:GetDesc().category~=Airbase.Category.AIRDROME then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
if group and group:IsAlive() then
|
if group and group:IsAlive() then
|
||||||
|
|
||||||
-- Debug.
|
-- Debug.
|
||||||
self:T(string.format("%s, checking if group %s is on runway?",self:GetName(), group:GetName()))
|
self:T(string.format("%s, checking if group %s is on runway?",self:GetName(), group:GetName()))
|
||||||
|
|
||||||
-- Get coordinates on runway.
|
-- Get coordinates on runway.
|
||||||
local runwaypoints=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
local runwaypoints=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
||||||
|
|
||||||
-- Mark runway spawn points.
|
-- Mark runway spawn points.
|
||||||
--[[
|
--[[
|
||||||
for _i,_coord in pairs(runwaypoints) do
|
for _i,_coord in pairs(runwaypoints) do
|
||||||
_coord:MarkToAll(string.format("runway %d",_i))
|
_coord:MarkToAll(string.format("runway %d",_i))
|
||||||
end
|
end
|
||||||
]]
|
]]
|
||||||
|
|
||||||
-- Get units of group.
|
-- Get units of group.
|
||||||
local units=group:GetUnits()
|
local units=group:GetUnits()
|
||||||
|
|
||||||
-- Loop over units.
|
-- Loop over units.
|
||||||
for _,_unit in pairs(units) do
|
for _,_unit in pairs(units) do
|
||||||
|
|
||||||
local unit=_unit --Wrapper.Unit#UNIT
|
local unit=_unit --Wrapper.Unit#UNIT
|
||||||
|
|
||||||
-- Check if unit is alive and not in air.
|
-- Check if unit is alive and not in air.
|
||||||
if unit and unit:IsAlive() and not unit:InAir() then
|
if unit and unit:IsAlive() and not unit:InAir() then
|
||||||
self:T(string.format("%s, checking if unit %s is on runway?",self:GetName(), unit:GetName()))
|
self:T(string.format("%s, checking if unit %s is on runway?",self:GetName(), unit:GetName()))
|
||||||
|
|
||||||
-- Loop over runway spawn points.
|
-- Loop over runway spawn points.
|
||||||
for _i,_coord in pairs(runwaypoints) do
|
for _i,_coord in pairs(runwaypoints) do
|
||||||
|
|
||||||
-- Distance between unit and spawn pos.
|
-- Distance between unit and spawn pos.
|
||||||
local dist=unit:GetCoordinate():Get2DDistance(_coord)
|
local dist=unit:GetCoordinate():Get2DDistance(_coord)
|
||||||
|
|
||||||
-- Mark unit spawn points for debugging.
|
-- Mark unit spawn points for debugging.
|
||||||
--unit:GetCoordinate():MarkToAll(string.format("unit %s distance to rwy %d = %d",unit:GetName(),_i, dist))
|
--unit:GetCoordinate():MarkToAll(string.format("unit %s distance to rwy %d = %d",unit:GetName(),_i, dist))
|
||||||
|
|
||||||
-- Check if unit is withing radius.
|
-- Check if unit is withing radius.
|
||||||
if dist<radius then
|
if dist<radius then
|
||||||
self:E(string.format("%s, unit %s of group %s was spawned on runway #%d. Distance %.1f < radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
|
self:E(string.format("%s, unit %s of group %s was spawned on runway #%d. Distance %.1f < radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
|
||||||
@@ -940,16 +940,16 @@ function AIRBASE:CheckOnRunWay(group, radius, despawn)
|
|||||||
self:T(string.format("%s, unit %s of group %s was NOT spawned on runway #%d. Distance %.1f > radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
|
self:T(string.format("%s, unit %s of group %s was NOT spawned on runway #%d. Distance %.1f > radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
|
||||||
--unit:FlareGreen()
|
--unit:FlareGreen()
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:T(string.format("%s, checking if unit %s of group %s is on runway. Unit is NOT alive.",self:GetName(), unit:GetName(), group:GetName()))
|
self:T(string.format("%s, checking if unit %s of group %s is on runway. Unit is NOT alive.",self:GetName(), unit:GetName(), group:GetName()))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:T(string.format("%s, checking if group %s is on runway. Group is NOT alive.",self:GetName(), group:GetName()))
|
self:T(string.format("%s, checking if group %s is on runway. Group is NOT alive.",self:GetName(), group:GetName()))
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -980,15 +980,15 @@ function AIRBASE._CheckTerminalType(Term_Type, termtype)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Init no match.
|
-- Init no match.
|
||||||
local match=false
|
local match=false
|
||||||
|
|
||||||
-- Standar case.
|
-- Standar case.
|
||||||
if Term_Type==termtype then
|
if Term_Type==termtype then
|
||||||
match=true
|
match=true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Artificial cases. Combination of terminal types.
|
-- Artificial cases. Combination of terminal types.
|
||||||
if termtype==AIRBASE.TerminalType.OpenMedOrBig then
|
if termtype==AIRBASE.TerminalType.OpenMedOrBig then
|
||||||
if Term_Type==AIRBASE.TerminalType.OpenMed or Term_Type==AIRBASE.TerminalType.OpenBig then
|
if Term_Type==AIRBASE.TerminalType.OpenMed or Term_Type==AIRBASE.TerminalType.OpenBig then
|
||||||
@@ -1003,114 +1003,119 @@ function AIRBASE._CheckTerminalType(Term_Type, termtype)
|
|||||||
match=true
|
match=true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return match
|
return match
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get runways data. Only for airdromes!
|
--- Get runways data. Only for airdromes!
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @param #number magvar (Optional) Magnetic variation in degrees.
|
-- @param #number magvar (Optional) Magnetic variation in degrees.
|
||||||
|
-- @param #boolean mark (Optional) Place markers with runway data on F10 map.
|
||||||
-- @return #table Runway data.
|
-- @return #table Runway data.
|
||||||
function AIRBASE:GetRunwayData(magvar)
|
function AIRBASE:GetRunwayData(magvar, mark)
|
||||||
|
|
||||||
-- Runway table.
|
-- Runway table.
|
||||||
local runways={}
|
local runways={}
|
||||||
|
|
||||||
if self:GetAirbaseCategory()~=Airbase.Category.AIRDROME then
|
if self:GetAirbaseCategory()~=Airbase.Category.AIRDROME then
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get spawn points on runway.
|
-- Get spawn points on runway.
|
||||||
local runwaycoords=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
local runwaycoords=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
||||||
|
|
||||||
-- Magnetic declination.
|
-- Magnetic declination.
|
||||||
magvar=magvar or UTILS.GetMagneticDeclination()
|
magvar=magvar or UTILS.GetMagneticDeclination()
|
||||||
|
|
||||||
local N=#runwaycoords
|
local N=#runwaycoords
|
||||||
local dN=2
|
local dN=2
|
||||||
local ex=false
|
local ex=false
|
||||||
|
|
||||||
local name=self:GetName()
|
local name=self:GetName()
|
||||||
if name==AIRBASE.Nevada.Jean_Airport or
|
if name==AIRBASE.Nevada.Jean_Airport or
|
||||||
name==AIRBASE.Nevada.Creech_AFB or
|
name==AIRBASE.Nevada.Creech_AFB or
|
||||||
name==AIRBASE.PersianGulf.Abu_Dhabi_International_Airport or
|
name==AIRBASE.PersianGulf.Abu_Dhabi_International_Airport or
|
||||||
name==AIRBASE.PersianGulf.Dubai_Intl or
|
name==AIRBASE.PersianGulf.Dubai_Intl or
|
||||||
name==AIRBASE.PersianGulf.Shiraz_International_Airport or
|
name==AIRBASE.PersianGulf.Shiraz_International_Airport or
|
||||||
name==AIRBASE.PersianGulf.Kish_International_Airport then
|
name==AIRBASE.PersianGulf.Kish_International_Airport then
|
||||||
|
|
||||||
N=#runwaycoords/2
|
N=#runwaycoords/2
|
||||||
dN=1
|
dN=1
|
||||||
ex=true
|
ex=true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
for i=1,N,dN do
|
for i=1,N,dN do
|
||||||
|
|
||||||
local j=i+1
|
local j=i+1
|
||||||
if ex then
|
if ex then
|
||||||
--j=N+i
|
--j=N+i
|
||||||
j=#runwaycoords-i+1
|
j=#runwaycoords-i+1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Coordinates of the two runway points.
|
-- Coordinates of the two runway points.
|
||||||
local c1=runwaycoords[i] --Core.Point#COORDINATES
|
local c1=runwaycoords[i] --Core.Point#COORDINATES
|
||||||
local c2=runwaycoords[j] --Core.Point#COORDINATES
|
local c2=runwaycoords[j] --Core.Point#COORDINATES
|
||||||
|
|
||||||
-- Heading of runway.
|
-- Heading of runway.
|
||||||
local hdg=c1:HeadingTo(c2)
|
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))
|
local idx=string.format("%02d", UTILS.Round((hdg-magvar)/10, 0))
|
||||||
|
|
||||||
-- Runway table.
|
-- Runway table.
|
||||||
local runway={} --#AIRBASE.Runway
|
local runway={} --#AIRBASE.Runway
|
||||||
runway.heading=hdg
|
runway.heading=hdg
|
||||||
runway.idx=idx
|
runway.idx=idx
|
||||||
runway.length=c1:Get2DDistance(c2)
|
runway.length=c1:Get2DDistance(c2)
|
||||||
runway.position=c1
|
runway.position=c1
|
||||||
runway.endpoint=c2
|
runway.endpoint=c2
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m", self:GetName(), runway.idx, runway.heading, runway.length))
|
self:T(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m", self:GetName(), runway.idx, runway.heading, runway.length))
|
||||||
|
|
||||||
-- Debug mark
|
-- Debug mark
|
||||||
runway.position:MarkToAll(string.format("Runway %s Heading=%03d", runway.idx, runway.heading))
|
if mark then
|
||||||
|
runway.position:MarkToAll(string.format("Runway %s: true heading=%03d, length=%d m", runway.idx, runway.heading, runway.length))
|
||||||
|
end
|
||||||
|
|
||||||
-- Add runway.
|
-- Add runway.
|
||||||
table.insert(runways, runway)
|
table.insert(runways, runway)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get inverse runways
|
-- Get inverse runways
|
||||||
local inverse={}
|
local inverse={}
|
||||||
for _,_runway in pairs(runways) do
|
for _,_runway in pairs(runways) do
|
||||||
local r=_runway --#AIRBASE.Runway
|
local r=_runway --#AIRBASE.Runway
|
||||||
|
|
||||||
local runway={} --#AIRBASE.Runway
|
local runway={} --#AIRBASE.Runway
|
||||||
runway.heading=r.heading-180
|
runway.heading=r.heading-180
|
||||||
if runway.heading<0 then
|
if runway.heading<0 then
|
||||||
runway.heading=runway.heading+360
|
runway.heading=runway.heading+360
|
||||||
end
|
end
|
||||||
runway.idx=string.format("%02d", math.max(0, UTILS.Round((runway.heading-magvar)/10, 0)))
|
runway.idx=string.format("%02d", math.max(0, UTILS.Round((runway.heading-magvar)/10, 0)))
|
||||||
runway.length=r.length
|
runway.length=r.length
|
||||||
runway.position=r.endpoint
|
runway.position=r.endpoint
|
||||||
runway.endpoint=r.position
|
runway.endpoint=r.position
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m", self:GetName(), runway.idx, runway.heading, runway.length))
|
self:T(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m", self:GetName(), runway.idx, runway.heading, runway.length))
|
||||||
|
|
||||||
-- Debug mark
|
-- Debug mark
|
||||||
runway.position:MarkToAll(string.format("Runway %s Heading=%03d", runway.idx, runway.heading))
|
if mark then
|
||||||
|
runway.position:MarkToAll(string.format("Runway %s: true heading=%03d, length=%d m", runway.idx, runway.heading, runway.length))
|
||||||
|
end
|
||||||
|
|
||||||
-- Add runway.
|
-- Add runway.
|
||||||
table.insert(inverse, runway)
|
table.insert(inverse, runway)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Add inverse runway.
|
||||||
for _,runway in pairs(inverse) do
|
for _,runway in pairs(inverse) do
|
||||||
-- Add runway.
|
table.insert(runways, runway)
|
||||||
table.insert(runways, runway)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return runways
|
return runways
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1138,48 +1143,45 @@ function AIRBASE:GetActiveRunway(magvar)
|
|||||||
-- 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)
|
||||||
|
|
||||||
-- Active runway number.
|
-- Active runway number.
|
||||||
local iact=1
|
local iact=1
|
||||||
|
|
||||||
-- Check if wind is blowing (norm>0).
|
-- Check if wind is blowing (norm>0).
|
||||||
if norm>0 then
|
if norm>0 then
|
||||||
|
|
||||||
-- Normalize wind (not necessary).
|
-- Normalize wind (not necessary).
|
||||||
Vwind.x=Vwind.x/norm
|
Vwind.x=Vwind.x/norm
|
||||||
Vwind.y=0
|
Vwind.y=0
|
||||||
Vwind.z=Vwind.z/norm
|
Vwind.z=Vwind.z/norm
|
||||||
|
|
||||||
-- Loop over runways.
|
-- Loop over runways.
|
||||||
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
|
||||||
|
|
||||||
-- 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)
|
||||||
|
|
||||||
-- Debug.
|
-- 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?
|
-- 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
|
||||||
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 active runway based on wind direction.")
|
||||||
end
|
end
|
||||||
|
|
||||||
return runways[iact]
|
return runways[iact]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user