DorianH935

Untitled

Jan 29th, 2026
39
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.00 KB | None | 0 0
  1. -- OpenGlasses 2 AR Control System v3.0
  2. -- CORRECTED API VERSION
  3.  
  4. local component = require("component")
  5. local event = require("event")
  6. local term = require("term")
  7. local computer = require("computer")
  8. local serialization = require("serialization")
  9. local filesystem = require("filesystem")
  10.  
  11. -- Components
  12. local gpu = component.gpu
  13. local glasses = component.glasses
  14. local nav = component.navigation
  15. local radar = component.radar
  16. local geo = component.geolyzer or nil
  17.  
  18. -- Configuration
  19. local config = {
  20. radarEnabled = false,
  21. radarRange = 64,
  22. radarUpdateInterval = 0.5,
  23.  
  24. fullbrightEnabled = false,
  25. fullbrightOpacity = 0.3,
  26.  
  27. geolyserEnabled = false,
  28. geolyserRadius = 8,
  29. geolyserDepth = 32,
  30.  
  31. hudEnabled = true,
  32. showCoordinates = true,
  33. showCompass = true,
  34.  
  35. colors = {
  36. player = 0x00FF00,
  37. hostile = 0xFF0000,
  38. passive = 0x00FFFF,
  39. item = 0xFFFF00,
  40. waypoint = 0xFFFFFF,
  41. ore = 0xFFAA00
  42. }
  43. }
  44.  
  45. -- State
  46. local widgets = {
  47. radar = {},
  48. fullbright = nil,
  49. geolyser = {},
  50. waypoints = {},
  51. hud = {}
  52. }
  53.  
  54. local running = true
  55. local playerPos = {x=0, y=0, z=0}
  56. local playerFacing = 0
  57. local savedWaypoints = {}
  58.  
  59. -- Utility Functions
  60. local function saveConfig()
  61. local file = io.open("/home/ar_config.cfg", "w")
  62. if file then
  63. file:write(serialization.serialize(config))
  64. file:close()
  65. end
  66. end
  67.  
  68. local function loadConfig()
  69. if filesystem.exists("/home/ar_config.cfg") then
  70. local file = io.open("/home/ar_config.cfg", "r")
  71. if file then
  72. local content = file:read("*a")
  73. file:close()
  74. local success, loaded = pcall(serialization.unserialize, content)
  75. if success then
  76. for k, v in pairs(loaded) do
  77. config[k] = v
  78. end
  79. end
  80. end
  81. end
  82. end
  83.  
  84. local function saveWaypoints()
  85. local file = io.open("/home/ar_waypoints.dat", "w")
  86. if file then
  87. file:write(serialization.serialize(savedWaypoints))
  88. file:close()
  89. end
  90. end
  91.  
  92. local function loadWaypoints()
  93. if filesystem.exists("/home/ar_waypoints.dat") then
  94. local file = io.open("/home/ar_waypoints.dat", "r")
  95. if file then
  96. local content = file:read("*a")
  97. file:close()
  98. local success, loaded = pcall(serialization.unserialize, content)
  99. if success then
  100. savedWaypoints = loaded
  101. end
  102. end
  103. end
  104. end
  105.  
  106. local function updatePlayerPos()
  107. local x, y, z = nav.getPosition()
  108. playerPos = {x=math.floor(x), y=math.floor(y), z=math.floor(z)}
  109. playerFacing = nav.getFacing()
  110. end
  111.  
  112. local function getDistance(x1, y1, z1, x2, y2, z2)
  113. return math.sqrt((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2)
  114. end
  115.  
  116. local function getCardinalDirection(yaw)
  117. yaw = yaw % 360
  118. if yaw < 0 then yaw = yaw + 360 end
  119.  
  120. if yaw >= 337.5 or yaw < 22.5 then return "S"
  121. elseif yaw >= 22.5 and yaw < 67.5 then return "SW"
  122. elseif yaw >= 67.5 and yaw < 112.5 then return "W"
  123. elseif yaw >= 112.5 and yaw < 157.5 then return "NW"
  124. elseif yaw >= 157.5 and yaw < 202.5 then return "N"
  125. elseif yaw >= 202.5 and yaw < 247.5 then return "NE"
  126. elseif yaw >= 247.5 and yaw < 292.5 then return "E"
  127. elseif yaw >= 292.5 and yaw < 337.5 then return "SE"
  128. end
  129. return "?"
  130. end
  131.  
  132. -- Widget Management
  133. local function clearAllWidgets()
  134. glasses.removeAll()
  135. widgets.radar = {}
  136. widgets.fullbright = nil
  137. widgets.geolyser = {}
  138. widgets.waypoints = {}
  139. widgets.hud = {}
  140. end
  141.  
  142. local function clearRadar()
  143. for _, widget in pairs(widgets.radar) do
  144. if widget and widget.removeWidget then
  145. widget.removeWidget()
  146. end
  147. end
  148. widgets.radar = {}
  149. end
  150.  
  151. local function clearGeolyser()
  152. for _, widget in pairs(widgets.geolyser) do
  153. if widget and widget.removeWidget then
  154. widget.removeWidget()
  155. end
  156. end
  157. widgets.geolyser = {}
  158. end
  159.  
  160. local function clearHUD()
  161. for _, widget in pairs(widgets.hud) do
  162. if widget and widget.removeWidget then
  163. widget.removeWidget()
  164. end
  165. end
  166. widgets.hud = {}
  167. end
  168.  
  169. local function clearWaypoints()
  170. for _, widget in pairs(widgets.waypoints) do
  171. if widget and widget.removeWidget then
  172. widget.removeWidget()
  173. end
  174. end
  175. widgets.waypoints = {}
  176. end
  177.  
  178. -- Fullbright
  179. local function enableFullbright()
  180. if widgets.fullbright then
  181. widgets.fullbright.removeWidget()
  182. end
  183.  
  184. -- Create fullscreen bright overlay
  185. widgets.fullbright = glasses.addQuad2D()
  186. widgets.fullbright.addPoint(-500, -500)
  187. widgets.fullbright.addPoint(500, -500)
  188. widgets.fullbright.addPoint(500, 500)
  189. widgets.fullbright.addPoint(-500, 500)
  190. widgets.fullbright.setColor(255, 255, 255)
  191. widgets.fullbright.setAlpha(config.fullbrightOpacity)
  192.  
  193. config.fullbrightEnabled = true
  194. end
  195.  
  196. local function disableFullbright()
  197. if widgets.fullbright then
  198. widgets.fullbright.removeWidget()
  199. widgets.fullbright = nil
  200. end
  201. config.fullbrightEnabled = false
  202. end
  203.  
  204. -- HUD
  205. local function updateHUD()
  206. if not config.hudEnabled then return end
  207.  
  208. clearHUD()
  209. updatePlayerPos()
  210.  
  211. -- Coordinates text
  212. if config.showCoordinates then
  213. local coordText = glasses.addText2D()
  214. coordText.addText(5, 5, string.format("XYZ: %d, %d, %d", playerPos.x, playerPos.y, playerPos.z))
  215. coordText.setColor(255, 255, 255)
  216. table.insert(widgets.hud, coordText)
  217. end
  218.  
  219. -- Compass text
  220. if config.showCompass then
  221. local direction = getCardinalDirection(playerFacing)
  222. local compassText = glasses.addText2D()
  223. compassText.addText(5, 15, string.format("Facing: %s (%.1f°)", direction, playerFacing))
  224. compassText.setColor(255, 255, 0)
  225. table.insert(widgets.hud, compassText)
  226. end
  227.  
  228. -- Status text
  229. local statusText = glasses.addText2D()
  230. local status = {}
  231. if config.radarEnabled then table.insert(status, "RADAR") end
  232. if config.fullbrightEnabled then table.insert(status, "BRIGHT") end
  233. if config.geolyserEnabled then table.insert(status, "GEO") end
  234.  
  235. if #status > 0 then
  236. statusText.addText(5, 25, "Active: " .. table.concat(status, " | "))
  237. else
  238. statusText.addText(5, 25, "All systems standby")
  239. end
  240. statusText.setColor(0, 255, 0)
  241. table.insert(widgets.hud, statusText)
  242. end
  243.  
  244. -- Radar
  245. local function updateRadar()
  246. if not config.radarEnabled then return end
  247.  
  248. clearRadar()
  249. updatePlayerPos()
  250.  
  251. local entities = radar.getPlayers(config.radarRange)
  252.  
  253. for _, ent in ipairs(entities) do
  254. local dist = getDistance(playerPos.x, playerPos.y, playerPos.z, ent.x, ent.y, ent.z)
  255.  
  256. -- Skip if too close (probably the player)
  257. if dist > 1 then
  258. local color = config.colors.player
  259. local isHostile = false
  260.  
  261. -- Classify entity
  262. local name = ent.name or "Unknown"
  263. if name:match("Creeper") or name:match("Zombie") or name:match("Skeleton") or
  264. name:match("Spider") or name:match("Witch") or name:match("Enderman") then
  265. color = config.colors.hostile
  266. isHostile = true
  267. elseif name:match("Cow") or name:match("Sheep") or name:match("Pig") or
  268. name:match("Chicken") or name:match("Horse") then
  269. color = config.colors.passive
  270. end
  271.  
  272. -- Create 3D marker
  273. local dot = glasses.addDot3D()
  274. dot.set3DPos(ent.x, ent.y + 1, ent.z)
  275. dot.setColor((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF)
  276. dot.setSize(isHostile and 3 or 2)
  277. dot.setAlpha(0.9)
  278.  
  279. -- Create 3D label
  280. local label = glasses.addText3D()
  281. label.set3DPos(ent.x, ent.y + 2, ent.z)
  282. label.setText(string.format("%s %.1fm", name, dist))
  283. label.setColor((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF)
  284. label.setAlpha(0.8)
  285.  
  286. -- Add danger warning for nearby hostiles
  287. if isHostile and dist < 10 then
  288. local warning = glasses.addText3D()
  289. warning.set3DPos(ent.x, ent.y + 2.5, ent.z)
  290. warning.setText("! DANGER !")
  291. warning.setColor(255, 0, 0)
  292. warning.setAlpha(1.0)
  293. table.insert(widgets.radar, warning)
  294. end
  295.  
  296. table.insert(widgets.radar, dot)
  297. table.insert(widgets.radar, label)
  298. end
  299. end
  300. end
  301.  
  302. -- Geolyser
  303. local function isOre(hardness)
  304. return hardness >= 3 and hardness <= 5
  305. end
  306.  
  307. local function updateGeolyser()
  308. if not config.geolyserEnabled or not geo then return end
  309.  
  310. clearGeolyser()
  311. updatePlayerPos()
  312.  
  313. local radius = config.geolyserRadius
  314. local depth = config.geolyserDepth
  315. local foundOres = 0
  316.  
  317. -- Scan in layers
  318. for y = 0, -depth, -2 do
  319. local scan = geo.scan(playerPos.x, playerPos.y + y, playerPos.z, radius, radius, 1)
  320. local idx = 1
  321.  
  322. for dx = -radius, radius-1 do
  323. for dz = -radius, radius-1 do
  324. local hardness = scan[idx]
  325. idx = idx + 1
  326.  
  327. if hardness and isOre(hardness) then
  328. local wx = playerPos.x + dx
  329. local wy = playerPos.y + y
  330. local wz = playerPos.z + dz
  331.  
  332. local cube = glasses.addCube3D()
  333. cube.set3DPos(wx + 0.5, wy + 0.5, wz + 0.5)
  334. cube.setColor(255, 170, 0)
  335. cube.setAlpha(0.4)
  336. cube.setVisibleThroughObjects(true)
  337.  
  338. table.insert(widgets.geolyser, cube)
  339. foundOres = foundOres + 1
  340. end
  341. end
  342. end
  343. end
  344.  
  345. -- Show ore count in HUD
  346. if foundOres > 0 then
  347. local oreText = glasses.addText2D()
  348. oreText.addText(5, 35, string.format("Ores detected: %d", foundOres))
  349. oreText.setColor(255, 170, 0)
  350. table.insert(widgets.hud, oreText)
  351. end
  352. end
  353.  
  354. -- Waypoint Management
  355. local function addWaypoint(name, x, y, z, color)
  356. color = color or config.colors.waypoint
  357.  
  358. local marker = glasses.addDot3D()
  359. marker.set3DPos(x, y, z)
  360. marker.setColor((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF)
  361. marker.setSize(4)
  362. marker.setAlpha(1.0)
  363.  
  364. local label = glasses.addText3D()
  365. label.set3DPos(x, y + 1, z)
  366. updatePlayerPos()
  367. local dist = getDistance(playerPos.x, playerPos.y, playerPos.z, x, y, z)
  368. label.setText(string.format("%s %.1fm", name, dist))
  369. label.setColor((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF)
  370.  
  371. table.insert(widgets.waypoints, marker)
  372. table.insert(widgets.waypoints, label)
  373. end
  374.  
  375. local function refreshWaypoints()
  376. clearWaypoints()
  377. for _, wp in ipairs(savedWaypoints) do
  378. addWaypoint(wp.name, wp.x, wp.y, wp.z, wp.color)
  379. end
  380. end
  381.  
  382. -- UI Drawing
  383. local function drawMenu()
  384. term.clear()
  385. gpu.setBackground(0x000000)
  386. gpu.setForeground(0xFFFFFF)
  387.  
  388. print("╔═════════════════════════════════════════════╗")
  389. print("║ OpenGlasses 2 AR Control System v3.0 ║")
  390. print("╚═════════════════════════════════════════════╝")
  391. print()
  392.  
  393. updatePlayerPos()
  394. print(string.format("Position: %d, %d, %d | Facing: %s",
  395. playerPos.x, playerPos.y, playerPos.z, getCardinalDirection(playerFacing)))
  396. print()
  397.  
  398. print("╔═══ FEATURES ═══════════════════════════════╗")
  399. print(string.format("║ [1] Radar: %-7s Range: %2dm ║",
  400. config.radarEnabled and "ON" or "OFF", config.radarRange))
  401. print(string.format("║ [2] Fullbright: %-7s Opacity: %3d%% ║",
  402. config.fullbrightEnabled and "ON" or "OFF", math.floor(config.fullbrightOpacity * 100)))
  403.  
  404. if geo then
  405. print(string.format("║ [3] Geolyser: %-7s R:%2d D:%2d ║",
  406. config.geolyserEnabled and "ON" or "OFF", config.geolyserRadius, config.geolyserDepth))
  407. else
  408. print("║ [3] Geolyser: N/A (no geolyzer) ║")
  409. end
  410.  
  411. print(string.format("║ [4] HUD: %-7s ║",
  412. config.hudEnabled and "ON" or "OFF"))
  413. print("╚════════════════════════════════════════════╝")
  414. print()
  415.  
  416. print("╔═══ WAYPOINTS ══════════════════════════════╗")
  417. print("║ [W] Add Waypoint at Current Position ║")
  418. print("║ [L] List Waypoints ║")
  419. print("║ [D] Delete Waypoint ║")
  420. print(string.format("║ Total Waypoints: %-3d ║", #savedWaypoints))
  421. print("╚════════════════════════════════════════════╝")
  422. print()
  423.  
  424. print("╔═══ SETTINGS ═══════════════════════════════╗")
  425. print("║ [R] Adjust Radar Range ║")
  426. print("║ [F] Adjust Fullbright Opacity ║")
  427. if geo then
  428. print("║ [G] Adjust Geolyser Settings ║")
  429. end
  430. print("║ [H] Toggle HUD Elements ║")
  431. print("╚════════════════════════════════════════════╝")
  432. print()
  433.  
  434. print("╔═══ SYSTEM ═════════════════════════════════╗")
  435. print("║ [C] Clear All Widgets ║")
  436. print("║ [S] Save Configuration ║")
  437. print("║ [Q] Quit ║")
  438. print("╚════════════════════════════════════════════╝")
  439. print()
  440. print("Press a key to select option...")
  441. end
  442.  
  443. local function listWaypoints()
  444. term.clear()
  445. print("╔═══ WAYPOINTS ══════════════════════════════╗")
  446. if #savedWaypoints == 0 then
  447. print("║ No waypoints saved ║")
  448. else
  449. for i, wp in ipairs(savedWaypoints) do
  450. print(string.format("║ %2d. %-20s (%d,%d,%d) ║",
  451. i, wp.name:sub(1,20), wp.x, wp.y, wp.z))
  452. end
  453. end
  454. print("╚════════════════════════════════════════════╝")
  455. print("\nPress any key to continue...")
  456. event.pull("key_down")
  457. end
  458.  
  459. -- Event Handlers
  460. local function handleInput(char, code)
  461. if char == 0 then return end
  462.  
  463. local key = string.char(char):lower()
  464.  
  465. if key == "1" then
  466. config.radarEnabled = not config.radarEnabled
  467. if config.radarEnabled then
  468. updateRadar()
  469. else
  470. clearRadar()
  471. end
  472. updateHUD()
  473.  
  474. elseif key == "2" then
  475. if config.fullbrightEnabled then
  476. disableFullbright()
  477. else
  478. enableFullbright()
  479. end
  480. updateHUD()
  481.  
  482. elseif key == "3" and geo then
  483. config.geolyserEnabled = not config.geolyserEnabled
  484. if config.geolyserEnabled then
  485. updateGeolyser()
  486. else
  487. clearGeolyser()
  488. end
  489. updateHUD()
  490.  
  491. elseif key == "4" then
  492. config.hudEnabled = not config.hudEnabled
  493. if config.hudEnabled then
  494. updateHUD()
  495. else
  496. clearHUD()
  497. end
  498.  
  499. elseif key == "w" then
  500. term.clear()
  501. print("Add Waypoint at Current Position")
  502. updatePlayerPos()
  503. print(string.format("Position: %d, %d, %d", playerPos.x, playerPos.y, playerPos.z))
  504. print("\nEnter waypoint name:")
  505. local name = io.read()
  506. if name and name ~= "" then
  507. table.insert(savedWaypoints, {
  508. name = name,
  509. x = playerPos.x,
  510. y = playerPos.y,
  511. z = playerPos.z,
  512. color = config.colors.waypoint
  513. })
  514. saveWaypoints()
  515. refreshWaypoints()
  516. print("\nWaypoint added!")
  517. os.sleep(1)
  518. end
  519.  
  520. elseif key == "l" then
  521. listWaypoints()
  522.  
  523. elseif key == "d" then
  524. if #savedWaypoints == 0 then
  525. term.clear()
  526. print("No waypoints to delete!")
  527. os.sleep(1)
  528. return
  529. end
  530. listWaypoints()
  531. print("\nEnter waypoint number to delete (or 0 to cancel):")
  532. local num = tonumber(io.read())
  533. if num and num > 0 and num <= #savedWaypoints then
  534. table.remove(savedWaypoints, num)
  535. saveWaypoints()
  536. refreshWaypoints()
  537. print("Waypoint deleted!")
  538. os.sleep(1)
  539. end
  540.  
  541. elseif key == "r" then
  542. term.clear()
  543. print(string.format("Current radar range: %dm", config.radarRange))
  544. print("Enter new range (1-64):")
  545. local range = tonumber(io.read())
  546. if range and range >= 1 and range <= 64 then
  547. config.radarRange = range
  548. if config.radarEnabled then
  549. updateRadar()
  550. end
  551. end
  552.  
  553. elseif key == "f" then
  554. term.clear()
  555. print(string.format("Current fullbright opacity: %d%%",
  556. math.floor(config.fullbrightOpacity * 100)))
  557. print("Enter new opacity (0-100):")
  558. local opacity = tonumber(io.read())
  559. if opacity and opacity >= 0 and opacity <= 100 then
  560. config.fullbrightOpacity = opacity / 100
  561. if config.fullbrightEnabled then
  562. disableFullbright()
  563. enableFullbright()
  564. end
  565. end
  566.  
  567. elseif key == "g" and geo then
  568. term.clear()
  569. print(string.format("Current radius: %dm", config.geolyserRadius))
  570. print("Enter new radius (1-16):")
  571. local radius = tonumber(io.read())
  572. if radius and radius >= 1 and radius <= 16 then
  573. config.geolyserRadius = radius
  574. end
  575. print(string.format("Current depth: %dm", config.geolyserDepth))
  576. print("Enter new depth (1-64):")
  577. local depth = tonumber(io.read())
  578. if depth and depth >= 1 and depth <= 64 then
  579. config.geolyserDepth = depth
  580. end
  581. if config.geolyserEnabled then
  582. updateGeolyser()
  583. end
  584.  
  585. elseif key == "h" then
  586. term.clear()
  587. print("HUD Element Toggles:")
  588. print(string.format("[1] Coordinates: %s", config.showCoordinates and "ON" or "OFF"))
  589. print(string.format("[2] Compass: %s", config.showCompass and "ON" or "OFF"))
  590. print("\nEnter option (1-2):")
  591. local opt = io.read()
  592. if opt == "1" then
  593. config.showCoordinates = not config.showCoordinates
  594. elseif opt == "2" then
  595. config.showCompass = not config.showCompass
  596. end
  597. updateHUD()
  598.  
  599. elseif key == "c" then
  600. clearAllWidgets()
  601. config.radarEnabled = false
  602. config.fullbrightEnabled = false
  603. config.geolyserEnabled = false
  604. config.hudEnabled = false
  605.  
  606. elseif key == "s" then
  607. saveConfig()
  608. term.clear()
  609. print("Configuration saved!")
  610. os.sleep(1)
  611.  
  612. elseif key == "q" then
  613. running = false
  614. end
  615. end
  616.  
  617. -- Main Loop
  618. local function mainLoop()
  619. local lastRadarUpdate = 0
  620. local lastGeoUpdate = 0
  621. local lastHUDUpdate = 0
  622.  
  623. while running do
  624. drawMenu()
  625.  
  626. local currentTime = computer.uptime()
  627.  
  628. -- Update radar
  629. if config.radarEnabled and (currentTime - lastRadarUpdate) > config.radarUpdateInterval then
  630. updateRadar()
  631. lastRadarUpdate = currentTime
  632. end
  633.  
  634. -- Update geolyser
  635. if config.geolyserEnabled and (currentTime - lastGeoUpdate) > 5 then
  636. updateGeolyser()
  637. lastGeoUpdate = currentTime
  638. end
  639.  
  640. -- Update HUD
  641. if config.hudEnabled and (currentTime - lastHUDUpdate) > 1 then
  642. updateHUD()
  643. lastHUDUpdate = currentTime
  644. end
  645.  
  646. -- Input handling
  647. local eventType, _, char, code = event.pull(0.1, "key_down")
  648. if eventType == "key_down" then
  649. handleInput(char, code)
  650. end
  651. end
  652. end
  653.  
  654. -- Initialization
  655. term.clear()
  656. print("╔═══════════════════════════════════════════╗")
  657. print("║ OpenGlasses 2 AR Control System v3.0 ║")
  658. print("║ Initializing... ║")
  659. print("╚═══════════════════════════════════════════╝")
  660. print()
  661.  
  662. -- Check components
  663. print("Checking components...")
  664. if not component.isAvailable("glasses") then
  665. print("✗ ERROR: OpenGlasses Terminal not found!")
  666. return
  667. else
  668. print("✓ OpenGlasses Terminal found")
  669. end
  670.  
  671. if not component.isAvailable("navigation") then
  672. print("✗ ERROR: Navigation upgrade not found!")
  673. return
  674. else
  675. print("✓ Navigation upgrade found")
  676. end
  677.  
  678. if not component.isAvailable("radar") then
  679. print("✗ ERROR: Radar upgrade not found!")
  680. return
  681. else
  682. print("✓ Radar upgrade found")
  683. end
  684.  
  685. if not component.isAvailable("geolyzer") then
  686. print("⚠ WARNING: Geolyzer not found (feature disabled)")
  687. else
  688. print("✓ Geolyzer found")
  689. end
  690.  
  691. print()
  692. print("Loading configuration...")
  693. loadConfig()
  694. loadWaypoints()
  695.  
  696. print("✓ Configuration loaded")
  697. print()
  698. print("Refreshing waypoints...")
  699. refreshWaypoints()
  700.  
  701. if config.hudEnabled then
  702. updateHUD()
  703. end
  704.  
  705. print()
  706. print("✓ All systems ready!")
  707. os.sleep(2)
  708.  
  709. -- Run
  710. clearAllWidgets()
  711. mainLoop()
  712.  
  713. -- Cleanup
  714. clearAllWidgets()
  715. saveConfig()
  716. saveWaypoints()
  717. term.clear()
  718. print("AR Control System shutdown complete.")
  719. print("Configuration and waypoints saved.")
Advertisement
Add Comment
Please, Sign In to add comment