Advertisement
Hiranus

DraconicEvolution Reactor Automation

Feb 21st, 2022 (edited)
1,079
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.46 KB | None | 0 0
  1. local reactorCardId = 0
  2.  
  3. local desiredTemp = 7995
  4. local allowedTempDifference = 5
  5. local baseReactorIO = 1500000
  6. local reactorHeatUpSpeedMultipler = 2
  7. local maxReactorFuelTotal = 10368
  8. local shieldDesiredPower = 0.10
  9. local shieldMaxInputMultipler = 50
  10. local fuelShutdownLevel = 0.9
  11.  
  12. local reactor = nil
  13. local variableStore  = nil
  14.  
  15. local outputFlowGate = nil
  16. local outputFlow = 0
  17.  
  18. local inputFlowGate = nil
  19. local inputFlow = 0
  20.  
  21. local previousReactorInfo = nil
  22. local currentReactorInfo = nil
  23. local startingReactorOutput = 0
  24. local currentReactorFuelTotal = 0
  25.  
  26. local temperatureDiff = 0
  27. local outputDiff = 0
  28.  
  29. local lastOutputUpdateTicksAgo = 0
  30.  
  31. local desiredTempMin = desiredTemp - allowedTempDifference
  32. local desiredTempMax = desiredTemp + allowedTempDifference
  33.  
  34. local function CheckNumberBetween(min,max,val)
  35.     return min < val and max > val
  36. end
  37.  
  38. local reactorStates = {
  39.     "Off",
  40.     "Charging",
  41.     "Running",
  42.     "Stopping",
  43.     "Cooling Down",
  44.     "Exploding"
  45. }
  46. reactorStates[0] = reactorStates[1] --fix for not initalized reactor
  47.  
  48. local function SetNewReactorOutput(value,forceNewValue)
  49.     if value < 0 then
  50.         value = 0
  51.     end
  52.     value = math.ceil(value)
  53.     if forceNewValue ~= true then
  54.         local gateNum = outputFlowGate.getSignalLowFlow()
  55.         if outputFlow ~= gateNum then  ---To allow manual number override
  56.             value = gateNum
  57.         end
  58.     end
  59.     lastOutputUpdateTicksAgo = 0
  60.     outputFlow = value
  61.     outputFlowGate.setSignalLowFlow(value)
  62. end
  63. local function SetNewReactorInput(value)
  64.     if value < 0 or value ~= value then
  65.         value = 0
  66.     end
  67.     value = math.ceil(value)
  68.     inputFlow = value
  69.     inputFlowGate.setSignalLowFlow(value)
  70. end
  71.  
  72. local function ShieldTooLowFix()
  73.     local shieldPercent = currentReactorInfo.shield_charge/currentReactorInfo.max_shield_charge
  74.     return 1 + math.max(shieldMaxInputMultipler * ((shieldDesiredPower - shieldPercent)/shieldDesiredPower),0)
  75. end
  76.  
  77. local function UpdateReactorInput()
  78.     local newShield = currentReactorInfo.field_drain + (currentReactorInfo.field_drain * shieldDesiredPower)
  79.     newShield = newShield * ShieldTooLowFix()
  80.     SetNewReactorInput(newShield)
  81. end
  82.  
  83. local function GetReactorData()
  84.     return variableStore.read(reactorCardId).value.v
  85. end
  86.  
  87. local function InitalizeReactorComponents()
  88.     local sucessfulInitialization = true
  89.     repeat
  90.     if sucessfulInitialization == false then
  91.         sleep(0.05)
  92.         term.clear()
  93.         term.setCursorPos(1,1)
  94.     end
  95.     sucessfulInitialization = true
  96.     local deviceList = peripheral.getNames()
  97.     local flowGates = {}
  98.     for i = 1, #deviceList do
  99.         local device = peripheral.getType(deviceList[i])
  100.         if device == "draconic_reactor" then
  101.             reactor = peripheral.wrap(deviceList[i])
  102.         elseif device == "variableStore" then
  103.             variableStore = peripheral.wrap(deviceList[i])
  104.         elseif device == "flow_gate" then
  105.             flowGates[#flowGates + 1] = peripheral.wrap(deviceList[i])
  106.         end
  107.     end
  108.     if #flowGates ~= 2 then
  109.         print("You need exactly 2 flow gates")
  110.         sucessfulInitialization = false
  111.     else
  112.         for i = 1, #flowGates do
  113.             local gate = flowGates[i]
  114.             if gate.getSignalHighFlow() == 0 then
  115.                 inputFlowGate = gate
  116.             elseif gate.getSignalHighFlow() == 1 then
  117.                 outputFlowGate = gate
  118.             end
  119.         end
  120.     end
  121.  
  122.     if outputFlowGate == nil or inputFlowGate == nil then
  123.         print("At Least one flow gate is missing configuration. Please set in \"Redstone Signal Hgh\":");
  124.         print("0 : Input")
  125.         print("1 : Output")
  126.         sucessfulInitialization = false;
  127.     end
  128.     if reactor == nil then
  129.     --    error("Reactor is missing");
  130.     end
  131.     if variableStore == nil then
  132.         print("Variable Store is missing");
  133.         sucessfulInitialization = false;
  134.     end
  135.     until (sucessfulInitialization)
  136. end
  137.  
  138. local function ReactorRunning()
  139.     lastOutputUpdateTicksAgo = lastOutputUpdateTicksAgo + 1
  140.     if previousReactorInfo ~= nil then
  141.         local newFlowDiff = math.ceil(outputDiff/2 * startingReactorOutput)
  142.         local newOutputFlow = math.ceil(outputFlow+newFlowDiff)
  143.         local maxAllowedTemp = desiredTemp + allowedTempDifference
  144.         local mult = 1 - (math.sin((maxAllowedTemp - currentReactorInfo.temperature) / (allowedTempDifference * 2) * math.pi)^128)
  145.         if CheckNumberBetween(desiredTempMin,desiredTempMax,currentReactorInfo.temperature) then
  146.             if math.abs(temperatureDiff)>0.05 then
  147.                 return
  148.             end
  149.             if math.abs(desiredTemp - currentReactorInfo.temperature) < lastOutputUpdateTicksAgo then
  150.                 SetNewReactorOutput(outputFlow + (outputDiff*startingReactorOutput) * mult)
  151.             end
  152.         elseif ((currentReactorInfo.temperature < desiredTemp - allowedTempDifference and outputDiff*reactorHeatUpSpeedMultipler > temperatureDiff)
  153.                 or (currentReactorInfo.temperature > desiredTemp + allowedTempDifference)) and lastOutputUpdateTicksAgo > 10 then
  154.             SetNewReactorOutput(newOutputFlow)
  155.         end
  156.     end
  157. end
  158.  
  159. local function DisplayReactorStats()
  160.  
  161.     term.clear()
  162.     term.setCursorPos(1,1)
  163.     if previousReactorInfo ~= nil then
  164.         print("Reactor state : ".. reactorStates[currentReactorInfo.reactor_state])
  165.         print()
  166.         print("Previous temperature : "..string.format("%.5f",(previousReactorInfo.temperature)))
  167.         print("Current temperature  : "..string.format("%.5f",currentReactorInfo.temperature))
  168.         print()
  169.         print("Temperature difference : "..string.format("%.6f",temperatureDiff))
  170.         print()
  171.         print("Reactor output : "..outputFlow)
  172.         print()
  173.         print()
  174.         print("Previous containment field : ".. string.format("%.3f",previousReactorInfo.shield_charge).. "  ".. string.format("%.2f",((previousReactorInfo.shield_charge)/previousReactorInfo.max_shield_charge)*100).."%")
  175.         print("Current containment field  : ".. string.format("%.3f",currentReactorInfo.shield_charge).. "  ".. string.format("%.2f",((currentReactorInfo.shield_charge)/currentReactorInfo.max_shield_charge)*100).."%")
  176.         print()
  177.         print("Reactor input : "..inputFlow)
  178.         print()
  179.         print()
  180.         print("Fuel : "..string.format("%.3f",currentReactorInfo.converted_fuel).." / "..currentReactorFuelTotal.."  "..string.format("%.3f",currentReactorInfo.converted_fuel/currentReactorFuelTotal*100) .."%")
  181.         print("Fuel conversion rate : "..string.format("%.3f",currentReactorInfo.fuel_use_rate * 1000).." nb/t")
  182.     end
  183. end
  184.  
  185.  
  186.  
  187. local function MainReactorLoop()
  188.     previousReactorInfo = currentReactorInfo
  189.     currentReactorInfo = GetReactorData()
  190.     if next(currentReactorInfo) == nil then
  191.         return
  192.     end
  193.  
  194.     if previousReactorInfo ~= nil and previousReactorInfo.temperature == nil then
  195.         return
  196.     end
  197.     if previousReactorInfo ~= nil then
  198.         --print ("has Reactor info")
  199.         temperatureDiff = currentReactorInfo.temperature - previousReactorInfo.temperature
  200.         outputDiff = (1-(currentReactorInfo.temperature/desiredTemp))
  201.  
  202.         if previousReactorInfo.reactor_state ~= 2 and currentReactorInfo.reactor_state == 2 then
  203.         -- this will happen only once
  204.             --print ("started heating Up")
  205.             currentReactorFuelTotal = math.floor((currentReactorInfo.reactable_fuel or 0) + (currentReactorInfo.converted_fuel or 0)+0.5)
  206.             startingReactorOutput = currentReactorFuelTotal / maxReactorFuelTotal * baseReactorIO
  207.             SetNewReactorOutput(0,true)
  208.             SetNewReactorInput(10000000)
  209.         elseif previousReactorInfo.reactor_state == 2 and currentReactorInfo.reactor_state == 2 then
  210.         ---injecting 10M into reactor
  211.         --- maybe try to start reactor
  212.             ---reactor.activateReactor()
  213.  
  214.         elseif previousReactorInfo.reactor_state ~= 3 and currentReactorInfo.reactor_state == 3 then
  215.         -- this will happen only once
  216.            -- print ("Started Running")
  217.             SetNewReactorOutput(0,true)
  218.             UpdateReactorInput()
  219.         elseif previousReactorInfo.reactor_state == 3 and currentReactorInfo.reactor_state == 3 then
  220.             if currentReactorInfo.converted_fuel / currentReactorFuelTotal >= fuelShutdownLevel then
  221.                 --We are shutting reactor down
  222.                 SetNewReactorOutput(0)
  223.             else
  224.                 ReactorRunning()
  225.             end
  226.             UpdateReactorInput()
  227.         elseif currentReactorInfo.reactor_state >= 4 then
  228.             UpdateReactorInput()
  229.         end
  230.     elseif previousReactorInfo == nil and currentReactorInfo.reactor_state ~= 1 then
  231.         --we are starting program with reactor already running
  232.         if currentReactorInfo.reactor_state <= 3 then
  233.             currentReactorFuelTotal = math.floor((currentReactorInfo.reactable_fuel or 0) + (currentReactorInfo.converted_fuel or 0)+0.5)
  234.             startingReactorOutput = currentReactorFuelTotal / maxReactorFuelTotal * baseReactorIO
  235.             if currentReactorInfo.reactor_state == 2 then
  236.                 SetNewReactorInput(10000000)
  237.             else
  238.                 UpdateReactorInput()
  239.             end
  240.             SetNewReactorOutput(outputFlowGate.getSignalLowFlow(value),true)
  241.         end
  242.     end
  243.     DisplayReactorStats()
  244. end
  245.  
  246. InitalizeReactorComponents();
  247.  
  248. repeat
  249.     MainReactorLoop()
  250.     sleep(0.05)
  251. until (false)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement