Advertisement
neuroticfox

DC CC 0.1b

Jan 1st, 2023 (edited)
1,095
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 21.63 KB | None | 0 0
  1. --peripheral config
  2. local sideoutputFlux = "top"
  3.  
  4. --output multiplier: set by modpack (default = 1.0), change this to the value of draconic evolution config (!!!not tested yet!!!)
  5. local reactorOutputMultiplier = 1.0
  6.  
  7. local reactornumber = "1"
  8.  
  9. --Do not change anything below
  10.  
  11. --originally made by electronx3
  12. --modified by jona23 to work in 1.16+
  13.  
  14. --constants
  15. local val_1div3 = 1.0/3.0
  16.  
  17.  
  18. --config
  19.  
  20. --emergency shutdown parameters
  21. local maxOvershoot = 200.0      --reactor will shutdown when temperature gets hotter than idealTemp+maxOvershoot
  22. local minFuel = 0.05
  23.  
  24. --default parameters
  25. local idealTemp = 8000.0
  26. local idealField = 0.09
  27.  
  28. local maxTempInc = 400.0        --max. temperature increase per computer tick
  29. local maxOutflow = 30000000.0
  30.  
  31. local chargeInflow = 20000000
  32. local shutDownField = 0.1       --field strength while shutdown
  33.  
  34. local safeMode = true           --when set to false, the automatic emergency shutdown function is disabled
  35.  
  36.  
  37. --peripherals
  38. local reactor
  39. local inputFlux
  40. local outputFlux
  41. local mon
  42.  
  43. --info
  44. local info
  45.  
  46. local currentEmergency = false
  47. local currentField
  48. local currentFuel
  49.  
  50. local stableTicks = 0
  51. local screenPage = 0
  52. local openConfirmDialog = false
  53.  
  54. local manualStart = false
  55. local manualCharge = false
  56. local manualStop = false
  57.  
  58.  
  59. --the program
  60.  
  61. function updateInfo()
  62.     info = reactor.getReactorInfo()
  63.    
  64.     if info == nil or info == null then
  65.       error("Reactor has an invalid setup!")
  66.     end
  67.    
  68.     currentField = info.fieldStrength / info.maxFieldStrength
  69.     currentFuel = 1.0 - (info.fuelConversion / info.maxFuelConversion)
  70. end
  71.  
  72. function isEmergency()
  73.     currentEmergency = safeMode and not (info.temperature < 2000.0) and (info.status == "running" or info.status == "online" or info.status == "stopping") and (info.temperature > idealTemp + maxOvershoot or currentField < 0.004 or currentFuel < minFuel)
  74.     return currentEmergency
  75. end
  76.  
  77. function calcInflow(targetStrength, fieldDrainRate)
  78.     return fieldDrainRate / (1.0 - targetStrength)
  79. end
  80.  
  81. --creators of the setupPeripherals function: https://github.com/acidjazz/drmon/blob/master/drmon.lua
  82. function setupPeripherals()
  83.     print("Setup peripherals...")
  84.     reactor = periphSearch("draconic_reactor")
  85.     inputFlux = periphSearch("flow_gate")
  86.     outputFlux = peripheral.wrap(sideoutputFlux)
  87.    
  88.     if reactor == null then
  89.         error("No valid reactor was found!")
  90.     end
  91.     if inputFlux == null then
  92.         error("No valid input fluxgate was found!")
  93.     end  
  94.     if outputFlux == null then
  95.         error("No valid output fluxgate was found!")
  96.     end
  97.    
  98.     inputFlux.setOverrideEnabled(true)
  99.     inputFlux.setFlowOverride(0)
  100.     outputFlux.setOverrideEnabled(true)
  101.     outputFlux.setFlowOverride(0)
  102.    
  103.     local tmpMon = periphSearch("monitor")
  104.     if tmpMon == null then
  105.         mon = null
  106.         print("WARN: No valid monitor was found!")
  107.  
  108.     else
  109.         monX, monY = tmpMon.getSize()
  110.         mon = {}
  111.         mon.monitor, mon.x, mon.y = tmpMon, monX, monY
  112.     end
  113.    
  114.     print("Done!")
  115. end
  116.  
  117. function periphSearch(type)
  118.     local names = peripheral.getNames()
  119.     local i, name
  120.     for i, name in pairs(names) do
  121.         if peripheral.getType(name) == type then
  122.             return peripheral.wrap(name)
  123.         end
  124.     end
  125.     return null
  126. end
  127.  
  128. function clickListener()
  129.     if mon == null then
  130.         return
  131.     end
  132.    
  133.     while true do
  134.         event, side, xPos, yPos = os.pullEvent("monitor_touch")
  135.        
  136.         local cFlow = 0 --remove local later
  137.        
  138.         if yPos == mon.y and xPos >= 1 and xPos <= 4 then
  139.             openConfirmDialog = false
  140.             screenPage = (screenPage + 1) % 2
  141.         elseif screenPage == 1 then        
  142.             if yPos == 8 then
  143.                 local tmpTemp = idealTemp
  144.            
  145.                 if xPos >= 2 and xPos <= 3 then
  146.                     tmpTemp = tmpTemp - 1.0
  147.                 elseif xPos >= 5 and xPos <= 6 then
  148.                     tmpTemp = tmpTemp - 10.0
  149.                 elseif xPos >= 9 and xPos <= 11 then
  150.                     tmpTemp = tmpTemp - 100.0
  151.                 elseif xPos >= 14 and xPos <= 16 then
  152.                     tmpTemp = 8000.0
  153.                 elseif xPos >= 19 and xPos <= 21 then
  154.                     tmpTemp = tmpTemp + 100.0
  155.                 elseif xPos >= 24 and xPos <= 25 then
  156.                     tmpTemp = tmpTemp + 10.0
  157.                 elseif xPos >= 27 and xPos <= 28 then
  158.                     tmpTemp = tmpTemp + 1.0
  159.                 end
  160.                
  161.                 if tmpTemp < 20.0 then
  162.                     tmpTemp = 20.0
  163.                 elseif tmpTemp > 20000.0 then
  164.                     tmpTemp = 20000.0
  165.                 end
  166.                
  167.                 idealTemp = tmpTemp
  168.                 --print("new default temperature: " .. math.floor(idealTemp) .. "°C")
  169.             elseif yPos == 12 then
  170.                 local tmpField = idealField
  171.                
  172.                 if xPos >= 2 and xPos <= 3 then
  173.                     tmpField = tmpField - 0.001
  174.                 elseif xPos >= 5 and xPos <= 6 then
  175.                     tmpField = tmpField - 0.01
  176.                 elseif xPos >= 9 and xPos <= 11 then
  177.                     tmpField = tmpField - 0.1
  178.                 elseif xPos >= 14 and xPos <= 16 then
  179.                     tmpField = 0.01
  180.                 elseif xPos >= 19 and xPos <= 21 then
  181.                     tmpField = tmpField + 0.1
  182.                 elseif xPos >= 24 and xPos <= 25 then
  183.                     tmpField = tmpField + 0.01
  184.                 elseif xPos >= 27 and xPos <= 28 then
  185.                     tmpField = tmpField + 0.001
  186.                 end
  187.                
  188.                 if tmpField < 0.005 then
  189.                     tmpField = 0.005
  190.                 elseif tmpField > 0.6 then
  191.                     tmpField = 0.6
  192.                 end
  193.                
  194.                 idealField = tmpField
  195.                 --print("new default field strength: " .. math.floor(idealField*1000.0)/10.0 .. "%")
  196.             elseif yPos == 15 then              
  197.                 if openConfirmDialog then
  198.                     if xPos >= 25 and xPos <= 28 then
  199.                         openConfirmDialog = false
  200.                     elseif xPos >= 16 and xPos <= 22 then
  201.                         openConfirmDialog = false
  202.                         safeMode = false
  203.                         --print("WARN: Safe mode deactivated!")
  204.                     end
  205.                 elseif xPos >= 26 and xPos <= 28 then
  206.                     if safeMode then
  207.                         openConfirmDialog = true
  208.                     else
  209.                         safeMode = true
  210.                         --print("Safe mode activated!")
  211.                     end
  212.                 end
  213.             elseif yPos == 17 and info ~= null then
  214.                 if not currentEmergency then
  215.                     if (info.status == "running" or info.status == "online") and xPos >= 2 and xPos <= 5 then
  216.                         manualStop = true
  217.                     elseif (info.status == "cold" or info.status == "offline" or info.status == "cooling") and xPos >= 2 and xPos <= 7 then
  218.                         manualCharge = true
  219.                     elseif (info.status == "stopping" or info.status == "warming_up" or info.status == "charged") and xPos >= 2 and xPos <= 6 then
  220.                         manualStart = true
  221.                     elseif info.status == "warming_up" and xPos >= 9 and xPos <= 12 then
  222.                         manualStop = true
  223.                     end
  224.                 end
  225.                 if info.temperature < 2000.0 and xPos >= 26 and xPos <= 28 then
  226.                     print("Program stopped!")
  227.                     return
  228.                 end
  229.             end
  230.         end
  231.         saveConfig()
  232.     end
  233. end
  234.  
  235. --graphic stuff: inspired by https://github.com/acidjazz/drmon/blob/master/drmon.lua
  236. function gClear()
  237.   mon.monitor.setBackgroundColor(colors.black)
  238.   mon.monitor.clear()
  239.   mon.monitor.setCursorPos(1,1)
  240. end
  241. function gWrite(text, x, y, cl, clBg)
  242.     mon.monitor.setCursorPos(x, y)
  243.     mon.monitor.setTextColor(cl)
  244.     mon.monitor.setBackgroundColor(clBg)
  245.     mon.monitor.write(text)
  246. end
  247. function gWriteR(text, x, y, cl, clBg)
  248.     gWrite(text, mon.x - string.len(tostring(text)) - x, y, cl, clBg)
  249. end
  250. function gWriteLR(textL, textR, xL, xR, y, clL, clR, clBg)
  251.     gWrite(textL, xL, y, clL, clBg)
  252.     gWriteR(textR, xR, y, clR, clBg)
  253. end
  254. function gDrawLine(x, y, length, cl)
  255.     if length < 0 then
  256.         return
  257.     end
  258.     mon.monitor.setCursorPos(x, y)
  259.     mon.monitor.setBackgroundColor(cl)
  260.     mon.monitor.write(string.rep(" ", length))
  261. end
  262. function gDrawProgressBar(x, y, length, proportion, cl, clBg)
  263.     if proportion < 0.0 or proportion > 1.0 then
  264.         gDrawLine(x, y, length, cl)
  265.     else
  266.         gDrawLine(x, y, length, clBg)
  267.         gDrawLine(x, y, math.floor(proportion*length), cl)
  268.     end
  269. end
  270. function gDrawStandardProgressBar(y, proportion, cl)
  271.     gDrawProgressBar(2, y, mon.x-2, proportion, cl, colors.gray)
  272. end
  273.  
  274.  
  275. function update()
  276.     local newInflow = 0.0
  277.     local newOutflow = 0.0  
  278.    
  279.     while true do  
  280.             local targetShieldPercent = idealField or 15 -- Desired shield strength
  281.     local targetShield = (targetShieldPercent / 100)
  282.  -- Reactor equation variables
  283.     local targetTemp50  = math.min((idealTemp / 10000) * 50, 99)
  284.     local coreSat       = info.energySaturation / info.maxEnergySaturation
  285.     local convLVL       = (info.fuelConversion / info.maxFuelConversion * 1.3) - 0.3
  286.  -- Calculate the temperature rise resistance for the reactor at the desired temperature.
  287.     local targetTempResist = ((targetTemp50^4) / (100 - targetTemp50))
  288.  -- Calculate the temperature rise exponential needed to reach the desired temperature
  289.     local targetTempExpo = -(targetTempResist*convLVL) - 1000*convLVL + targetTempResist
  290.  -- Calculate the saturation level needed to produce the required tempRiseExpo
  291.     local term1 = 1334.1-(3*targetTempExpo)
  292.     local term2 = (1200690-(2700*targetTempExpo))^2
  293.     local term3 = ((-1350*targetTempExpo)+(((-4*term1^3+term2)^(1/2))/2)+600345)^(1/3)
  294.     local targetNegCSat = -(term1/(3*term3))-(term3/3)
  295.  -- Saturation received from above equation needs to be reformatted to a more useful form
  296.     local targetCoreSat = 1 - (targetNegCSat/99)
  297.     local targetSat = targetCoreSat * info.maxEnergySaturation
  298.  -- Calculate the difference between where saturation is and where it needs to be
  299.     local saturationError = info.energySaturation - targetSat
  300.  -- Calculate field drain
  301.     local tempDrainFactor = 0
  302.     if info.temperature > 8000 then
  303.         tempDrainFactor = 1 + ((info.temperature-8000)^2 * 0.0000025)
  304.     elseif info.temperature > 2000 then
  305.         tempDrainFactor = 1
  306.     elseif info.temperature > 1000 then
  307.         tempDrainFactor = (info.temperature-1000)/1000
  308.     end
  309.     local baseMaxRFt = (info.maxEnergySaturation / 1000) * reactorOutputMultiplier * 1.5
  310.     local fieldDrain = math.min(tempDrainFactor * math.max(0.01, (1-coreSat)) * (baseMaxRFt / 10.923556), 2147000000)
  311.     local fieldNegPercent = 1 - targetShield
  312.  --local fieldInputRate = fieldDrain / fieldNegPercent
  313.     local fieldStrengthError = (info.maxFieldStrength * targetShield) - info.fieldStrength
  314.     local requiredInput = math.min((info.maxFieldStrength * info.fieldDrainRate) / (info.maxFieldStrength - info.fieldStrength), info.maxFieldStrength - info.fieldStrength)
  315.  --Automations
  316.    if info.status == "running" then
  317.     local outputNeeded = math.min(saturationError, (info.maxEnergySaturation/40))-- + info.generationRate
  318.         outputFlux.setFlowOverride(outputNeeded)
  319.         inputFlux.setFlowOverride(math.min(fieldStrengthError + requiredInput, info.maxFieldStrength) - info.fieldDrainRate + 1)
  320.     elseif info.status == "warming_up" then
  321.         outputFlux.setFlowOverride(0)
  322.         inputFlux.setFlowOverride(500000000)
  323.     elseif info.status == "stopping" then
  324.         outputFlux.setFlowOverride(0)
  325.         inputFlux.setFlowOverride(requiredInput)
  326.     if info.temperature > cutoffTemp then
  327.         print("Reactor Too Hot, shutting down")
  328.         reactor.stopReactor()
  329.     end
  330.     if ((info.fieldStrength / info.maxFieldStrength) * 100) < cutoffField then
  331.         print("Reactor Field Has Failed, Failsafe Activated, Shutting Down")
  332.         reactor.stopReactor()
  333.     end
  334.     if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 0.2 then
  335.         print("Reactor Fuel Low, Shutting Down")
  336.         reactor.stopReactor()
  337.     end
  338.    end
  339.     -- Get Temp Rise
  340.         oldTemp = currentTemp or info.temperature
  341.         currentTemp = info.temperature
  342.         oldTempRate = tempChangeRate or currentTemp - oldTemp
  343.         tempChangeRate = currentTemp - oldTemp
  344.         tempAccel = tempChangeRate - oldTempRate
  345.     if tempAccel == 0 then
  346.         tempAccel = 0.001
  347.     end
  348.        
  349.        
  350.         if mon ~= null then
  351.             gClear()
  352.            
  353.             if screenPage == 0 then
  354.                 local clTemp
  355.                 if info.temperature < idealTemp*0.95 then
  356.                     clTemp = colors.green
  357.                 elseif info.temperature < idealTemp + 1.0 then
  358.                     clTemp = colors.yellow
  359.                 elseif info.temperature < idealTemp + maxOvershoot then
  360.                     clTemp = colors.orange
  361.                 else
  362.                     clTemp = colors.red
  363.                 end
  364.                
  365.                 gWriteLR("temperature:", math.floor(info.temperature*10.0)/10.0 .. "°C", 2, 0, 7, colors.white, clTemp, colors.black)
  366.                 gWriteLR("set: " .. math.floor(idealTemp) .. "°C", "max: " .. math.floor(idealTemp + maxOvershoot) .. "°C", 2, 0, 8, colors.white, colors.white, colors.black)
  367.                 gDrawStandardProgressBar(9, info.temperature/16000.0, clTemp)              
  368.                
  369.                 local clField
  370.                 if currentField > idealField*1.05 then
  371.                     clField = colors.green
  372.                 elseif currentField > idealField*0.95 then
  373.                     clField = colors.yellow
  374.                 else
  375.                     clField = colors.red
  376.                 end
  377.                
  378.                 gWriteLR("field strength:", math.floor(currentField*10000.0)/100.0 .. "%", 2, 0, 11, colors.white, clField, colors.black)
  379.                 gWriteLR("set: " .. math.floor(idealField*1000)/10.0 .. "%", "min: 0.4%", 2, 0, 12, colors.white, colors.white, colors.black)
  380.                 gDrawStandardProgressBar(13, currentField, clField)
  381.                
  382.                 gWriteLR("status", info.status:upper(), 2, 0, 15, colors.white, colors.white, colors.black)
  383.                
  384.                 local clFuel
  385.                 if currentFuel > 0.15 then
  386.                     clFuel = colors.green
  387.                 elseif currentFuel > 0.05 then
  388.                     clFuel = colors.yellow
  389.                 elseif currentFuel > 0.01 then
  390.                     clFuel = colors.orange
  391.                 else
  392.                     clFuel = colors.red
  393.                 end
  394.                 gWriteLR("fuel:", math.floor(currentFuel*10000.0)/100.0 .. "%", 2, 0, 16, colors.white, clFuel, colors.black)
  395.             elseif screenPage == 1 then
  396.                 local clTemp
  397.                 if info.temperature < idealTemp*0.95 then
  398.                     clTemp = colors.green
  399.                 elseif info.temperature < idealTemp + 1.0 then
  400.                     clTemp = colors.yellow
  401.                 elseif info.temperature < idealTemp + maxOvershoot then
  402.                     clTemp = colors.orange
  403.                 else
  404.                     clTemp = colors.red
  405.                 end
  406.                
  407.                 gWriteLR("temp: " .. math.floor(idealTemp) .. " (" .. math.floor(idealTemp + maxOvershoot) .. ")", math.floor(info.temperature*10.0)/10.0 .. "°C", 2, 0, 7, colors.white, clTemp, colors.black)
  408.                 gDrawStandardProgressBar(9, info.temperature/16000.0, clTemp)
  409.                
  410.                 gWrite("<", 2, 8, colors.white, colors.blue)
  411.                 gWrite("<<", 5, 8, colors.white, colors.blue)
  412.                 gWrite("<<<", 9, 8, colors.white, colors.blue)
  413.                 gWrite("res", 14, 8, colors.white, colors.blue)
  414.                 gWrite(">>>", 19, 8, colors.white, colors.blue)
  415.                 gWrite(">>", 24, 8, colors.white, colors.blue)
  416.                 gWrite(">", 28, 8, colors.white, colors.blue)              
  417.                
  418.                 local clField
  419.                 if currentField > idealField*1.05 then
  420.                     clField = colors.green
  421.                 elseif currentField > idealField*0.95 then
  422.                     clField = colors.yellow
  423.                 else
  424.                     clField = colors.red
  425.                 end
  426.                
  427.                 gWriteLR("field: " .. math.floor(idealField*1000)/10.0 .. "% (0.4%)", math.floor(currentField*10000.0)/100.0 .. "%", 2, 0, 11, colors.white, clField, colors.black)
  428.                 gDrawStandardProgressBar(13, currentField, clField)
  429.                
  430.                 gWrite("<", 2, 12, colors.white, colors.blue)
  431.                 gWrite("<<", 5, 12, colors.white, colors.blue)
  432.                 gWrite("<<<", 9, 12, colors.white, colors.blue)
  433.                 gWrite("res", 14, 12, colors.white, colors.blue)
  434.                 gWrite(">>>", 19, 12, colors.white, colors.blue)
  435.                 gWrite(">>", 24, 12, colors.white, colors.blue)
  436.                 gWrite(">", 28, 12, colors.white, colors.blue)
  437.                
  438.                 if safeMode then
  439.                     if openConfirmDialog then
  440.                         gWrite("DISABLE?", 2, 15, colors.white, colors.black)
  441.                         gWrite("CONFIRM", 16, 15, colors.white, colors.green)
  442.                         gWrite("EXIT", 25, 15, colors.white, colors.red)
  443.                     else
  444.                         gWrite("safe mode:", 2, 15, colors.white, colors.black)
  445.                         gWrite("ON", 27, 15, colors.green, colors.black)
  446.                     end
  447.                 else
  448.                     gWrite("safe mode:", 2, 15, colors.white, colors.black)
  449.                     gWrite("OFF", 26, 15, colors.red, colors.black)
  450.                 end
  451.                
  452.                 if not currentEmergency then
  453.                     if info.status == "running" or info.status == "online" then
  454.                         gWrite("STOP", 2, 17, colors.white, colors.red)
  455.                     elseif info.status == "cold" or info.status == "offline" or info.status == "cooling" then
  456.                         gWrite("CHARGE", 2, 17, colors.white, colors.blue)
  457.                     elseif info.status == "stopping" or info.status == "charged" then
  458.                         gWrite("START", 2, 17, colors.white, colors.green)
  459.                     elseif info.status == "warming_up" then
  460.                         gWrite("START", 2, 17, colors.white, colors.green)
  461.                         gWrite("STOP", 9, 17, colors.white, colors.red)
  462.                     end
  463.                 end
  464.                
  465.                 if info.temperature < 2000.0 then
  466.                     gWrite("END", 26, 17, colors.white, colors.red)
  467.                 end
  468.             end
  469.            
  470.             gWriteLR("Draconic Reactor Number", reactornumber, 2, 0, 1, colors.white, colors.white, colors.black)        
  471.            
  472.             gWriteLR("inflow:", newInflow .. " RF/t", 2, 0, 3, colors.white, colors.white, colors.black)
  473.             gWriteLR("outflow:", outflowMultiplied .. " RF/t", 2, 0, 4, colors.white, colors.white, colors.black)      
  474.             local gain = outflowMultiplied - newInflow
  475.             if gain > 0.0 then
  476.                 gWriteLR("-> gain:", gain .. " RF/t", 2, 0, 5, colors.white, colors.green, colors.black)
  477.             elseif gain < 0.0 then
  478.                 gWriteLR("-> gain:", gain .. " RF/t", 2, 0, 5, colors.white, colors.red, colors.black)
  479.             elseif gain == 0.0 then
  480.                 gWriteLR("-> gain:", "0 RF/t", 2, 0, 5, colors.white, colors.white, colors.black)
  481.             end
  482.            
  483.             gDrawLine(1, mon.y, 4, colors.gray)
  484.         end
  485.        
  486.         sleep(0.02)
  487.     end
  488. end
  489.  
  490. function setup()
  491.     term.clear()
  492.     print("Starting program...")    
  493.    
  494.     if fs.exists("config.txt") then
  495.         print("Loading config...")
  496.         loadConfig()
  497.         print("Done!")
  498.     else
  499.         print("Creating config...")
  500.         saveConfig()
  501.         print("Done!")
  502.     end
  503.  
  504.     if chargeInflow < 0 then
  505.         chargeInflow = 0
  506.     end
  507.    
  508.     stableTicks = 0
  509.    
  510.     setupPeripherals()
  511.     print("Started!")
  512. end
  513.  
  514. function saveConfig()
  515.     local config = fs.open("config.txt", "w")
  516.     config.writeLine(reactorOutputMultiplier*1000000.0)
  517.     config.writeLine(maxOvershoot)
  518.     config.writeLine(minFuel*100.0)
  519.     config.writeLine(idealTemp)
  520.     config.writeLine(idealField*1000.0)
  521.     config.writeLine(maxTempInc)
  522.     config.writeLine(maxOutflow)
  523.     config.writeLine(chargeInflow)
  524.     config.writeLine(shutDownField*1000.0)
  525.     config.close()
  526. end
  527. function loadConfig()
  528.     local config = fs.open("config.txt", "r")
  529.     reactorOutputMultiplier = tonumber(config.readLine())/1000000.0
  530.     maxOvershoot = tonumber(config.readLine())
  531.     minFuel = tonumber(config.readLine())/100.0
  532.     idealTemp = tonumber(config.readLine())
  533.     idealField = tonumber(config.readLine())/1000.0
  534.     maxTempInc = tonumber(config.readLine())
  535.     maxOutflow = tonumber(config.readLine())
  536.     chargeInflow = tonumber(config.readLine())
  537.     shutDownField = tonumber(config.readLine())/1000.0
  538.     config.close()
  539. end
  540.  
  541. function main()
  542.     setup()
  543.     if mon == null then
  544.         update()
  545.     else
  546.         parallel.waitForAny(update, clickListener)
  547.         gClear()
  548.         gWrite("Program stopped!", 1, 1, colors.white, colors.black)
  549.     end
  550. end
  551.  
  552. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement