TEMPEST.114 Posted March 12, 2023 Posted March 12, 2023 (edited) The only thing missing from my automated METAR script is the description of the type of cloud coverage. I can't see where this is hiding. Has anyone solved this already? If so would you elucidate please? Thanks Edited March 13, 2023 by Elphaba
Chump Posted March 13, 2023 Posted March 13, 2023 If you are talking about the preset clouds, the density property is found at: \Config\Effects\clouds.lua If you are talking about manual settings, the slider has 10 increments so you would need to adjust from octas. I did it like this: local function getCoverage(c) -- instead of using octals, split into ten parts for cloud density slider in ME if c < .3 then -- 1-2 return "FEW", 1 elseif c > .2 and c < .6 then -- 3-5 return "SCT", 2 elseif c > .5 and c < .9 then -- 6-8 return "BKN", 3 end return "OVC", 4 -- 9-10 end
TEMPEST.114 Posted March 14, 2023 Author Posted March 14, 2023 On 3/13/2023 at 1:20 PM, Chump said: getCoverage(c) that's awesome! but where are you getting 'c' from? Is the density in clouds.lua read and stored in env.mission that I can read at runtime?
Chump Posted March 14, 2023 Posted March 14, 2023 (edited) 3 hours ago, Elphaba said: that's awesome! but where are you getting 'c' from? Is the density in clouds.lua read and stored in env.mission that I can read at runtime? I modified the getCoverage() function so that it only contains pertinent information now. You can try something like this to get cloud density now: local function getCoverage(coverage) -- instead of using octals, split into ten parts for cloud density slider in ME if coverage < .3 then -- 1-2 return "FEW" elseif coverage > .2 and coverage < .6 then -- 3-5 return "SCT" elseif coverage > .5 and coverage < .9 then -- 6-8 return "BKN" end return "OVC" -- 9-10 end local weather = env.mission.weather if weather.atmosphere_type == 0 then -- no dynamic weather local preset = weather.clouds.preset if preset then local CloudPresets = dofile("Config\\Effects\\getCloudsPresets.lua") local cloudPreset = CloudPresets[preset] if cloudPreset then for _, layer in ipairs(cloudPreset.layers) do if layer.coverage > 0 then local c = getCoverage(layer.coverage) -- c will contain "FEW", "BKN", etc. end end end else local c = getCoverage(weather.clouds.density / 10) -- c will contain "FEW", "BKN", etc. end end Edited March 14, 2023 by Chump fixed typos
TEMPEST.114 Posted March 14, 2023 Author Posted March 14, 2023 25 minutes ago, Chump said: I modified the getCoverage() function so that it only contains pertinent information now. You can try something like this to get cloud density now: local function getCoverage(coverage) -- instead of using octals, split into ten parts for cloud density slider in ME if coverage < .3 then -- 1-2 return "FEW" elseif coverage > .2 and coverage < .6 then -- 3-5 return "SCT" elseif coverage > .5 and coverage < .9 then -- 6-8 return "BKN" end return "OVC" -- 9-10 end local weather = env.mission.weather if weather.atmosphere_type == 0 then -- no dynamic weather local preset = weather.clouds.preset if preset then local CloudPresets = dofile("Config\\Effects\\getCloudsPresets.lua") local cloudPreset = CloudPresets.preset for _, layer in ipairs(p.layers) do if layer.coverage > 0 then local c = getCoverage(layer.coverage) -- c will contain "FEW", "BKN", etc. end end else local c = getCoverage(weather.clouds.density / 10) -- c will contain "FEW", "BKN", etc. end end That's wonderful and very clear code, I can follow that. But this means I have to desanitise the server right so I can do the 'dofile'? I was trying to avoid that. Maybe if the clouds.lua doesn't change much I can just hardcode it in?
TEMPEST.114 Posted March 14, 2023 Author Posted March 14, 2023 32 minutes ago, Chump said: I modified the getCoverage() function so that it only contains pertinent information now. You can try something like this to get cloud density now: local function getCoverage(coverage) -- instead of using octals, split into ten parts for cloud density slider in ME if coverage < .3 then -- 1-2 return "FEW" elseif coverage > .2 and coverage < .6 then -- 3-5 return "SCT" elseif coverage > .5 and coverage < .9 then -- 6-8 return "BKN" end return "OVC" -- 9-10 end local weather = env.mission.weather if weather.atmosphere_type == 0 then -- no dynamic weather local preset = weather.clouds.preset if preset then local CloudPresets = dofile("Config\\Effects\\getCloudsPresets.lua") local cloudPreset = CloudPresets.preset for _, layer in ipairs(p.layers) do if layer.coverage > 0 then local c = getCoverage(layer.coverage) -- c will contain "FEW", "BKN", etc. end end else local c = getCoverage(weather.clouds.density / 10) -- c will contain "FEW", "BKN", etc. end end And what do you do if it's dynamic weather? Is that not available at all from the api?
Chump Posted March 14, 2023 Posted March 14, 2023 1 hour ago, Elphaba said: But this means I have to desanitise the server right so I can do the 'dofile'? I was trying to avoid that. Maybe if the clouds.lua doesn't change much I can just hardcode it in? It isn't the dofile() that is the issue. It is the other functions that are called by the scripts. getCloudsPresets.lua will work fine without desanitization, but clouds.lua contains a translation method: readableName = '01 ##'.. _('Few Scattered Clouds \nMETAR: FEW/SCT 7/8'), -- pretty much defined as local function _(text) return gettext.translate(text) end I suppose that you have an option of redefining this function to simply return the passed-in string: function _(s) return s end You could define this in the clouds.lua file so that you did not have to define it globally (not sure what would break). Here is some sample code that should give you an idea of how it works: --[[ NOTE: -- this method is used in clouds.lua for translations -- not translating, just returning string -- redefining it here could have a side-effect on translations -- it will also not allow you to use the throwaway variable in loops --]] function _(s) return s end local function getCoverage(coverage) -- instead of using octals, split into ten parts for cloud density slider in ME if coverage < .3 then -- 1-2 return "FEW" elseif coverage > .2 and coverage < .6 then -- 3-5 return "SCT" elseif coverage > .5 and coverage < .9 then -- 6-8 return "BKN" end return "OVC" -- 9-10 end local weather = env.mission.weather if weather.atmosphere_type == 0 then -- no dynamic weather local preset = weather.clouds.preset if preset then local CloudPresets = dofile("Config\\Effects\\getCloudsPresets.lua") local cloudPreset = CloudPresets[preset] if cloudPreset then for i, layer in ipairs(cloudPreset.layers) do -- NOTE: added index variable here instead of using throwaway if layer.coverage > 0 then trigger.action.outText(string.format("%sm: %s", layer.altitudeMin, getCoverage(layer.coverage)), 5) end end end else local clouds = weather.clouds trigger.action.outText(string.format("%sm: %s", clouds.base, getCoverage(clouds.density / 10)), 5) end end Unfortunately, I have not found a good set of useful methods for clouds from the weather.dll to support dynamic weather. Hope this helps! 1
TEMPEST.114 Posted March 14, 2023 Author Posted March 14, 2023 4 hours ago, Chump said: It isn't the dofile() that is the issue. It is the other functions that are called by the scripts. getCloudsPresets.lua will work fine without desanitization, but clouds.lua contains a translation method: readableName = '01 ##'.. _('Few Scattered Clouds \nMETAR: FEW/SCT 7/8'), -- pretty much defined as local function _(text) return gettext.translate(text) end I suppose that you have an option of redefining this function to simply return the passed-in string: function _(s) return s end You could define this in the clouds.lua file so that you did not have to define it globally (not sure what would break). Here is some sample code that should give you an idea of how it works: --[[ NOTE: -- this method is used in clouds.lua for translations -- not translating, just returning string -- redefining it here could have a side-effect on translations -- it will also not allow you to use the throwaway variable in loops --]] function _(s) return s end local function getCoverage(coverage) -- instead of using octals, split into ten parts for cloud density slider in ME if coverage < .3 then -- 1-2 return "FEW" elseif coverage > .2 and coverage < .6 then -- 3-5 return "SCT" elseif coverage > .5 and coverage < .9 then -- 6-8 return "BKN" end return "OVC" -- 9-10 end local weather = env.mission.weather if weather.atmosphere_type == 0 then -- no dynamic weather local preset = weather.clouds.preset if preset then local CloudPresets = dofile("Config\\Effects\\getCloudsPresets.lua") local cloudPreset = CloudPresets[preset] if cloudPreset then for i, layer in ipairs(cloudPreset.layers) do -- NOTE: added index variable here instead of using throwaway if layer.coverage > 0 then trigger.action.outText(string.format("%sm: %s", layer.altitudeMin, getCoverage(layer.coverage)), 5) end end end else local clouds = weather.clouds trigger.action.outText(string.format("%sm: %s", clouds.base, getCoverage(clouds.density / 10)), 5) end end Unfortunately, I have not found a good set of useful methods for clouds from the weather.dll to support dynamic weather. Hope this helps! You can redefine a function in another table/file? Wow... Thank you for all this and for taking the time to go through it.
Recommended Posts