-- ============================================================================ -- X-Plane Glass Cockpit — Terrain awareness probe (FlyWithLua companion) -- ============================================================================ -- The web MFD can't read X-Plane's scenery elevation over the Web API. This -- script samples a grid of terrain heights around the aircraft with X-Plane's -- terrain probe and writes them to terrain.json in the sync folder; the bridge -- streams it to the tablets, which colour it red/yellow vs aircraft altitude -- (G1000 TAWS). See terrain-sync in server/fmssync.js. -- -- INSTALL: copy to /Resources/plugins/FlyWithLua/Scripts/ (alongside -- fms-sync.lua). Needs FlyWithLua NG+ (XPLM scenery-probe bindings). -- ============================================================================ local SYNC = SYSTEM_DIRECTORY .. "Output/fms-sync/" local OUT = SYNC .. "terrain.json" os.execute('mkdir -p "' .. SYNC .. '" 2>/dev/null || mkdir "' .. SYNC .. '" 2>nul') local M_FT = 3.28084 local ROWS, COLS = 24, 24 local DLAT, DLON = 0.35, 0.5 -- half-box (deg) around the aircraft local probe = XPLMCreateProbe(0) -- xplm_ProbeY -- terrain elevation (ft MSL) at a lat/lon, via the vertical scenery probe local function elev_ft(lat, lon) local x, y, z = XPLMWorldToLocal(lat, lon, 0) local res, _px, py = XPLMProbeTerrainXYZ(probe, x, y, z) if res ~= 0 then return 0 end -- 0 = xplm_ProbeHitTerrain local _plat, _plon, palt = XPLMLocalToWorld(x, py, z) return math.max(0, math.floor(palt * M_FT)) end function gc_terrain_tick() local lat = get("sim/flightmodel/position/latitude") local lon = get("sim/flightmodel/position/longitude") local alt = math.floor(get("sim/flightmodel/position/elevation") * M_FT) -- true MSL local n, s = lat + DLAT, lat - DLAT local w, e = lon - DLON, lon + DLON local cells = {} for r = 0, ROWS - 1 do -- r = 0 → north (top) local glat = n - (r / (ROWS - 1)) * (n - s) for c = 0, COLS - 1 do -- c = 0 → west local glon = w + (c / (COLS - 1)) * (e - w) cells[#cells + 1] = elev_ft(glat, glon) end end local f = io.open(OUT, "w") if not f then return end f:write(string.format( '{"lat":%.5f,"lon":%.5f,"alt":%d,"n":%.5f,"s":%.5f,"w":%.5f,"e":%.5f,"rows":%d,"cols":%d,"elev":[%s]}', lat, lon, alt, n, s, w, e, ROWS, COLS, table.concat(cells, ","))) f:close() end do_often("gc_terrain_tick()") -- ~1×/sec logMsg("[glass-cockpit] terrain probe active -> " .. OUT)