Merge pull request #2142 from FlightControl-Master/FF/MasterDevel

ATIS
This commit is contained in:
Frank 2024-07-01 22:14:49 +02:00 committed by GitHub
commit 7e20a0a0dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 284 additions and 159 deletions

View File

@ -317,18 +317,18 @@
-- atis:Start()
--
-- This uses a male voice with US accent. It requires SRS to be installed in the `D:\DCS\_SRS\` directory. Note that backslashes need to be escaped or simply use slashes (as in linux).
--
-- ### SRS can use multiple frequencies:
--
--
-- ### SRS can use multiple frequencies:
--
-- atis=ATIS:New("Batumi", {305,103.85}, {radio.modulation.AM,radio.modulation.FM})
-- atis:SetSRS("D:\\DCS\\_SRS\\", "male", "en-US")
-- atis:Start()
--
--
-- ### SRS Localization
--
--
-- You can localize the SRS output, all you need is to provide a table of translations and set the `locale` of your instance. You need to provide the translations in your script **before you instantiate your ATIS**.
-- The German localization (already provided in the code) e.g. looks like follows:
--
--
-- ATIS.Messages.DE =
-- {
-- HOURS = "Uhr",
@ -389,13 +389,13 @@
-- FARP = "Farp",
-- DELIMITER = "Komma", -- decimal delimiter
-- }
--
--
-- Then set up your ATIS and set the locale:
--
--
-- atis=ATIS:New("Batumi", 305, radio.modulation.AM)
-- atis:SetSRS("D:\\DCS\\_SRS\\", "female", "de_DE")
-- atis:SetLocale("de") -- available locales from source are "en", "de" and "es"
-- atis:Start()
-- atis:Start()
--
-- ## FARPS
--
@ -497,7 +497,7 @@ ATIS.Alphabet = {
-- @field #number TheChannel -10° (West).
-- @field #number Syria +5° (East).
-- @field #number MarianaIslands +2° (East).
-- @field #number SinaiMao +5° (East).
-- @field #number SinaiMap +5° (East).
ATIS.RunwayM2T = {
Caucasus = 0,
Nevada = 12,
@ -620,6 +620,8 @@ ATIS.ICAOPhraseology = {
-- @field #ATIS.Soundfile VORFrequency
ATIS.Sound = {
ActiveRunway = { filename = "ActiveRunway.ogg", duration = 0.99 },
ActiveRunwayDeparture = { filename = "ActiveRunwayDeparture.ogg", duration = 0.99 },
ActiveRunwayArrival = { filename = "ActiveRunwayArrival.ogg", duration = 0.99 },
AdviceOnInitial = { filename = "AdviceOnInitial.ogg", duration = 3.00 },
Airport = { filename = "Airport.ogg", duration = 0.66 },
Altimeter = { filename = "Altimeter.ogg", duration = 0.68 },
@ -899,6 +901,7 @@ ATIS.version = "1.0.0"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Correct fog for elevation.
-- TODO: Generalize sound files input to be able to use custom made sounds.
-- DONE: Option to add multiple frequencies for SRS
-- DONE: Zulu time --> Zulu in output.
-- DONE: Fix for AB not having a runway - Helopost like Naqoura
@ -1102,6 +1105,52 @@ function ATIS:SetSoundfilesPath( pathMain, pathAirports, pathNato )
return self
end
--- Set the path to the csv file that contains information about the used sound files.
-- The parameter file has to be located on your local disk (**not** inside the miz file).
-- @param #ATIS self
-- @param #string csvfile Full path to the csv file on your local disk.
-- @return #ATIS self
function ATIS:SetSoundfilesInfo( csvfile )
--- Local function to return the ATIS.Soundfile for a given file name
local function getSound(filename)
for key,_soundfile in pairs(self.Sound) do
local soundfile=_soundfile --#ATIS.Soundfile
if filename==soundfile.filename then
return soundfile
end
end
return nil
end
-- Read csv file
local data=UTILS.ReadCSV(csvfile)
if data then
for i,sound in pairs(data) do
-- Get the ATIS.Soundfile
local soundfile=getSound(sound.filename..".ogg") --#ATIS.Soundfile
if soundfile then
-- Set duration
soundfile.duration=tonumber(sound.duration)
else
self:E(string.format("ERROR: Could not get info for sound file %s", sound.filename))
end
end
else
self:E(string.format("ERROR: Could not read sound csv file!"))
end
return self
end
--- Set airborne unit (airplane or helicopter), used to transmit radio messages including subtitles.
-- Best is to place the unit on a parking spot of the airbase and set it to *uncontrolled* in the mission editor.
-- @param #ATIS self
@ -1552,13 +1601,13 @@ end
function ATIS:SetSRS(PathToSRS, Gender, Culture, Voice, Port, GoogleKey)
--if PathToSRS or MSRS.path then
self.useSRS=true
local path = PathToSRS or MSRS.path
local gender = Gender or MSRS.gender
local culture = Culture or MSRS.culture
local voice = Voice or MSRS.voice
local port = Port or MSRS.port or 5002
self.msrs=MSRS:New(path, self.frequency, self.modulation)
self.msrs:SetGender(gender)
self.msrs:SetCulture(culture)
@ -1667,16 +1716,16 @@ function ATIS:onafterStart( From, Event, To )
self.radioqueue:SetRadioPower( self.power )
-- Init numbers.
self.radioqueue:SetDigit( 0, ATIS.Sound.N0.filename, ATIS.Sound.N0.duration, self.soundpath )
self.radioqueue:SetDigit( 1, ATIS.Sound.N1.filename, ATIS.Sound.N1.duration, self.soundpath )
self.radioqueue:SetDigit( 2, ATIS.Sound.N2.filename, ATIS.Sound.N2.duration, self.soundpath )
self.radioqueue:SetDigit( 3, ATIS.Sound.N3.filename, ATIS.Sound.N3.duration, self.soundpath )
self.radioqueue:SetDigit( 4, ATIS.Sound.N4.filename, ATIS.Sound.N4.duration, self.soundpath )
self.radioqueue:SetDigit( 5, ATIS.Sound.N5.filename, ATIS.Sound.N5.duration, self.soundpath )
self.radioqueue:SetDigit( 6, ATIS.Sound.N6.filename, ATIS.Sound.N6.duration, self.soundpath )
self.radioqueue:SetDigit( 7, ATIS.Sound.N7.filename, ATIS.Sound.N7.duration, self.soundpath )
self.radioqueue:SetDigit( 8, ATIS.Sound.N8.filename, ATIS.Sound.N8.duration, self.soundpath )
self.radioqueue:SetDigit( 9, ATIS.Sound.N9.filename, ATIS.Sound.N9.duration, self.soundpath )
self.radioqueue:SetDigit( 0, self.Sound.N0.filename, self.Sound.N0.duration, self.soundpath )
self.radioqueue:SetDigit( 1, self.Sound.N1.filename, self.Sound.N1.duration, self.soundpath )
self.radioqueue:SetDigit( 2, self.Sound.N2.filename, self.Sound.N2.duration, self.soundpath )
self.radioqueue:SetDigit( 3, self.Sound.N3.filename, self.Sound.N3.duration, self.soundpath )
self.radioqueue:SetDigit( 4, self.Sound.N4.filename, self.Sound.N4.duration, self.soundpath )
self.radioqueue:SetDigit( 5, self.Sound.N5.filename, self.Sound.N5.duration, self.soundpath )
self.radioqueue:SetDigit( 6, self.Sound.N6.filename, self.Sound.N6.duration, self.soundpath )
self.radioqueue:SetDigit( 7, self.Sound.N7.filename, self.Sound.N7.duration, self.soundpath )
self.radioqueue:SetDigit( 8, self.Sound.N8.filename, self.Sound.N8.duration, self.soundpath )
self.radioqueue:SetDigit( 9, self.Sound.N9.filename, self.Sound.N9.duration, self.soundpath )
-- Start radio queue.
self.radioqueue:Start( 1, 0.1 )
@ -1923,7 +1972,7 @@ function ATIS:onafterBroadcast( From, Event, To )
--------------------------
--- Sunrise and Sunset ---
--------------------------
local hours = self.gettext:GetEntry("HOURS",self.locale)
local sunrise = coord:GetSunrise()
sunrise = UTILS.Split( sunrise, ":" )
@ -2023,8 +2072,6 @@ function ATIS:onafterBroadcast( From, Event, To )
-- Cloud preset (DCS 2.7)
local cloudspreset = clouds.preset or "Nothing"
env.info("FF cloud preset "..cloudspreset)
-- Precepitation: 0=None, 1=Rain, 2=Thunderstorm, 3=Snow, 4=Snowstorm.
local precepitation = 0
@ -2053,7 +2100,6 @@ function ATIS:onafterBroadcast( From, Event, To )
else
precepitation = 3 -- snow
end
env.info("Fprecipt "..precepitation)
elseif cloudspreset:find( "RainyPreset" ) then
-- Overcast + Rain
clouddens = 9
@ -2061,7 +2107,7 @@ function ATIS:onafterBroadcast( From, Event, To )
precepitation = 1 -- rain
else
precepitation = 3 -- snow
end
end
elseif cloudspreset:find( "Preset10" ) then
-- Scattered 5
clouddens = 4
@ -2166,36 +2212,36 @@ function ATIS:onafterBroadcast( From, Event, To )
-- No cloud info for dynamic weather.
local CloudCover = {} -- #ATIS.Soundfile
CloudCover = ATIS.Sound.CloudsNotAvailable
CloudCover = self.Sound.CloudsNotAvailable
--local CLOUDSsub = "Cloud coverage information not available"
local CLOUDSsub = self.gettext:GetEntry("NOCLOUDINFO",self.locale)
-- Only valid for static weather.
if static then
if clouddens >= 9 then
-- Overcast 9,10
CloudCover = ATIS.Sound.CloudsOvercast
CloudCover = self.Sound.CloudsOvercast
--CLOUDSsub = "Overcast"
CLOUDSsub = self.gettext:GetEntry("OVERCAST",self.locale)
elseif clouddens >= 7 then
-- Broken 7,8
CloudCover = ATIS.Sound.CloudsBroken
CloudCover = self.Sound.CloudsBroken
--CLOUDSsub = "Broken clouds"
CLOUDSsub = self.gettext:GetEntry("BROKEN",self.locale)
elseif clouddens >= 4 then
-- Scattered 4,5,6
CloudCover = ATIS.Sound.CloudsScattered
CloudCover = self.Sound.CloudsScattered
--CLOUDSsub = "Scattered clouds"
CLOUDSsub = self.gettext:GetEntry("SCATTERED",self.locale)
elseif clouddens >= 1 then
-- Few 1,2,3
CloudCover = ATIS.Sound.CloudsFew
CloudCover = self.Sound.CloudsFew
--CLOUDSsub = "Few clouds"
CLOUDSsub = self.gettext:GetEntry("FEWCLOUDS",self.locale)
else
-- No clouds
CLOUDBASE = nil
CLOUDCEIL = nil
CloudCover = ATIS.Sound.CloudsNo
CloudCover = self.Sound.CloudsNo
--CLOUDSsub = "No clouds"
CLOUDSsub = self.gettext:GetEntry("NOCLOUDS",self.locale)
end
@ -2229,7 +2275,7 @@ function ATIS:onafterBroadcast( From, Event, To )
subtitle = string.format( "%s %s", information, NATO )
local _INFORMATION = subtitle
if not self.useSRS then
self:Transmission( ATIS.Sound.Information, 0.5, subtitle )
self:Transmission( self.Sound.Information, 0.5, subtitle )
self.radioqueue:NewTransmission( string.format( "%s.ogg", NATO ), 0.75, self.soundpathNato )
end
alltext = alltext .. ";\n" .. subtitle
@ -2238,7 +2284,7 @@ function ATIS:onafterBroadcast( From, Event, To )
subtitle = string.format( "%s Zulu", ZULU )
if not self.useSRS then
self.radioqueue:Number2Transmission( ZULU, nil, 0.5 )
self:Transmission( ATIS.Sound.Zulu, 0.2, subtitle )
self:Transmission( self.Sound.Zulu, 0.2, subtitle )
end
alltext = alltext .. ";\n" .. subtitle
@ -2249,9 +2295,9 @@ function ATIS:onafterBroadcast( From, Event, To )
--subtitle = string.format( "Sunrise at %s local time", SUNRISE )
subtitle = string.format( sunrise, SUNRISE )
if not self.useSRS then
self:Transmission( ATIS.Sound.SunriseAt, 0.5, subtitle )
self:Transmission( self.Sound.SunriseAt, 0.5, subtitle )
self.radioqueue:Number2Transmission( SUNRISE, nil, 0.2 )
self:Transmission( ATIS.Sound.TimeLocal, 0.2 )
self:Transmission( self.Sound.TimeLocal, 0.2 )
end
alltext = alltext .. ";\n" .. subtitle
@ -2260,9 +2306,9 @@ function ATIS:onafterBroadcast( From, Event, To )
--subtitle = string.format( "Sunset at %s local time", SUNSET )
subtitle = string.format( sunset, SUNSET )
if not self.useSRS then
self:Transmission( ATIS.Sound.SunsetAt, 0.5, subtitle )
self:Transmission( self.Sound.SunsetAt, 0.5, subtitle )
self.radioqueue:Number2Transmission( SUNSET, nil, 0.5 )
self:Transmission( ATIS.Sound.TimeLocal, 0.2 )
self:Transmission( self.Sound.TimeLocal, 0.2 )
end
alltext = alltext .. ";\n" .. subtitle
end
@ -2287,17 +2333,17 @@ function ATIS:onafterBroadcast( From, Event, To )
end
local _WIND = subtitle
if not self.useSRS then
self:Transmission( ATIS.Sound.WindFrom, 1.0, subtitle )
self:Transmission( self.Sound.WindFrom, 1.0, subtitle )
self.radioqueue:Number2Transmission( WINDFROM )
self:Transmission( ATIS.Sound.At, 0.2 )
self:Transmission( self.Sound.At, 0.2 )
self.radioqueue:Number2Transmission( WINDSPEED )
if self.metric then
self:Transmission( ATIS.Sound.MetersPerSecond, 0.2 )
self:Transmission( self.Sound.MetersPerSecond, 0.2 )
else
self:Transmission( ATIS.Sound.Knots, 0.2 )
self:Transmission( self.Sound.Knots, 0.2 )
end
if turbulence > 0 then
self:Transmission( ATIS.Sound.Gusting, 0.2 )
self:Transmission( self.Sound.Gusting, 0.2 )
end
end
alltext = alltext .. ";\n" .. subtitle
@ -2313,12 +2359,12 @@ function ATIS:onafterBroadcast( From, Event, To )
subtitle = string.format( visi, VISIBILITY )
end
if not self.useSRS then
self:Transmission( ATIS.Sound.Visibilty, 1.0, subtitle )
self:Transmission( self.Sound.Visibilty, 1.0, subtitle )
self.radioqueue:Number2Transmission( VISIBILITY )
if self.metric then
self:Transmission( ATIS.Sound.Kilometers, 0.2 )
self:Transmission( self.Sound.Kilometers, 0.2 )
else
self:Transmission( ATIS.Sound.StatuteMiles, 0.2 )
self:Transmission( self.Sound.StatuteMiles, 0.2 )
end
end
alltext = alltext .. ";\n" .. subtitle
@ -2369,21 +2415,21 @@ function ATIS:onafterBroadcast( From, Event, To )
--subtitle = string.format( "Weather phenomena: %s", wpsub )
subtitle = string.format( "%s: %s", phenos, wpsub )
if not self.useSRS then
self:Transmission( ATIS.Sound.WeatherPhenomena, 1.0, subtitle )
self:Transmission( self.Sound.WeatherPhenomena, 1.0, subtitle )
if precepitation == 1 then
self:Transmission( ATIS.Sound.Rain, 0.5 )
self:Transmission( self.Sound.Rain, 0.5 )
elseif precepitation == 2 then
self:Transmission( ATIS.Sound.ThunderStorm, 0.5 )
self:Transmission( self.Sound.ThunderStorm, 0.5 )
elseif precepitation == 3 then
self:Transmission( ATIS.Sound.Snow, 0.5 )
self:Transmission( self.Sound.Snow, 0.5 )
elseif precepitation == 4 then
self:Transmission( ATIS.Sound.SnowStorm, 0.5 )
self:Transmission( self.Sound.SnowStorm, 0.5 )
end
if fog then
self:Transmission( ATIS.Sound.Fog, 0.5 )
self:Transmission( self.Sound.Fog, 0.5 )
end
if dust then
self:Transmission( ATIS.Sound.Dust, 0.5 )
self:Transmission( self.Sound.Dust, 0.5 )
end
end
alltext = alltext .. ";\n" .. subtitle
@ -2409,29 +2455,29 @@ function ATIS:onafterBroadcast( From, Event, To )
subtitle = string.format( cloudbase, cbase, cceil )
end
if not self.useSRS then
self:Transmission( ATIS.Sound.CloudBase, 1.0, subtitle )
self:Transmission( self.Sound.CloudBase, 1.0, subtitle )
if tonumber( CLOUDBASE1000 ) > 0 then
self.radioqueue:Number2Transmission( CLOUDBASE1000 )
self:Transmission( ATIS.Sound.Thousand, 0.1 )
self:Transmission( self.Sound.Thousand, 0.1 )
end
if tonumber( CLOUDBASE0100 ) > 0 then
self.radioqueue:Number2Transmission( CLOUDBASE0100 )
self:Transmission( ATIS.Sound.Hundred, 0.1 )
self:Transmission( self.Sound.Hundred, 0.1 )
end
-- Ceiling
self:Transmission( ATIS.Sound.CloudCeiling, 0.5 )
self:Transmission( self.Sound.CloudCeiling, 0.5 )
if tonumber( CLOUDCEIL1000 ) > 0 then
self.radioqueue:Number2Transmission( CLOUDCEIL1000 )
self:Transmission( ATIS.Sound.Thousand, 0.1 )
self:Transmission( self.Sound.Thousand, 0.1 )
end
if tonumber( CLOUDCEIL0100 ) > 0 then
self.radioqueue:Number2Transmission( CLOUDCEIL0100 )
self:Transmission( ATIS.Sound.Hundred, 0.1 )
self:Transmission( self.Sound.Hundred, 0.1 )
end
if self.metric then
self:Transmission( ATIS.Sound.Meters, 0.1 )
self:Transmission( self.Sound.Meters, 0.1 )
else
self:Transmission( ATIS.Sound.Feet, 0.1 )
self:Transmission( self.Sound.Feet, 0.1 )
end
end
end
@ -2459,15 +2505,15 @@ function ATIS:onafterBroadcast( From, Event, To )
end
local _TEMPERATURE = subtitle
if not self.useSRS then
self:Transmission( ATIS.Sound.Temperature, 1.0, subtitle )
self:Transmission( self.Sound.Temperature, 1.0, subtitle )
if temperature < 0 then
self:Transmission( ATIS.Sound.Minus, 0.2 )
self:Transmission( self.Sound.Minus, 0.2 )
end
self.radioqueue:Number2Transmission( TEMPERATURE )
if self.TDegF then
self:Transmission( ATIS.Sound.DegreesFahrenheit, 0.2 )
self:Transmission( self.Sound.DegreesFahrenheit, 0.2 )
else
self:Transmission( ATIS.Sound.DegreesCelsius, 0.2 )
self:Transmission( self.Sound.DegreesCelsius, 0.2 )
end
end
alltext = alltext .. ";\n" .. subtitle
@ -2493,15 +2539,15 @@ function ATIS:onafterBroadcast( From, Event, To )
end
local _DEWPOINT = subtitle
if not self.useSRS then
self:Transmission( ATIS.Sound.DewPoint, 1.0, subtitle )
self:Transmission( self.Sound.DewPoint, 1.0, subtitle )
if dewpoint < 0 then
self:Transmission( ATIS.Sound.Minus, 0.2 )
self:Transmission( self.Sound.Minus, 0.2 )
end
self.radioqueue:Number2Transmission( DEWPOINT )
if self.TDegF then
self:Transmission( ATIS.Sound.DegreesFahrenheit, 0.2 )
self:Transmission( self.Sound.DegreesFahrenheit, 0.2 )
else
self:Transmission( ATIS.Sound.DegreesCelsius, 0.2 )
self:Transmission( self.Sound.DegreesCelsius, 0.2 )
end
end
alltext = alltext .. ";\n" .. subtitle
@ -2548,33 +2594,33 @@ function ATIS:onafterBroadcast( From, Event, To )
local _ALTIMETER = subtitle
if not self.useSRS then
self:Transmission( ATIS.Sound.Altimeter, 1.0, subtitle )
self:Transmission( self.Sound.Altimeter, 1.0, subtitle )
if not self.qnhonly then
self:Transmission( ATIS.Sound.QNH, 0.5 )
self:Transmission( self.Sound.QNH, 0.5 )
end
self.radioqueue:Number2Transmission( QNH[1] )
if ATIS.ICAOPhraseology[UTILS.GetDCSMap()] then
self:Transmission( ATIS.Sound.Decimal, 0.2 )
self:Transmission( self.Sound.Decimal, 0.2 )
end
self.radioqueue:Number2Transmission( QNH[2] )
if not self.qnhonly then
self:Transmission( ATIS.Sound.QFE, 0.75 )
self:Transmission( self.Sound.QFE, 0.75 )
self.radioqueue:Number2Transmission( QFE[1] )
if ATIS.ICAOPhraseology[UTILS.GetDCSMap()] then
self:Transmission( ATIS.Sound.Decimal, 0.2 )
self:Transmission( self.Sound.Decimal, 0.2 )
end
self.radioqueue:Number2Transmission( QFE[2] )
end
if self.PmmHg then
self:Transmission( ATIS.Sound.MillimetersOfMercury, 0.1 )
self:Transmission( self.Sound.MillimetersOfMercury, 0.1 )
else
if self.metric then
self:Transmission( ATIS.Sound.HectoPascal, 0.1 )
self:Transmission( self.Sound.HectoPascal, 0.1 )
else
self:Transmission( ATIS.Sound.InchesOfMercury, 0.1 )
self:Transmission( self.Sound.InchesOfMercury, 0.1 )
end
end
end
@ -2586,40 +2632,54 @@ function ATIS:onafterBroadcast( From, Event, To )
-- Active runway.
local subtitle = ""
if runwayLanding then
local actrun = self.gettext:GetEntry("ACTIVELANDING",self.locale)
--subtitle=string.format("Active runway landing %s", runwayLanding)
subtitle=string.format("%s %s", actrun, runwayLanding)
if rwyLandingLeft==true then
--subtitle=subtitle.." Left"
subtitle=subtitle.." "..self.gettext:GetEntry("LEFT",self.locale)
elseif rwyLandingLeft==false then
--subtitle=subtitle.." Right"
subtitle=subtitle.." "..self.gettext:GetEntry("RIGHT",self.locale)
end
alltext = alltext .. ";\n" .. subtitle
end
if not self.useSRS then
self:Transmission(self.Sound.ActiveRunwayArrival, 1.0, subtitle)
self.radioqueue:Number2Transmission(runwayLanding)
if rwyLandingLeft==true then
self:Transmission(self.Sound.Left, 0.2)
elseif rwyLandingLeft==false then
self:Transmission(self.Sound.Right, 0.2)
end
end
end
if runwayTakeoff then
local actrun = self.gettext:GetEntry("ACTIVERUN",self.locale)
--subtitle=string.format("Active runway %s", runwayLanding)
subtitle=string.format("%s %s", actrun, runwayTakeoff)
if rwyTakeoffLeft==true then
--subtitle=subtitle.." Left"
subtitle=subtitle.." "..self.gettext:GetEntry("LEFT",self.locale)
elseif rwyTakeoffLeft==false then
--subtitle=subtitle.." Right"
subtitle=subtitle.." "..self.gettext:GetEntry("RIGHT",self.locale)
end
alltext = alltext .. ";\n" .. subtitle
if not self.useSRS then
self:Transmission(self.Sound.ActiveRunwayDeparture, 1.0, subtitle)
self.radioqueue:Number2Transmission(runwayTakeoff)
if rwyTakeoffLeft==true then
self:Transmission(self.Sound.Left, 0.2)
elseif rwyTakeoffLeft==false then
self:Transmission(self.Sound.Right, 0.2)
end
end
end
_RUNACT = subtitle
if not self.useSRS then
self:Transmission(ATIS.Sound.ActiveRunway, 1.0, subtitle)
self.radioqueue:Number2Transmission(runwayLanding)
if rwyLandingLeft==true then
self:Transmission(ATIS.Sound.Left, 0.2)
elseif rwyLandingLeft==false then
self:Transmission(ATIS.Sound.Right, 0.2)
end
end
alltext = alltext .. ";\n" .. subtitle
-- Runway length.
@ -2648,31 +2708,32 @@ function ATIS:onafterBroadcast( From, Event, To )
-- Transmit.
if not self.useSRS then
self:Transmission( ATIS.Sound.RunwayLength, 1.0, subtitle )
self:Transmission( self.Sound.RunwayLength, 1.0, subtitle )
if tonumber( L1000 ) > 0 then
self.radioqueue:Number2Transmission( L1000 )
self:Transmission( ATIS.Sound.Thousand, 0.1 )
self:Transmission( self.Sound.Thousand, 0.1 )
end
if tonumber( L0100 ) > 0 then
self.radioqueue:Number2Transmission( L0100 )
self:Transmission( ATIS.Sound.Hundred, 0.1 )
self:Transmission( self.Sound.Hundred, 0.1 )
end
if self.metric then
self:Transmission( ATIS.Sound.Meters, 0.1 )
self:Transmission( self.Sound.Meters, 0.1 )
else
self:Transmission( ATIS.Sound.Feet, 0.1 )
self:Transmission( self.Sound.Feet, 0.1 )
end
end
alltext = alltext .. ";\n" .. subtitle
end
end
-- Airfield elevation
if self.elevation then
local elev = self.gettext:GetEntry("ELEVATION",self.locale)
local meters = self.gettext:GetEntry("METERS",self.locale)
local feet = self.gettext:GetEntry("FEET",self.locale)
local elevation = self.airbase:GetHeight()
if not self.metric then
elevation = UTILS.MetersToFeet( elevation )
@ -2692,19 +2753,19 @@ function ATIS:onafterBroadcast( From, Event, To )
-- Transmit.
if not self.useSRS then
self:Transmission( ATIS.Sound.Elevation, 1.0, subtitle )
self:Transmission( self.Sound.Elevation, 1.0, subtitle )
if tonumber( L1000 ) > 0 then
self.radioqueue:Number2Transmission( L1000 )
self:Transmission( ATIS.Sound.Thousand, 0.1 )
self:Transmission( self.Sound.Thousand, 0.1 )
end
if tonumber( L0100 ) > 0 then
self.radioqueue:Number2Transmission( L0100 )
self:Transmission( ATIS.Sound.Hundred, 0.1 )
self:Transmission( self.Sound.Hundred, 0.1 )
end
if self.metric then
self:Transmission( ATIS.Sound.Meters, 0.1 )
self:Transmission( self.Sound.Meters, 0.1 )
else
self:Transmission( ATIS.Sound.Feet, 0.1 )
self:Transmission( self.Sound.Feet, 0.1 )
end
end
alltext = alltext .. ";\n" .. subtitle
@ -2723,16 +2784,16 @@ function ATIS:onafterBroadcast( From, Event, To )
--subtitle = string.format( "Tower frequency %s", freqs )
subtitle = string.format( "%s %s", twrfrq, freqs )
if not self.useSRS then
self:Transmission( ATIS.Sound.TowerFrequency, 1.0, subtitle )
self:Transmission( self.Sound.TowerFrequency, 1.0, subtitle )
for _, freq in pairs( self.towerfrequency ) do
local f = string.format( "%.3f", freq )
f = UTILS.Split( f, "." )
self.radioqueue:Number2Transmission( f[1], nil, 0.5 )
if tonumber( f[2] ) > 0 then
self:Transmission( ATIS.Sound.Decimal, 0.2 )
self:Transmission( self.Sound.Decimal, 0.2 )
self.radioqueue:Number2Transmission( f[2] )
end
self:Transmission( ATIS.Sound.MegaHertz, 0.2 )
self:Transmission( self.Sound.MegaHertz, 0.2 )
end
end
alltext = alltext .. ";\n" .. subtitle
@ -2745,15 +2806,15 @@ function ATIS:onafterBroadcast( From, Event, To )
--subtitle = string.format( "ILS frequency %.2f MHz", ils.frequency )
subtitle = string.format( "%s %.2f MHz", ilstxt, ils.frequency )
if not self.useSRS then
self:Transmission( ATIS.Sound.ILSFrequency, 1.0, subtitle )
self:Transmission( self.Sound.ILSFrequency, 1.0, subtitle )
local f = string.format( "%.2f", ils.frequency )
f = UTILS.Split( f, "." )
self.radioqueue:Number2Transmission( f[1], nil, 0.5 )
if tonumber( f[2] ) > 0 then
self:Transmission( ATIS.Sound.Decimal, 0.2 )
self:Transmission( self.Sound.Decimal, 0.2 )
self.radioqueue:Number2Transmission( f[2] )
end
self:Transmission( ATIS.Sound.MegaHertz, 0.2 )
self:Transmission( self.Sound.MegaHertz, 0.2 )
end
alltext = alltext .. ";\n" .. subtitle
end
@ -2765,15 +2826,15 @@ function ATIS:onafterBroadcast( From, Event, To )
--subtitle = string.format( "Outer NDB frequency %.2f MHz", ndb.frequency )
subtitle = string.format( "%s %.2f MHz", ndbtxt, ndb.frequency )
if not self.useSRS then
self:Transmission( ATIS.Sound.OuterNDBFrequency, 1.0, subtitle )
self:Transmission( self.Sound.OuterNDBFrequency, 1.0, subtitle )
local f = string.format( "%.2f", ndb.frequency )
f = UTILS.Split( f, "." )
self.radioqueue:Number2Transmission( f[1], nil, 0.5 )
if tonumber( f[2] ) > 0 then
self:Transmission( ATIS.Sound.Decimal, 0.2 )
self:Transmission( self.Sound.Decimal, 0.2 )
self.radioqueue:Number2Transmission( f[2] )
end
self:Transmission( ATIS.Sound.MegaHertz, 0.2 )
self:Transmission( self.Sound.MegaHertz, 0.2 )
end
alltext = alltext .. ";\n" .. subtitle
end
@ -2785,15 +2846,15 @@ function ATIS:onafterBroadcast( From, Event, To )
--subtitle = string.format( "Inner NDB frequency %.2f MHz", ndb.frequency )
subtitle = string.format( "%s %.2f MHz", ndbtxt, ndb.frequency )
if not self.useSRS then
self:Transmission( ATIS.Sound.InnerNDBFrequency, 1.0, subtitle )
self:Transmission( self.Sound.InnerNDBFrequency, 1.0, subtitle )
local f = string.format( "%.2f", ndb.frequency )
f = UTILS.Split( f, "." )
self.radioqueue:Number2Transmission( f[1], nil, 0.5 )
if tonumber( f[2] ) > 0 then
self:Transmission( ATIS.Sound.Decimal, 0.2 )
self:Transmission( self.Sound.Decimal, 0.2 )
self.radioqueue:Number2Transmission( f[2] )
end
self:Transmission( ATIS.Sound.MegaHertz, 0.2 )
self:Transmission( self.Sound.MegaHertz, 0.2 )
end
alltext = alltext .. ";\n" .. subtitle
end
@ -2809,15 +2870,15 @@ function ATIS:onafterBroadcast( From, Event, To )
subtitle = string.format( "%s %.2f MHz", vorttstxt, self.vor )
end
if not self.useSRS then
self:Transmission( ATIS.Sound.VORFrequency, 1.0, subtitle )
self:Transmission( self.Sound.VORFrequency, 1.0, subtitle )
local f = string.format( "%.2f", self.vor )
f = UTILS.Split( f, "." )
self.radioqueue:Number2Transmission( f[1], nil, 0.5 )
if tonumber( f[2] ) > 0 then
self:Transmission( ATIS.Sound.Decimal, 0.2 )
self:Transmission( self.Sound.Decimal, 0.2 )
self.radioqueue:Number2Transmission( f[2] )
end
self:Transmission( ATIS.Sound.MegaHertz, 0.2 )
self:Transmission( self.Sound.MegaHertz, 0.2 )
end
alltext = alltext .. ";\n" .. subtitle
end
@ -2828,7 +2889,7 @@ function ATIS:onafterBroadcast( From, Event, To )
--subtitle=string.format("TACAN channel %dX Ray", self.tacan)
subtitle=string.format(tactxt, self.tacan)
if not self.useSRS then
self:Transmission( ATIS.Sound.TACANChannel, 1.0, subtitle )
self:Transmission( self.Sound.TACANChannel, 1.0, subtitle )
self.radioqueue:Number2Transmission( tostring( self.tacan ), nil, 0.2 )
self.radioqueue:NewTransmission( "Xray.ogg", 0.75, self.soundpathNato, nil, 0.2 )
end
@ -2841,7 +2902,7 @@ function ATIS:onafterBroadcast( From, Event, To )
--subtitle = string.format( "RSBN channel %d", self.rsbn )
subtitle = string.format( "%s %d", rsbntxt, self.rsbn )
if not self.useSRS then
self:Transmission( ATIS.Sound.RSBNChannel, 1.0, subtitle )
self:Transmission( self.Sound.RSBNChannel, 1.0, subtitle )
self.radioqueue:Number2Transmission( tostring( self.rsbn ), nil, 0.2 )
end
alltext = alltext .. ";\n" .. subtitle
@ -2854,7 +2915,7 @@ function ATIS:onafterBroadcast( From, Event, To )
--subtitle = string.format( "PRMG channel %d", ndb.frequency )
subtitle = string.format( "%s %d", prmtxt, ndb.frequency )
if not self.useSRS then
self:Transmission( ATIS.Sound.PRMGChannel, 1.0, subtitle )
self:Transmission( self.Sound.PRMGChannel, 1.0, subtitle )
self.radioqueue:Number2Transmission( tostring( ndb.frequency ), nil, 0.5 )
end
alltext = alltext .. ";\n" .. subtitle
@ -2870,7 +2931,7 @@ function ATIS:onafterBroadcast( From, Event, To )
--subtitle = string.format( "Advise on initial contact, you have information %s", NATO )
subtitle = string.format( "%s %s", advtxt, NATO )
if not self.useSRS then
self:Transmission( ATIS.Sound.AdviceOnInitial, 0.5, subtitle )
self:Transmission( self.Sound.AdviceOnInitial, 0.5, subtitle )
self.radioqueue:NewTransmission( string.format( "%s.ogg", NATO ), 0.75, self.soundpathNato )
end
alltext = alltext .. ";\n" .. subtitle
@ -2910,8 +2971,8 @@ function ATIS:onafterReport( From, Event, To, Text )
local emes = self.gettext:GetEntry("METERSPER",self.locale)
local tacan = self.gettext:GetEntry("TACAN",self.locale)
local farp = self.gettext:GetEntry("FARP",self.locale)
local text = string.gsub( text, "SM", statute )
text = string.gsub( text, "°C", degc )
text = string.gsub( text, "°F", degf )
@ -2921,13 +2982,13 @@ function ATIS:onafterReport( From, Event, To, Text )
text = string.gsub( text, "m/s", emes )
text = string.gsub( text, "TACAN", tacan )
text = string.gsub( text, "FARP", farp )
local delimiter = self.gettext:GetEntry("DELIMITER",self.locale)
if string.lower(self.locale) ~= "en" then
text = string.gsub(text,"(%d+)(%.)(%d+)","%1 "..delimiter.." %3")
end
-- Replace ";" by "."
local text = string.gsub( text, ";", " . " )

View File

@ -268,7 +268,7 @@ function RADIOQUEUE:NewTransmission(filename, duration, path, tstart, interval,
return nil
end
if type(duration)~="number" then
self:E(self.lid.."ERROR: Duration specified is NOT a number.")
self:E(self.lid..string.format("ERROR: Duration specified is NOT a number but type=%s. Filename=%s, duration=%s", type(duration), tostring(filename), tostring(duration)))
return nil
end
@ -361,6 +361,7 @@ end
-- @param #RADIOQUEUE self
-- @param #RADIOQUEUE.Transmission transmission The transmission.
function RADIOQUEUE:Broadcast(transmission)
self:T("Broarcast")
if ((transmission.soundfile and transmission.soundfile.useSRS) or transmission.soundtext) and self.msrs then
self:_BroadcastSRS(transmission)
@ -425,7 +426,7 @@ function RADIOQUEUE:Broadcast(transmission)
else
-- Broadcasting from carrier. No subtitle possible. Need to send messages to players.
self:T(self.lid..string.format("Broadcasting via trigger.action.radioTransmission()."))
self:T(self.lid..string.format("Broadcasting via trigger.action.radioTransmission()"))
-- Position from where to transmit.
local vec3=nil
@ -453,6 +454,8 @@ function RADIOQUEUE:Broadcast(transmission)
local text=string.format("file=%s, freq=%.2f MHz, duration=%.2f sec, subtitle=%s", filename, self.frequency/1000000, transmission.duration, transmission.subtitle or "")
MESSAGE:New(string.format(text, filename, transmission.duration, transmission.subtitle or ""), 5, "RADIOQUEUE "..self.alias):ToAll()
end
else
self:E("ERROR: Could not get vec3 to determin transmission origin! Did you specify a sender and is it still alive?")
end
end
@ -482,7 +485,6 @@ end
--- Check radio queue for transmissions to be broadcasted.
-- @param #RADIOQUEUE self
function RADIOQUEUE:_CheckRadioQueue()
--env.info("FF check radio queue "..self.alias)
-- Check if queue is empty.
if #self.queue==0 then

View File

@ -160,7 +160,7 @@ do -- Sound File
-- @param #string FileName The name of the sound file, e.g. "Hello World.ogg".
-- @param #string Path The path of the directory, where the sound file is located. Default is "l10n/DEFAULT/" within the miz file.
-- @param #number Duration Duration in seconds, how long it takes to play the sound file. Default is 3 seconds.
-- @param #bolean UseSrs Set if SRS should be used to play this file. Default is false.
-- @param #boolean UseSrs Set if SRS should be used to play this file. Default is false.
-- @return #SOUNDFILE self
function SOUNDFILE:New(FileName, Path, Duration, UseSrs)
@ -249,6 +249,9 @@ do -- Sound File
-- @param #string Duration Duration in seconds. Default 3 seconds.
-- @return #SOUNDFILE self
function SOUNDFILE:SetDuration(Duration)
if Duration and type(Duration)=="string" then
Duration=tonumber(Duration)
end
self.duration=Duration or 3
return self
end

View File

@ -3196,7 +3196,7 @@ end
-- @param #table Table The table.
-- @param #table Object The object to check.
-- @param #string Key (Optional) Key to check. By default, the object itself is checked.
-- @return #booolen Returns `true` if object is in table.
-- @return #boolean Returns `true` if object is in table.
function UTILS.IsInTable(Table, Object, Key)
for key, object in pairs(Table) do
@ -3218,7 +3218,7 @@ end
-- @param #table Table The table.
-- @param #table Objects The objects to check.
-- @param #string Key (Optional) Key to check.
-- @return #booolen Returns `true` if object is in table.
-- @return #boolean Returns `true` if object is in table.
function UTILS.IsAnyInTable(Table, Objects, Key)
for _,Object in pairs(UTILS.EnsureTable(Objects)) do
@ -3366,14 +3366,14 @@ end
--- Checks if the current time is in between start_time and end_time
-- @param #string time_string_01 Time string like "07:15:22"
-- @param #string time_string_02 Time string like "08:11:27"
-- @return #bool True if it is, False if it's not
-- @return #boolean True if it is, False if it's not
function UTILS.TimeBetween(start_time, end_time)
return UTILS.TimeLaterThan(start_time) and UTILS.TimeBefore(end_time)
end
--- Easy to read one line to roll the dice on something. 1% is very unlikely to happen, 99% is very likely to happen
-- @param #number chance (optional) Percentage chance you want something to happen. Defaults to a random number if not given
-- @return #bool True if the dice roll was within the given percentage chance of happening
-- @return #boolean True if the dice roll was within the given percentage chance of happening
function UTILS.PercentageChance(chance)
chance = chance or math.random(0, 100)
chance = UTILS.Clamp(chance, 0, 100)
@ -3426,10 +3426,10 @@ function UTILS.RemapValue(value, old_min, old_max, new_min, new_max)
end
--- Given a triangle made out of 3 vector 2s, return a vec2 that is a random number in this triangle
-- @param #Vec2 pt1 Min value to remap from
-- @param #Vec2 pt2 Max value to remap from
-- @param #Vec2 pt3 Max value to remap from
-- @return #Vec2 Random point in triangle
-- @param DCS#Vec2 pt1 Min value to remap from
-- @param DCS#Vec2 pt2 Max value to remap from
-- @param DCS#Vec2 pt3 Max value to remap from
-- @return DCS#Vec2 Random point in triangle
function UTILS.RandomPointInTriangle(pt1, pt2, pt3)
local pt = {math.random(), math.random()}
table.sort(pt)
@ -3447,7 +3447,7 @@ end
-- @param #number angle Min value to remap from
-- @param #number min Max value to remap from
-- @param #number max Max value to remap from
-- @return #bool
-- @return #boolean
function UTILS.AngleBetween(angle, min, max)
angle = (360 + (angle % 360)) % 360
min = (360 + min % 360) % 360
@ -3507,10 +3507,10 @@ end
--- Rotates a point around another point with a given angle. Useful if you're loading in groups or
--- statics but you want to rotate them all as a collection. You can get the center point of everything
--- and then rotate all the positions of every object around this center point.
-- @param #Vec2 point Point that you want to rotate
-- @param #Vec2 pivot Pivot point of the rotation
-- @param DCS#Vec2 point Point that you want to rotate
-- @param DCS#Vec2 pivot Pivot point of the rotation
-- @param #number angle How many degrees the point should be rotated
-- @return #Vec Rotated point
-- @return DCS#Vec2 Rotated point
function UTILS.RotatePointAroundPivot(point, pivot, angle)
local radians = math.rad(angle)
@ -3542,7 +3542,7 @@ end
--- Check if a string starts with something
-- @param #string str String to check
-- @param #string value
-- @return #bool True if str starts with value
-- @return #boolean True if str starts with value
function string.startswith(str, value)
return string.sub(str,1,string.len(value)) == value
end
@ -3551,7 +3551,7 @@ end
--- Check if a string ends with something
-- @param #string str String to check
-- @param #string value
-- @return #bool True if str ends with value
-- @return #boolean True if str ends with value
function string.endswith(str, value)
return value == "" or str:sub(-#value) == value
end
@ -3574,16 +3574,16 @@ end
--- string.split("hello_dcs_world", "-") would return {"hello", "dcs", "world"}
-- @param #string str
-- @param #string value
-- @return #bool True if str contains value
-- @return #boolean True if str contains value
function string.contains(str, value)
return string.match(str, value)
end
--- Moves an object from one table to another
-- @param #obj object to move
-- @param #from_table table to move from
-- @param #to_table table to move to
-- @param #table obj object to move
-- @param #table from_table table to move from
-- @param #table to_table table to move to
function table.move_object(obj, from_table, to_table)
local index
for i, v in pairs(from_table) do
@ -3602,7 +3602,7 @@ end
--- The table can be made up out of complex tables or values as well
-- @param #table tbl
-- @param #string element
-- @return #bool True if tbl contains element
-- @return #boolean True if tbl contains element
function table.contains(tbl, element)
if element == nil or tbl == nil then return false end
@ -3619,7 +3619,7 @@ end
--- Checks if a table contains a specific key.
-- @param #table tbl Table to check
-- @param #string key Key to look for
-- @return #bool True if tbl contains key
-- @return #boolean True if tbl contains key
function table.contains_key(tbl, key)
if tbl[key] ~= nil then return true else return false end
end
@ -3666,7 +3666,7 @@ end
--- Finds the index of an element in a table.
-- @param #table table Table to search
-- @param #string element Element to find
-- @return #int Index of the element, or nil if not found
-- @return #number Index of the element, or nil if not found
function table.index_of(table, element)
for i, v in ipairs(table) do
if v == element then
@ -3678,7 +3678,7 @@ end
--- Counts the number of elements in a table.
-- @param #table T Table to count
-- @return #int Number of elements in the table
-- @return #number Number of elements in the table
function table.length(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
@ -3687,8 +3687,8 @@ end
--- Slices a table between two indices, much like Python's my_list[2:-1]
-- @param #table tbl Table to slice
-- @param #int first Starting index
-- @param #int last Ending index
-- @param #number first Starting index
-- @param #number last Ending index
-- @return #table Sliced table
function table.slice(tbl, first, last)
local sliced = {}
@ -3709,7 +3709,7 @@ end
--- Counts the number of occurrences of a value in a table.
-- @param #table tbl Table to search
-- @param #string value Value to count
-- @return #int Number of occurrences of the value
-- @return #number Number of occurrences of the value
function table.count_value(tbl, value)
local count = 0
for _, item in pairs(tbl) do
@ -3990,3 +3990,62 @@ function UTILS.MGRSStringToSRSFriendly(Text,Slow)
Text = "MGRS;"..Text
return Text
end
--- Read csv file and convert it to a lua table.
-- The csv must have a header specifing the names of the columns. The column names are used as table keys.
-- @param #string filename File name including full path on local disk.
-- @return #table The table filled with data from the csv file.
function UTILS.ReadCSV(filename)
if not UTILS.FileExists(filename) then
env.error("File does not exist")
return nil
end
--- Function that load data from a file.
local function _loadfile( filename )
local f = io.open( filename, "rb" )
if f then
local data = f:read( "*all" )
f:close()
return data
else
BASE:E(string.format( "WARNING: Could read data from file %s!", tostring( filename ) ) )
return nil
end
end
-- Load asset data from file.
local data = _loadfile( filename )
local lines=UTILS.Split(data, "\n" )
-- Remove carriage returns from end of lines
for _,line in pairs(lines) do
line=string.gsub(line, "[\n\r]","")
end
local sep=";"
local columns=UTILS.Split(lines[1], sep)
-- Remove header line.
table.remove(lines, 1)
local csvdata={}
for i, line in pairs(lines) do
line=string.gsub(line, "[\n\r]","")
local row={}
for j, value in pairs(UTILS.Split(line, sep)) do
local key=string.gsub(columns[j], "[\n\r]","")
row[key]=value
end
table.insert(csvdata, row)
end
return csvdata
end