Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local event,term,os,computer,com,unicode,keyb,gpu =
- require("event"),require("term"),require("os"),require("computer"),
- require("component"),require("unicode"),require("keyboard"),
- require("component").gpu
- local reactorsFile = "/home/reactors.txt"
- local cfgName = "/home/DracReactorConfig.cfg"
- local MAX_REACTORS = 5
- local CHARGE_FLOW = 535000
- local CHARGE_DURATION = 12
- local autostateByAdr = {}
- local flowInitByAdr = {}
- local chargeRequestByAdr = {}
- local cfg = {}
- local DEFAULT_CONFIG = [[
- -- Интервалы для кнопок +/-
- default_interval = 1000
- ctrl_interval = 5000
- shift_interval = 10000
- ctrlShift_interval = 20000
- -- Автономный режим:
- -- Основные константы
- shield = 25 - Щиты будут автоматически поддерживаться
- на этом уровне ( в %)
- tempCriticalEdge = 8100 -- Если температура превысит это
- -- значение, программа экстренно понизит поток вывода;
- -- Форсированный режим
- forceModeTempLowEdge = 7500 -- Пока температура не превысит
- -- это значение, программа будет работать в форсированном
- -- режиме, иначе - перейдет в безопасный режим;
- forceModeStepCase = 5000 -- Если разница между текущей
- -- выработкой энергии и выставленным потоком превысит это
- -- значение, то к потоку добавится
- forceModeStep = 20000 -- это значение
- -- безопасный режим
- safeModeTempWaitEdge = 8000 -- Если температура превысит это
- -- значение, программа будет ожидать,
- safeModeTempToWaitEdge = 7850 -- пока температура не
- -- понизится до этого значения;
- safeModeStepCase = 0 -- Если разница между текущей
- -- выработкой энергии и выставленным потоком превысит это
- -- значение, то к потоку добавится
- safemodeStep = 8000 -- это значение
- autoProtectTempEdge = 8300 -- При достижении этой
- -- температуры включается автономный режим
- screen_w = 80 -- Ширина экрана
- screen_h = 25 -- Высота экрана
- fuelStopPct = 98 -- % топлива, при котором реактор выключается]]
- local function parseNum(s)
- local n = ""
- for i = 1, #s do
- local c = s:byte(i, i)
- if c >= 48 and c <= 57 or c == 46 then
- n = n .. string.char(c)
- end
- end
- return n ~= "" and tonumber(n) or n
- end
- local confnames = {
- "default_interval", "ctrl_interval", "shift_interval",
- "ctrlShift_interval", "shield", "tempCriticalEdge",
- "forceModeTempLowEdge", "forceModeStepCase", "forceModeStep",
- "safeModeTempWaitEdge", "safeModeTempToWaitEdge",
- "safeModeStepCase", "safemodeStep", "autoProtectTempEdge",
- "screen_w", "screen_h", "fuelStopPct"
- }
- local function readConfig(n)
- local f = io.open(n, "r")
- if not f then return nil end
- local t = {}
- for l in f:lines() do
- local k, v = l:match("^%s*([%w_]+)%s*=%s*([%d%.]+)")
- if k and v then t[k] = tonumber(v) end
- end
- f:close()
- return t
- end
- local function hasConfigKeys(p)
- if not p then return false end
- for i = 1, #confnames do
- if p[confnames[i]] == nil then return false end
- end
- return true
- end
- local function readParse(n)
- local f = io.open(n, "r")
- if f then
- local t = {}
- local i = 1
- while true do
- local s = f:read("*l")
- if not s then break end
- if parseNum(s) ~= "" then
- t[i] = parseNum(s)
- i = i + 1
- end
- end
- f:close()
- return t
- else
- return false
- end
- end
- local function writeText(n, t)
- local f = io.open(n, "w")
- f:write(t)
- f:close()
- end
- local function configWrite(n)
- local p = readConfig(n)
- if not p or not hasConfigKeys(p) then
- writeText(n, DEFAULT_CONFIG)
- return
- end
- if cfg.default_interval and cfg.ctrl_interval and
- cfg.shift_interval and cfg.ctrlShift_interval and
- cfg.shield and cfg.tempCriticalEdge and
- cfg.forceModeTempLowEdge and cfg.forceModeStepCase and
- cfg.forceModeStep and cfg.safeModeTempWaitEdge and
- cfg.safeModeTempToWaitEdge and cfg.safeModeStepCase and
- cfg.safemodeStep and cfg.autoProtectTempEdge and
- cfg.screen_w and cfg.screen_h and cfg.fuelStopPct then
- writeText(n, string.format([[
- default_interval = %d
- ctrl_interval = %d
- shift_interval = %d
- ctrlShift_interval = %d
- shield = %0.2f
- tempCriticalEdge = %d
- forceModeTempLowEdge = %d
- forceModeStepCase = %d
- forceModeStep = %d
- safeModeTempWaitEdge = %d
- safeModeTempToWaitEdge = %d
- safeModeStepCase = %d
- safemodeStep = %d
- autoProtectTempEdge = %d
- screen_w = %d
- screen_h = %d
- fuelStopPct = %d]],
- cfg.default_interval, cfg.ctrl_interval,
- cfg.shift_interval, cfg.ctrlShift_interval,
- cfg.shield, cfg.tempCriticalEdge,
- cfg.forceModeTempLowEdge, cfg.forceModeStepCase,
- cfg.forceModeStep, cfg.safeModeTempWaitEdge,
- cfg.safeModeTempToWaitEdge, cfg.safeModeStepCase,
- cfg.safemodeStep, cfg.autoProtectTempEdge,
- cfg.screen_w, cfg.screen_h, cfg.fuelStopPct)
- )
- end
- end
- local function makeConfig(t, t2)
- local c = {}
- for i = 1, #t do
- c[tostring(t[i])] = t2[i]
- end
- return c
- end
- local function listAddresses(t)
- local l = {}
- for a in com.list(t) do
- l[#l + 1] = a
- end
- return l
- end
- local function readReactorsFile()
- local f = io.open(reactorsFile, "r")
- if not f then return nil end
- local l = {}
- for line in f:lines() do
- local r, u, d = line:match("(%S+)%s+(%S+)%s+(%S+)")
- if r and u and d then
- l[#l + 1] = {reactorAdr = r, upAdr = u, downAdr = d}
- end
- end
- f:close()
- return #l > 0 and l or nil
- end
- local function writeReactorsFile(l)
- local f = io.open(reactorsFile, "w")
- for i = 1, #l do
- f:write(string.format("%s %s %s\n",
- l[i].reactorAdr, l[i].upAdr, l[i].downAdr))
- end
- f:close()
- end
- local function validEntry(e)
- return com.get(e.reactorAdr) and com.get(e.upAdr) and
- com.get(e.downAdr)
- end
- local function mergeEntries(e)
- local usedReactors, usedGates = {}, {}
- for i = 1, #e do
- usedReactors[e[i].reactorAdr] = true
- usedGates[e[i].upAdr] = true
- usedGates[e[i].downAdr] = true
- end
- local reactorsList = listAddresses("draconic_reactor")
- local gates = listAddresses("flux_gate")
- local freeReactors, freeGates = {}, {}
- for i = 1, #reactorsList do
- if not usedReactors[reactorsList[i]] then
- freeReactors[#freeReactors + 1] = reactorsList[i]
- end
- end
- for i = 1, #gates do
- if not usedGates[gates[i]] then
- freeGates[#freeGates + 1] = gates[i]
- end
- end
- local addCount = math.min(#freeReactors,
- math.floor(#freeGates / 2), MAX_REACTORS - #e)
- for i = 1, addCount do
- e[#e + 1] = {
- reactorAdr = freeReactors[i],
- upAdr = freeGates[(i - 1) * 2 + 1],
- downAdr = freeGates[(i - 1) * 2 + 2]
- }
- end
- return e
- end
- local function buildReactors()
- newEntriesAdded = false
- lastAddedReactorAdr = nil
- local entries = readReactorsFile()
- local currentReactors = reactors or {}
- if entries then
- local valid = {}
- for i = 1, #entries do
- if validEntry(entries[i]) then
- valid[#valid + 1] = entries[i]
- end
- end
- if #valid > 0 then entries = valid end
- end
- if entries and #entries > 0 and
- #listAddresses("draconic_reactor") > #entries then
- newEntriesAdded = true
- end
- if not entries or #entries == 0 then return nil end
- local oldByAdr = {}
- for i = 1, #currentReactors do
- oldByAdr[currentReactors[i].reactorAdr] = currentReactors[i]
- end
- local reactors = {}
- for i = 1, #entries do
- local e = entries[i]
- local old = oldByAdr[e.reactorAdr]
- reactors[i] = {
- index = i,
- reactorAdr = e.reactorAdr,
- upAdr = e.upAdr,
- downAdr = e.downAdr,
- reactor = com.proxy(com.get(e.reactorAdr)),
- upgate = com.proxy(com.get(e.upAdr)),
- downgate = com.proxy(com.get(e.downAdr)),
- maxGenerationRate = old and old.maxGenerationRate or 0,
- autostate = old and old.autostate or
- (autostateByAdr[e.reactorAdr] ~= nil and
- autostateByAdr[e.reactorAdr] or false),
- temprise = old and old.temprise or false,
- flowInit = old and old.flowInit or
- (flowInitByAdr[e.reactorAdr] ~= nil and
- flowInitByAdr[e.reactorAdr] or false),
- chargeRequested = old and old.chargeRequested or
- (chargeRequestByAdr[e.reactorAdr] or 0),
- lastTemp = nil,
- row = {},
- powerBtn = {},
- tab = {}
- }
- if not old then lastAddedReactorAdr = e.reactorAdr end
- end
- return reactors
- end
- configWrite(cfgName)
- cfg = readConfig(cfgName) or makeConfig(confnames, readParse(cfgName))
- local reactors = {}
- local activeIndex = 1
- local summaryProfitCord = {}
- local summaryEuCord = {}
- local summaryShieldCord = {}
- local summaryGenCord = {}
- local summaryMaxProfitCord = {}
- local maxSummaryProfit = 0
- local newEntriesAdded = false
- local pendingActiveReactorAdr = nil
- local color = {
- red = 0xFF0000, green = 0x00FF00, yellow = 0xFFD166,
- skyblue = 0x4FC3F7, black = 0x0F1115, grey = 0x0F1115,
- panel = 0x1A1F27, blue = 0x4FC3F7, orange = 0xFF9800,
- white = 0xE6EDF3, dark = 0x242B36, dim = 0x7A8599
- }
- local rback = gpu.getBackground()
- local rfore = gpu.getForeground()
- local chatBox = nil
- local handleMain, handleOptions, handleStart, screenAssign
- local screenOverview, assignMode, firstStartCompleted
- local assignState, assignUi, autoStopped, autoWaitTempByAdr
- local chargeRequestByAdr, autoStoppedCord, chargeHintDismissed
- local chargeHint
- local easyAssign = {
- active = false, step = "reactor", index = 1,
- core = nil, shield = nil, output = nil, saved = false,
- message = nil, heavyBtn = {}, easyBtn = {},
- continueBtn = {}, finishBtn = {}, backBtn = {},
- known = {}, lastChatStep = nil, lastChatMessage = nil
- }
- assignState = {
- reactorIndex = nil, reactorAdr = nil,
- shieldGateIdx = nil, shieldGateAdr = nil,
- outGateIdx = nil, outGateAdr = nil,
- step = "reactor", message = nil
- }
- assignUi = {
- reactors = {}, gates = {}, gateAddrs = {},
- reactorAddrs = {}, gateUse = {}, selectedAdr = nil,
- back = {x = nil, y = nil, w = 0}
- }
- autoStopped = {}
- autoWaitTempByAdr = {}
- chargeRequestByAdr = {}
- autoStoppedCord = {x = nil, y = nil}
- chargeHintDismissed = false
- chargeHint = {x = nil, y = nil, w = 0, visible = false}
- local menuItem = {
- options = {name = "Настройки |", x = 1, y = 2},
- save = {name = "Сохранить |", x = 1, y = 2},
- cancel = {name = " Отменить |", x = 12, y = 2},
- overview = {name = "Главный |", x = 1, y = 2},
- refresh = {name = "Обновить |", x = 1, y = 2},
- gates = {name = "Гейты |", x = 1, y = 2},
- back = {name = "Назад |", x = 1, y = 2},
- reset = {name = "Сброс |", x = 1, y = 2},
- optionsBack = {name = " Назад |", x = 1, y = 2}
- }
- -- !!! ВАЖНО: Определяем screenW и screenH ДО их использования !!!
- local xz, yz = gpu.maxResolution()
- local screenW = math.min(120, xz)
- local screenH = math.min(40, yz)
- gpu.setResolution(screenW, screenH)
- gpu.setBackground(color.grey)
- gpu.setForeground(color.white)
- local prog = true
- local ops = true
- local canedit = true
- local canclose = true
- local temprise = false
- local autostate = false
- local maxGenerationRate = 0
- local lastDetailUpdate = 0
- local lastOverviewUpdate = 0
- local OptionDefault = {value = cfg.default_interval}
- local OptionCtrl = {value = cfg.ctrl_interval}
- local OptionShift = {value = cfg.shift_interval}
- local OptionCtrlShift = {value = cfg.ctrlShift_interval}
- local OptionShield = {value = cfg.shield}
- local OptionFuelStop = {value = cfg.fuelStopPct or 98}
- local infcord = {}
- for _, f in ipairs({
- "status", "temp", "generation", "maxgen", "flow",
- "puregen", "drain", "fstrth", "esturn", "fuel",
- "fuelconv", "core"
- }) do
- infcord[f] = {value = nil, x = nil, y = nil}
- end
- local button = {
- continue = {name = "Продолжить", x = nil, y = nil},
- change = {name = "Изменить", x = nil, y = nil},
- add = {name = " + ", x = nil, y = nil},
- sub = {name = " - ", x = nil, y = nil},
- start = {name = " [PWR] ЗАПУСК ", x = nil, y = nil,
- visible = nil},
- stop = {name = " [PWR] СТОП ", x = nil, y = nil,
- visible = nil},
- charge = {name = "Зарядить реактор ", x = nil, y = nil,
- visible = nil},
- autoon = {name = "[ON] ", x = nil, y = nil},
- autooff = {name = "[OFF]", x = nil, y = nil}
- }
- local function textWidth(s)
- local ok, len = pcall(unicode.len, s)
- return ok and len or #s
- end
- printf = function(s, ...)
- return io.write(s:format(...))
- end
- local function guiWrite(x, y, cf, cb, s, ...)
- term.setCursor(x, y)
- local fg, bg = gpu.getForeground(), gpu.getBackground()
- if cf >= 0 and cb >= 0 then
- gpu.setForeground(cf)
- gpu.setBackground(cb)
- printf(s, ...)
- gpu.setForeground(fg)
- gpu.setBackground(bg)
- elseif cb < 0 and cf >= 0 then
- gpu.setForeground(cf)
- printf(s, ...)
- gpu.setForeground(fg)
- elseif cf < 0 and cb >= 0 then
- printf(s, ...)
- gpu.setBackground(bg)
- else
- gpu.setForeground(color.white)
- printf(s, ...)
- gpu.setForeground(fg)
- end
- end
- local function getCord(p)
- p.x, p.y = term.getCursor()
- return p.x, p.y
- end
- local function guiClear(y)
- local fg, bg = gpu.getForeground(), gpu.getBackground()
- gpu.setForeground(color.white)
- gpu.setBackground(color.grey)
- for i = y + 3, 3, -1 do
- term.setCursor(1, i)
- term.clearLine()
- end
- gpu.setForeground(fg)
- gpu.setBackground(bg)
- end
- local function setActive(i)
- if not reactors[i] then return end
- activeIndex = i
- reactor = reactors[i].reactor
- upgate = reactors[i].upgate
- downgate = reactors[i].downgate
- autostate = reactors[i].autostate
- temprise = reactors[i].temprise
- maxGenerationRate = reactors[i].maxGenerationRate
- end
- local function syncActive()
- if reactors[activeIndex] then
- reactors[activeIndex].autostate = autostate
- reactors[activeIndex].temprise = temprise
- reactors[activeIndex].maxGenerationRate = maxGenerationRate
- end
- end
- local function drawHeader(t)
- local x = gpu.getResolution()
- gpu.setBackground(color.grey)
- gpu.setForeground(color.white)
- term.clear()
- gpu.setBackground(color.panel)
- gpu.setForeground(color.white)
- term.clearLine()
- printf(" %s", t)
- gpu.setForeground(color.green)
- printf(" | Разработал : GintaRus")
- gpu.setForeground(color.white)
- printf("\n")
- gpu.setBackground(color.grey)
- gpu.setForeground(color.white)
- term.clearLine()
- gpu.setBackground(0xFF0000)
- gpu.set(x - 2, 1, " X ")
- gpu.setBackground(color.grey)
- gpu.setForeground(color.white)
- return x
- end
- local function drawSeparator(x)
- gpu.setBackground(color.grey)
- gpu.setForeground(color.dim)
- gpu.fill(1, 3, x, 1, "-")
- gpu.setBackground(color.grey)
- gpu.setForeground(color.white)
- term.setCursor(1, 4)
- end
- local function makeButton(x, y, t)
- term.setCursor(x, y)
- local fg, bg = gpu.getForeground(), gpu.getBackground()
- gpu.setBackground(color.blue)
- gpu.setForeground(color.white)
- printf(t)
- gpu.setBackground(bg)
- gpu.setForeground(fg)
- end
- local function makePowerButton(x, y, t, bg, fg)
- term.setCursor(x, y)
- local rfg, rbg = gpu.getForeground(), gpu.getBackground()
- gpu.setBackground(bg)
- gpu.setForeground(fg)
- printf(t)
- gpu.setBackground(rbg)
- gpu.setForeground(rfg)
- end
- local function getGateFlow(g)
- if not g then return 0 end
- local ok, v = pcall(g.getSignalLowFlow)
- if ok and type(v) == "number" then return v end
- local ok2, v2 = pcall(g.getFlow)
- if ok2 and type(v2) == "number" then return v2 end
- return 0
- end
- local function isComponentAlive(a)
- return a and com.get(a) ~= nil
- end
- local function ensureFlowInit(r, force)
- if not r or (r.flowInit and not force) then return end
- pcall(r.upgate.setSignalLowFlow, r.upgate, CHARGE_FLOW)
- r.flowInit = true
- flowInitByAdr[r.reactorAdr] = true
- if reactors[activeIndex] and
- reactors[activeIndex].reactorAdr == r.reactorAdr then
- infcord.flow.value = CHARGE_FLOW
- if handleMain and infcord.flow.x then
- guiWrite(infcord.flow.x, infcord.flow.y,
- color.red, color.grey, "%s",
- numformat(infcord.flow.value))
- end
- end
- end
- local function canChargeStatus(s)
- return s == "offline" or s == "stopping" or s == "cold" or
- s == "cooling" or s == "warming_up"
- end
- local function statusText(s)
- if s == "online" then return "ВКЛ"
- elseif s == "offline" then return "ВЫК"
- elseif s == "charging" then return "ЗАР"
- elseif s == "charged" then return "ГОТ"
- elseif s == "stopping" then return "СТП"
- elseif s == "cold" then return "ХОЛ"
- elseif s == "cooling" then return "ОСТ"
- elseif s == "warming_up" then return "РАЗ"
- else return s end
- end
- local function show(fc, bc, p)
- local fg, bg = gpu.getForeground(), gpu.getBackground()
- term.setCursor(p.x, p.y)
- gpu.setForeground(fc)
- gpu.setBackground(bc)
- local st = " "
- for i = 0, #tostring(p.value) do st = st .. " " end
- gpu.set(p.x, p.y, st)
- printf("%d", p.value)
- gpu.setForeground(fg)
- gpu.setBackground(bg)
- end
- local function numformat(n)
- local s = tostring(n)
- if n >= 1000 and n < 1000000 then
- return s:sub(1, #s - 3) .. " " .. s:sub(#s - 2) .. " "
- elseif n >= 1000000 then
- return s:sub(1, #s - 6) .. " " ..
- s:sub(#s - 5, #s - 3) .. " " ..
- s:sub(#s - 2) .. " "
- else
- return s .. " "
- end
- end
- local function overviewCols(x)
- local c = x >= 120 and
- {status = 6, temp = 15, fuel = 27, profit = 43,
- gen = 60, flow = 77} or
- {status = 5, temp = 11, fuel = 20, profit = 33,
- gen = 48, flow = 63}
- local ctrl = math.max(c.flow + 12, 65)
- if ctrl + 16 > x then ctrl = math.max(65, x - 16) end
- c.ctrl = ctrl
- return c
- end
- local function coreformat()
- local n = com.draconic_rf_storage.getEnergyStored()
- if n > 10^12 then
- return string.format(" Накоплено в ядре: %0.3f T \n",
- n / 10^12)
- elseif n > 10^9 then
- return string.format(" Накоплено в ядре: %0.3f B \n",
- n / 10^9)
- elseif n > 10^6 then
- return string.format(" Накоплено в ядре: %0.3f M \n",
- n / 10^6)
- elseif n > 10^3 then
- return string.format(" Накоплено в ядре: %0.3f K \n",
- n / 10^3)
- else
- return string.format(" Накоплено в ядре: %d \n", n)
- end
- end
- local function checkButtons()
- local ok, inf = pcall(reactor.getReactorInfo)
- if not ok or type(inf) ~= "table" then return end
- infcord.status.value = inf.status
- button.start.visible = false
- button.stop.visible = false
- button.charge.visible = false
- if canChargeStatus(infcord.status.value) then
- guiWrite(button.charge.x, button.charge.y,
- color.skyblue, color.black, "%s", button.charge.name)
- button.charge.visible = true
- elseif infcord.status.value == "charged" then
- guiWrite(button.start.x, button.start.y,
- color.green, color.black, "%s", button.start.name)
- button.start.visible = true
- guiWrite(button.stop.x, button.stop.y,
- color.red, color.black, "%s", button.stop.name)
- button.stop.visible = true
- elseif infcord.status.value == "online" or
- infcord.status.value == "charging" then
- guiWrite(button.stop.x, button.stop.y,
- color.red, color.black, "%s", button.stop.name)
- button.stop.visible = true
- elseif infcord.status.value == "stopping" and
- (inf.energySaturation / inf.maxEnergySaturation) * 100 >= 50
- and (inf.fieldStrength / inf.maxFieldStrength) * 100 >= 50
- and inf.temperature > 2000 then
- guiWrite(button.start.x, button.start.y,
- color.green, color.black, "%s", button.start.name)
- button.start.visible = true
- end
- end
- local function screenStart()
- handleMain = false
- handleOptions = false
- handleStart = true
- local x = drawHeader("HiTech Classic is the best (Preparation)")
- if not firstStartCompleted then
- printf("Эта страница для настройки программы при " ..
- "первом запуске или после сбоя")
- end
- drawSeparator(x)
- term.setCursor(1, screenH - 2)
- menuItem.gates.x, menuItem.gates.y = term.getCursor()
- gpu.setForeground(color.blue)
- printf(menuItem.gates.name)
- menuItem.gates.w = textWidth(menuItem.gates.name)
- gpu.setForeground(color.white)
- local hadFile = readReactorsFile() ~= nil
- while true do
- if not ops then return end
- reactors = buildReactors()
- if reactors and #reactors > 0 then
- setActive(1)
- firstStartCompleted = true
- if not hadFile then
- screenAssign()
- return
- end
- break
- end
- if not hadFile and
- #listAddresses("draconic_reactor") > 0 and
- #listAddresses("flux_gate") >= 2 then
- reactors = reactors or {}
- firstStartCompleted = true
- screenOverview()
- return
- end
- guiClear(2)
- printf("Подключите реакторы и флюкс-гейты " ..
- "(2 гейта на каждый реактор)\n")
- printf("Максимум: %d реакторов. Адреса можно " ..
- "сохранить в %s\n", MAX_REACTORS, reactorsFile)
- os.sleep(1)
- end
- end
- local function screenOptions()
- handleMain = false
- handleStart = false
- handleOptions = true
- handleOverview = false
- handleAssign = false
- canedit = true
- canclose = true
- local x = drawHeader("HiTech Classic is the best (Options)")
- menuItem.save.x, menuItem.save.y = term.getCursor()
- gpu.setForeground(color.blue)
- printf(menuItem.save.name)
- menuItem.save.w = textWidth(menuItem.save.name)
- menuItem.cancel.x, menuItem.cancel.y = term.getCursor()
- printf(menuItem.cancel.name)
- menuItem.cancel.w = textWidth(menuItem.cancel.name)
- menuItem.optionsBack.x, menuItem.optionsBack.y = term.getCursor()
- printf(menuItem.optionsBack.name)
- menuItem.optionsBack.w = textWidth(menuItem.optionsBack.name)
- gpu.setForeground(color.white)
- drawSeparator(x)
- local labels = {
- " Интервал для щелчка: ",
- " Интервал для CTRL: ",
- " Интервал для SHIFT: ",
- " Интервал для CTRL+SHIFT: ",
- " Уровень щитов: ",
- " Отключение по топливу (%%): "
- }
- local opts = {
- OptionDefault, OptionCtrl, OptionShift,
- OptionCtrlShift, OptionShield, OptionFuelStop
- }
- for i = 1, #labels do
- printf(labels[i])
- opts[i].x, opts[i].y = term.getCursor()
- printf("%d\n", opts[i].value)
- end
- end
- local function clearPromptLine()
- local _, y = term.getCursor()
- if y > 1 then
- term.setCursor(1, y - 1)
- term.clearLine()
- term.setCursor(1, y - 1)
- end
- end
- local function readIndex(prompt, max, used)
- while true do
- printf("%s", prompt)
- local input = term.read(false, false) or ""
- clearPromptLine()
- local num = tonumber(input:match("%d+"))
- if num and num >= 1 and num <= max and not used[num] then
- return num
- end
- printf("Неверный выбор, попробуйте снова.\n")
- end
- end
- local function readIndexAllowZero(prompt, max)
- while true do
- printf("%s", prompt)
- local input = term.read(false, false) or ""
- clearPromptLine()
- local lower = input:lower()
- if lower:find("назад") or lower:find("back") or
- lower:match("^b%s*$") then
- return -1
- end
- local num = tonumber(input:match("%d+"))
- if num and num >= 0 and num <= max then return num end
- printf("Неверный выбор, попробуйте снова.\n")
- end
- end
- local saveAssignedGates
- local function getChatBox()
- if chatBox then return chatBox end
- if com.isAvailable("chat_box") then
- chatBox = com.chat_box
- end
- return chatBox
- end
- local function chatSay(m, c)
- local b = getChatBox()
- if not b or not m then return false end
- if b.say and pcall(function() b.say(m) end) then
- return true
- end
- if b.sendMessage and pcall(function() b.sendMessage(m) end) then
- return true
- end
- if b.sendMessage and pcall(function()
- b.sendMessage(m, c or 64)
- end) then
- return true
- end
- return false
- end
- local function maybeChatSay(s, m, c)
- if s and easyAssign.lastChatStep ~= s then
- easyAssign.lastChatStep = s
- easyAssign.lastChatMessage = nil
- end
- if m and easyAssign.lastChatMessage ~= m then
- easyAssign.lastChatMessage = m
- chatSay(m, c)
- end
- end
- local function snapshotComponents(t)
- local l = {}
- for a in com.list(t) do
- l[#l + 1] = a
- end
- return l
- end
- local function initEasyKnown()
- easyAssign.known = {draconic_reactor = {}, flux_gate = {}}
- for _, a in ipairs(snapshotComponents("draconic_reactor")) do
- easyAssign.known.draconic_reactor[a] = true
- end
- for _, a in ipairs(snapshotComponents("flux_gate")) do
- easyAssign.known.flux_gate[a] = true
- end
- end
- local function findNewComponent(t)
- if not easyAssign.known or not easyAssign.known[t] then
- initEasyKnown()
- end
- for a in com.list(t) do
- if not easyAssign.known[t][a] then
- easyAssign.known[t][a] = true
- return a
- end
- end
- return nil
- end
- local function isAddressUsed(a)
- if not a then return false end
- local e = readReactorsFile() or {}
- for i = 1, #e do
- if e[i].reactorAdr == a or e[i].upAdr == a or
- e[i].downAdr == a then
- return true
- end
- end
- return false
- end
- local function clearAssignedByAdr(a)
- if not a then return false end
- local e = readReactorsFile() or {}
- local n, removed = {}, false
- for i = 1, #e do
- if e[i].reactorAdr ~= a then
- n[#n + 1] = e[i]
- else
- removed = true
- end
- end
- if removed then writeReactorsFile(n) end
- return removed
- end
- local function startEasyAssign()
- local e = readReactorsFile() or {}
- if #e >= MAX_REACTORS then
- easyAssign.active = false
- easyAssign.message = "Достигнут лимит реакторов."
- return
- end
- if not getChatBox() then
- easyAssign.active = false
- easyAssign.message = "Ошибка: для работы нужен chat_box."
- return
- end
- easyAssign.active = true
- easyAssign.step = "reactor"
- easyAssign.core = nil
- easyAssign.shield = nil
- easyAssign.output = nil
- easyAssign.saved = false
- easyAssign.message = nil
- easyAssign.index = #e + 1
- easyAssign.lastChatStep = nil
- easyAssign.lastChatMessage = nil
- initEasyKnown()
- maybeChatSay("intro", "Легкий режим: подключите адаптер " ..
- "к реактору #" .. tostring(easyAssign.index) ..
- " и смотрите монитор.")
- end
- local function screenAssignChoice()
- handleMain = false
- handleStart = false
- handleOptions = false
- handleOverview = false
- handleAssign = true
- local x = drawHeader("HiTech Classic is the best (Гейты)")
- drawSeparator(x)
- assignUi.reactors = {}
- assignUi.gates = {}
- assignUi.gateAddrs = {}
- assignUi.reactorAddrs = {}
- assignUi.gateUse = {}
- assignUi.selectedAdr = nil
- gpu.setBackground(color.grey)
- gpu.setForeground(color.white)
- gpu.fill(1, 4, x, 21, " ")
- term.setCursor(1, 2)
- menuItem.back.x, menuItem.back.y = term.getCursor()
- assignUi.back.x, assignUi.back.y, assignUi.back.w =
- menuItem.back.x, menuItem.back.y,
- textWidth(menuItem.back.name)
- gpu.setForeground(color.blue)
- printf(menuItem.back.name)
- menuItem.back.w = textWidth(menuItem.back.name)
- gpu.setForeground(color.white)
- term.setCursor(2, 5)
- printf("Выберите способ добавления гейтов:")
- local heavyLabel = " Тяжелый способ (анализатор) "
- local easyLabel = " Легкий способ (подключение) "
- easyAssign.heavyBtn = {x = 2, y = 7, w = textWidth(heavyLabel)}
- easyAssign.easyBtn = {x = 2, y = 9, w = textWidth(easyLabel)}
- guiWrite(2, 7, color.white, color.red, "%s", heavyLabel)
- guiWrite(2, 9, color.white, color.green, "%s", easyLabel)
- if easyAssign.message then
- guiWrite(2, 12, color.yellow, -1, "%s", easyAssign.message)
- end
- end
- local function screenAssignEasy()
- handleMain = false
- handleStart = false
- handleOptions = false
- handleOverview = false
- handleAssign = true
- local x = drawHeader("HiTech Classic is the best (Гейты - Легкий)")
- drawSeparator(x)
- gpu.setBackground(color.grey)
- gpu.setForeground(color.white)
- gpu.fill(1, 4, x, 21, " ")
- term.setCursor(1, 2)
- menuItem.back.x, menuItem.back.y = term.getCursor()
- easyAssign.backBtn = {
- x = menuItem.back.x, y = menuItem.back.y,
- w = textWidth(menuItem.back.name)
- }
- gpu.setForeground(color.blue)
- printf(menuItem.back.name)
- menuItem.back.w = textWidth(menuItem.back.name)
- gpu.setForeground(color.white)
- term.setCursor(2, 5)
- printf("РЕАКТОР #%d", easyAssign.index or 1)
- term.setCursor(2, 7)
- if easyAssign.step == "reactor" then
- guiWrite(2, 7, color.green, -1,
- "Подключите адаптер к ядру реактора.")
- maybeChatSay("reactor", "Подключите адаптер к ядру реактора.",
- 255)
- elseif easyAssign.step == "shield" then
- guiWrite(2, 7, color.green, -1,
- "Подключите адаптер к гейту ЩИТОВ.")
- maybeChatSay("shield", "Подключите адаптер к гейту ЩИТОВ.",
- 4096)
- elseif easyAssign.step == "output" then
- guiWrite(2, 7, color.green, -1,
- "Подключите адаптер к гейту ВЫВОДА.")
- maybeChatSay("output", "Подключите адаптер к гейту ВЫВОДА.",
- 16711680)
- elseif easyAssign.step == "done" then
- guiWrite(2, 7, color.green, -1, "Реактор добавлен.")
- maybeChatSay("done", "Реактор добавлен. Смотрите монитор.",
- 65280)
- end
- term.setCursor(2, 9)
- printf("Ожидаю компонент...")
- local infoY = 11
- local function displayStatus(label, value, isCurrent)
- local c = (isCurrent and easyAssign.step == label:lower()) and
- color.blue or (value and color.green or color.white)
- local offset = label == "Ядро" and 0 or
- label == "Щиты" and 1 or 2
- guiWrite(2, infoY + offset, c, -1, "%s: %s",
- label, value or "-")
- end
- displayStatus("Ядро", easyAssign.core, true)
- displayStatus("Щиты", easyAssign.shield, true)
- displayStatus("Вывод", easyAssign.output, true)
- if easyAssign.message then
- guiWrite(2, infoY + 4, color.yellow, -1, "%s",
- easyAssign.message)
- end
- if easyAssign.step == "done" then
- local contLabel = " [Продолжить] "
- local finLabel = " [Завершить] "
- easyAssign.continueBtn = {x = 2, y = infoY + 6,
- w = textWidth(contLabel)}
- easyAssign.finishBtn = {x = 2 + textWidth(contLabel) + 2,
- y = infoY + 6, w = textWidth(finLabel)}
- guiWrite(2, infoY + 6, color.white, color.green,
- "%s", contLabel)
- guiWrite(2 + textWidth(contLabel) + 2, infoY + 6,
- color.white, color.red, "%s", finLabel)
- end
- end
- local function screenAssignManual()
- handleMain = false
- handleStart = false
- handleOptions = false
- handleOverview = false
- handleAssign = true
- local x = drawHeader("HiTech Classic is the best (Гейты)")
- drawSeparator(x)
- assignUi.reactors = {}
- assignUi.gates = {}
- assignUi.gateAddrs = {}
- assignUi.reactorAddrs = {}
- assignUi.gateUse = {}
- assignUi.selectedAdr = nil
- gpu.setBackground(color.grey)
- gpu.setForeground(color.white)
- gpu.fill(1, 4, x, 21, " ")
- term.setCursor(1, 2)
- menuItem.back.x, menuItem.back.y = term.getCursor()
- assignUi.back.x, assignUi.back.y, assignUi.back.w =
- menuItem.back.x, menuItem.back.y,
- textWidth(menuItem.back.name)
- gpu.setForeground(color.blue)
- printf(menuItem.back.name)
- menuItem.back.w = textWidth(menuItem.back.name)
- gpu.setForeground(color.white)
- term.setCursor(2, 4)
- printf("Выберите реактор")
- local reactorsList = listAddresses("draconic_reactor")
- local gates = listAddresses("flux_gate")
- assignUi.gateAddrs = gates
- assignUi.reactorAddrs = reactorsList
- if #reactorsList == 0 or #gates < 2 then
- printf("Недостаточно реакторов или флюкс-гейтов.\n")
- os.sleep(1)
- screenOverview()
- return
- end
- local count = math.min(#reactorsList, MAX_REACTORS)
- term.setCursor(2, 5)
- printf("Реакторы:")
- for i = 1, count do
- term.setCursor(2, 5 + i)
- local label = string.format("%d) %s", i, reactorsList[i])
- local bg = assignState.reactorIndex == i and color.blue or -1
- local fg = assignState.reactorIndex == i and color.black or
- color.white
- guiWrite(2, 5 + i, fg, bg, "%s", label)
- assignUi.reactors[i] = {x = 2, y = 5 + i,
- w = textWidth(label)}
- end
- local entries = readReactorsFile() or {}
- local gateUse = {}
- for i = 1, #entries do
- gateUse[entries[i].upAdr] = entries[i].reactorAdr
- gateUse[entries[i].downAdr] = entries[i].reactorAdr
- end
- assignUi.gateUse = gateUse
- local selectedAdr = assignState.reactorIndex and
- reactorsList[assignState.reactorIndex] or nil
- assignUi.selectedAdr = selectedAdr
- local selectedEntry = nil
- if selectedAdr then
- for i = 1, #entries do
- if entries[i].reactorAdr == selectedAdr then
- selectedEntry = entries[i]
- break
- end
- end
- end
- assignUi.selectedEntry = selectedEntry
- term.setCursor(40, 5)
- printf("Гейты:")
- for i = 1, #gates do
- if i + 5 > 24 then break end
- term.setCursor(40, 5 + i)
- local label = string.format("%d) %s", i, gates[i])
- local c = color.dim
- if selectedAdr then
- if (selectedEntry and (gates[i] == selectedEntry.upAdr or
- gates[i] == selectedEntry.downAdr)) or
- assignState.shieldGateIdx == i or
- assignState.outGateIdx == i then
- c = color.green
- elseif gateUse[gates[i]] and
- gateUse[gates[i]] ~= selectedAdr then
- c = color.red
- end
- end
- guiWrite(40, 5 + i, c, -1, "%s", label)
- assignUi.gates[i] = {x = 40, y = 5 + i,
- w = textWidth(label)}
- end
- end
- local function screenAssign()
- if assignMode == "manual" then
- screenAssignManual()
- elseif assignMode == "easy" then
- screenAssignEasy()
- else
- screenAssignChoice()
- end
- end
- local function acceptEasyComponent(a, t)
- if easyAssign.step == "reactor" then
- if t ~= "draconic_reactor" then
- easyAssign.message = "Нужен draconic_reactor."
- screenAssignEasy()
- return
- end
- if isAddressUsed(a) then
- easyAssign.message = "Адрес уже используется."
- screenAssignEasy()
- return
- end
- easyAssign.core = a
- easyAssign.step = "shield"
- easyAssign.message = "Реактор принят."
- maybeChatSay("accepted", "Реактор принят. Смотри монитор.")
- screenAssignEasy()
- return
- end
- if easyAssign.step == "shield" then
- if t ~= "flux_gate" then
- easyAssign.message = "Нужен flux_gate."
- screenAssignEasy()
- return
- end
- if isAddressUsed(a) then
- easyAssign.message = "Адрес уже используется."
- screenAssignEasy()
- return
- end
- easyAssign.shield = a
- easyAssign.step = "output"
- easyAssign.message = "Гейт щитов принят."
- maybeChatSay("accepted", "Гейт щитов принят. Смотри монитор.")
- screenAssignEasy()
- return
- end
- if easyAssign.step == "output" then
- if t ~= "flux_gate" then
- easyAssign.message = "Нужен flux_gate."
- screenAssignEasy()
- return
- end
- if isAddressUsed(a) or a == easyAssign.shield then
- easyAssign.message = "Нужны два разных гейта."
- screenAssignEasy()
- return
- end
- easyAssign.output = a
- local saved = saveAssignedGates(easyAssign.core,
- easyAssign.shield, easyAssign.output)
- if not saved then
- easyAssign.message = "Не удалось сохранить."
- screenAssignEasy()
- return
- end
- easyAssign.saved = true
- easyAssign.step = "done"
- easyAssign.message = "Успешно сохранено."
- maybeChatSay("accepted", "Успешно сохранено. Смотри монитор.")
- screenAssignEasy()
- end
- end
- local function handleComponentAdded(_, a, t)
- if handleAssign and assignMode == "easy" and easyAssign.active then
- acceptEasyComponent(a, t)
- end
- end
- local function pollEasyAssign()
- if not handleAssign or assignMode ~= "easy" or
- not easyAssign.active then
- return
- end
- local addr
- if easyAssign.step == "reactor" then
- addr = findNewComponent("draconic_reactor")
- else
- addr = findNewComponent("flux_gate")
- end
- if addr then
- local t = easyAssign.step == "reactor" and
- "draconic_reactor" or "flux_gate"
- acceptEasyComponent(addr, t)
- end
- end
- local function refreshReactors(openAssign)
- autostateByAdr = {}
- flowInitByAdr = {}
- autoWaitTempByAdr = {}
- chargeRequestByAdr = {}
- for i = 1, #reactors do
- local r = reactors[i]
- autostateByAdr[r.reactorAdr] = r.autostate
- flowInitByAdr[r.reactorAdr] = r.flowInit
- chargeRequestByAdr[r.reactorAdr] = r.chargeRequested
- end
- syncActive()
- local prevAdr = reactors[activeIndex] and
- reactors[activeIndex].reactorAdr
- reactors = buildReactors() or reactors
- local idx = 1
- if pendingActiveReactorAdr then
- for i = 1, #reactors do
- if reactors[i].reactorAdr == pendingActiveReactorAdr then
- idx = i
- break
- end
- end
- pendingActiveReactorAdr = nil
- elseif lastAddedReactorAdr then
- for i = 1, #reactors do
- if reactors[i].reactorAdr == lastAddedReactorAdr then
- idx = i
- break
- end
- end
- lastAddedReactorAdr = nil
- elseif prevAdr then
- for i = 1, #reactors do
- if reactors[i].reactorAdr == prevAdr then
- idx = i
- break
- end
- end
- end
- setActive(idx)
- if openAssign and newEntriesAdded then
- resetAssignState()
- screenAssign()
- return
- end
- if handleMain then
- screenMain()
- else
- screenOverview()
- end
- end
- local function resetAssignState()
- assignState.reactorIndex = nil
- assignState.reactorAdr = nil
- assignState.shieldGateIdx = nil
- assignState.shieldGateAdr = nil
- assignState.outGateIdx = nil
- assignState.outGateAdr = nil
- assignState.step = "reactor"
- end
- saveAssignedGates = function(reactorAdr, shieldAdr, outAdr)
- if not reactorAdr or not shieldAdr or not outAdr then
- return false
- end
- local entries = readReactorsFile() or {}
- local updated = false
- for i = 1, #entries do
- if entries[i].reactorAdr == reactorAdr then
- entries[i].upAdr = outAdr
- entries[i].downAdr = shieldAdr
- updated = true
- break
- end
- end
- if not updated then
- entries[#entries + 1] = {
- reactorAdr = reactorAdr,
- upAdr = outAdr,
- downAdr = shieldAdr
- }
- end
- if #entries > MAX_REACTORS then
- local trimmed = {}
- for i = 1, MAX_REACTORS do
- trimmed[i] = entries[i]
- end
- entries = trimmed
- end
- writeReactorsFile(entries)
- pendingActiveReactorAdr = reactorAdr
- return true
- end
- local function clearAssignedGates(reactorIndex)
- local reactorsList = listAddresses("draconic_reactor")
- if not reactorsList[reactorIndex] then return false end
- local entries = readReactorsFile() or {}
- local newEntries = {}
- for i = 1, #entries do
- if entries[i].reactorAdr ~= reactorsList[reactorIndex] then
- newEntries[#newEntries + 1] = entries[i]
- end
- end
- writeReactorsFile(newEntries)
- return true
- end
- screenOverview = function()
- handleMain = false
- handleStart = false
- handleOptions = false
- handleOverview = true
- handleAssign = false
- local x = drawHeader("HiTech Classic is the best")
- reactors = reactors or {}
- local cols = overviewCols(x)
- term.setCursor(1, 2)
- for _, key in ipairs({"options", "overview", "refresh", "gates"}) do
- local m = menuItem[key]
- m.x, m.y = term.getCursor()
- gpu.setForeground(color.blue)
- printf(m.name)
- m.w = textWidth(m.name)
- gpu.setForeground(color.white)
- end
- for i = 1, #reactors do
- local label = string.format("[R%d]", i)
- reactors[i].tab.x, reactors[i].tab.y = term.getCursor()
- reactors[i].tab.w = textWidth(label)
- local fg = i == activeIndex and color.black or color.blue
- local bg = i == activeIndex and color.orange or color.white
- guiWrite(reactors[i].tab.x, reactors[i].tab.y, fg, bg,
- "%s", label)
- printf(" ")
- end
- drawSeparator(x)
- gpu.setBackground(color.grey)
- gpu.setForeground(color.white)
- gpu.fill(1, 4, x, 21, " ")
- if #reactors == 0 then
- term.setCursor(2, 5)
- printf("Нет настроенных реакторов.\n")
- printf("Откройте \"Гейты\" и назначьте гейты.")
- return
- end
- gpu.setBackground(color.panel)
- gpu.setForeground(color.white)
- gpu.fill(2, 4, x - 2, 6, " ")
- term.setCursor(3, 4)
- printf("Сводка")
- local labels = {
- "Суммарная прибыль:",
- "Суммарная EU:",
- "Тратим на щиты RF:",
- "Суммарная выработка:",
- "Максимум прибыли RF/EU:"
- }
- local coords = {
- summaryProfitCord, summaryEuCord, summaryShieldCord,
- summaryGenCord, summaryMaxProfitCord
- }
- for i = 1, #labels do
- term.setCursor(3, 4 + i)
- printf(labels[i])
- term.setCursor(28, 4 + i)
- getCord(coords[i])
- end
- local autoX = math.max(40, x - 33)
- term.setCursor(autoX, 4)
- printf("Выключены автоматически:")
- term.setCursor(autoX, 5)
- getCord(autoStoppedCord)
- gpu.setBackground(color.dark)
- gpu.setForeground(color.white)
- gpu.fill(2, 11, x - 2, 1, " ")
- term.setCursor(2, 11)
- printf("#")
- local headers = {"СТАТУС", " ТЕМП", "ТОПЛИВО", "ПРИБЫЛЬ",
- "ГЕН", "ПОТОК"}
- local hpos = {cols.status, cols.temp, cols.fuel, cols.profit,
- cols.gen, cols.flow}
- for i = 1, #headers do
- term.setCursor(hpos[i], 11)
- printf(headers[i])
- end
- term.setCursor(cols.ctrl, 11)
- printf("УПР")
- gpu.setForeground(color.dim)
- gpu.fill(2, 12, x - 2, 1, "-")
- gpu.setForeground(color.white)
- gpu.setBackground(color.grey)
- for i = 1, #reactors do
- local r = reactors[i]
- term.setCursor(2, 12 + i)
- printf("#%d", i)
- for _, f in ipairs({"status", "temp", "fuel", "profit",
- "gen", "flow"}) do
- term.setCursor(cols[f], 12 + i)
- r.row[f] = {x = cols[f], y = 12 + i}
- end
- r.control = {
- dec = {x = cols.ctrl, y = 12 + i, w = 3},
- inc = {x = cols.ctrl + 4, y = 12 + i, w = 3},
- auto = {x = cols.ctrl + 8, y = 12 + i, w = 4}
- }
- term.setCursor(cols.ctrl + 13, 12 + i)
- r.powerBtn.x, r.powerBtn.y = term.getCursor()
- r.powerBtn.w = 3
- end
- end
- local function screenMain()
- handleOptions = false
- handleStart = false
- handleMain = true
- handleOverview = false
- handleAssign = false
- if not reactor or not upgate or not downgate or
- (reactors[activeIndex] and
- (not isComponentAlive(reactors[activeIndex].reactorAdr) or
- not isComponentAlive(reactors[activeIndex].upAdr) or
- not isComponentAlive(reactors[activeIndex].downAdr))) then
- refreshReactors(false)
- screenOverview()
- return
- end
- local x = drawHeader("HiTech Classic is the best")
- local ok, inf = pcall(reactor.getReactorInfo)
- if not ok or type(inf) ~= "table" then
- refreshReactors(false)
- screenOverview()
- return
- end
- if reactors[activeIndex] and
- (not isComponentAlive(reactors[activeIndex].reactorAdr) or
- not isComponentAlive(reactors[activeIndex].upAdr) or
- not isComponentAlive(reactors[activeIndex].downAdr)) then
- refreshReactors(false)
- screenOverview()
- return
- end
- infcord.status.value = inf.status
- term.setCursor(1, 2)
- for _, key in ipairs({"options", "overview", "refresh", "gates"}) do
- local m = menuItem[key]
- m.x, m.y = term.getCursor()
- gpu.setForeground(color.blue)
- printf(m.name)
- m.w = textWidth(m.name)
- gpu.setForeground(color.white)
- end
- for i = 1, #reactors do
- local label = string.format("[R%d]", i)
- reactors[i].tab.x, reactors[i].tab.y = term.getCursor()
- reactors[i].tab.w = textWidth(label)
- local fg = i == activeIndex and color.black or color.blue
- local bg = i == activeIndex and color.orange or color.white
- guiWrite(reactors[i].tab.x, reactors[i].tab.y, fg, bg,
- "%s", label)
- printf(" ")
- end
- guiWrite(x - 25, 1, color.yellow, color.panel, "Макс. выраб.: ")
- getCord(infcord.maxgen)
- if inf.generationRate > maxGenerationRate then
- maxGenerationRate = inf.generationRate
- end
- guiWrite(infcord.maxgen.x, infcord.maxgen.y,
- color.green, color.panel, "%s", numformat(maxGenerationRate))
- drawSeparator(x)
- gpu.setBackground(color.panel)
- gpu.setForeground(color.blue)
- printf(" ПАРАМЕТРЫ ")
- term.setCursor(30, 4)
- printf(" УПРАВЛЕНИЕ ")
- gpu.setBackground(color.grey)
- gpu.setForeground(color.white)
- term.setCursor(1, 6)
- gpu.setBackground(color.panel)
- printf(" Температура: ")
- gpu.setBackground(color.grey)
- printf(" ")
- getCord(infcord.temp)
- guiWrite(infcord.temp.x, infcord.temp.y, -1, -1,
- "%0.2f\n", inf.temperature)
- printf(" Вырабатывает: ")
- getCord(infcord.generation)
- guiWrite(infcord.generation.x, infcord.generation.y, -1, -1,
- "%s \n", numformat(inf.generationRate))
- gpu.setBackground(color.panel)
- printf(" Поток: ")
- gpu.setBackground(color.grey)
- printf(" ")
- getCord(infcord.flow)
- infcord.flow.value = getGateFlow(upgate)
- guiWrite(infcord.flow.x, infcord.flow.y, -1, -1,
- "%s ", numformat(infcord.flow.value))
- getCord(button.add)
- makeButton(button.add.x + 4, button.add.y, button.add.name)
- getCord(button.sub)
- makeButton(button.sub.x + 2, button.sub.y, button.sub.name)
- printf("\n")
- printf(" Итоговая мосч: ")
- getCord(infcord.puregen)
- guiWrite(infcord.puregen.x, infcord.puregen.y, -1, -1,
- "%s \n", numformat(inf.generationRate - getGateFlow(downgate)))
- gpu.setBackground(color.panel)
- printf(" Поглощает: ")
- gpu.setBackground(color.grey)
- printf(" ")
- getCord(infcord.drain)
- guiWrite(infcord.drain.x, infcord.drain.y, -1, -1,
- "%s \n", numformat(getGateFlow(downgate)))
- printf(" Мощность поля: ")
- getCord(infcord.fstrth)
- if inf.maxFieldStrength > 0 then
- guiWrite(infcord.fstrth.x, infcord.fstrth.y, -1, -1,
- "%d / %d (%0.2f %%) \n",
- inf.fieldStrength - inf.fieldDrainRate,
- inf.maxFieldStrength,
- ((inf.fieldStrength - inf.fieldDrainRate) /
- inf.maxFieldStrength) * 100)
- else
- guiWrite(infcord.fstrth.x, infcord.fstrth.y, -1, -1,
- "0 / 0 (0 %%) \n")
- end
- gpu.setBackground(color.panel)
- printf(" Насыщенность: ")
- gpu.setBackground(color.grey)
- printf(" ")
- getCord(infcord.esturn)
- if inf.maxEnergySaturation > 0 then
- guiWrite(infcord.esturn.x, infcord.esturn.y, -1, -1,
- "%d / %d (%0.2f %%) \n",
- inf.energySaturation,
- inf.maxEnergySaturation,
- (inf.energySaturation / inf.maxEnergySaturation) * 100)
- else
- guiWrite(infcord.esturn.x, infcord.esturn.y, -1, -1,
- "0 / 0 (0 %%) \n")
- end
- printf(" Топливо: ")
- getCord(infcord.fuel)
- local fuelPct = inf.maxFuelConversion > 0 and
- (inf.fuelConversion / inf.maxFuelConversion) * 100 or 0
- if fuelPct < 78 then
- guiWrite(infcord.fuel.x, infcord.fuel.y, -1, -1,
- "%d / %d (%0.2f %%) \n",
- inf.fuelConversion, inf.maxFuelConversion, fuelPct)
- elseif inf.maxFuelConversion > 0 then
- local c = (inf.status == "online" or inf.status == "charging" or
- inf.status == "charged") and color.red or -1
- guiWrite(infcord.fuel.x, infcord.fuel.y, c, -1,
- "%d / %d (%0.2f %%) Критический уровень топлива\n",
- inf.fuelConversion, inf.maxFuelConversion, fuelPct)
- else
- guiWrite(infcord.fuel.x, infcord.fuel.y, -1, -1,
- "0 / 0 (0 %%) \n")
- end
- gpu.setBackground(color.panel)
- printf(" Расход топлива: ")
- gpu.setBackground(color.grey)
- printf(" ")
- getCord(infcord.fuelconv)
- guiWrite(infcord.fuelconv.x, infcord.fuelconv.y, -1, -1,
- "%d\n", inf.fuelConversionRate)
- getCord(infcord.core)
- if com.isAvailable("draconic_rf_storage") then
- guiWrite(infcord.core.x, infcord.core.y, -1, -1,
- coreformat())
- end
- printf("\n")
- button.stop.x, button.stop.y = term.getCursor()
- button.start.x, button.start.y = button.stop.x, button.stop.y + 1
- button.charge.x, button.charge.y = button.stop.x, button.stop.y + 2
- button.stop.w = textWidth(button.stop.name)
- button.start.w = textWidth(button.start.name)
- button.charge.w = textWidth(button.charge.name)
- if not chargeHintDismissed then
- local h1 = "Перед первым запуском поставь поток на 535 000."
- local h2 = "Потом включай."
- chargeHint.x = 1
- chargeHint.y = math.max(1, screenH - 1)
- local fg, bg = gpu.getForeground(), gpu.getBackground()
- gpu.setForeground(color.green)
- gpu.setBackground(color.grey)
- gpu.set(chargeHint.x, chargeHint.y, h1)
- if math.min(screenH, chargeHint.y + 1) ~= chargeHint.y then
- gpu.set(chargeHint.x, math.min(screenH, chargeHint.y + 1), h2)
- end
- gpu.setForeground(fg)
- gpu.setBackground(bg)
- chargeHint.w = math.max(textWidth(h1), textWidth(h2))
- chargeHint.visible = true
- else
- chargeHint.visible = false
- end
- term.setCursor(button.stop.x, button.stop.y + 3)
- printf(" Автономный режим: ")
- getCord(button.autoon)
- getCord(button.autooff)
- if not autostate then
- guiWrite(button.autooff.x, button.autooff.y,
- color.red, color.black, "%s\n", button.autooff.name)
- else
- guiWrite(button.autoon.x, button.autoon.y,
- color.green, color.black, "%s\n", button.autoon.name)
- end
- checkButtons()
- end
- local function refreshOverview()
- if not handleOverview or not reactors or #reactors == 0 then
- return
- end
- local stopPct = cfg.fuelStopPct or 98
- local totalGen = 0
- local totalProfit = 0
- local totalShield = 0
- local maxProfit = 0
- gpu.setForeground(color.white)
- gpu.setBackground(color.grey)
- for i = 1, #reactors do
- local r = reactors[i]
- local ok, inf = pcall(r.reactor.getReactorInfo)
- if not ok or type(inf) ~= "table" then
- for _, f in ipairs({"status", "temp", "fuel", "profit",
- "gen", "flow"}) do
- guiWrite(r.row[f].x, r.row[f].y, color.red, -1,
- f == "status" and "ERR" or "----")
- end
- else
- totalGen = totalGen + inf.generationRate
- guiWrite(r.row.gen.x, r.row.gen.y, -1, -1,
- "%s", numformat(inf.generationRate))
- local flow = getGateFlow(r.upgate)
- guiWrite(r.row.flow.x, r.row.flow.y, -1, -1,
- "%s", numformat(flow))
- local shieldFlow = getGateFlow(r.downgate)
- totalShield = totalShield + shieldFlow
- local profit = inf.generationRate - shieldFlow
- totalProfit = totalProfit + profit
- if profit > maxProfit then maxProfit = profit end
- guiWrite(r.row.profit.x, r.row.profit.y, -1, -1,
- "%s", numformat(profit))
- local tempColor = inf.temperature >= cfg.tempCriticalEdge and
- color.red or inf.temperature >= cfg.safeModeTempWaitEdge and
- color.yellow or color.white
- guiWrite(r.row.temp.x, r.row.temp.y, tempColor, -1,
- "%4.0fC", inf.temperature)
- local fuelPct = inf.maxFuelConversion > 0 and
- (inf.fuelConversion / inf.maxFuelConversion) * 100 or 0
- if autoStopped[r.reactorAdr] and
- (inf.status == "online" or inf.status == "charging" or
- inf.status == "charged") then
- autoStopped[r.reactorAdr] = nil
- end
- if fuelPct >= stopPct and
- (inf.status == "online" or inf.status == "charging" or
- inf.status == "charged") and
- not autoStopped[r.reactorAdr] then
- r.reactor.stopReactor()
- autoStopped[r.reactorAdr] = true
- end
- guiWrite(r.row.fuel.x, r.row.fuel.y,
- fuelPct >= 80 and color.red or color.white, -1,
- "%5.1f%%", fuelPct)
- local stColor = (inf.status == "online" or
- inf.status == "charging" or
- inf.status == "charged") and color.green or
- (inf.status == "offline" or
- inf.status == "stopping") and color.red or
- color.white
- guiWrite(r.row.status.x, r.row.status.y, stColor, -1,
- "%s", statusText(inf.status))
- makePowerButton(r.control.dec.x, r.control.dec.y,
- "[-]", color.dim, color.white)
- makePowerButton(r.control.inc.x, r.control.inc.y,
- "[+]", color.dim, color.white)
- makePowerButton(r.control.auto.x, r.control.auto.y,
- "AUTO", r.autostate and color.green or color.red,
- color.white)
- if inf.status == "online" or inf.status == "charging" or
- inf.status == "charged" then
- r.powerBtn.action = "stop"
- makePowerButton(r.powerBtn.x, r.powerBtn.y,
- "PWR", color.red, color.white)
- else
- r.powerBtn.action = "start"
- makePowerButton(r.powerBtn.x, r.powerBtn.y,
- "PWR", color.green, color.white)
- end
- end
- end
- if totalProfit > maxSummaryProfit then
- maxSummaryProfit = totalProfit
- end
- guiWrite(summaryProfitCord.x, summaryProfitCord.y,
- color.white, color.panel, "%s", numformat(totalProfit))
- guiWrite(summaryEuCord.x, summaryEuCord.y,
- color.white, color.panel, "%s",
- numformat(math.floor(totalProfit / 8)))
- guiWrite(summaryShieldCord.x, summaryShieldCord.y,
- color.white, color.panel, "%s", numformat(totalShield))
- guiWrite(summaryGenCord.x, summaryGenCord.y,
- color.white, color.panel, "%s", numformat(totalGen))
- guiWrite(summaryMaxProfitCord.x, summaryMaxProfitCord.y,
- color.white, color.panel, "%s / %s",
- numformat(maxSummaryProfit),
- numformat(math.floor(maxSummaryProfit / 8)))
- local autoList = {}
- for i = 1, #reactors do
- if autoStopped[reactors[i].reactorAdr] then
- autoList[#autoList + 1] = "R" .. i
- end
- end
- local autoText = #autoList > 0 and table.concat(autoList, ", ")
- or "нет"
- guiWrite(autoStoppedCord.x, autoStoppedCord.y,
- color.red, -1, "%s", autoText)
- end
- local screen = {
- overview = screenOverview,
- detail = screenMain,
- options = screenOptions
- }
- local function editOption(p)
- while true do
- gpu.fill(p.x, p.y, #tostring(p.value), 1, " ")
- term.setCursor(p.x, p.y)
- p.value = term.read(false, false)
- local val = tonumber(p.value)
- if val then
- p.value = val
- show(color.black, color.grey, p)
- break
- end
- end
- canedit = true
- canclose = true
- screen.options()
- end
- local function add(n, i)
- n.value = n.value + i
- upgate.setSignalLowFlow(n.value)
- return n.value
- end
- local function sub(n, i)
- term.setCursor(n.x, n.y)
- n.value = n.value - i
- return n.value
- end
- local function refreshInfo()
- local ok, inf = pcall(reactor.getReactorInfo)
- if not ok or type(inf) ~= "table" then
- refreshReactors(false)
- screenOverview()
- return
- end
- infcord.status.value = inf.status
- local tbuf1 = inf.temperature
- os.sleep(0.1)
- local ok2, inf2 = pcall(reactor.getReactorInfo)
- local tbuf2 = ok2 and type(inf2) == "table" and
- inf2.temperature or tbuf1
- if handleMain and cfg.autoProtectTempEdge and
- inf.temperature >= cfg.autoProtectTempEdge and not autostate then
- autostate = true
- guiWrite(button.autoon.x, button.autoon.y,
- color.green, color.black, "%s\n", button.autoon.name)
- end
- local stopPct = cfg.fuelStopPct or 98
- local fuelPct = inf.maxFuelConversion > 0 and
- (inf.fuelConversion / inf.maxFuelConversion) * 100 or 0
- if autoStopped[reactors[activeIndex].reactorAdr] and
- (inf.status == "online" or inf.status == "charging" or
- inf.status == "charged") then
- autoStopped[reactors[activeIndex].reactorAdr] = nil
- end
- if fuelPct >= stopPct and
- (inf.status == "online" or inf.status == "charging" or
- inf.status == "charged") and
- not autoStopped[reactors[activeIndex].reactorAdr] then
- reactor.stopReactor()
- autoStopped[reactors[activeIndex].reactorAdr] = true
- end
- if tbuf2 > tbuf1 then
- guiWrite(infcord.temp.x, infcord.temp.y,
- color.red, -1, "%0.2f \n", inf.temperature)
- temprise = true
- elseif tbuf2 < tbuf1 then
- guiWrite(infcord.temp.x, infcord.temp.y,
- color.blue, -1, "%0.2f \n", inf.temperature)
- temprise = false
- elseif inf.temperature == 2000 then
- guiWrite(infcord.temp.x, infcord.temp.y, -1, -1,
- "%0.2f \n", inf.temperature)
- end
- guiWrite(infcord.generation.x, infcord.generation.y, -1, -1,
- "%s\n", numformat(inf.generationRate))
- if inf.generationRate > maxGenerationRate then
- maxGenerationRate = inf.generationRate
- end
- guiWrite(infcord.maxgen.x, infcord.maxgen.y,
- color.green, color.panel, "%s", numformat(maxGenerationRate))
- infcord.flow.value = getGateFlow(upgate)
- guiWrite(infcord.flow.x, infcord.flow.y, -1, -1,
- "%s", numformat(infcord.flow.value))
- guiWrite(infcord.puregen.x, infcord.puregen.y, -1, -1,
- "%s\n", numformat(inf.generationRate - getGateFlow(downgate)))
- infcord.drain.value = inf.fieldDrainRate
- guiWrite(infcord.drain.x, infcord.drain.y, -1, -1,
- "%s\n", numformat(getGateFlow(downgate)))
- if inf.maxFieldStrength > 0 then
- guiWrite(infcord.fstrth.x, infcord.fstrth.y, -1, -1,
- "%d / %d (%0.2f %%) \n",
- inf.fieldStrength - inf.fieldDrainRate,
- inf.maxFieldStrength,
- ((inf.fieldStrength - inf.fieldDrainRate) /
- inf.maxFieldStrength) * 100)
- else
- guiWrite(infcord.fstrth.x, infcord.fstrth.y, -1, -1,
- "0 / 0 (0 %%) \n")
- end
- if inf.maxEnergySaturation > 0 then
- guiWrite(infcord.esturn.x, infcord.esturn.y, -1, -1,
- "%d / %d (%0.2f %%) \n",
- inf.energySaturation, inf.maxEnergySaturation,
- (inf.energySaturation / inf.maxEnergySaturation) * 100)
- else
- guiWrite(infcord.esturn.x, infcord.esturn.y, -1, -1,
- "0 / 0 (0 %%) \n")
- end
- if fuelPct < 78 then
- guiWrite(infcord.fuel.x, infcord.fuel.y, -1, -1,
- "%d / %d (%0.2f %%) \n",
- inf.fuelConversion, inf.maxFuelConversion, fuelPct)
- elseif inf.maxFuelConversion > 0 then
- local c = (inf.status == "online" or inf.status == "charging" or
- inf.status == "charged") and color.red or -1
- guiWrite(infcord.fuel.x, infcord.fuel.y, c, -1,
- "%d / %d (%0.2f %%) Критический уровень топлива\n",
- inf.fuelConversion, inf.maxFuelConversion, fuelPct)
- else
- guiWrite(infcord.fuel.x, infcord.fuel.y, -1, -1,
- "0 / 0 (0 %%)\n")
- end
- guiWrite(infcord.fuelconv.x, infcord.fuelconv.y, -1, -1,
- "%d\n", inf.fuelConversionRate)
- if com.isAvailable("draconic_rf_storage") then
- guiWrite(infcord.core.x, infcord.core.y, -1, -1,
- coreformat())
- if button.stop.y ~= infcord.core.y + 2 then
- screenMain()
- end
- elseif button.stop.y ~= infcord.fuelconv.y + 2 then
- screenMain()
- end
- checkButtons()
- syncActive()
- end
- local function autoForReactor(r, state)
- if not r or not r.reactor or not r.upgate or not r.downgate then
- return
- end
- local ok, inf = pcall(r.reactor.getReactorInfo)
- if not ok or type(inf) ~= "table" then return end
- local now = computer.uptime()
- if (r.chargeRequested and now <= r.chargeRequested) or
- inf.status == "charging" then
- r.downgate.setOverrideEnabled(true)
- r.downgate.setFlowOverride(900000)
- return
- end
- local isActive = reactors[activeIndex] and
- reactors[activeIndex].reactorAdr == r.reactorAdr
- if cfg.autoProtectTempEdge and
- inf.temperature >= cfg.autoProtectTempEdge and not r.autostate then
- r.autostate = true
- if isActive then
- autostate = true
- if handleMain and button.autoon.x then
- guiWrite(button.autoon.x, button.autoon.y,
- color.green, color.black, "%s\n",
- button.autoon.name)
- end
- end
- end
- local shieldPct = cfg.shield or 25
- local flow = getGateFlow(r.upgate)
- if type(flow) ~= "number" then flow = 0 end
- local drain = inf.fieldDrainRate
- if state then
- local forceEdge = math.max(cfg.forceModeTempLowEdge or 7600, 7600)
- local waittemp = autoWaitTempByAdr[r.reactorAdr]
- local tempRise = false
- if r.lastTemp then
- tempRise = inf.temperature > r.lastTemp or
- (inf.temperature == r.lastTemp and
- (r.temprise or false))
- end
- r.lastTemp = inf.temperature
- r.temprise = tempRise
- r.downgate.setOverrideEnabled(true)
- r.downgate.setFlowOverride(drain / (1 - shieldPct / 100))
- if inf.temperature <= forceEdge then
- if flow - inf.generationRate <= cfg.forceModeStepCase then
- r.upgate.setSignalLowFlow(flow + cfg.forceModeStep)
- end
- elseif flow - inf.generationRate <= cfg.safeModeStepCase and
- inf.temperature >= forceEdge then
- if not waittemp then
- r.upgate.setSignalLowFlow(getGateFlow(r.upgate) +
- cfg.safemodeStep)
- elseif inf.temperature < cfg.safeModeTempToWaitEdge then
- waittemp = false
- end
- elseif tempRise and inf.temperature >= cfg.safeModeTempWaitEdge then
- if inf.temperature > cfg.safeModeTempWaitEdge then
- waittemp = true
- end
- if inf.temperature > cfg.tempCriticalEdge then
- r.upgate.setSignalLowFlow(inf.generationRate - 1000)
- end
- end
- autoWaitTempByAdr[r.reactorAdr] = waittemp
- if isActive and handleMain and infcord.flow.x then
- infcord.flow.value = flow
- guiWrite(infcord.flow.x, infcord.flow.y,
- color.red, color.grey, "%s", numformat(flow))
- end
- else
- local downflow = inf.status == "charging" and 900000 or
- drain / (1 - shieldPct / 100)
- if inf.status == "charging" then
- r.downgate.setOverrideEnabled(true)
- r.downgate.setFlowOverride(downflow)
- else
- r.downgate.setOverrideEnabled(false)
- r.downgate.setSignalHighFlow(downflow)
- r.downgate.setSignalLowFlow(downflow)
- end
- end
- end
- local function tcall(type, scrnAdr, x, y, btn, player)
- local rx, ry = gpu.getResolution()
- if x >= rx - 2 and x <= rx and y == 1 then
- event.ignore("touch", tcall)
- prog = false
- ops = false
- return
- end
- local function isClick(m)
- return m and m.x and x >= m.x and
- x <= m.x + (m.w or #m.name) - 1 and y == m.y
- end
- if handleStart and isClick(menuItem.gates) then
- resetAssignState()
- screenAssign()
- return
- end
- if handleMain then
- if isClick(button.add) then
- local d
- if keyb.isShiftDown() then
- d = keyb.isControlDown() and cfg.ctrlShift_interval or
- cfg.shift_interval
- else
- d = keyb.isControlDown() and cfg.ctrl_interval or
- cfg.default_interval
- end
- upgate.setSignalLowFlow(add(infcord.flow, d))
- guiWrite(infcord.flow.x, infcord.flow.y,
- color.red, color.grey, "%s",
- numformat(infcord.flow.value))
- return
- end
- if isClick(button.sub) then
- local d
- if keyb.isShiftDown() then
- d = keyb.isControlDown() and cfg.ctrlShift_interval or
- cfg.shift_interval
- else
- d = keyb.isControlDown() and cfg.ctrl_interval or
- cfg.default_interval
- end
- upgate.setSignalLowFlow(sub(infcord.flow, d))
- guiWrite(infcord.flow.x, infcord.flow.y,
- color.blue, color.grey, "%s",
- numformat(infcord.flow.value))
- return
- end
- if not autostate and isClick(button.autooff) then
- gpu.set(button.autooff.x, button.autooff.y, " ")
- autostate = true
- guiWrite(button.autoon.x, button.autoon.y,
- color.green, color.black, "%s\n",
- button.autoon.name)
- return
- end
- if autostate and isClick(button.autoon) then
- gpu.set(button.autoon.x, button.autoon.y, " ")
- autostate = false
- guiWrite(button.autooff.x, button.autooff.y,
- color.red, color.black, "%s\n",
- button.autooff.name)
- return
- end
- if isClick(button.charge) then
- if reactor and reactor.chargeReactor then
- pcall(reactor.chargeReactor)
- else
- ensureFlowInit(reactors[activeIndex], true)
- if upgate then
- upgate.setSignalLowFlow(CHARGE_FLOW)
- infcord.flow.value = CHARGE_FLOW
- if infcord.flow.x then
- guiWrite(infcord.flow.x, infcord.flow.y,
- color.red, color.grey, "%s",
- numformat(infcord.flow.value))
- end
- end
- end
- if chargeHint.visible then
- guiWrite(chargeHint.x, chargeHint.y,
- color.white, color.grey, "%s",
- string.rep(" ", chargeHint.w))
- guiWrite(chargeHint.x, chargeHint.y + 1,
- color.white, color.grey, "%s",
- string.rep(" ", chargeHint.w))
- chargeHint.visible = false
- chargeHintDismissed = true
- end
- guiWrite(button.charge.x, button.charge.y,
- -1, color.grey, " ",
- button.charge.name)
- button.charge.visible = false
- local cr = reactors[activeIndex]
- if cr and cr.reactorAdr then
- cr.chargeRequested = computer.uptime() + CHARGE_DURATION
- chargeRequestByAdr[cr.reactorAdr] = cr.chargeRequested
- end
- return
- end
- if button.start.visible and isClick(button.start) then
- ensureFlowInit(reactors[activeIndex])
- reactor.activateReactor()
- if reactors[activeIndex] then
- autoStopped[reactors[activeIndex].reactorAdr] = nil
- end
- guiWrite(button.start.x, button.start.y,
- -1, color.grey, " ",
- button.start.name)
- button.start.visible = false
- return
- end
- if button.stop.visible and isClick(button.stop) then
- reactor.stopReactor()
- guiWrite(button.stop.x, button.stop.y,
- -1, color.grey, " ",
- button.stop.name)
- button.stop.visible = false
- return
- end
- for _, key in ipairs({"options", "overview", "refresh", "gates"}) do
- if isClick(menuItem[key]) then
- if key == "overview" then
- syncActive()
- screenOverview()
- elseif key == "options" then
- screenOptions()
- elseif key == "refresh" then
- refreshReactors(true)
- elseif key == "gates" then
- resetAssignState()
- screenAssign()
- end
- return
- end
- end
- for i = 1, #reactors do
- if isClick(reactors[i].tab) then
- syncActive()
- setActive(i)
- screenMain()
- return
- end
- end
- if x == 1 and y == 1 then
- event.ignore("touch", tcall)
- prog = false
- return
- end
- end
- if handleOverview then
- for _, key in ipairs({"options", "refresh", "gates"}) do
- if isClick(menuItem[key]) then
- if key == "options" then
- screenOptions()
- elseif key == "refresh" then
- refreshReactors(true)
- elseif key == "gates" then
- resetAssignState()
- screenAssign()
- end
- return
- end
- end
- for i = 1, #reactors do
- local r = reactors[i]
- if isClick(r.tab) then
- syncActive()
- setActive(i)
- screenMain()
- return
- end
- if r.control then
- if isClick(r.control.dec) then
- local f = getGateFlow(r.upgate)
- r.upgate.setSignalLowFlow(f - cfg.default_interval)
- return
- end
- if isClick(r.control.inc) then
- local f = getGateFlow(r.upgate)
- r.upgate.setSignalLowFlow(f + cfg.default_interval)
- return
- end
- if isClick(r.control.auto) then
- r.autostate = not r.autostate
- if i == activeIndex then
- autostate = r.autostate
- end
- refreshOverview()
- return
- end
- end
- if isClick(r.powerBtn) then
- if r.powerBtn.action == "start" then
- ensureFlowInit(r)
- r.reactor.activateReactor()
- autoStopped[r.reactorAdr] = nil
- else
- r.reactor.stopReactor()
- end
- return
- end
- end
- if x == 1 and y == 1 then
- event.ignore("touch", tcall)
- prog = false
- return
- end
- end
- if handleOptions then
- if canedit then
- local opts = {OptionDefault, OptionCtrl, OptionShift,
- OptionCtrlShift, OptionShield,
- OptionFuelStop}
- for i = 1, #opts do
- if isClick({x = opts[i].x, y = opts[i].y,
- w = #tostring(opts[i].value)}) then
- canclose = false
- canedit = false
- editOption(opts[i])
- return
- end
- end
- end
- if canclose then
- if isClick(menuItem.optionsBack) then
- screenOverview()
- return
- end
- if isClick(menuItem.save) then
- cfg.default_interval = OptionDefault.value
- cfg.ctrl_interval = OptionCtrl.value
- cfg.shift_interval = OptionShift.value
- cfg.ctrlShift_interval = OptionCtrlShift.value
- cfg.shield = OptionShield.value
- cfg.fuelStopPct = OptionFuelStop.value
- configWrite(cfgName)
- screenOverview()
- return
- end
- if isClick(menuItem.cancel) then
- OptionDefault.value = cfg.default_interval
- OptionCtrl.value = cfg.ctrl_interval
- OptionShift.value = cfg.shift_interval
- OptionCtrlShift.value = cfg.ctrlShift_interval
- OptionShield.value = cfg.shield
- OptionFuelStop.value = cfg.fuelStopPct or 98
- screenOverview()
- return
- end
- end
- end
- if handleAssign then
- if assignMode ~= "manual" and assignMode ~= "easy" then
- if isClick(easyAssign.backBtn) then
- assignMode = nil
- easyAssign.active = false
- screenOverview()
- return
- end
- if isClick(easyAssign.heavyBtn) then
- assignMode = "manual"
- resetAssignState()
- screenAssignManual()
- return
- end
- if isClick(easyAssign.easyBtn) then
- assignMode = "easy"
- startEasyAssign()
- if not easyAssign.active then
- assignMode = nil
- screenAssignChoice()
- else
- screenAssignEasy()
- end
- return
- end
- return
- elseif assignMode == "easy" then
- if isClick(easyAssign.backBtn) then
- if easyAssign.saved and easyAssign.core then
- clearAssignedByAdr(easyAssign.core)
- end
- easyAssign.active = false
- easyAssign.step = "reactor"
- easyAssign.core = nil
- easyAssign.shield = nil
- easyAssign.output = nil
- easyAssign.saved = false
- easyAssign.message = nil
- assignMode = nil
- screenAssignChoice()
- return
- end
- if easyAssign.step == "done" then
- if isClick(easyAssign.continueBtn) then
- startEasyAssign()
- screenAssignEasy()
- return
- end
- if isClick(easyAssign.finishBtn) then
- easyAssign.active = false
- assignMode = nil
- refreshReactors(false)
- screenOverview()
- return
- end
- end
- return
- end
- if isClick(menuItem.back) then
- if not assignState.reactorIndex and
- not assignState.shieldGateIdx and
- not assignState.outGateIdx then
- resetAssignState()
- assignMode = nil
- screenOverview()
- else
- assignState.message = "Выбери гейты!"
- screenAssign()
- end
- return
- end
- if assignUi.reset and isClick(assignUi.reset) and
- assignState.reactorIndex then
- clearAssignedGates(assignState.reactorIndex)
- reactors = buildReactors() or reactors
- resetAssignState()
- screenAssign()
- return
- end
- for i = 1, #assignUi.reactors do
- if isClick(assignUi.reactors[i]) then
- assignState.reactorIndex = i
- assignState.reactorAdr = assignUi.reactorAddrs[i]
- assignState.shieldGateIdx = nil
- assignState.shieldGateAdr = nil
- assignState.outGateIdx = nil
- assignState.outGateAdr = nil
- assignState.step = "shield"
- screenAssign()
- return
- end
- end
- for i = 1, #assignUi.gates do
- local btn = assignUi.gates[i]
- if isClick(btn) then
- local gateAdr = assignUi.gateAddrs[i]
- if assignState.step == "reactor" then
- return
- end
- if gateAdr and assignUi.gateUse[gateAdr] and
- assignUi.gateUse[gateAdr] ~= assignUi.selectedAdr then
- return
- end
- if not assignState.reactorIndex then
- assignState.step = "reactor"
- screenAssign()
- return
- end
- if assignState.step == "shield" then
- assignState.shieldGateIdx = i
- assignState.shieldGateAdr = gateAdr
- assignState.step = "output"
- screenAssign()
- return
- elseif assignState.step == "output" then
- if assignState.shieldGateAdr == gateAdr then
- assignState.message = "Нужны два разных гейта!"
- screenAssign()
- return
- end
- assignState.outGateIdx = i
- assignState.outGateAdr = gateAdr
- if not assignState.reactorAdr and
- assignState.reactorIndex then
- assignState.reactorAdr =
- assignUi.reactorAddrs[assignState.reactorIndex]
- end
- if not assignState.shieldGateAdr and
- assignState.shieldGateIdx then
- assignState.shieldGateAdr =
- assignUi.gateAddrs[assignState.shieldGateIdx]
- end
- local saved = saveAssignedGates(
- assignState.reactorAdr,
- assignState.shieldGateAdr,
- assignState.outGateAdr)
- if not saved then
- assignState.message = "Не удалось сохранить гейты!"
- screenAssign()
- return
- end
- local targetAdr = assignState.reactorAdr
- resetAssignState()
- assignMode = nil
- handleAssign = false
- handleMain = true
- handleOverview = false
- reactors = buildReactors() or reactors
- local idx = 1
- if targetAdr then
- for j = 1, #reactors do
- if reactors[j].reactorAdr == targetAdr then
- idx = j
- break
- end
- end
- end
- setActive(idx)
- if not reactors or #reactors == 0 or
- not reactor or not upgate or not downgate then
- screenOverview()
- else
- screenMain()
- end
- return
- end
- end
- end
- if x == 1 and y == 1 then
- event.ignore("touch", tcall)
- prog = false
- return
- end
- end
- end
- event.listen("touch", tcall)
- event.listen("component_added", handleComponentAdded)
- screenStart()
- if upgate and downgate then
- screen.overview()
- end
- while prog do
- local now = computer.uptime()
- if handleMain and now - lastDetailUpdate >= 0.2 then
- lastDetailUpdate = now
- if not pcall(refreshInfo) then
- autostate = false
- if not pcall(screenStart) or not pcall(screenMain) then
- break
- end
- end
- elseif handleOverview and now - lastOverviewUpdate >= 0.5 then
- lastOverviewUpdate = now
- if not pcall(refreshOverview) and not pcall(screenOverview) then
- break
- end
- end
- if reactors and #reactors > 0 then
- for i = 1, #reactors do
- autoForReactor(reactors[i], reactors[i].autostate)
- end
- end
- pollEasyAssign()
- os.sleep(0)
- end
- gpu.setBackground(rback)
- gpu.setForeground(rfore)
- gpu.setResolution(xz, yz)
- term.clear()
Add Comment
Please, Sign In to add comment