Hiranus icon

DraconicEvolution Reactor Automation

Hiranus | PRO | 02/24/22 07:38:22 AM UTC (Edited) | 0 ⭐ | 1306 👁️ | Never ⏰ | []
Lua |

9.46 KB

|

None

|

0 👍

/

0 👎

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)

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎