neuroticfox

Microwave

Jul 24th, 2021 (edited)
806
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local component = require("component")
  2. local event = require("event")
  3. local term = require("term")
  4. local gpu = component.gpu
  5. local screen = component.screen
  6.  
  7.  -- DynamicRes
  8.  
  9. local ratioX, ratioY = screen.getAspectRatio()
  10. local maxX, maxY = gpu.maxResolution()
  11. gpu.setResolution(math.min(ratioX*55, maxX), math.min(ratioY*25,maxY))
  12.  
  13.  -- Safety Checks
  14.  
  15. if not component.isAvailable("draconic_reactor") then
  16.   print("Reactor not connected. Please connect computer to reactor with an Adapter block.")
  17.   os.exit()
  18. end
  19. reactor = component.draconic_reactor
  20. local flux_gates = {}
  21. for x,y in pairs(component.list("flux_gate")) do
  22.   flux_gates[#flux_gates+1] = x
  23. end
  24. if #flux_gates < 2 then
  25.   print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
  26.   os.exit()
  27. end
  28. flux_in = component.proxy(flux_gates[1])
  29. flux_out = component.proxy(flux_gates[2])
  30. if not flux_in or not flux_out then
  31.   print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
  32.   os.exit()
  33. end
  34.  
  35.  -- Functions
  36.  
  37. function exit_msg(msg)
  38.   term.clear()
  39.   print(msg)
  40.   os.exit()
  41. end
  42.  
  43. function modify_temp(offset)
  44.   local new_temp = ideal_temp + offset
  45.   if new_temp > 10000 then
  46.     new_temp = 10000
  47.   elseif new_temp < 2000 then
  48.     new_temp = 2000
  49.   end
  50.   ideal_temp = new_temp
  51. end
  52.  
  53. local bypassfield = 0
  54. local chaosmode = 0
  55.  
  56. function modify_field(offset)
  57.   local new_strength = ideal_strength + offset
  58.   if new_strength > 100 then
  59.     new_strength = 100
  60.   elseif new_strength < 75 and chaosmode == 1 then
  61.     new_strength = 75
  62.   elseif new_strength < 1 and bypassfield == 0 then
  63.     new_strength = 1
  64.   elseif new_strength < 0.1 and bypassfield == 1 then
  65.     new_strength = 0.1
  66.   end
  67.   ideal_strength = new_strength
  68. end
  69.  
  70.  -- Buttons
  71.  
  72. local adj_button_width = 19
  73. local temp_adjust_x_offset = 68
  74. local temp_adjust_y_offset = 2
  75. local field_adjust_x_offset = temp_adjust_x_offset + adj_button_width + 2
  76. local field_adjust_y_offset = 2
  77. local status = "PeFi"
  78. local lowest_field = 100
  79. local lowest_fuel = 100
  80. local highest_temp = 0
  81. local highest_sat = 0
  82. local highest_outflow = 0
  83. local cutoff_field = 0.75
  84.  
  85.       -- Inflow PID
  86. local proportional_field_error = 0
  87. local inflow_I_sum = 0
  88. local integral_field_error = 0
  89. local derivative_field_error = 0
  90. local inflow_D_last = 0
  91. local inflow_correction = 0
  92.  
  93.     -- Outflow PID
  94. local proportional_temp_error = 0
  95. local outflow_I_sum = 0
  96. local integral_temp_error = 0
  97. local derivative_temp_error = 0
  98. local outflow_D_last = 0
  99. local outflow_correction = 0
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108. local buttons = {
  109.   start={
  110.     x=2,
  111.     y=30,
  112.     width=18,
  113.     height=1,
  114.     text="Start",
  115.     action=function()
  116.       if safe then
  117.         state = "Charging"
  118.         reactor.chargeReactor()
  119.       elseif shutting_down then
  120.         state = "Active"
  121.         reactor.activateReactor()
  122.       end
  123.     end,
  124.     condition=function() return safe or shutting_down end
  125.   },
  126.   shutdown={
  127.     x=2,
  128.     y=30,
  129.     width=18,
  130.     height=1,
  131.     text="Shutdown",
  132.     action=function()
  133.     cutoff_temp = 10500
  134.     ideal_temp = 8000
  135.     ideal_strength = 55
  136.     cutoff_field = 0.45
  137.       state = "Manual Shutdown"
  138.       reactor.stopReactor()
  139.     end,
  140.     condition=function() return running end
  141.   },
  142.       chaosmode={
  143.     x=2,
  144.     y=32,
  145.     width=18,
  146.     height=1,
  147.     text=" Chaos Mode",
  148.     action=function()
  149.       cutoff_temp = 19750
  150.       cutoff_field = 12.5
  151.       ideal_strength = 75
  152.       ideal_temp = 50000
  153.       lowest_field = 100
  154.     end,
  155.     condition=function() return running end
  156.   },
  157.     analytics={
  158.     x=42,
  159.     y=30,
  160.     width=18,
  161.     height=1,
  162.     text="Reset Analytics",
  163.     action=function()
  164.       highest_temp = 0
  165.       lowest_field = 200
  166.       highest_outflow = 0
  167.       status = "PeFi"
  168.     end,
  169.   },
  170.     Explode={
  171.     x=22,
  172.     y=32,
  173.     width=18,
  174.     height=1,
  175.     text="Initiate Meltdown",
  176.     action=function()
  177.       ideal_strength = 0
  178.       ideal_temp = 30000
  179.     end,
  180.     condition=function() return running end
  181.   },
  182.     force_exit={
  183.     x=22,
  184.     y=30,
  185.     width=18,
  186.     height=1,
  187.     text="Force Exit",
  188.     action=function()
  189.       cutoff_temp = 10500
  190.       ideal_temp = 2000
  191.       ideal_strength = 55
  192.       cutoff_field = 0.45
  193.       state = "Manual Shutdown"
  194.       reactor.stopReactor()
  195.       gpu.setResolution(gpu.maxResolution())
  196.       event_loop = false
  197.     end,
  198.     condition=function() return running or shutting_down end
  199.   },
  200.     switch_gates={
  201.     x=2,
  202.     y=32,
  203.     width=18,
  204.     height=1,
  205.     text="Swap flux gates",
  206.     action=function()
  207.       cutoff_temp = 10500
  208.       local old_addr = flux_in.address
  209.       flux_in = component.proxy(flux_out.address)
  210.       flux_out = component.proxy(old_addr)
  211.     end,
  212.     condition=function() return safe or shutting_down end
  213.   },
  214.     exit={
  215.     x=22,
  216.     y=30,
  217.     width=18,
  218.     height=1,
  219.     text="Exit",
  220.     action=function()
  221.       event_loop = false
  222.     end,
  223.     condition=function() return safe end
  224.   },
  225.   temp_up_max={
  226.     x=temp_adjust_x_offset,
  227.     y=temp_adjust_y_offset,
  228.     width=adj_button_width,
  229.     height=1,
  230.     text="Maximum",
  231.     action=function()
  232.       ideal_temp = 10000
  233.     end
  234.   },
  235.   temp_up_thousand={
  236.     x=temp_adjust_x_offset,
  237.     y=temp_adjust_y_offset+2,
  238.     width=adj_button_width,
  239.     height=1,
  240.     text="+1000",
  241.     action=function() modify_temp(1000) end
  242.   },
  243.   temp_up_hundred={
  244.     x=temp_adjust_x_offset,
  245.     y=temp_adjust_y_offset+4,
  246.     width=adj_button_width,
  247.     height=1,
  248.     text="+100",
  249.     action=function() modify_temp(100) end
  250.   },
  251.   temp_up_ten={
  252.     x=temp_adjust_x_offset,
  253.     y=temp_adjust_y_offset+6,
  254.     width=adj_button_width,
  255.     height=1,
  256.     text="+10",
  257.     action=function() modify_temp(10) end
  258.   },
  259.   temp_up_one={
  260.     x=temp_adjust_x_offset,
  261.     y=temp_adjust_y_offset+8,
  262.     width=adj_button_width,
  263.     height=1,
  264.     text="+1",
  265.     action=function() modify_temp(1) end
  266.   },
  267.   temp_down_thousand={
  268.     x=temp_adjust_x_offset,
  269.     y=temp_adjust_y_offset+18,
  270.     width=adj_button_width,
  271.     height=1,
  272.     text="-1000",
  273.     action=function() modify_temp(-1000) end
  274.   },
  275.     temp_down_max={
  276.     x=temp_adjust_x_offset,
  277.     y=temp_adjust_y_offset+20,
  278.     width=adj_button_width,
  279.     height=1,
  280.     text="Minimum",
  281.     action=function() modify_temp(-20000) end
  282.   },
  283.   temp_down_hundred={
  284.     x=temp_adjust_x_offset,
  285.     y=temp_adjust_y_offset+16,
  286.     width=adj_button_width,
  287.     height=1,
  288.     text="-100",
  289.     action=function() modify_temp(-100) end
  290.   },
  291.   temp_down_ten={
  292.     x=temp_adjust_x_offset,
  293.     y=temp_adjust_y_offset+14,
  294.     width=adj_button_width,
  295.     height=1,
  296.     text="-10",
  297.     action=function() modify_temp(-10) end
  298.   },
  299.   temp_down_one={
  300.     x=temp_adjust_x_offset,
  301.     y=temp_adjust_y_offset+12,
  302.     width=adj_button_width,
  303.     height=1,
  304.     text="-1",
  305.     action=function() modify_temp(-1) end
  306.   },
  307.   field_up_ten={
  308.     x=field_adjust_x_offset,
  309.     y=field_adjust_y_offset+3,
  310.     width=adj_button_width,
  311.     height=1,
  312.     text="+10",
  313.     action=function() modify_field(10) end
  314.   },
  315.     field_up_one={
  316.     x=field_adjust_x_offset,
  317.     y=field_adjust_y_offset+5,
  318.     width=adj_button_width,
  319.     height=1,
  320.     text="+1",
  321.     action=function() modify_field(1) end
  322.   },
  323.   field_up_tenth={
  324.     x=field_adjust_x_offset,
  325.     y=field_adjust_y_offset+7,
  326.     width=adj_button_width,
  327.     height=1,
  328.     text="+0.1",
  329.     action=function() modify_field(0.1) end
  330.   },
  331.   field_down_ten={
  332.     x=field_adjust_x_offset,
  333.     y=field_adjust_y_offset+17,
  334.     width=adj_button_width,
  335.     height=1,
  336.     text="-10",
  337.     action=function() modify_field(-10) end
  338.   },
  339.     field_down_one={
  340.     x=field_adjust_x_offset,
  341.     y=field_adjust_y_offset+15,
  342.     width=adj_button_width,
  343.     height=1,
  344.     text="-1",
  345.     action=function() modify_field(-1) end
  346.   },
  347.   field_down_tenth={
  348.     x=field_adjust_x_offset,
  349.     y=field_adjust_y_offset+13,
  350.     width=adj_button_width,
  351.     height=1,
  352.     text="-0.1",
  353.     action=function() modify_field(-0.1) end
  354.   },
  355.     BypassField={
  356.     x=field_adjust_x_offset,
  357.     y=field_adjust_y_offset+19,
  358.     width=adj_button_width,
  359.     height=1,
  360.     text="Bypass Lock",
  361.     action=function()
  362.       bypassfield = 1
  363.       cutoff_field = 0.001
  364.     end
  365.   }
  366. }
  367.  
  368.  -- main code
  369.  
  370. flux_in.setFlowOverride(0)
  371. flux_out.setFlowOverride(0)
  372. flux_in.setOverrideEnabled(true)
  373. flux_out.setOverrideEnabled(true)
  374.  
  375. local condition = reactor.getReactorInfo()
  376. if not condition then
  377.   print("Reactor not initialized, please ensure the stabilizers are properly laid out.")
  378.   os.exit()
  379. end
  380.  
  381. ideal_strength = 15
  382.  
  383. ideal_temp = 8000
  384. cutoff_temp = 10001
  385.  
  386.  -- tweakable pid gains
  387.  
  388. inflow_P_gain = 1
  389. inflow_I_gain = 0.04
  390. inflow_D_gain = 0.05
  391.  
  392. outflow_P_gain = 500
  393. outflow_I_gain = 0.10
  394. outflow_II_gain = 0.0000003
  395. outflow_D_gain = 30000
  396.  
  397.  -- initialize main loop
  398.  
  399. inflow_I_sum = 0
  400. inflow_D_last = 0
  401.  
  402. outflow_I_sum = 0
  403. outflow_II_sum = 0
  404. outflow_D_last = 0
  405.  
  406. state = "Standby"
  407. shutting_down = false
  408.  
  409. if condition.temperature > 25 then
  410.   state = "Cooling"
  411. end
  412. if condition.temperature > 2000 then
  413.   state = "Active"
  414. end
  415.  
  416.  -- Possible states:
  417.   --Standby
  418.   --Charging
  419.   --Active
  420.   --Manual Shutdown
  421.   --Emergency Shutdown
  422.   --Cooling
  423.  
  424. event_loop = true
  425. while event_loop do
  426.  
  427.   if not component.isAvailable("draconic_reactor") then
  428.     exit_msg("Reactor disconnected, exiting")
  429.   end
  430.  
  431.   if not component.isAvailable("flux_gate") then
  432.     exit_msg("Flux gates disconnected, exiting")
  433.   end
  434.  
  435.     local info = reactor.getReactorInfo()
  436.  
  437.  -- Highest Heat Value
  438.  
  439. if info.temperature > highest_temp then
  440.   highest_temp = info.temperature
  441. end
  442.  
  443.  -- Highest Sat Value
  444.  
  445. if ((info.energySaturation / info.maxEnergySaturation) * 100) > highest_sat then
  446.   highest_sat = ((info.energySaturation / info.maxEnergySaturation) * 100)
  447. end
  448.  
  449.  -- Lowest Field Value ((1 - info.fuelConversion / info.maxFuelConversion) * 100)
  450.  
  451. if ((info.fieldStrength / info.maxFieldStrength) * 100) < lowest_field then
  452.   lowest_field = ((info.fieldStrength / info.maxFieldStrength) * 100)
  453. end
  454.  
  455.  -- Lowest Field Value
  456.  
  457. if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < lowest_fuel then
  458.   lowest_fuel = ((1 - info.fuelConversion / info.maxFuelConversion) * 100)
  459. end
  460.  
  461.   local inflow = 0
  462.   local outflow = 0
  463.  
  464.   shutting_down = state == "Manual Shutdown" or state == "Emergency Shutdown"
  465.   running = state == "Charging" or state == "Active"
  466.   safe = state == "Standby" or state == "Cooling"
  467.  
  468.   if state == "Charging" then
  469.     inflow = 5000000
  470.  
  471.     if info.temperature > 2000 then
  472.       reactor.activateReactor()
  473.       state = "Active"
  474.     end
  475.   elseif state == "Cooling" then
  476.     if info.temperature < 25 then
  477.       state = "Standby"
  478.     end
  479.     inflow = 10
  480.     outflow = 20
  481.   elseif state == "Standby" then
  482.     inflow = 10
  483.     outflow = 20
  484.   else
  485.     -- adjust inflow rate based on field strength
  486.    
  487.     field_error = (info.maxFieldStrength * (ideal_strength / 100)) - info.fieldStrength
  488.     proportional_field_error = field_error * inflow_P_gain
  489.     inflow_I_sum = inflow_I_sum + field_error
  490.     integral_field_error = inflow_I_sum * inflow_I_gain
  491.     derivative_field_error = (field_error - inflow_D_last) * inflow_D_gain
  492.     inflow_D_last = field_error
  493.     inflow_correction = proportional_field_error + integral_field_error + derivative_field_error
  494.     if inflow_correction < 0 then
  495.       inflow_I_sum = inflow_I_sum - field_error
  496.     end
  497.     inflow = inflow_correction
  498.  
  499.     if not shutting_down then
  500.  
  501.       -- adjust outflow rate based on core temperature
  502.  
  503.       temp_error = ideal_temp - info.temperature
  504.       proportional_temp_error = temp_error * outflow_P_gain
  505.       outflow_I_sum = outflow_I_sum + temp_error
  506.       integral_temp_error = outflow_I_sum * outflow_I_gain
  507.       if math.abs(temp_error) < 100 then
  508.         outflow_II_sum = outflow_II_sum + integral_temp_error
  509.       else
  510.         outflow_II_sum = 0
  511.       end
  512.       second_integral_temp_error = outflow_II_sum * outflow_II_gain
  513.       derivative_temp_error = (temp_error - outflow_D_last) * outflow_D_gain
  514.       outflow_D_last = temp_error
  515.       outflow_correction = proportional_temp_error + integral_temp_error + second_integral_temp_error + derivative_temp_error
  516.       if outflow_correction < 0 then
  517.         outflow_I_sum = outflow_I_sum - temp_error
  518.       end
  519.       outflow = outflow_correction
  520.  
  521.       -- cut off reactor in case of emergency
  522.  
  523.       if info.temperature > cutoff_temp then
  524.         print("Reactor Too Hot, shutting down")
  525.         state = "Emergency Shutdown"
  526.         status = "HiTe"
  527.         reactor.stopReactor()
  528.       end
  529.       if ((info.fieldStrength / info.maxFieldStrength) * 100) < cutoff_field then
  530.         print("Reactor Field Has Failed, Failsafe Activated, Shutting Down")
  531.         state = "Emergency Shutdown"
  532.         status = "LoFi"
  533.         reactor.stopReactor()
  534.       end
  535.       if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 1.25 then
  536.         print("Reactor Fuel Low, Shutting Down")
  537.       state = "Emergency Shutdown"
  538.       status = "LoFu"
  539.       reactor.stopReactor()
  540.       end
  541.     else
  542.       if info.temperature < 2000 then
  543.         state = "Cooling"
  544.       end
  545.     end
  546.   end
  547.  
  548.   if state ~= "Active" and not shutting_down then
  549.     inflow_I_sum = 0
  550.     inflow_D_last = 0
  551.     outflow_I_sum = 0
  552.     outflow_II_sum = 0
  553.     outflow_D_last = 0
  554.   end
  555.  
  556.   if inflow < 0 then
  557.     inflow = 0
  558.   end
  559.   if outflow < 0 then
  560.     outflow = 0
  561.   end
  562.  
  563.   inflow = math.floor(inflow)
  564.   outflow = math.floor(outflow)
  565.  
  566.   flux_in.setFlowOverride(inflow)
  567.   flux_out.setFlowOverride(outflow)
  568.  
  569.   -- Draw screen
  570.  
  571.   if term.isAvailable() then
  572.  
  573.     -- Draw Values
  574.  
  575. function modify_eff(offset)
  576.   local eff = ((outflow / inflow) * 100)
  577.   if eff > 100000 then
  578.     eff = 1
  579.   end
  580. end
  581.  
  582.     local secondsToExpire = (info.maxFuelConversion - info.fuelConversion) / math.max(info.fuelConversionRate*0.00002, 0.00001)
  583.  
  584.     local left_margin = 2
  585.     local spacing = 1
  586.     local values = {
  587. string.format("      Estimated time to refuel: %2dd, %2dh, %2dm, %2ds", secondsToExpire/86400, secondsToExpire/3600 % 24, secondsToExpire/60 % 60, secondsToExpire % 60),
  588.       " ",
  589.               "                  Reactor Statistics",
  590.               "----------------------------------------------------------",
  591. string.format("Ideal Field:                |           %5.1f%%           |", ideal_strength),
  592. string.format("Current Field:              |  %7.1f%% (%10.1fRF)   |", ((info.fieldStrength / info.maxFieldStrength) * 100), ((info.fieldStrength / info.maxFieldStrength) * 100000000)),
  593.               "----------------------------|----------------------------|",
  594. string.format("Fuel Remaining:             |           %5.1f%%           |", ((1 - info.fuelConversion / info.maxFuelConversion) * 100)),
  595. string.format("Fuel Use Rate:              |%10.1f nb/t (%4.2f Nu/s) |", info.fuelConversionRate, ((info.fuelConversionRate / 50000) / 16)),
  596.               "----------------------------|----------------------------|",
  597. string.format("Temperature                 |   %7.1f°c (%7.1f°f)    |", info.temperature, ((info.temperature * 1.8) + 32)),
  598. string.format("Ideal Temperature:          |   %7.1f°c (%7.1f°f)    |", ideal_temp, ((ideal_temp * 1.8) + 32)),
  599.               "----------------------------|----------------------------|",
  600. string.format("Energy Input:               |   %12.1f RF/t        |", inflow),
  601. string.format("Energy Output:              |   %12.1f RF/t        |", outflow),
  602. string.format("Energy Efficiency:          |   %12.1f%%            |", ((outflow / inflow) * 100)),
  603. string.format("Energy Profit:              |  %13.1f RF/t        |", (outflow - inflow)),
  604.               "----------------------------------------------------------",
  605.               "                                                         ",
  606.               "                    Debug Information                    ",
  607.               "                                                         ",
  608. string.format("Max Field Drop:             |        %5.2f%%              ", lowest_field),
  609. string.format("Lowest Recorded Fuel:       |        %5.2f%%              ", lowest_fuel),
  610. string.format("Max Temp Spike:             |     %8.2f              ", highest_temp),
  611. string.format("Max Saturation:             |       %6.2f%%              ", highest_sat),
  612.               "Status:                     |  " .. state .. "-" .. status .. "               ",
  613.               "----------------------------------------------------------",
  614.               " ",
  615.               " ",
  616.               " ",
  617.               " ",
  618.               " ",
  619.               " ",
  620.               " ",
  621.               " ",
  622.               " ",
  623.               " ",
  624.               " ",
  625.               " ",
  626.               " ",
  627.               " ",
  628.               " ",
  629. "                                                PID Values",
  630.               " ",
  631. "                     P             IS            I             D             DL            C",
  632. string.format("        Input:  %12.1f, %12.1f, %12.1f, %12.1f, %12.1f, %12.1f", proportional_field_error, inflow_I_sum, integral_field_error, derivative_field_error, inflow_D_last, inflow_correction),
  633. string.format("        Output: %12.1f, %12.1f, %12.1f, %12.1f, %12.1f, %12.1f", proportional_temp_error, outflow_I_sum, integral_temp_error, derivative_temp_error, outflow_D_last, outflow_correction),    
  634. }
  635.  
  636.  
  637.     term.clear()
  638.    
  639.     for i, v in ipairs(values) do
  640.       term.setCursor(left_margin, i * spacing)
  641.       term.write(v)
  642.     end
  643.  
  644.     -- Draw button values
  645.  
  646.     term.setCursor(temp_adjust_x_offset, temp_adjust_y_offset+10)
  647.     term.write("Reactor Temperature")
  648.     term.setCursor(field_adjust_x_offset+1, field_adjust_y_offset+10)
  649.     term.write("Field Strength")
  650.  
  651.     -- Draw Buttons
  652.  
  653.     gpu.setForeground(0x000000)
  654.  
  655.     for bname, button in pairs(buttons) do
  656.       if button.depressed then
  657.  
  658.         button.depressed = button.depressed - 1
  659.         if button.depressed == 0 then
  660.           button.depressed = nil
  661.         end
  662.       end
  663.       if button.condition == nil or button.condition() then
  664.         local center_color = 0xAAAAAA
  665.         local highlight_color = 0xCCCCCC
  666.         local lowlight_color = 0x808080
  667.         if button.depressed then
  668.           center_color = 0x999999
  669.           highlight_color = 0x707070
  670.           lowlight_color = 0xBBBBBB
  671.         end
  672.         gpu.setBackground(center_color)
  673.         gpu.fill(button.x, button.y, button.width, button.height, " ")
  674.         if button.width > 1 and button.height > 1 then
  675.           gpu.setBackground(lowlight_color)
  676.           gpu.fill(button.x+1, button.y+button.height-1, button.width-1, 1, " ")
  677.           gpu.fill(button.x+button.width-1, button.y, 1, button.height, " ")
  678.           gpu.setBackground(highlight_color)
  679.           gpu.fill(button.x, button.y, 1, button.height, " ")
  680.           gpu.fill(button.x, button.y, button.width, 1, " ")
  681.         end
  682.         gpu.setBackground(center_color)
  683.         term.setCursor(button.x + math.floor(button.width / 2 - #button.text / 2), button.y + math.floor(button.height / 2))
  684.         term.write(button.text)
  685.       end
  686.     end
  687.  
  688.     gpu.setBackground(0x000000)
  689.     gpu.setForeground(0xFFFFFF)
  690.   end  
  691.  
  692.   -- Wait for next tick, or manual shutdown
  693.  
  694.   local event, id, op1, op2 = event.pull(0.05)
  695.   if event == "interrupted" then
  696.     if safe then
  697.       break
  698.     end
  699.   elseif event == "touch" then
  700.    
  701.     -- Handle Button Presses
  702.  
  703.     local x = op1
  704.     local y = op2
  705.  
  706.     for bname, button in pairs(buttons) do
  707.       if (button.condition == nil or button.condition()) and x >= button.x and x <= button.x + button.width and y >= button.y and y <= button.y + button.height then
  708.         button.action()
  709.         button.depressed = 3
  710.       end
  711.     end
  712.   end
  713. end
  714.  
  715. term.clear()
RAW Paste Data