mirror of
https://github.com/weyne85/DCS-ExportScripts.git
synced 2025-10-29 16:58:18 +00:00
updated F-16, F-5, P-51D, Mosquito, AH-64D, F-86F Sabre, UH-1H Huey with 8000 series
added some radios for huey and f5. added crew status for huey.
This commit is contained in:
parent
e9979166f0
commit
74f78669ae
@ -1,4 +1,9 @@
|
|||||||
-- AH64D_BLK_II
|
-- AH64D_BLK_II
|
||||||
|
-- https://github.com/asherao/DCS-ExportScripts
|
||||||
|
|
||||||
|
local base = _G -- game information
|
||||||
|
local os = base.os -- time
|
||||||
|
local Terrain = require('terrain') -- map info
|
||||||
|
|
||||||
ExportScript.FoundDCSModule = true
|
ExportScript.FoundDCSModule = true
|
||||||
ExportScript.Version.AH64D_BLK_II = "1.2.1"
|
ExportScript.Version.AH64D_BLK_II = "1.2.1"
|
||||||
@ -716,30 +721,9 @@ ExportScript.ConfigArguments =
|
|||||||
|
|
||||||
-- Pointed to by ProcessIkarusDCSHighImportance
|
-- Pointed to by ProcessIkarusDCSHighImportance
|
||||||
function ExportScript.ProcessIkarusDCSConfigHighImportance(mainPanelDevice)
|
function ExportScript.ProcessIkarusDCSConfigHighImportance(mainPanelDevice)
|
||||||
--[[
|
|
||||||
every frame export to Ikarus
|
|
||||||
Example from A-10C
|
|
||||||
Get Radio Frequencies
|
|
||||||
get data from device
|
|
||||||
local lUHFRadio = GetDevice(54)
|
|
||||||
ExportScript.Tools.SendData("ExportID", "Format")
|
|
||||||
ExportScript.Tools.SendData(2000, string.format("%7.3f", lUHFRadio:get_frequency()/1000000)) -- <- special function for get frequency data
|
|
||||||
ExportScript.Tools.SendData(2000, ExportScript.Tools.RoundFreqeuncy((UHF_RADIO:get_frequency()/1000000))) -- ExportScript.Tools.RoundFreqeuncy(frequency (MHz|KHz), format ("7.3"), PrefixZeros (false), LeastValue (0.025))
|
|
||||||
]]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function ExportScript.ProcessDACConfigHighImportance(mainPanelDevice)
|
function ExportScript.ProcessDACConfigHighImportance(mainPanelDevice)
|
||||||
--[[
|
|
||||||
every frame export to DAC
|
|
||||||
Example from A-10C
|
|
||||||
Get Radio Frequencies
|
|
||||||
get data from device
|
|
||||||
local UHF_RADIO = GetDevice(54)
|
|
||||||
ExportScript.Tools.SendDataDAC("ExportID", "Format")
|
|
||||||
ExportScript.Tools.SendDataDAC("ExportID", "Format", HardwareConfigID)
|
|
||||||
ExportScript.Tools.SendDataDAC("2000", string.format("%7.3f", UHF_RADIO:get_frequency()/1000000))
|
|
||||||
ExportScript.Tools.SendDataDAC("2000", ExportScript.Tools.RoundFreqeuncy((UHF_RADIO:get_frequency()/1000000))) -- ExportScript.Tools.RoundFreqeuncy(frequency (MHz|KHz), format ("7.3"), PrefixZeros (false), LeastValue (0.025))
|
|
||||||
]]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
@ -749,34 +733,28 @@ end
|
|||||||
|
|
||||||
-- Pointed to by ExportScript.ProcessIkarusDCSConfigLowImportance
|
-- Pointed to by ExportScript.ProcessIkarusDCSConfigLowImportance
|
||||||
function ExportScript.ProcessIkarusDCSConfigLowImportance(mainPanelDevice)
|
function ExportScript.ProcessIkarusDCSConfigLowImportance(mainPanelDevice)
|
||||||
--[[
|
|
||||||
export in low tick interval to Ikarus
|
|
||||||
Example from A-10C
|
|
||||||
Get Radio Frequencies
|
|
||||||
get data from device
|
|
||||||
local lUHFRadio = GetDevice(54)
|
|
||||||
ExportScript.Tools.SendData("ExportID", "Format")
|
|
||||||
ExportScript.Tools.SendData(2000, string.format("%7.3f", lUHFRadio:get_frequency()/1000000)) -- <- special function for get frequency data
|
|
||||||
ExportScript.Tools.SendData(2000, ExportScript.Tools.RoundFreqeuncy((UHF_RADIO:get_frequency()/1000000))) -- ExportScript.Tools.RoundFreqeuncy(frequency (MHz|KHz), format ("7.3"), PrefixZeros (false), LeastValue (0.025))
|
|
||||||
]]
|
|
||||||
|
|
||||||
ExportScript.CountermeasureReadouts(mainPanelDevice)
|
ExportScript.CountermeasureReadouts(mainPanelDevice)
|
||||||
|
--ExportScript.MfdReadouts(mainPanelDevice) --Testing in progress
|
||||||
|
--ExportScript.TSD(mainPanelDevice) -- Disabled: see note in Function
|
||||||
|
|
||||||
|
if LoIsObjectExportAllowed() then -- returns true if world objects data is available
|
||||||
|
if LoIsOwnshipExportAllowed() then -- returns true if ownship data is available
|
||||||
|
ExportScript.LoAircraftInfo(mainPanelDevice) -- Provides a lot of aircraft properties
|
||||||
|
ExportScript.AirportInfo(mainPanelDevice) -- Provides info on the two closest airports
|
||||||
|
ExportScript.WindsAloft(mainPanelDevice) -- Gets winds at the aircraft
|
||||||
|
ExportScript.GroundRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
|
ExportScript.AirRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
|
ExportScript.IglaHunter(mainPanelDevice) -- Locates closest Igla (Use in Single Player)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function ExportScript.ProcessDACConfigLowImportance(mainPanelDevice)
|
function ExportScript.ProcessDACConfigLowImportance(mainPanelDevice)
|
||||||
--[[
|
|
||||||
export in low tick interval to DAC
|
|
||||||
Example from A-10C
|
|
||||||
Get Radio Frequencies
|
|
||||||
get data from device
|
|
||||||
local UHF_RADIO = GetDevice(54)
|
|
||||||
ExportScript.Tools.SendDataDAC("ExportID", "Format")
|
|
||||||
ExportScript.Tools.SendDataDAC("ExportID", "Format", HardwareConfigID)
|
|
||||||
ExportScript.Tools.SendDataDAC("2000", string.format("%7.3f", UHF_RADIO:get_frequency()/1000000))
|
|
||||||
ExportScript.Tools.SendDataDAC("2000", ExportScript.Tools.RoundFreqeuncy((UHF_RADIO:get_frequency()/1000000))) -- ExportScript.Tools.RoundFreqeuncy(frequency (MHz|KHz), format ("7.3"), PrefixZeros (false), LeastValue (0.025))
|
|
||||||
]]
|
|
||||||
|
|
||||||
--=====================================================================================
|
--=====================================================================================
|
||||||
|
ExportScript.Tools.WriteToLog('CMSP ')
|
||||||
--[[
|
--[[
|
||||||
ExportScript.Tools.WriteToLog('list_cockpit_params(): '..ExportScript.Tools.dump(list_cockpit_params()))
|
ExportScript.Tools.WriteToLog('list_cockpit_params(): '..ExportScript.Tools.dump(list_cockpit_params()))
|
||||||
ExportScript.Tools.WriteToLog('CMSP: '..ExportScript.Tools.dump(list_indication(7)))
|
ExportScript.Tools.WriteToLog('CMSP: '..ExportScript.Tools.dump(list_indication(7)))
|
||||||
@ -803,10 +781,11 @@ end
|
|||||||
-- Custom functions --
|
-- Custom functions --
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
-------------------------------------
|
||||||
|
--- Apache Flare and Chaff Counts ---
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
function ExportScript.CountermeasureReadouts(mainPanelDevice)
|
function ExportScript.CountermeasureReadouts(mainPanelDevice)
|
||||||
-------------------------------------
|
|
||||||
--- Apache Flare and Chaff Counts ---
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
local CmwsInfo_24 = ExportScript.Tools.split(list_indication(24), "%c")--this contains the formated table of the kneeboard
|
local CmwsInfo_24 = ExportScript.Tools.split(list_indication(24), "%c")--this contains the formated table of the kneeboard
|
||||||
|
|
||||||
@ -834,4 +813,838 @@ function ExportScript.CountermeasureReadouts(mainPanelDevice)
|
|||||||
ExportScript.Tools.SendData(3004, string.format("F " .. txt_FLARES_Count .. "\nC " .. txt_CHAFFS_Count))
|
ExportScript.Tools.SendData(3004, string.format("F " .. txt_FLARES_Count .. "\nC " .. txt_CHAFFS_Count))
|
||||||
ExportScript.Tools.SendData(3005, string.format("FLARE\n" .. txt_FLARES_Count))
|
ExportScript.Tools.SendData(3005, string.format("FLARE\n" .. txt_FLARES_Count))
|
||||||
ExportScript.Tools.SendData(3006, string.format("CHAFF\n" .. txt_CHAFFS_Count))
|
ExportScript.Tools.SendData(3006, string.format("CHAFF\n" .. txt_CHAFFS_Count))
|
||||||
|
ExportScript.Tools.SendData(3999, string.format(ExportScript.Tools.dump(CmwsInfo_24)))
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
-- Apache MFD Readouts --
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
function ExportScript.MfdReadouts(mainPanelDevice)
|
||||||
|
--[[ This can be tested by creating three "Momentary Button/Displays"
|
||||||
|
-- Change the Title Text Change on DCS Update Settings DCS ID to 5000, 5001, and 5002.
|
||||||
|
-- When in cockpit the values will populate.
|
||||||
|
-- Press the FCR, WPN, and TSD buttons to see them change.
|
||||||
|
-- You can remove this comment from your code.]]
|
||||||
|
|
||||||
|
--this contains the formated table of the Pilot Left MFD
|
||||||
|
local MfdPltLeftInfo_6 = ExportScript.Tools.split(list_indication(6), "%c")
|
||||||
|
|
||||||
|
-- init the names of the containers for the variables
|
||||||
|
local button_T1
|
||||||
|
local button_T2
|
||||||
|
|
||||||
|
for k,v in pairs(MfdPltLeftInfo_6) do -- start searching through the list_indication
|
||||||
|
|
||||||
|
if v == "PB1_1" then -- reference the list_indication to get the correct entry
|
||||||
|
button_T1 = MfdPltLeftInfo_6[k+1]
|
||||||
|
end
|
||||||
|
|
||||||
|
if v == "PB2_3" or v == "PB2_1" then -- this one seems to change depending on the screen...
|
||||||
|
button_T2 = MfdPltLeftInfo_6[k+1]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- if a value was not present, it wasn't populated
|
||||||
|
-- fill it with something else to indicate that to the user
|
||||||
|
-- otherwise, keep its value
|
||||||
|
-- Don't forget to add the NilOrEmpty() function in the General Helper Functions section
|
||||||
|
button_T1 = NilOrEmpty(button_T1)
|
||||||
|
button_T2 = NilOrEmpty(button_T2)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(5000, string.format(button_T1))
|
||||||
|
ExportScript.Tools.SendData(5001, string.format(button_T2))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
-- Apache TSD Info --
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
function ExportScript.TSD(mainPanelDevice)
|
||||||
|
-- Note: Unfortunately, this info does not update unless the TSD is visible.
|
||||||
|
-- Therefore, implementation of this fucntion is on hold.
|
||||||
|
|
||||||
|
local list_indication_8 = ExportScript.Tools.split(list_indication(8), "%c")--this contains the formated table of the kneeboard
|
||||||
|
|
||||||
|
for k,v in pairs(list_indication_8) do
|
||||||
|
if v == "NextWaypointStatusWindow_text_1" then
|
||||||
|
NextWptReadout1 = list_indication_8[k+1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for k,v in pairs(list_indication_8) do
|
||||||
|
if v == "NextWaypointStatusWindow_text_2" then
|
||||||
|
NextWptReadout2 = list_indication_8[k+1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for k,v in pairs(list_indication_8) do
|
||||||
|
if v == "NextWaypointStatusWindow_text_3" then
|
||||||
|
NextWptReadout3 = list_indication_8[k+1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for k,v in pairs(list_indication_8) do
|
||||||
|
if v == "NextWaypointStatusWindow_text_4" then
|
||||||
|
NextWptReadout4 = list_indication_8[k+1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: Debug endurance readout
|
||||||
|
-- possible issue may be due to the colon in string
|
||||||
|
for k,v in pairs(list_indication_8) do
|
||||||
|
if v == "EnduranceStatusWindow_text_1" then
|
||||||
|
Endurance = list_indication_8[k+1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for k,v in pairs(list_indication_8) do
|
||||||
|
if v == "WindStatusWindow_CALM_text" then
|
||||||
|
WindStatus = list_indication_8[k+1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
NextWptReadout1 = trim(NextWptReadout1)
|
||||||
|
NextWptReadout2 = trim(NextWptReadout2)
|
||||||
|
NextWptReadout3 = trim(NextWptReadout3)
|
||||||
|
NextWptReadout4 = trim(NextWptReadout4)
|
||||||
|
Endurance = trim(Endurance)
|
||||||
|
WindStatus = trim(WindStatus)
|
||||||
|
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(3007, string.format(NextWptReadout1))
|
||||||
|
ExportScript.Tools.SendData(3008, string.format(NextWptReadout2))
|
||||||
|
ExportScript.Tools.SendData(3009, string.format(NextWptReadout3))
|
||||||
|
ExportScript.Tools.SendData(3010, string.format(NextWptReadout4))
|
||||||
|
ExportScript.Tools.SendData(3011, string.format(Endurance))
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.LoAircraftInfo(mainPanelDevice)
|
||||||
|
|
||||||
|
-- General
|
||||||
|
local aircraftName = LoGetSelfData().Name -- DCS Name of the aircraft eg "F-5E-3"
|
||||||
|
local pilotName = LoGetPilotName() -- Logbook Pilot name
|
||||||
|
|
||||||
|
-- Times DCS times are default in seconds
|
||||||
|
local dcsModelTime = LoGetModelTime() -- time since aircraft spawn
|
||||||
|
local missionStartTime = LoGetMissionStartTime() -- second after midnight that the mission started
|
||||||
|
local dcsTimeLocal = formatTime(LoGetMissionStartTime() + LoGetModelTime()) -- up-to-date time in dcs
|
||||||
|
local utcOffset = -1 * Terrain.GetTerrainConfig('SummerTimeDelta') * 3600 -- eg -1 * 4 * 3600 (for seconds to get hours)
|
||||||
|
local dcsTimeUtc = formatTime(dcsModelTime + LoGetMissionStartTime() + utcOffset) -- dcs zulu time
|
||||||
|
local realTimeLocal = os.date("%H-%M-%S") -- real life time
|
||||||
|
local realTimeUtc = os.date("!%H-%M-%S") -- real life zulu time
|
||||||
|
--local playTime = formatTime(DCS.getRealTime()) -- does not work, export environment no access
|
||||||
|
|
||||||
|
-- Player Aircraft Properties
|
||||||
|
local altMsl_meters = LoGetAltitudeAboveSeaLevel()
|
||||||
|
local altMsl_feet = meters2feet(altMsl_meters)
|
||||||
|
local altAgl_meters = LoGetAltitudeAboveGroundLevel()
|
||||||
|
local altAgl_feet = meters2feet(altAgl_meters)
|
||||||
|
|
||||||
|
local verticalVelocity_metric = LoGetVerticalVelocity()
|
||||||
|
local verticalVelocity_imperial = metersPerSecond2feetPerMinute(LoGetVerticalVelocity())
|
||||||
|
|
||||||
|
local ias_metric = LoGetIndicatedAirSpeed()
|
||||||
|
local ias_knots = metersPerSecond2knots(LoGetIndicatedAirSpeed())
|
||||||
|
local ias_mph = metersPerSecond2milesPerHour(LoGetIndicatedAirSpeed())
|
||||||
|
|
||||||
|
local tas_metric = LoGetTrueAirSpeed()
|
||||||
|
local tas_knots = metersPerSecond2knots(LoGetTrueAirSpeed())
|
||||||
|
local tas_mph = metersPerSecond2milesPerHour(LoGetTrueAirSpeed())
|
||||||
|
|
||||||
|
local speed_mach = LoGetMachNumber()
|
||||||
|
local accel_g = LoGetAccelerationUnits().y
|
||||||
|
local aoa = LoGetAngleOfAttack()
|
||||||
|
|
||||||
|
--local atmosphericPressure_mmhg = LoGetBasicAtmospherePressure() -- does not seem to work
|
||||||
|
|
||||||
|
local aircraftPitch, aircraftBank, aircraftYawTrue = LoGetADIPitchBankYaw()
|
||||||
|
aircraftPitch = aircraftPitch * 57.3
|
||||||
|
aircraftBank = aircraftBank * 57.3
|
||||||
|
aircraftYawTrue = aircraftYawTrue * 57.3 -- true heading
|
||||||
|
local aircraftYawMagnetic = LoGetMagneticYaw() * 57.3 -- magnetic heading
|
||||||
|
local aircraftHeading = aircraftYawMagnetic -- this cound be negative
|
||||||
|
if aircraftHeading < 0 then aircraftHeading = aircraftHeading + 360 end -- removes the negative
|
||||||
|
local magneticVariance = aircraftYawTrue - aircraftYawMagnetic -- works for all maps
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData() -- relative the the player
|
||||||
|
local lLatitude = selfData.LatLongAlt.Lat
|
||||||
|
local lLongitude = selfData.LatLongAlt.Long
|
||||||
|
local mgrs = Terrain.GetMGRScoordinates(LoGetSelfData().Position.x, LoGetSelfData().Position.z)
|
||||||
|
local mgrsTable = mgrsTableize(mgrs) -- format is mgrsTable[1][1], mgrsTable[1][2], mgrsTable[1][3], mgrsTable[1][4]
|
||||||
|
|
||||||
|
local aircraftHeadingTrue = selfData.Heading * 57.3 -- true yeading (same as trueYaw for fixed wing aircraft)
|
||||||
|
|
||||||
|
-- Engine Info
|
||||||
|
local engineInfo = LoGetEngineInfo()
|
||||||
|
local lEngineRPMleft = engineInfo.RPM.left -- ENG1 RPM %
|
||||||
|
local lEngineRPMright = engineInfo.RPM.right -- ENG2 RPM %
|
||||||
|
local lEngineFuelInternal = engineInfo.fuel_internal -- 1 = full. 0 = empty. Includes external tanks for FF aircraft
|
||||||
|
local lEngineFuelExternal = engineInfo.fuel_external -- TANK2 (EXT) (KG) -- does not seem to work for FF modules
|
||||||
|
local lEngineFuelTotal = lEngineFuelInternal + lEngineFuelExternal
|
||||||
|
local lEngineTempLeft = engineInfo.Temperature.left -- ENG1 EGT ºC. May get odd numbers
|
||||||
|
local lEngineTempRight = engineInfo.Temperature.right -- ENG2 EGT ºC. May get odd numbers
|
||||||
|
|
||||||
|
local lFuelConsumptionLeft = engineInfo.FuelConsumption.left -- {left ,right},kg per sec
|
||||||
|
local lFuelConsumptionRight = engineInfo.FuelConsumption.right -- {left ,right},kg per sec
|
||||||
|
local lFuelConsumptionTotal = lFuelConsumptionLeft + lFuelConsumptionRight -- total,kg per sec
|
||||||
|
local lHydraulicPressureLeft = engineInfo.HydraulicPressure.left -- {left ,right},kg per square centimeter
|
||||||
|
local lHydraulicPressureRight = engineInfo.HydraulicPressure.right -- {left ,right},kg per square centimeter
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8000, aircraftName)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8001, pilotName)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8002, 'Real Time\n'.. realTimeLocal .. '\nDCS Time\n' .. dcsTimeLocal) -- clocks
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8003, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_feet,-1)) .. ' ft'
|
||||||
|
.. '\nIAS ' .. round(ias_knots,0) .. ' kts'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_imperial,-2)) .. ' ft/min'
|
||||||
|
) -- Aircraft Instrument panel (western)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8004, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_meters,-1)) .. ' m'
|
||||||
|
.. '\nIAS ' .. round(ias_metric,0) .. ' km/h'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_metric,0)) .. ' m/s'
|
||||||
|
) -- Aircraft Instrument panel (eastern)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8005, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_feet,-1)) .. ' ft'
|
||||||
|
.. '\nIAS ' .. round(ias_mph,0) .. ' mph'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_imperial,-2)) .. ' ft/min'
|
||||||
|
) -- Aircraft Instrument panel (western ww2)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8006, "Lat-Long-DMS\n" .. formatCoord("DMS",true, lLatitude)
|
||||||
|
.. "\n" .. formatCoord("DMS",false, lLongitude)
|
||||||
|
) -- Player coordinates in DMS
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8007, "Lat-Long-DDM\n" .. formatCoord("DDM",true, lLatitude)
|
||||||
|
.. "\n" .. formatCoord("DDM",false, lLongitude)
|
||||||
|
) -- Player coordinates in DDM
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8008, 'MGRS\n'.. mgrsTable[1][1] .. ' ' .. mgrsTable[1][2]
|
||||||
|
.. '\n' .. mgrsTable[1][3] .. ' ' .. mgrsTable[1][4]
|
||||||
|
) -- Player coordinates in MGRS on 2 rows + title
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8009, 'Mag Var\n' .. format_int(round(magneticVariance, 2))) -- also called magnetic deviation
|
||||||
|
|
||||||
|
-- Example for using the Lo Data. Feel free to make your own!
|
||||||
|
ExportScript.Tools.SendData(8010, format_int(round(kgPerSecond2poundPerHour(lFuelConsumptionLeft), -1))) -- fuel use in pph
|
||||||
|
|
||||||
|
end
|
||||||
|
function ExportScript.AirportInfo(mainPanelDevice)
|
||||||
|
|
||||||
|
local airdromes = LoGetWorldObjects("airdromes") -- returns a list of runways and their popperties
|
||||||
|
local airportInfo = {} -- contains generated table of important properties
|
||||||
|
-- the table will be sorted by nearest airport first
|
||||||
|
-- for this table:
|
||||||
|
-- airportInfo[1] is the first element
|
||||||
|
-- airportInfo[1][1] is the airport name of the first element/airport
|
||||||
|
-- airportInfo[1][2] is the distance to the airport of the first element/airport
|
||||||
|
-- airportInfo[1][3] is the bearing to the airport of the first element/airport
|
||||||
|
-- airportInfo[1][4] is the extimated time en route
|
||||||
|
-- airportInfo[1][5] is the direction of the wind
|
||||||
|
-- airportInfo[1][6] is the windStrength of the wind
|
||||||
|
-- airportInfo[1][7] is the main runway heading
|
||||||
|
-- airportInfo[1][8] is the reverse of the main runway
|
||||||
|
-- airportInfo[1][9] is the prefered runway based on winds
|
||||||
|
|
||||||
|
for key,value in pairs(airdromes) do
|
||||||
|
|
||||||
|
-- remove the woRunWay entries so that only named runways are in the list
|
||||||
|
if value.Name ~= 'woRunWay' then
|
||||||
|
|
||||||
|
-- get the distance from the player to the runway
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
-- get the direction from the player to the runway
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
-- estimate the runway heading based on the reported values
|
||||||
|
local runwayHeading = round(value.Heading * 57.3,-1) / 10
|
||||||
|
if runwayHeading < 0 then
|
||||||
|
runwayHeading = 36 + runwayHeading
|
||||||
|
end
|
||||||
|
-- Reverse it for the reciprocal runway
|
||||||
|
local runwayHeadingReciprocal
|
||||||
|
if runwayHeading > 18 then
|
||||||
|
runwayHeadingReciprocal = runwayHeading-18
|
||||||
|
else
|
||||||
|
runwayHeadingReciprocal = runwayHeading+18
|
||||||
|
end
|
||||||
|
|
||||||
|
local ete = distance / metersPerSecond2knots(LoGetTrueAirSpeed()) * (60 * 60) --based on tas bc dcs is flat...
|
||||||
|
-- if ete is more than 24hrs, make it 24 hrs, which shows up as 00-00-00
|
||||||
|
-- this case is for choppers and aircraft that arent moving
|
||||||
|
if ete > 86400 then ete = 86400 end
|
||||||
|
ete = formatTime(ete)
|
||||||
|
|
||||||
|
-- wind at airport calculations. Each airport has slighty different winds
|
||||||
|
-- https://forum.dcs.world/topic/165136-logetwindatpoint-in-exportlua/#comment-3294428
|
||||||
|
-- LoGetWindAtPoint(x,y,z,is_radio_alt), 2 meters off the ground for the "wind sensor"
|
||||||
|
local vx,_vy,vz,_absolute_height = LoGetWindAtPoint(value.Position.x,2,value.Position.y,true)
|
||||||
|
local windDirectionInRadians = math.atan2(vz,vx)
|
||||||
|
local windDirection = windDirectionInRadians * 57.3
|
||||||
|
local windStrength = math.sqrt((vx)^2 + (vz)^2)
|
||||||
|
if windDirection < 0 then
|
||||||
|
windDirection = 360 + windDirection
|
||||||
|
end
|
||||||
|
-- Convert to direction to from direction
|
||||||
|
if windDirection > 180 then
|
||||||
|
windDirection = windDirection - 180
|
||||||
|
else
|
||||||
|
windDirection = windDirection + 180
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate the prefered runway for landing
|
||||||
|
-- if the rounded runway is within +- 9 of the rounded wind, then it is prefered
|
||||||
|
local windRounded = round(windDirection, -1)
|
||||||
|
if windRounded >= runwayHeading - 9 and windRounded <= runwayHeading + 9 then
|
||||||
|
runwayHeadingPrefered = runwayHeading
|
||||||
|
else
|
||||||
|
runwayHeadingPrefered = runwayHeadingReciprocal
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Populate the table with the important info for each airport
|
||||||
|
table.insert(airportInfo, -- the table name
|
||||||
|
{value.Name, -- airport name [1]
|
||||||
|
distance, bearing, ete, --[2][3][4]
|
||||||
|
windDirection,windStrength, --wind direction [5], wind Strength [6]
|
||||||
|
runwayHeading, runwayHeadingReciprocal,runwayHeadingPrefered}) -- [7][8][9]
|
||||||
|
|
||||||
|
end -- end of woRunWay
|
||||||
|
end -- end of FOR loop
|
||||||
|
|
||||||
|
-- sort the table based on the second value, which is distance
|
||||||
|
-- https://stackoverflow.com/questions/51276613/how-to-sort-table-by-value-and-then-print-index-in-order
|
||||||
|
-- https://www.tutorialspoint.com/sort-function-in-lua-programming
|
||||||
|
table.sort(airportInfo, function(a,b) return a[2] < b[2] end)
|
||||||
|
|
||||||
|
-- Primary Airport (closest)
|
||||||
|
ExportScript.Tools.SendData(8101, airportInfo[1][1] .. '\n' -- name of airport
|
||||||
|
--[[.. 'BRG ']] .. format_int(addZeros3(round(airportInfo[1][3],0))) .. 'º ' -- bearing
|
||||||
|
--[[.. 'DIST ']] .. format_int(round(airportInfo[1][2], 0)) .. 'nm\n' -- distance
|
||||||
|
.. 'ETE ' .. airportInfo[1][4] .. '\n' -- estimated time in route
|
||||||
|
.. '' .. prefixZerosFixedLength(round(airportInfo[1][5], 0),3) .. 'º ' -- wind bearing
|
||||||
|
.. round(metersPerSecond2knots(airportInfo[1][6]),0) .. 'kts' -- wing strength
|
||||||
|
.. '\n' .. prefixZerosFixedLength(airportInfo[1][7],2) -- runway 1
|
||||||
|
.. '-' .. prefixZerosFixedLength(airportInfo[1][8],2) -- runway 2
|
||||||
|
.. ' (' .. prefixZerosFixedLength(airportInfo[1][9],2) .. ')') -- prefered runway based on wind in parens
|
||||||
|
|
||||||
|
-- Secondary Airport (second closest)
|
||||||
|
ExportScript.Tools.SendData(8102, airportInfo[2][1] .. '\n' -- name of airport
|
||||||
|
--[[.. 'BRG ']] .. format_int(addZeros3(round(airportInfo[2][3],0))) .. 'º ' -- bearing
|
||||||
|
--[[.. 'DIST ']] .. format_int(round(airportInfo[2][2], 0)) .. 'nm\n' -- distance
|
||||||
|
.. 'ETE ' .. airportInfo[2][4] .. '\n' -- estimated time in route
|
||||||
|
.. '' .. prefixZerosFixedLength(round(airportInfo[2][5], 0),3) .. 'º ' -- wind bearing
|
||||||
|
.. round(metersPerSecond2knots(airportInfo[2][6]),0) .. 'kts' -- wing strength
|
||||||
|
.. '\n' .. prefixZerosFixedLength(airportInfo[2][7],2) -- runway 1
|
||||||
|
.. '-' .. prefixZerosFixedLength(airportInfo[2][8],2) -- runway 2
|
||||||
|
.. ' (' .. prefixZerosFixedLength(airportInfo[2][9],2) .. ')') -- prefered runway based on wind in parens
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.WindsAloft(mainPanelDevice)
|
||||||
|
|
||||||
|
-- Winds relative to the aircraft, aka, winds aloft
|
||||||
|
local windAloft = LoGetVectorWindVelocity()
|
||||||
|
local windStrengthAloft = math.sqrt((windAloft.x)^2 + (windAloft.z)^2)
|
||||||
|
local windDirectionAloft = math.deg(math.atan2(windAloft.z, windAloft.x))
|
||||||
|
if windDirectionAloft < 0 then
|
||||||
|
windDirectionAloft = 360 + windDirectionAloft
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert to direction to from direction
|
||||||
|
if windDirectionAloft > 180 then
|
||||||
|
windDirectionAloft = windDirectionAloft - 180
|
||||||
|
else
|
||||||
|
windDirectionAloft = windDirectionAloft + 180
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8100, 'Wind Aloft\n' .. addZeros3(round(windDirectionAloft,0)) .. 'º '
|
||||||
|
.. round(metersPerSecond2knots(windStrengthAloft,0)) .. 'kts'
|
||||||
|
) -- winds at the aircraft
|
||||||
|
end
|
||||||
|
function ExportScript.GroundRadar(mainPanelDevice) -- may return some odd things
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
|
||||||
|
local tableOfGround = {}
|
||||||
|
-- relative to the player...
|
||||||
|
local tableOfGround_friendly = {}
|
||||||
|
local tableOfGround_friendlyReports = {}
|
||||||
|
local tableOfGround_enemy = {}
|
||||||
|
local tableOfGround_enemyReports = {}
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.Type.level1 == 2 then
|
||||||
|
table.insert(tableOfGround, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfGround) do
|
||||||
|
if value.CoalitionID == selfCoalitionID then
|
||||||
|
table.insert(tableOfGround_friendly, value)
|
||||||
|
else
|
||||||
|
table.insert(tableOfGround_enemy, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: only do enemy reports if there is an awacs unit(?)
|
||||||
|
for key,value in pairs(tableOfGround_enemy) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfGround_enemyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
end
|
||||||
|
table.sort(tableOfGround_enemyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfGround_friendly) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfGround_friendlyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfGround_friendlyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8200 = 'No Ground\nEnemy\nDetected'
|
||||||
|
if tableOfGround_enemyReports[1] ~= nill then
|
||||||
|
string_8200 = 'Enemy Ground\n' .. tableOfGround_enemyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_enemyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_enemyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8201 = 'No Ground\nEnemy\nDetected'
|
||||||
|
if tableOfGround_enemyReports[2] ~= nill then
|
||||||
|
string_8201 = 'Enemy Ground\n'.. tableOfGround_enemyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_enemyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_enemyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8202 = 'No Ground\nFriend\nDetected'
|
||||||
|
if tableOfGround_friendlyReports[1] ~= nill then
|
||||||
|
string_8202 = 'Friend Ground\n' .. tableOfGround_friendlyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_friendlyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_friendlyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8203 = 'No Ground\nFriend\nDetected'
|
||||||
|
if tableOfGround_friendlyReports[2] ~= nill then
|
||||||
|
string_8203 = 'Friend Ground\n' .. tableOfGround_friendlyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_friendlyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_friendlyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8200, string_8200)
|
||||||
|
ExportScript.Tools.SendData(8201, string_8201)
|
||||||
|
ExportScript.Tools.SendData(8202, string_8202)
|
||||||
|
ExportScript.Tools.SendData(8203, string_8203)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.AirRadar(mainPanelDevice)
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
|
||||||
|
local tableOfAircraft = {}
|
||||||
|
-- relative to the player...
|
||||||
|
local tableOfAircraft_friendly = {}
|
||||||
|
local tableOfAircraft_friendlyReports = {}
|
||||||
|
local tableOfAircraft_enemy = {}
|
||||||
|
local tableOfAircraft_enemyReports = {}
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.Type.level1 == 1 then
|
||||||
|
table.insert(tableOfAircraft, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfAircraft) do
|
||||||
|
if value.CoalitionID == selfCoalitionID then
|
||||||
|
table.insert(tableOfAircraft_friendly, value)
|
||||||
|
else
|
||||||
|
table.insert(tableOfAircraft_enemy, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: only do enemy reports if there is a awacs unit
|
||||||
|
for key,value in pairs(tableOfAircraft_enemy) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfAircraft_enemyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
-- https://stackoverflow.com/questions/51276613/how-to-sort-table-by-value-and-then-print-index-in-order
|
||||||
|
-- https://www.tutorialspoint.com/sort-function-in-lua-programming
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfAircraft_enemyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfAircraft_friendly) do -- [1] will always be the player
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfAircraft_friendlyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfAircraft_friendlyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8210 = 'No Air\nEnemy\nDetected'
|
||||||
|
if tableOfAircraft_enemyReports[1] ~= nill then
|
||||||
|
string_8210 = 'Enemy Air\n' .. tableOfAircraft_enemyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_enemyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_enemyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8211 = 'No Air\nEnemy\nDetected'
|
||||||
|
if tableOfAircraft_enemyReports[2] ~= nill then
|
||||||
|
string_8211 = 'Enemy Air\n' .. tableOfAircraft_enemyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_enemyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_enemyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8212 = 'No Air\nFriend\nDetected'
|
||||||
|
if tableOfAircraft_friendlyReports[2] ~= nill then
|
||||||
|
string_8212 = 'Friend Air\n' .. tableOfAircraft_friendlyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_friendlyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_friendlyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8213 = 'No Air\nFriend\nDetected'
|
||||||
|
if tableOfAircraft_friendlyReports[3] ~= nill then
|
||||||
|
string_8213 = 'Friend Air\n' .. tableOfAircraft_friendlyReports[3][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_friendlyReports[3][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_friendlyReports[3][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8210,string_8210)
|
||||||
|
ExportScript.Tools.SendData(8211, string_8211)
|
||||||
|
ExportScript.Tools.SendData(8212, string_8212)
|
||||||
|
ExportScript.Tools.SendData(8213, string_8213)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.IglaHunter(mainPanelDevice) -- Locates the nearest Igla
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
local tableOfIgla = {}
|
||||||
|
local tableOfIgla_report = {}
|
||||||
|
|
||||||
|
--TODO: Might have to refine this.
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.CoalitionID ~= selfCoalitionID then
|
||||||
|
if value.Type.level3 == 27 then
|
||||||
|
if value.Type.level2 == 16 then
|
||||||
|
if value.Type.level1 == 2 then
|
||||||
|
if value.Type.level4 == 55 or 54 or 53 or 52 or 62 then
|
||||||
|
table.insert(tableOfIgla, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--if tableOfIgla ~= null then
|
||||||
|
for key,value in pairs(tableOfIgla) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfIgla_report, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
table.sort(tableOfIgla_report, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8666 = 'Igla Hunter\nSearching...'
|
||||||
|
if tableOfIgla_report[1] ~= nill then
|
||||||
|
string_8666 = 'Igla Detected\n' .. tableOfIgla_report[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfIgla_report[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfIgla_report[1][2],0) .. ' nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8666, string_8666)
|
||||||
|
|
||||||
|
end
|
||||||
|
----------------------
|
||||||
|
-- Helper Functions --
|
||||||
|
----------------------
|
||||||
|
function ExportScript.Linearize(current_value, raw_tab, final_tab)
|
||||||
|
-- (c) scoobie
|
||||||
|
if current_value <= raw_tab[1] then
|
||||||
|
return final_tab[1]
|
||||||
|
end
|
||||||
|
for index, value in pairs(raw_tab) do
|
||||||
|
if current_value <= value then
|
||||||
|
local ft = final_tab[index]
|
||||||
|
local rt = raw_tab[index]
|
||||||
|
return (current_value - rt) * (ft - final_tab[index - 1]) / (rt - raw_tab[index - 1]) + ft
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- we shouldn't be here, so something went wrong - return arbitrary max. final value, maybe the user will notice the problem:
|
||||||
|
return final_tab[#final_tab]
|
||||||
|
end
|
||||||
|
|
||||||
|
function trim(s) --http://lua-users.org/wiki/CommonFunctions
|
||||||
|
-- from PiL2 20.4
|
||||||
|
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||||
|
end
|
||||||
|
function formatTime(time)
|
||||||
|
local seconds = math.floor(time) % 60
|
||||||
|
local minutes = math.floor(time / 60) % 60
|
||||||
|
local hours = math.floor(time / (60 * 60)) % 24
|
||||||
|
return string.format("%02d", hours) .. "-" .. string.format("%02d", minutes) .. "-" .. string.format("%02d", seconds)
|
||||||
|
end
|
||||||
|
|
||||||
|
function meters2feet(meters)
|
||||||
|
local feet = meters * 3.281
|
||||||
|
return feet
|
||||||
|
end
|
||||||
|
|
||||||
|
function feet2meters(feet)
|
||||||
|
local meters = feet / 3.281
|
||||||
|
return feet
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2milesPerHour(metersPerSecond)
|
||||||
|
local milesPerHour = metersPerSecond * 2.237
|
||||||
|
return milesPerHour
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2knots(metersPerSecond)
|
||||||
|
local knots = metersPerSecond * 1.944
|
||||||
|
return knots
|
||||||
|
end
|
||||||
|
|
||||||
|
function kgPerSecond2poundPerHour(kgPerSecond)
|
||||||
|
poundPerHour = kgPerSecond * 7937
|
||||||
|
return poundPerHour
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2feetPerMinute(metersPerSecond)
|
||||||
|
local feetPerMinute = metersPerSecond * 197
|
||||||
|
return feetPerMinute
|
||||||
|
end
|
||||||
|
|
||||||
|
function round(num, numDecimalPlaces) --http://lua-users.org/wiki/SimpleRound
|
||||||
|
local mult = 10^(numDecimalPlaces or 0)
|
||||||
|
return math.floor(num * mult + 0.5) / mult
|
||||||
|
end
|
||||||
|
|
||||||
|
function format_int(number) --https://stackoverflow.com/questions/10989788/format-integer-in-lua
|
||||||
|
local i, j, minus, int, fraction = tostring(number):find('([-]?)(%d+)([.]?%d*)')
|
||||||
|
-- reverse the int-string and append a comma to all blocks of 3 digits
|
||||||
|
int = int:reverse():gsub("(%d%d%d)", "%1,")
|
||||||
|
-- reverse the int-string back remove an optional comma and put the
|
||||||
|
-- optional minus and fractional part back
|
||||||
|
return minus .. int:reverse():gsub("^,", "") .. fraction
|
||||||
|
end
|
||||||
|
|
||||||
|
function formatCoord(type, isLat, d)
|
||||||
|
local h
|
||||||
|
if isLat then
|
||||||
|
if d < 0 then
|
||||||
|
h = 'S'
|
||||||
|
d = -d
|
||||||
|
else
|
||||||
|
h = 'N'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if d < 0 then
|
||||||
|
h = 'W'
|
||||||
|
d = -d
|
||||||
|
else
|
||||||
|
h = 'E'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local g = math.floor(d)
|
||||||
|
local m = math.floor(d * 60 - g * 60)
|
||||||
|
local s = d * 3600 - g * 3600 - m * 60
|
||||||
|
|
||||||
|
if type == "DMS" then -- Degree Minutes Seconds
|
||||||
|
s = math.floor(s * 100) / 100
|
||||||
|
return string.format('%s %2d°%.2d\'%05.2f"', h, g, m, s)
|
||||||
|
elseif type == "DDM" then -- Degree Decimal Minutes
|
||||||
|
s = math.floor(s / 60 * 1000)
|
||||||
|
return string.format('%s %2d°%02d.%3.3d\'', h, g, m, s)
|
||||||
|
else -- Decimal Degrees
|
||||||
|
return string.format('%f',d)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function getdistance(lat1,lat2,lon1,lon2,unit) -- https://www.geeksforgeeks.org/program-distance-two-points-earth/
|
||||||
|
--Example Locations
|
||||||
|
--lat1 = 42.1578 -- POTI
|
||||||
|
--lat2 = 42.3269 -- HONI
|
||||||
|
--lon1 = 41.6777
|
||||||
|
--lon2 = 42.4122
|
||||||
|
|
||||||
|
local lon1 = toRadians(lon1)
|
||||||
|
local lon2 = toRadians(lon2)
|
||||||
|
local lat1 = toRadians(lat1)
|
||||||
|
local lat2 = toRadians(lat2)
|
||||||
|
|
||||||
|
-- Haversine formula
|
||||||
|
local dlon = lon2 - lon1
|
||||||
|
local dlat = lat2 - lat1
|
||||||
|
local a = math.pow(math.sin(dlat / 2), 2) +
|
||||||
|
math.cos(lat1) * math.cos(lat2) *
|
||||||
|
math.pow(math.sin(dlon / 2),2)
|
||||||
|
|
||||||
|
local c = 2 * math.asin(math.sqrt(a))
|
||||||
|
|
||||||
|
local r -- Radius of earth in X.
|
||||||
|
if unit == 'nm' then
|
||||||
|
r = 6371 / 1.852 -- times 1.852 because I could not find a good NM source
|
||||||
|
elseif unit == 'km' then
|
||||||
|
r = 6371 -- Use 6371 for kilometers
|
||||||
|
elseif unit == 'miles' then
|
||||||
|
r = 3956 -- Use 3956 for miles
|
||||||
|
elseif unit == 'meters' then
|
||||||
|
r = 6371 * 1000
|
||||||
|
end
|
||||||
|
|
||||||
|
-- calculate the result
|
||||||
|
return (c * r)
|
||||||
|
end
|
||||||
|
|
||||||
|
function toRadians(angleIn10thofaDegree)
|
||||||
|
return (angleIn10thofaDegree * math.pi) / 180
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function getBearing(lat1,lat2,lon1,lon2, magnetic)
|
||||||
|
local bearing_rad = math.atan2(lon2 - lon1, lat2 - lat1)
|
||||||
|
if bearing_rad < 0 then
|
||||||
|
bearing_rad = bearing_rad + (2 * math.pi)
|
||||||
|
end
|
||||||
|
|
||||||
|
bearing = math.deg(bearing_rad)
|
||||||
|
|
||||||
|
-- start calculation for getting the magnetic bar
|
||||||
|
local _aircraftPitch, _aircraftBank, aircraftYawTrue = LoGetADIPitchBankYaw()
|
||||||
|
aircraftYawTrue = aircraftYawTrue * 57.3 -- actually heading
|
||||||
|
local aircraftYawMagnetic = LoGetMagneticYaw() * 57.3
|
||||||
|
local magneticVariance = aircraftYawTrue - aircraftYawMagnetic
|
||||||
|
|
||||||
|
if magnetic == true then
|
||||||
|
bearing = bearing - magneticVariance
|
||||||
|
end
|
||||||
|
|
||||||
|
-- correction for bearings less than 0 due to the calculation above
|
||||||
|
if bearing < 0 then
|
||||||
|
bearing = bearing + 360
|
||||||
|
end
|
||||||
|
|
||||||
|
return bearing
|
||||||
|
end
|
||||||
|
|
||||||
|
function addZeros3(number)
|
||||||
|
number = string.format("%.1d" , number)
|
||||||
|
if #number == 2 then
|
||||||
|
number = "0" .. number
|
||||||
|
elseif #number == 1 then
|
||||||
|
number = "00" .. number
|
||||||
|
end
|
||||||
|
return number
|
||||||
|
end
|
||||||
|
|
||||||
|
function prefixZerosFixedLength(number, digitLength) -- prefixZerosFixedLength(99, 3) --> 099
|
||||||
|
number = string.format("%.1d" , number) -- make the number a string
|
||||||
|
local zerosToAdd = digitLength - #number
|
||||||
|
s = ''
|
||||||
|
for i = 1, zerosToAdd do
|
||||||
|
s = s .. 0
|
||||||
|
end
|
||||||
|
return s .. number
|
||||||
|
end
|
||||||
|
|
||||||
|
function mgrsTableize(mgrsString)
|
||||||
|
-- Reference: https://upload.wikimedia.org/wikipedia/commons/b/b7/Universal_Transverse_Mercator_zones.svg
|
||||||
|
-- example: 38 T LM 12345 54321
|
||||||
|
-- (\d+\s\w)\s(\w+)\s(.+)\s(.+) --c# version of regex
|
||||||
|
-- UTMZone = string,
|
||||||
|
-- MGRSDigraph = string,
|
||||||
|
-- Easting = number,
|
||||||
|
-- Northing = number
|
||||||
|
local UTMZone , MGRSDigraph, Easting, Northing = mgrsString:match('(%d+%s%w)%s(%w+)%s(.+)%s(.+)')
|
||||||
|
local mgrsTbl = {}
|
||||||
|
table.insert(mgrsTbl, {UTMZone,MGRSDigraph,Easting,Northing})
|
||||||
|
return mgrsTbl
|
||||||
|
end
|
||||||
|
|
||||||
|
function isNilOrEmpty(value)
|
||||||
|
if value == "" or value == nil then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function NilOrEmpty(value)
|
||||||
|
if value == "" then
|
||||||
|
return 'empty'
|
||||||
|
elseif value == nil then
|
||||||
|
return 'empty'
|
||||||
|
else
|
||||||
|
return value
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@ -706,9 +706,9 @@ function ExportScript.ProcessIkarusDCSConfigLowImportance(mainPanelDevice)
|
|||||||
ExportScript.LoAircraftInfo(mainPanelDevice) -- Provides a lot of aircraft properties
|
ExportScript.LoAircraftInfo(mainPanelDevice) -- Provides a lot of aircraft properties
|
||||||
ExportScript.AirportInfo(mainPanelDevice) -- Provides info on the two closest airports
|
ExportScript.AirportInfo(mainPanelDevice) -- Provides info on the two closest airports
|
||||||
ExportScript.WindsAloft(mainPanelDevice) -- Gets winds at the aircraft
|
ExportScript.WindsAloft(mainPanelDevice) -- Gets winds at the aircraft
|
||||||
ExportScript.GroundRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies
|
ExportScript.GroundRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
ExportScript.AirRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies
|
ExportScript.AirRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
ExportScript.IglaHunter(mainPanelDevice) -- Locates closest Igla
|
ExportScript.IglaHunter(mainPanelDevice) -- Locates closest Igla (Use in Single Player)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1954,7 +1954,6 @@ function ExportScript.Linearize(current_value, raw_tab, final_tab)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function trim(s) --http://lua-users.org/wiki/CommonFunctions
|
function trim(s) --http://lua-users.org/wiki/CommonFunctions
|
||||||
|
|
||||||
-- from PiL2 20.4
|
-- from PiL2 20.4
|
||||||
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||||
end
|
end
|
||||||
|
|||||||
@ -532,9 +532,9 @@ function ExportScript.ProcessIkarusDCSConfigLowImportance(mainPanelDevice)
|
|||||||
ExportScript.LoAircraftInfo(mainPanelDevice) -- Provides a lot of aircraft properties
|
ExportScript.LoAircraftInfo(mainPanelDevice) -- Provides a lot of aircraft properties
|
||||||
ExportScript.AirportInfo(mainPanelDevice) -- Provides info on the two closest airports
|
ExportScript.AirportInfo(mainPanelDevice) -- Provides info on the two closest airports
|
||||||
ExportScript.WindsAloft(mainPanelDevice) -- Gets winds at the aircraft
|
ExportScript.WindsAloft(mainPanelDevice) -- Gets winds at the aircraft
|
||||||
ExportScript.GroundRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies
|
ExportScript.GroundRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
ExportScript.AirRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies
|
ExportScript.AirRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
ExportScript.IglaHunter(mainPanelDevice) -- Locates closest Igla
|
ExportScript.IglaHunter(mainPanelDevice) -- Locates closest Igla (Use in Single Player)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
-- F-86 Export
|
-- F-86 Export
|
||||||
|
-- https://github.com/asherao/DCS-ExportScripts
|
||||||
|
|
||||||
|
local base = _G -- game information
|
||||||
|
local os = base.os -- time
|
||||||
|
local Terrain = require('terrain') -- map info
|
||||||
ExportScript.FoundDCSModule = true
|
ExportScript.FoundDCSModule = true
|
||||||
ExportScript.Version.F86 = "1.2.1"
|
ExportScript.Version.F86 = "1.2.1"
|
||||||
--ExportScript.NoLuaExportBeforeNextFrame = true
|
|
||||||
|
|
||||||
ExportScript.ConfigEveryFrameArguments =
|
ExportScript.ConfigEveryFrameArguments =
|
||||||
{
|
{
|
||||||
@ -365,7 +368,16 @@ function ExportScript.ProcessIkarusDCSConfigLowImportance(mainPanelDevice)
|
|||||||
ExportScript.Tools.IkarusCockpitLights(mainPanelDevice, {654,813,811,812})
|
ExportScript.Tools.IkarusCockpitLights(mainPanelDevice, {654,813,811,812})
|
||||||
-- Compass Light Switch, Instrument Panel Primary Light Rheostat, Instrument Panel Auxiliary Light Rheostat, Console and Panel Light Rheostat
|
-- Compass Light Switch, Instrument Panel Primary Light Rheostat, Instrument Panel Auxiliary Light Rheostat, Console and Panel Light Rheostat
|
||||||
|
|
||||||
|
if LoIsObjectExportAllowed() then -- returns true if world objects data is available
|
||||||
|
if LoIsOwnshipExportAllowed() then -- returns true if ownship data is available
|
||||||
|
ExportScript.LoAircraftInfo(mainPanelDevice) -- Provides a lot of aircraft properties
|
||||||
|
ExportScript.AirportInfo(mainPanelDevice) -- Provides info on the two closest airports
|
||||||
|
ExportScript.WindsAloft(mainPanelDevice) -- Gets winds at the aircraft
|
||||||
|
ExportScript.GroundRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
|
ExportScript.AirRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
|
ExportScript.IglaHunter(mainPanelDevice) -- Locates closest Igla (Use in Single Player)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ExportScript.ProcessDACConfigLowImportance(mainPanelDevice)
|
function ExportScript.ProcessDACConfigLowImportance(mainPanelDevice)
|
||||||
@ -432,10 +444,730 @@ function ExportScript.Radios(mainPanelDevice)
|
|||||||
ExportScript.Tools.SendData(3003, "ADF\n" .. ADF_Freq)
|
ExportScript.Tools.SendData(3003, "ADF\n" .. ADF_Freq)
|
||||||
end
|
end
|
||||||
|
|
||||||
-----------------------------
|
function ExportScript.LoAircraftInfo(mainPanelDevice)
|
||||||
-- Helper functions --
|
|
||||||
-----------------------------
|
-- General
|
||||||
|
local aircraftName = LoGetSelfData().Name -- DCS Name of the aircraft eg "F-5E-3"
|
||||||
|
local pilotName = LoGetPilotName() -- Logbook Pilot name
|
||||||
|
|
||||||
|
-- Times DCS times are default in seconds
|
||||||
|
local dcsModelTime = LoGetModelTime() -- time since aircraft spawn
|
||||||
|
local missionStartTime = LoGetMissionStartTime() -- second after midnight that the mission started
|
||||||
|
local dcsTimeLocal = formatTime(LoGetMissionStartTime() + LoGetModelTime()) -- up-to-date time in dcs
|
||||||
|
local utcOffset = -1 * Terrain.GetTerrainConfig('SummerTimeDelta') * 3600 -- eg -1 * 4 * 3600 (for seconds to get hours)
|
||||||
|
local dcsTimeUtc = formatTime(dcsModelTime + LoGetMissionStartTime() + utcOffset) -- dcs zulu time
|
||||||
|
local realTimeLocal = os.date("%H-%M-%S") -- real life time
|
||||||
|
local realTimeUtc = os.date("!%H-%M-%S") -- real life zulu time
|
||||||
|
--local playTime = formatTime(DCS.getRealTime()) -- does not work, export environment no access
|
||||||
|
|
||||||
|
-- Player Aircraft Properties
|
||||||
|
local altMsl_meters = LoGetAltitudeAboveSeaLevel()
|
||||||
|
local altMsl_feet = meters2feet(altMsl_meters)
|
||||||
|
local altAgl_meters = LoGetAltitudeAboveGroundLevel()
|
||||||
|
local altAgl_feet = meters2feet(altAgl_meters)
|
||||||
|
|
||||||
|
local verticalVelocity_metric = LoGetVerticalVelocity()
|
||||||
|
local verticalVelocity_imperial = metersPerSecond2feetPerMinute(LoGetVerticalVelocity())
|
||||||
|
|
||||||
|
local ias_metric = LoGetIndicatedAirSpeed()
|
||||||
|
local ias_knots = metersPerSecond2knots(LoGetIndicatedAirSpeed())
|
||||||
|
local ias_mph = metersPerSecond2milesPerHour(LoGetIndicatedAirSpeed())
|
||||||
|
|
||||||
------------------
|
local tas_metric = LoGetTrueAirSpeed()
|
||||||
-- Notes --
|
local tas_knots = metersPerSecond2knots(LoGetTrueAirSpeed())
|
||||||
------------------
|
local tas_mph = metersPerSecond2milesPerHour(LoGetTrueAirSpeed())
|
||||||
|
|
||||||
|
local speed_mach = LoGetMachNumber()
|
||||||
|
local accel_g = LoGetAccelerationUnits().y
|
||||||
|
local aoa = LoGetAngleOfAttack()
|
||||||
|
|
||||||
|
--local atmosphericPressure_mmhg = LoGetBasicAtmospherePressure() -- does not seem to work
|
||||||
|
|
||||||
|
local aircraftPitch, aircraftBank, aircraftYawTrue = LoGetADIPitchBankYaw()
|
||||||
|
aircraftPitch = aircraftPitch * 57.3
|
||||||
|
aircraftBank = aircraftBank * 57.3
|
||||||
|
aircraftYawTrue = aircraftYawTrue * 57.3 -- true heading
|
||||||
|
local aircraftYawMagnetic = LoGetMagneticYaw() * 57.3 -- magnetic heading
|
||||||
|
local aircraftHeading = aircraftYawMagnetic -- this cound be negative
|
||||||
|
if aircraftHeading < 0 then aircraftHeading = aircraftHeading + 360 end -- removes the negative
|
||||||
|
local magneticVariance = aircraftYawTrue - aircraftYawMagnetic -- works for all maps
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData() -- relative the the player
|
||||||
|
local lLatitude = selfData.LatLongAlt.Lat
|
||||||
|
local lLongitude = selfData.LatLongAlt.Long
|
||||||
|
local mgrs = Terrain.GetMGRScoordinates(LoGetSelfData().Position.x, LoGetSelfData().Position.z)
|
||||||
|
local mgrsTable = mgrsTableize(mgrs) -- format is mgrsTable[1][1], mgrsTable[1][2], mgrsTable[1][3], mgrsTable[1][4]
|
||||||
|
|
||||||
|
local aircraftHeadingTrue = selfData.Heading * 57.3 -- true yeading (same as trueYaw for fixed wing aircraft)
|
||||||
|
|
||||||
|
-- Engine Info
|
||||||
|
local engineInfo = LoGetEngineInfo()
|
||||||
|
local lEngineRPMleft = engineInfo.RPM.left -- ENG1 RPM %
|
||||||
|
local lEngineRPMright = engineInfo.RPM.right -- ENG2 RPM %
|
||||||
|
local lEngineFuelInternal = engineInfo.fuel_internal -- 1 = full. 0 = empty. Includes external tanks for FF aircraft
|
||||||
|
local lEngineFuelExternal = engineInfo.fuel_external -- TANK2 (EXT) (KG) -- does not seem to work for FF modules
|
||||||
|
local lEngineFuelTotal = lEngineFuelInternal + lEngineFuelExternal
|
||||||
|
local lEngineTempLeft = engineInfo.Temperature.left -- ENG1 EGT ºC. May get odd numbers
|
||||||
|
local lEngineTempRight = engineInfo.Temperature.right -- ENG2 EGT ºC. May get odd numbers
|
||||||
|
|
||||||
|
local lFuelConsumptionLeft = engineInfo.FuelConsumption.left -- {left ,right},kg per sec
|
||||||
|
local lFuelConsumptionRight = engineInfo.FuelConsumption.right -- {left ,right},kg per sec
|
||||||
|
local lFuelConsumptionTotal = lFuelConsumptionLeft + lFuelConsumptionRight -- total,kg per sec
|
||||||
|
local lHydraulicPressureLeft = engineInfo.HydraulicPressure.left -- {left ,right},kg per square centimeter
|
||||||
|
local lHydraulicPressureRight = engineInfo.HydraulicPressure.right -- {left ,right},kg per square centimeter
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8000, aircraftName)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8001, pilotName)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8002, 'Real Time\n'.. realTimeLocal .. '\nDCS Time\n' .. dcsTimeLocal) -- clocks
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8003, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_feet,-1)) .. ' ft'
|
||||||
|
.. '\nIAS ' .. round(ias_knots,0) .. ' kts'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_imperial,-2)) .. ' ft/min'
|
||||||
|
) -- Aircraft Instrument panel (western)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8004, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_meters,-1)) .. ' m'
|
||||||
|
.. '\nIAS ' .. round(ias_metric,0) .. ' km/h'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_metric,0)) .. ' m/s'
|
||||||
|
) -- Aircraft Instrument panel (eastern)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8005, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_feet,-1)) .. ' ft'
|
||||||
|
.. '\nIAS ' .. round(ias_mph,0) .. ' mph'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_imperial,-2)) .. ' ft/min'
|
||||||
|
) -- Aircraft Instrument panel (western ww2)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8006, "Lat-Long-DMS\n" .. formatCoord("DMS",true, lLatitude)
|
||||||
|
.. "\n" .. formatCoord("DMS",false, lLongitude)
|
||||||
|
) -- Player coordinates in DMS
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8007, "Lat-Long-DDM\n" .. formatCoord("DDM",true, lLatitude)
|
||||||
|
.. "\n" .. formatCoord("DDM",false, lLongitude)
|
||||||
|
) -- Player coordinates in DDM
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8008, 'MGRS\n'.. mgrsTable[1][1] .. ' ' .. mgrsTable[1][2]
|
||||||
|
.. '\n' .. mgrsTable[1][3] .. ' ' .. mgrsTable[1][4]
|
||||||
|
) -- Player coordinates in MGRS on 2 rows + title
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8009, 'Mag Var\n' .. format_int(round(magneticVariance, 2))) -- also called magnetic deviation
|
||||||
|
|
||||||
|
-- Example for using the Lo Data. Feel free to make your own!
|
||||||
|
ExportScript.Tools.SendData(8010, format_int(round(kgPerSecond2poundPerHour(lFuelConsumptionLeft), -1))) -- fuel use in pph
|
||||||
|
|
||||||
|
end
|
||||||
|
function ExportScript.AirportInfo(mainPanelDevice)
|
||||||
|
|
||||||
|
local airdromes = LoGetWorldObjects("airdromes") -- returns a list of runways and their popperties
|
||||||
|
local airportInfo = {} -- contains generated table of important properties
|
||||||
|
-- the table will be sorted by nearest airport first
|
||||||
|
-- for this table:
|
||||||
|
-- airportInfo[1] is the first element
|
||||||
|
-- airportInfo[1][1] is the airport name of the first element/airport
|
||||||
|
-- airportInfo[1][2] is the distance to the airport of the first element/airport
|
||||||
|
-- airportInfo[1][3] is the bearing to the airport of the first element/airport
|
||||||
|
-- airportInfo[1][4] is the extimated time en route
|
||||||
|
-- airportInfo[1][5] is the direction of the wind
|
||||||
|
-- airportInfo[1][6] is the windStrength of the wind
|
||||||
|
-- airportInfo[1][7] is the main runway heading
|
||||||
|
-- airportInfo[1][8] is the reverse of the main runway
|
||||||
|
-- airportInfo[1][9] is the prefered runway based on winds
|
||||||
|
|
||||||
|
for key,value in pairs(airdromes) do
|
||||||
|
|
||||||
|
-- remove the woRunWay entries so that only named runways are in the list
|
||||||
|
if value.Name ~= 'woRunWay' then
|
||||||
|
|
||||||
|
-- get the distance from the player to the runway
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
-- get the direction from the player to the runway
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
-- estimate the runway heading based on the reported values
|
||||||
|
local runwayHeading = round(value.Heading * 57.3,-1) / 10
|
||||||
|
if runwayHeading < 0 then
|
||||||
|
runwayHeading = 36 + runwayHeading
|
||||||
|
end
|
||||||
|
-- Reverse it for the reciprocal runway
|
||||||
|
local runwayHeadingReciprocal
|
||||||
|
if runwayHeading > 18 then
|
||||||
|
runwayHeadingReciprocal = runwayHeading-18
|
||||||
|
else
|
||||||
|
runwayHeadingReciprocal = runwayHeading+18
|
||||||
|
end
|
||||||
|
|
||||||
|
local ete = distance / metersPerSecond2knots(LoGetTrueAirSpeed()) * (60 * 60) --based on tas bc dcs is flat...
|
||||||
|
-- if ete is more than 24hrs, make it 24 hrs, which shows up as 00-00-00
|
||||||
|
-- this case is for choppers and aircraft that arent moving
|
||||||
|
if ete > 86400 then ete = 86400 end
|
||||||
|
ete = formatTime(ete)
|
||||||
|
|
||||||
|
-- wind at airport calculations. Each airport has slighty different winds
|
||||||
|
-- https://forum.dcs.world/topic/165136-logetwindatpoint-in-exportlua/#comment-3294428
|
||||||
|
-- LoGetWindAtPoint(x,y,z,is_radio_alt), 2 meters off the ground for the "wind sensor"
|
||||||
|
local vx,_vy,vz,_absolute_height = LoGetWindAtPoint(value.Position.x,2,value.Position.y,true)
|
||||||
|
local windDirectionInRadians = math.atan2(vz,vx)
|
||||||
|
local windDirection = windDirectionInRadians * 57.3
|
||||||
|
local windStrength = math.sqrt((vx)^2 + (vz)^2)
|
||||||
|
if windDirection < 0 then
|
||||||
|
windDirection = 360 + windDirection
|
||||||
|
end
|
||||||
|
-- Convert to direction to from direction
|
||||||
|
if windDirection > 180 then
|
||||||
|
windDirection = windDirection - 180
|
||||||
|
else
|
||||||
|
windDirection = windDirection + 180
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate the prefered runway for landing
|
||||||
|
-- if the rounded runway is within +- 9 of the rounded wind, then it is prefered
|
||||||
|
local windRounded = round(windDirection, -1)
|
||||||
|
if windRounded >= runwayHeading - 9 and windRounded <= runwayHeading + 9 then
|
||||||
|
runwayHeadingPrefered = runwayHeading
|
||||||
|
else
|
||||||
|
runwayHeadingPrefered = runwayHeadingReciprocal
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Populate the table with the important info for each airport
|
||||||
|
table.insert(airportInfo, -- the table name
|
||||||
|
{value.Name, -- airport name [1]
|
||||||
|
distance, bearing, ete, --[2][3][4]
|
||||||
|
windDirection,windStrength, --wind direction [5], wind Strength [6]
|
||||||
|
runwayHeading, runwayHeadingReciprocal,runwayHeadingPrefered}) -- [7][8][9]
|
||||||
|
|
||||||
|
end -- end of woRunWay
|
||||||
|
end -- end of FOR loop
|
||||||
|
|
||||||
|
-- sort the table based on the second value, which is distance
|
||||||
|
-- https://stackoverflow.com/questions/51276613/how-to-sort-table-by-value-and-then-print-index-in-order
|
||||||
|
-- https://www.tutorialspoint.com/sort-function-in-lua-programming
|
||||||
|
table.sort(airportInfo, function(a,b) return a[2] < b[2] end)
|
||||||
|
|
||||||
|
-- Primary Airport (closest)
|
||||||
|
ExportScript.Tools.SendData(8101, airportInfo[1][1] .. '\n' -- name of airport
|
||||||
|
--[[.. 'BRG ']] .. format_int(addZeros3(round(airportInfo[1][3],0))) .. 'º ' -- bearing
|
||||||
|
--[[.. 'DIST ']] .. format_int(round(airportInfo[1][2], 0)) .. 'nm\n' -- distance
|
||||||
|
.. 'ETE ' .. airportInfo[1][4] .. '\n' -- estimated time in route
|
||||||
|
.. '' .. prefixZerosFixedLength(round(airportInfo[1][5], 0),3) .. 'º ' -- wind bearing
|
||||||
|
.. round(metersPerSecond2knots(airportInfo[1][6]),0) .. 'kts' -- wing strength
|
||||||
|
.. '\n' .. prefixZerosFixedLength(airportInfo[1][7],2) -- runway 1
|
||||||
|
.. '-' .. prefixZerosFixedLength(airportInfo[1][8],2) -- runway 2
|
||||||
|
.. ' (' .. prefixZerosFixedLength(airportInfo[1][9],2) .. ')') -- prefered runway based on wind in parens
|
||||||
|
|
||||||
|
-- Secondary Airport (second closest)
|
||||||
|
ExportScript.Tools.SendData(8102, airportInfo[2][1] .. '\n' -- name of airport
|
||||||
|
--[[.. 'BRG ']] .. format_int(addZeros3(round(airportInfo[2][3],0))) .. 'º ' -- bearing
|
||||||
|
--[[.. 'DIST ']] .. format_int(round(airportInfo[2][2], 0)) .. 'nm\n' -- distance
|
||||||
|
.. 'ETE ' .. airportInfo[2][4] .. '\n' -- estimated time in route
|
||||||
|
.. '' .. prefixZerosFixedLength(round(airportInfo[2][5], 0),3) .. 'º ' -- wind bearing
|
||||||
|
.. round(metersPerSecond2knots(airportInfo[2][6]),0) .. 'kts' -- wing strength
|
||||||
|
.. '\n' .. prefixZerosFixedLength(airportInfo[2][7],2) -- runway 1
|
||||||
|
.. '-' .. prefixZerosFixedLength(airportInfo[2][8],2) -- runway 2
|
||||||
|
.. ' (' .. prefixZerosFixedLength(airportInfo[2][9],2) .. ')') -- prefered runway based on wind in parens
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.WindsAloft(mainPanelDevice)
|
||||||
|
|
||||||
|
-- Winds relative to the aircraft, aka, winds aloft
|
||||||
|
local windAloft = LoGetVectorWindVelocity()
|
||||||
|
local windStrengthAloft = math.sqrt((windAloft.x)^2 + (windAloft.z)^2)
|
||||||
|
local windDirectionAloft = math.deg(math.atan2(windAloft.z, windAloft.x))
|
||||||
|
if windDirectionAloft < 0 then
|
||||||
|
windDirectionAloft = 360 + windDirectionAloft
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert to direction to from direction
|
||||||
|
if windDirectionAloft > 180 then
|
||||||
|
windDirectionAloft = windDirectionAloft - 180
|
||||||
|
else
|
||||||
|
windDirectionAloft = windDirectionAloft + 180
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8100, 'Wind Aloft\n' .. addZeros3(round(windDirectionAloft,0)) .. 'º '
|
||||||
|
.. round(metersPerSecond2knots(windStrengthAloft,0)) .. 'kts'
|
||||||
|
) -- winds at the aircraft
|
||||||
|
end
|
||||||
|
function ExportScript.GroundRadar(mainPanelDevice) -- may return some odd things
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
|
||||||
|
local tableOfGround = {}
|
||||||
|
-- relative to the player...
|
||||||
|
local tableOfGround_friendly = {}
|
||||||
|
local tableOfGround_friendlyReports = {}
|
||||||
|
local tableOfGround_enemy = {}
|
||||||
|
local tableOfGround_enemyReports = {}
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.Type.level1 == 2 then
|
||||||
|
table.insert(tableOfGround, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfGround) do
|
||||||
|
if value.CoalitionID == selfCoalitionID then
|
||||||
|
table.insert(tableOfGround_friendly, value)
|
||||||
|
else
|
||||||
|
table.insert(tableOfGround_enemy, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: only do enemy reports if there is an awacs unit(?)
|
||||||
|
for key,value in pairs(tableOfGround_enemy) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfGround_enemyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
end
|
||||||
|
table.sort(tableOfGround_enemyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfGround_friendly) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfGround_friendlyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfGround_friendlyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8200 = 'No Ground\nEnemy\nDetected'
|
||||||
|
if tableOfGround_enemyReports[1] ~= nill then
|
||||||
|
string_8200 = 'Enemy Ground\n' .. tableOfGround_enemyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_enemyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_enemyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8201 = 'No Ground\nEnemy\nDetected'
|
||||||
|
if tableOfGround_enemyReports[2] ~= nill then
|
||||||
|
string_8201 = 'Enemy Ground\n'.. tableOfGround_enemyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_enemyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_enemyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8202 = 'No Ground\nFriend\nDetected'
|
||||||
|
if tableOfGround_friendlyReports[1] ~= nill then
|
||||||
|
string_8202 = 'Friend Ground\n' .. tableOfGround_friendlyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_friendlyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_friendlyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8203 = 'No Ground\nFriend\nDetected'
|
||||||
|
if tableOfGround_friendlyReports[2] ~= nill then
|
||||||
|
string_8203 = 'Friend Ground\n' .. tableOfGround_friendlyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_friendlyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_friendlyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8200, string_8200)
|
||||||
|
ExportScript.Tools.SendData(8201, string_8201)
|
||||||
|
ExportScript.Tools.SendData(8202, string_8202)
|
||||||
|
ExportScript.Tools.SendData(8203, string_8203)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.AirRadar(mainPanelDevice)
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
|
||||||
|
local tableOfAircraft = {}
|
||||||
|
-- relative to the player...
|
||||||
|
local tableOfAircraft_friendly = {}
|
||||||
|
local tableOfAircraft_friendlyReports = {}
|
||||||
|
local tableOfAircraft_enemy = {}
|
||||||
|
local tableOfAircraft_enemyReports = {}
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.Type.level1 == 1 then
|
||||||
|
table.insert(tableOfAircraft, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfAircraft) do
|
||||||
|
if value.CoalitionID == selfCoalitionID then
|
||||||
|
table.insert(tableOfAircraft_friendly, value)
|
||||||
|
else
|
||||||
|
table.insert(tableOfAircraft_enemy, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: only do enemy reports if there is a awacs unit
|
||||||
|
for key,value in pairs(tableOfAircraft_enemy) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfAircraft_enemyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
-- https://stackoverflow.com/questions/51276613/how-to-sort-table-by-value-and-then-print-index-in-order
|
||||||
|
-- https://www.tutorialspoint.com/sort-function-in-lua-programming
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfAircraft_enemyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfAircraft_friendly) do -- [1] will always be the player
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfAircraft_friendlyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfAircraft_friendlyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8210 = 'No Air\nEnemy\nDetected'
|
||||||
|
if tableOfAircraft_enemyReports[1] ~= nill then
|
||||||
|
string_8210 = 'Enemy Air\n' .. tableOfAircraft_enemyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_enemyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_enemyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8211 = 'No Air\nEnemy\nDetected'
|
||||||
|
if tableOfAircraft_enemyReports[2] ~= nill then
|
||||||
|
string_8211 = 'Enemy Air\n' .. tableOfAircraft_enemyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_enemyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_enemyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8212 = 'No Air\nFriend\nDetected'
|
||||||
|
if tableOfAircraft_friendlyReports[2] ~= nill then
|
||||||
|
string_8212 = 'Friend Air\n' .. tableOfAircraft_friendlyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_friendlyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_friendlyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8213 = 'No Air\nFriend\nDetected'
|
||||||
|
if tableOfAircraft_friendlyReports[3] ~= nill then
|
||||||
|
string_8213 = 'Friend Air\n' .. tableOfAircraft_friendlyReports[3][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_friendlyReports[3][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_friendlyReports[3][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8210,string_8210)
|
||||||
|
ExportScript.Tools.SendData(8211, string_8211)
|
||||||
|
ExportScript.Tools.SendData(8212, string_8212)
|
||||||
|
ExportScript.Tools.SendData(8213, string_8213)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.IglaHunter(mainPanelDevice) -- Locates the nearest Igla
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
local tableOfIgla = {}
|
||||||
|
local tableOfIgla_report = {}
|
||||||
|
|
||||||
|
--TODO: Might have to refine this.
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.CoalitionID ~= selfCoalitionID then
|
||||||
|
if value.Type.level3 == 27 then
|
||||||
|
if value.Type.level2 == 16 then
|
||||||
|
if value.Type.level1 == 2 then
|
||||||
|
if value.Type.level4 == 55 or 54 or 53 or 52 or 62 then
|
||||||
|
table.insert(tableOfIgla, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--if tableOfIgla ~= null then
|
||||||
|
for key,value in pairs(tableOfIgla) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfIgla_report, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
table.sort(tableOfIgla_report, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8666 = 'Igla Hunter\nSearching...'
|
||||||
|
if tableOfIgla_report[1] ~= nill then
|
||||||
|
string_8666 = 'Igla Detected\n' .. tableOfIgla_report[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfIgla_report[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfIgla_report[1][2],0) .. ' nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8666, string_8666)
|
||||||
|
|
||||||
|
end
|
||||||
|
----------------------
|
||||||
|
-- Helper Functions --
|
||||||
|
----------------------
|
||||||
|
function ExportScript.Linearize(current_value, raw_tab, final_tab)
|
||||||
|
-- (c) scoobie
|
||||||
|
if current_value <= raw_tab[1] then
|
||||||
|
return final_tab[1]
|
||||||
|
end
|
||||||
|
for index, value in pairs(raw_tab) do
|
||||||
|
if current_value <= value then
|
||||||
|
local ft = final_tab[index]
|
||||||
|
local rt = raw_tab[index]
|
||||||
|
return (current_value - rt) * (ft - final_tab[index - 1]) / (rt - raw_tab[index - 1]) + ft
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- we shouldn't be here, so something went wrong - return arbitrary max. final value, maybe the user will notice the problem:
|
||||||
|
return final_tab[#final_tab]
|
||||||
|
end
|
||||||
|
|
||||||
|
function trim(s) --http://lua-users.org/wiki/CommonFunctions
|
||||||
|
-- from PiL2 20.4
|
||||||
|
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||||
|
end
|
||||||
|
function formatTime(time)
|
||||||
|
local seconds = math.floor(time) % 60
|
||||||
|
local minutes = math.floor(time / 60) % 60
|
||||||
|
local hours = math.floor(time / (60 * 60)) % 24
|
||||||
|
return string.format("%02d", hours) .. "-" .. string.format("%02d", minutes) .. "-" .. string.format("%02d", seconds)
|
||||||
|
end
|
||||||
|
|
||||||
|
function meters2feet(meters)
|
||||||
|
local feet = meters * 3.281
|
||||||
|
return feet
|
||||||
|
end
|
||||||
|
|
||||||
|
function feet2meters(feet)
|
||||||
|
local meters = feet / 3.281
|
||||||
|
return feet
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2milesPerHour(metersPerSecond)
|
||||||
|
local milesPerHour = metersPerSecond * 2.237
|
||||||
|
return milesPerHour
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2knots(metersPerSecond)
|
||||||
|
local knots = metersPerSecond * 1.944
|
||||||
|
return knots
|
||||||
|
end
|
||||||
|
|
||||||
|
function kgPerSecond2poundPerHour(kgPerSecond)
|
||||||
|
poundPerHour = kgPerSecond * 7937
|
||||||
|
return poundPerHour
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2feetPerMinute(metersPerSecond)
|
||||||
|
local feetPerMinute = metersPerSecond * 197
|
||||||
|
return feetPerMinute
|
||||||
|
end
|
||||||
|
|
||||||
|
function round(num, numDecimalPlaces) --http://lua-users.org/wiki/SimpleRound
|
||||||
|
local mult = 10^(numDecimalPlaces or 0)
|
||||||
|
return math.floor(num * mult + 0.5) / mult
|
||||||
|
end
|
||||||
|
|
||||||
|
function format_int(number) --https://stackoverflow.com/questions/10989788/format-integer-in-lua
|
||||||
|
local i, j, minus, int, fraction = tostring(number):find('([-]?)(%d+)([.]?%d*)')
|
||||||
|
-- reverse the int-string and append a comma to all blocks of 3 digits
|
||||||
|
int = int:reverse():gsub("(%d%d%d)", "%1,")
|
||||||
|
-- reverse the int-string back remove an optional comma and put the
|
||||||
|
-- optional minus and fractional part back
|
||||||
|
return minus .. int:reverse():gsub("^,", "") .. fraction
|
||||||
|
end
|
||||||
|
|
||||||
|
function formatCoord(type, isLat, d)
|
||||||
|
local h
|
||||||
|
if isLat then
|
||||||
|
if d < 0 then
|
||||||
|
h = 'S'
|
||||||
|
d = -d
|
||||||
|
else
|
||||||
|
h = 'N'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if d < 0 then
|
||||||
|
h = 'W'
|
||||||
|
d = -d
|
||||||
|
else
|
||||||
|
h = 'E'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local g = math.floor(d)
|
||||||
|
local m = math.floor(d * 60 - g * 60)
|
||||||
|
local s = d * 3600 - g * 3600 - m * 60
|
||||||
|
|
||||||
|
if type == "DMS" then -- Degree Minutes Seconds
|
||||||
|
s = math.floor(s * 100) / 100
|
||||||
|
return string.format('%s %2d°%.2d\'%05.2f"', h, g, m, s)
|
||||||
|
elseif type == "DDM" then -- Degree Decimal Minutes
|
||||||
|
s = math.floor(s / 60 * 1000)
|
||||||
|
return string.format('%s %2d°%02d.%3.3d\'', h, g, m, s)
|
||||||
|
else -- Decimal Degrees
|
||||||
|
return string.format('%f',d)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function getdistance(lat1,lat2,lon1,lon2,unit) -- https://www.geeksforgeeks.org/program-distance-two-points-earth/
|
||||||
|
--Example Locations
|
||||||
|
--lat1 = 42.1578 -- POTI
|
||||||
|
--lat2 = 42.3269 -- HONI
|
||||||
|
--lon1 = 41.6777
|
||||||
|
--lon2 = 42.4122
|
||||||
|
|
||||||
|
local lon1 = toRadians(lon1)
|
||||||
|
local lon2 = toRadians(lon2)
|
||||||
|
local lat1 = toRadians(lat1)
|
||||||
|
local lat2 = toRadians(lat2)
|
||||||
|
|
||||||
|
-- Haversine formula
|
||||||
|
local dlon = lon2 - lon1
|
||||||
|
local dlat = lat2 - lat1
|
||||||
|
local a = math.pow(math.sin(dlat / 2), 2) +
|
||||||
|
math.cos(lat1) * math.cos(lat2) *
|
||||||
|
math.pow(math.sin(dlon / 2),2)
|
||||||
|
|
||||||
|
local c = 2 * math.asin(math.sqrt(a))
|
||||||
|
|
||||||
|
local r -- Radius of earth in X.
|
||||||
|
if unit == 'nm' then
|
||||||
|
r = 6371 / 1.852 -- times 1.852 because I could not find a good NM source
|
||||||
|
elseif unit == 'km' then
|
||||||
|
r = 6371 -- Use 6371 for kilometers
|
||||||
|
elseif unit == 'miles' then
|
||||||
|
r = 3956 -- Use 3956 for miles
|
||||||
|
elseif unit == 'meters' then
|
||||||
|
r = 6371 * 1000
|
||||||
|
end
|
||||||
|
|
||||||
|
-- calculate the result
|
||||||
|
return (c * r)
|
||||||
|
end
|
||||||
|
|
||||||
|
function toRadians(angleIn10thofaDegree)
|
||||||
|
return (angleIn10thofaDegree * math.pi) / 180
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function getBearing(lat1,lat2,lon1,lon2, magnetic)
|
||||||
|
local bearing_rad = math.atan2(lon2 - lon1, lat2 - lat1)
|
||||||
|
if bearing_rad < 0 then
|
||||||
|
bearing_rad = bearing_rad + (2 * math.pi)
|
||||||
|
end
|
||||||
|
|
||||||
|
bearing = math.deg(bearing_rad)
|
||||||
|
|
||||||
|
-- start calculation for getting the magnetic bar
|
||||||
|
local _aircraftPitch, _aircraftBank, aircraftYawTrue = LoGetADIPitchBankYaw()
|
||||||
|
aircraftYawTrue = aircraftYawTrue * 57.3 -- actually heading
|
||||||
|
local aircraftYawMagnetic = LoGetMagneticYaw() * 57.3
|
||||||
|
local magneticVariance = aircraftYawTrue - aircraftYawMagnetic
|
||||||
|
|
||||||
|
if magnetic == true then
|
||||||
|
bearing = bearing - magneticVariance
|
||||||
|
end
|
||||||
|
|
||||||
|
-- correction for bearings less than 0 due to the calculation above
|
||||||
|
if bearing < 0 then
|
||||||
|
bearing = bearing + 360
|
||||||
|
end
|
||||||
|
|
||||||
|
return bearing
|
||||||
|
end
|
||||||
|
|
||||||
|
function addZeros3(number)
|
||||||
|
number = string.format("%.1d" , number)
|
||||||
|
if #number == 2 then
|
||||||
|
number = "0" .. number
|
||||||
|
elseif #number == 1 then
|
||||||
|
number = "00" .. number
|
||||||
|
end
|
||||||
|
return number
|
||||||
|
end
|
||||||
|
|
||||||
|
function prefixZerosFixedLength(number, digitLength) -- prefixZerosFixedLength(99, 3) --> 099
|
||||||
|
number = string.format("%.1d" , number) -- make the number a string
|
||||||
|
local zerosToAdd = digitLength - #number
|
||||||
|
s = ''
|
||||||
|
for i = 1, zerosToAdd do
|
||||||
|
s = s .. 0
|
||||||
|
end
|
||||||
|
return s .. number
|
||||||
|
end
|
||||||
|
|
||||||
|
function mgrsTableize(mgrsString)
|
||||||
|
-- Reference: https://upload.wikimedia.org/wikipedia/commons/b/b7/Universal_Transverse_Mercator_zones.svg
|
||||||
|
-- example: 38 T LM 12345 54321
|
||||||
|
-- (\d+\s\w)\s(\w+)\s(.+)\s(.+) --c# version of regex
|
||||||
|
-- UTMZone = string,
|
||||||
|
-- MGRSDigraph = string,
|
||||||
|
-- Easting = number,
|
||||||
|
-- Northing = number
|
||||||
|
local UTMZone , MGRSDigraph, Easting, Northing = mgrsString:match('(%d+%s%w)%s(%w+)%s(.+)%s(.+)')
|
||||||
|
local mgrsTbl = {}
|
||||||
|
table.insert(mgrsTbl, {UTMZone,MGRSDigraph,Easting,Northing})
|
||||||
|
return mgrsTbl
|
||||||
|
end
|
||||||
|
|
||||||
|
function isNilOrEmpty(value)
|
||||||
|
if value == "" or value == nil then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function NilOrEmpty(value)
|
||||||
|
if value == "" then
|
||||||
|
return 'empty'
|
||||||
|
elseif value == nil then
|
||||||
|
return 'empty'
|
||||||
|
else
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@ -7,9 +7,15 @@ Please report any bugs, conflicts, or fixes on the github.
|
|||||||
https://github.com/asherao/DCS-ExportScripts
|
https://github.com/asherao/DCS-ExportScripts
|
||||||
See the bottom of the file for notes.
|
See the bottom of the file for notes.
|
||||||
Tiles and unique exports will be enabled after testing.
|
Tiles and unique exports will be enabled after testing.
|
||||||
|
~Bailey
|
||||||
*****DISCLAIMER*****
|
*****DISCLAIMER*****
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
|
-- https://github.com/asherao/DCS-ExportScripts
|
||||||
|
local base = _G -- game information
|
||||||
|
local os = base.os -- time
|
||||||
|
local Terrain = require('terrain') -- map info
|
||||||
|
|
||||||
ExportScript.FoundDCSModule = true
|
ExportScript.FoundDCSModule = true
|
||||||
ExportScript.Version.MosquitoFBMkVI = "1.2.1"
|
ExportScript.Version.MosquitoFBMkVI = "1.2.1"
|
||||||
|
|
||||||
@ -106,9 +112,9 @@ ExportScript.ConfigEveryFrameArguments =
|
|||||||
[102] = "%.4f", -- Clock start/stop twist {0.0, 1.0}
|
[102] = "%.4f", -- Clock start/stop twist {0.0, 1.0}
|
||||||
[103] = "%.4f", -- Voltimeter {0.0, 1.0}
|
[103] = "%.4f", -- Voltimeter {0.0, 1.0}
|
||||||
|
|
||||||
[104] = "%.4f", -- T1154M1Gauge
|
[104] = "%.4f", -- unknown ???
|
||||||
[105] = "%.4f", -- T1154M2Gauge
|
[105] = "%.4f", -- unknown ???
|
||||||
[106] = "%.4f", -- T1154M3Gauge
|
[106] = "%.4f", -- unknown ???
|
||||||
|
|
||||||
[110] = "%.4f", -- Rudder trim hand knob needle {-1.0, 1.0}
|
[110] = "%.4f", -- Rudder trim hand knob needle {-1.0, 1.0}
|
||||||
[115] = "%.4f", -- Bomb Doors Lever {-1.0, 1.0}
|
[115] = "%.4f", -- Bomb Doors Lever {-1.0, 1.0}
|
||||||
@ -520,6 +526,17 @@ function ExportScript.ProcessIkarusDCSConfigLowImportance(mainPanelDevice)
|
|||||||
ExportScript.oxygenTile(mainPanelDevice)
|
ExportScript.oxygenTile(mainPanelDevice)
|
||||||
ExportScript.BestPowerTiles(mainPanelDevice)
|
ExportScript.BestPowerTiles(mainPanelDevice)
|
||||||
ExportScript.MaxSpeedTiles(mainPanelDevice)
|
ExportScript.MaxSpeedTiles(mainPanelDevice)
|
||||||
|
|
||||||
|
if LoIsObjectExportAllowed() then -- returns true if world objects data is available
|
||||||
|
if LoIsOwnshipExportAllowed() then -- returns true if ownship data is available
|
||||||
|
ExportScript.LoAircraftInfo(mainPanelDevice) -- Provides a lot of aircraft properties
|
||||||
|
ExportScript.AirportInfo(mainPanelDevice) -- Provides info on the two closest airports
|
||||||
|
ExportScript.WindsAloft(mainPanelDevice) -- Gets winds at the aircraft
|
||||||
|
ExportScript.GroundRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
|
ExportScript.AirRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
|
ExportScript.IglaHunter(mainPanelDevice) -- Locates closest Igla (Use in Single Player)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ExportScript.ProcessDACConfigLowImportance(mainPanelDevice)
|
function ExportScript.ProcessDACConfigLowImportance(mainPanelDevice)
|
||||||
@ -1528,6 +1545,509 @@ function ExportScript.StallSpeeds(mainPanelDevice)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function ExportScript.LoAircraftInfo(mainPanelDevice)
|
||||||
|
|
||||||
|
-- General
|
||||||
|
local aircraftName = LoGetSelfData().Name -- DCS Name of the aircraft eg "F-5E-3"
|
||||||
|
local pilotName = LoGetPilotName() -- Logbook Pilot name
|
||||||
|
|
||||||
|
-- Times DCS times are default in seconds
|
||||||
|
local dcsModelTime = LoGetModelTime() -- time since aircraft spawn
|
||||||
|
local missionStartTime = LoGetMissionStartTime() -- second after midnight that the mission started
|
||||||
|
local dcsTimeLocal = formatTime(LoGetMissionStartTime() + LoGetModelTime()) -- up-to-date time in dcs
|
||||||
|
local utcOffset = -1 * Terrain.GetTerrainConfig('SummerTimeDelta') * 3600 -- eg -1 * 4 * 3600 (for seconds to get hours)
|
||||||
|
local dcsTimeUtc = formatTime(dcsModelTime + LoGetMissionStartTime() + utcOffset) -- dcs zulu time
|
||||||
|
local realTimeLocal = os.date("%H-%M-%S") -- real life time
|
||||||
|
local realTimeUtc = os.date("!%H-%M-%S") -- real life zulu time
|
||||||
|
--local playTime = formatTime(DCS.getRealTime()) -- does not work, export environment no access
|
||||||
|
|
||||||
|
-- Player Aircraft Properties
|
||||||
|
local altMsl_meters = LoGetAltitudeAboveSeaLevel()
|
||||||
|
local altMsl_feet = meters2feet(altMsl_meters)
|
||||||
|
local altAgl_meters = LoGetAltitudeAboveGroundLevel()
|
||||||
|
local altAgl_feet = meters2feet(altAgl_meters)
|
||||||
|
|
||||||
|
local verticalVelocity_metric = LoGetVerticalVelocity()
|
||||||
|
local verticalVelocity_imperial = metersPerSecond2feetPerMinute(LoGetVerticalVelocity())
|
||||||
|
|
||||||
|
local ias_metric = LoGetIndicatedAirSpeed()
|
||||||
|
local ias_knots = metersPerSecond2knots(LoGetIndicatedAirSpeed())
|
||||||
|
local ias_mph = metersPerSecond2milesPerHour(LoGetIndicatedAirSpeed())
|
||||||
|
|
||||||
|
local tas_metric = LoGetTrueAirSpeed()
|
||||||
|
local tas_knots = metersPerSecond2knots(LoGetTrueAirSpeed())
|
||||||
|
local tas_mph = metersPerSecond2milesPerHour(LoGetTrueAirSpeed())
|
||||||
|
|
||||||
|
local speed_mach = LoGetMachNumber()
|
||||||
|
local accel_g = LoGetAccelerationUnits().y
|
||||||
|
local aoa = LoGetAngleOfAttack()
|
||||||
|
|
||||||
|
--local atmosphericPressure_mmhg = LoGetBasicAtmospherePressure() -- does not seem to work
|
||||||
|
|
||||||
|
local aircraftPitch, aircraftBank, aircraftYawTrue = LoGetADIPitchBankYaw()
|
||||||
|
aircraftPitch = aircraftPitch * 57.3
|
||||||
|
aircraftBank = aircraftBank * 57.3
|
||||||
|
aircraftYawTrue = aircraftYawTrue * 57.3 -- true heading
|
||||||
|
local aircraftYawMagnetic = LoGetMagneticYaw() * 57.3 -- magnetic heading
|
||||||
|
local aircraftHeading = aircraftYawMagnetic -- this cound be negative
|
||||||
|
if aircraftHeading < 0 then aircraftHeading = aircraftHeading + 360 end -- removes the negative
|
||||||
|
local magneticVariance = aircraftYawTrue - aircraftYawMagnetic -- works for all maps
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData() -- relative the the player
|
||||||
|
local lLatitude = selfData.LatLongAlt.Lat
|
||||||
|
local lLongitude = selfData.LatLongAlt.Long
|
||||||
|
local mgrs = Terrain.GetMGRScoordinates(LoGetSelfData().Position.x, LoGetSelfData().Position.z)
|
||||||
|
local mgrsTable = mgrsTableize(mgrs) -- format is mgrsTable[1][1], mgrsTable[1][2], mgrsTable[1][3], mgrsTable[1][4]
|
||||||
|
|
||||||
|
local aircraftHeadingTrue = selfData.Heading * 57.3 -- true yeading (same as trueYaw for fixed wing aircraft)
|
||||||
|
|
||||||
|
-- Engine Info
|
||||||
|
local engineInfo = LoGetEngineInfo()
|
||||||
|
local lEngineRPMleft = engineInfo.RPM.left -- ENG1 RPM %
|
||||||
|
local lEngineRPMright = engineInfo.RPM.right -- ENG2 RPM %
|
||||||
|
local lEngineFuelInternal = engineInfo.fuel_internal -- 1 = full. 0 = empty. Includes external tanks for FF aircraft
|
||||||
|
local lEngineFuelExternal = engineInfo.fuel_external -- TANK2 (EXT) (KG) -- does not seem to work for FF modules
|
||||||
|
local lEngineFuelTotal = lEngineFuelInternal + lEngineFuelExternal
|
||||||
|
local lEngineTempLeft = engineInfo.Temperature.left -- ENG1 EGT ºC. May get odd numbers
|
||||||
|
local lEngineTempRight = engineInfo.Temperature.right -- ENG2 EGT ºC. May get odd numbers
|
||||||
|
|
||||||
|
local lFuelConsumptionLeft = engineInfo.FuelConsumption.left -- {left ,right},kg per sec
|
||||||
|
local lFuelConsumptionRight = engineInfo.FuelConsumption.right -- {left ,right},kg per sec
|
||||||
|
local lFuelConsumptionTotal = lFuelConsumptionLeft + lFuelConsumptionRight -- total,kg per sec
|
||||||
|
local lHydraulicPressureLeft = engineInfo.HydraulicPressure.left -- {left ,right},kg per square centimeter
|
||||||
|
local lHydraulicPressureRight = engineInfo.HydraulicPressure.right -- {left ,right},kg per square centimeter
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8000, aircraftName)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8001, pilotName)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8002, 'Real Time\n'.. realTimeLocal .. '\nDCS Time\n' .. dcsTimeLocal) -- clocks
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8003, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_feet,-1)) .. ' ft'
|
||||||
|
.. '\nIAS ' .. round(ias_knots,0) .. ' kts'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_imperial,-2)) .. ' ft/min'
|
||||||
|
) -- Aircraft Instrument panel (western)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8004, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_meters,-1)) .. ' m'
|
||||||
|
.. '\nIAS ' .. round(ias_metric,0) .. ' km/h'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_metric,0)) .. ' m/s'
|
||||||
|
) -- Aircraft Instrument panel (eastern)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8005, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_feet,-1)) .. ' ft'
|
||||||
|
.. '\nIAS ' .. round(ias_mph,0) .. ' mph'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_imperial,-2)) .. ' ft/min'
|
||||||
|
) -- Aircraft Instrument panel (western ww2)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8006, "Lat-Long-DMS\n" .. formatCoord("DMS",true, lLatitude)
|
||||||
|
.. "\n" .. formatCoord("DMS",false, lLongitude)
|
||||||
|
) -- Player coordinates in DMS
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8007, "Lat-Long-DDM\n" .. formatCoord("DDM",true, lLatitude)
|
||||||
|
.. "\n" .. formatCoord("DDM",false, lLongitude)
|
||||||
|
) -- Player coordinates in DDM
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8008, 'MGRS\n'.. mgrsTable[1][1] .. ' ' .. mgrsTable[1][2]
|
||||||
|
.. '\n' .. mgrsTable[1][3] .. ' ' .. mgrsTable[1][4]
|
||||||
|
) -- Player coordinates in MGRS on 2 rows + title
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8009, 'Mag Var\n' .. format_int(round(magneticVariance, 2))) -- also called magnetic deviation
|
||||||
|
|
||||||
|
-- Example for using the Lo Data. Feel free to make your own!
|
||||||
|
ExportScript.Tools.SendData(8010, format_int(round(kgPerSecond2poundPerHour(lFuelConsumptionLeft), -1))) -- fuel use in pph
|
||||||
|
|
||||||
|
end
|
||||||
|
function ExportScript.AirportInfo(mainPanelDevice)
|
||||||
|
|
||||||
|
local airdromes = LoGetWorldObjects("airdromes") -- returns a list of runways and their popperties
|
||||||
|
local airportInfo = {} -- contains generated table of important properties
|
||||||
|
-- the table will be sorted by nearest airport first
|
||||||
|
-- for this table:
|
||||||
|
-- airportInfo[1] is the first element
|
||||||
|
-- airportInfo[1][1] is the airport name of the first element/airport
|
||||||
|
-- airportInfo[1][2] is the distance to the airport of the first element/airport
|
||||||
|
-- airportInfo[1][3] is the bearing to the airport of the first element/airport
|
||||||
|
-- airportInfo[1][4] is the extimated time en route
|
||||||
|
-- airportInfo[1][5] is the direction of the wind
|
||||||
|
-- airportInfo[1][6] is the windStrength of the wind
|
||||||
|
-- airportInfo[1][7] is the main runway heading
|
||||||
|
-- airportInfo[1][8] is the reverse of the main runway
|
||||||
|
-- airportInfo[1][9] is the prefered runway based on winds
|
||||||
|
|
||||||
|
for key,value in pairs(airdromes) do
|
||||||
|
|
||||||
|
-- remove the woRunWay entries so that only named runways are in the list
|
||||||
|
if value.Name ~= 'woRunWay' then
|
||||||
|
|
||||||
|
-- get the distance from the player to the runway
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
-- get the direction from the player to the runway
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
-- estimate the runway heading based on the reported values
|
||||||
|
local runwayHeading = round(value.Heading * 57.3,-1) / 10
|
||||||
|
if runwayHeading < 0 then
|
||||||
|
runwayHeading = 36 + runwayHeading
|
||||||
|
end
|
||||||
|
-- Reverse it for the reciprocal runway
|
||||||
|
local runwayHeadingReciprocal
|
||||||
|
if runwayHeading > 18 then
|
||||||
|
runwayHeadingReciprocal = runwayHeading-18
|
||||||
|
else
|
||||||
|
runwayHeadingReciprocal = runwayHeading+18
|
||||||
|
end
|
||||||
|
|
||||||
|
local ete = distance / metersPerSecond2knots(LoGetTrueAirSpeed()) * (60 * 60) --based on tas bc dcs is flat...
|
||||||
|
-- if ete is more than 24hrs, make it 24 hrs, which shows up as 00-00-00
|
||||||
|
-- this case is for choppers and aircraft that arent moving
|
||||||
|
if ete > 86400 then ete = 86400 end
|
||||||
|
ete = formatTime(ete)
|
||||||
|
|
||||||
|
-- wind at airport calculations. Each airport has slighty different winds
|
||||||
|
-- https://forum.dcs.world/topic/165136-logetwindatpoint-in-exportlua/#comment-3294428
|
||||||
|
-- LoGetWindAtPoint(x,y,z,is_radio_alt), 2 meters off the ground for the "wind sensor"
|
||||||
|
local vx,_vy,vz,_absolute_height = LoGetWindAtPoint(value.Position.x,2,value.Position.y,true)
|
||||||
|
local windDirectionInRadians = math.atan2(vz,vx)
|
||||||
|
local windDirection = windDirectionInRadians * 57.3
|
||||||
|
local windStrength = math.sqrt((vx)^2 + (vz)^2)
|
||||||
|
if windDirection < 0 then
|
||||||
|
windDirection = 360 + windDirection
|
||||||
|
end
|
||||||
|
-- Convert to direction to from direction
|
||||||
|
if windDirection > 180 then
|
||||||
|
windDirection = windDirection - 180
|
||||||
|
else
|
||||||
|
windDirection = windDirection + 180
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate the prefered runway for landing
|
||||||
|
-- if the rounded runway is within +- 9 of the rounded wind, then it is prefered
|
||||||
|
local windRounded = round(windDirection, -1)
|
||||||
|
if windRounded >= runwayHeading - 9 and windRounded <= runwayHeading + 9 then
|
||||||
|
runwayHeadingPrefered = runwayHeading
|
||||||
|
else
|
||||||
|
runwayHeadingPrefered = runwayHeadingReciprocal
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Populate the table with the important info for each airport
|
||||||
|
table.insert(airportInfo, -- the table name
|
||||||
|
{value.Name, -- airport name [1]
|
||||||
|
distance, bearing, ete, --[2][3][4]
|
||||||
|
windDirection,windStrength, --wind direction [5], wind Strength [6]
|
||||||
|
runwayHeading, runwayHeadingReciprocal,runwayHeadingPrefered}) -- [7][8][9]
|
||||||
|
|
||||||
|
end -- end of woRunWay
|
||||||
|
end -- end of FOR loop
|
||||||
|
|
||||||
|
-- sort the table based on the second value, which is distance
|
||||||
|
-- https://stackoverflow.com/questions/51276613/how-to-sort-table-by-value-and-then-print-index-in-order
|
||||||
|
-- https://www.tutorialspoint.com/sort-function-in-lua-programming
|
||||||
|
table.sort(airportInfo, function(a,b) return a[2] < b[2] end)
|
||||||
|
|
||||||
|
-- Primary Airport (closest)
|
||||||
|
ExportScript.Tools.SendData(8101, airportInfo[1][1] .. '\n' -- name of airport
|
||||||
|
--[[.. 'BRG ']] .. format_int(addZeros3(round(airportInfo[1][3],0))) .. 'º ' -- bearing
|
||||||
|
--[[.. 'DIST ']] .. format_int(round(airportInfo[1][2], 0)) .. 'nm\n' -- distance
|
||||||
|
.. 'ETE ' .. airportInfo[1][4] .. '\n' -- estimated time in route
|
||||||
|
.. '' .. prefixZerosFixedLength(round(airportInfo[1][5], 0),3) .. 'º ' -- wind bearing
|
||||||
|
.. round(metersPerSecond2knots(airportInfo[1][6]),0) .. 'kts' -- wing strength
|
||||||
|
.. '\n' .. prefixZerosFixedLength(airportInfo[1][7],2) -- runway 1
|
||||||
|
.. '-' .. prefixZerosFixedLength(airportInfo[1][8],2) -- runway 2
|
||||||
|
.. ' (' .. prefixZerosFixedLength(airportInfo[1][9],2) .. ')') -- prefered runway based on wind in parens
|
||||||
|
|
||||||
|
-- Secondary Airport (second closest)
|
||||||
|
ExportScript.Tools.SendData(8102, airportInfo[2][1] .. '\n' -- name of airport
|
||||||
|
--[[.. 'BRG ']] .. format_int(addZeros3(round(airportInfo[2][3],0))) .. 'º ' -- bearing
|
||||||
|
--[[.. 'DIST ']] .. format_int(round(airportInfo[2][2], 0)) .. 'nm\n' -- distance
|
||||||
|
.. 'ETE ' .. airportInfo[2][4] .. '\n' -- estimated time in route
|
||||||
|
.. '' .. prefixZerosFixedLength(round(airportInfo[2][5], 0),3) .. 'º ' -- wind bearing
|
||||||
|
.. round(metersPerSecond2knots(airportInfo[2][6]),0) .. 'kts' -- wing strength
|
||||||
|
.. '\n' .. prefixZerosFixedLength(airportInfo[2][7],2) -- runway 1
|
||||||
|
.. '-' .. prefixZerosFixedLength(airportInfo[2][8],2) -- runway 2
|
||||||
|
.. ' (' .. prefixZerosFixedLength(airportInfo[2][9],2) .. ')') -- prefered runway based on wind in parens
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.WindsAloft(mainPanelDevice)
|
||||||
|
|
||||||
|
-- Winds relative to the aircraft, aka, winds aloft
|
||||||
|
local windAloft = LoGetVectorWindVelocity()
|
||||||
|
local windStrengthAloft = math.sqrt((windAloft.x)^2 + (windAloft.z)^2)
|
||||||
|
local windDirectionAloft = math.deg(math.atan2(windAloft.z, windAloft.x))
|
||||||
|
if windDirectionAloft < 0 then
|
||||||
|
windDirectionAloft = 360 + windDirectionAloft
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert to direction to from direction
|
||||||
|
if windDirectionAloft > 180 then
|
||||||
|
windDirectionAloft = windDirectionAloft - 180
|
||||||
|
else
|
||||||
|
windDirectionAloft = windDirectionAloft + 180
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8100, 'Wind Aloft\n' .. addZeros3(round(windDirectionAloft,0)) .. 'º '
|
||||||
|
.. round(metersPerSecond2knots(windStrengthAloft,0)) .. 'kts'
|
||||||
|
) -- winds at the aircraft
|
||||||
|
end
|
||||||
|
function ExportScript.GroundRadar(mainPanelDevice) -- may return some odd things
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
|
||||||
|
local tableOfGround = {}
|
||||||
|
-- relative to the player...
|
||||||
|
local tableOfGround_friendly = {}
|
||||||
|
local tableOfGround_friendlyReports = {}
|
||||||
|
local tableOfGround_enemy = {}
|
||||||
|
local tableOfGround_enemyReports = {}
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.Type.level1 == 2 then
|
||||||
|
table.insert(tableOfGround, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfGround) do
|
||||||
|
if value.CoalitionID == selfCoalitionID then
|
||||||
|
table.insert(tableOfGround_friendly, value)
|
||||||
|
else
|
||||||
|
table.insert(tableOfGround_enemy, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: only do enemy reports if there is an awacs unit(?)
|
||||||
|
for key,value in pairs(tableOfGround_enemy) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfGround_enemyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
end
|
||||||
|
table.sort(tableOfGround_enemyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfGround_friendly) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfGround_friendlyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfGround_friendlyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8200 = 'No Ground\nEnemy\nDetected'
|
||||||
|
if tableOfGround_enemyReports[1] ~= nill then
|
||||||
|
string_8200 = 'Enemy Ground\n' .. tableOfGround_enemyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_enemyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_enemyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8201 = 'No Ground\nEnemy\nDetected'
|
||||||
|
if tableOfGround_enemyReports[2] ~= nill then
|
||||||
|
string_8201 = 'Enemy Ground\n'.. tableOfGround_enemyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_enemyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_enemyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8202 = 'No Ground\nFriend\nDetected'
|
||||||
|
if tableOfGround_friendlyReports[1] ~= nill then
|
||||||
|
string_8202 = 'Friend Ground\n' .. tableOfGround_friendlyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_friendlyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_friendlyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8203 = 'No Ground\nFriend\nDetected'
|
||||||
|
if tableOfGround_friendlyReports[2] ~= nill then
|
||||||
|
string_8203 = 'Friend Ground\n' .. tableOfGround_friendlyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_friendlyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_friendlyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8200, string_8200)
|
||||||
|
ExportScript.Tools.SendData(8201, string_8201)
|
||||||
|
ExportScript.Tools.SendData(8202, string_8202)
|
||||||
|
ExportScript.Tools.SendData(8203, string_8203)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.AirRadar(mainPanelDevice)
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
|
||||||
|
local tableOfAircraft = {}
|
||||||
|
-- relative to the player...
|
||||||
|
local tableOfAircraft_friendly = {}
|
||||||
|
local tableOfAircraft_friendlyReports = {}
|
||||||
|
local tableOfAircraft_enemy = {}
|
||||||
|
local tableOfAircraft_enemyReports = {}
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.Type.level1 == 1 then
|
||||||
|
table.insert(tableOfAircraft, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfAircraft) do
|
||||||
|
if value.CoalitionID == selfCoalitionID then
|
||||||
|
table.insert(tableOfAircraft_friendly, value)
|
||||||
|
else
|
||||||
|
table.insert(tableOfAircraft_enemy, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: only do enemy reports if there is a awacs unit
|
||||||
|
for key,value in pairs(tableOfAircraft_enemy) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfAircraft_enemyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
-- https://stackoverflow.com/questions/51276613/how-to-sort-table-by-value-and-then-print-index-in-order
|
||||||
|
-- https://www.tutorialspoint.com/sort-function-in-lua-programming
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfAircraft_enemyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfAircraft_friendly) do -- [1] will always be the player
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfAircraft_friendlyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfAircraft_friendlyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8210 = 'No Air\nEnemy\nDetected'
|
||||||
|
if tableOfAircraft_enemyReports[1] ~= nill then
|
||||||
|
string_8210 = 'Enemy Air\n' .. tableOfAircraft_enemyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_enemyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_enemyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8211 = 'No Air\nEnemy\nDetected'
|
||||||
|
if tableOfAircraft_enemyReports[2] ~= nill then
|
||||||
|
string_8211 = 'Enemy Air\n' .. tableOfAircraft_enemyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_enemyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_enemyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8212 = 'No Air\nFriend\nDetected'
|
||||||
|
if tableOfAircraft_friendlyReports[2] ~= nill then
|
||||||
|
string_8212 = 'Friend Air\n' .. tableOfAircraft_friendlyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_friendlyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_friendlyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8213 = 'No Air\nFriend\nDetected'
|
||||||
|
if tableOfAircraft_friendlyReports[3] ~= nill then
|
||||||
|
string_8213 = 'Friend Air\n' .. tableOfAircraft_friendlyReports[3][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_friendlyReports[3][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_friendlyReports[3][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8210,string_8210)
|
||||||
|
ExportScript.Tools.SendData(8211, string_8211)
|
||||||
|
ExportScript.Tools.SendData(8212, string_8212)
|
||||||
|
ExportScript.Tools.SendData(8213, string_8213)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.IglaHunter(mainPanelDevice) -- Locates the nearest Igla
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
local tableOfIgla = {}
|
||||||
|
local tableOfIgla_report = {}
|
||||||
|
|
||||||
|
--TODO: Might have to refine this.
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.CoalitionID ~= selfCoalitionID then
|
||||||
|
if value.Type.level3 == 27 then
|
||||||
|
if value.Type.level2 == 16 then
|
||||||
|
if value.Type.level1 == 2 then
|
||||||
|
if value.Type.level4 == 55 or 54 or 53 or 52 or 62 then
|
||||||
|
table.insert(tableOfIgla, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--if tableOfIgla ~= null then
|
||||||
|
for key,value in pairs(tableOfIgla) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfIgla_report, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
table.sort(tableOfIgla_report, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8666 = 'Igla Hunter\nSearching...'
|
||||||
|
if tableOfIgla_report[1] ~= nill then
|
||||||
|
string_8666 = 'Igla Detected\n' .. tableOfIgla_report[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfIgla_report[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfIgla_report[1][2],0) .. ' nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8666, string_8666)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
------------------------------
|
------------------------------
|
||||||
-- Ideas for implementation --
|
-- Ideas for implementation --
|
||||||
@ -1677,6 +2197,9 @@ end
|
|||||||
-- General Helper Functions --
|
-- General Helper Functions --
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
|
----------------------
|
||||||
|
-- Helper Functions --
|
||||||
|
----------------------
|
||||||
function ExportScript.Linearize(current_value, raw_tab, final_tab)
|
function ExportScript.Linearize(current_value, raw_tab, final_tab)
|
||||||
-- (c) scoobie
|
-- (c) scoobie
|
||||||
if current_value <= raw_tab[1] then
|
if current_value <= raw_tab[1] then
|
||||||
@ -1693,29 +2216,197 @@ function ExportScript.Linearize(current_value, raw_tab, final_tab)
|
|||||||
return final_tab[#final_tab]
|
return final_tab[#final_tab]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function trim(s) --http://lua-users.org/wiki/CommonFunctions
|
||||||
|
-- from PiL2 20.4
|
||||||
|
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||||
|
end
|
||||||
|
function formatTime(time)
|
||||||
|
local seconds = math.floor(time) % 60
|
||||||
|
local minutes = math.floor(time / 60) % 60
|
||||||
|
local hours = math.floor(time / (60 * 60)) % 24
|
||||||
|
return string.format("%02d", hours) .. "-" .. string.format("%02d", minutes) .. "-" .. string.format("%02d", seconds)
|
||||||
|
end
|
||||||
|
|
||||||
|
function meters2feet(meters)
|
||||||
|
local feet = meters * 3.281
|
||||||
|
return feet
|
||||||
|
end
|
||||||
|
|
||||||
|
function feet2meters(feet)
|
||||||
|
local meters = feet / 3.281
|
||||||
|
return feet
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2milesPerHour(metersPerSecond)
|
||||||
|
local milesPerHour = metersPerSecond * 2.237
|
||||||
|
return milesPerHour
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2knots(metersPerSecond)
|
||||||
|
local knots = metersPerSecond * 1.944
|
||||||
|
return knots
|
||||||
|
end
|
||||||
|
|
||||||
|
function kgPerSecond2poundPerHour(kgPerSecond)
|
||||||
|
poundPerHour = kgPerSecond * 7937
|
||||||
|
return poundPerHour
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2feetPerMinute(metersPerSecond)
|
||||||
|
local feetPerMinute = metersPerSecond * 197
|
||||||
|
return feetPerMinute
|
||||||
|
end
|
||||||
|
|
||||||
function round(num, numDecimalPlaces) --http://lua-users.org/wiki/SimpleRound
|
function round(num, numDecimalPlaces) --http://lua-users.org/wiki/SimpleRound
|
||||||
local mult = 10^(numDecimalPlaces or 0)
|
local mult = 10^(numDecimalPlaces or 0)
|
||||||
return math.floor(num * mult + 0.5) / mult
|
return math.floor(num * mult + 0.5) / mult
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function format_int(number) --https://stackoverflow.com/questions/10989788/format-integer-in-lua
|
function format_int(number) --https://stackoverflow.com/questions/10989788/format-integer-in-lua
|
||||||
|
|
||||||
local i, j, minus, int, fraction = tostring(number):find('([-]?)(%d+)([.]?%d*)')
|
local i, j, minus, int, fraction = tostring(number):find('([-]?)(%d+)([.]?%d*)')
|
||||||
|
|
||||||
-- reverse the int-string and append a comma to all blocks of 3 digits
|
-- reverse the int-string and append a comma to all blocks of 3 digits
|
||||||
int = int:reverse():gsub("(%d%d%d)", "%1,")
|
int = int:reverse():gsub("(%d%d%d)", "%1,")
|
||||||
|
|
||||||
-- reverse the int-string back remove an optional comma and put the
|
-- reverse the int-string back remove an optional comma and put the
|
||||||
-- optional minus and fractional part back
|
-- optional minus and fractional part back
|
||||||
return minus .. int:reverse():gsub("^,", "") .. fraction
|
return minus .. int:reverse():gsub("^,", "") .. fraction
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function formatCoord(type, isLat, d)
|
||||||
|
local h
|
||||||
|
if isLat then
|
||||||
|
if d < 0 then
|
||||||
|
h = 'S'
|
||||||
|
d = -d
|
||||||
|
else
|
||||||
|
h = 'N'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if d < 0 then
|
||||||
|
h = 'W'
|
||||||
|
d = -d
|
||||||
|
else
|
||||||
|
h = 'E'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local g = math.floor(d)
|
||||||
|
local m = math.floor(d * 60 - g * 60)
|
||||||
|
local s = d * 3600 - g * 3600 - m * 60
|
||||||
|
|
||||||
|
if type == "DMS" then -- Degree Minutes Seconds
|
||||||
|
s = math.floor(s * 100) / 100
|
||||||
|
return string.format('%s %2d°%.2d\'%05.2f"', h, g, m, s)
|
||||||
|
elseif type == "DDM" then -- Degree Decimal Minutes
|
||||||
|
s = math.floor(s / 60 * 1000)
|
||||||
|
return string.format('%s %2d°%02d.%3.3d\'', h, g, m, s)
|
||||||
|
else -- Decimal Degrees
|
||||||
|
return string.format('%f',d)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function getdistance(lat1,lat2,lon1,lon2,unit) -- https://www.geeksforgeeks.org/program-distance-two-points-earth/
|
||||||
|
--Example Locations
|
||||||
|
--lat1 = 42.1578 -- POTI
|
||||||
|
--lat2 = 42.3269 -- HONI
|
||||||
|
--lon1 = 41.6777
|
||||||
|
--lon2 = 42.4122
|
||||||
|
|
||||||
|
local lon1 = toRadians(lon1)
|
||||||
|
local lon2 = toRadians(lon2)
|
||||||
|
local lat1 = toRadians(lat1)
|
||||||
|
local lat2 = toRadians(lat2)
|
||||||
|
|
||||||
|
-- Haversine formula
|
||||||
|
local dlon = lon2 - lon1
|
||||||
|
local dlat = lat2 - lat1
|
||||||
|
local a = math.pow(math.sin(dlat / 2), 2) +
|
||||||
|
math.cos(lat1) * math.cos(lat2) *
|
||||||
|
math.pow(math.sin(dlon / 2),2)
|
||||||
|
|
||||||
|
local c = 2 * math.asin(math.sqrt(a))
|
||||||
|
|
||||||
|
local r -- Radius of earth in X.
|
||||||
|
if unit == 'nm' then
|
||||||
|
r = 6371 / 1.852 -- times 1.852 because I could not find a good NM source
|
||||||
|
elseif unit == 'km' then
|
||||||
|
r = 6371 -- Use 6371 for kilometers
|
||||||
|
elseif unit == 'miles' then
|
||||||
|
r = 3956 -- Use 3956 for miles
|
||||||
|
elseif unit == 'meters' then
|
||||||
|
r = 6371 * 1000
|
||||||
|
end
|
||||||
|
|
||||||
|
-- calculate the result
|
||||||
|
return (c * r)
|
||||||
|
end
|
||||||
|
|
||||||
|
function toRadians(angleIn10thofaDegree)
|
||||||
|
return (angleIn10thofaDegree * math.pi) / 180
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function getBearing(lat1,lat2,lon1,lon2, magnetic)
|
||||||
|
local bearing_rad = math.atan2(lon2 - lon1, lat2 - lat1)
|
||||||
|
if bearing_rad < 0 then
|
||||||
|
bearing_rad = bearing_rad + (2 * math.pi)
|
||||||
|
end
|
||||||
|
|
||||||
|
bearing = math.deg(bearing_rad)
|
||||||
|
|
||||||
|
-- start calculation for getting the magnetic bar
|
||||||
|
local _aircraftPitch, _aircraftBank, aircraftYawTrue = LoGetADIPitchBankYaw()
|
||||||
|
aircraftYawTrue = aircraftYawTrue * 57.3 -- actually heading
|
||||||
|
local aircraftYawMagnetic = LoGetMagneticYaw() * 57.3
|
||||||
|
local magneticVariance = aircraftYawTrue - aircraftYawMagnetic
|
||||||
|
|
||||||
|
if magnetic == true then
|
||||||
|
bearing = bearing - magneticVariance
|
||||||
|
end
|
||||||
|
|
||||||
|
-- correction for bearings less than 0 due to the calculation above
|
||||||
|
if bearing < 0 then
|
||||||
|
bearing = bearing + 360
|
||||||
|
end
|
||||||
|
|
||||||
|
return bearing
|
||||||
|
end
|
||||||
|
|
||||||
|
function addZeros3(number)
|
||||||
|
number = string.format("%.1d" , number)
|
||||||
|
if #number == 2 then
|
||||||
|
number = "0" .. number
|
||||||
|
elseif #number == 1 then
|
||||||
|
number = "00" .. number
|
||||||
|
end
|
||||||
|
return number
|
||||||
|
end
|
||||||
|
|
||||||
|
function prefixZerosFixedLength(number, digitLength) -- prefixZerosFixedLength(99, 3) --> 099
|
||||||
|
number = string.format("%.1d" , number) -- make the number a string
|
||||||
|
local zerosToAdd = digitLength - #number
|
||||||
|
s = ''
|
||||||
|
for i = 1, zerosToAdd do
|
||||||
|
s = s .. 0
|
||||||
|
end
|
||||||
|
return s .. number
|
||||||
|
end
|
||||||
|
|
||||||
|
function mgrsTableize(mgrsString)
|
||||||
|
-- Reference: https://upload.wikimedia.org/wikipedia/commons/b/b7/Universal_Transverse_Mercator_zones.svg
|
||||||
|
-- example: 38 T LM 12345 54321
|
||||||
|
-- (\d+\s\w)\s(\w+)\s(.+)\s(.+) --c# version of regex
|
||||||
|
-- UTMZone = string,
|
||||||
|
-- MGRSDigraph = string,
|
||||||
|
-- Easting = number,
|
||||||
|
-- Northing = number
|
||||||
|
local UTMZone , MGRSDigraph, Easting, Northing = mgrsString:match('(%d+%s%w)%s(%w+)%s(.+)%s(.+)')
|
||||||
|
local mgrsTbl = {}
|
||||||
|
table.insert(mgrsTbl, {UTMZone,MGRSDigraph,Easting,Northing})
|
||||||
|
return mgrsTbl
|
||||||
|
end
|
||||||
|
|
||||||
function kts2mph(kts) -- converts kts to floored mph
|
function kts2mph(kts) -- converts kts to floored mph
|
||||||
local mph = kts * 1.15078
|
local mph = kts * 1.15078
|
||||||
mph = math.floor(mph)
|
mph = math.floor(mph)
|
||||||
return mph
|
return mph
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1,5 +1,10 @@
|
|||||||
-- P-51D-25-NA Export
|
-- P-51D-25-NA Export
|
||||||
|
|
||||||
|
-- https://github.com/asherao/DCS-ExportScripts
|
||||||
|
local base = _G -- game information
|
||||||
|
local os = base.os -- time
|
||||||
|
local Terrain = require('terrain') -- map info
|
||||||
|
|
||||||
ExportScript.FoundDCSModule = true
|
ExportScript.FoundDCSModule = true
|
||||||
ExportScript.Version.P51D25NA = "1.2.1"
|
ExportScript.Version.P51D25NA = "1.2.1"
|
||||||
|
|
||||||
@ -278,16 +283,17 @@ end
|
|||||||
|
|
||||||
-- Pointed to by ExportScript.ProcessIkarusDCSConfigLowImportance
|
-- Pointed to by ExportScript.ProcessIkarusDCSConfigLowImportance
|
||||||
function ExportScript.ProcessIkarusDCSConfigLowImportance(mainPanelDevice)
|
function ExportScript.ProcessIkarusDCSConfigLowImportance(mainPanelDevice)
|
||||||
--[[
|
|
||||||
export in low tick interval to Ikarus
|
if LoIsObjectExportAllowed() then -- returns true if world objects data is available
|
||||||
Example from A-10C
|
if LoIsOwnshipExportAllowed() then -- returns true if ownship data is available
|
||||||
Get Radio Frequencies
|
ExportScript.LoAircraftInfo(mainPanelDevice) -- Provides a lot of aircraft properties
|
||||||
get data from device
|
ExportScript.AirportInfo(mainPanelDevice) -- Provides info on the two closest airports
|
||||||
local lUHFRadio = GetDevice(54)
|
ExportScript.WindsAloft(mainPanelDevice) -- Gets winds at the aircraft
|
||||||
ExportScript.Tools.SendData("ExportID", "Format")
|
ExportScript.GroundRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
ExportScript.Tools.SendData(2000, string.format("%7.3f", lUHFRadio:get_frequency()/1000000)) -- <- special function for get frequency data
|
ExportScript.AirRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
ExportScript.Tools.SendData(2000, ExportScript.Tools.RoundFreqeuncy((UHF_RADIO:get_frequency()/1000000))) -- ExportScript.Tools.RoundFreqeuncy(frequency (MHz|KHz), format ("7.3"), PrefixZeros (false), LeastValue (0.025))
|
ExportScript.IglaHunter(mainPanelDevice) -- Locates closest Igla (Use in Single Player)
|
||||||
]]
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ExportScript.ProcessDACConfigLowImportance(mainPanelDevice)
|
function ExportScript.ProcessDACConfigLowImportance(mainPanelDevice)
|
||||||
@ -329,3 +335,714 @@ end
|
|||||||
-----------------------------
|
-----------------------------
|
||||||
-- Custom functions --
|
-- Custom functions --
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
function ExportScript.LoAircraftInfo(mainPanelDevice)
|
||||||
|
|
||||||
|
-- General
|
||||||
|
local aircraftName = LoGetSelfData().Name -- DCS Name of the aircraft eg "F-5E-3"
|
||||||
|
local pilotName = LoGetPilotName() -- Logbook Pilot name
|
||||||
|
|
||||||
|
-- Times DCS times are default in seconds
|
||||||
|
local dcsModelTime = LoGetModelTime() -- time since aircraft spawn
|
||||||
|
local missionStartTime = LoGetMissionStartTime() -- second after midnight that the mission started
|
||||||
|
local dcsTimeLocal = formatTime(LoGetMissionStartTime() + LoGetModelTime()) -- up-to-date time in dcs
|
||||||
|
local utcOffset = -1 * Terrain.GetTerrainConfig('SummerTimeDelta') * 3600 -- eg -1 * 4 * 3600 (for seconds to get hours)
|
||||||
|
local dcsTimeUtc = formatTime(dcsModelTime + LoGetMissionStartTime() + utcOffset) -- dcs zulu time
|
||||||
|
local realTimeLocal = os.date("%H-%M-%S") -- real life time
|
||||||
|
local realTimeUtc = os.date("!%H-%M-%S") -- real life zulu time
|
||||||
|
--local playTime = formatTime(DCS.getRealTime()) -- does not work, export environment no access
|
||||||
|
|
||||||
|
-- Player Aircraft Properties
|
||||||
|
local altMsl_meters = LoGetAltitudeAboveSeaLevel()
|
||||||
|
local altMsl_feet = meters2feet(altMsl_meters)
|
||||||
|
local altAgl_meters = LoGetAltitudeAboveGroundLevel()
|
||||||
|
local altAgl_feet = meters2feet(altAgl_meters)
|
||||||
|
|
||||||
|
local verticalVelocity_metric = LoGetVerticalVelocity()
|
||||||
|
local verticalVelocity_imperial = metersPerSecond2feetPerMinute(LoGetVerticalVelocity())
|
||||||
|
|
||||||
|
local ias_metric = LoGetIndicatedAirSpeed()
|
||||||
|
local ias_knots = metersPerSecond2knots(LoGetIndicatedAirSpeed())
|
||||||
|
local ias_mph = metersPerSecond2milesPerHour(LoGetIndicatedAirSpeed())
|
||||||
|
|
||||||
|
local tas_metric = LoGetTrueAirSpeed()
|
||||||
|
local tas_knots = metersPerSecond2knots(LoGetTrueAirSpeed())
|
||||||
|
local tas_mph = metersPerSecond2milesPerHour(LoGetTrueAirSpeed())
|
||||||
|
|
||||||
|
local speed_mach = LoGetMachNumber()
|
||||||
|
local accel_g = LoGetAccelerationUnits().y
|
||||||
|
local aoa = LoGetAngleOfAttack()
|
||||||
|
|
||||||
|
--local atmosphericPressure_mmhg = LoGetBasicAtmospherePressure() -- does not seem to work
|
||||||
|
|
||||||
|
local aircraftPitch, aircraftBank, aircraftYawTrue = LoGetADIPitchBankYaw()
|
||||||
|
aircraftPitch = aircraftPitch * 57.3
|
||||||
|
aircraftBank = aircraftBank * 57.3
|
||||||
|
aircraftYawTrue = aircraftYawTrue * 57.3 -- true heading
|
||||||
|
local aircraftYawMagnetic = LoGetMagneticYaw() * 57.3 -- magnetic heading
|
||||||
|
local aircraftHeading = aircraftYawMagnetic -- this cound be negative
|
||||||
|
if aircraftHeading < 0 then aircraftHeading = aircraftHeading + 360 end -- removes the negative
|
||||||
|
local magneticVariance = aircraftYawTrue - aircraftYawMagnetic -- works for all maps
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData() -- relative the the player
|
||||||
|
local lLatitude = selfData.LatLongAlt.Lat
|
||||||
|
local lLongitude = selfData.LatLongAlt.Long
|
||||||
|
local mgrs = Terrain.GetMGRScoordinates(LoGetSelfData().Position.x, LoGetSelfData().Position.z)
|
||||||
|
local mgrsTable = mgrsTableize(mgrs) -- format is mgrsTable[1][1], mgrsTable[1][2], mgrsTable[1][3], mgrsTable[1][4]
|
||||||
|
|
||||||
|
local aircraftHeadingTrue = selfData.Heading * 57.3 -- true yeading (same as trueYaw for fixed wing aircraft)
|
||||||
|
|
||||||
|
-- Engine Info
|
||||||
|
local engineInfo = LoGetEngineInfo()
|
||||||
|
local lEngineRPMleft = engineInfo.RPM.left -- ENG1 RPM %
|
||||||
|
local lEngineRPMright = engineInfo.RPM.right -- ENG2 RPM %
|
||||||
|
local lEngineFuelInternal = engineInfo.fuel_internal -- 1 = full. 0 = empty. Includes external tanks for FF aircraft
|
||||||
|
local lEngineFuelExternal = engineInfo.fuel_external -- TANK2 (EXT) (KG) -- does not seem to work for FF modules
|
||||||
|
local lEngineFuelTotal = lEngineFuelInternal + lEngineFuelExternal
|
||||||
|
local lEngineTempLeft = engineInfo.Temperature.left -- ENG1 EGT ºC. May get odd numbers
|
||||||
|
local lEngineTempRight = engineInfo.Temperature.right -- ENG2 EGT ºC. May get odd numbers
|
||||||
|
|
||||||
|
local lFuelConsumptionLeft = engineInfo.FuelConsumption.left -- {left ,right},kg per sec
|
||||||
|
local lFuelConsumptionRight = engineInfo.FuelConsumption.right -- {left ,right},kg per sec
|
||||||
|
local lFuelConsumptionTotal = lFuelConsumptionLeft + lFuelConsumptionRight -- total,kg per sec
|
||||||
|
local lHydraulicPressureLeft = engineInfo.HydraulicPressure.left -- {left ,right},kg per square centimeter
|
||||||
|
local lHydraulicPressureRight = engineInfo.HydraulicPressure.right -- {left ,right},kg per square centimeter
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8000, aircraftName)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8001, pilotName)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8002, 'Real Time\n'.. realTimeLocal .. '\nDCS Time\n' .. dcsTimeLocal) -- clocks
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8003, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_feet,-1)) .. ' ft'
|
||||||
|
.. '\nIAS ' .. round(ias_knots,0) .. ' kts'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_imperial,-2)) .. ' ft/min'
|
||||||
|
) -- Aircraft Instrument panel (western)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8004, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_meters,-1)) .. ' m'
|
||||||
|
.. '\nIAS ' .. round(ias_metric,0) .. ' km/h'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_metric,0)) .. ' m/s'
|
||||||
|
) -- Aircraft Instrument panel (eastern)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8005, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_feet,-1)) .. ' ft'
|
||||||
|
.. '\nIAS ' .. round(ias_mph,0) .. ' mph'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_imperial,-2)) .. ' ft/min'
|
||||||
|
) -- Aircraft Instrument panel (western ww2)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8006, "Lat-Long-DMS\n" .. formatCoord("DMS",true, lLatitude)
|
||||||
|
.. "\n" .. formatCoord("DMS",false, lLongitude)
|
||||||
|
) -- Player coordinates in DMS
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8007, "Lat-Long-DDM\n" .. formatCoord("DDM",true, lLatitude)
|
||||||
|
.. "\n" .. formatCoord("DDM",false, lLongitude)
|
||||||
|
) -- Player coordinates in DDM
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8008, 'MGRS\n'.. mgrsTable[1][1] .. ' ' .. mgrsTable[1][2]
|
||||||
|
.. '\n' .. mgrsTable[1][3] .. ' ' .. mgrsTable[1][4]
|
||||||
|
) -- Player coordinates in MGRS on 2 rows + title
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8009, 'Mag Var\n' .. format_int(round(magneticVariance, 2))) -- also called magnetic deviation
|
||||||
|
|
||||||
|
-- Example for using the Lo Data. Feel free to make your own!
|
||||||
|
ExportScript.Tools.SendData(8010, format_int(round(kgPerSecond2poundPerHour(lFuelConsumptionLeft), -1))) -- fuel use in pph
|
||||||
|
|
||||||
|
end
|
||||||
|
function ExportScript.AirportInfo(mainPanelDevice)
|
||||||
|
|
||||||
|
local airdromes = LoGetWorldObjects("airdromes") -- returns a list of runways and their popperties
|
||||||
|
local airportInfo = {} -- contains generated table of important properties
|
||||||
|
-- the table will be sorted by nearest airport first
|
||||||
|
-- for this table:
|
||||||
|
-- airportInfo[1] is the first element
|
||||||
|
-- airportInfo[1][1] is the airport name of the first element/airport
|
||||||
|
-- airportInfo[1][2] is the distance to the airport of the first element/airport
|
||||||
|
-- airportInfo[1][3] is the bearing to the airport of the first element/airport
|
||||||
|
-- airportInfo[1][4] is the extimated time en route
|
||||||
|
-- airportInfo[1][5] is the direction of the wind
|
||||||
|
-- airportInfo[1][6] is the windStrength of the wind
|
||||||
|
-- airportInfo[1][7] is the main runway heading
|
||||||
|
-- airportInfo[1][8] is the reverse of the main runway
|
||||||
|
-- airportInfo[1][9] is the prefered runway based on winds
|
||||||
|
|
||||||
|
for key,value in pairs(airdromes) do
|
||||||
|
|
||||||
|
-- remove the woRunWay entries so that only named runways are in the list
|
||||||
|
if value.Name ~= 'woRunWay' then
|
||||||
|
|
||||||
|
-- get the distance from the player to the runway
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
-- get the direction from the player to the runway
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
-- estimate the runway heading based on the reported values
|
||||||
|
local runwayHeading = round(value.Heading * 57.3,-1) / 10
|
||||||
|
if runwayHeading < 0 then
|
||||||
|
runwayHeading = 36 + runwayHeading
|
||||||
|
end
|
||||||
|
-- Reverse it for the reciprocal runway
|
||||||
|
local runwayHeadingReciprocal
|
||||||
|
if runwayHeading > 18 then
|
||||||
|
runwayHeadingReciprocal = runwayHeading-18
|
||||||
|
else
|
||||||
|
runwayHeadingReciprocal = runwayHeading+18
|
||||||
|
end
|
||||||
|
|
||||||
|
local ete = distance / metersPerSecond2knots(LoGetTrueAirSpeed()) * (60 * 60) --based on tas bc dcs is flat...
|
||||||
|
-- if ete is more than 24hrs, make it 24 hrs, which shows up as 00-00-00
|
||||||
|
-- this case is for choppers and aircraft that arent moving
|
||||||
|
if ete > 86400 then ete = 86400 end
|
||||||
|
ete = formatTime(ete)
|
||||||
|
|
||||||
|
-- wind at airport calculations. Each airport has slighty different winds
|
||||||
|
-- https://forum.dcs.world/topic/165136-logetwindatpoint-in-exportlua/#comment-3294428
|
||||||
|
-- LoGetWindAtPoint(x,y,z,is_radio_alt), 2 meters off the ground for the "wind sensor"
|
||||||
|
local vx,_vy,vz,_absolute_height = LoGetWindAtPoint(value.Position.x,2,value.Position.y,true)
|
||||||
|
local windDirectionInRadians = math.atan2(vz,vx)
|
||||||
|
local windDirection = windDirectionInRadians * 57.3
|
||||||
|
local windStrength = math.sqrt((vx)^2 + (vz)^2)
|
||||||
|
if windDirection < 0 then
|
||||||
|
windDirection = 360 + windDirection
|
||||||
|
end
|
||||||
|
-- Convert to direction to from direction
|
||||||
|
if windDirection > 180 then
|
||||||
|
windDirection = windDirection - 180
|
||||||
|
else
|
||||||
|
windDirection = windDirection + 180
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate the prefered runway for landing
|
||||||
|
-- if the rounded runway is within +- 9 of the rounded wind, then it is prefered
|
||||||
|
local windRounded = round(windDirection, -1)
|
||||||
|
if windRounded >= runwayHeading - 9 and windRounded <= runwayHeading + 9 then
|
||||||
|
runwayHeadingPrefered = runwayHeading
|
||||||
|
else
|
||||||
|
runwayHeadingPrefered = runwayHeadingReciprocal
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Populate the table with the important info for each airport
|
||||||
|
table.insert(airportInfo, -- the table name
|
||||||
|
{value.Name, -- airport name [1]
|
||||||
|
distance, bearing, ete, --[2][3][4]
|
||||||
|
windDirection,windStrength, --wind direction [5], wind Strength [6]
|
||||||
|
runwayHeading, runwayHeadingReciprocal,runwayHeadingPrefered}) -- [7][8][9]
|
||||||
|
|
||||||
|
end -- end of woRunWay
|
||||||
|
end -- end of FOR loop
|
||||||
|
|
||||||
|
-- sort the table based on the second value, which is distance
|
||||||
|
-- https://stackoverflow.com/questions/51276613/how-to-sort-table-by-value-and-then-print-index-in-order
|
||||||
|
-- https://www.tutorialspoint.com/sort-function-in-lua-programming
|
||||||
|
table.sort(airportInfo, function(a,b) return a[2] < b[2] end)
|
||||||
|
|
||||||
|
-- Primary Airport (closest)
|
||||||
|
ExportScript.Tools.SendData(8101, airportInfo[1][1] .. '\n' -- name of airport
|
||||||
|
--[[.. 'BRG ']] .. format_int(addZeros3(round(airportInfo[1][3],0))) .. 'º ' -- bearing
|
||||||
|
--[[.. 'DIST ']] .. format_int(round(airportInfo[1][2], 0)) .. 'nm\n' -- distance
|
||||||
|
.. 'ETE ' .. airportInfo[1][4] .. '\n' -- estimated time in route
|
||||||
|
.. '' .. prefixZerosFixedLength(round(airportInfo[1][5], 0),3) .. 'º ' -- wind bearing
|
||||||
|
.. round(metersPerSecond2knots(airportInfo[1][6]),0) .. 'kts' -- wing strength
|
||||||
|
.. '\n' .. prefixZerosFixedLength(airportInfo[1][7],2) -- runway 1
|
||||||
|
.. '-' .. prefixZerosFixedLength(airportInfo[1][8],2) -- runway 2
|
||||||
|
.. ' (' .. prefixZerosFixedLength(airportInfo[1][9],2) .. ')') -- prefered runway based on wind in parens
|
||||||
|
|
||||||
|
-- Secondary Airport (second closest)
|
||||||
|
ExportScript.Tools.SendData(8102, airportInfo[2][1] .. '\n' -- name of airport
|
||||||
|
--[[.. 'BRG ']] .. format_int(addZeros3(round(airportInfo[2][3],0))) .. 'º ' -- bearing
|
||||||
|
--[[.. 'DIST ']] .. format_int(round(airportInfo[2][2], 0)) .. 'nm\n' -- distance
|
||||||
|
.. 'ETE ' .. airportInfo[2][4] .. '\n' -- estimated time in route
|
||||||
|
.. '' .. prefixZerosFixedLength(round(airportInfo[2][5], 0),3) .. 'º ' -- wind bearing
|
||||||
|
.. round(metersPerSecond2knots(airportInfo[2][6]),0) .. 'kts' -- wing strength
|
||||||
|
.. '\n' .. prefixZerosFixedLength(airportInfo[2][7],2) -- runway 1
|
||||||
|
.. '-' .. prefixZerosFixedLength(airportInfo[2][8],2) -- runway 2
|
||||||
|
.. ' (' .. prefixZerosFixedLength(airportInfo[2][9],2) .. ')') -- prefered runway based on wind in parens
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.WindsAloft(mainPanelDevice)
|
||||||
|
|
||||||
|
-- Winds relative to the aircraft, aka, winds aloft
|
||||||
|
local windAloft = LoGetVectorWindVelocity()
|
||||||
|
local windStrengthAloft = math.sqrt((windAloft.x)^2 + (windAloft.z)^2)
|
||||||
|
local windDirectionAloft = math.deg(math.atan2(windAloft.z, windAloft.x))
|
||||||
|
if windDirectionAloft < 0 then
|
||||||
|
windDirectionAloft = 360 + windDirectionAloft
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert to direction to from direction
|
||||||
|
if windDirectionAloft > 180 then
|
||||||
|
windDirectionAloft = windDirectionAloft - 180
|
||||||
|
else
|
||||||
|
windDirectionAloft = windDirectionAloft + 180
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8100, 'Wind Aloft\n' .. addZeros3(round(windDirectionAloft,0)) .. 'º '
|
||||||
|
.. round(metersPerSecond2knots(windStrengthAloft,0)) .. 'kts'
|
||||||
|
) -- winds at the aircraft
|
||||||
|
end
|
||||||
|
function ExportScript.GroundRadar(mainPanelDevice) -- may return some odd things
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
|
||||||
|
local tableOfGround = {}
|
||||||
|
-- relative to the player...
|
||||||
|
local tableOfGround_friendly = {}
|
||||||
|
local tableOfGround_friendlyReports = {}
|
||||||
|
local tableOfGround_enemy = {}
|
||||||
|
local tableOfGround_enemyReports = {}
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.Type.level1 == 2 then
|
||||||
|
table.insert(tableOfGround, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfGround) do
|
||||||
|
if value.CoalitionID == selfCoalitionID then
|
||||||
|
table.insert(tableOfGround_friendly, value)
|
||||||
|
else
|
||||||
|
table.insert(tableOfGround_enemy, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: only do enemy reports if there is an awacs unit(?)
|
||||||
|
for key,value in pairs(tableOfGround_enemy) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfGround_enemyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
end
|
||||||
|
table.sort(tableOfGround_enemyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfGround_friendly) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfGround_friendlyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfGround_friendlyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8200 = 'No Ground\nEnemy\nDetected'
|
||||||
|
if tableOfGround_enemyReports[1] ~= nill then
|
||||||
|
string_8200 = 'Enemy Ground\n' .. tableOfGround_enemyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_enemyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_enemyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8201 = 'No Ground\nEnemy\nDetected'
|
||||||
|
if tableOfGround_enemyReports[2] ~= nill then
|
||||||
|
string_8201 = 'Enemy Ground\n'.. tableOfGround_enemyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_enemyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_enemyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8202 = 'No Ground\nFriend\nDetected'
|
||||||
|
if tableOfGround_friendlyReports[1] ~= nill then
|
||||||
|
string_8202 = 'Friend Ground\n' .. tableOfGround_friendlyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_friendlyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_friendlyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8203 = 'No Ground\nFriend\nDetected'
|
||||||
|
if tableOfGround_friendlyReports[2] ~= nill then
|
||||||
|
string_8203 = 'Friend Ground\n' .. tableOfGround_friendlyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_friendlyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_friendlyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8200, string_8200)
|
||||||
|
ExportScript.Tools.SendData(8201, string_8201)
|
||||||
|
ExportScript.Tools.SendData(8202, string_8202)
|
||||||
|
ExportScript.Tools.SendData(8203, string_8203)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.AirRadar(mainPanelDevice)
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
|
||||||
|
local tableOfAircraft = {}
|
||||||
|
-- relative to the player...
|
||||||
|
local tableOfAircraft_friendly = {}
|
||||||
|
local tableOfAircraft_friendlyReports = {}
|
||||||
|
local tableOfAircraft_enemy = {}
|
||||||
|
local tableOfAircraft_enemyReports = {}
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.Type.level1 == 1 then
|
||||||
|
table.insert(tableOfAircraft, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfAircraft) do
|
||||||
|
if value.CoalitionID == selfCoalitionID then
|
||||||
|
table.insert(tableOfAircraft_friendly, value)
|
||||||
|
else
|
||||||
|
table.insert(tableOfAircraft_enemy, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: only do enemy reports if there is a awacs unit
|
||||||
|
for key,value in pairs(tableOfAircraft_enemy) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfAircraft_enemyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
-- https://stackoverflow.com/questions/51276613/how-to-sort-table-by-value-and-then-print-index-in-order
|
||||||
|
-- https://www.tutorialspoint.com/sort-function-in-lua-programming
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfAircraft_enemyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfAircraft_friendly) do -- [1] will always be the player
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfAircraft_friendlyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfAircraft_friendlyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8210 = 'No Air\nEnemy\nDetected'
|
||||||
|
if tableOfAircraft_enemyReports[1] ~= nill then
|
||||||
|
string_8210 = 'Enemy Air\n' .. tableOfAircraft_enemyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_enemyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_enemyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8211 = 'No Air\nEnemy\nDetected'
|
||||||
|
if tableOfAircraft_enemyReports[2] ~= nill then
|
||||||
|
string_8211 = 'Enemy Air\n' .. tableOfAircraft_enemyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_enemyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_enemyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8212 = 'No Air\nFriend\nDetected'
|
||||||
|
if tableOfAircraft_friendlyReports[2] ~= nill then
|
||||||
|
string_8212 = 'Friend Air\n' .. tableOfAircraft_friendlyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_friendlyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_friendlyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8213 = 'No Air\nFriend\nDetected'
|
||||||
|
if tableOfAircraft_friendlyReports[3] ~= nill then
|
||||||
|
string_8213 = 'Friend Air\n' .. tableOfAircraft_friendlyReports[3][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_friendlyReports[3][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_friendlyReports[3][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8210,string_8210)
|
||||||
|
ExportScript.Tools.SendData(8211, string_8211)
|
||||||
|
ExportScript.Tools.SendData(8212, string_8212)
|
||||||
|
ExportScript.Tools.SendData(8213, string_8213)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.IglaHunter(mainPanelDevice) -- Locates the nearest Igla
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
local tableOfIgla = {}
|
||||||
|
local tableOfIgla_report = {}
|
||||||
|
|
||||||
|
--TODO: Might have to refine this.
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.CoalitionID ~= selfCoalitionID then
|
||||||
|
if value.Type.level3 == 27 then
|
||||||
|
if value.Type.level2 == 16 then
|
||||||
|
if value.Type.level1 == 2 then
|
||||||
|
if value.Type.level4 == 55 or 54 or 53 or 52 or 62 then
|
||||||
|
table.insert(tableOfIgla, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--if tableOfIgla ~= null then
|
||||||
|
for key,value in pairs(tableOfIgla) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfIgla_report, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
table.sort(tableOfIgla_report, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8666 = 'Igla Hunter\nSearching...'
|
||||||
|
if tableOfIgla_report[1] ~= nill then
|
||||||
|
string_8666 = 'Igla Detected\n' .. tableOfIgla_report[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfIgla_report[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfIgla_report[1][2],0) .. ' nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8666, string_8666)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
----------------------
|
||||||
|
-- Helper Functions --
|
||||||
|
----------------------
|
||||||
|
function ExportScript.Linearize(current_value, raw_tab, final_tab)
|
||||||
|
-- (c) scoobie
|
||||||
|
if current_value <= raw_tab[1] then
|
||||||
|
return final_tab[1]
|
||||||
|
end
|
||||||
|
for index, value in pairs(raw_tab) do
|
||||||
|
if current_value <= value then
|
||||||
|
local ft = final_tab[index]
|
||||||
|
local rt = raw_tab[index]
|
||||||
|
return (current_value - rt) * (ft - final_tab[index - 1]) / (rt - raw_tab[index - 1]) + ft
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- we shouldn't be here, so something went wrong - return arbitrary max. final value, maybe the user will notice the problem:
|
||||||
|
return final_tab[#final_tab]
|
||||||
|
end
|
||||||
|
|
||||||
|
function trim(s) --http://lua-users.org/wiki/CommonFunctions
|
||||||
|
-- from PiL2 20.4
|
||||||
|
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||||
|
end
|
||||||
|
function formatTime(time)
|
||||||
|
local seconds = math.floor(time) % 60
|
||||||
|
local minutes = math.floor(time / 60) % 60
|
||||||
|
local hours = math.floor(time / (60 * 60)) % 24
|
||||||
|
return string.format("%02d", hours) .. "-" .. string.format("%02d", minutes) .. "-" .. string.format("%02d", seconds)
|
||||||
|
end
|
||||||
|
|
||||||
|
function meters2feet(meters)
|
||||||
|
local feet = meters * 3.281
|
||||||
|
return feet
|
||||||
|
end
|
||||||
|
|
||||||
|
function feet2meters(feet)
|
||||||
|
local meters = feet / 3.281
|
||||||
|
return feet
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2milesPerHour(metersPerSecond)
|
||||||
|
local milesPerHour = metersPerSecond * 2.237
|
||||||
|
return milesPerHour
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2knots(metersPerSecond)
|
||||||
|
local knots = metersPerSecond * 1.944
|
||||||
|
return knots
|
||||||
|
end
|
||||||
|
|
||||||
|
function kgPerSecond2poundPerHour(kgPerSecond)
|
||||||
|
poundPerHour = kgPerSecond * 7937
|
||||||
|
return poundPerHour
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2feetPerMinute(metersPerSecond)
|
||||||
|
local feetPerMinute = metersPerSecond * 197
|
||||||
|
return feetPerMinute
|
||||||
|
end
|
||||||
|
|
||||||
|
function round(num, numDecimalPlaces) --http://lua-users.org/wiki/SimpleRound
|
||||||
|
local mult = 10^(numDecimalPlaces or 0)
|
||||||
|
return math.floor(num * mult + 0.5) / mult
|
||||||
|
end
|
||||||
|
|
||||||
|
function format_int(number) --https://stackoverflow.com/questions/10989788/format-integer-in-lua
|
||||||
|
local i, j, minus, int, fraction = tostring(number):find('([-]?)(%d+)([.]?%d*)')
|
||||||
|
-- reverse the int-string and append a comma to all blocks of 3 digits
|
||||||
|
int = int:reverse():gsub("(%d%d%d)", "%1,")
|
||||||
|
-- reverse the int-string back remove an optional comma and put the
|
||||||
|
-- optional minus and fractional part back
|
||||||
|
return minus .. int:reverse():gsub("^,", "") .. fraction
|
||||||
|
end
|
||||||
|
|
||||||
|
function formatCoord(type, isLat, d)
|
||||||
|
local h
|
||||||
|
if isLat then
|
||||||
|
if d < 0 then
|
||||||
|
h = 'S'
|
||||||
|
d = -d
|
||||||
|
else
|
||||||
|
h = 'N'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if d < 0 then
|
||||||
|
h = 'W'
|
||||||
|
d = -d
|
||||||
|
else
|
||||||
|
h = 'E'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local g = math.floor(d)
|
||||||
|
local m = math.floor(d * 60 - g * 60)
|
||||||
|
local s = d * 3600 - g * 3600 - m * 60
|
||||||
|
|
||||||
|
if type == "DMS" then -- Degree Minutes Seconds
|
||||||
|
s = math.floor(s * 100) / 100
|
||||||
|
return string.format('%s %2d°%.2d\'%05.2f"', h, g, m, s)
|
||||||
|
elseif type == "DDM" then -- Degree Decimal Minutes
|
||||||
|
s = math.floor(s / 60 * 1000)
|
||||||
|
return string.format('%s %2d°%02d.%3.3d\'', h, g, m, s)
|
||||||
|
else -- Decimal Degrees
|
||||||
|
return string.format('%f',d)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function getdistance(lat1,lat2,lon1,lon2,unit) -- https://www.geeksforgeeks.org/program-distance-two-points-earth/
|
||||||
|
--Example Locations
|
||||||
|
--lat1 = 42.1578 -- POTI
|
||||||
|
--lat2 = 42.3269 -- HONI
|
||||||
|
--lon1 = 41.6777
|
||||||
|
--lon2 = 42.4122
|
||||||
|
|
||||||
|
local lon1 = toRadians(lon1)
|
||||||
|
local lon2 = toRadians(lon2)
|
||||||
|
local lat1 = toRadians(lat1)
|
||||||
|
local lat2 = toRadians(lat2)
|
||||||
|
|
||||||
|
-- Haversine formula
|
||||||
|
local dlon = lon2 - lon1
|
||||||
|
local dlat = lat2 - lat1
|
||||||
|
local a = math.pow(math.sin(dlat / 2), 2) +
|
||||||
|
math.cos(lat1) * math.cos(lat2) *
|
||||||
|
math.pow(math.sin(dlon / 2),2)
|
||||||
|
|
||||||
|
local c = 2 * math.asin(math.sqrt(a))
|
||||||
|
|
||||||
|
local r -- Radius of earth in X.
|
||||||
|
if unit == 'nm' then
|
||||||
|
r = 6371 / 1.852 -- times 1.852 because I could not find a good NM source
|
||||||
|
elseif unit == 'km' then
|
||||||
|
r = 6371 -- Use 6371 for kilometers
|
||||||
|
elseif unit == 'miles' then
|
||||||
|
r = 3956 -- Use 3956 for miles
|
||||||
|
elseif unit == 'meters' then
|
||||||
|
r = 6371 * 1000
|
||||||
|
end
|
||||||
|
|
||||||
|
-- calculate the result
|
||||||
|
return (c * r)
|
||||||
|
end
|
||||||
|
|
||||||
|
function toRadians(angleIn10thofaDegree)
|
||||||
|
return (angleIn10thofaDegree * math.pi) / 180
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function getBearing(lat1,lat2,lon1,lon2, magnetic)
|
||||||
|
local bearing_rad = math.atan2(lon2 - lon1, lat2 - lat1)
|
||||||
|
if bearing_rad < 0 then
|
||||||
|
bearing_rad = bearing_rad + (2 * math.pi)
|
||||||
|
end
|
||||||
|
|
||||||
|
bearing = math.deg(bearing_rad)
|
||||||
|
|
||||||
|
-- start calculation for getting the magnetic bar
|
||||||
|
local _aircraftPitch, _aircraftBank, aircraftYawTrue = LoGetADIPitchBankYaw()
|
||||||
|
aircraftYawTrue = aircraftYawTrue * 57.3 -- actually heading
|
||||||
|
local aircraftYawMagnetic = LoGetMagneticYaw() * 57.3
|
||||||
|
local magneticVariance = aircraftYawTrue - aircraftYawMagnetic
|
||||||
|
|
||||||
|
if magnetic == true then
|
||||||
|
bearing = bearing - magneticVariance
|
||||||
|
end
|
||||||
|
|
||||||
|
-- correction for bearings less than 0 due to the calculation above
|
||||||
|
if bearing < 0 then
|
||||||
|
bearing = bearing + 360
|
||||||
|
end
|
||||||
|
|
||||||
|
return bearing
|
||||||
|
end
|
||||||
|
|
||||||
|
function addZeros3(number)
|
||||||
|
number = string.format("%.1d" , number)
|
||||||
|
if #number == 2 then
|
||||||
|
number = "0" .. number
|
||||||
|
elseif #number == 1 then
|
||||||
|
number = "00" .. number
|
||||||
|
end
|
||||||
|
return number
|
||||||
|
end
|
||||||
|
|
||||||
|
function prefixZerosFixedLength(number, digitLength) -- prefixZerosFixedLength(99, 3) --> 099
|
||||||
|
number = string.format("%.1d" , number) -- make the number a string
|
||||||
|
local zerosToAdd = digitLength - #number
|
||||||
|
s = ''
|
||||||
|
for i = 1, zerosToAdd do
|
||||||
|
s = s .. 0
|
||||||
|
end
|
||||||
|
return s .. number
|
||||||
|
end
|
||||||
|
|
||||||
|
function mgrsTableize(mgrsString)
|
||||||
|
-- Reference: https://upload.wikimedia.org/wikipedia/commons/b/b7/Universal_Transverse_Mercator_zones.svg
|
||||||
|
-- example: 38 T LM 12345 54321
|
||||||
|
-- (\d+\s\w)\s(\w+)\s(.+)\s(.+) --c# version of regex
|
||||||
|
-- UTMZone = string,
|
||||||
|
-- MGRSDigraph = string,
|
||||||
|
-- Easting = number,
|
||||||
|
-- Northing = number
|
||||||
|
local UTMZone , MGRSDigraph, Easting, Northing = mgrsString:match('(%d+%s%w)%s(%w+)%s(.+)%s(.+)')
|
||||||
|
local mgrsTbl = {}
|
||||||
|
table.insert(mgrsTbl, {UTMZone,MGRSDigraph,Easting,Northing})
|
||||||
|
return mgrsTbl
|
||||||
|
end
|
||||||
|
|||||||
@ -1,4 +1,9 @@
|
|||||||
-- Uh-1H
|
-- Uh-1H
|
||||||
|
-- https://github.com/asherao/DCS-ExportScripts
|
||||||
|
|
||||||
|
local base = _G -- game information
|
||||||
|
local os = base.os -- time
|
||||||
|
local Terrain = require('terrain') -- map info
|
||||||
|
|
||||||
ExportScript.FoundDCSModule = true
|
ExportScript.FoundDCSModule = true
|
||||||
ExportScript.Version.UH1H = "1.2.1"
|
ExportScript.Version.UH1H = "1.2.1"
|
||||||
@ -623,6 +628,21 @@ function ExportScript.ProcessIkarusDCSConfigLowImportance(mainPanelDevice)
|
|||||||
end
|
end
|
||||||
ExportScript.Tools.SendData(2007, string.format("%s", lADF_ARN83))
|
ExportScript.Tools.SendData(2007, string.format("%s", lADF_ARN83))
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
ExportScript.UhfRadioPresets(mainPanelDevice) -- AN/ARC-164 UHF Preset List
|
||||||
|
ExportScript.CrewStatusRepeater(mainPanelDevice) -- Crew Status Window
|
||||||
|
ExportScript.RadioFreqs(mainPanelDevice)
|
||||||
|
|
||||||
|
if LoIsObjectExportAllowed() then -- returns true if world objects data is available
|
||||||
|
if LoIsOwnshipExportAllowed() then -- returns true if ownship data is available
|
||||||
|
ExportScript.LoAircraftInfo(mainPanelDevice) -- Provides a lot of aircraft properties
|
||||||
|
ExportScript.AirportInfo(mainPanelDevice) -- Provides info on the two closest airports
|
||||||
|
ExportScript.WindsAloft(mainPanelDevice) -- Gets winds at the aircraft
|
||||||
|
ExportScript.GroundRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
|
ExportScript.AirRadar(mainPanelDevice) -- Reports 2 closest friendlies and 2 enemies (Use in Single Player)
|
||||||
|
ExportScript.IglaHunter(mainPanelDevice) -- Locates closest Igla (Use in Single Player)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ExportScript.ProcessDACConfigLowImportance(mainPanelDevice)
|
function ExportScript.ProcessDACConfigLowImportance(mainPanelDevice)
|
||||||
@ -904,4 +924,849 @@ function ExportScript.ProcessDACConfigLowImportance(mainPanelDevice)
|
|||||||
ExportScript.Tools.WriteToLog(ltmp2..' (metatable): '..ExportScript.Tools.dump(getmetatable(ltmp1)))
|
ExportScript.Tools.WriteToLog(ltmp2..' (metatable): '..ExportScript.Tools.dump(getmetatable(ltmp1)))
|
||||||
end
|
end
|
||||||
]]
|
]]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
----------------------
|
||||||
|
-- Custom functions --
|
||||||
|
----------------------
|
||||||
|
function ExportScript.CrewStatusRepeater(mainPanelDevice) -- Crew Status Window
|
||||||
|
|
||||||
|
local crewStatusInfo = parse_indication(6) -- contains table of the status of the crew
|
||||||
|
|
||||||
|
if crewStatusInfo.txt_mem0 ~= null then -- if there is a pilot entry
|
||||||
|
ExportScript.Tools.SendData(3000,'Pilot\n' .. crewStatusInfo.txt_status0
|
||||||
|
.. '\nAmmo ' .. trim(crewStatusInfo.txt_ammo0)
|
||||||
|
.. '\nBurst ' .. trim(crewStatusInfo.txt_burst0))
|
||||||
|
else
|
||||||
|
ExportScript.Tools.SendData(3000,'Pilot\n' .. '--\n'.. '--\n'.. '--')
|
||||||
|
end
|
||||||
|
|
||||||
|
if crewStatusInfo.txt_mem1 ~= null then -- if there is a copilot entry
|
||||||
|
ExportScript.Tools.SendData(3001,'Co-pilot\nROE ' .. crewStatusInfo.txt_status1
|
||||||
|
.. '\nAmmo ' .. trim(crewStatusInfo.txt_ammo1)
|
||||||
|
.. '\nBurst ' .. trim(crewStatusInfo.txt_burst1))
|
||||||
|
else
|
||||||
|
ExportScript.Tools.SendData(3001,'Co-pilot\n' .. '--\n'.. '--\n'.. '--')
|
||||||
|
end
|
||||||
|
|
||||||
|
if crewStatusInfo.txt_mem2 ~= null then -- if there is a LH Gunner entry
|
||||||
|
ExportScript.Tools.SendData(3002,'LH Gunner\nROE ' .. crewStatusInfo.txt_status2
|
||||||
|
.. '\nAmmo ' .. trim(crewStatusInfo.txt_ammo2)
|
||||||
|
.. '\nBurst ' .. trim(crewStatusInfo.txt_burst2))
|
||||||
|
else
|
||||||
|
ExportScript.Tools.SendData(3002,'LH Gunner\n' .. '--\n'.. '--\n'.. '--')
|
||||||
|
end
|
||||||
|
|
||||||
|
if crewStatusInfo.txt_mem3 ~= null then -- if there is a RH Gunner entry
|
||||||
|
ExportScript.Tools.SendData(3003,'RH Gunner\nROE ' .. crewStatusInfo.txt_status3
|
||||||
|
.. '\nAmmo ' .. trim(crewStatusInfo.txt_ammo3)
|
||||||
|
.. '\nBurst ' .. trim(crewStatusInfo.txt_burst3))
|
||||||
|
else
|
||||||
|
ExportScript.Tools.SendData(3003,'RH Gunner\n' .. '--\n'.. '--\n'.. '--')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.UhfRadioPresets(mainPanelDevice) -- AN/ARC-164 UHF Preset List
|
||||||
|
|
||||||
|
local UhfPresetReadout = ExportScript.Tools.getListIndicatorValue(7) -- uhf radio presets
|
||||||
|
|
||||||
|
local UhfCh1 = UhfPresetReadout.SheetTable_Channel1
|
||||||
|
local UhfCh2 = UhfPresetReadout.SheetTable_Channel2
|
||||||
|
local UhfCh3 = UhfPresetReadout.SheetTable_Channel3
|
||||||
|
local UhfCh4 = UhfPresetReadout.SheetTable_Channel4
|
||||||
|
local UhfCh5= UhfPresetReadout.SheetTable_Channel5
|
||||||
|
local UhfCh6 = UhfPresetReadout.SheetTable_Channel6
|
||||||
|
local UhfCh7 = UhfPresetReadout.SheetTable_Channel7
|
||||||
|
local UhfCh8 = UhfPresetReadout.SheetTable_Channel8
|
||||||
|
local UhfCh9 = UhfPresetReadout.SheetTable_Channel9
|
||||||
|
local UhfCh10 = UhfPresetReadout.SheetTable_Channel10
|
||||||
|
local UhfCh11 = UhfPresetReadout.SheetTable_Channel11
|
||||||
|
local UhfCh12 = UhfPresetReadout.SheetTable_Channel12
|
||||||
|
local UhfCh13 = UhfPresetReadout.SheetTable_Channel13
|
||||||
|
local UhfCh14 = UhfPresetReadout.SheetTable_Channel14
|
||||||
|
local UhfCh15 = UhfPresetReadout.SheetTable_Channel15
|
||||||
|
local UhfCh16 = UhfPresetReadout.SheetTable_Channel16
|
||||||
|
local UhfCh17 = UhfPresetReadout.SheetTable_Channel17
|
||||||
|
local UhfCh18 = UhfPresetReadout.SheetTable_Channel18
|
||||||
|
local UhfCh19 = UhfPresetReadout.SheetTable_Channel19
|
||||||
|
local UhfCh20 = UhfPresetReadout.SheetTable_Channel20
|
||||||
|
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(3016, "UHF 1-4"
|
||||||
|
.. "\n" .. UhfCh1
|
||||||
|
.. "\n" .. UhfCh2
|
||||||
|
.. "\n" .. UhfCh3
|
||||||
|
.. "\n" .. UhfCh4
|
||||||
|
)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(3017, "UHF 5-8"
|
||||||
|
.. "\n" .. UhfCh5
|
||||||
|
.. "\n" .. UhfCh6
|
||||||
|
.. "\n" .. UhfCh7
|
||||||
|
.. "\n" .. UhfCh8
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(3018, "UHF 9-12"
|
||||||
|
.. "\n" .. UhfCh9
|
||||||
|
.. "\n" .. UhfCh10
|
||||||
|
.. "\n" .. UhfCh11
|
||||||
|
.. "\n" .. UhfCh12
|
||||||
|
)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(3019, "UHF 13-16"
|
||||||
|
.. "\n" .. UhfCh13
|
||||||
|
.. "\n" .. UhfCh14
|
||||||
|
.. "\n" .. UhfCh15
|
||||||
|
.. "\n" .. UhfCh16
|
||||||
|
)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(3020, "UHF 16-20"
|
||||||
|
.. "\n" .. UhfCh17
|
||||||
|
.. "\n" .. UhfCh18
|
||||||
|
.. "\n" .. UhfCh19
|
||||||
|
.. "\n" .. UhfCh20
|
||||||
|
)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.RadioFreqs(mainPanelDevice) -- TODO: More radios
|
||||||
|
local radoioVhf = ExportScript.Tools.RoundFreqeuncy(GetDevice(20):get_frequency()/1000000) -- "116.000"
|
||||||
|
local radioUhf = ExportScript.Tools.RoundFreqeuncy(GetDevice(22):get_frequency()/1000000) -- "251.000"
|
||||||
|
local radioHf = ExportScript.Tools.RoundFreqeuncy(GetDevice(23):get_frequency()/1000000) -- " 30.000"
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(3010, "VHF\n" .. radoioVhf .. ' MHz')
|
||||||
|
ExportScript.Tools.SendData(3011, "UHF\n" .. radioUhf .. ' MHz')
|
||||||
|
ExportScript.Tools.SendData(3012, "HF\n" .. radioHf .. ' MHz')
|
||||||
|
ExportScript.Tools.SendData(3013, "Radio Stack\n" .. radoioVhf .. ' MHz\n'
|
||||||
|
.. radioUhf .. ' MHz\n' .. radioHf .. ' MHz')
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.LoAircraftInfo(mainPanelDevice)
|
||||||
|
|
||||||
|
-- General
|
||||||
|
local aircraftName = LoGetSelfData().Name -- DCS Name of the aircraft eg "F-5E-3"
|
||||||
|
local pilotName = LoGetPilotName() -- Logbook Pilot name
|
||||||
|
|
||||||
|
-- Times DCS times are default in seconds
|
||||||
|
local dcsModelTime = LoGetModelTime() -- time since aircraft spawn
|
||||||
|
local missionStartTime = LoGetMissionStartTime() -- second after midnight that the mission started
|
||||||
|
local dcsTimeLocal = formatTime(LoGetMissionStartTime() + LoGetModelTime()) -- up-to-date time in dcs
|
||||||
|
local utcOffset = -1 * Terrain.GetTerrainConfig('SummerTimeDelta') * 3600 -- eg -1 * 4 * 3600 (for seconds to get hours)
|
||||||
|
local dcsTimeUtc = formatTime(dcsModelTime + LoGetMissionStartTime() + utcOffset) -- dcs zulu time
|
||||||
|
local realTimeLocal = os.date("%H-%M-%S") -- real life time
|
||||||
|
local realTimeUtc = os.date("!%H-%M-%S") -- real life zulu time
|
||||||
|
--local playTime = formatTime(DCS.getRealTime()) -- does not work, export environment no access
|
||||||
|
|
||||||
|
-- Player Aircraft Properties
|
||||||
|
local altMsl_meters = LoGetAltitudeAboveSeaLevel()
|
||||||
|
local altMsl_feet = meters2feet(altMsl_meters)
|
||||||
|
local altAgl_meters = LoGetAltitudeAboveGroundLevel()
|
||||||
|
local altAgl_feet = meters2feet(altAgl_meters)
|
||||||
|
|
||||||
|
local verticalVelocity_metric = LoGetVerticalVelocity()
|
||||||
|
local verticalVelocity_imperial = metersPerSecond2feetPerMinute(LoGetVerticalVelocity())
|
||||||
|
|
||||||
|
local ias_metric = LoGetIndicatedAirSpeed()
|
||||||
|
local ias_knots = metersPerSecond2knots(LoGetIndicatedAirSpeed())
|
||||||
|
local ias_mph = metersPerSecond2milesPerHour(LoGetIndicatedAirSpeed())
|
||||||
|
|
||||||
|
local tas_metric = LoGetTrueAirSpeed()
|
||||||
|
local tas_knots = metersPerSecond2knots(LoGetTrueAirSpeed())
|
||||||
|
local tas_mph = metersPerSecond2milesPerHour(LoGetTrueAirSpeed())
|
||||||
|
|
||||||
|
local speed_mach = LoGetMachNumber()
|
||||||
|
local accel_g = LoGetAccelerationUnits().y
|
||||||
|
local aoa = LoGetAngleOfAttack()
|
||||||
|
|
||||||
|
--local atmosphericPressure_mmhg = LoGetBasicAtmospherePressure() -- does not seem to work
|
||||||
|
|
||||||
|
local aircraftPitch, aircraftBank, aircraftYawTrue = LoGetADIPitchBankYaw()
|
||||||
|
aircraftPitch = aircraftPitch * 57.3
|
||||||
|
aircraftBank = aircraftBank * 57.3
|
||||||
|
aircraftYawTrue = aircraftYawTrue * 57.3 -- true heading
|
||||||
|
local aircraftYawMagnetic = LoGetMagneticYaw() * 57.3 -- magnetic heading
|
||||||
|
local aircraftHeading = aircraftYawMagnetic -- this cound be negative
|
||||||
|
if aircraftHeading < 0 then aircraftHeading = aircraftHeading + 360 end -- removes the negative
|
||||||
|
local magneticVariance = aircraftYawTrue - aircraftYawMagnetic -- works for all maps
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData() -- relative the the player
|
||||||
|
local lLatitude = selfData.LatLongAlt.Lat
|
||||||
|
local lLongitude = selfData.LatLongAlt.Long
|
||||||
|
local mgrs = Terrain.GetMGRScoordinates(LoGetSelfData().Position.x, LoGetSelfData().Position.z)
|
||||||
|
local mgrsTable = mgrsTableize(mgrs) -- format is mgrsTable[1][1], mgrsTable[1][2], mgrsTable[1][3], mgrsTable[1][4]
|
||||||
|
|
||||||
|
local aircraftHeadingTrue = selfData.Heading * 57.3 -- true yeading (same as trueYaw for fixed wing aircraft)
|
||||||
|
|
||||||
|
-- Engine Info
|
||||||
|
local engineInfo = LoGetEngineInfo()
|
||||||
|
local lEngineRPMleft = engineInfo.RPM.left -- ENG1 RPM %
|
||||||
|
local lEngineRPMright = engineInfo.RPM.right -- ENG2 RPM %
|
||||||
|
local lEngineFuelInternal = engineInfo.fuel_internal -- 1 = full. 0 = empty. Includes external tanks for FF aircraft
|
||||||
|
local lEngineFuelExternal = engineInfo.fuel_external -- TANK2 (EXT) (KG) -- does not seem to work for FF modules
|
||||||
|
local lEngineFuelTotal = lEngineFuelInternal + lEngineFuelExternal
|
||||||
|
local lEngineTempLeft = engineInfo.Temperature.left -- ENG1 EGT ºC. May get odd numbers
|
||||||
|
local lEngineTempRight = engineInfo.Temperature.right -- ENG2 EGT ºC. May get odd numbers
|
||||||
|
|
||||||
|
local lFuelConsumptionLeft = engineInfo.FuelConsumption.left -- {left ,right},kg per sec
|
||||||
|
local lFuelConsumptionRight = engineInfo.FuelConsumption.right -- {left ,right},kg per sec
|
||||||
|
local lFuelConsumptionTotal = lFuelConsumptionLeft + lFuelConsumptionRight -- total,kg per sec
|
||||||
|
local lHydraulicPressureLeft = engineInfo.HydraulicPressure.left -- {left ,right},kg per square centimeter
|
||||||
|
local lHydraulicPressureRight = engineInfo.HydraulicPressure.right -- {left ,right},kg per square centimeter
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8000, aircraftName)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8001, pilotName)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8002, 'Real Time\n'.. realTimeLocal .. '\nDCS Time\n' .. dcsTimeLocal) -- clocks
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8003, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_feet,-1)) .. ' ft'
|
||||||
|
.. '\nIAS ' .. round(ias_knots,0) .. ' kts'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_imperial,-2)) .. ' ft/min'
|
||||||
|
) -- Aircraft Instrument panel (western)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8004, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_meters,-1)) .. ' m'
|
||||||
|
.. '\nIAS ' .. round(ias_metric,0) .. ' km/h'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_metric,0)) .. ' m/s'
|
||||||
|
) -- Aircraft Instrument panel (eastern)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8005, 'HDG ' .. prefixZerosFixedLength(round(aircraftHeading,0),3) .. 'º'
|
||||||
|
.. '\nALT ' .. format_int(round(altMsl_feet,-1)) .. ' ft'
|
||||||
|
.. '\nIAS ' .. round(ias_mph,0) .. ' mph'
|
||||||
|
.. '\nV/S ' .. format_int(round(verticalVelocity_imperial,-2)) .. ' ft/min'
|
||||||
|
) -- Aircraft Instrument panel (western ww2)
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8006, "Lat-Long-DMS\n" .. formatCoord("DMS",true, lLatitude)
|
||||||
|
.. "\n" .. formatCoord("DMS",false, lLongitude)
|
||||||
|
) -- Player coordinates in DMS
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8007, "Lat-Long-DDM\n" .. formatCoord("DDM",true, lLatitude)
|
||||||
|
.. "\n" .. formatCoord("DDM",false, lLongitude)
|
||||||
|
) -- Player coordinates in DDM
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8008, 'MGRS\n'.. mgrsTable[1][1] .. ' ' .. mgrsTable[1][2]
|
||||||
|
.. '\n' .. mgrsTable[1][3] .. ' ' .. mgrsTable[1][4]
|
||||||
|
) -- Player coordinates in MGRS on 2 rows + title
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8009, 'Mag Var\n' .. format_int(round(magneticVariance, 2))) -- also called magnetic deviation
|
||||||
|
|
||||||
|
-- Example for using the Lo Data. Feel free to make your own!
|
||||||
|
ExportScript.Tools.SendData(8010, format_int(round(kgPerSecond2poundPerHour(lFuelConsumptionLeft), -1))) -- fuel use in pph
|
||||||
|
|
||||||
|
end
|
||||||
|
function ExportScript.AirportInfo(mainPanelDevice)
|
||||||
|
|
||||||
|
local airdromes = LoGetWorldObjects("airdromes") -- returns a list of runways and their popperties
|
||||||
|
local airportInfo = {} -- contains generated table of important properties
|
||||||
|
-- the table will be sorted by nearest airport first
|
||||||
|
-- for this table:
|
||||||
|
-- airportInfo[1] is the first element
|
||||||
|
-- airportInfo[1][1] is the airport name of the first element/airport
|
||||||
|
-- airportInfo[1][2] is the distance to the airport of the first element/airport
|
||||||
|
-- airportInfo[1][3] is the bearing to the airport of the first element/airport
|
||||||
|
-- airportInfo[1][4] is the extimated time en route
|
||||||
|
-- airportInfo[1][5] is the direction of the wind
|
||||||
|
-- airportInfo[1][6] is the windStrength of the wind
|
||||||
|
-- airportInfo[1][7] is the main runway heading
|
||||||
|
-- airportInfo[1][8] is the reverse of the main runway
|
||||||
|
-- airportInfo[1][9] is the prefered runway based on winds
|
||||||
|
|
||||||
|
for key,value in pairs(airdromes) do
|
||||||
|
|
||||||
|
-- remove the woRunWay entries so that only named runways are in the list
|
||||||
|
if value.Name ~= 'woRunWay' then
|
||||||
|
|
||||||
|
-- get the distance from the player to the runway
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
-- get the direction from the player to the runway
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
-- estimate the runway heading based on the reported values
|
||||||
|
local runwayHeading = round(value.Heading * 57.3,-1) / 10
|
||||||
|
if runwayHeading < 0 then
|
||||||
|
runwayHeading = 36 + runwayHeading
|
||||||
|
end
|
||||||
|
-- Reverse it for the reciprocal runway
|
||||||
|
local runwayHeadingReciprocal
|
||||||
|
if runwayHeading > 18 then
|
||||||
|
runwayHeadingReciprocal = runwayHeading-18
|
||||||
|
else
|
||||||
|
runwayHeadingReciprocal = runwayHeading+18
|
||||||
|
end
|
||||||
|
|
||||||
|
local ete = distance / metersPerSecond2knots(LoGetTrueAirSpeed()) * (60 * 60) --based on tas bc dcs is flat...
|
||||||
|
-- if ete is more than 24hrs, make it 24 hrs, which shows up as 00-00-00
|
||||||
|
-- this case is for choppers and aircraft that arent moving
|
||||||
|
if ete > 86400 then ete = 86400 end
|
||||||
|
ete = formatTime(ete)
|
||||||
|
|
||||||
|
-- wind at airport calculations. Each airport has slighty different winds
|
||||||
|
-- https://forum.dcs.world/topic/165136-logetwindatpoint-in-exportlua/#comment-3294428
|
||||||
|
-- LoGetWindAtPoint(x,y,z,is_radio_alt), 2 meters off the ground for the "wind sensor"
|
||||||
|
local vx,_vy,vz,_absolute_height = LoGetWindAtPoint(value.Position.x,2,value.Position.y,true)
|
||||||
|
local windDirectionInRadians = math.atan2(vz,vx)
|
||||||
|
local windDirection = windDirectionInRadians * 57.3
|
||||||
|
local windStrength = math.sqrt((vx)^2 + (vz)^2)
|
||||||
|
if windDirection < 0 then
|
||||||
|
windDirection = 360 + windDirection
|
||||||
|
end
|
||||||
|
-- Convert to direction to from direction
|
||||||
|
if windDirection > 180 then
|
||||||
|
windDirection = windDirection - 180
|
||||||
|
else
|
||||||
|
windDirection = windDirection + 180
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate the prefered runway for landing
|
||||||
|
-- if the rounded runway is within +- 9 of the rounded wind, then it is prefered
|
||||||
|
local windRounded = round(windDirection, -1)
|
||||||
|
if windRounded >= runwayHeading - 9 and windRounded <= runwayHeading + 9 then
|
||||||
|
runwayHeadingPrefered = runwayHeading
|
||||||
|
else
|
||||||
|
runwayHeadingPrefered = runwayHeadingReciprocal
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Populate the table with the important info for each airport
|
||||||
|
table.insert(airportInfo, -- the table name
|
||||||
|
{value.Name, -- airport name [1]
|
||||||
|
distance, bearing, ete, --[2][3][4]
|
||||||
|
windDirection,windStrength, --wind direction [5], wind Strength [6]
|
||||||
|
runwayHeading, runwayHeadingReciprocal,runwayHeadingPrefered}) -- [7][8][9]
|
||||||
|
|
||||||
|
end -- end of woRunWay
|
||||||
|
end -- end of FOR loop
|
||||||
|
|
||||||
|
-- sort the table based on the second value, which is distance
|
||||||
|
-- https://stackoverflow.com/questions/51276613/how-to-sort-table-by-value-and-then-print-index-in-order
|
||||||
|
-- https://www.tutorialspoint.com/sort-function-in-lua-programming
|
||||||
|
table.sort(airportInfo, function(a,b) return a[2] < b[2] end)
|
||||||
|
|
||||||
|
-- Primary Airport (closest)
|
||||||
|
ExportScript.Tools.SendData(8101, airportInfo[1][1] .. '\n' -- name of airport
|
||||||
|
--[[.. 'BRG ']] .. format_int(addZeros3(round(airportInfo[1][3],0))) .. 'º ' -- bearing
|
||||||
|
--[[.. 'DIST ']] .. format_int(round(airportInfo[1][2], 0)) .. 'nm\n' -- distance
|
||||||
|
.. 'ETE ' .. airportInfo[1][4] .. '\n' -- estimated time in route
|
||||||
|
.. '' .. prefixZerosFixedLength(round(airportInfo[1][5], 0),3) .. 'º ' -- wind bearing
|
||||||
|
.. round(metersPerSecond2knots(airportInfo[1][6]),0) .. 'kts' -- wing strength
|
||||||
|
.. '\n' .. prefixZerosFixedLength(airportInfo[1][7],2) -- runway 1
|
||||||
|
.. '-' .. prefixZerosFixedLength(airportInfo[1][8],2) -- runway 2
|
||||||
|
.. ' (' .. prefixZerosFixedLength(airportInfo[1][9],2) .. ')') -- prefered runway based on wind in parens
|
||||||
|
|
||||||
|
-- Secondary Airport (second closest)
|
||||||
|
ExportScript.Tools.SendData(8102, airportInfo[2][1] .. '\n' -- name of airport
|
||||||
|
--[[.. 'BRG ']] .. format_int(addZeros3(round(airportInfo[2][3],0))) .. 'º ' -- bearing
|
||||||
|
--[[.. 'DIST ']] .. format_int(round(airportInfo[2][2], 0)) .. 'nm\n' -- distance
|
||||||
|
.. 'ETE ' .. airportInfo[2][4] .. '\n' -- estimated time in route
|
||||||
|
.. '' .. prefixZerosFixedLength(round(airportInfo[2][5], 0),3) .. 'º ' -- wind bearing
|
||||||
|
.. round(metersPerSecond2knots(airportInfo[2][6]),0) .. 'kts' -- wing strength
|
||||||
|
.. '\n' .. prefixZerosFixedLength(airportInfo[2][7],2) -- runway 1
|
||||||
|
.. '-' .. prefixZerosFixedLength(airportInfo[2][8],2) -- runway 2
|
||||||
|
.. ' (' .. prefixZerosFixedLength(airportInfo[2][9],2) .. ')') -- prefered runway based on wind in parens
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.WindsAloft(mainPanelDevice)
|
||||||
|
|
||||||
|
-- Winds relative to the aircraft, aka, winds aloft
|
||||||
|
local windAloft = LoGetVectorWindVelocity()
|
||||||
|
local windStrengthAloft = math.sqrt((windAloft.x)^2 + (windAloft.z)^2)
|
||||||
|
local windDirectionAloft = math.deg(math.atan2(windAloft.z, windAloft.x))
|
||||||
|
if windDirectionAloft < 0 then
|
||||||
|
windDirectionAloft = 360 + windDirectionAloft
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert to direction to from direction
|
||||||
|
if windDirectionAloft > 180 then
|
||||||
|
windDirectionAloft = windDirectionAloft - 180
|
||||||
|
else
|
||||||
|
windDirectionAloft = windDirectionAloft + 180
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8100, 'Wind Aloft\n' .. addZeros3(round(windDirectionAloft,0)) .. 'º '
|
||||||
|
.. round(metersPerSecond2knots(windStrengthAloft,0)) .. 'kts'
|
||||||
|
) -- winds at the aircraft
|
||||||
|
end
|
||||||
|
function ExportScript.GroundRadar(mainPanelDevice) -- may return some odd things
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
|
||||||
|
local tableOfGround = {}
|
||||||
|
-- relative to the player...
|
||||||
|
local tableOfGround_friendly = {}
|
||||||
|
local tableOfGround_friendlyReports = {}
|
||||||
|
local tableOfGround_enemy = {}
|
||||||
|
local tableOfGround_enemyReports = {}
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.Type.level1 == 2 then
|
||||||
|
table.insert(tableOfGround, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfGround) do
|
||||||
|
if value.CoalitionID == selfCoalitionID then
|
||||||
|
table.insert(tableOfGround_friendly, value)
|
||||||
|
else
|
||||||
|
table.insert(tableOfGround_enemy, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: only do enemy reports if there is an awacs unit(?)
|
||||||
|
for key,value in pairs(tableOfGround_enemy) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfGround_enemyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
end
|
||||||
|
table.sort(tableOfGround_enemyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfGround_friendly) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfGround_friendlyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfGround_friendlyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8200 = 'No Ground\nEnemy\nDetected'
|
||||||
|
if tableOfGround_enemyReports[1] ~= nill then
|
||||||
|
string_8200 = 'Enemy Ground\n' .. tableOfGround_enemyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_enemyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_enemyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8201 = 'No Ground\nEnemy\nDetected'
|
||||||
|
if tableOfGround_enemyReports[2] ~= nill then
|
||||||
|
string_8201 = 'Enemy Ground\n'.. tableOfGround_enemyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_enemyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_enemyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8202 = 'No Ground\nFriend\nDetected'
|
||||||
|
if tableOfGround_friendlyReports[1] ~= nill then
|
||||||
|
string_8202 = 'Friend Ground\n' .. tableOfGround_friendlyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_friendlyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_friendlyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8203 = 'No Ground\nFriend\nDetected'
|
||||||
|
if tableOfGround_friendlyReports[2] ~= nill then
|
||||||
|
string_8203 = 'Friend Ground\n' .. tableOfGround_friendlyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfGround_friendlyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfGround_friendlyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8200, string_8200)
|
||||||
|
ExportScript.Tools.SendData(8201, string_8201)
|
||||||
|
ExportScript.Tools.SendData(8202, string_8202)
|
||||||
|
ExportScript.Tools.SendData(8203, string_8203)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.AirRadar(mainPanelDevice)
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
|
||||||
|
local tableOfAircraft = {}
|
||||||
|
-- relative to the player...
|
||||||
|
local tableOfAircraft_friendly = {}
|
||||||
|
local tableOfAircraft_friendlyReports = {}
|
||||||
|
local tableOfAircraft_enemy = {}
|
||||||
|
local tableOfAircraft_enemyReports = {}
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.Type.level1 == 1 then
|
||||||
|
table.insert(tableOfAircraft, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfAircraft) do
|
||||||
|
if value.CoalitionID == selfCoalitionID then
|
||||||
|
table.insert(tableOfAircraft_friendly, value)
|
||||||
|
else
|
||||||
|
table.insert(tableOfAircraft_enemy, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: only do enemy reports if there is a awacs unit
|
||||||
|
for key,value in pairs(tableOfAircraft_enemy) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfAircraft_enemyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
-- https://stackoverflow.com/questions/51276613/how-to-sort-table-by-value-and-then-print-index-in-order
|
||||||
|
-- https://www.tutorialspoint.com/sort-function-in-lua-programming
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfAircraft_enemyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
|
||||||
|
for key,value in pairs(tableOfAircraft_friendly) do -- [1] will always be the player
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfAircraft_friendlyReports, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
|
||||||
|
end
|
||||||
|
table.sort(tableOfAircraft_friendlyReports, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8210 = 'No Air\nEnemy\nDetected'
|
||||||
|
if tableOfAircraft_enemyReports[1] ~= nill then
|
||||||
|
string_8210 = 'Enemy Air\n' .. tableOfAircraft_enemyReports[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_enemyReports[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_enemyReports[1][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8211 = 'No Air\nEnemy\nDetected'
|
||||||
|
if tableOfAircraft_enemyReports[2] ~= nill then
|
||||||
|
string_8211 = 'Enemy Air\n' .. tableOfAircraft_enemyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_enemyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_enemyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8212 = 'No Air\nFriend\nDetected'
|
||||||
|
if tableOfAircraft_friendlyReports[2] ~= nill then
|
||||||
|
string_8212 = 'Friend Air\n' .. tableOfAircraft_friendlyReports[2][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_friendlyReports[2][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_friendlyReports[2][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
local string_8213 = 'No Air\nFriend\nDetected'
|
||||||
|
if tableOfAircraft_friendlyReports[3] ~= nill then
|
||||||
|
string_8213 = 'Friend Air\n' .. tableOfAircraft_friendlyReports[3][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfAircraft_friendlyReports[3][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfAircraft_friendlyReports[3][2],0) .. 'nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8210,string_8210)
|
||||||
|
ExportScript.Tools.SendData(8211, string_8211)
|
||||||
|
ExportScript.Tools.SendData(8212, string_8212)
|
||||||
|
ExportScript.Tools.SendData(8213, string_8213)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExportScript.IglaHunter(mainPanelDevice) -- Locates the nearest Igla
|
||||||
|
|
||||||
|
local tableOfUnits = LoGetWorldObjects('units')
|
||||||
|
local selfData = LoGetSelfData()
|
||||||
|
local selfCoalitionID = selfData.CoalitionID
|
||||||
|
|
||||||
|
local tableOfIgla = {}
|
||||||
|
local tableOfIgla_report = {}
|
||||||
|
|
||||||
|
--TODO: Might have to refine this.
|
||||||
|
for key,value in pairs(tableOfUnits) do
|
||||||
|
if value.CoalitionID ~= selfCoalitionID then
|
||||||
|
if value.Type.level3 == 27 then
|
||||||
|
if value.Type.level2 == 16 then
|
||||||
|
if value.Type.level1 == 2 then
|
||||||
|
if value.Type.level4 == 55 or 54 or 53 or 52 or 62 then
|
||||||
|
table.insert(tableOfIgla, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--if tableOfIgla ~= null then
|
||||||
|
for key,value in pairs(tableOfIgla) do
|
||||||
|
local distance = getdistance(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, "nm")
|
||||||
|
|
||||||
|
local bearing = getBearing(LoGetSelfData().LatLongAlt.Lat,
|
||||||
|
value.LatLongAlt.Lat,
|
||||||
|
LoGetSelfData().LatLongAlt.Long,
|
||||||
|
value.LatLongAlt.Long, true)
|
||||||
|
|
||||||
|
table.insert(tableOfIgla_report, -- the table name
|
||||||
|
{value.Name, distance, bearing}) --[1][2][3]
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
table.sort(tableOfIgla_report, function(a,b) return a[2] < b[2] end) -- sort based on the second value, which is distance
|
||||||
|
|
||||||
|
local string_8666 = 'Igla Hunter\nSearching...'
|
||||||
|
if tableOfIgla_report[1] ~= nill then
|
||||||
|
string_8666 = 'Igla Detected\n' .. tableOfIgla_report[1][1]
|
||||||
|
.. '\n ' .. prefixZerosFixedLength(tableOfIgla_report[1][3],3) -- bearing
|
||||||
|
.. 'º ' .. round(tableOfIgla_report[1][2],0) .. ' nm'--distance
|
||||||
|
end
|
||||||
|
|
||||||
|
ExportScript.Tools.SendData(8666, string_8666)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
----------------------
|
||||||
|
-- Helper Functions --
|
||||||
|
----------------------
|
||||||
|
function ExportScript.Linearize(current_value, raw_tab, final_tab)
|
||||||
|
-- (c) scoobie
|
||||||
|
if current_value <= raw_tab[1] then
|
||||||
|
return final_tab[1]
|
||||||
|
end
|
||||||
|
for index, value in pairs(raw_tab) do
|
||||||
|
if current_value <= value then
|
||||||
|
local ft = final_tab[index]
|
||||||
|
local rt = raw_tab[index]
|
||||||
|
return (current_value - rt) * (ft - final_tab[index - 1]) / (rt - raw_tab[index - 1]) + ft
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- we shouldn't be here, so something went wrong - return arbitrary max. final value, maybe the user will notice the problem:
|
||||||
|
return final_tab[#final_tab]
|
||||||
|
end
|
||||||
|
|
||||||
|
function trim(s) --http://lua-users.org/wiki/CommonFunctions
|
||||||
|
-- from PiL2 20.4
|
||||||
|
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||||
|
end
|
||||||
|
function formatTime(time)
|
||||||
|
local seconds = math.floor(time) % 60
|
||||||
|
local minutes = math.floor(time / 60) % 60
|
||||||
|
local hours = math.floor(time / (60 * 60)) % 24
|
||||||
|
return string.format("%02d", hours) .. "-" .. string.format("%02d", minutes) .. "-" .. string.format("%02d", seconds)
|
||||||
|
end
|
||||||
|
|
||||||
|
function meters2feet(meters)
|
||||||
|
local feet = meters * 3.281
|
||||||
|
return feet
|
||||||
|
end
|
||||||
|
|
||||||
|
function feet2meters(feet)
|
||||||
|
local meters = feet / 3.281
|
||||||
|
return feet
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2milesPerHour(metersPerSecond)
|
||||||
|
local milesPerHour = metersPerSecond * 2.237
|
||||||
|
return milesPerHour
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2knots(metersPerSecond)
|
||||||
|
local knots = metersPerSecond * 1.944
|
||||||
|
return knots
|
||||||
|
end
|
||||||
|
|
||||||
|
function kgPerSecond2poundPerHour(kgPerSecond)
|
||||||
|
poundPerHour = kgPerSecond * 7937
|
||||||
|
return poundPerHour
|
||||||
|
end
|
||||||
|
|
||||||
|
function metersPerSecond2feetPerMinute(metersPerSecond)
|
||||||
|
local feetPerMinute = metersPerSecond * 197
|
||||||
|
return feetPerMinute
|
||||||
|
end
|
||||||
|
|
||||||
|
function round(num, numDecimalPlaces) --http://lua-users.org/wiki/SimpleRound
|
||||||
|
local mult = 10^(numDecimalPlaces or 0)
|
||||||
|
return math.floor(num * mult + 0.5) / mult
|
||||||
|
end
|
||||||
|
|
||||||
|
function format_int(number) --https://stackoverflow.com/questions/10989788/format-integer-in-lua
|
||||||
|
local i, j, minus, int, fraction = tostring(number):find('([-]?)(%d+)([.]?%d*)')
|
||||||
|
-- reverse the int-string and append a comma to all blocks of 3 digits
|
||||||
|
int = int:reverse():gsub("(%d%d%d)", "%1,")
|
||||||
|
-- reverse the int-string back remove an optional comma and put the
|
||||||
|
-- optional minus and fractional part back
|
||||||
|
return minus .. int:reverse():gsub("^,", "") .. fraction
|
||||||
|
end
|
||||||
|
|
||||||
|
function formatCoord(type, isLat, d)
|
||||||
|
local h
|
||||||
|
if isLat then
|
||||||
|
if d < 0 then
|
||||||
|
h = 'S'
|
||||||
|
d = -d
|
||||||
|
else
|
||||||
|
h = 'N'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if d < 0 then
|
||||||
|
h = 'W'
|
||||||
|
d = -d
|
||||||
|
else
|
||||||
|
h = 'E'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local g = math.floor(d)
|
||||||
|
local m = math.floor(d * 60 - g * 60)
|
||||||
|
local s = d * 3600 - g * 3600 - m * 60
|
||||||
|
|
||||||
|
if type == "DMS" then -- Degree Minutes Seconds
|
||||||
|
s = math.floor(s * 100) / 100
|
||||||
|
return string.format('%s %2d°%.2d\'%05.2f"', h, g, m, s)
|
||||||
|
elseif type == "DDM" then -- Degree Decimal Minutes
|
||||||
|
s = math.floor(s / 60 * 1000)
|
||||||
|
return string.format('%s %2d°%02d.%3.3d\'', h, g, m, s)
|
||||||
|
else -- Decimal Degrees
|
||||||
|
return string.format('%f',d)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function getdistance(lat1,lat2,lon1,lon2,unit) -- https://www.geeksforgeeks.org/program-distance-two-points-earth/
|
||||||
|
--Example Locations
|
||||||
|
--lat1 = 42.1578 -- POTI
|
||||||
|
--lat2 = 42.3269 -- HONI
|
||||||
|
--lon1 = 41.6777
|
||||||
|
--lon2 = 42.4122
|
||||||
|
|
||||||
|
local lon1 = toRadians(lon1)
|
||||||
|
local lon2 = toRadians(lon2)
|
||||||
|
local lat1 = toRadians(lat1)
|
||||||
|
local lat2 = toRadians(lat2)
|
||||||
|
|
||||||
|
-- Haversine formula
|
||||||
|
local dlon = lon2 - lon1
|
||||||
|
local dlat = lat2 - lat1
|
||||||
|
local a = math.pow(math.sin(dlat / 2), 2) +
|
||||||
|
math.cos(lat1) * math.cos(lat2) *
|
||||||
|
math.pow(math.sin(dlon / 2),2)
|
||||||
|
|
||||||
|
local c = 2 * math.asin(math.sqrt(a))
|
||||||
|
|
||||||
|
local r -- Radius of earth in X.
|
||||||
|
if unit == 'nm' then
|
||||||
|
r = 6371 / 1.852 -- times 1.852 because I could not find a good NM source
|
||||||
|
elseif unit == 'km' then
|
||||||
|
r = 6371 -- Use 6371 for kilometers
|
||||||
|
elseif unit == 'miles' then
|
||||||
|
r = 3956 -- Use 3956 for miles
|
||||||
|
elseif unit == 'meters' then
|
||||||
|
r = 6371 * 1000
|
||||||
|
end
|
||||||
|
|
||||||
|
-- calculate the result
|
||||||
|
return (c * r)
|
||||||
|
end
|
||||||
|
|
||||||
|
function toRadians(angleIn10thofaDegree)
|
||||||
|
return (angleIn10thofaDegree * math.pi) / 180
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function getBearing(lat1,lat2,lon1,lon2, magnetic)
|
||||||
|
local bearing_rad = math.atan2(lon2 - lon1, lat2 - lat1)
|
||||||
|
if bearing_rad < 0 then
|
||||||
|
bearing_rad = bearing_rad + (2 * math.pi)
|
||||||
|
end
|
||||||
|
|
||||||
|
bearing = math.deg(bearing_rad)
|
||||||
|
|
||||||
|
-- start calculation for getting the magnetic bar
|
||||||
|
local _aircraftPitch, _aircraftBank, aircraftYawTrue = LoGetADIPitchBankYaw()
|
||||||
|
aircraftYawTrue = aircraftYawTrue * 57.3 -- actually heading
|
||||||
|
local aircraftYawMagnetic = LoGetMagneticYaw() * 57.3
|
||||||
|
local magneticVariance = aircraftYawTrue - aircraftYawMagnetic
|
||||||
|
|
||||||
|
if magnetic == true then
|
||||||
|
bearing = bearing - magneticVariance
|
||||||
|
end
|
||||||
|
|
||||||
|
-- correction for bearings less than 0 due to the calculation above
|
||||||
|
if bearing < 0 then
|
||||||
|
bearing = bearing + 360
|
||||||
|
end
|
||||||
|
|
||||||
|
return bearing
|
||||||
|
end
|
||||||
|
|
||||||
|
function addZeros3(number)
|
||||||
|
number = string.format("%.1d" , number)
|
||||||
|
if #number == 2 then
|
||||||
|
number = "0" .. number
|
||||||
|
elseif #number == 1 then
|
||||||
|
number = "00" .. number
|
||||||
|
end
|
||||||
|
return number
|
||||||
|
end
|
||||||
|
|
||||||
|
function prefixZerosFixedLength(number, digitLength) -- prefixZerosFixedLength(99, 3) --> 099
|
||||||
|
number = string.format("%.1d" , number) -- make the number a string
|
||||||
|
local zerosToAdd = digitLength - #number
|
||||||
|
s = ''
|
||||||
|
for i = 1, zerosToAdd do
|
||||||
|
s = s .. 0
|
||||||
|
end
|
||||||
|
return s .. number
|
||||||
|
end
|
||||||
|
|
||||||
|
function mgrsTableize(mgrsString)
|
||||||
|
-- Reference: https://upload.wikimedia.org/wikipedia/commons/b/b7/Universal_Transverse_Mercator_zones.svg
|
||||||
|
-- example: 38 T LM 12345 54321
|
||||||
|
-- (\d+\s\w)\s(\w+)\s(.+)\s(.+) --c# version of regex
|
||||||
|
-- UTMZone = string,
|
||||||
|
-- MGRSDigraph = string,
|
||||||
|
-- Easting = number,
|
||||||
|
-- Northing = number
|
||||||
|
local UTMZone , MGRSDigraph, Easting, Northing = mgrsString:match('(%d+%s%w)%s(%w+)%s(.+)%s(.+)')
|
||||||
|
local mgrsTbl = {}
|
||||||
|
table.insert(mgrsTbl, {UTMZone,MGRSDigraph,Easting,Northing})
|
||||||
|
return mgrsTbl
|
||||||
|
end
|
||||||
|
|
||||||
|
function isNilOrEmpty(value)
|
||||||
|
if value == "" or value == nil then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function NilOrEmpty(value)
|
||||||
|
if value == "" then
|
||||||
|
return 'empty'
|
||||||
|
elseif value == nil then
|
||||||
|
return 'empty'
|
||||||
|
else
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user