Advertisement
neuroticfox

Draconic Control v15.0b3 [xMPD] [Lua 5.3 / 5.2]

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