local reactorCardId = 0 local desiredTemp = 7995 local allowedTempDifference = 5 local baseReactorIO = 1500000 local reactorHeatUpSpeedMultipler = 2 local maxReactorFuelTotal = 10368 local shieldDesiredPower = 0.10 local shieldMaxInputMultipler = 50 local fuelShutdownLevel = 0.9 local reactor = nil local variableStore = nil local outputFlowGate = nil local outputFlow = 0 local inputFlowGate = nil local inputFlow = 0 local previousReactorInfo = nil local currentReactorInfo = nil local startingReactorOutput = 0 local currentReactorFuelTotal = 0 local temperatureDiff = 0 local outputDiff = 0 local lastOutputUpdateTicksAgo = 0 local desiredTempMin = desiredTemp - allowedTempDifference local desiredTempMax = desiredTemp + allowedTempDifference local function CheckNumberBetween(min,max,val) return min < val and max > val end local reactorStates = { "Off", "Charging", "Running", "Stopping", "Cooling Down", "Exploding" } reactorStates[0] = reactorStates[1] --fix for not initalized reactor local function SetNewReactorOutput(value,forceNewValue) if value < 0 then value = 0 end value = math.ceil(value) if forceNewValue ~= true then local gateNum = outputFlowGate.getSignalLowFlow() if outputFlow ~= gateNum then ---To allow manual number override value = gateNum end end lastOutputUpdateTicksAgo = 0 outputFlow = value outputFlowGate.setSignalLowFlow(value) end local function SetNewReactorInput(value) if value < 0 or value ~= value then value = 0 end value = math.ceil(value) inputFlow = value inputFlowGate.setSignalLowFlow(value) end local function ShieldTooLowFix() local shieldPercent = currentReactorInfo.shield_charge/currentReactorInfo.max_shield_charge return 1 + math.max(shieldMaxInputMultipler * ((shieldDesiredPower - shieldPercent)/shieldDesiredPower),0) end local function UpdateReactorInput() local newShield = currentReactorInfo.field_drain + (currentReactorInfo.field_drain * shieldDesiredPower) newShield = newShield * ShieldTooLowFix() SetNewReactorInput(newShield) end local function GetReactorData() return variableStore.read(reactorCardId).value.v end local function InitalizeReactorComponents() local sucessfulInitialization = true repeat if sucessfulInitialization == false then sleep(0.05) term.clear() term.setCursorPos(1,1) end sucessfulInitialization = true local deviceList = peripheral.getNames() local flowGates = {} for i = 1, #deviceList do local device = peripheral.getType(deviceList[i]) if device == "draconic_reactor" then reactor = peripheral.wrap(deviceList[i]) elseif device == "variableStore" then variableStore = peripheral.wrap(deviceList[i]) elseif device == "flow_gate" then flowGates[#flowGates + 1] = peripheral.wrap(deviceList[i]) end end if #flowGates ~= 2 then print("You need exactly 2 flow gates") sucessfulInitialization = false else for i = 1, #flowGates do local gate = flowGates[i] if gate.getSignalHighFlow() == 0 then inputFlowGate = gate elseif gate.getSignalHighFlow() == 1 then outputFlowGate = gate end end end if outputFlowGate == nil or inputFlowGate == nil then print("At Least one flow gate is missing configuration. Please set in \"Redstone Signal Hgh\":"); print("0 : Input") print("1 : Output") sucessfulInitialization = false; end if reactor == nil then -- error("Reactor is missing"); end if variableStore == nil then print("Variable Store is missing"); sucessfulInitialization = false; end until (sucessfulInitialization) end local function ReactorRunning() lastOutputUpdateTicksAgo = lastOutputUpdateTicksAgo + 1 if previousReactorInfo ~= nil then local newFlowDiff = math.ceil(outputDiff/2 * startingReactorOutput) local newOutputFlow = math.ceil(outputFlow+newFlowDiff) local maxAllowedTemp = desiredTemp + allowedTempDifference local mult = 1 - (math.sin((maxAllowedTemp - currentReactorInfo.temperature) / (allowedTempDifference * 2) * math.pi)^128) if CheckNumberBetween(desiredTempMin,desiredTempMax,currentReactorInfo.temperature) then if math.abs(temperatureDiff)>0.05 then return end if math.abs(desiredTemp - currentReactorInfo.temperature) < lastOutputUpdateTicksAgo then SetNewReactorOutput(outputFlow + (outputDiff*startingReactorOutput) * mult) end elseif ((currentReactorInfo.temperature < desiredTemp - allowedTempDifference and outputDiff*reactorHeatUpSpeedMultipler > temperatureDiff) or (currentReactorInfo.temperature > desiredTemp + allowedTempDifference)) and lastOutputUpdateTicksAgo > 10 then SetNewReactorOutput(newOutputFlow) end end end local function DisplayReactorStats() term.clear() term.setCursorPos(1,1) if previousReactorInfo ~= nil then print("Reactor state : ".. reactorStates[currentReactorInfo.reactor_state]) print() print("Previous temperature : "..string.format("%.5f",(previousReactorInfo.temperature))) print("Current temperature : "..string.format("%.5f",currentReactorInfo.temperature)) print() print("Temperature difference : "..string.format("%.6f",temperatureDiff)) print() print("Reactor output : "..outputFlow) print() print() print("Previous containment field : ".. string.format("%.3f",previousReactorInfo.shield_charge).. " ".. string.format("%.2f",((previousReactorInfo.shield_charge)/previousReactorInfo.max_shield_charge)*100).."%") print("Current containment field : ".. string.format("%.3f",currentReactorInfo.shield_charge).. " ".. string.format("%.2f",((currentReactorInfo.shield_charge)/currentReactorInfo.max_shield_charge)*100).."%") print() print("Reactor input : "..inputFlow) print() print() print("Fuel : "..string.format("%.3f",currentReactorInfo.converted_fuel).." / "..currentReactorFuelTotal.." "..string.format("%.3f",currentReactorInfo.converted_fuel/currentReactorFuelTotal*100) .."%") print("Fuel conversion rate : "..string.format("%.3f",currentReactorInfo.fuel_use_rate * 1000).." nb/t") end end local function MainReactorLoop() previousReactorInfo = currentReactorInfo currentReactorInfo = GetReactorData() if next(currentReactorInfo) == nil then return end if previousReactorInfo ~= nil and previousReactorInfo.temperature == nil then return end if previousReactorInfo ~= nil then --print ("has Reactor info") temperatureDiff = currentReactorInfo.temperature - previousReactorInfo.temperature outputDiff = (1-(currentReactorInfo.temperature/desiredTemp)) if previousReactorInfo.reactor_state ~= 2 and currentReactorInfo.reactor_state == 2 then -- this will happen only once --print ("started heating Up") currentReactorFuelTotal = math.floor((currentReactorInfo.reactable_fuel or 0) + (currentReactorInfo.converted_fuel or 0)+0.5) startingReactorOutput = currentReactorFuelTotal / maxReactorFuelTotal * baseReactorIO SetNewReactorOutput(0,true) SetNewReactorInput(10000000) elseif previousReactorInfo.reactor_state == 2 and currentReactorInfo.reactor_state == 2 then ---injecting 10M into reactor --- maybe try to start reactor ---reactor.activateReactor() elseif previousReactorInfo.reactor_state ~= 3 and currentReactorInfo.reactor_state == 3 then -- this will happen only once -- print ("Started Running") SetNewReactorOutput(0,true) UpdateReactorInput() elseif previousReactorInfo.reactor_state == 3 and currentReactorInfo.reactor_state == 3 then if currentReactorInfo.converted_fuel / currentReactorFuelTotal >= fuelShutdownLevel then --We are shutting reactor down SetNewReactorOutput(0) else ReactorRunning() end UpdateReactorInput() elseif currentReactorInfo.reactor_state >= 4 then UpdateReactorInput() end elseif previousReactorInfo == nil and currentReactorInfo.reactor_state ~= 1 then --we are starting program with reactor already running if currentReactorInfo.reactor_state <= 3 then currentReactorFuelTotal = math.floor((currentReactorInfo.reactable_fuel or 0) + (currentReactorInfo.converted_fuel or 0)+0.5) startingReactorOutput = currentReactorFuelTotal / maxReactorFuelTotal * baseReactorIO if currentReactorInfo.reactor_state == 2 then SetNewReactorInput(10000000) else UpdateReactorInput() end SetNewReactorOutput(outputFlowGate.getSignalLowFlow(value),true) end end DisplayReactorStats() end InitalizeReactorComponents(); repeat MainReactorLoop() sleep(0.05) until (false)