Advertisement
neuroticfox

Draconic Control v14.0 [sMAT] [Lua 5.3 / 5.2]

Jun 27th, 2023 (edited)
1,283
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 32.24 KB | None | 0 0
  1. -- Dear Programmer:
  2. -- When we wrote this code, only god and
  3. -- us understood how it worked. And now
  4. -- only god knows.
  5. --
  6. -- Therefore, if you are trying to optimize
  7. -- this script and it fails (Very likely),
  8. -- please increase this counter for the next
  9. -- person.
  10. --
  11. -- wastedHours = 541
  12.  
  13.  :: start ::
  14.  -- Locals & Requirements
  15.     local component = require("component")
  16.     local event = require("event")
  17.     local term = require("term")
  18.     local gpu = component.gpu
  19.     local screen = component.screen
  20.     local unicode= require("unicode")
  21.     local reactorOutputMultiplier = 1
  22.     local cutoffTemp = 9005
  23.     local chaosMode = 0
  24.     local tempDrop = 0
  25.     local devMode = 0
  26.     local fieldAdj = 0
  27.     local deviation = 0
  28.     local cVar = "DEV RELEASE: Use at your own risk."
  29.     local tArgs = {...}
  30.     local Arg0 = tonumber(tArgs[1])
  31.     local Arg1 = tonumber(tArgs[2])
  32.     local Arg2 = tonumber(tArgs[3])
  33.     local Arg3 = tonumber(tArgs[4])
  34.     local Arg4 = tostring(tArgs[5])
  35.     local Arg5 = tostring(tArgs[6])
  36.     local ratioX, ratioY = screen.getAspectRatio()
  37.     local maxX, maxY = gpu.maxResolution()
  38.     gpu.setResolution(math.min(ratioX*55, maxX), math.min(ratioY*25,maxY))
  39. term.clear()
  40. term.setCursor(0, 0)
  41. os.sleep(0.5)
  42.  -- pArgs
  43. if not Arg0 then
  44. os.execute(cls)
  45. print("Draconic Control 14")
  46. print("1.12 - 1.16 Compatible-ish")
  47. print()
  48. print("dc14 [Mult] [Temp] [Field] [Mode]")
  49. print()
  50. print("Arguments")
  51. print()
  52. print("[Mult]           -   Reactor Output Multiplier")
  53. print("1.16 [10]            1.12 [1]")
  54. print()
  55. print("[Temp]           -   Desired Reactor Temperature")
  56. print("Default [8000]           Range [2500-8000]")
  57. print()
  58. print("[Field]          -   Desired Field Strength")
  59. print("Default [15]         Range [0.5-99]")
  60. print()
  61. print("[Mode]           -   Set Desired Program Mode")
  62. print("Default [1]          Range [1-3]")
  63. print("[1-3]            -   Simple, Dev, noGUI")
  64. print()
  65. print("       Compiled by BrokenSynapse & AwesomeAlec1")
  66. print()
  67. print("Thanks to Maurdekye for creating the base of this program:")
  68. print("             https://youtu.be/iLvkk41K84E")
  69. print()
  70. print(" Thanks to AwesomeAlec1 for creating the control script:")
  71. print("             https://youtu.be/CLku1ckXpeU")
  72. print()
  73. print("  Thanks to MightyPirates for being so gracious as to")
  74. print("   let me fix what they broke by never using Lua 5.3")
  75. print()
  76. print("   And a very special thanks to ZanBorg for breaking")
  77. print("      this script until it doesn't break anymore.")
  78. goto fin
  79. end
  80.  -- sArgs
  81. local reactorOutputMultiplier = Arg0
  82. local idealTemp = Arg1 or 8000
  83. local idealField = Arg2 or 15
  84. local Mode = Arg3 or 1
  85.  -- Components
  86.     if not component.isAvailable("draconic_reactor") then
  87.         print("Reactor not connected. Please connect computer to reactor with an Adapter block.")
  88.         os.exit()
  89.     end
  90.     local reactor = component.draconic_reactor
  91.     local info = reactor.getReactorInfo()
  92.     local fluxGates = {}
  93.     for x,y in pairs(component.list("flux_gate")) do
  94.         fluxGates[#fluxGates+1] = x
  95.     end
  96.     if #fluxGates < 2 then
  97.         print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
  98.         os.exit()
  99.     end
  100.     local inputFlux = component.proxy(fluxGates[1])
  101.     local outputFlux = component.proxy(fluxGates[2])
  102.     outputFlux.setOverrideEnabled(true)
  103.     inputFlux.setOverrideEnabled(true)
  104.     if not inputFlux or not outputFlux then
  105.         print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
  106.         os.exit()
  107.     end
  108.  -- AutoSet Gates
  109.         reactor.chargeReactor()
  110.         satOne = info.energySaturation
  111.         fieldOne = info.fieldStrength
  112.         inputFlux.setFlowOverride(1.0)
  113.         os.sleep(0.5)
  114.         satTwo = info.energySaturation
  115.         fieldTwo = info.fieldStrength
  116.         inputFlux.setFlowOverride(0.0)
  117.         reactor.stopReactor()
  118.     if satTwo <= satOne or fieldTwo <= fieldOne then
  119.     local oldAddr = inputFlux.address
  120.       inputFlux = component.proxy(outputFlux.address)
  121.       outputFlux = component.proxy(oldAddr)
  122.     end
  123.  
  124.  -- Functions
  125.  
  126. function exit_msg(msg)
  127.     term.clear()
  128.     print(msg)
  129.     os.exit()
  130. end
  131. function modifyTemp(offset)
  132.     local newTemp = idealTemp + offset
  133.     if newTemp > 8000 and Mode == 1 then
  134.         newTemp = 8000
  135.     elseif newTemp > 8000 and Mode == 2 and chaosmode == 0 then
  136.         newTemp = 8000
  137.     elseif newTemp > 18000 and chaosmode == 1 then
  138.         newTemp = 18000
  139.     elseif newTemp < 2000 then
  140.         newTemp = 2000
  141.     end
  142.         idealTemp = newTemp
  143.     end
  144. function modifyField(offset)
  145.     local newField = idealField + offset
  146.     if newField > 99 then
  147.         newField = 99
  148.     elseif newField < 100 and chaosMode == 1 then
  149.         newField = 100
  150.     elseif newField < 0.5 and Mode == 1 or Mode == 3 then
  151.         newField = 0.5
  152.     elseif newField < 0.125 and Mode == 2 then
  153.         newField = 0.125
  154.     end
  155.         idealField = newField
  156.     end
  157.    
  158.  -- Buttons
  159.     local adj_button_width = 19
  160.     local tempOffsetX = 62
  161.     local tempOffsetY = 2
  162.     local fieldOffsetX = tempOffsetX + adj_button_width + 2
  163.     local fieldOffsetY = 2
  164.     local cutoffField = 0.75
  165.     highest_use = 0.1
  166.     local buttons = {
  167.     startButton={
  168.     x=2,
  169.     y=20,
  170.     width=18,
  171.     height=1,
  172.     text="Start",
  173.     textcolor = 0x0000AA,
  174.     action=function()
  175.       if info.status == "cooling" or info.status == "cold" then
  176.             chaosMode = 0
  177.             idealField = Arg2
  178.             cutoffField = 0.4
  179.             idealTemp = Arg1
  180.             startingVar = 1
  181.             cVar = "Do not use Chaos Mode with less than one block of fuel"
  182.         reactor.chargeReactor()
  183.       elseif info.status == "stopping" then
  184.             chaosMode = 0
  185.             idealField = Arg2
  186.             cutoffField = 0.4
  187.             idealTemp = Arg1
  188.             startingVar = 0
  189.             cVar = "Do not use Chaos Mode with less than one block of fuel"
  190.         reactor.activateReactor()
  191.       end
  192.     end,
  193.     condition=function() return info.status ~= "running" and info.status ~= "warming_up" end
  194.   },
  195.   shutdownButton={
  196.     x=2,
  197.     y=20,
  198.     width=18,
  199.     height=1,
  200.     text="Shutdown",
  201.     textcolor = 0xAA0000,
  202.     action=function()
  203.     cutoffTemp = 9000
  204.     idealTemp = Arg1
  205.     cutoffField = 0.4
  206.     cVar = "Do not use Chaos Mode with less than one block of fuel"
  207.       state = "MASD"
  208.       reactor.stopReactor()
  209.     end,
  210.     condition=function() return info.status == "running" or info.status == "warming_up" end
  211.   },
  212.   chaosMode={
  213.     x=2,
  214.     y=22,
  215.     width=18,
  216.     height=1,
  217.     text=" Chaos Mode",
  218.     textcolor = 0x800080,
  219.     action=function()
  220.         if chaosMode == 0 then
  221.             chaosMode = 1
  222.             cutoffTemp = 18000
  223.             idealTemp = 18000
  224.             idealField = 100
  225.             cutoffField = 5
  226.             idealTemp = 8000
  227.         elseif chaosMode == 1 then
  228.             chaosMode = 0
  229.             idealField = Arg2
  230.             cutoffField = 0.4
  231.             idealTemp = Arg1
  232.         end
  233.     end,
  234.     condition=function() return Mode == 2 and info.status == "running" end
  235.   },
  236.   forceExit={
  237.     x=158,
  238.     y=1,
  239.     width=3,
  240.     height=1,
  241.     text=" X ",
  242.     textcolor = 0xB00000,
  243.     action=function()
  244.         inputFlux.setFlowOverride(250000.0)
  245.         chaosMode = 0
  246.         idealField = 99
  247.         cutoffField = 0.4
  248.         idealTemp = Arg1
  249.       reactor.stopReactor()
  250.       gpu.setResolution(gpu.maxResolution())
  251.       event_loop = false
  252.       os.execute("cls")
  253.     end,
  254. --    condition=function() return running or shutting_down end
  255.   },
  256.   Update={
  257.     x=22,
  258.     y=22,
  259.     width=18,
  260.     height=1,
  261.     text="Update",
  262.     action=function()
  263.         reactor.stopReactor()
  264.         os.execute("cd /home; pastebin get -f YZK9hTBU dc14; cls; dc14")
  265.     end,
  266.     condition=function() return info.status ~= "running" and info.status ~= "warming_up" end
  267.   },
  268.   switchGates={
  269.     x=2,
  270.     y=22,
  271.     width=18,
  272.     height=1,
  273.     text="Swap Flux Gates",
  274.     action=function()
  275.       cutoffTemp = 10500
  276.       local old_addr = inputFlux.address
  277.       inputFlux = component.proxy(outputFlux.address)
  278.       outputFlux = component.proxy(old_addr)
  279.     end,
  280.     condition=function() return info.status == "cooling" or info.status == "cold" or info.status == "stopping" end
  281.   },
  282.   tempMax={
  283.     x=tempOffsetX,
  284.     y=tempOffsetY,
  285.     width=adj_button_width,
  286.     height=1,
  287.     text="Maximum",
  288.     textcolor = 0x552222,
  289.     action=function()
  290.     idealTemp = 8000 end
  291.   },
  292.   tempPThousand={
  293.     x=tempOffsetX,
  294.     y=tempOffsetY+2,
  295.     width=adj_button_width,
  296.     height=1,
  297.     text="+1000",
  298.     textcolor = 0x552222,
  299.     action=function() modifyTemp(1000) end
  300.   },
  301.   tempPHundred={
  302.     x=tempOffsetX,
  303.     y=tempOffsetY+4,
  304.     width=adj_button_width,
  305.     height=1,
  306.     text="+100",
  307.     textcolor = 0x552222,
  308.     action=function() modifyTemp(100) end
  309.   },
  310.   tempPTen={
  311.     x=tempOffsetX,
  312.     y=tempOffsetY+6,
  313.     width=adj_button_width,
  314.     height=1,
  315.     text="+10",
  316.     textcolor = 0x552222,
  317.     action=function() modifyTemp(10) end
  318.   },
  319.   tempPOne={
  320.     x=tempOffsetX,
  321.     y=tempOffsetY+8,
  322.     width=adj_button_width,
  323.     height=1,
  324.     text="+1",
  325.     textcolor = 0x552222,
  326.     action=function() modifyTemp(1) end
  327.   },
  328.   tempMin={
  329.     x=tempOffsetX,
  330.     y=tempOffsetY+20,
  331.     width=adj_button_width,
  332.     height=1,
  333.     text="Minimum",
  334.     textcolor = 0x552222,
  335.     action=function() modifyTemp(-20000) end
  336.   },
  337.   tempMThousand={
  338.     x=tempOffsetX,
  339.     y=tempOffsetY+18,
  340.     width=adj_button_width,
  341.     height=1,
  342.     text="-1000",
  343.     textcolor = 0x552222,
  344.     action=function() modifyTemp(-1000) end
  345.   },
  346.   tempMHundred={
  347.     x=tempOffsetX,
  348.     y=tempOffsetY+16,
  349.     width=adj_button_width,
  350.     height=1,
  351.     text="-100",
  352.     textcolor = 0x552222,
  353.     action=function() modifyTemp(-100) end
  354.   },
  355.   tempMTen={
  356.     x=tempOffsetX,
  357.     y=tempOffsetY+14,
  358.     width=adj_button_width,
  359.     height=1,
  360.     text="-10",
  361.     textcolor = 0x552222,
  362.     action=function() modifyTemp(-10) end
  363.   },
  364.   tempMOne={
  365.     x=tempOffsetX,
  366.     y=tempOffsetY+12,
  367.     width=adj_button_width,
  368.     height=1,
  369.     text="-1",
  370.     textcolor = 0x552222,
  371.     action=function() modifyTemp(-1) end
  372.   },
  373.   fieldPTen={
  374.     x=fieldOffsetX,
  375.     y=fieldOffsetY+1,
  376.     width=adj_button_width,
  377.     height=1,
  378.     text="+10",
  379.     textcolor = 0x222299,
  380.     action=function() modifyField(10) end
  381.   },
  382.     fieldPOne={
  383.     x=fieldOffsetX,
  384.     y=fieldOffsetY+3,
  385.     width=adj_button_width,
  386.     height=1,
  387.     text="+1",
  388.     textcolor = 0x222299,
  389.     action=function() modifyField(1) end
  390.   },
  391.   fieldPTenth={
  392.     x=fieldOffsetX,
  393.     y=fieldOffsetY+5,
  394.     width=adj_button_width,
  395.     height=1,
  396.     text="+0.1",
  397.     textcolor = 0x222299,
  398.     action=function() modifyField(0.1) end
  399.   },
  400.     fieldPThou={
  401.     x=fieldOffsetX,
  402.     y=fieldOffsetY+7,
  403.     width=adj_button_width,
  404.     height=1,
  405.     text="+0.005",
  406.     textcolor = 0x222299,
  407.     action=function() modifyField(0.005) end
  408.   },
  409.   fieldMTen={
  410.     x=fieldOffsetX,
  411.     y=fieldOffsetY+19,
  412.     width=adj_button_width,
  413.     height=1,
  414.     text="-10",
  415.     textcolor = 0x222299,
  416.     action=function() modifyField(-10) end
  417.   },
  418.     fieldMOne={
  419.     x=fieldOffsetX,
  420.     y=fieldOffsetY+17,
  421.     width=adj_button_width,
  422.     height=1,
  423.     text="-1",
  424.     textcolor = 0x222299,
  425.     action=function() modifyField(-1) end
  426.   },
  427.   fieldMTenth={
  428.     x=fieldOffsetX,
  429.     y=fieldOffsetY+15,
  430.     width=adj_button_width,
  431.     height=1,
  432.     text="-0.1",
  433.     textcolor = 0x222299,
  434.     action=function() modifyField(-0.1) end
  435.    },
  436.      fieldMThou={
  437.     x=fieldOffsetX,
  438.     y=fieldOffsetY+13,
  439.     width=adj_button_width,
  440.     height=1,
  441.     text="-0.005",
  442.     textcolor = 0x222299,
  443.     action=function() modifyField(-0.005) end
  444.    }
  445. }
  446.  
  447.  -- tweakable pid gains
  448.  
  449. inflow_P_gain = 1
  450. inflow_I_gain = 0.04
  451. inflow_D_gain = 0.1
  452.  
  453. outflow_P_gain = 500
  454. outflow_I_gain = 0.5
  455. outflow_II_gain = 0.0000003
  456. outflow_D_gain = 60000
  457.  
  458.  -- initialize main loop
  459.  
  460. inflow_I_sum = 0
  461. inflow_D_last = 0
  462.  
  463. outflow_I_sum = 0
  464. outflow_II_sum = 0
  465. outflow_D_last = 0
  466.  
  467. state = "Standby"
  468. shutting_down = false
  469.  
  470. if condition.temperature > 25 then
  471.   state = "Cooling"
  472. end
  473. if condition.temperature > 2000 then
  474.   state = "Active"
  475. end
  476.  
  477.  -- Possible states:
  478.   --Standby
  479.   --Charging
  480.   --Active
  481.   --Manual Shutdown
  482.   --Emergency Shutdown
  483.   --Cooling
  484.  
  485.  -- Control Loop
  486. event_loop = true
  487. while event_loop do
  488. :: loopstart ::
  489.         info = reactor.getReactorInfo()
  490.     if not info or info.maxFuelConversion < 0.001 then
  491.     cutoffTemp = 9000
  492.     idealTemp = Arg1
  493.     chaosMode = 0
  494.     gpu.setBackground(0x000000)
  495.     gpu.setForeground(0xFF0000)
  496.     term.setCursor(55, 1)
  497.     print "Please verify that your reactor is refueled."
  498.     term.setCursor(55, 2)
  499.     print "Please verify the integrity of your reactor."
  500.     goto start
  501.     gpu.setForeground(0x000000)
  502.     end
  503.     if info.temperature >= 2000 and info.status ~= "stopping"  then
  504.         reactor.activateReactor()
  505.     end
  506.    
  507.  -- Chaos Mode Safe Shutdown
  508.     if info.temperature > 18000 and chaosMode == 1 and tempDrop == 0 then
  509.         idealTemp = 16000
  510.         tempDrop = 1
  511.         cVar = "Cooling For Shutdown"
  512.     elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 8 and chaosMode == 1  and tempDrop == 1 then
  513.         idealTemp = 14000
  514.         tempDrop = 2
  515.     elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 12.5 and chaosMode == 1  and info.maxFuelConversion < 1297 then
  516.         idealTemp = 8000
  517.         idealField = 99
  518.     elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 1.3 and chaosMode == 1  and tempDrop == 2 and info.maxFuelConversion < 5185 then
  519.         idealTemp = 8000
  520.         idealField = 25
  521.     elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 1 and chaosMode == 1  and tempDrop == 2 then
  522.         idealTemp = 8000
  523.         idealField = 25
  524.     end
  525.  
  526.      -- adjust inflow rate based on field strength
  527.    
  528.     local field_error = (info.maxFieldStrength * (idealField / 100)) - info.fieldStrength
  529.     local proportional_field_error = field_error * inflow_P_gain
  530.     inflow_I_sum = inflow_I_sum + field_error
  531.     local integral_field_error = inflow_I_sum * inflow_I_gain
  532.     local derivative_field_error = (field_error - inflow_D_last) * inflow_D_gain
  533.     inflow_D_last = field_error
  534.     local inflow_correction = proportional_field_error + integral_field_error + derivative_field_error
  535.     if inflow_correction < 0 then
  536.       inflow_I_sum = inflow_I_sum - field_error
  537.     end
  538.     inflow = inflow_correction
  539.  
  540.     if not shutting_down then
  541.  
  542.       -- adjust outflow rate based on core temperature
  543.  
  544.       local temp_error = idealTemp - info.temperature
  545.       local proportional_temp_error = temp_error * outflow_P_gain
  546.       outflow_I_sum = outflow_I_sum + temp_error
  547.       local integral_temp_error = outflow_I_sum * outflow_I_gain
  548.       if math.abs(temp_error) < 100 then
  549.         outflow_II_sum = outflow_II_sum + integral_temp_error
  550.       else
  551.         outflow_II_sum = 0
  552.       end
  553.       local second_integral_temp_error = outflow_II_sum * outflow_II_gain
  554.       local derivative_temp_error = (temp_error - outflow_D_last) * outflow_D_gain
  555.       outflow_D_last = temp_error
  556.       local outflow_correction = proportional_temp_error + integral_temp_error + second_integral_temp_error + derivative_temp_error
  557.       if outflow_correction < 0 then
  558.         outflow_I_sum = outflow_I_sum - temp_error
  559.       end
  560.       outflow = outflow_correction
  561.  
  562.         if info.temperature > idealTemp then
  563.           state = "Manual Shutdown"
  564.           reactor.stopReactor()
  565.           os.sleep(0.10)
  566.           state = "Active"
  567.           reactor.activateReactor()
  568.         end
  569.  
  570.  -- Auto Adjust Offset
  571.  
  572.     if info.temperature == idealTemp and ((info.fieldStrength / info.maxFieldStrength) * 100) < idealField and chaosMode ~= 1 then
  573.         fieldAdj = (idealField - ((info.fieldStrength / info.maxFieldStrength) * 100))
  574.     end
  575.  
  576.     local targetShieldPercent = idealField or 15 -- Desired shield strength
  577.     local targetShield = (targetShieldPercent / 100)
  578.    
  579.  -- Reactor equation variables
  580.     local targetTemp50  = math.min((targetTemp / 10000) * 50, 99)
  581.     local coreSat       = reactorInfo.energySaturation / reactorInfo.maxEnergySaturation
  582.     local convLVL       = (reactorInfo.fuelConversion / reactorInfo.maxFuelConversion * 1.3) - 0.3
  583.  
  584.     -- Calculate the temperature rise resistance for the reactor at the desired temperature.
  585.     local targetTempResist = ((targetTemp50^4) / (100 - targetTemp50))
  586.  
  587.     -- Calculate the temperature rise exponential needed to reach the desired temperature
  588.     local targetTempExpo = -(targetTempResist*convLVL) - 1000*convLVL + targetTempResist
  589.  
  590.     -- Calculate the saturation level needed to produce the required tempRiseExpo
  591.     local term1 = 1334.1-(3*targetTempExpo)
  592.     local term2 = (1200690-(2700*targetTempExpo))^2
  593.     local term3 = ((-1350*targetTempExpo)+(((-4*term1^3+term2)^(1/2))/2)+600345)^(1/3)
  594.     local targetNegCSat = -(term1/(3*term3))-(term3/3)
  595.  
  596.     -- Saturation received from above equation needs to be reformatted to a more useful form
  597.     local targetCoreSat = 1 - (targetNegCSat/99)
  598.     local targetSat = targetCoreSat * reactorInfo.maxEnergySaturation
  599.  
  600.     -- Calculate the difference between where saturation is and where it needs to be
  601.     local saturationError = reactorInfo.energySaturation - targetSat
  602.  
  603.     -- Calculate field drain
  604.     local tempDrainFactor = 0
  605.     if reactorInfo.temperature > 8000 then
  606.       tempDrainFactor = 1 + ((reactorInfo.temperature-8000)^2 * 0.0000025)
  607.     elseif reactorInfo.temperature > 2000 then
  608.       tempDrainFactor = 1
  609.     elseif reactorInfo.temperature > 1000 then
  610.       tempDrainFactor = (reactorInfo.temperature-1000)/1000
  611.     end
  612.    
  613.     local baseMaxRFt = (reactorInfo.maxEnergySaturation / 1000) * reactorOutputMultiplier * 1.5
  614.     local fieldDrain = math.min(tempDrainFactor * math.max(0.01, (1-coreSat)) * (baseMaxRFt / 10.923556), 2147000000)
  615.     local fieldNegPercent = 1 - targetShield
  616.  
  617.     --local fieldInputRate = fieldDrain / fieldNegPercent
  618.     local fieldStrengthError = (reactorInfo.maxFieldStrength * targetShield) - reactorInfo.fieldStrength
  619.     local requiredInput = math.min((reactorInfo.maxFieldStrength * reactorInfo.fieldDrainRate) / (reactorInfo.maxFieldStrength - reactorInfo.fieldStrength), reactorInfo.maxFieldStrength - reactorInfo.fieldStrength)
  620.          
  621.  --Automations
  622.  
  623.     if info.status == "running" then
  624.     local outputNeeded = math.min(saturationError, (info.maxEnergySaturation/40))-- + info.generationRate
  625.         outputFlux.setFlowOverride(outputNeeded)
  626.         inputFlux.setFlowOverride(math.min(fieldStrengthError + requiredInput, info.maxFieldStrength) - info.fieldDrainRate + 1)
  627.     elseif info.status == "warming_up" then
  628.         outputFlux.setFlowOverride(0.0)
  629.         inputFlux.setFlowOverride(550000000.0)
  630.     elseif info.status == "stopping" then
  631.         outputFlux.setFlowOverride(0.0)
  632.         inputFlux.setFlowOverride(requiredInput)
  633.     end
  634.     if info.temperature > cutoffTemp then
  635.         print("Reactor Too Hot, shutting down")
  636.         reactor.stopReactor()
  637.     end
  638.     if ((info.fieldStrength / info.maxFieldStrength) * 100) < cutoffField then
  639.         print("Reactor Field Has Failed, Failsafe Activated, Shutting Down")
  640.         reactor.stopReactor()
  641.     end
  642.     if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 0.2 then
  643.         print("Reactor Fuel Low, Shutting Down")
  644.         reactor.stopReactor()
  645.     end
  646.    end
  647.  
  648.     -- Get Temp Rise
  649.         oldTemp = currentTemp or info.temperature
  650.         currentTemp = info.temperature
  651.         oldTempRate = tempChangeRate or currentTemp - oldTemp
  652.         tempChangeRate = currentTemp - oldTemp
  653.         tempAccel = tempChangeRate - oldTempRate
  654.     if tempAccel == 0 then
  655.         tempAccel = 0.001
  656.     end
  657.     -- Get Fuel Use Rate
  658.         oldFuel = currentFuel or (info.maxFuelConversion - info.fuelConversion)
  659.         currentFuel = (info.maxFuelConversion - info.fuelConversion)
  660.         oldUseRate = fuelUseRate or math.max(info.fuelConversionRate*20, 0.1)
  661.         fuelUseRate = math.max(info.fuelConversionRate*20, 0.1)
  662.         fuelAccel = math.max(fuelUseRate - oldUseRate, 0.1)
  663.  -- Fuel Conversion Rate
  664.     if info.fuelConversionRate > 249999 then
  665.         fuelConversionRate = ((info.fuelConversionRate / (info.maxFuelConversion * 1000000)) * 2000)
  666.         fuelMeasure = "  %%/s"
  667.     elseif info.fuelConversionRate > 999 then
  668.         fuelConversionRate = (info.fuelConversionRate / 1000)
  669.         fuelMeasure = " "..(unicode.char(956)).."b/t"
  670.     elseif info.fuelConversionRate > 999999 then
  671.         fuelConversionRate = (info.fuelConversionRate / 1000000)
  672.         fuelMeasure = " mb/t"
  673.     else
  674.         fuelConversionRate = info.fuelConversionRate
  675.         fuelMeasure = " nb/t"
  676.     end
  677.  -- Get Time Until Cool
  678.     if info.fuelConversionRate < 1 then
  679.         tempDrain = ((info.temperature - 2000) / 0.4)
  680.     else
  681.         tempDrain = 1
  682.     end
  683.  -- Get Temp Rise
  684.    
  685.    
  686.  --Burn Stage
  687.     if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 20 then burnStage = "H"
  688.     elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 15 then burnStage = "He"
  689.     elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 10 then burnStage = "C"
  690.     elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 8 then burnStage = "Ne"
  691.     elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 5.5 then burnStage = "O"
  692.     elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 2.5 then burnStage = "Si"
  693.     elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 1 then burnStage = "Fe"
  694.     end
  695.  -- Accuracy
  696.     if ((info.fieldStrength / info.maxFieldStrength) * 100) > idealField then
  697.      deviation = (((info.fieldStrength / info.maxFieldStrength) * 100) + fieldAdj) - idealField
  698.     elseif ((info.fieldStrength / info.maxFieldStrength) * 100) < idealField then
  699.      deviation = idealField - (((info.fieldStrength / info.maxFieldStrength) * 100) + fieldAdj)
  700.     end
  701.  -- DrawData
  702.     local secondsToExpire = (info.maxFuelConversion - info.fuelConversion) / math.max(info.fuelConversionRate*0.00002, 0.00001)
  703.  -- GUI
  704.     if term.isAvailable() and Mode ~= 3 then
  705.         function modify_eff(offset)
  706.             local eff = ((outputFlux / inputFlux) * 100)
  707.             if eff > 100000 then
  708.             eff = 1
  709.         end
  710.     end
  711.     local left_margin = 2
  712.     local spacing = 1
  713.     local values = {
  714.                 "Draconic Control™  [v14.0 sMAT | YZK9hTBU]",
  715.                 " ",
  716.                 "┌──────────────────Reactor Statistics────────────────────┐",
  717. string.format("│Time Until Refuel:         │  %5.0fd, %2.0fh, %2.0fm, %2.0fs     │", secondsToExpire/86400, secondsToExpire   /3600 % 24, secondsToExpire/60 % 60, secondsToExpire % 60),
  718. string.format("│Time Until Cool:           │  %5.0fd, %2.0fh, %2.0fm, %2.0fs     │", tempDrain/86400, tempDrain   /3600 % 24, tempDrain/60 % 60, tempDrain % 60),
  719. string.format("│Ideal Field:               │           %8.3f%%        │", idealField),
  720. string.format("│Current Field:             │           %7.3f%%         │", ((info.fieldStrength / info.maxFieldStrength) * 100) + fieldAdj),
  721.                 "├───────────────────────────┼────────────────────────────┤",
  722. string.format("│Fuel Remaining:            │           %7.3f%%         │", ((1 - info.fuelConversion / info.maxFuelConversion) * 100)),
  723. string.format("│Fuel Use Rate:             │           %7.3f" .. fuelMeasure .. "     │", fuelConversionRate),
  724.                 "├───────────────────────────┼────────────────────────────┤",
  725. string.format("│Temperature                │   %7.1f°c [%8.1f°f]   │", info.temperature, ((info.temperature * 1.8) + 32)),
  726. string.format("│Ideal Temperature:         │   %7.1f°c [%8.1f°f]   │", idealTemp, ((idealTemp * 1.8) + 32)),
  727.                 "├───────────────────────────┼────────────────────────────┤",
  728. string.format("│Energy Input:              │   %12.1f RF/t        │", requiredInput),
  729. string.format("│Energy Output:             │   %12.1f RF/t        │", outputFlux.getFlow()),
  730.                 "└───────────────────────────┴────────────────────────────┘",
  731.                 " " .. cVar,
  732.                 " "
  733. }
  734.     local values2 = {
  735. " ",
  736. " ",
  737. " ",
  738. "                                                                                                                          [Reference Table]",
  739. "                                                                                                             ┌─────────────┬─────────────┬─────────────┐",
  740. "                                                                                                             │ Temperature │  Remaining  │ Consumption │",
  741. "                                                                                                             ├─────────────┼─────────────┼─────────────┤",
  742. "                                                                                                             │    14000    │    93.27    │    91.90    │",
  743. "                                                                                                             ├─────────────┼─────────────┼─────────────┤",
  744. "                                                                                                             │    15000    │    59.00    │    123.5    │",
  745. "                                                                                                             ├─────────────┼─────────────┼─────────────┤",
  746. "                                                                                                             │    16000    │    36.45    │     161     │",
  747. "                                                                                                             ├─────────────┼─────────────┼─────────────┤",
  748. "                                                                                                             │    17000    │    21.40    │     204     │",
  749. "                                                                                                             ├─────────────┼─────────────┼─────────────┤",
  750. "                                                                                                             │    18000    │    11.80    │     251     │",
  751. "                                                                                                             ├─────────────┼─────────────┼─────────────┤",
  752. "                                                                                                             │    19000    │    03.89    │     303     │",
  753. "                                                                                                             └─────────────┴─────────────┴─────────────┘",
  754. " ",
  755. " ",
  756. " ",
  757. " ",
  758. " ",
  759. " ",
  760. " ",
  761. " ",
  762. " ",
  763. " ",
  764. " ",
  765. " ",
  766. " ",
  767.               "Eq. Fusion Stage     " .. burnStage,
  768. string.format("Max Fuel [nb]:       %4.3f", (info.maxFuelConversion * 1000000)),
  769. string.format("Fuel Remaining [nb]: %4.3f", ((info.maxFuelConversion - info.fuelConversion) * 1000000)),
  770. string.format("Temperature Rise: %4.3f", tempAccel),
  771. string.format("Temp Resist for target temp %g (%g): %.2f", idealTemp, targetTemp50, targetTempResist),
  772. string.format("Temp expo for convLVL %.2f: %.2f", convLVL, targetTempExpo),
  773. string.format("Saturation needed for zero rise: %g (%3.2f%%)", targetSat, targetCoreSat*100),
  774. string.format("Error between current saturation and target saturation: %g\n", saturationError),
  775. string.format("Current field drain is %g RF/t", info.fieldDrainRate),
  776. string.format("Current temp drain factor for temp %g is %1.2f", info.temperature, tempDrainFactor),
  777. string.format("fieldNegPercent is %g", fieldNegPercent),
  778. string.format("Required input to counter field drain: %g RF/t\n", requiredInput),
  779. string.format("Field Deviation: " .. unicode.char(8776) .. deviation .. "%%"),
  780. string.format("Field #:       %9.3f", info.fieldStrength),
  781. string.format("Field Per:     %9.3f", ((info.fieldStrength / info.maxFieldStrength) * 100)),
  782. string.format("Input Flux Gate:  [" .. inputFlux.address .. "] Set To: " .. inputFlux.getFlow()),
  783. string.format("Output Flux Gate: [" .. outputFlux.address .. "] Set To: " .. outputFlux.getFlow())
  784. }
  785. term.clear()
  786.     if Mode == 2 and Mode ~= 3 then
  787.     for i, v in ipairs(values2) do
  788.         term.setCursor(left_margin, i * spacing)
  789.         term.write(v)
  790.         end
  791.     end
  792.     if Mode ~= 3 then
  793.     for i, v in ipairs(values) do
  794.         term.setCursor(left_margin, i * spacing)
  795.         term.write(v)
  796.         end
  797.     end
  798.  -- Draw Buttons
  799.  
  800.         term.setCursor(tempOffsetX, tempOffsetY+10)
  801.         term.write("Reactor Temperature")
  802.         term.setCursor(fieldOffsetX+1, fieldOffsetY+10)
  803.         term.write("  Field Strength")
  804.         gpu.setForeground(0xFFFFFF)
  805.     for bname, button in pairs(buttons) do
  806.         gpu.setForeground(0x000000)
  807.         if button.depressed then
  808.             button.depressed = button.depressed - 1
  809.             if button.depressed == 0 then
  810.                 button.depressed = nil
  811.             end
  812.         end
  813.     if button.condition == nil or button.condition() then
  814.         local centerColor = 0xBBBBBB
  815.         local highlightColor = 0xCCCCCC
  816.         local lowlightColor = 0x808080
  817.     if button.depressed then
  818.         centerColor = 0xAAAAAA
  819.         highlightColor = 0x707070
  820.         lowlightColor = 0xBBBBBB
  821.     end
  822.         gpu.setBackground(centerColor)
  823.         gpu.fill(button.x, button.y, button.width, button.height, " ")
  824.     if button.width > 1 and button.height > 1 then
  825.         gpu.setBackground(lowlightColor)
  826.         gpu.fill(button.x+1, button.y+button.height-1, button.width-1, 1, " ")
  827.         gpu.fill(button.x+button.width-1, button.y, 1, button.height, " ")
  828.         gpu.setBackground(highlightColor)
  829.         gpu.fill(button.x, button.y, 1, button.height, " ")
  830.         gpu.fill(button.x, button.y, button.width, 1, " ")
  831.     end
  832.         gpu.setBackground(centerColor)
  833.     if button.textcolor then gpu.setForeground(button.textcolor) end
  834.         term.setCursor(button.x + math.floor(button.width / 2 - #button.text / 2), button.y + math.floor(button.height / 2))
  835.         term.write(button.text)
  836.     end
  837.     end
  838.     gpu.setBackground(0x676767)
  839.     gpu.setForeground(0x220000)
  840.     end
  841.     if term.isAvailable() and Mode == 3 then
  842.     local left_margin = 2
  843.     local spacing = 1
  844.     local values3 = {
  845. "Eq. Fusion Stage     " .. burnStage,
  846. string.format("Max Fuel [nb]:       %4.3f", (info.maxFuelConversion * 1000000)),
  847. string.format("Fuel Remaining [nb]: %4.3f", ((info.maxFuelConversion - info.fuelConversion) * 1000000)),
  848. string.format("Temperature Rise: %4.3f", tempAccel),
  849. string.format("Temp Resist for target temp %g (%g): %.2f", idealTemp, targetTemp50, targetTempResist),
  850. string.format("Temp expo for convLVL %.2f: %.2f", convLVL, targetTempExpo),
  851. string.format("Saturation needed for zero rise: %g (%3.2f%%)", targetSat, targetCoreSat*100),
  852. string.format("Error between current saturation and target saturation: %g\n", saturationError),
  853. string.format("Current field drain is %g RF/t", info.fieldDrainRate),
  854. string.format("Current temp drain factor for temp %g is %1.2f", info.temperature, tempDrainFactor),
  855. string.format("fieldNegPercent is %g", fieldNegPercent),
  856. string.format("Required input to counter field drain: %g RF/t\n", requiredInput),
  857. string.format("Field Deviation: " .. unicode.char(8776) .. deviation .. "%%"),
  858. string.format("Input Flux Gate:  [" .. inputFlux.address .. "] Set To: " .. inputFlux.getFlow()),
  859. string.format("Output Flux Gate: [" .. outputFlux.address .. "] Set To: " .. outputFlux.getFlow())
  860. }
  861.  for i, v in ipairs(values3) do
  862.  term.setCursor(left_margin, i * spacing)
  863.  term.write(v)
  864.  end
  865. end
  866.  -- Wait for next tick, or manual shutdown
  867.     local event, id, op1, op2 = event.pull(0.05)
  868.     if event == "interrupted" then
  869.         if safe then
  870.         break
  871.         end
  872.     elseif event == "touch" then
  873.  -- Handle Button Presses
  874.         local x = op1
  875.         local y = op2
  876.         for bname, button in pairs(buttons) do
  877.             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
  878.                 button.action()
  879.                 button.depressed = 3
  880.             end
  881.         end
  882.     end
  883.     os.sleep()
  884.         if info.fuelConversionRate == 0 and chaosMode == 1 then
  885.         reactor.stopReactor()
  886.         cutoffTemp = 9001
  887.         idealTemp = 8000
  888.         chaosMode = 0
  889.     end
  890. end
  891. :: fin ::
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement