View difference between Paste ID: v6vzj1Ez and GxgdUYWf
SHOW: | | - or go back to the newest paste.
1
local event = require("event")
2
local term = require("term")
3
local os = require("os")
4
local computer = require("computer")
5
local com = require("component")
6
local unicode = require("unicode")
7
local keyb = require("keyboard")
8
local gpu = com.gpu
9
10
local reactorsFile = "/home/reactors.txt"
11
local cfgName = "/home/DracReactorConfig.cfg"
12
local MAX_REACTORS = 5
13
local CHARGE_FLOW = 535000
14-
local CHARGE_DURATION = 12 -- seconds to keep the charge override active
14+
local CHARGE_DURATION = 12
15
local autostateByAdr = {}
16
local flowInitByAdr = {}
17
local chargeRequestByAdr = {}
18
19
local DEFAULT_CONFIG = [[
20
-- Интервалы для кнопок +/-
21
default_interval = 1000
22
ctrl_interval = 5000
23
shift_interval = 10000
24
ctrlShift_interval = 20000
25
-- Автономный режим:
26
-- Основные константы
27
shield = 25 - Щиты будут автоматически поддерживаться на этом уровне ( в %)
28
tempCriticalEdge = 8100 -- Если температура превысит это значение, программа экстренно понизит поток вывода;
29
-- Форсированный режим
30
forceModeTempLowEdge = 7500 -- Пока температура не превысит это значение, программа будет работать в форсированном режиме, иначе - перейдет в безопасный режим;
31
forceModeStepCase = 5000  -- Если разница между текущей выработкой энергии и выставленным потоком превысит это значение, то к потоку добавится
32
forceModeStep = 20000 -- это значение
33
-- безопасный режим
34
safeModeTempWaitEdge = 8000 -- Если температура превысит это значение, программа будет ожидать,
35
safeModeTempToWaitEdge = 7850 -- пока температура не понизится до этого значения;
36
safeModeStepCase = 0 -- Если разница между текущей выработкой энергии и выставленным потоком превысит это значение, то к потоку добавится
37
safemodeStep = 8000 -- это значение
38
autoProtectTempEdge = 8300 -- При достижении этой температуры включается автономный режим
39
screen_w = 80 -- Ширина экрана
40
screen_h = 25 -- Высота экрана
41
fuelStopPct = 98 -- % топлива, при котором реактор выключается]]
42
43-
local n = ""
43+
44-
for i=1,#str do
44+
    local n = ""
45-
local ch = str:byte(i,i)
45+
    for i = 1, #str do
46-
if ch >= 48 and ch <= 57 or ch == 46 then
46+
        local ch = str:byte(i, i)
47-
n = n..string.char(ch)
47+
        if ch >= 48 and ch <= 57 or ch == 46 then
48
            n = n .. string.char(ch)
49
        end
50-
if n ~= "" then
50+
    end
51-
return tonumber(n)
51+
    if n ~= "" then
52-
else return n
52+
        return tonumber(n)
53
    else
54
        return n
55
    end
56
end
57-
local confnames = 
57+
58-
{
58+
59-
[1] = "default_interval",
59+
local confnames = {
60-
[2] = "ctrl_interval",
60+
    [1]  = "default_interval",
61-
[3] = "shift_interval",
61+
    [2]  = "ctrl_interval",
62-
[4] = "ctrlShift_interval",
62+
    [3]  = "shift_interval",
63-
[5] = "shield",
63+
    [4]  = "ctrlShift_interval",
64-
[6] = "tempCriticalEdge",
64+
    [5]  = "shield",
65-
[7] = "forceModeTempLowEdge",
65+
    [6]  = "tempCriticalEdge",
66-
[8] = "forceModeStepCase",
66+
    [7]  = "forceModeTempLowEdge",
67-
[9] = "forceModeStep",
67+
    [8]  = "forceModeStepCase",
68-
[10] = "safeModeTempWaitEdge",
68+
    [9]  = "forceModeStep",
69-
[11] = "safeModeTempToWaitEdge",
69+
    [10] = "safeModeTempWaitEdge",
70-
[12] = "safeModeStepCase",
70+
    [11] = "safeModeTempToWaitEdge",
71-
[13] = "safemodeStep",
71+
    [12] = "safeModeStepCase",
72-
[14] = "autoProtectTempEdge",
72+
    [13] = "safemodeStep",
73-
[15] = "screen_w",
73+
    [14] = "autoProtectTempEdge",
74-
[16] = "screen_h",
74+
    [15] = "screen_w",
75-
[17] = "fuelStopPct"
75+
    [16] = "screen_h",
76
    [17] = "fuelStopPct"
77
}
78
79-
local file = io.open(name,"r")
79+
80-
if not file then
80+
    local file = io.open(name, "r")
81-
return nil
81+
    if not file then
82
        return nil
83-
local tab = {}
83+
    end
84-
for line in file:lines() do
84+
    local tab = {}
85-
local key, val = line:match("^%s*([%w_]+)%s*=%s*([%d%.]+)")
85+
    for line in file:lines() do
86-
if key and val then
86+
        local key, val = line:match("^%s*([%w_]+)%s*=%s*([%d%.]+)")
87-
tab[key] = tonumber(val)
87+
        if key and val then
88
            tab[key] = tonumber(val)
89
        end
90-
file:close()
90+
    end
91-
return tab
91+
    file:close()
92
    return tab
93
end
94
95-
if not parsed then
95+
96-
return false
96+
    if not parsed then
97
        return false
98-
for i=1,#confnames do
98+
    end
99-
if parsed[confnames[i]] == nil then
99+
    for i = 1, #confnames do
100-
return false
100+
        if parsed[confnames[i]] == nil then
101
            return false
102
        end
103-
return true
103+
    end
104
    return true
105
end
106
107-
local file = io.open(name,"r")
107+
108-
if file then
108+
    local file = io.open(name, "r")
109-
local tab = {}
109+
    if file then
110-
local i = 1
110+
        local tab = {}
111-
while true do
111+
        local i = 1
112-
local str = file:read("*l")
112+
        while true do
113-
if str == nil then
113+
            local str = file:read("*l")
114-
break
114+
            if str == nil then
115
                break
116-
if parseNum(str) ~= "" then
116+
            end
117-
tab[i] = parseNum(str)
117+
            if parseNum(str) ~= "" then
118-
i=i+1
118+
                tab[i] = parseNum(str)
119
                i = i + 1
120
            end
121-
file:close()
121+
        end
122-
return tab
122+
        file:close()
123-
else 
123+
        return tab
124-
return false
124+
    else
125
        return false
126
    end
127
end
128-
local function writeText(name,text)
128+
129-
local file = io.open(name,"w")
129+
local function writeText(name, text)
130-
file:write(text)
130+
    local file = io.open(name, "w")
131-
file:close()
131+
    file:write(text)
132
    file:close()
133
end
134
135-
local parsed = readConfig(name)
135+
136-
if not parsed or not hasConfigKeys(parsed) then
136+
    local parsed = readConfig(name)
137-
writeText(name,DEFAULT_CONFIG)
137+
    if not parsed or not hasConfigKeys(parsed) then
138-
elseif cfg.default_interval ~= nil and
138+
        writeText(name, DEFAULT_CONFIG)
139-
cfg.ctrl_interval ~= nil and
139+
    elseif cfg.default_interval ~= nil and
140-
cfg.shift_interval ~= nil and
140+
        cfg.ctrl_interval ~= nil and
141-
cfg.ctrlShift_interval ~= nil and
141+
        cfg.shift_interval ~= nil and
142-
cfg.shield ~= nil and
142+
        cfg.ctrlShift_interval ~= nil and
143-
cfg.tempCriticalEdge ~= nil and
143+
        cfg.shield ~= nil and
144-
cfg.forceModeTempLowEdge ~= nil and
144+
        cfg.tempCriticalEdge ~= nil and
145-
cfg.forceModeStepCase ~= nil and
145+
        cfg.forceModeTempLowEdge ~= nil and
146-
cfg.forceModeStep ~= nil and
146+
        cfg.forceModeStepCase ~= nil and
147-
cfg.safeModeTempWaitEdge ~= nil and
147+
        cfg.forceModeStep ~= nil and
148-
cfg.safeModeTempToWaitEdge ~= nil and
148+
        cfg.safeModeTempWaitEdge ~= nil and
149-
cfg.safeModeStepCase ~= nil and
149+
        cfg.safeModeTempToWaitEdge ~= nil and
150-
cfg.safemodeStep ~= nil and
150+
        cfg.safeModeStepCase ~= nil and
151-
cfg.autoProtectTempEdge ~= nil and
151+
        cfg.safemodeStep ~= nil and
152-
cfg.screen_w ~= nil and
152+
        cfg.autoProtectTempEdge ~= nil and
153-
cfg.screen_h ~= nil and
153+
        cfg.screen_w ~= nil and
154-
cfg.fuelStopPct ~= nil then
154+
        cfg.screen_h ~= nil and
155
        cfg.fuelStopPct ~= nil then
156-
writeText(name,string.format(
156+
157-
[[
157+
        writeText(name, string.format([[
158
-- Интервалы для кнопок +/-
159
default_interval = %d 
160
ctrl_interval = %d 
161
shift_interval = %d 
162
ctrlShift_interval = %d 
163
-- Автономный режим:
164
-- Основные константы
165
shield = %0.2f - Щиты будут автоматически поддерживаться на этом уровне ( в %)
166
tempCriticalEdge = %d -- Если температура превысит это значение, программа экстренно понизит поток вывода;
167
-- Форсированный режим
168
forceModeTempLowEdge = %d -- Пока температура не превысит это значение, программа будет работать в форсированном режиме, иначе - перейдет в безопасный режим;
169
forceModeStepCase = %d -- Если разница между текущей выработкой энергии и выставленным потоком превысит это значение, то к потоку добавится
170
forceModeStep = %d -- это значение
171
-- Безопасный режим
172
safeModeTempWaitEdge = %d -- Если температура превысит это значение, программа будет ожидать,
173
safeModeTempToWaitEdge = %d -- пока температура не понизится до этого значения;
174
safeModeStepCase = %d -- Если разница между текущей выработкой энергии и выставленным потоком превысит это значение, то к потоку добавится
175
safemodeStep = %d -- это значение
176
autoProtectTempEdge = %d -- При достижении этой температуры включается автономный режим
177
screen_w = %d -- Ширина экрана
178
screen_h = %d -- Высота экрана
179
fuelStopPct = %d -- % топлива, при котором реактор выключается]],
180-
cfg.default_interval,
180+
            cfg.default_interval,
181-
cfg.ctrl_interval,
181+
            cfg.ctrl_interval,
182-
cfg.shift_interval,
182+
            cfg.shift_interval,
183-
cfg.ctrlShift_interval,
183+
            cfg.ctrlShift_interval,
184-
cfg.shield,
184+
            cfg.shield,
185-
cfg.tempCriticalEdge,
185+
            cfg.tempCriticalEdge,
186-
cfg.forceModeTempLowEdge,
186+
            cfg.forceModeTempLowEdge,
187-
cfg.forceModeStepCase,
187+
            cfg.forceModeStepCase,
188-
cfg.forceModeStep,
188+
            cfg.forceModeStep,
189-
cfg.safeModeTempWaitEdge,
189+
            cfg.safeModeTempWaitEdge,
190-
cfg.safeModeTempToWaitEdge,
190+
            cfg.safeModeTempToWaitEdge,
191-
cfg.safeModeStepCase,
191+
            cfg.safeModeStepCase,
192-
cfg.safemodeStep,
192+
            cfg.safemodeStep,
193-
cfg.autoProtectTempEdge,
193+
            cfg.autoProtectTempEdge,
194-
cfg.screen_w,
194+
            cfg.screen_w,
195-
cfg.screen_h,
195+
            cfg.screen_h,
196-
cfg.fuelStopPct
196+
            cfg.fuelStopPct
197-
))
197+
        ))
198
    end
199
end
200
201-
local function makeConfig(tab,tab2)
201+
local function makeConfig(tab, tab2)
202-
local config = {}
202+
    local config = {}
203-
for i=1,#tab do
203+
    for i = 1, #tab do
204-
config[tostring(tab[i])] = tab2[i]
204+
        config[tostring(tab[i])] = tab2[i]
205
    end
206-
return config
206+
    return config
207
end
208
209
local function listAddresses(typeName)
210-
local list = {}
210+
    local list = {}
211-
for adr in com.list(typeName) do
211+
    for adr in com.list(typeName) do
212-
list[#list+1] = adr
212+
        list[#list + 1] = adr
213
    end
214-
return list
214+
    return list
215
end
216
217
local function readReactorsFile()
218-
local file = io.open(reactorsFile,"r")
218+
    local file = io.open(reactorsFile, "r")
219-
if not file then
219+
    if not file then
220-
return nil
220+
        return nil
221
    end
222-
local list = {}
222+
    local list = {}
223-
for line in file:lines() do
223+
    for line in file:lines() do
224-
local r,u,d = line:match("(%S+)%s+(%S+)%s+(%S+)")
224+
        local r, u, d = line:match("(%S+)%s+(%S+)%s+(%S+)")
225-
if r and u and d then
225+
        if r and u and d then
226-
list[#list+1] = {reactorAdr = r, upAdr = u, downAdr = d}
226+
            list[#list + 1] = {reactorAdr = r, upAdr = u, downAdr = d}
227
        end
228
    end
229-
file:close()
229+
    file:close()
230-
if #list == 0 then
230+
    if #list == 0 then
231-
return nil
231+
        return nil
232
    end
233-
return list
233+
    return list
234
end
235
236
local function writeReactorsFile(list)
237-
local file = io.open(reactorsFile,"w")
237+
    local file = io.open(reactorsFile, "w")
238-
for i=1,#list do
238+
    for i = 1, #list do
239-
file:write(string.format("%s %s %s\n",list[i].reactorAdr,list[i].upAdr,list[i].downAdr))
239+
        file:write(string.format("%s %s %s\n", list[i].reactorAdr, list[i].upAdr, list[i].downAdr))
240
    end
241-
file:close()
241+
    file:close()
242
end
243
244
local function validEntry(entry)
245-
return com.get(entry.reactorAdr) ~= nil and com.get(entry.upAdr) ~= nil and com.get(entry.downAdr) ~= nil
245+
    return com.get(entry.reactorAdr) ~= nil and com.get(entry.upAdr) ~= nil and com.get(entry.downAdr) ~= nil
246
end
247
248
local function mergeEntries(entries)
249-
local usedReactors = {}
249+
    local usedReactors = {}
250-
local usedGates = {}
250+
    local usedGates = {}
251-
for i=1,#entries do
251+
    for i = 1, #entries do
252-
usedReactors[entries[i].reactorAdr] = true
252+
        usedReactors[entries[i].reactorAdr] = true
253-
usedGates[entries[i].upAdr] = true
253+
        usedGates[entries[i].upAdr] = true
254-
usedGates[entries[i].downAdr] = true
254+
        usedGates[entries[i].downAdr] = true
255
    end
256-
local reactorsList = listAddresses("draconic_reactor")
256+
    local reactorsList = listAddresses("draconic_reactor")
257-
local gates = listAddresses("flux_gate")
257+
    local gates = listAddresses("flux_gate")
258-
local freeReactors = {}
258+
    local freeReactors = {}
259-
local freeGates = {}
259+
    local freeGates = {}
260-
for i=1,#reactorsList do
260+
    for i = 1, #reactorsList do
261-
if not usedReactors[reactorsList[i]] then
261+
        if not usedReactors[reactorsList[i]] then
262-
freeReactors[#freeReactors+1] = reactorsList[i]
262+
            freeReactors[#freeReactors + 1] = reactorsList[i]
263
        end
264
    end
265-
for i=1,#gates do
265+
    for i = 1, #gates do
266-
if not usedGates[gates[i]] then
266+
        if not usedGates[gates[i]] then
267-
freeGates[#freeGates+1] = gates[i]
267+
            freeGates[#freeGates + 1] = gates[i]
268
        end
269
    end
270-
local addCount = math.min(#freeReactors, math.floor(#freeGates/2), MAX_REACTORS - #entries)
270+
    local addCount = math.min(#freeReactors, math.floor(#freeGates / 2), MAX_REACTORS - #entries)
271-
for i=1,addCount do
271+
    for i = 1, addCount do
272-
entries[#entries+1] = {
272+
        entries[#entries + 1] = {
273-
reactorAdr = freeReactors[i],
273+
            reactorAdr = freeReactors[i],
274-
upAdr = freeGates[(i-1)*2+1],
274+
            upAdr = freeGates[(i - 1) * 2 + 1],
275-
downAdr = freeGates[(i-1)*2+2]
275+
            downAdr = freeGates[(i - 1) * 2 + 2]
276
        }
277
    end
278-
return entries
278+
    return entries
279
end
280
281
local function buildReactors()
282-
newEntriesAdded = false
282+
    newEntriesAdded = false
283-
lastAddedReactorAdr = nil
283+
    lastAddedReactorAdr = nil
284-
local entries = readReactorsFile()
284+
    local entries = readReactorsFile()
285-
local currentReactors = reactors or {}
285+
    local currentReactors = reactors or {}
286-
if entries then
286+
    if entries then
287-
local valid = {}
287+
        local valid = {}
288-
for i=1,#entries do
288+
        for i = 1, #entries do
289-
if validEntry(entries[i]) then
289+
            if validEntry(entries[i]) then
290-
valid[#valid+1] = entries[i]
290+
                valid[#valid + 1] = entries[i]
291
            end
292
        end
293-
if #valid > 0 then
293+
        if #valid > 0 then
294-
entries = valid
294+
            entries = valid
295
        end
296
    end
297-
if entries and #entries > 0 then
297+
    if entries and #entries > 0 then
298-
local reactorsList = listAddresses("draconic_reactor")
298+
        local reactorsList = listAddresses("draconic_reactor")
299-
if #reactorsList > #entries then
299+
        if #reactorsList > #entries then
300-
newEntriesAdded = true
300+
            newEntriesAdded = true
301
        end
302
    end
303-
if not entries or #entries == 0 then
303+
    if not entries or #entries == 0 then
304-
return nil
304+
        return nil
305
    end
306-
local oldByAdr = {}
306+
    local oldByAdr = {}
307-
for i=1,#currentReactors do
307+
    for i = 1, #currentReactors do
308-
oldByAdr[currentReactors[i].reactorAdr] = currentReactors[i]
308+
        oldByAdr[currentReactors[i].reactorAdr] = currentReactors[i]
309
    end
310
    local reactors = {}
311-
for i=1,#entries do
311+
    for i = 1, #entries do
312-
local e = entries[i]
312+
        local e = entries[i]
313-
local old = oldByAdr[e.reactorAdr]
313+
        local old = oldByAdr[e.reactorAdr]
314-
local savedAuto = autostateByAdr[e.reactorAdr]
314+
        local savedAuto = autostateByAdr[e.reactorAdr]
315-
local savedFlowInit = flowInitByAdr[e.reactorAdr]
315+
        local savedFlowInit = flowInitByAdr[e.reactorAdr]
316-
local savedCharge = chargeRequestByAdr[e.reactorAdr]
316+
        local savedCharge = chargeRequestByAdr[e.reactorAdr]
317-
reactors[i] = {
317+
        reactors[i] = {
318-
index = i,
318+
            index = i,
319-
reactorAdr = e.reactorAdr,
319+
            reactorAdr = e.reactorAdr,
320-
upAdr = e.upAdr,
320+
            upAdr = e.upAdr,
321-
downAdr = e.downAdr,
321+
            downAdr = e.downAdr,
322-
reactor = com.proxy(com.get(e.reactorAdr)),
322+
            reactor = com.proxy(com.get(e.reactorAdr)),
323-
upgate = com.proxy(com.get(e.upAdr)),
323+
            upgate = com.proxy(com.get(e.upAdr)),
324-
downgate = com.proxy(com.get(e.downAdr)),
324+
            downgate = com.proxy(com.get(e.downAdr)),
325-
maxGenerationRate = old and old.maxGenerationRate or 0,
325+
            maxGenerationRate = old and old.maxGenerationRate or 0,
326-
autostate = old and old.autostate or (savedAuto ~= nil and savedAuto or false),
326+
            autostate = old and old.autostate or (savedAuto ~= nil and savedAuto or false),
327-
temprise = old and old.temprise or false,
327+
            temprise = old and old.temprise or false,
328-
flowInit = old and old.flowInit or (savedFlowInit ~= nil and savedFlowInit or false),
328+
            flowInit = old and old.flowInit or (savedFlowInit ~= nil and savedFlowInit or false),
329-
chargeRequested = old and old.chargeRequested or (savedCharge or 0),
329+
            chargeRequested = old and old.chargeRequested or (savedCharge or 0),
330-
lastTemp = nil,
330+
            lastTemp = nil,
331-
row = {},
331+
            row = {},
332-
powerBtn = {},
332+
            powerBtn = {},
333-
tab = {}
333+
            tab = {}
334
        }
335-
if not old then
335+
        if not old then
336-
lastAddedReactorAdr = e.reactorAdr
336+
            lastAddedReactorAdr = e.reactorAdr
337
        end
338
    end
339-
return reactors
339+
    return reactors
340
end
341
342
configWrite(cfgName)
343
cfg = readConfig(cfgName)
344
if not cfg then
345-
cfg = makeConfig(confnames,readParse(cfgName))
345+
    cfg = makeConfig(confnames, readParse(cfgName))
346
end
347
348
local reactors = {}
349
local activeIndex = 1
350-
local summaryProfitCord = {x=nil,y=nil}
350+
local summaryProfitCord = {x = nil, y = nil}
351-
local summaryEuCord = {x=nil,y=nil}
351+
local summaryEuCord = {x = nil, y = nil}
352-
local summaryShieldCord = {x=nil,y=nil}
352+
local summaryShieldCord = {x = nil, y = nil}
353-
local summaryGenCord = {x=nil,y=nil}
353+
local summaryGenCord = {x = nil, y = nil}
354-
local summaryMaxProfitCord = {x=nil,y=nil}
354+
local summaryMaxProfitCord = {x = nil, y = nil}
355
local maxSummaryProfit = 0
356
local newEntriesAdded = false
357
local pendingActiveReactorAdr = nil
358
autostateByAdr = {}
359
flowInitByAdr = {}
360
361-
local color = { }
361+
local color = {}
362-
color["red"]   = 0xFF0000
362+
color["red"]    = 0xFF0000
363-
color["green"] = 0x00FF00
363+
color["green"]  = 0x00FF00
364
color["yellow"] = 0xFFD166
365
color["skyblue"] = 0x4FC3F7
366-
color["black"]   = 0x0F1115
366+
color["black"]  = 0x0F1115
367
color["grey"]   = 0x0F1115
368
color["panel"]  = 0x1A1F27
369
color["blue"]   = 0x4FC3F7
370
color["orange"] = 0xFF9800
371-
color["white"] = 0xE6EDF3
371+
color["white"]  = 0xE6EDF3
372-
color["dark"]  = 0x242B36
372+
color["dark"]   = 0x242B36
373-
color["dim"]   = 0x7A8599
373+
color["dim"]    = 0x7A8599
374
375
local rback = gpu.getBackground()
376
local rfore = gpu.getForeground()
377
local chatBox = nil
378
379
local handleMain
380
local handleOptions
381
local handleStart
382
local screenAssign
383
local screenOverview
384
local assignMode = nil
385
local firstStartCompleted = false
386-
local assignState = {reactorIndex = nil, reactorAdr = nil, shieldGateIdx = nil, shieldGateAdr = nil, outGateIdx = nil, outGateAdr = nil, step = "reactor", message = nil}
386+
local assignState = {
387-
local assignUi = {reactors = {}, gates = {}, gateAddrs = {}, reactorAddrs = {}, gateUse = {}, selectedAdr = nil, back = {x=nil,y=nil,w=0}}
387+
    reactorIndex = nil,
388
    reactorAdr = nil,
389-
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}
389+
    shieldGateIdx = nil,
390
    shieldGateAdr = nil,
391
    outGateIdx = nil,
392
    outGateAdr = nil,
393-
local autoStoppedCord = {x=nil,y=nil}
393+
    step = "reactor",
394
    message = nil
395-
local chargeHint = {x=nil,y=nil,w=0,visible=false}
395+
396
local assignUi = {
397
    reactors = {},
398-
menuItem["options"] = 
398+
    gates = {},
399-
{
399+
    gateAddrs = {},
400-
["name"] ="Настройки |",
400+
    reactorAddrs = {},
401-
["x"] = 1,
401+
    gateUse = {},
402-
["y"] = 2
402+
    selectedAdr = nil,
403
    back = {x = nil, y = nil, w = 0}
404-
menuItem["save"] = 
404+
405-
{
405+
406-
["name"] ="Сохранить |",
406+
local easyAssign = {
407-
["x"] = 1,
407+
    active = false,
408-
["y"] = 2
408+
    step = "reactor",
409
    index = 1,
410-
menuItem["cancel"] = 
410+
    core = nil,
411-
{
411+
    shield = nil,
412-
["name"] =" Отменить  |",
412+
    output = nil,
413-
["x"] = 12,
413+
    saved = false,
414-
["y"] = 2
414+
    message = nil,
415
    heavyBtn = {},
416-
menuItem["overview"] =
416+
    easyBtn = {},
417-
{
417+
    continueBtn = {},
418-
["name"] ="Главный |",
418+
    finishBtn = {},
419-
["x"] = 1,
419+
    backBtn = {},
420-
["y"] = 2
420+
    known = {},
421
    lastChatStep = nil,
422-
menuItem["refresh"] =
422+
    lastChatMessage = nil
423-
{
423+
424-
["name"] ="Обновить |",
424+
425-
["x"] = 1,
425+
426-
["y"] = 2
426+
427
local autoStoppedCord = {x = nil, y = nil}
428-
menuItem["gates"] =
428+
429-
{
429+
local chargeHint = {x = nil, y = nil, w = 0, visible = false}
430-
["name"] ="Гейты |",
430+
431-
["x"] = 1,
431+
432-
["y"] = 2
432+
menuItem["options"] = {
433
    ["name"] = "Настройки |",
434-
menuItem["back"] =
434+
    ["x"] = 1,
435-
{
435+
    ["y"] = 2
436-
["name"] ="Назад |",
436+
437-
["x"] = 1,
437+
menuItem["save"] = {
438-
["y"] = 2
438+
    ["name"] = "Сохранить |",
439
    ["x"] = 1,
440-
menuItem["reset"] =
440+
    ["y"] = 2
441-
{
441+
442-
["name"] ="Сброс |",
442+
menuItem["cancel"] = {
443-
["x"] = 1,
443+
    ["name"] = " Отменить  |",
444-
["y"] = 2
444+
    ["x"] = 12,
445
    ["y"] = 2
446-
menuItem["optionsBack"] =
446+
447-
{
447+
menuItem["overview"] = {
448-
["name"] =" Назад |",
448+
    ["name"] = "Главный |",
449-
["x"] = 1,
449+
    ["x"] = 1,
450-
["y"] = 2
450+
    ["y"] = 2
451
}
452-
menuItem["optionsBack"] =
452+
menuItem["refresh"] = {
453-
{
453+
    ["name"] = "Обновить |",
454-
["name"] =" Назад |",
454+
    ["x"] = 1,
455-
["x"] = 1,
455+
    ["y"] = 2
456-
["y"] = 2
456+
457
menuItem["gates"] = {
458
    ["name"] = "Гейты |",
459-
local xz,yz = gpu.maxResolution()
459+
    ["x"] = 1,
460
    ["y"] = 2
461
}
462-
gpu.setResolution(screenW,screenH)
462+
menuItem["back"] = {
463
    ["name"] = "Назад |",
464
    ["x"] = 1,
465
    ["y"] = 2
466
}
467
menuItem["reset"] = {
468
    ["name"] = "Сброс |",
469
    ["x"] = 1,
470
    ["y"] = 2
471
}
472
menuItem["optionsBack"] = {
473
    ["name"] = " Назад |",
474
    ["x"] = 1,
475
    ["y"] = 2
476
}
477
478
local xz, yz = gpu.maxResolution()
479
local screenW = math.min(120, xz)
480
local screenH = math.min(40, yz)
481-
local infcord =
481+
gpu.setResolution(screenW, screenH)
482-
{
482+
483-
["status"] = 
483+
484-
	{
484+
485-
	["value"] = nil,
485+
486-
	["x"] = nil,
486+
487-
	["y"] = nil
487+
488-
	},
488+
489-
["temp"] = 
489+
490-
	{
490+
491-
	["value"] = nil,
491+
492-
	["x"] = nil,
492+
493-
	["y"] = nil
493+
494-
	},
494+
495-
["generation"] =
495+
496-
	{
496+
497-
	["value"] = nil,
497+
498-
	["x"] = nil,
498+
499-
	["y"] = nil
499+
500-
	},
500+
local infcord = {
501-
["maxgen"] =
501+
    ["status"] = {
502-
	{
502+
        ["value"] = nil,
503-
	["value"] = nil,
503+
        ["x"] = nil,
504-
	["x"] = nil,
504+
        ["y"] = nil
505-
	["y"] = nil
505+
    },
506-
	},
506+
    ["temp"] = {
507-
["flow"] =
507+
        ["value"] = nil,
508-
	{
508+
        ["x"] = nil,
509-
	["value"] = nil,
509+
        ["y"] = nil
510-
	["x"] = nil,
510+
    },
511-
	["y"] = nil
511+
    ["generation"] = {
512-
	},
512+
        ["value"] = nil,
513-
["puregen"] =
513+
        ["x"] = nil,
514-
	{
514+
        ["y"] = nil
515-
	["value"] = nil,
515+
    },
516-
	["x"] = nil,
516+
    ["maxgen"] = {
517-
	["y"] = nil
517+
        ["value"] = nil,
518-
	},
518+
        ["x"] = nil,
519-
["drain"] = 
519+
        ["y"] = nil
520-
	{
520+
    },
521-
	["value"] = nil,
521+
    ["flow"] = {
522-
	["x"] = nil,
522+
        ["value"] = nil,
523-
	["y"] = nil
523+
        ["x"] = nil,
524-
	},
524+
        ["y"] = nil
525-
["fstrth"] =
525+
    },
526-
	{
526+
    ["puregen"] = {
527-
	["value"] = nil,
527+
        ["value"] = nil,
528-
	["x"] = nil,
528+
        ["x"] = nil,
529-
	["y"] = nil
529+
        ["y"] = nil
530-
	},
530+
    },
531-
["esturn"] =
531+
    ["drain"] = {
532-
	{
532+
        ["value"] = nil,
533-
	["value"] = nil,
533+
        ["x"] = nil,
534-
	["x"] = nil,
534+
        ["y"] = nil
535-
	["y"] = nil
535+
    },
536-
	},
536+
    ["fstrth"] = {
537-
["fuel"] =
537+
        ["value"] = nil,
538-
	{
538+
        ["x"] = nil,
539-
	["value"] = nil,
539+
        ["y"] = nil
540-
	["x"] = nil,
540+
    },
541-
	["y"] = nil
541+
    ["esturn"] = {
542-
	},
542+
        ["value"] = nil,
543-
["fuelconv"] =
543+
        ["x"] = nil,
544-
	{
544+
        ["y"] = nil
545-
	["value"] = nil,
545+
    },
546-
	["x"] = nil,
546+
    ["fuel"] = {
547-
	["y"] = nil
547+
        ["value"] = nil,
548-
	},
548+
        ["x"] = nil,
549-
["core"] =
549+
        ["y"] = nil
550-
	{
550+
    },
551-
	["value"] = nil,
551+
    ["fuelconv"] = {
552-
	["x"] = nil,
552+
        ["value"] = nil,
553-
	["y"] = nil
553+
        ["x"] = nil,
554-
	}
554+
        ["y"] = nil
555
    },
556
    ["core"] = {
557-
local button =
557+
        ["value"] = nil,
558-
{
558+
        ["x"] = nil,
559-
["continue"] = 
559+
        ["y"] = nil
560-
	{ 
560+
    }
561-
	["name"] = "Продолжить",
561+
562-
	["x"] = nil,
562+
563-
	["y"] = nil
563+
local button = {
564-
	},
564+
    ["continue"] = {
565-
["change"] =
565+
        ["name"] = "Продолжить",
566-
	{
566+
        ["x"] = nil,
567-
	["name"] = "Изменить",
567+
        ["y"] = nil
568-
	["x"] = nil,
568+
    },
569-
	["y"] = nil
569+
    ["change"] = {
570-
	},
570+
        ["name"] = "Изменить",
571-
["add"] =
571+
        ["x"] = nil,
572-
	{
572+
        ["y"] = nil
573-
	["name"] = " + ",
573+
    },
574-
	["x"] = nil,
574+
    ["add"] = {
575-
	["y"] = nil
575+
        ["name"] = " + ",
576-
	},
576+
        ["x"] = nil,
577-
["sub"] =
577+
        ["y"] = nil
578-
	{
578+
    },
579-
	["name"] = " - ",
579+
    ["sub"] = {
580-
	["x"] = nil,
580+
        ["name"] = " - ",
581-
	["y"] = nil
581+
        ["x"] = nil,
582-
	},
582+
        ["y"] = nil
583-
["start"] =
583+
    },
584-
	{
584+
    ["start"] = {
585-
	["name"] = " [PWR] ЗАПУСК ",
585+
        ["name"] = " [PWR] ЗАПУСК ",
586-
	["x"] = nil,
586+
        ["x"] = nil,
587-
	["y"] = nil,
587+
        ["y"] = nil,
588-
	["visible"] = nil
588+
        ["visible"] = nil
589-
	},
589+
    },
590-
["stop"] =
590+
    ["stop"] = {
591-
	{
591+
        ["name"] = " [PWR] СТОП ",
592-
	["name"] = " [PWR] СТОП ",
592+
        ["x"] = nil,
593-
	["x"] = nil,
593+
        ["y"] = nil,
594-
	["y"] = nil,
594+
        ["visible"] = nil
595-
	["visible"] = nil
595+
    },
596-
	},
596+
    ["charge"] = {
597-
["charge"] =
597+
        ["name"] = "Зарядить реактор ",
598-
	{
598+
        ["x"] = nil,
599-
	["name"] = "Зарядить реактор ",
599+
        ["y"] = nil,
600-
	["x"] = nil,
600+
        ["visible"] = nil
601-
	["y"] = nil,
601+
    },
602-
	["visible"] = nil
602+
    ["autoon"] = {
603-
	},
603+
        ["name"] = "[ON] ",
604-
["autoon"] =
604+
        ["x"] = nil,
605-
	{
605+
        ["y"] = nil,
606-
	["name"] = "[ON] ",
606+
    },
607-
	["x"] = nil,
607+
    ["autooff"] = {
608-
	["y"] = nil,	
608+
        ["name"] = "[OFF]",
609-
	},
609+
        ["x"] = nil,
610-
["autooff"] =
610+
        ["y"] = nil,
611-
	{
611+
    }
612-
	["name"] = "[OFF]",
612+
613-
	["x"] = nil,
613+
614-
	["y"] = nil,	
614+
615-
	}
615+
616
local canclose = true
617
local temprise
618
local autostate = false
619
local maxGenerationRate = 0
620
local lastDetailUpdate = 0
621
local lastOverviewUpdate = 0
622
623
printf = function(s, ...)
624
    return io.write(s:format(...))
625
end
626
627-
printf = function (s,...)
627+
628-
return io.write(s:format(...))
628+
    local ok, len = pcall(unicode.len, s)
629
    if ok and len then
630
        return len
631
    end
632-
local ok, len = pcall(unicode.len, s)
632+
    return #s
633-
if ok and len then
633+
634-
return len
634+
635
local function guiWrite(x, y, cf, cb, s, ...)
636-
return #s
636+
    term.setCursor(x, y)
637
    if cf >= 0 and cb >= 0 then
638
        local fg = gpu.getForeground()
639-
local function guiWrite(x,y,cf,cb,s,...)
639+
        local bg = gpu.getBackground()
640-
term.setCursor(x,y)
640+
        gpu.setForeground(cf)
641-
if cf >=0 and cb >=0 then
641+
        gpu.setBackground(cb)
642-
local fg = gpu.getForeground()
642+
        printf(s, ...)
643-
local bg = gpu.getBackground()
643+
        gpu.setForeground(fg)
644-
gpu.setForeground(cf)
644+
        gpu.setBackground(bg)
645-
gpu.setBackground(cb)
645+
    elseif cb < 0 and cf >= 0 then
646-
printf(s,...)
646+
        local fg = gpu.getForeground()
647-
gpu.setForeground(fg)
647+
        gpu.setForeground(cf)
648-
gpu.setBackground(bg)
648+
        printf(s, ...)
649-
elseif cb <0 and cf>=0 then
649+
        gpu.setForeground(fg)
650-
local fg = gpu.getForeground()
650+
    elseif cf < 0 and cb >= 0 then
651-
gpu.setForeground(cf)
651+
        local bg = gpu.getBackground()
652-
printf(s,...)
652+
        printf(s, ...)
653-
gpu.setForeground(fg)
653+
        gpu.setBackground(bg)
654-
elseif cf < 0 and cb >= 0 then
654+
    else
655-
local bg = gpu.getBackground()
655+
        local fg = gpu.getForeground()
656-
printf(s,...)
656+
        gpu.setForeground(color.white)
657-
gpu.setBackground(bg)
657+
        printf(s, ...)
658-
else
658+
        gpu.setForeground(fg)
659-
local fg = gpu.getForeground()
659+
    end
660
end
661-
printf(s,...)
661+
662-
gpu.setForeground(fg)
662+
663
    param.x, param.y = term.getCursor()
664
    return param.x, param.y
665
end
666
667-
param.x,param.y = term.getCursor()
667+
668-
return param.x,param.y
668+
    local fg = gpu.getForeground()
669
    local bg = gpu.getBackground()
670
    gpu.setForeground(color.white)
671
    gpu.setBackground(color.grey)
672-
local fg = gpu.getForeground()
672+
    for i = y + 3, 3, -1 do
673-
local bg = gpu.getBackground()
673+
        term.setCursor(1, i)
674
        term.clearLine()
675
    end
676-
for i=y+3,3,-1 do
676+
    gpu.setForeground(fg)
677-
term.setCursor(1,i)
677+
    gpu.setBackground(bg)
678-
term.clearLine()
678+
679
680-
gpu.setForeground(fg)
680+
681-
gpu.setBackground(bg)
681+
    if not reactors[index] then
682
        return
683
    end
684
    activeIndex = index
685-
if not reactors[index] then
685+
    reactor = reactors[index].reactor
686-
return
686+
    upgate = reactors[index].upgate
687
    downgate = reactors[index].downgate
688-
activeIndex = index
688+
    autostate = reactors[index].autostate
689-
reactor = reactors[index].reactor
689+
    temprise = reactors[index].temprise
690-
upgate = reactors[index].upgate
690+
    maxGenerationRate = reactors[index].maxGenerationRate
691-
downgate = reactors[index].downgate
691+
692-
autostate = reactors[index].autostate
692+
693-
temprise = reactors[index].temprise
693+
694-
maxGenerationRate = reactors[index].maxGenerationRate
694+
    if not reactors[activeIndex] then
695
        return
696
    end
697
    reactors[activeIndex].autostate = autostate
698-
if not reactors[activeIndex] then
698+
    reactors[activeIndex].temprise = temprise
699-
return
699+
    reactors[activeIndex].maxGenerationRate = maxGenerationRate
700
end
701-
reactors[activeIndex].autostate = autostate
701+
702-
reactors[activeIndex].temprise = temprise
702+
703-
reactors[activeIndex].maxGenerationRate = maxGenerationRate
703+
    local x = gpu.getResolution()
704
    gpu.setBackground(color.grey)
705
    gpu.setForeground(color.white)
706
    term.clear()
707-
local x = gpu.getResolution()
707+
    gpu.setBackground(color.panel)
708
    gpu.setForeground(color.white)
709
    term.clearLine()
710
    printf(" %s", title)
711-
gpu.setBackground(color.panel)
711+
    gpu.setForeground(color.green)
712
    printf(" | Разработал : GintaRus")
713-
term.clearLine()
713+
    gpu.setForeground(color.white)
714-
printf(" %s",title)
714+
    printf("\n")
715-
gpu.setForeground(color.green)
715+
    gpu.setBackground(color.grey)
716-
printf(" | Разработал : GintaRus")
716+
    gpu.setForeground(color.white)
717
    term.clearLine()
718-
printf("\n")
718+
    gpu.setBackground(0xFF0000)
719
    gpu.set(x - 2, 1, " X ")
720
    gpu.setBackground(color.grey)
721-
term.clearLine()
721+
    gpu.setForeground(color.white)
722-
gpu.setBackground(0xFF0000)
722+
    return x
723-
gpu.set(x-2,1," X ")
723+
724
725
local function drawSeparator(x)
726-
return x
726+
    gpu.setBackground(color.grey)
727
    gpu.setForeground(color.dim)
728
    gpu.fill(1, 3, x, 1, "-")
729
    gpu.setBackground(color.grey)
730
    gpu.setForeground(color.white)
731-
gpu.setForeground(color.dim)
731+
    term.setCursor(1, 4)
732-
gpu.fill(1,3,x,1,"-")
732+
733
734
local function makeButton(x, y, text)
735-
term.setCursor(1,4)
735+
    term.setCursor(x, y)
736
    local fg = gpu.getForeground()
737
    local bg = gpu.getBackground()
738-
local function makeButton(x,y,text)
738+
    gpu.setBackground(color.blue)
739-
term.setCursor(x,y)
739+
    gpu.setForeground(color.white)
740-
local fg = gpu.getForeground()
740+
    printf(text)
741-
local bg = gpu.getBackground()
741+
    gpu.setBackground(bg)
742-
gpu.setBackground(color.blue)
742+
    gpu.setForeground(fg)
743
end
744-
printf(text)
744+
745-
gpu.setBackground(bg)
745+
local function makePowerButton(x, y, text, bg, fg)
746-
gpu.setForeground(fg)
746+
    term.setCursor(x, y)
747
    local rfg = gpu.getForeground()
748
    local rbg = gpu.getBackground()
749
    gpu.setBackground(bg)
750-
local function makePowerButton(x,y,text,bg,fg)
750+
    gpu.setForeground(fg)
751-
term.setCursor(x,y)
751+
    printf(text)
752-
local rfg = gpu.getForeground()
752+
    gpu.setBackground(rbg)
753-
local rbg = gpu.getBackground()
753+
    gpu.setForeground(rfg)
754-
gpu.setBackground(bg)
754+
755-
gpu.setForeground(fg)
755+
756-
printf(text)
756+
757-
gpu.setBackground(rbg)
757+
    if not gate then
758-
gpu.setForeground(rfg)
758+
        return 0
759
    end
760
    local ok, value = pcall(gate.getSignalLowFlow)
761
    if ok and type(value) == "number" then
762-
if not gate then
762+
        return value
763-
return 0
763+
    end
764
    local ok2, value2 = pcall(gate.getFlow)
765-
local ok, value = pcall(gate.getSignalLowFlow)
765+
    if ok2 and type(value2) == "number" then
766-
if ok and type(value) == "number" then
766+
        return value2
767-
return value
767+
    end
768
    return 0
769-
local ok2, value2 = pcall(gate.getFlow)
769+
770-
if ok2 and type(value2) == "number" then
770+
771-
return value2
771+
772
    if not addr then
773-
return 0
773+
        return false
774
    end
775
    return com.get(addr) ~= nil
776
end
777-
if not addr then
777+
778-
return false
778+
779
    if not r or (r.flowInit and not force) then
780-
return com.get(addr) ~= nil
780+
        return
781
    end
782
    pcall(r.upgate.setSignalLowFlow, r.upgate, CHARGE_FLOW)
783
    r.flowInit = true
784-
if not r or (r.flowInit and not force) then
784+
    flowInitByAdr[r.reactorAdr] = true
785-
return
785+
    if reactors[activeIndex] and reactors[activeIndex].reactorAdr == r.reactorAdr then
786
        infcord.flow.value = CHARGE_FLOW
787-
pcall(r.upgate.setSignalLowFlow, r.upgate, CHARGE_FLOW)
787+
        if handleMain and infcord.flow.x then
788-
r.flowInit = true
788+
            guiWrite(infcord.flow.x, infcord.flow.y, color.red, color.grey, "%s", numformat(infcord.flow.value))
789-
flowInitByAdr[r.reactorAdr] = true
789+
        end
790-
if reactors[activeIndex] and reactors[activeIndex].reactorAdr == r.reactorAdr then
790+
    end
791-
infcord.flow.value = CHARGE_FLOW
791+
792-
if handleMain and infcord.flow.x then
792+
793-
guiWrite(infcord.flow.x,infcord.flow.y,color.red,color.grey,"%s",numformat(infcord.flow.value))
793+
794
    return status == "offline" or status == "stopping" or status == "cold" or status == "cooling" or status == "warming_up"
795
end
796
797
local function statusText(status)
798
    if status == "online" then
799-
return status == "offline" or status == "stopping" or status == "cold" or status == "cooling" or status == "warming_up"
799+
        return "ВКЛ"
800
    elseif status == "offline" then
801
        return "ВЫК"
802
    elseif status == "charging" then
803-
if status == "online" then
803+
        return "ЗАР"
804-
return "ВКЛ"
804+
    elseif status == "charged" then
805-
elseif status == "offline" then
805+
        return "ГОТ"
806-
return "ВЫК"
806+
    elseif status == "stopping" then
807-
elseif status == "charging" then
807+
        return "СТП"
808-
return "ЗАР"
808+
    elseif status == "cold" then
809-
elseif status == "charged" then
809+
        return "ХОЛ"
810-
return "ГОТ"
810+
    elseif status == "cooling" then
811-
elseif status == "stopping" then
811+
        return "ОСТ"
812-
return "СТП"
812+
    elseif status == "warming_up" then
813-
elseif status == "cold" then
813+
        return "РАЗ"
814-
return "ХОЛ"
814+
    end
815-
elseif status == "cooling" then
815+
    return status
816-
return "ОСТ"
816+
817-
elseif status == "warming_up" then
817+
818-
return "РАЗ"
818+
local function show(fc, bc, param)
819
    local fg = gpu.getForeground()
820-
return status
820+
    local bg = gpu.getBackground()
821
    term.setCursor(param.x, param.y)
822
    gpu.setForeground(fc)
823-
local function show(fc,bc,param)
823+
    gpu.setBackground(bc)
824-
local fg = gpu.getForeground()
824+
    local st = " "
825-
local bg = gpu.getBackground()
825+
    for i = 0, #tostring(param.value) do
826-
term.setCursor(param.x,param.y)
826+
        st = st .. " "
827-
gpu.setForeground(fc)
827+
    end
828-
gpu.setBackground(bc)
828+
    gpu.set(param.x, param.y, st)
829-
local st = " "
829+
    printf("%d", param.value)
830-
for i = 0,#tostring(param.value) do
830+
    gpu.setForeground(fg)
831-
st=st.." "
831+
    gpu.setBackground(bg)
832
end
833-
gpu.set(param.x,param.y,st)
833+
834-
printf("%d",param.value)
834+
835-
gpu.setForeground(fg)
835+
    local s = tostring(n)
836-
gpu.setBackground(bg)
836+
    if n >= 1000 and n < 1000000 then
837
        local t = s:sub(1, #s - 3)
838
        local e = s:sub(#s - 2)
839
        s = t .. " " .. e .. "  "
840-
local s = tostring(n)
840+
        return s
841-
if n >= 1000 and n < 1000000 then
841+
    elseif n >= 1000000 then
842-
local t = s:sub(1,#s-3)
842+
        local m = s:sub(1, #s - 6)
843-
local e = s:sub(#s-2)
843+
        local t = s:sub(#s - 5, #s - 3)
844-
s = t.." "..e.."  "
844+
        local e = s:sub(#s - 2)
845-
return s
845+
        s = m .. " " .. t .. " " .. e .. "  "
846-
elseif n >= 1000000 then
846+
        return s
847-
local m = s:sub(1,#s-6)
847+
    else
848-
local t = s:sub(#s-5,#s-3)
848+
        s = s .. "  "
849-
local e = s:sub(#s-2)
849+
        return s
850-
s = m.." "..t.." "..e.."  "
850+
    end
851-
return s
851+
852-
else
852+
853-
s=s.."  "
853+
854-
return s
854+
    local cols
855
    if x >= 120 then
856
        cols = {status = 6, temp = 15, fuel = 27, profit = 43, gen = 60, flow = 77}
857
    else
858
        cols = {status = 5, temp = 11, fuel = 20, profit = 33, gen = 48, flow = 63}
859-
local cols
859+
    end
860-
if x >= 120 then
860+
    local ctrl = cols.flow + 12
861-
cols = {status=6,temp=15,fuel=27,profit=43,gen=60,flow=77}
861+
    if ctrl < 65 then
862-
else
862+
        ctrl = 65
863-
cols = {status=5,temp=11,fuel=20,profit=33,gen=48,flow=63}
863+
    end
864
    if ctrl + 16 > x then
865-
local ctrl = cols.flow + 12
865+
        ctrl = math.max(65, x - 16)
866-
if ctrl < 65 then
866+
    end
867-
ctrl = 65
867+
    cols.ctrl = ctrl
868
    return cols
869-
if ctrl + 16 > x then
869+
870-
ctrl = math.max(65, x - 16)
870+
871
local function coreformat()
872-
cols.ctrl = ctrl
872+
    local num = com.draconic_rf_storage.getEnergyStored()
873-
return cols
873+
    if num > 10 ^ 12 then
874
        return string.format(" Накоплено в ядре: %0.3f T   \n", num / 10 ^ 12)
875
    elseif num > 10 ^ 9 then
876
        return string.format(" Накоплено в ядре: %0.3f B   \n", num / 10 ^ 9)
877-
local num = com.draconic_rf_storage.getEnergyStored()
877+
    elseif num > 10 ^ 6 then
878-
if num > 10^12 then
878+
        return string.format(" Накоплено в ядре: %0.3f M   \n", num / 10 ^ 6)
879-
return string.format(" Накоплено в ядре: %0.3f T   \n",num/10^12)
879+
    elseif num > 10 ^ 3 then
880-
elseif num > 10^9 then 
880+
        return string.format(" Накоплено в ядре: %0.3f K   \n", num / 10 ^ 3)
881-
return string.format(" Накоплено в ядре: %0.3f B   \n",num/10^9)
881+
    else
882-
elseif num > 10^6 then
882+
        return string.format(" Накоплено в ядре: %d   \n", num)
883-
return string.format(" Накоплено в ядре: %0.3f M   \n",num/10^6)
883+
    end
884-
elseif num > 10^3 then
884+
885-
return string.format(" Накоплено в ядре: %0.3f K   \n",num/10^3)
885+
886-
else
886+
887-
return string.format(" Накоплено в ядре: %d   \n",num)
887+
    local ok, inf = pcall(reactor.getReactorInfo)
888
    if not ok or type(inf) ~= "table" then
889
        return
890
    end
891-
-- Анализ и корректировка запомненных адресов
891+
    infcord.status.value = inf.status
892
    button.start.visible = false
893-
local ok, inf = pcall(reactor.getReactorInfo)
893+
    button.stop.visible = false
894-
if not ok or type(inf) ~= "table" then
894+
    button.charge.visible = false
895-
return
895+
    if canChargeStatus(infcord.status.value) then
896
        guiWrite(button.charge.x, button.charge.y, color.skyblue, color.black, "%s", button.charge.name)
897-
infcord.status.value = inf.status
897+
        button.charge.visible = true
898-
button.start.visible = false
898+
    elseif infcord.status.value == "charged" then
899-
button.stop.visible = false
899+
        guiWrite(button.start.x, button.start.y, color.green, color.black, "%s", button.start.name)
900-
button.charge.visible = false
900+
        button.start.visible = true
901-
if canChargeStatus(infcord.status.value) then
901+
        guiWrite(button.stop.x, button.stop.y, color.red, color.black, "%s", button.stop.name)
902-
guiWrite(button.charge.x,button.charge.y,color.skyblue,color.black,"%s",button.charge.name)
902+
        button.stop.visible = true
903-
button.charge.visible = true
903+
    elseif infcord.status.value == "online" or infcord.status.value == "charging" then
904-
elseif infcord.status.value == "charged" then
904+
        guiWrite(button.stop.x, button.stop.y, color.red, color.black, "%s", button.stop.name)
905-
guiWrite(button.start.x,button.start.y,color.green,color.black,"%s",button.start.name)
905+
        button.stop.visible = true
906-
button.start.visible = true
906+
    elseif infcord.status.value == "stopping" then
907-
guiWrite(button.stop.x,button.stop.y,color.red,color.black,"%s",button.stop.name)
907+
        if (inf.energySaturation / inf.maxEnergySaturation) * 100 >= 50 and
908-
button.stop.visible = true
908+
            (inf.fieldStrength / inf.maxFieldStrength) * 100 >= 50 and
909-
elseif infcord.status.value == "online" or infcord.status.value == "charging" then
909+
            inf.temperature > 2000 then
910-
guiWrite(button.stop.x,button.stop.y,color.red,color.black,"%s",button.stop.name)
910+
            guiWrite(button.start.x, button.start.y, color.green, color.black, "%s", button.start.name)
911-
button.stop.visible = true
911+
            button.start.visible = true
912-
elseif infcord.status.value == "stopping" then
912+
        end
913-
if (inf.energySaturation/inf.maxEnergySaturation)*100 >=50 and (inf.fieldStrength/inf.maxFieldStrength)*100 >= 50 and inf.temperature > 2000 then
913+
    end
914-
guiWrite(button.start.x,button.start.y,color.green,color.black,"%s",button.start.name)
914+
915-
button.start.visible = true
915+
916
local function screenStart()
917
    handleMain = false
918
    handleOptions = false
919-
-- Инициализация программы, анализ и настройка всей технической белеберды
919+
    handleStart = true
920
    local x = drawHeader("HiTech Classic is the best   (Preparation)")
921-
handleMain = false
921+
    if not firstStartCompleted then
922-
handleOptions = false
922+
        printf("Эта страница для настройки программы при первом запуске или после сбоя")
923-
handleStart = true
923+
    end
924-
local x = drawHeader("HiTech Classic is the best   (Preparation)")
924+
    drawSeparator(x)
925-
if not firstStartCompleted then
925+
    term.setCursor(1, screenH - 2)
926-
printf("Эта страница для настройки программы при первом запуске или после сбоя")
926+
    menuItem.gates.x, menuItem.gates.y = term.getCursor()
927
    gpu.setForeground(color.blue)
928-
drawSeparator(x)
928+
    printf(menuItem.gates.name)
929-
term.setCursor(1,screenH - 2)
929+
    menuItem.gates.w = textWidth(menuItem.gates.name)
930-
menuItem.gates.x,menuItem.gates.y = term.getCursor()
930+
    gpu.setForeground(color.white)
931-
gpu.setForeground(color.blue)
931+
    local hadFile = readReactorsFile() ~= nil
932-
printf(menuItem.gates.name)
932+
    while true do
933-
menuItem.gates.w = textWidth(menuItem.gates.name)
933+
        if not ops then
934
            return
935-
local hadFile = readReactorsFile() ~= nil
935+
        end
936-
while true do
936+
        reactors = buildReactors()
937-
if not ops then return end
937+
        if reactors and #reactors > 0 then
938-
reactors = buildReactors()
938+
            setActive(1)
939-
if reactors and #reactors > 0 then
939+
            firstStartCompleted = true
940-
setActive(1)
940+
            if not hadFile then
941-
firstStartCompleted = true
941+
                screenAssign()
942-
if not hadFile then
942+
                return
943-
screenAssign()
943+
            end
944-
return
944+
            break
945
        end
946-
break
946+
        if not hadFile then
947
            local reactorsList = listAddresses("draconic_reactor")
948-
if not hadFile then
948+
            local gates = listAddresses("flux_gate")
949-
local reactorsList = listAddresses("draconic_reactor")
949+
            if #reactorsList > 0 and #gates >= 2 then
950-
local gates = listAddresses("flux_gate")
950+
                reactors = reactors or {}
951-
if #reactorsList > 0 and #gates >= 2 then
951+
                firstStartCompleted = true
952-
reactors = reactors or {}
952+
                screenOverview()
953-
firstStartCompleted = true
953+
                return
954-
screenOverview()
954+
            end
955-
return
955+
        end
956
        guiClear(2)
957
        printf("Подключите реакторы и флюкс-гейты (2 гейта на каждый реактор)\n")
958-
guiClear(2)
958+
        printf("Максимум: %d реакторов. Адреса можно сохранить в %s\n", MAX_REACTORS, reactorsFile)
959-
printf("Подключите реакторы и флюкс-гейты (2 гейта на каждый реактор)\n")
959+
        os.sleep(1)
960-
printf("Максимум: %d реакторов. Адреса можно сохранить в %s\n",MAX_REACTORS,reactorsFile)
960+
    end
961-
os.sleep(1)
961+
962
963
local function screenOptions()
964-
-- Экран настроек
964+
    handleMain = false
965
    handleStart = false
966-
handleMain = false
966+
    handleOptions = true
967-
handleStart = false
967+
    handleOverview = false
968-
handleOptions = true
968+
    handleAssign = false
969-
handleOverview = false
969+
    canedit = true
970-
handleAssign = false
970+
    canclose = true
971-
canedit = true
971+
    local x = drawHeader("HiTech Classic is the best   (Options)")
972-
canclose = true
972+
    menuItem.save.x, menuItem.save.y = term.getCursor()
973-
local x = drawHeader("HiTech Classic is the best   (Options)")
973+
    gpu.setForeground(color.blue)
974-
menuItem.save.x,menuItem.save.y =term.getCursor()
974+
    printf(menuItem.save.name)
975-
gpu.setForeground(color.blue)
975+
    menuItem.save.w = textWidth(menuItem.save.name)
976-
printf(menuItem.save.name)
976+
    menuItem.cancel.x, menuItem.cancel.y = term.getCursor()
977-
menuItem.save.w = textWidth(menuItem.save.name)
977+
    printf(menuItem.cancel.name)
978-
menuItem.cancel.x,menuItem.cancel.y =term.getCursor()
978+
    menuItem.cancel.w = textWidth(menuItem.cancel.name)
979-
printf(menuItem.cancel.name)
979+
    menuItem.optionsBack.x, menuItem.optionsBack.y = term.getCursor()
980-
menuItem.cancel.w = textWidth(menuItem.cancel.name)
980+
    printf(menuItem.optionsBack.name)
981-
menuItem.optionsBack.x,menuItem.optionsBack.y =term.getCursor()
981+
    menuItem.optionsBack.w = textWidth(menuItem.optionsBack.name)
982-
printf(menuItem.optionsBack.name)
982+
    gpu.setForeground(color.white)
983-
menuItem.optionsBack.w = textWidth(menuItem.optionsBack.name)
983+
    drawSeparator(x)
984
    printf(" Интервал для щелчка: ")
985-
drawSeparator(x)
985+
    OptionDefault["x"], OptionDefault["y"] = term.getCursor()
986-
printf(" Интервал для щелчка: ")
986+
    printf("%d\n", OptionDefault.value)
987-
OptionDefault["x"],OptionDefault["y"] = term.getCursor()
987+
    printf(" Интервал для CTRL: ")
988-
printf("%d\n",OptionDefault.value)
988+
    OptionCtrl["x"], OptionCtrl["y"] = term.getCursor()
989-
printf(" Интервал для CTRL: ")
989+
    printf("%d\n", OptionCtrl.value)
990-
OptionCtrl["x"],OptionCtrl["y"] = term.getCursor()
990+
    printf(" Интервал для SHIFT: ")
991-
printf("%d\n",OptionCtrl.value)
991+
    OptionShift["x"], OptionShift["y"] = term.getCursor()
992-
printf(" Интервал для SHIFT: ")
992+
    printf("%d\n", OptionShift.value)
993-
OptionShift["x"],OptionShift["y"] = term.getCursor()
993+
    printf(" Интервал для CTRL+SHIFT: ")
994-
printf("%d\n",OptionShift.value)
994+
    OptionCtrlShift["x"], OptionCtrlShift["y"] = term.getCursor()
995-
printf(" Интервал для CTRL+SHIFT: ")
995+
    printf("%d\n", OptionCtrlShift.value)
996-
OptionCtrlShift["x"],OptionCtrlShift["y"] = term.getCursor()
996+
    printf(" Уровень щитов: ")
997-
printf("%d\n",OptionCtrlShift.value)
997+
    OptionShield["x"], OptionShield["y"] = term.getCursor()
998-
printf(" Уровень щитов: ")
998+
    printf("%d\n", OptionShield.value)
999-
OptionShield["x"],OptionShield["y"] = term.getCursor()
999+
    printf(" Отключение по топливу (%%): ")
1000-
printf("%d\n",OptionShield.value)
1000+
    OptionFuelStop["x"], OptionFuelStop["y"] = term.getCursor()
1001-
printf(" Отключение по топливу (%%): ")
1001+
    printf("%d\n", OptionFuelStop.value)
1002-
OptionFuelStop["x"],OptionFuelStop["y"] = term.getCursor()
1002+
1003-
printf("%d\n",OptionFuelStop.value)
1003+
1004
local function clearPromptLine()
1005-
-- Назначение гейтов
1005+
    local _, y = term.getCursor()
1006
    if y > 1 then
1007-
local _, y = term.getCursor()
1007+
        term.setCursor(1, y - 1)
1008-
if y > 1 then
1008+
        term.clearLine()
1009-
term.setCursor(1, y - 1)
1009+
        term.setCursor(1, y - 1)
1010-
term.clearLine()
1010+
    end
1011-
term.setCursor(1, y - 1)
1011+
1012
1013
local function readIndex(prompt, max, used)
1014
    while true do
1015-
local function readIndex(prompt,max,used)
1015+
        printf("%s", prompt)
1016-
while true do
1016+
        local input = term.read(false, false) or ""
1017-
printf("%s",prompt)
1017+
        clearPromptLine()
1018-
local input = term.read(false,false) or ""
1018+
        local num = tonumber(input:match("%d+"))
1019-
clearPromptLine()
1019+
        if num and num >= 1 and num <= max and not used[num] then
1020-
local num = tonumber(input:match("%d+"))
1020+
            return num
1021-
if num and num >= 1 and num <= max and not used[num] then
1021+
        end
1022-
return num
1022+
        printf("Неверный выбор, попробуйте снова.\n")
1023
    end
1024-
printf("Неверный выбор, попробуйте снова.\n")
1024+
1025
1026
local function readIndexAllowZero(prompt, max)
1027
    while true do
1028-
local function readIndexAllowZero(prompt,max)
1028+
        printf("%s", prompt)
1029-
while true do
1029+
        local input = term.read(false, false) or ""
1030-
printf("%s",prompt)
1030+
        clearPromptLine()
1031-
local input = term.read(false,false) or ""
1031+
        local lower = input:lower()
1032-
clearPromptLine()
1032+
        if lower:find("назад") or lower:find("back") or lower:match("^b%s*$") then
1033-
local lower = input:lower()
1033+
            return -1
1034-
if lower:find("назад") or lower:find("back") or lower:match("^b%s*$") then
1034+
        end
1035-
return -1
1035+
        local num = tonumber(input:match("%d+"))
1036
        if num and num >= 0 and num <= max then
1037-
local num = tonumber(input:match("%d+"))
1037+
            return num
1038-
if num and num >= 0 and num <= max then
1038+
        end
1039-
return num
1039+
        printf("Неверный выбор, попробуйте снова.\n")
1040
    end
1041-
printf("Неверный выбор, попробуйте снова.\n")
1041+
1042
1043
local saveAssignedGates
1044
1045
local function getChatBox()
1046
    if chatBox then
1047
        return chatBox
1048-
if chatBox then
1048+
    end
1049-
return chatBox
1049+
    if com.isAvailable("chat_box") then
1050
        chatBox = com.chat_box
1051-
if com.isAvailable("chat_box") then
1051+
    end
1052-
chatBox = com.chat_box
1052+
    return chatBox
1053
end
1054-
return chatBox
1054+
1055
local function chatSay(message, color_code)
1056
    local box = getChatBox()
1057
    if not box or not message then
1058-
local box = getChatBox()
1058+
        return false
1059-
if not box or not message then
1059+
    end
1060-
return false
1060+
    if box.say and pcall(function()
1061
        box.say(message)
1062-
if box.say and pcall(function() box.say(message) end) then
1062+
    end) then
1063-
return true
1063+
        return true
1064
    end
1065-
if box.sendMessage and pcall(function() box.sendMessage(message) end) then
1065+
    if box.sendMessage and pcall(function()
1066-
return true
1066+
        box.sendMessage(message)
1067
    end) then
1068-
if box.sendMessage and pcall(function() box.sendMessage(message, color_code or 64) end) then
1068+
        return true
1069-
return true
1069+
    end
1070
    if box.sendMessage and pcall(function()
1071-
return false
1071+
        box.sendMessage(message, color_code or 64)
1072
    end) then
1073
        return true
1074
    end
1075-
if step and easyAssign.lastChatStep ~= step then
1075+
    return false
1076-
easyAssign.lastChatStep = step
1076+
1077-
easyAssign.lastChatMessage = nil
1077+
1078
local function maybeChatSay(step, message, color_code)
1079-
if message and easyAssign.lastChatMessage ~= message then
1079+
    if step and easyAssign.lastChatStep ~= step then
1080-
easyAssign.lastChatMessage = message
1080+
        easyAssign.lastChatStep = step
1081-
chatSay(message, color_code)
1081+
        easyAssign.lastChatMessage = nil
1082
    end
1083
    if message and easyAssign.lastChatMessage ~= message then
1084
        easyAssign.lastChatMessage = message
1085
        chatSay(message, color_code)
1086-
local list = {}
1086+
    end
1087-
for adr in com.list(typeName) do
1087+
1088-
list[#list+1] = adr
1088+
1089
local function snapshotComponents(typeName)
1090-
return list
1090+
    local list = {}
1091
    for adr in com.list(typeName) do
1092
        list[#list + 1] = adr
1093
    end
1094-
easyAssign.known = {draconic_reactor = {}, flux_gate = {}}
1094+
    return list
1095-
for _, addr in ipairs(snapshotComponents("draconic_reactor")) do
1095+
1096-
easyAssign.known.draconic_reactor[addr] = true
1096+
1097
local function initEasyKnown()
1098-
for _, addr in ipairs(snapshotComponents("flux_gate")) do
1098+
    easyAssign.known = {draconic_reactor = {}, flux_gate = {}}
1099-
easyAssign.known.flux_gate[addr] = true
1099+
    for _, addr in ipairs(snapshotComponents("draconic_reactor")) do
1100
        easyAssign.known.draconic_reactor[addr] = true
1101
    end
1102
    for _, addr in ipairs(snapshotComponents("flux_gate")) do
1103
        easyAssign.known.flux_gate[addr] = true
1104-
if not easyAssign.known or not easyAssign.known[typeName] then
1104+
    end
1105-
initEasyKnown()
1105+
1106
1107-
for addr in com.list(typeName) do
1107+
1108-
if not easyAssign.known[typeName][addr] then
1108+
    if not easyAssign.known or not easyAssign.known[typeName] then
1109-
easyAssign.known[typeName][addr] = true
1109+
        initEasyKnown()
1110-
return addr
1110+
    end
1111
    for addr in com.list(typeName) do
1112
        if not easyAssign.known[typeName][addr] then
1113-
return nil
1113+
            easyAssign.known[typeName][addr] = true
1114
            return addr
1115
        end
1116
    end
1117-
if not addr then
1117+
    return nil
1118-
return false
1118+
1119
1120-
local entries = readReactorsFile() or {}
1120+
1121-
for i=1,#entries do
1121+
    if not addr then
1122-
if entries[i].reactorAdr == addr or entries[i].upAdr == addr or entries[i].downAdr == addr then
1122+
        return false
1123-
return true
1123+
    end
1124
    local entries = readReactorsFile() or {}
1125
    for i = 1, #entries do
1126-
return false
1126+
        if entries[i].reactorAdr == addr or entries[i].upAdr == addr or entries[i].downAdr == addr then
1127
            return true
1128
        end
1129
    end
1130-
if not reactorAdr then
1130+
    return false
1131-
return false
1131+
1132
1133-
local entries = readReactorsFile() or {}
1133+
1134-
local newEntries = {}
1134+
    if not reactorAdr then
1135-
local removed = false
1135+
        return false
1136-
for i=1,#entries do
1136+
    end
1137-
if entries[i].reactorAdr ~= reactorAdr then
1137+
    local entries = readReactorsFile() or {}
1138-
newEntries[#newEntries+1] = entries[i]
1138+
    local newEntries = {}
1139-
else
1139+
    local removed = false
1140-
removed = true
1140+
    for i = 1, #entries do
1141
        if entries[i].reactorAdr ~= reactorAdr then
1142
            newEntries[#newEntries + 1] = entries[i]
1143-
if removed then
1143+
        else
1144-
writeReactorsFile(newEntries)
1144+
            removed = true
1145
        end
1146-
return removed
1146+
    end
1147
    if removed then
1148
        writeReactorsFile(newEntries)
1149
    end
1150-
local entries = readReactorsFile() or {}
1150+
    return removed
1151-
if #entries >= MAX_REACTORS then
1151+
1152-
easyAssign.active = false
1152+
1153-
easyAssign.message = "Достигнут лимит реакторов."
1153+
1154-
return
1154+
    local entries = readReactorsFile() or {}
1155
    if #entries >= MAX_REACTORS then
1156-
if not getChatBox() then
1156+
        easyAssign.active = false
1157-
easyAssign.active = false
1157+
        easyAssign.message = "Достигнут лимит реакторов."
1158-
easyAssign.message = "Ошибка: для работы нужен chat_box."
1158+
        return
1159-
return
1159+
    end
1160
    if not getChatBox() then
1161-
easyAssign.active = true
1161+
        easyAssign.active = false
1162-
easyAssign.step = "reactor"
1162+
        easyAssign.message = "Ошибка: для работы нужен chat_box."
1163-
easyAssign.core = nil
1163+
        return
1164-
easyAssign.shield = nil
1164+
    end
1165-
easyAssign.output = nil
1165+
    easyAssign.active = true
1166-
easyAssign.saved = false
1166+
    easyAssign.step = "reactor"
1167-
easyAssign.message = nil
1167+
    easyAssign.core = nil
1168-
easyAssign.index = #entries + 1
1168+
    easyAssign.shield = nil
1169-
easyAssign.lastChatStep = nil
1169+
    easyAssign.output = nil
1170-
easyAssign.lastChatMessage = nil
1170+
    easyAssign.saved = false
1171-
initEasyKnown()
1171+
    easyAssign.message = nil
1172-
maybeChatSay("intro", "Легкий режим: подключите адаптер к реактору #" .. tostring(easyAssign.index) .. " и смотрите монитор.")
1172+
    easyAssign.index = #entries + 1
1173
    easyAssign.lastChatStep = nil
1174
    easyAssign.lastChatMessage = nil
1175
    initEasyKnown()
1176-
handleMain = false
1176+
    maybeChatSay("intro", "Легкий режим: подключите адаптер к реактору #" .. tostring(easyAssign.index) .. " и смотрите монитор.")
1177-
handleStart = false
1177+
1178-
handleOptions = false
1178+
1179-
handleOverview = false
1179+
1180-
handleAssign = true
1180+
    handleMain = false
1181-
local x = drawHeader("HiTech Classic is the best   (Гейты)")
1181+
    handleStart = false
1182-
drawSeparator(x)
1182+
    handleOptions = false
1183-
assignUi.reactors = {}
1183+
    handleOverview = false
1184-
assignUi.gates = {}
1184+
    handleAssign = true
1185-
assignUi.gateAddrs = {}
1185+
    local x = drawHeader("HiTech Classic is the best   (Гейты)")
1186-
assignUi.reactorAddrs = {}
1186+
    drawSeparator(x)
1187-
assignUi.gateUse = {}
1187+
    assignUi.reactors = {}
1188-
assignUi.selectedAdr = nil
1188+
    assignUi.gates = {}
1189
    assignUi.gateAddrs = {}
1190
    assignUi.reactorAddrs = {}
1191-
gpu.fill(1,4,x,21," ")
1191+
    assignUi.gateUse = {}
1192-
term.setCursor(1,2)
1192+
    assignUi.selectedAdr = nil
1193-
menuItem.back.x,menuItem.back.y = term.getCursor()
1193+
    gpu.setBackground(color.grey)
1194-
assignUi.back.x,assignUi.back.y,assignUi.back.w = menuItem.back.x,menuItem.back.y,textWidth(menuItem.back.name)
1194+
    gpu.setForeground(color.white)
1195-
gpu.setForeground(color.blue)
1195+
    gpu.fill(1, 4, x, 21, " ")
1196-
printf(menuItem.back.name)
1196+
    term.setCursor(1, 2)
1197-
menuItem.back.w = textWidth(menuItem.back.name)
1197+
    menuItem.back.x, menuItem.back.y = term.getCursor()
1198
    assignUi.back.x, assignUi.back.y, assignUi.back.w = menuItem.back.x, menuItem.back.y, textWidth(menuItem.back.name)
1199-
term.setCursor(2,5)
1199+
    gpu.setForeground(color.blue)
1200-
printf("Выберите способ добавления гейтов:")
1200+
    printf(menuItem.back.name)
1201-
local heavyLabel = " Тяжелый способ (анализатор) "
1201+
    menuItem.back.w = textWidth(menuItem.back.name)
1202-
local easyLabel = " Легкий способ (подключение) "
1202+
    gpu.setForeground(color.white)
1203-
local heavyX, heavyY = 2, 7
1203+
    term.setCursor(2, 5)
1204-
local easyX, easyY = 2, 9
1204+
    printf("Выберите способ добавления гейтов:")
1205-
easyAssign.heavyBtn = {x=heavyX,y=heavyY,w=textWidth(heavyLabel)}
1205+
    local heavyLabel = " Тяжелый способ (анализатор) "
1206-
easyAssign.easyBtn = {x=easyX,y=easyY,w=textWidth(easyLabel)}
1206+
    local easyLabel = " Легкий способ (подключение) "
1207-
guiWrite(heavyX,heavyY,color.white,color.red,"%s",heavyLabel)
1207+
    local heavyX, heavyY = 2, 7
1208-
guiWrite(easyX,easyY,color.white,color.green,"%s",easyLabel)
1208+
    local easyX, easyY = 2, 9
1209-
if easyAssign.message then
1209+
    easyAssign.heavyBtn = {x = heavyX, y = heavyY, w = textWidth(heavyLabel)}
1210-
guiWrite(2,12,color.yellow,-1,"%s",easyAssign.message)
1210+
    easyAssign.easyBtn = {x = easyX, y = easyY, w = textWidth(easyLabel)}
1211
    guiWrite(heavyX, heavyY, color.white, color.red, "%s", heavyLabel)
1212
    guiWrite(easyX, easyY, color.white, color.green, "%s", easyLabel)
1213
    if easyAssign.message then
1214
        guiWrite(2, 12, color.yellow, -1, "%s", easyAssign.message)
1215-
handleMain = false
1215+
    end
1216-
handleStart = false
1216+
1217-
handleOptions = false
1217+
1218-
handleOverview = false
1218+
1219-
handleAssign = true
1219+
    handleMain = false
1220-
local x = drawHeader("HiTech Classic is the best   (Гейты - Легкий)")
1220+
    handleStart = false
1221-
drawSeparator(x)
1221+
    handleOptions = false
1222
    handleOverview = false
1223
    handleAssign = true
1224-
gpu.fill(1,4,x,21," ")
1224+
    local x = drawHeader("HiTech Classic is the best   (Гейты - Легкий)")
1225-
term.setCursor(1,2)
1225+
    drawSeparator(x)
1226-
menuItem.back.x,menuItem.back.y = term.getCursor()
1226+
    gpu.setBackground(color.grey)
1227-
easyAssign.backBtn = {x=menuItem.back.x,y=menuItem.back.y,w=textWidth(menuItem.back.name)}
1227+
    gpu.setForeground(color.white)
1228-
gpu.setForeground(color.blue)
1228+
    gpu.fill(1, 4, x, 21, " ")
1229-
printf(menuItem.back.name)
1229+
    term.setCursor(1, 2)
1230-
menuItem.back.w = textWidth(menuItem.back.name)
1230+
    menuItem.back.x, menuItem.back.y = term.getCursor()
1231
    easyAssign.backBtn = {x = menuItem.back.x, y = menuItem.back.y, w = textWidth(menuItem.back.name)}
1232-
term.setCursor(2,5)
1232+
    gpu.setForeground(color.blue)
1233-
printf("РЕАКТОР #%d", easyAssign.index or 1)
1233+
    printf(menuItem.back.name)
1234-
term.setCursor(2,7)
1234+
    menuItem.back.w = textWidth(menuItem.back.name)
1235-
if easyAssign.step == "reactor" then
1235+
    gpu.setForeground(color.white)
1236-
guiWrite(2,7,color.green,-1,"Подключите адаптер к ядру реактора.")
1236+
    term.setCursor(2, 5)
1237-
maybeChatSay("reactor", "Подключите адаптер к ядру реактора.", 255)
1237+
    printf("РЕАКТОР #%d", easyAssign.index or 1)
1238-
elseif easyAssign.step == "shield" then
1238+
    term.setCursor(2, 7)
1239-
guiWrite(2,7,color.green,-1,"Подключите адаптер к гейту ЩИТОВ.")
1239+
    if easyAssign.step == "reactor" then
1240-
maybeChatSay("shield", "Подключите адаптер к гейту ЩИТОВ.", 4096)
1240+
        guiWrite(2, 7, color.green, -1, "Подключите адаптер к ядру реактора.")
1241-
elseif easyAssign.step == "output" then
1241+
        maybeChatSay("reactor", "Подключите адаптер к ядру реактора.", 255)
1242-
guiWrite(2,7,color.green,-1,"Подключите адаптер к гейту ВЫВОДА.")
1242+
    elseif easyAssign.step == "shield" then
1243-
maybeChatSay("output", "Подключите адаптер к гейту ВЫВОДА.", 16711680)
1243+
        guiWrite(2, 7, color.green, -1, "Подключите адаптер к гейту ЩИТОВ.")
1244-
elseif easyAssign.step == "done" then
1244+
        maybeChatSay("shield", "Подключите адаптер к гейту ЩИТОВ.", 4096)
1245-
guiWrite(2,7,color.green,-1,"Реактор добавлен.")
1245+
    elseif easyAssign.step == "output" then
1246-
maybeChatSay("done", "Реактор добавлен. Смотрите монитор.", 65280)
1246+
        guiWrite(2, 7, color.green, -1, "Подключите адаптер к гейту ВЫВОДА.")
1247
        maybeChatSay("output", "Подключите адаптер к гейту ВЫВОДА.", 16711680)
1248-
term.setCursor(2,9)
1248+
    elseif easyAssign.step == "done" then
1249-
printf("Ожидаю компонент...")
1249+
        guiWrite(2, 7, color.green, -1, "Реактор добавлен.")
1250-
local infoY = 11
1250+
        maybeChatSay("done", "Реактор добавлен. Смотрите монитор.", 65280)
1251-
local coreLine = "Ядро: " .. (easyAssign.core or "-")
1251+
    end
1252-
local shieldLine = "Щиты: " .. (easyAssign.shield or "-")
1252+
    term.setCursor(2, 9)
1253-
local outputLine = "Вывод: " .. (easyAssign.output or "-")
1253+
    printf("Ожидаю компонент...")
1254-
local coreColor = (easyAssign.step == "reactor") and color.blue or (easyAssign.core and color.green or color.white)
1254+
    local infoY = 11
1255-
local shieldColor = (easyAssign.step == "shield") and color.blue or (easyAssign.shield and color.green or color.white)
1255+
    local coreLine = "Ядро: " .. (easyAssign.core or "-")
1256-
local outputColor = (easyAssign.step == "output") and color.blue or (easyAssign.output and color.green or color.white)
1256+
    local shieldLine = "Щиты: " .. (easyAssign.shield or "-")
1257-
guiWrite(2,infoY,coreColor,-1,"%s",coreLine)
1257+
    local outputLine = "Вывод: " .. (easyAssign.output or "-")
1258-
guiWrite(2,infoY + 1,shieldColor,-1,"%s",shieldLine)
1258+
    local coreColor = (easyAssign.step == "reactor") and color.blue or (easyAssign.core and color.green or color.white)
1259-
guiWrite(2,infoY + 2,outputColor,-1,"%s",outputLine)
1259+
    local shieldColor = (easyAssign.step == "shield") and color.blue or (easyAssign.shield and color.green or color.white)
1260-
if easyAssign.message then
1260+
    local outputColor = (easyAssign.step == "output") and color.blue or (easyAssign.output and color.green or color.white)
1261-
guiWrite(2,infoY + 4,color.yellow,-1,"%s",easyAssign.message)
1261+
    guiWrite(2, infoY, coreColor, -1, "%s", coreLine)
1262
    guiWrite(2, infoY + 1, shieldColor, -1, "%s", shieldLine)
1263-
if easyAssign.step == "done" then
1263+
    guiWrite(2, infoY + 2, outputColor, -1, "%s", outputLine)
1264-
local contLabel = " [Продолжить] "
1264+
    if easyAssign.message then
1265-
local finLabel = " [Завершить] "
1265+
        guiWrite(2, infoY + 4, color.yellow, -1, "%s", easyAssign.message)
1266-
local contX, contY = 2, infoY + 6
1266+
    end
1267-
local finX, finY = 2 + textWidth(contLabel) + 2, infoY + 6
1267+
    if easyAssign.step == "done" then
1268-
easyAssign.continueBtn = {x=contX,y=contY,w=textWidth(contLabel)}
1268+
        local contLabel = " [Продолжить] "
1269-
easyAssign.finishBtn = {x=finX,y=finY,w=textWidth(finLabel)}
1269+
        local finLabel = " [Завершить] "
1270-
guiWrite(contX,contY,color.white,color.green,"%s",contLabel)
1270+
        local contX, contY = 2, infoY + 6
1271-
guiWrite(finX,finY,color.white,color.red,"%s",finLabel)
1271+
        local finX, finY = 2 + textWidth(contLabel) + 2, infoY + 6
1272
        easyAssign.continueBtn = {x = contX, y = contY, w = textWidth(contLabel)}
1273
        easyAssign.finishBtn = {x = finX, y = finY, w = textWidth(finLabel)}
1274
        guiWrite(contX, contY, color.white, color.green, "%s", contLabel)
1275
        guiWrite(finX, finY, color.white, color.red, "%s", finLabel)
1276-
handleMain = false
1276+
    end
1277-
handleStart = false
1277+
1278-
handleOptions = false
1278+
1279-
handleOverview = false
1279+
1280-
handleAssign = true
1280+
    handleMain = false
1281-
local x = drawHeader("HiTech Classic is the best   (Гейты)")
1281+
    handleStart = false
1282-
drawSeparator(x)
1282+
    handleOptions = false
1283-
assignUi.reactors = {}
1283+
    handleOverview = false
1284-
assignUi.gates = {}
1284+
    handleAssign = true
1285-
assignUi.gateAddrs = {}
1285+
    local x = drawHeader("HiTech Classic is the best   (Гейты)")
1286-
assignUi.reactorAddrs = {}
1286+
    drawSeparator(x)
1287-
assignUi.gateUse = {}
1287+
    assignUi.reactors = {}
1288-
assignUi.selectedAdr = nil
1288+
    assignUi.gates = {}
1289
    assignUi.gateAddrs = {}
1290
    assignUi.reactorAddrs = {}
1291-
gpu.fill(1,4,x,21," ")
1291+
    assignUi.gateUse = {}
1292-
term.setCursor(1,2)
1292+
    assignUi.selectedAdr = nil
1293-
menuItem.back.x,menuItem.back.y = term.getCursor()
1293+
    gpu.setBackground(color.grey)
1294-
assignUi.back.x,assignUi.back.y,assignUi.back.w = menuItem.back.x,menuItem.back.y,textWidth(menuItem.back.name)
1294+
    gpu.setForeground(color.white)
1295-
gpu.setForeground(color.blue)
1295+
    gpu.fill(1, 4, x, 21, " ")
1296-
printf(menuItem.back.name)
1296+
    term.setCursor(1, 2)
1297-
menuItem.back.w = textWidth(menuItem.back.name)
1297+
    menuItem.back.x, menuItem.back.y = term.getCursor()
1298
    assignUi.back.x, assignUi.back.y, assignUi.back.w = menuItem.back.x, menuItem.back.y, textWidth(menuItem.back.name)
1299-
term.setCursor(2,4)
1299+
    gpu.setForeground(color.blue)
1300-
printf("Выберите реактор")
1300+
    printf(menuItem.back.name)
1301-
local reactorsList = listAddresses("draconic_reactor")
1301+
    menuItem.back.w = textWidth(menuItem.back.name)
1302-
local gates = listAddresses("flux_gate")
1302+
    gpu.setForeground(color.white)
1303-
assignUi.gateAddrs = gates
1303+
    term.setCursor(2, 4)
1304-
assignUi.reactorAddrs = reactorsList
1304+
    printf("Выберите реактор")
1305-
if #reactorsList == 0 or #gates < 2 then
1305+
    local reactorsList = listAddresses("draconic_reactor")
1306-
printf("Недостаточно реакторов или флюкс-гейтов.\n")
1306+
    local gates = listAddresses("flux_gate")
1307-
os.sleep(1)
1307+
    assignUi.gateAddrs = gates
1308-
screenOverview()
1308+
    assignUi.reactorAddrs = reactorsList
1309-
return
1309+
    if #reactorsList == 0 or #gates < 2 then
1310
        printf("Недостаточно реакторов или флюкс-гейтов.\n")
1311-
local count = math.min(#reactorsList, MAX_REACTORS)
1311+
        os.sleep(1)
1312-
term.setCursor(2,5)
1312+
        screenOverview()
1313-
printf("Реакторы:")
1313+
        return
1314-
local rowY = 6
1314+
    end
1315-
for i=1,count do
1315+
    local count = math.min(#reactorsList, MAX_REACTORS)
1316-
term.setCursor(2,rowY)
1316+
    term.setCursor(2, 5)
1317-
local label = string.format("%d) %s",i,reactorsList[i])
1317+
    printf("Реакторы:")
1318-
if assignState.reactorIndex == i then
1318+
    local rowY = 6
1319-
guiWrite(2,rowY,color.black,color.blue,"%s",label)
1319+
    for i = 1, count do
1320-
else
1320+
        term.setCursor(2, rowY)
1321-
guiWrite(2,rowY,color.white,-1,"%s",label)
1321+
        local label = string.format("%d) %s", i, reactorsList[i])
1322
        if assignState.reactorIndex == i then
1323-
assignUi.reactors[i] = {x=2,y=rowY,w=textWidth(label)}
1323+
            guiWrite(2, rowY, color.black, color.blue, "%s", label)
1324-
rowY = rowY + 1
1324+
        else
1325
            guiWrite(2, rowY, color.white, -1, "%s", label)
1326
        end
1327-
local entries = readReactorsFile() or {}
1327+
        assignUi.reactors[i] = {x = 2, y = rowY, w = textWidth(label)}
1328-
local gateUse = {}
1328+
        rowY = rowY + 1
1329-
for i=1,#entries do
1329+
    end
1330-
gateUse[entries[i].upAdr] = entries[i].reactorAdr
1330+
1331-
gateUse[entries[i].downAdr] = entries[i].reactorAdr
1331+
    local entries = readReactorsFile() or {}
1332
    local gateUse = {}
1333-
assignUi.gateUse = gateUse
1333+
    for i = 1, #entries do
1334-
local selectedAdr = assignState.reactorIndex and reactorsList[assignState.reactorIndex] or nil
1334+
        gateUse[entries[i].upAdr] = entries[i].reactorAdr
1335-
assignUi.selectedAdr = selectedAdr
1335+
        gateUse[entries[i].downAdr] = entries[i].reactorAdr
1336-
local selectedEntry = nil
1336+
    end
1337-
if selectedAdr then
1337+
    assignUi.gateUse = gateUse
1338-
for i=1,#entries do
1338+
    local selectedAdr = assignState.reactorIndex and reactorsList[assignState.reactorIndex] or nil
1339-
if entries[i].reactorAdr == selectedAdr then
1339+
    assignUi.selectedAdr = selectedAdr
1340-
selectedEntry = entries[i]
1340+
    local selectedEntry = nil
1341-
break
1341+
    if selectedAdr then
1342
        for i = 1, #entries do
1343
            if entries[i].reactorAdr == selectedAdr then
1344
                selectedEntry = entries[i]
1345-
assignUi.selectedEntry = selectedEntry
1345+
                break
1346
            end
1347-
term.setCursor(40,5)
1347+
        end
1348-
printf("Гейты:")
1348+
    end
1349-
local gateY = 6
1349+
    assignUi.selectedEntry = selectedEntry
1350-
for i=1,#gates do
1350+
1351-
if gateY > 24 then
1351+
    term.setCursor(40, 5)
1352-
break
1352+
    printf("Гейты:")
1353
    local gateY = 6
1354-
term.setCursor(40,gateY)
1354+
    for i = 1, #gates do
1355-
local label = string.format("%d) %s",i,gates[i])
1355+
        if gateY > 24 then
1356-
local colorGate = color.dim
1356+
            break
1357-
if selectedAdr then
1357+
        end
1358-
if selectedEntry and (gates[i] == selectedEntry.upAdr or gates[i] == selectedEntry.downAdr) then
1358+
        term.setCursor(40, gateY)
1359-
colorGate = color.green
1359+
        local label = string.format("%d) %s", i, gates[i])
1360-
elseif assignState.shieldGateIdx == i or assignState.outGateIdx == i then
1360+
        local colorGate = color.dim
1361-
colorGate = color.green
1361+
        if selectedAdr then
1362-
elseif gateUse[gates[i]] and gateUse[gates[i]] ~= selectedAdr then
1362+
            if selectedEntry and (gates[i] == selectedEntry.upAdr or gates[i] == selectedEntry.downAdr) then
1363-
colorGate = color.red
1363+
                colorGate = color.green
1364-
else
1364+
            elseif assignState.shieldGateIdx == i or assignState.outGateIdx == i then
1365-
colorGate = color.dim
1365+
                colorGate = color.green
1366
            elseif gateUse[gates[i]] and gateUse[gates[i]] ~= selectedAdr then
1367
                colorGate = color.red
1368-
guiWrite(40,gateY,colorGate,-1,"%s",label)
1368+
            else
1369-
assignUi.gates[i] = {x=40,y=gateY,w=textWidth(label)}
1369+
                colorGate = color.dim
1370-
gateY = gateY + 1
1370+
            end
1371
        end
1372
        guiWrite(40, gateY, colorGate, -1, "%s", label)
1373
        assignUi.gates[i] = {x = 40, y = gateY, w = textWidth(label)}
1374
        gateY = gateY + 1
1375-
if assignMode == "manual" then
1375+
    end
1376-
screenAssignManual()
1376+
1377-
elseif assignMode == "easy" then
1377+
1378-
screenAssignEasy()
1378+
1379-
else
1379+
    if assignMode == "manual" then
1380-
screenAssignChoice()
1380+
        screenAssignManual()
1381
    elseif assignMode == "easy" then
1382
        screenAssignEasy()
1383
    else
1384
        screenAssignChoice()
1385-
if easyAssign.step == "reactor" then
1385+
    end
1386-
if componentType ~= "draconic_reactor" then
1386+
1387-
easyAssign.message = "Нужен draconic_reactor."
1387+
1388-
screenAssignEasy()
1388+
1389-
return
1389+
    if easyAssign.step == "reactor" then
1390
        if componentType ~= "draconic_reactor" then
1391-
if isAddressUsed(address) then
1391+
            easyAssign.message = "Нужен draconic_reactor."
1392-
easyAssign.message = "Адрес уже используется."
1392+
            screenAssignEasy()
1393-
screenAssignEasy()
1393+
            return
1394-
return
1394+
        end
1395
        if isAddressUsed(address) then
1396-
easyAssign.core = address
1396+
            easyAssign.message = "Адрес уже используется."
1397-
easyAssign.step = "shield"
1397+
            screenAssignEasy()
1398-
easyAssign.message = "Реактор принят."
1398+
            return
1399-
maybeChatSay("accepted", "Реактор принят. Смотри монитор.")
1399+
        end
1400-
screenAssignEasy()
1400+
        easyAssign.core = address
1401-
return
1401+
        easyAssign.step = "shield"
1402
        easyAssign.message = "Реактор принят."
1403-
if easyAssign.step == "shield" then
1403+
        maybeChatSay("accepted", "Реактор принят. Смотри монитор.")
1404-
if componentType ~= "flux_gate" then
1404+
        screenAssignEasy()
1405-
easyAssign.message = "Нужен flux_gate."
1405+
        return
1406-
screenAssignEasy()
1406+
    end
1407-
return
1407+
    if easyAssign.step == "shield" then
1408
        if componentType ~= "flux_gate" then
1409-
if isAddressUsed(address) then
1409+
            easyAssign.message = "Нужен flux_gate."
1410-
easyAssign.message = "Адрес уже используется."
1410+
            screenAssignEasy()
1411-
screenAssignEasy()
1411+
            return
1412-
return
1412+
        end
1413
        if isAddressUsed(address) then
1414-
easyAssign.shield = address
1414+
            easyAssign.message = "Адрес уже используется."
1415-
easyAssign.step = "output"
1415+
            screenAssignEasy()
1416-
easyAssign.message = "Гейт щитов принят."
1416+
            return
1417-
maybeChatSay("accepted", "Гейт щитов принят. Смотри монитор.")
1417+
        end
1418-
screenAssignEasy()
1418+
        easyAssign.shield = address
1419-
return
1419+
        easyAssign.step = "output"
1420
        easyAssign.message = "Гейт щитов принят."
1421-
if easyAssign.step == "output" then
1421+
        maybeChatSay("accepted", "Гейт щитов принят. Смотри монитор.")
1422-
if componentType ~= "flux_gate" then
1422+
        screenAssignEasy()
1423-
easyAssign.message = "Нужен flux_gate."
1423+
        return
1424-
screenAssignEasy()
1424+
    end
1425-
return
1425+
    if easyAssign.step == "output" then
1426
        if componentType ~= "flux_gate" then
1427-
if isAddressUsed(address) or address == easyAssign.shield then
1427+
            easyAssign.message = "Нужен flux_gate."
1428-
easyAssign.message = "Нужны два разных гейта."
1428+
            screenAssignEasy()
1429-
screenAssignEasy()
1429+
            return
1430-
return
1430+
        end
1431
        if isAddressUsed(address) or address == easyAssign.shield then
1432-
easyAssign.output = address
1432+
            easyAssign.message = "Нужны два разных гейта."
1433-
local saved = saveAssignedGates(easyAssign.core, easyAssign.shield, easyAssign.output)
1433+
            screenAssignEasy()
1434-
if not saved then
1434+
            return
1435-
easyAssign.message = "Не удалось сохранить."
1435+
        end
1436-
screenAssignEasy()
1436+
        easyAssign.output = address
1437-
return
1437+
        local saved = saveAssignedGates(easyAssign.core, easyAssign.shield, easyAssign.output)
1438
        if not saved then
1439-
easyAssign.saved = true
1439+
            easyAssign.message = "Не удалось сохранить."
1440-
easyAssign.step = "done"
1440+
            screenAssignEasy()
1441-
easyAssign.message = "Успешно сохранено."
1441+
            return
1442-
maybeChatSay("accepted", "Успешно сохранено. Смотри монитор.")
1442+
        end
1443-
screenAssignEasy()
1443+
        easyAssign.saved = true
1444-
return
1444+
        easyAssign.step = "done"
1445
        easyAssign.message = "Успешно сохранено."
1446
        maybeChatSay("accepted", "Успешно сохранено. Смотри монитор.")
1447
        screenAssignEasy()
1448
        return
1449-
if not handleAssign or assignMode ~= "easy" or not easyAssign.active then
1449+
    end
1450-
return
1450+
1451
1452-
acceptEasyComponent(address, componentType)
1452+
1453
    if not handleAssign or assignMode ~= "easy" or not easyAssign.active then
1454
        return
1455
    end
1456-
if not handleAssign or assignMode ~= "easy" or not easyAssign.active then
1456+
    acceptEasyComponent(address, componentType)
1457-
return
1457+
1458
1459-
if easyAssign.step == "reactor" then
1459+
1460-
local addr = findNewComponent("draconic_reactor")
1460+
    if not handleAssign or assignMode ~= "easy" or not easyAssign.active then
1461-
if addr then
1461+
        return
1462-
acceptEasyComponent(addr, "draconic_reactor")
1462+
    end
1463
    if easyAssign.step == "reactor" then
1464-
elseif easyAssign.step == "shield" or easyAssign.step == "output" then
1464+
        local addr = findNewComponent("draconic_reactor")
1465-
local addr = findNewComponent("flux_gate")
1465+
        if addr then
1466-
if addr then
1466+
            acceptEasyComponent(addr, "draconic_reactor")
1467-
acceptEasyComponent(addr, "flux_gate")
1467+
        end
1468
    elseif easyAssign.step == "shield" or easyAssign.step == "output" then
1469
        local addr = findNewComponent("flux_gate")
1470
        if addr then
1471
            acceptEasyComponent(addr, "flux_gate")
1472
        end
1473
    end
1474
end
1475-
autoWaitTempByAdr = {}
1475+
1476-
chargeRequestByAdr = {}
1476+
1477-
for i=1,#reactors do
1477+
    autostateByAdr = {}
1478-
local r = reactors[i]
1478+
    flowInitByAdr = {}
1479-
autostateByAdr[r.reactorAdr] = r.autostate
1479+
    autoWaitTempByAdr = {}
1480-
flowInitByAdr[r.reactorAdr] = r.flowInit
1480+
    chargeRequestByAdr = {}
1481-
chargeRequestByAdr[r.reactorAdr] = r.chargeRequested
1481+
    for i = 1, #reactors do
1482
        local r = reactors[i]
1483-
syncActive()
1483+
        autostateByAdr[r.reactorAdr] = r.autostate
1484-
local prevAdr = reactors[activeIndex] and reactors[activeIndex].reactorAdr
1484+
        flowInitByAdr[r.reactorAdr] = r.flowInit
1485-
reactors = buildReactors() or reactors
1485+
        chargeRequestByAdr[r.reactorAdr] = r.chargeRequested
1486-
local idx = 1
1486+
    end
1487-
if pendingActiveReactorAdr then
1487+
    syncActive()
1488-
for i=1,#reactors do
1488+
    local prevAdr = reactors[activeIndex] and reactors[activeIndex].reactorAdr
1489-
if reactors[i].reactorAdr == pendingActiveReactorAdr then
1489+
    reactors = buildReactors() or reactors
1490-
idx = i
1490+
    local idx = 1
1491-
break
1491+
    if pendingActiveReactorAdr then
1492
        for i = 1, #reactors do
1493
            if reactors[i].reactorAdr == pendingActiveReactorAdr then
1494-
pendingActiveReactorAdr = nil
1494+
                idx = i
1495-
elseif lastAddedReactorAdr then
1495+
                break
1496-
for i=1,#reactors do
1496+
            end
1497-
if reactors[i].reactorAdr == lastAddedReactorAdr then
1497+
        end
1498-
idx = i
1498+
        pendingActiveReactorAdr = nil
1499-
break
1499+
    elseif lastAddedReactorAdr then
1500
        for i = 1, #reactors do
1501
            if reactors[i].reactorAdr == lastAddedReactorAdr then
1502-
lastAddedReactorAdr = nil
1502+
                idx = i
1503-
elseif prevAdr then
1503+
                break
1504-
for i=1,#reactors do
1504+
            end
1505-
if reactors[i].reactorAdr == prevAdr then
1505+
        end
1506-
idx = i
1506+
        lastAddedReactorAdr = nil
1507-
break
1507+
    elseif prevAdr then
1508
        for i = 1, #reactors do
1509
            if reactors[i].reactorAdr == prevAdr then
1510
                idx = i
1511-
setActive(idx)
1511+
                break
1512-
if openAssign and newEntriesAdded then
1512+
            end
1513-
resetAssignState()
1513+
        end
1514-
screenAssign()
1514+
    end
1515-
return
1515+
    setActive(idx)
1516
    if openAssign and newEntriesAdded then
1517-
if handleMain then
1517+
        resetAssignState()
1518-
screenMain()
1518+
        screenAssign()
1519-
else
1519+
        return
1520-
screenOverview()
1520+
    end
1521
    if handleMain then
1522
        screenMain()
1523
    else
1524
        screenOverview()
1525-
assignState.reactorIndex = nil
1525+
    end
1526-
assignState.reactorAdr = nil
1526+
1527-
assignState.shieldGateIdx = nil
1527+
1528-
assignState.shieldGateAdr = nil
1528+
1529-
assignState.outGateIdx = nil
1529+
    assignState.reactorIndex = nil
1530-
assignState.outGateAdr = nil
1530+
    assignState.reactorAdr = nil
1531-
assignState.step = "reactor"
1531+
    assignState.shieldGateIdx = nil
1532
    assignState.shieldGateAdr = nil
1533
    assignState.outGateIdx = nil
1534
    assignState.outGateAdr = nil
1535-
if not reactorAdr or not shieldAdr or not outAdr then
1535+
    assignState.step = "reactor"
1536-
return false
1536+
1537
1538-
local entries = readReactorsFile() or {}
1538+
1539-
local updated = false
1539+
    if not reactorAdr or not shieldAdr or not outAdr then
1540-
for i=1,#entries do
1540+
        return false
1541-
if entries[i].reactorAdr == reactorAdr then
1541+
    end
1542-
entries[i].upAdr = outAdr
1542+
    local entries = readReactorsFile() or {}
1543-
entries[i].downAdr = shieldAdr
1543+
    local updated = false
1544-
updated = true
1544+
    for i = 1, #entries do
1545-
break
1545+
        if entries[i].reactorAdr == reactorAdr then
1546
            entries[i].upAdr = outAdr
1547
            entries[i].downAdr = shieldAdr
1548-
if not updated then
1548+
            updated = true
1549-
entries[#entries+1] = {
1549+
            break
1550-
reactorAdr = reactorAdr,
1550+
        end
1551-
upAdr = outAdr,
1551+
    end
1552-
downAdr = shieldAdr
1552+
    if not updated then
1553
        entries[#entries + 1] = {
1554
            reactorAdr = reactorAdr,
1555-
if #entries > MAX_REACTORS then
1555+
            upAdr = outAdr,
1556-
local trimmed = {}
1556+
            downAdr = shieldAdr
1557-
for i=1,MAX_REACTORS do
1557+
        }
1558-
trimmed[i] = entries[i]
1558+
    end
1559
    if #entries > MAX_REACTORS then
1560-
entries = trimmed
1560+
        local trimmed = {}
1561
        for i = 1, MAX_REACTORS do
1562-
writeReactorsFile(entries)
1562+
            trimmed[i] = entries[i]
1563-
pendingActiveReactorAdr = reactorAdr
1563+
        end
1564-
return true
1564+
        entries = trimmed
1565
    end
1566
    writeReactorsFile(entries)
1567
    pendingActiveReactorAdr = reactorAdr
1568-
local reactorsList = listAddresses("draconic_reactor")
1568+
    return true
1569-
if not reactorsList[reactorIndex] then
1569+
1570-
return false
1570+
1571
local function clearAssignedGates(reactorIndex)
1572-
local entries = readReactorsFile() or {}
1572+
    local reactorsList = listAddresses("draconic_reactor")
1573-
local newEntries = {}
1573+
    if not reactorsList[reactorIndex] then
1574-
for i=1,#entries do
1574+
        return false
1575-
if entries[i].reactorAdr ~= reactorsList[reactorIndex] then
1575+
    end
1576-
newEntries[#newEntries+1] = entries[i]
1576+
    local entries = readReactorsFile() or {}
1577
    local newEntries = {}
1578
    for i = 1, #entries do
1579-
writeReactorsFile(newEntries)
1579+
        if entries[i].reactorAdr ~= reactorsList[reactorIndex] then
1580-
return true
1580+
            newEntries[#newEntries + 1] = entries[i]
1581
        end
1582-
-- Экран обзора реакторов
1582+
    end
1583
    writeReactorsFile(newEntries)
1584-
handleMain = false
1584+
    return true
1585-
handleStart = false
1585+
1586-
handleOptions = false
1586+
1587-
handleOverview = true
1587+
1588-
handleAssign = false
1588+
    handleMain = false
1589-
local x = drawHeader("HiTech Classic is the best")
1589+
    handleStart = false
1590-
reactors = reactors or {}
1590+
    handleOptions = false
1591-
local cols = overviewCols(x)
1591+
    handleOverview = true
1592-
term.setCursor(1,2)
1592+
    handleAssign = false
1593-
menuItem.options.x,menuItem.options.y = term.getCursor()
1593+
    local x = drawHeader("HiTech Classic is the best")
1594-
gpu.setForeground(color.blue)
1594+
    reactors = reactors or {}
1595-
printf(menuItem.options.name)
1595+
    local cols = overviewCols(x)
1596-
menuItem.options.w = textWidth(menuItem.options.name)
1596+
    term.setCursor(1, 2)
1597
    menuItem.options.x, menuItem.options.y = term.getCursor()
1598-
menuItem.overview.x,menuItem.overview.y = term.getCursor()
1598+
    gpu.setForeground(color.blue)
1599-
gpu.setForeground(color.blue)
1599+
    printf(menuItem.options.name)
1600-
printf(menuItem.overview.name)
1600+
    menuItem.options.w = textWidth(menuItem.options.name)
1601-
menuItem.overview.w = textWidth(menuItem.overview.name)
1601+
    gpu.setForeground(color.white)
1602
    menuItem.overview.x, menuItem.overview.y = term.getCursor()
1603-
menuItem.refresh.x,menuItem.refresh.y = term.getCursor()
1603+
    gpu.setForeground(color.blue)
1604-
gpu.setForeground(color.blue)
1604+
    printf(menuItem.overview.name)
1605-
printf(menuItem.refresh.name)
1605+
    menuItem.overview.w = textWidth(menuItem.overview.name)
1606-
menuItem.refresh.w = textWidth(menuItem.refresh.name)
1606+
    gpu.setForeground(color.white)
1607
    menuItem.refresh.x, menuItem.refresh.y = term.getCursor()
1608-
menuItem.gates.x,menuItem.gates.y = term.getCursor()
1608+
    gpu.setForeground(color.blue)
1609-
gpu.setForeground(color.blue)
1609+
    printf(menuItem.refresh.name)
1610-
printf(menuItem.gates.name)
1610+
    menuItem.refresh.w = textWidth(menuItem.refresh.name)
1611-
menuItem.gates.w = textWidth(menuItem.gates.name)
1611+
    gpu.setForeground(color.white)
1612
    menuItem.gates.x, menuItem.gates.y = term.getCursor()
1613-
for i=1,#reactors do
1613+
    gpu.setForeground(color.blue)
1614-
local label = string.format("[R%d]",i)
1614+
    printf(menuItem.gates.name)
1615-
reactors[i].tab.x,reactors[i].tab.y = term.getCursor()
1615+
    menuItem.gates.w = textWidth(menuItem.gates.name)
1616-
reactors[i].tab.w = textWidth(label)
1616+
    gpu.setForeground(color.white)
1617-
if i == activeIndex then
1617+
    for i = 1, #reactors do
1618-
guiWrite(reactors[i].tab.x,reactors[i].tab.y,color.black,color.orange,"%s",label)
1618+
        local label = string.format("[R%d]", i)
1619-
else
1619+
        reactors[i].tab.x, reactors[i].tab.y = term.getCursor()
1620-
guiWrite(reactors[i].tab.x,reactors[i].tab.y,color.blue,color.white,"%s",label)
1620+
        reactors[i].tab.w = textWidth(label)
1621
        if i == activeIndex then
1622-
printf(" ")
1622+
            guiWrite(reactors[i].tab.x, reactors[i].tab.y, color.black, color.orange, "%s", label)
1623
        else
1624-
drawSeparator(x)
1624+
            guiWrite(reactors[i].tab.x, reactors[i].tab.y, color.blue, color.white, "%s", label)
1625
        end
1626
        printf(" ")
1627-
gpu.fill(1,4,x,21," ")
1627+
    end
1628-
if #reactors == 0 then
1628+
    drawSeparator(x)
1629-
term.setCursor(2,5)
1629+
    gpu.setBackground(color.grey)
1630-
printf("Нет настроенных реакторов.")
1630+
    gpu.setForeground(color.white)
1631-
term.setCursor(2,6)
1631+
    gpu.fill(1, 4, x, 21, " ")
1632-
printf("Откройте \"Гейты\" и назначьте гейты.")
1632+
    if #reactors == 0 then
1633-
return
1633+
        term.setCursor(2, 5)
1634
        printf("Нет настроенных реакторов.")
1635
        term.setCursor(2, 6)
1636-
gpu.setBackground(color.panel)
1636+
        printf("Откройте \"Гейты\" и назначьте гейты.")
1637
        return
1638-
gpu.fill(2,4,x-2,6," ")
1638+
    end
1639-
term.setCursor(3,4)
1639+
1640-
printf("Сводка")
1640+
    gpu.setBackground(color.panel)
1641-
term.setCursor(3,5)
1641+
    gpu.setForeground(color.white)
1642-
printf("Суммарная прибыль:")
1642+
    gpu.fill(2, 4, x - 2, 6, " ")
1643-
term.setCursor(28,5)
1643+
    term.setCursor(3, 4)
1644-
getCord(summaryProfitCord)
1644+
    printf("Сводка")
1645-
term.setCursor(3,6)
1645+
    term.setCursor(3, 5)
1646-
printf("Суммарная EU:")
1646+
    printf("Суммарная прибыль:")
1647-
term.setCursor(28,6)
1647+
    term.setCursor(28, 5)
1648-
getCord(summaryEuCord)
1648+
    getCord(summaryProfitCord)
1649-
term.setCursor(3,7)
1649+
    term.setCursor(3, 6)
1650-
printf("Тратим на щиты RF:")
1650+
    printf("Суммарная EU:")
1651-
term.setCursor(28,7)
1651+
    term.setCursor(28, 6)
1652-
getCord(summaryShieldCord)
1652+
    getCord(summaryEuCord)
1653-
term.setCursor(3,8)
1653+
    term.setCursor(3, 7)
1654-
printf("Суммарная выработка:")
1654+
    printf("Тратим на щиты RF:")
1655-
term.setCursor(28,8)
1655+
    term.setCursor(28, 7)
1656-
getCord(summaryGenCord)
1656+
    getCord(summaryShieldCord)
1657-
term.setCursor(3,9)
1657+
    term.setCursor(3, 8)
1658-
printf("Максимум прибыли RF/EU:")
1658+
    printf("Суммарная выработка:")
1659-
term.setCursor(28,9)
1659+
    term.setCursor(28, 8)
1660-
getCord(summaryMaxProfitCord)
1660+
    getCord(summaryGenCord)
1661-
local autoX = math.max(40, x - 33)
1661+
    term.setCursor(3, 9)
1662-
term.setCursor(autoX,4)
1662+
    printf("Максимум прибыли RF/EU:")
1663-
printf("Выключены автоматически:")
1663+
    term.setCursor(28, 9)
1664-
term.setCursor(autoX,5)
1664+
    getCord(summaryMaxProfitCord)
1665-
getCord(autoStoppedCord)
1665+
    local autoX = math.max(40, x - 33)
1666
    term.setCursor(autoX, 4)
1667-
gpu.setBackground(color.dark)
1667+
    printf("Выключены автоматически:")
1668
    term.setCursor(autoX, 5)
1669-
gpu.fill(2,11,x-2,1," ")
1669+
    getCord(autoStoppedCord)
1670-
term.setCursor(2,11)
1670+
1671-
printf("#")
1671+
    gpu.setBackground(color.dark)
1672-
term.setCursor(cols.status,11)
1672+
    gpu.setForeground(color.white)
1673-
printf("СТАТУС")
1673+
    gpu.fill(2, 11, x - 2, 1, " ")
1674-
term.setCursor(cols.temp,11)
1674+
    term.setCursor(2, 11)
1675-
printf(" ТЕМП")
1675+
    printf("#")
1676-
term.setCursor(cols.fuel,11)
1676+
    term.setCursor(cols.status, 11)
1677-
printf("ТОПЛИВО")
1677+
    printf("СТАТУС")
1678-
term.setCursor(cols.profit,11)
1678+
    term.setCursor(cols.temp, 11)
1679-
printf("ПРИБЫЛЬ")
1679+
    printf(" ТЕМП")
1680-
term.setCursor(cols.gen,11)
1680+
    term.setCursor(cols.fuel, 11)
1681-
printf("ГЕН")
1681+
    printf("ТОПЛИВО")
1682-
term.setCursor(cols.flow,11)
1682+
    term.setCursor(cols.profit, 11)
1683-
printf("ПОТОК")
1683+
    printf("ПРИБЫЛЬ")
1684-
term.setCursor(cols.ctrl,11)
1684+
    term.setCursor(cols.gen, 11)
1685-
printf("УПР")
1685+
    printf("ГЕН")
1686-
gpu.setForeground(color.dim)
1686+
    term.setCursor(cols.flow, 11)
1687-
gpu.fill(2,12,x-2,1,"-")
1687+
    printf("ПОТОК")
1688
    term.setCursor(cols.ctrl, 11)
1689
    printf("УПР")
1690-
local rowY = 13
1690+
    gpu.setForeground(color.dim)
1691-
for i=1,#reactors do
1691+
    gpu.fill(2, 12, x - 2, 1, "-")
1692-
local r = reactors[i]
1692+
    gpu.setForeground(color.white)
1693-
term.setCursor(2,rowY)
1693+
    gpu.setBackground(color.grey)
1694-
printf("#%d",i)
1694+
    local rowY = 13
1695-
term.setCursor(cols.status,rowY)
1695+
    for i = 1, #reactors do
1696-
r.row.status = {x=cols.status,y=rowY}
1696+
        local r = reactors[i]
1697-
term.setCursor(cols.temp,rowY)
1697+
        term.setCursor(2, rowY)
1698-
r.row.temp = {x=cols.temp,y=rowY}
1698+
        printf("#%d", i)
1699-
term.setCursor(cols.fuel,rowY)
1699+
        term.setCursor(cols.status, rowY)
1700-
r.row.fuel = {x=cols.fuel,y=rowY}
1700+
        r.row.status = {x = cols.status, y = rowY}
1701-
term.setCursor(cols.profit,rowY)
1701+
        term.setCursor(cols.temp, rowY)
1702-
r.row.profit = {x=cols.profit,y=rowY}
1702+
        r.row.temp = {x = cols.temp, y = rowY}
1703-
term.setCursor(cols.gen,rowY)
1703+
        term.setCursor(cols.fuel, rowY)
1704-
r.row.gen = {x=cols.gen,y=rowY}
1704+
        r.row.fuel = {x = cols.fuel, y = rowY}
1705-
term.setCursor(cols.flow,rowY)
1705+
        term.setCursor(cols.profit, rowY)
1706-
r.row.flow = {x=cols.flow,y=rowY}
1706+
        r.row.profit = {x = cols.profit, y = rowY}
1707-
term.setCursor(cols.ctrl,rowY)
1707+
        term.setCursor(cols.gen, rowY)
1708-
r.control = r.control or {}
1708+
        r.row.gen = {x = cols.gen, y = rowY}
1709-
r.control.dec = {x=cols.ctrl,y=rowY,w=3}
1709+
        term.setCursor(cols.flow, rowY)
1710-
term.setCursor(cols.ctrl + 4,rowY)
1710+
        r.row.flow = {x = cols.flow, y = rowY}
1711-
r.control.inc = {x=cols.ctrl + 4,y=rowY,w=3}
1711+
        term.setCursor(cols.ctrl, rowY)
1712-
term.setCursor(cols.ctrl + 8,rowY)
1712+
        r.control = r.control or {}
1713-
r.control.auto = {x=cols.ctrl + 8,y=rowY,w=4}
1713+
        r.control.dec = {x = cols.ctrl, y = rowY, w = 3}
1714-
term.setCursor(cols.ctrl + 13,rowY)
1714+
        term.setCursor(cols.ctrl + 4, rowY)
1715-
r.powerBtn.x,r.powerBtn.y = term.getCursor()
1715+
        r.control.inc = {x = cols.ctrl + 4, y = rowY, w = 3}
1716-
r.powerBtn.w = 3
1716+
        term.setCursor(cols.ctrl + 8, rowY)
1717-
rowY = rowY + 1
1717+
        r.control.auto = {x = cols.ctrl + 8, y = rowY, w = 4}
1718
        term.setCursor(cols.ctrl + 13, rowY)
1719
        r.powerBtn.x, r.powerBtn.y = term.getCursor()
1720-
-- Инициализация главного экрана
1720+
        r.powerBtn.w = 3
1721
        rowY = rowY + 1
1722-
handleOptions = false
1722+
    end
1723-
handleStart = false
1723+
1724-
handleMain = true
1724+
1725-
handleOverview = false
1725+
1726-
handleAssign = false
1726+
    handleOptions = false
1727-
if not reactor or not upgate or not downgate then
1727+
    handleStart = false
1728-
screenOverview()
1728+
    handleMain = true
1729-
return
1729+
    handleOverview = false
1730
    handleAssign = false
1731-
if reactors[activeIndex] and (not isComponentAlive(reactors[activeIndex].reactorAdr) or not isComponentAlive(reactors[activeIndex].upAdr) or not isComponentAlive(reactors[activeIndex].downAdr)) then
1731+
    if not reactor or not upgate or not downgate then
1732-
refreshReactors(false)
1732+
        screenOverview()
1733-
screenOverview()
1733+
        return
1734-
return
1734+
    end
1735
    if reactors[activeIndex] and (not isComponentAlive(reactors[activeIndex].reactorAdr) or
1736-
local x = drawHeader("HiTech Classic is the best")
1736+
        not isComponentAlive(reactors[activeIndex].upAdr) or
1737-
local ok, inf = pcall(reactor.getReactorInfo)
1737+
        not isComponentAlive(reactors[activeIndex].downAdr)) then
1738-
if not ok or type(inf) ~= "table" then
1738+
        refreshReactors(false)
1739-
refreshReactors(false)
1739+
        screenOverview()
1740-
screenOverview()
1740+
        return
1741-
return
1741+
    end
1742
    local x = drawHeader("HiTech Classic is the best")
1743-
if reactors[activeIndex] and (not isComponentAlive(reactors[activeIndex].reactorAdr) or not isComponentAlive(reactors[activeIndex].upAdr) or not isComponentAlive(reactors[activeIndex].downAdr)) then
1743+
    local ok, inf = pcall(reactor.getReactorInfo)
1744-
refreshReactors(false)
1744+
    if not ok or type(inf) ~= "table" then
1745-
screenOverview()
1745+
        refreshReactors(false)
1746-
return
1746+
        screenOverview()
1747
        return
1748-
infcord.status.value = inf.status
1748+
    end
1749-
menuItem.options.x,menuItem.options.y =term.getCursor()
1749+
    if reactors[activeIndex] and (not isComponentAlive(reactors[activeIndex].reactorAdr) or
1750-
gpu.setForeground(color.blue)
1750+
        not isComponentAlive(reactors[activeIndex].upAdr) or
1751-
printf(menuItem.options.name)
1751+
        not isComponentAlive(reactors[activeIndex].downAdr)) then
1752-
menuItem.options.w = textWidth(menuItem.options.name)
1752+
        refreshReactors(false)
1753
        screenOverview()
1754-
menuItem.overview.x,menuItem.overview.y = term.getCursor()
1754+
        return
1755-
gpu.setForeground(color.blue)
1755+
    end
1756-
printf(menuItem.overview.name)
1756+
    infcord.status.value = inf.status
1757-
menuItem.overview.w = textWidth(menuItem.overview.name)
1757+
    menuItem.options.x, menuItem.options.y = term.getCursor()
1758
    gpu.setForeground(color.blue)
1759-
menuItem.refresh.x,menuItem.refresh.y = term.getCursor()
1759+
    printf(menuItem.options.name)
1760-
gpu.setForeground(color.blue)
1760+
    menuItem.options.w = textWidth(menuItem.options.name)
1761-
printf(menuItem.refresh.name)
1761+
    gpu.setForeground(color.white)
1762-
menuItem.refresh.w = textWidth(menuItem.refresh.name)
1762+
    menuItem.overview.x, menuItem.overview.y = term.getCursor()
1763
    gpu.setForeground(color.blue)
1764-
menuItem.gates.x,menuItem.gates.y = term.getCursor()
1764+
    printf(menuItem.overview.name)
1765-
gpu.setForeground(color.blue)
1765+
    menuItem.overview.w = textWidth(menuItem.overview.name)
1766-
printf(menuItem.gates.name)
1766+
    gpu.setForeground(color.white)
1767-
menuItem.gates.w = textWidth(menuItem.gates.name)
1767+
    menuItem.refresh.x, menuItem.refresh.y = term.getCursor()
1768
    gpu.setForeground(color.blue)
1769-
for i=1,#reactors do
1769+
    printf(menuItem.refresh.name)
1770-
local label = string.format("[R%d]",i)
1770+
    menuItem.refresh.w = textWidth(menuItem.refresh.name)
1771-
reactors[i].tab.x,reactors[i].tab.y = term.getCursor()
1771+
    gpu.setForeground(color.white)
1772-
reactors[i].tab.w = textWidth(label)
1772+
    menuItem.gates.x, menuItem.gates.y = term.getCursor()
1773-
if i == activeIndex then
1773+
    gpu.setForeground(color.blue)
1774-
guiWrite(reactors[i].tab.x,reactors[i].tab.y,color.black,color.orange,"%s",label)
1774+
    printf(menuItem.gates.name)
1775-
else
1775+
    menuItem.gates.w = textWidth(menuItem.gates.name)
1776-
guiWrite(reactors[i].tab.x,reactors[i].tab.y,color.blue,color.white,"%s",label)
1776+
    gpu.setForeground(color.white)
1777
    for i = 1, #reactors do
1778-
printf(" ")
1778+
        local label = string.format("[R%d]", i)
1779
        reactors[i].tab.x, reactors[i].tab.y = term.getCursor()
1780-
guiWrite(x-25,1,color.yellow,color.panel,"Макс. выраб.: ")
1780+
        reactors[i].tab.w = textWidth(label)
1781-
getCord(infcord.maxgen)
1781+
        if i == activeIndex then
1782-
if inf.generationRate > maxGenerationRate then
1782+
            guiWrite(reactors[i].tab.x, reactors[i].tab.y, color.black, color.orange, "%s", label)
1783-
maxGenerationRate = inf.generationRate
1783+
        else
1784
            guiWrite(reactors[i].tab.x, reactors[i].tab.y, color.blue, color.white, "%s", label)
1785-
guiWrite(infcord.maxgen.x,infcord.maxgen.y,color.green,color.panel,"%s",numformat(maxGenerationRate))
1785+
        end
1786-
drawSeparator(x)
1786+
        printf(" ")
1787-
gpu.setBackground(color.panel)
1787+
    end
1788-
gpu.setForeground(color.blue)
1788+
    guiWrite(x - 25, 1, color.yellow, color.panel, "Макс. выраб.: ")
1789-
printf(" ПАРАМЕТРЫ ")
1789+
    getCord(infcord.maxgen)
1790-
term.setCursor(30,4)
1790+
    if inf.generationRate > maxGenerationRate then
1791-
printf(" УПРАВЛЕНИЕ ")
1791+
        maxGenerationRate = inf.generationRate
1792
    end
1793
    guiWrite(infcord.maxgen.x, infcord.maxgen.y, color.green, color.panel, "%s", numformat(maxGenerationRate))
1794-
term.setCursor(1,6)
1794+
    drawSeparator(x)
1795-
gpu.setBackground(color.panel)
1795+
    gpu.setBackground(color.panel)
1796-
printf(" Температура:     ")
1796+
    gpu.setForeground(color.blue)
1797
    printf(" ПАРАМЕТРЫ ")
1798-
printf(" ")
1798+
    term.setCursor(30, 4)
1799-
getCord(infcord.temp)
1799+
    printf(" УПРАВЛЕНИЕ ")
1800-
guiWrite(infcord.temp.x,infcord.temp.y,-1,-1,"%0.2f\n",inf.temperature)
1800+
    gpu.setBackground(color.grey)
1801-
printf(" Вырабатывает:     ")
1801+
    gpu.setForeground(color.white)
1802-
getCord(infcord.generation)
1802+
    term.setCursor(1, 6)
1803-
guiWrite(infcord.generation.x,infcord.generation.y,-1,-1,"%s  \n",numformat(inf.generationRate))
1803+
    gpu.setBackground(color.panel)
1804-
gpu.setBackground(color.panel)
1804+
    printf(" Температура:     ")
1805-
printf (" Поток:           ")
1805+
    gpu.setBackground(color.grey)
1806
    printf(" ")
1807-
printf(" ")
1807+
    getCord(infcord.temp)
1808-
getCord(infcord.flow)
1808+
    guiWrite(infcord.temp.x, infcord.temp.y, -1, -1, "%0.2f\n", inf.temperature)
1809-
infcord.flow.value = getGateFlow(upgate)
1809+
    printf(" Вырабатывает:     ")
1810-
guiWrite(infcord.flow.x,infcord.flow.y,-1,-1,"%s  ",numformat(infcord.flow.value))
1810+
    getCord(infcord.generation)
1811-
getCord(button.add)
1811+
    guiWrite(infcord.generation.x, infcord.generation.y, -1, -1, "%s  \n", numformat(inf.generationRate))
1812-
makeButton(button.add.x + 4, button.add.y ,button.add.name)
1812+
    gpu.setBackground(color.panel)
1813-
getCord(button.sub)
1813+
    printf(" Поток:           ")
1814-
makeButton(button.sub.x+2,button.sub.y,button.sub.name)
1814+
    gpu.setBackground(color.grey)
1815
    printf(" ")
1816-
printf("\n")
1816+
    getCord(infcord.flow)
1817-
printf (" Итоговая мосч:    ")
1817+
    infcord.flow.value = getGateFlow(upgate)
1818-
getCord(infcord.puregen)
1818+
    guiWrite(infcord.flow.x, infcord.flow.y, -1, -1, "%s  ", numformat(infcord.flow.value))
1819-
guiWrite(infcord.puregen.x,infcord.puregen.y,-1,-1,"%s  \n",numformat(inf.generationRate - getGateFlow(downgate)))
1819+
    getCord(button.add)
1820-
gpu.setBackground(color.panel)
1820+
    makeButton(button.add.x + 4, button.add.y, button.add.name)
1821-
printf (" Поглощает:       ")
1821+
    getCord(button.sub)
1822
    makeButton(button.sub.x + 2, button.sub.y, button.sub.name)
1823-
printf(" ")
1823+
1824-
getCord(infcord.drain)
1824+
    printf("\n")
1825-
guiWrite(infcord.drain.x,infcord.drain.y,-1,-1,"%s  \n",numformat(getGateFlow(downgate)))
1825+
    printf(" Итоговая мосч:    ")
1826
    getCord(infcord.puregen)
1827-
printf (" Мощность поля:    ")
1827+
    guiWrite(infcord.puregen.x, infcord.puregen.y, -1, -1, "%s  \n", numformat(inf.generationRate - getGateFlow(downgate)))
1828-
getCord(infcord.fstrth)
1828+
    gpu.setBackground(color.panel)
1829-
if inf.maxFieldStrength > 0 then
1829+
    printf(" Поглощает:       ")
1830-
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)
1830+
    gpu.setBackground(color.grey)
1831-
else
1831+
    printf(" ")
1832-
guiWrite(infcord.fstrth.x,infcord.fstrth.y,-1,-1,"0 / 0 (0 %%) \n")
1832+
    getCord(infcord.drain)
1833
    guiWrite(infcord.drain.x, infcord.drain.y, -1, -1, "%s  \n", numformat(getGateFlow(downgate)))
1834-
gpu.setBackground(color.panel)
1834+
1835-
printf (" Насыщенность:    ")
1835+
    printf(" Мощность поля:    ")
1836
    getCord(infcord.fstrth)
1837-
printf(" ")
1837+
    if inf.maxFieldStrength > 0 then
1838-
getCord(infcord.esturn)
1838+
        guiWrite(infcord.fstrth.x, infcord.fstrth.y, -1, -1, "%d / %d (%0.2f %%) \n",
1839-
if inf.maxEnergySaturation > 0 then
1839+
            inf.fieldStrength - inf.fieldDrainRate,
1840-
guiWrite(infcord.esturn.x,infcord.esturn.y,-1,-1,"%d / %d (%0.2f %%) \n",inf.energySaturation,inf.maxEnergySaturation,(inf.energySaturation/inf.maxEnergySaturation)*100)
1840+
            inf.maxFieldStrength,
1841-
else
1841+
            ((inf.fieldStrength - inf.fieldDrainRate) / inf.maxFieldStrength) * 100)
1842-
guiWrite(infcord.esturn.x,infcord.esturn.y,-1,-1,"0 / 0 (0 %%) \n")
1842+
    else
1843
        guiWrite(infcord.fstrth.x, infcord.fstrth.y, -1, -1, "0 / 0 (0 %%) \n")
1844-
printf (" Топливо:          ")
1844+
    end
1845-
getCord(infcord.fuel)
1845+
    gpu.setBackground(color.panel)
1846
    printf(" Насыщенность:    ")
1847-
if inf.fuelConversion/inf.maxFuelConversion < 0.78 then
1847+
    gpu.setBackground(color.grey)
1848-
guiWrite(infcord.fuel.x,infcord.fuel.y,-1,-1,"%d / %d (%0.2f %%)                           \n",inf.fuelConversion,inf.maxFuelConversion,(inf.fuelConversion/inf.maxFuelConversion)*100)
1848+
    printf(" ")
1849-
else
1849+
    getCord(infcord.esturn)
1850-
if inf.maxFuelConversion > 0 then
1850+
    if inf.maxEnergySaturation > 0 then
1851-
if inf.status == "online" or inf.status == "charging" or inf.status == "charged" then
1851+
        guiWrite(infcord.esturn.x, infcord.esturn.y, -1, -1, "%d / %d (%0.2f %%) \n",
1852-
guiWrite(infcord.fuel.x,infcord.fuel.y,color.red,-1,"%d / %d (%0.2f %%) Критический уровень топлива\n",inf.fuelConversion,inf.maxFuelConversion,(inf.fuelConversion/inf.maxFuelConversion)*100)
1852+
            inf.energySaturation,
1853-
else
1853+
            inf.maxEnergySaturation,
1854-
guiWrite(infcord.fuel.x,infcord.fuel.y,-1,-1,"%d / %d (%0.2f %%) Критический уровень топлива\n",inf.fuelConversion,inf.maxFuelConversion,(inf.fuelConversion/inf.maxFuelConversion)*100)
1854+
            (inf.energySaturation / inf.maxEnergySaturation) * 100)
1855
    else
1856-
else
1856+
        guiWrite(infcord.esturn.x, infcord.esturn.y, -1, -1, "0 / 0 (0 %%) \n")
1857-
guiWrite(infcord.fuel.x,infcord.fuel.y,-1,-1,"0 / 0 (0 %%)                           \n")
1857+
    end
1858
    printf(" Топливо:          ")
1859
    getCord(infcord.fuel)
1860-
gpu.setBackground(color.panel)
1860+
1861-
printf (" Расход топлива:  ")
1861+
    if inf.fuelConversion / inf.maxFuelConversion < 0.78 then
1862
        guiWrite(infcord.fuel.x, infcord.fuel.y, -1, -1, "%d / %d (%0.2f %%)                           \n",
1863-
printf(" ")
1863+
            inf.fuelConversion,
1864-
getCord(infcord.fuelconv)
1864+
            inf.maxFuelConversion,
1865-
guiWrite(infcord.fuelconv.x,infcord.fuelconv.y,-1,-1,"%d\n",inf.fuelConversionRate)
1865+
            (inf.fuelConversion / inf.maxFuelConversion) * 100)
1866
    else
1867-
getCord(infcord.core)
1867+
        if inf.maxFuelConversion > 0 then
1868-
if com.isAvailable("draconic_rf_storage") then
1868+
            if inf.status == "online" or inf.status == "charging" or inf.status == "charged" then
1869-
guiWrite(infcord.core.x,infcord.core.y,-1,-1,coreformat())
1869+
                guiWrite(infcord.fuel.x, infcord.fuel.y, color.red, -1, "%d / %d (%0.2f %%) Критический уровень топлива\n",
1870
                    inf.fuelConversion,
1871-
printf("\n")
1871+
                    inf.maxFuelConversion,
1872-
button.stop.x,button.stop.y = term.getCursor()
1872+
                    (inf.fuelConversion / inf.maxFuelConversion) * 100)
1873-
button.start.x,button.start.y = button.stop.x,button.stop.y + 1
1873+
            else
1874-
button.charge.x,button.charge.y = button.stop.x,button.stop.y + 2
1874+
                guiWrite(infcord.fuel.x, infcord.fuel.y, -1, -1, "%d / %d (%0.2f %%) Критический уровень топлива\n",
1875-
button.stop.w = textWidth(button.stop.name)
1875+
                    inf.fuelConversion,
1876-
button.start.w = textWidth(button.start.name)
1876+
                    inf.maxFuelConversion,
1877-
button.charge.w = textWidth(button.charge.name)
1877+
                    (inf.fuelConversion / inf.maxFuelConversion) * 100)
1878-
local controlsY = button.stop.y + 3
1878+
            end
1879-
if not chargeHintDismissed then
1879+
        else
1880-
	local hint1 = "Перед первым запуском поставь поток на 535 000."
1880+
            guiWrite(infcord.fuel.x, infcord.fuel.y, -1, -1, "0 / 0 (0 %%)                           \n")
1881-
	local hint2 = "Потом включай."
1881+
        end
1882-
	chargeHint.x = 1
1882+
    end
1883-
	chargeHint.y = math.max(1, screenH - 1)
1883+
    gpu.setBackground(color.panel)
1884-
	local hintY2 = math.min(screenH, chargeHint.y + 1)
1884+
    printf(" Расход топлива:  ")
1885-
	local prevFg = gpu.getForeground()
1885+
    gpu.setBackground(color.grey)
1886-
	local prevBg = gpu.getBackground()
1886+
    printf(" ")
1887-
	gpu.setForeground(color.green)
1887+
    getCord(infcord.fuelconv)
1888-
	gpu.setBackground(color.grey)
1888+
    guiWrite(infcord.fuelconv.x, infcord.fuelconv.y, -1, -1, "%d\n", inf.fuelConversionRate)
1889-
	gpu.set(chargeHint.x, chargeHint.y, hint1)
1889+
1890-
	if hintY2 ~= chargeHint.y then
1890+
    getCord(infcord.core)
1891-
		gpu.set(chargeHint.x, hintY2, hint2)
1891+
    if com.isAvailable("draconic_rf_storage") then
1892-
	end
1892+
        guiWrite(infcord.core.x, infcord.core.y, -1, -1, coreformat())
1893-
	gpu.setForeground(prevFg)
1893+
    end
1894-
	gpu.setBackground(prevBg)
1894+
    printf("\n")
1895-
	chargeHint.w = math.max(textWidth(hint1), textWidth(hint2))
1895+
    button.stop.x, button.stop.y = term.getCursor()
1896-
	chargeHint.visible = true
1896+
    button.start.x, button.start.y = button.stop.x, button.stop.y + 1
1897-
else
1897+
    button.charge.x, button.charge.y = button.stop.x, button.stop.y + 2
1898-
	chargeHint.visible = false
1898+
    button.stop.w = textWidth(button.stop.name)
1899
    button.start.w = textWidth(button.start.name)
1900-
term.setCursor(button.stop.x, controlsY)
1900+
    button.charge.w = textWidth(button.charge.name)
1901-
printf("                   Автономный режим: ")
1901+
    local controlsY = button.stop.y + 3
1902-
getCord(button.autoon)
1902+
    if not chargeHintDismissed then
1903-
getCord(button.autooff)
1903+
        local hint1 = "Перед первым запуском поставь поток на 535 000."
1904-
if not autostate then 
1904+
        local hint2 = "Потом включай."
1905-
guiWrite(button.autooff.x,button.autooff.y,color.red,color.black,"%s\n",button.autooff.name)
1905+
        chargeHint.x = 1
1906-
else
1906+
        chargeHint.y = math.max(1, screenH - 1)
1907-
guiWrite(button.autoon.x,button.autoon.y,color.green,color.black,"%s\n",button.autoon.name)
1907+
        local hintY2 = math.min(screenH, chargeHint.y + 1)
1908
        local prevFg = gpu.getForeground()
1909-
checkButtons()
1909+
        local prevBg = gpu.getBackground()
1910
        gpu.setForeground(color.green)
1911
        gpu.setBackground(color.grey)
1912-
-- Обновление обзора реакторов
1912+
        gpu.set(chargeHint.x, chargeHint.y, hint1)
1913
        if hintY2 ~= chargeHint.y then
1914-
if not handleOverview then
1914+
            gpu.set(chargeHint.x, hintY2, hint2)
1915-
return
1915+
        end
1916
        gpu.setForeground(prevFg)
1917-
if not reactors or #reactors == 0 then
1917+
        gpu.setBackground(prevBg)
1918-
return
1918+
        chargeHint.w = math.max(textWidth(hint1), textWidth(hint2))
1919
        chargeHint.visible = true
1920
    else
1921-
local stopPct = cfg.fuelStopPct or 98
1921+
        chargeHint.visible = false
1922-
local totalGen = 0
1922+
    end
1923-
local totalProfit = 0
1923+
    term.setCursor(button.stop.x, controlsY)
1924-
local totalShield = 0
1924+
    printf("                   Автономный режим: ")
1925-
local maxProfit = 0
1925+
    getCord(button.autoon)
1926
    getCord(button.autooff)
1927-
for i=1,#reactors do
1927+
    if not autostate then
1928-
local r = reactors[i]
1928+
        guiWrite(button.autooff.x, button.autooff.y, color.red, color.black, "%s\n", button.autooff.name)
1929-
local ok, inf = pcall(r.reactor.getReactorInfo)
1929+
    else
1930-
if not ok or type(inf) ~= "table" then
1930+
        guiWrite(button.autoon.x, button.autoon.y, color.green, color.black, "%s\n", button.autoon.name)
1931-
guiWrite(r.row.status.x,r.row.status.y,color.red,-1,"ERR")
1931+
    end
1932-
guiWrite(r.row.temp.x,r.row.temp.y,color.red,-1,"----")
1932+
    checkButtons()
1933-
guiWrite(r.row.fuel.x,r.row.fuel.y,color.red,-1,"----")
1933+
1934-
guiWrite(r.row.profit.x,r.row.profit.y,color.red,-1,"----")
1934+
1935-
guiWrite(r.row.gen.x,r.row.gen.y,color.red,-1,"----")
1935+
1936-
guiWrite(r.row.flow.x,r.row.flow.y,color.red,-1,"----")
1936+
    if not handleOverview then
1937-
else
1937+
        return
1938-
totalGen = totalGen + inf.generationRate
1938+
    end
1939-
guiWrite(r.row.gen.x,r.row.gen.y,-1,-1,"%s",numformat(inf.generationRate))
1939+
    if not reactors or #reactors == 0 then
1940-
local flow = getGateFlow(r.upgate)
1940+
        return
1941-
guiWrite(r.row.flow.x,r.row.flow.y,-1,-1,"%s",numformat(flow))
1941+
    end
1942-
local shieldFlow = getGateFlow(r.downgate)
1942+
    gpu.setForeground(color.white)
1943-
totalShield = totalShield + shieldFlow
1943+
    local stopPct = cfg.fuelStopPct or 98
1944-
local profit = inf.generationRate - shieldFlow
1944+
    local totalGen = 0
1945-
totalProfit = totalProfit + profit
1945+
    local totalProfit = 0
1946-
if profit > maxProfit then
1946+
    local totalShield = 0
1947-
maxProfit = profit
1947+
    local maxProfit = 0
1948
    gpu.setBackground(color.grey)
1949-
guiWrite(r.row.profit.x,r.row.profit.y,-1,-1,"%s",numformat(profit))
1949+
    for i = 1, #reactors do
1950-
local tempColor = color.white
1950+
        local r = reactors[i]
1951-
if inf.temperature >= cfg.tempCriticalEdge then
1951+
        local ok, inf = pcall(r.reactor.getReactorInfo)
1952-
tempColor = color.red
1952+
        if not ok or type(inf) ~= "table" then
1953-
elseif inf.temperature >= cfg.safeModeTempWaitEdge then
1953+
            guiWrite(r.row.status.x, r.row.status.y, color.red, -1, "ERR")
1954-
tempColor = color.yellow
1954+
            guiWrite(r.row.temp.x, r.row.temp.y, color.red, -1, "----")
1955
            guiWrite(r.row.fuel.x, r.row.fuel.y, color.red, -1, "----")
1956-
guiWrite(r.row.temp.x,r.row.temp.y,tempColor,-1,"%4.0fC",inf.temperature)
1956+
            guiWrite(r.row.profit.x, r.row.profit.y, color.red, -1, "----")
1957-
local fuelPct = 0
1957+
            guiWrite(r.row.gen.x, r.row.gen.y, color.red, -1, "----")
1958-
if inf.maxFuelConversion > 0 then
1958+
            guiWrite(r.row.flow.x, r.row.flow.y, color.red, -1, "----")
1959-
fuelPct = (inf.fuelConversion/inf.maxFuelConversion)*100
1959+
        else
1960
            totalGen = totalGen + inf.generationRate
1961-
if autoStopped[r.reactorAdr] and (inf.status == "online" or inf.status == "charging" or inf.status == "charged") then
1961+
            guiWrite(r.row.gen.x, r.row.gen.y, -1, -1, "%s", numformat(inf.generationRate))
1962-
autoStopped[r.reactorAdr] = nil
1962+
            local flow = getGateFlow(r.upgate)
1963
            guiWrite(r.row.flow.x, r.row.flow.y, -1, -1, "%s", numformat(flow))
1964-
if fuelPct >= stopPct and (inf.status == "online" or inf.status == "charging" or inf.status == "charged") then
1964+
            local shieldFlow = getGateFlow(r.downgate)
1965-
if not autoStopped[r.reactorAdr] then
1965+
            totalShield = totalShield + shieldFlow
1966-
r.reactor.stopReactor()
1966+
            local profit = inf.generationRate - shieldFlow
1967-
autoStopped[r.reactorAdr] = true
1967+
            totalProfit = totalProfit + profit
1968
            if profit > maxProfit then
1969
                maxProfit = profit
1970-
local fuelColor = color.white
1970+
            end
1971-
if fuelPct >= 80 then
1971+
            guiWrite(r.row.profit.x, r.row.profit.y, -1, -1, "%s", numformat(profit))
1972-
fuelColor = color.red
1972+
            local tempColor = color.white
1973
            if inf.temperature >= cfg.tempCriticalEdge then
1974-
guiWrite(r.row.fuel.x,r.row.fuel.y,fuelColor,-1,"%5.1f%%",fuelPct)
1974+
                tempColor = color.red
1975-
local stColor = color.white
1975+
            elseif inf.temperature >= cfg.safeModeTempWaitEdge then
1976-
if inf.status == "online" or inf.status == "charging" or inf.status == "charged" then
1976+
                tempColor = color.yellow
1977-
stColor = color.green
1977+
            end
1978-
elseif inf.status == "offline" or inf.status == "stopping" then
1978+
            guiWrite(r.row.temp.x, r.row.temp.y, tempColor, -1, "%4.0fC", inf.temperature)
1979-
stColor = color.red
1979+
            local fuelPct = 0
1980
            if inf.maxFuelConversion > 0 then
1981-
guiWrite(r.row.status.x,r.row.status.y,stColor,-1,"%s",statusText(inf.status))
1981+
                fuelPct = (inf.fuelConversion / inf.maxFuelConversion) * 100
1982-
makePowerButton(r.control.dec.x,r.control.dec.y,"[-]",color.dim,color.white)
1982+
            end
1983-
makePowerButton(r.control.inc.x,r.control.inc.y,"[+]",color.dim,color.white)
1983+
            if autoStopped[r.reactorAdr] and (inf.status == "online" or inf.status == "charging" or inf.status == "charged") then
1984-
local autoColor = r.autostate and color.green or color.red
1984+
                autoStopped[r.reactorAdr] = nil
1985-
makePowerButton(r.control.auto.x,r.control.auto.y,"AUTO",autoColor,color.white)
1985+
            end
1986-
if inf.status == "online" or inf.status == "charging" or inf.status == "charged" then
1986+
            if fuelPct >= stopPct and (inf.status == "online" or inf.status == "charging" or inf.status == "charged") then
1987-
r.powerBtn.action = "stop"
1987+
                if not autoStopped[r.reactorAdr] then
1988-
makePowerButton(r.powerBtn.x,r.powerBtn.y,"PWR",color.red,color.white)
1988+
                    r.reactor.stopReactor()
1989-
else
1989+
                    autoStopped[r.reactorAdr] = true
1990-
r.powerBtn.action = "start"
1990+
                end
1991-
makePowerButton(r.powerBtn.x,r.powerBtn.y,"PWR",color.green,color.white)
1991+
            end
1992
            local fuelColor = color.white
1993
            if fuelPct >= 80 then
1994
                fuelColor = color.red
1995-
if totalProfit > maxSummaryProfit then
1995+
            end
1996-
maxSummaryProfit = totalProfit
1996+
            guiWrite(r.row.fuel.x, r.row.fuel.y, fuelColor, -1, "%5.1f%%", fuelPct)
1997
            local stColor = color.white
1998-
guiWrite(summaryProfitCord.x,summaryProfitCord.y,color.white,color.panel,"%s",numformat(totalProfit))
1998+
            if inf.status == "online" or inf.status == "charging" or inf.status == "charged" then
1999-
guiWrite(summaryEuCord.x,summaryEuCord.y,color.white,color.panel,"%s",numformat(math.floor(totalProfit/8)))
1999+
                stColor = color.green
2000-
guiWrite(summaryShieldCord.x,summaryShieldCord.y,color.white,color.panel,"%s",numformat(totalShield))
2000+
            elseif inf.status == "offline" or inf.status == "stopping" then
2001-
guiWrite(summaryGenCord.x,summaryGenCord.y,color.white,color.panel,"%s",numformat(totalGen))
2001+
                stColor = color.red
2002-
guiWrite(summaryMaxProfitCord.x,summaryMaxProfitCord.y,color.white,color.panel,"%s / %s",numformat(maxSummaryProfit),numformat(math.floor(maxSummaryProfit/8)))
2002+
            end
2003-
local autoList = {}
2003+
            guiWrite(r.row.status.x, r.row.status.y, stColor, -1, "%s", statusText(inf.status))
2004-
for i=1,#reactors do
2004+
            makePowerButton(r.control.dec.x, r.control.dec.y, "[-]", color.dim, color.white)
2005-
if autoStopped[reactors[i].reactorAdr] then
2005+
            makePowerButton(r.control.inc.x, r.control.inc.y, "[+]", color.dim, color.white)
2006-
autoList[#autoList+1] = "R"..i
2006+
            local autoColor = r.autostate and color.green or color.red
2007
            makePowerButton(r.control.auto.x, r.control.auto.y, "AUTO", autoColor, color.white)
2008
            if inf.status == "online" or inf.status == "charging" or inf.status == "charged" then
2009-
local autoText = "нет"
2009+
                r.powerBtn.action = "stop"
2010-
if #autoList > 0 then
2010+
                makePowerButton(r.powerBtn.x, r.powerBtn.y, "PWR", color.red, color.white)
2011-
autoText = table.concat(autoList, ", ")
2011+
            else
2012
                r.powerBtn.action = "start"
2013-
guiWrite(autoStoppedCord.x,autoStoppedCord.y,color.red,-1,"%s",autoText)
2013+
                makePowerButton(r.powerBtn.x, r.powerBtn.y, "PWR", color.green, color.white)
2014
            end
2015
        end
2016
    end
2017
    if totalProfit > maxSummaryProfit then
2018
        maxSummaryProfit = totalProfit
2019
    end
2020
    guiWrite(summaryProfitCord.x, summaryProfitCord.y, color.white, color.panel, "%s", numformat(totalProfit))
2021-
local rd = true
2021+
    guiWrite(summaryEuCord.x, summaryEuCord.y, color.white, color.panel, "%s", numformat(math.floor(totalProfit / 8)))
2022-
while rd do
2022+
    guiWrite(summaryShieldCord.x, summaryShieldCord.y, color.white, color.panel, "%s", numformat(totalShield))
2023-
gpu.fill(param.x, param.y, #tostring(param.value), 1, " ")
2023+
    guiWrite(summaryGenCord.x, summaryGenCord.y, color.white, color.panel, "%s", numformat(totalGen))
2024-
term.setCursor(param.x,param.y)
2024+
    guiWrite(summaryMaxProfitCord.x, summaryMaxProfitCord.y, color.white, color.panel, "%s / %s",
2025
        numformat(maxSummaryProfit),
2026-
param.value = term.read(false,false)
2026+
        numformat(math.floor(maxSummaryProfit / 8)))
2027-
local val = tonumber(param.value)
2027+
    local autoList = {}
2028-
if val then
2028+
    for i = 1, #reactors do
2029-
param.value = val
2029+
        if autoStopped[reactors[i].reactorAdr] then
2030-
show(color.black,color.grey,param)
2030+
            autoList[#autoList + 1] = "R" .. i
2031-
rd = false
2031+
        end
2032
    end
2033
    local autoText = "нет"
2034-
canedit = true
2034+
    if #autoList > 0 then
2035-
canclose = true
2035+
        autoText = table.concat(autoList, ", ")
2036-
screen.options()
2036+
    end
2037
    guiWrite(autoStoppedCord.x, autoStoppedCord.y, color.red, -1, "%s", autoText)
2038
end
2039-
local function add(n,i)
2039+
2040-
n.value=n.value+i
2040+
2041-
upgate.setSignalLowFlow(n.value)
2041+
2042-
return n.value
2042+
2043
screen["options"] = screenOptions
2044
2045-
local function sub(n,i)
2045+
2046-
term.setCursor(n.x,n.y)
2046+
    local rd = true
2047-
n.value=n.value-i
2047+
    while rd do
2048-
return n.value
2048+
        gpu.fill(param.x, param.y, #tostring(param.value), 1, " ")
2049
        term.setCursor(param.x, param.y)
2050-
-- Обновление информации на экране + анализ поведения температуры
2050+
2051
        param.value = term.read(false, false)
2052-
local ok, inf = pcall(reactor.getReactorInfo)
2052+
        local val = tonumber(param.value)
2053-
if not ok or type(inf) ~= "table" then
2053+
        if val then
2054-
refreshReactors(false)
2054+
            param.value = val
2055-
screenOverview()
2055+
            show(color.black, color.grey, param)
2056-
return
2056+
            rd = false
2057
        end
2058-
infcord.status.value = inf.status
2058+
    end
2059
    canedit = true
2060-
local tbuf1 = inf.temperature
2060+
    canclose = true
2061-
os.sleep(0.1)
2061+
    screen.options()
2062-
local ok2, inf2 = pcall(reactor.getReactorInfo)
2062+
2063-
local tbuf2 = ok2 and type(inf2) == "table" and inf2.temperature or tbuf1
2063+
2064-
if handleMain then
2064+
local function add(n, i)
2065-
local stopPct = cfg.fuelStopPct or 98
2065+
    n.value = n.value + i
2066-
if cfg.autoProtectTempEdge and inf.temperature >= cfg.autoProtectTempEdge and not autostate then
2066+
    upgate.setSignalLowFlow(n.value)
2067-
autostate = true
2067+
    return n.value
2068-
guiWrite(button.autoon.x,button.autoon.y,color.green,color.black,"%s\n",button.autoon.name)
2068+
2069
2070
local function sub(n, i)
2071-
local fuelPct = 0
2071+
    term.setCursor(n.x, n.y)
2072-
if inf.maxFuelConversion >  0 then
2072+
    n.value = n.value - i
2073-
fuelPct = (inf.fuelConversion/inf.maxFuelConversion)*100
2073+
    return n.value
2074
end
2075-
if autoStopped[reactors[activeIndex].reactorAdr] and (inf.status == "online" or inf.status == "charging" or inf.status == "charged") then
2075+
2076-
autoStopped[reactors[activeIndex].reactorAdr] = nil
2076+
2077
    local ok, inf = pcall(reactor.getReactorInfo)
2078-
if fuelPct >= stopPct and (inf.status == "online" or inf.status == "charging" or inf.status == "charged") then
2078+
    if not ok or type(inf) ~= "table" then
2079-
if not autoStopped[reactors[activeIndex].reactorAdr] then
2079+
        refreshReactors(false)
2080-
reactor.stopReactor()
2080+
        screenOverview()
2081-
autoStopped[reactors[activeIndex].reactorAdr] = true
2081+
        return
2082
    end
2083
    infcord.status.value = inf.status
2084-
if tbuf2>tbuf1 then
2084+
    gpu.setForeground(color.white)
2085-
guiWrite(infcord.temp.x,infcord.temp.y,color.red,-1,"%0.2f \n",inf.temperature)
2085+
    local tbuf1 = inf.temperature
2086-
temprise = true
2086+
    os.sleep(0.1)
2087-
elseif tbuf2<tbuf1 then
2087+
    local ok2, inf2 = pcall(reactor.getReactorInfo)
2088-
guiWrite(infcord.temp.x,infcord.temp.y,color.blue,-1,"%0.2f \n",inf.temperature)
2088+
    local tbuf2 = ok2 and type(inf2) == "table" and inf2.temperature or tbuf1
2089-
temprise = false
2089+
    if handleMain then
2090-
else
2090+
        local stopPct = cfg.fuelStopPct or 98
2091-
if inf.temperature == 2000 then
2091+
        if cfg.autoProtectTempEdge and inf.temperature >= cfg.autoProtectTempEdge and not autostate then
2092-
guiWrite(infcord.temp.x,infcord.temp.y,-1,-1,"%0.2f \n",inf.temperature)
2092+
            autostate = true
2093
            guiWrite(button.autoon.x, button.autoon.y, color.green, color.black, "%s\n", button.autoon.name)
2094
        end
2095-
guiWrite(infcord.generation.x,infcord.generation.y,-1,-1,"%s\n",numformat(inf.generationRate))
2095+
    end
2096-
if inf.generationRate > maxGenerationRate then
2096+
    local fuelPct = 0
2097-
maxGenerationRate = inf.generationRate
2097+
    if inf.maxFuelConversion > 0 then
2098
        fuelPct = (inf.fuelConversion / inf.maxFuelConversion) * 100
2099-
guiWrite(infcord.maxgen.x,infcord.maxgen.y,color.green,color.panel,"%s",numformat(maxGenerationRate))
2099+
    end
2100-
infcord.flow.value = getGateFlow(upgate)
2100+
    if autoStopped[reactors[activeIndex].reactorAdr] and (inf.status == "online" or inf.status == "charging" or inf.status == "charged") then
2101-
guiWrite(infcord.flow.x,infcord.flow.y,-1,-1,"%s",numformat(infcord.flow.value))
2101+
        autoStopped[reactors[activeIndex].reactorAdr] = nil
2102-
guiWrite(infcord.puregen.x,infcord.puregen.y,-1,-1,"%s\n",numformat(inf.generationRate - getGateFlow(downgate)))
2102+
    end
2103-
infcord.drain.value = inf.fieldDrainRate
2103+
    if fuelPct >= stopPct and (inf.status == "online" or inf.status == "charging" or inf.status == "charged") then
2104-
guiWrite(infcord.drain.x,infcord.drain.y,-1,-1,"%s\n",numformat(getGateFlow(downgate)))
2104+
        if not autoStopped[reactors[activeIndex].reactorAdr] then
2105-
if inf.maxFieldStrength > 0 then
2105+
            reactor.stopReactor()
2106-
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)
2106+
            autoStopped[reactors[activeIndex].reactorAdr] = true
2107-
else
2107+
        end
2108-
guiWrite(infcord.fstrth.x,infcord.fstrth.y,-1,-1,"0 / 0 (0 %%) \n")
2108+
    end
2109
    if tbuf2 > tbuf1 then
2110-
if inf.maxEnergySaturation > 0 then
2110+
        guiWrite(infcord.temp.x, infcord.temp.y, color.red, -1, "%0.2f \n", inf.temperature)
2111-
guiWrite(infcord.esturn.x,infcord.esturn.y,-1,-1,"%d / %d (%0.2f %%) \n",inf.energySaturation,inf.maxEnergySaturation,(inf.energySaturation/inf.maxEnergySaturation)*100)
2111+
        temprise = true
2112-
else
2112+
    elseif tbuf2 < tbuf1 then
2113-
guiWrite(infcord.esturn.x,infcord.esturn.y,-1,-1,"0 / 0 (0 %%) \n")
2113+
        guiWrite(infcord.temp.x, infcord.temp.y, color.blue, -1, "%0.2f \n", inf.temperature)
2114
        temprise = false
2115-
if inf.fuelConversion/inf.maxFuelConversion < 0.78 then
2115+
    else
2116-
guiWrite(infcord.fuel.x,infcord.fuel.y,-1,-1,"%d / %d (%0.2f %%) \n",inf.fuelConversion,inf.maxFuelConversion,(inf.fuelConversion/inf.maxFuelConversion)*100)
2116+
        if inf.temperature == 2000 then
2117-
else
2117+
            guiWrite(infcord.temp.x, infcord.temp.y, -1, -1, "%0.2f \n", inf.temperature)
2118-
if inf.maxFuelConversion > 0 then
2118+
        end
2119-
if inf.status == "online" or inf.status == "charging" or inf.status == "charged" then
2119+
    end
2120-
guiWrite(infcord.fuel.x,infcord.fuel.y,color.red,-1,"%d / %d (%0.2f %%) Критический уровень топлива\n",inf.fuelConversion,inf.maxFuelConversion,(inf.fuelConversion/inf.maxFuelConversion)*100)
2120+
    guiWrite(infcord.generation.x, infcord.generation.y, -1, -1, "%s\n", numformat(inf.generationRate))
2121-
else
2121+
    if inf.generationRate > maxGenerationRate then
2122-
guiWrite(infcord.fuel.x,infcord.fuel.y,-1,-1,"%d / %d (%0.2f %%) Критический уровень топлива\n",inf.fuelConversion,inf.maxFuelConversion,(inf.fuelConversion/inf.maxFuelConversion)*100)
2122+
        maxGenerationRate = inf.generationRate
2123
    end
2124-
else
2124+
    guiWrite(infcord.maxgen.x, infcord.maxgen.y, color.green, color.panel, "%s", numformat(maxGenerationRate))
2125-
guiWrite(infcord.fuel.x,infcord.fuel.y,-1,-1,"0 / 0 (0 %%)\n")
2125+
    infcord.flow.value = getGateFlow(upgate)
2126
    guiWrite(infcord.flow.x, infcord.flow.y, -1, -1, "%s", numformat(infcord.flow.value))
2127
    guiWrite(infcord.puregen.x, infcord.puregen.y, -1, -1, "%s\n", numformat(inf.generationRate - getGateFlow(downgate)))
2128-
guiWrite(infcord.fuelconv.x,infcord.fuelconv.y,-1,-1,"%d\n",inf.fuelConversionRate)
2128+
    infcord.drain.value = inf.fieldDrainRate
2129-
if com.isAvailable("draconic_rf_storage") then
2129+
    guiWrite(infcord.drain.x, infcord.drain.y, -1, -1, "%s\n", numformat(getGateFlow(downgate)))
2130-
guiWrite(infcord.core.x,infcord.core.y,-1,-1,coreformat())
2130+
    if inf.maxFieldStrength > 0 then
2131-
if button.stop.y ~= infcord.core.y + 2 then
2131+
        guiWrite(infcord.fstrth.x, infcord.fstrth.y, -1, -1, "%d / %d (%0.2f %%) \n",
2132-
screenMain()
2132+
            inf.fieldStrength - inf.fieldDrainRate,
2133
            inf.maxFieldStrength,
2134-
elseif button.stop.y ~= infcord.fuelconv.y + 2 then
2134+
            ((inf.fieldStrength - inf.fieldDrainRate) / inf.maxFieldStrength) * 100)
2135-
screenMain()
2135+
    else
2136
        guiWrite(infcord.fstrth.x, infcord.fstrth.y, -1, -1, "0 / 0 (0 %%) \n")
2137-
checkButtons()
2137+
    end
2138-
syncActive()
2138+
    if inf.maxEnergySaturation > 0 then
2139
        guiWrite(infcord.esturn.x, infcord.esturn.y, -1, -1, "%d / %d (%0.2f %%) \n",
2140
            inf.energySaturation,
2141-
-- Алгоритм автономного режима
2141+
            inf.maxEnergySaturation,
2142
            (inf.energySaturation / inf.maxEnergySaturation) * 100)
2143-
if not r or not r.reactor or not r.upgate or not r.downgate then
2143+
    else
2144-
return
2144+
        guiWrite(infcord.esturn.x, infcord.esturn.y, -1, -1, "0 / 0 (0 %%) \n")
2145
    end
2146-
local ok, inf = pcall(r.reactor.getReactorInfo)
2146+
    if inf.fuelConversion / inf.maxFuelConversion < 0.78 then
2147-
if not ok or type(inf) ~= "table" then
2147+
        guiWrite(infcord.fuel.x, infcord.fuel.y, -1, -1, "%d / %d (%0.2f %%) \n",
2148-
return
2148+
            inf.fuelConversion,
2149
            inf.maxFuelConversion,
2150-
local now = computer.uptime()
2150+
            (inf.fuelConversion / inf.maxFuelConversion) * 100)
2151-
if r.chargeRequested and now <= r.chargeRequested then
2151+
    else
2152-
local downflow = 900000
2152+
        if inf.maxFuelConversion > 0 then
2153-
r.downgate.setOverrideEnabled(true)
2153+
            if inf.status == "online" or inf.status == "charging" or inf.status == "charged" then
2154-
r.downgate.setFlowOverride(downflow)
2154+
                guiWrite(infcord.fuel.x, infcord.fuel.y, color.red, -1, "%d / %d (%0.2f %%) Критический уровень топлива\n",
2155-
return
2155+
                    inf.fuelConversion,
2156
                    inf.maxFuelConversion,
2157-
if inf.status == "charging" then
2157+
                    (inf.fuelConversion / inf.maxFuelConversion) * 100)
2158-
local downflow = 900000
2158+
            else
2159-
r.downgate.setOverrideEnabled(true)
2159+
                guiWrite(infcord.fuel.x, infcord.fuel.y, -1, -1, "%d / %d (%0.2f %%) Критический уровень топлива\n",
2160-
r.downgate.setFlowOverride(downflow)
2160+
                    inf.fuelConversion,
2161-
return
2161+
                    inf.maxFuelConversion,
2162
                    (inf.fuelConversion / inf.maxFuelConversion) * 100)
2163-
local isActive = reactors[activeIndex] and reactors[activeIndex].reactorAdr == r.reactorAdr
2163+
            end
2164-
if cfg.autoProtectTempEdge and inf.temperature >= cfg.autoProtectTempEdge and not r.autostate then
2164+
        else
2165-
r.autostate = true
2165+
            guiWrite(infcord.fuel.x, infcord.fuel.y, -1, -1, "0 / 0 (0 %%)\n")
2166-
if isActive then
2166+
        end
2167-
autostate = true
2167+
    end
2168-
if handleMain and button.autoon.x then
2168+
    guiWrite(infcord.fuelconv.x, infcord.fuelconv.y, -1, -1, "%d\n", inf.fuelConversionRate)
2169-
guiWrite(button.autoon.x,button.autoon.y,color.green,color.black,"%s\n",button.autoon.name)
2169+
    if com.isAvailable("draconic_rf_storage") then
2170
        guiWrite(infcord.core.x, infcord.core.y, -1, -1, coreformat())
2171
        if button.stop.y ~= infcord.core.y + 2 then
2172
            screenMain()
2173-
local shieldPct = cfg.shield or 25
2173+
        end
2174-
local flow = getGateFlow(r.upgate)
2174+
    elseif button.stop.y ~= infcord.fuelconv.y + 2 then
2175-
if type(flow) ~= "number" then
2175+
        screenMain()
2176-
flow = 0
2176+
    end
2177
    checkButtons()
2178-
local drain = inf.fieldDrainRate
2178+
    syncActive()
2179-
if state then
2179+
2180-
local forceEdge = cfg.forceModeTempLowEdge or 7600
2180+
2181-
if forceEdge < 7600 then
2181+
2182-
forceEdge = 7600
2182+
    if not r or not r.reactor or not r.upgate or not r.downgate then
2183
        return
2184-
local waittemp = autoWaitTempByAdr[r.reactorAdr]
2184+
    end
2185-
local tempRise = false
2185+
    local ok, inf = pcall(r.reactor.getReactorInfo)
2186-
if r.lastTemp then
2186+
    if not ok or type(inf) ~= "table" then
2187-
if inf.temperature > r.lastTemp then
2187+
        return
2188-
tempRise = true
2188+
    end
2189-
elseif inf.temperature < r.lastTemp then
2189+
    local now = computer.uptime()
2190-
tempRise = false
2190+
    if r.chargeRequested and now <= r.chargeRequested then
2191-
else
2191+
        local downflow = 900000
2192-
tempRise = r.temprise or false
2192+
        r.downgate.setOverrideEnabled(true)
2193
        r.downgate.setFlowOverride(downflow)
2194
        return
2195-
r.lastTemp = inf.temperature
2195+
    end
2196-
r.temprise = tempRise
2196+
    if inf.status == "charging" then
2197-
local downflow = drain / (1 - (shieldPct/100))
2197+
        local downflow = 900000
2198-
r.downgate.setOverrideEnabled(true)
2198+
        r.downgate.setOverrideEnabled(true)
2199-
r.downgate.setFlowOverride(downflow)
2199+
        r.downgate.setFlowOverride(downflow)
2200-
if inf.temperature <= forceEdge then
2200+
        return
2201-
if flow - inf.generationRate <= cfg.forceModeStepCase then
2201+
    end
2202-
flow = flow + cfg.forceModeStep
2202+
    local isActive = reactors[activeIndex] and reactors[activeIndex].reactorAdr == r.reactorAdr
2203-
r.upgate.setSignalLowFlow(flow)
2203+
    if cfg.autoProtectTempEdge and inf.temperature >= cfg.autoProtectTempEdge and not r.autostate then
2204
        r.autostate = true
2205-
elseif flow - inf.generationRate <= cfg.safeModeStepCase and inf.temperature >= forceEdge then
2205+
        if isActive then
2206-
if not waittemp then
2206+
            autostate = true
2207-
flow = getGateFlow(r.upgate) + cfg.safemodeStep
2207+
            if handleMain and button.autoon.x then
2208-
r.upgate.setSignalLowFlow(flow)
2208+
                guiWrite(button.autoon.x, button.autoon.y, color.green, color.black, "%s\n", button.autoon.name)
2209-
elseif inf.temperature < cfg.safeModeTempToWaitEdge then
2209+
            end
2210-
waittemp = false
2210+
        end
2211
    end
2212-
elseif tempRise and inf.temperature >= cfg.safeModeTempWaitEdge then
2212+
    local shieldPct = cfg.shield or 25
2213-
if inf.temperature > cfg.safeModeTempWaitEdge then
2213+
    local flow = getGateFlow(r.upgate)
2214-
waittemp = true
2214+
    if type(flow) ~= "number" then
2215
        flow = 0
2216-
if inf.temperature > cfg.tempCriticalEdge then
2216+
    end
2217-
flow = inf.generationRate - 1000
2217+
    local drain = inf.fieldDrainRate
2218-
r.upgate.setSignalLowFlow(flow)
2218+
    if state then
2219
        local forceEdge = cfg.forceModeTempLowEdge or 7600
2220
        if forceEdge < 7600 then
2221-
autoWaitTempByAdr[r.reactorAdr] = waittemp
2221+
            forceEdge = 7600
2222-
if isActive and handleMain and infcord.flow.x then
2222+
        end
2223-
infcord.flow.value = flow
2223+
        local waittemp = autoWaitTempByAdr[r.reactorAdr]
2224-
guiWrite(infcord.flow.x,infcord.flow.y,color.red,color.grey,"%s",numformat(flow))
2224+
        local tempRise = false
2225
        if r.lastTemp then
2226-
else
2226+
            if inf.temperature > r.lastTemp then
2227-
local downflow
2227+
                tempRise = true
2228-
if inf.status == "charging" then
2228+
            elseif inf.temperature < r.lastTemp then
2229-
downflow = 900000
2229+
                tempRise = false
2230-
else
2230+
            else
2231-
downflow = drain / (1 - (shieldPct/100))
2231+
                tempRise = r.temprise or false
2232
            end
2233-
if inf.status == "charging" then
2233+
        end
2234-
r.downgate.setOverrideEnabled(true)
2234+
        r.lastTemp = inf.temperature
2235-
r.downgate.setFlowOverride(downflow)
2235+
        r.temprise = tempRise
2236-
else
2236+
        local downflow = drain / (1 - (shieldPct / 100))
2237-
r.downgate.setOverrideEnabled(false)
2237+
        r.downgate.setOverrideEnabled(true)
2238-
r.downgate.setSignalHighFlow(downflow)
2238+
        r.downgate.setFlowOverride(downflow)
2239-
r.downgate.setSignalLowFlow(downflow)
2239+
        if inf.temperature <= forceEdge then
2240
            if flow - inf.generationRate <= cfg.forceModeStepCase then
2241
                flow = flow + cfg.forceModeStep
2242
                r.upgate.setSignalLowFlow(flow)
2243-
-- Обработчик событий
2243+
            end
2244-
local function tcall(type,scrnAdr,x,y,btn,player)
2244+
        elseif flow - inf.generationRate <= cfg.safeModeStepCase and inf.temperature >= forceEdge then
2245-
local rx,ry = gpu.getResolution()
2245+
            if not waittemp then
2246-
--выход
2246+
                flow = getGateFlow(r.upgate) + cfg.safemodeStep
2247-
if x >= rx-2 and x<=rx and y == 1 then
2247+
                r.upgate.setSignalLowFlow(flow)
2248-
event.ignore("touch",tcall)
2248+
            elseif inf.temperature < cfg.safeModeTempToWaitEdge then
2249-
prog = false
2249+
                waittemp = false
2250-
ops = false
2250+
            end
2251
        elseif tempRise and inf.temperature >= cfg.safeModeTempWaitEdge then
2252-
if handleStart then
2252+
            if inf.temperature > cfg.safeModeTempWaitEdge then
2253-
if menuItem.gates.x and x>= menuItem.gates.x and x <= (menuItem.gates.x + (menuItem.gates.w or #menuItem.gates.name) - 1) and y == menuItem.gates.y then
2253+
                waittemp = true
2254-
resetAssignState()
2254+
            end
2255-
screenAssign()
2255+
            if inf.temperature > cfg.tempCriticalEdge then
2256-
return
2256+
                flow = inf.generationRate - 1000
2257
                r.upgate.setSignalLowFlow(flow)
2258
            end
2259-
-- Главный экран
2259+
        end
2260-
if handleMain then 
2260+
        autoWaitTempByAdr[r.reactorAdr] = waittemp
2261-
-- Увеличение
2261+
        if isActive and handleMain and infcord.flow.x then
2262-
if x >= button.add.x+4 and x <= button.add.x+3+#button.add.name and y == button.add.y then
2262+
            infcord.flow.value = flow
2263-
if keyb.isShiftDown() then
2263+
            guiWrite(infcord.flow.x, infcord.flow.y, color.red, color.grey, "%s", numformat(flow))
2264-
if keyb.isControlDown() then
2264+
        end
2265-
upgate.setSignalLowFlow(add(infcord.flow,cfg.ctrlShift_interval))
2265+
    else
2266-
else
2266+
        local downflow
2267-
upgate.setSignalLowFlow(add(infcord.flow,cfg.shift_interval)) 
2267+
        if inf.status == "charging" then
2268
            downflow = 900000
2269-
else
2269+
        else
2270-
if keyb.isControlDown() then
2270+
            downflow = drain / (1 - (shieldPct / 100))
2271-
upgate.setSignalLowFlow(add(infcord.flow,cfg.ctrl_interval)) 
2271+
        end
2272-
else
2272+
        if inf.status == "charging" then
2273-
upgate.setSignalLowFlow(add(infcord.flow,cfg.default_interval))
2273+
            r.downgate.setOverrideEnabled(true)
2274
            r.downgate.setFlowOverride(downflow)
2275
        else
2276-
guiWrite(infcord.flow.x,infcord.flow.y,color.red,color.grey,"%s",numformat(infcord.flow.value))
2276+
            r.downgate.setOverrideEnabled(false)
2277
            r.downgate.setSignalHighFlow(downflow)
2278-
--Уменьшение
2278+
            r.downgate.setSignalLowFlow(downflow)
2279-
if x >= button.sub.x+2 and x <= button.sub.x+1+#button.sub.name and y == button.sub.y then
2279+
        end
2280-
if keyb.isShiftDown() then
2280+
    end
2281-
if keyb.isControlDown() then
2281+
2282-
upgate.setSignalLowFlow(sub(infcord.flow,cfg.ctrlShift_interval)) 
2282+
2283-
else
2283+
local function tcall(type, scrnAdr, x, y, btn, player)
2284-
upgate.setSignalLowFlow(sub(infcord.flow,cfg.shift_interval)) 
2284+
    local rx, ry = gpu.getResolution()
2285
    if x >= rx - 2 and x <= rx and y == 1 then
2286-
else
2286+
        event.ignore("touch", tcall)
2287-
if keyb.isControlDown() then
2287+
        prog = false
2288-
upgate.setSignalLowFlow(sub(infcord.flow,cfg.ctrl_interval)) 
2288+
        ops = false
2289-
else
2289+
    end
2290-
upgate.setSignalLowFlow(sub(infcord.flow,cfg.default_interval)) 
2290+
    if handleStart then
2291
        if menuItem.gates.x and x >= menuItem.gates.x and x <= (menuItem.gates.x + (menuItem.gates.w or #menuItem.gates.name) - 1) and y == menuItem.gates.y then
2292
            resetAssignState()
2293-
guiWrite(infcord.flow.x,infcord.flow.y,color.blue,color.grey,"%s",numformat(infcord.flow.value))
2293+
            screenAssign()
2294
            return
2295
        end
2296-
if not autostate then
2296+
    end
2297-
if x >= button.autooff.x and x <= button.autooff.x + textWidth(button.autooff.name) - 1 and y == button.autooff.y then
2297+
    if handleMain then
2298-
gpu.set(button.autooff.x, button.autooff.y,"        ")
2298+
        if x >= button.add.x + 4 and x <= button.add.x + 3 + #button.add.name and y == button.add.y then
2299-
autostate = true
2299+
            if keyb.isShiftDown() then
2300-
guiWrite(button.autoon.x,button.autoon.y,color.green,color.black,"%s\n",button.autoon.name)
2300+
                if keyb.isControlDown() then
2301
                    upgate.setSignalLowFlow(add(infcord.flow, cfg.ctrlShift_interval))
2302-
else
2302+
                else
2303-
if x >= button.autoon.x and x <= button.autoon.x + textWidth(button.autoon.name) - 1 and y == button.autoon.y then
2303+
                    upgate.setSignalLowFlow(add(infcord.flow, cfg.shift_interval))
2304-
gpu.set(button.autoon.x, button.autoon.y,"       ")
2304+
                end
2305-
autostate = false
2305+
            else
2306-
guiWrite(button.autooff.x,button.autooff.y,color.red,color.black,"%s\n",button.autooff.name)
2306+
                if keyb.isControlDown() then
2307
                    upgate.setSignalLowFlow(add(infcord.flow, cfg.ctrl_interval))
2308
                else
2309-
do
2309+
                    upgate.setSignalLowFlow(add(infcord.flow, cfg.default_interval))
2310-
local w = button.charge.w or textWidth(button.charge.name)
2310+
                end
2311-
if button.charge.x and button.charge.y and x >= button.charge.x and x <= button.charge.x + w - 1 and y == button.charge.y then
2311+
            end
2312-
local usedNativeCharge = false
2312+
            guiWrite(infcord.flow.x, infcord.flow.y, color.red, color.grey, "%s", numformat(infcord.flow.value))
2313-
if reactor and reactor.chargeReactor then
2313+
        end
2314-
local ok = pcall(reactor.chargeReactor)
2314+
        if x >= button.sub.x + 2 and x <= button.sub.x + 1 + #button.sub.name and y == button.sub.y then
2315-
if ok then
2315+
            if keyb.isShiftDown() then
2316-
usedNativeCharge = true
2316+
                if keyb.isControlDown() then
2317
                    upgate.setSignalLowFlow(sub(infcord.flow, cfg.ctrlShift_interval))
2318
                else
2319-
if not usedNativeCharge then
2319+
                    upgate.setSignalLowFlow(sub(infcord.flow, cfg.shift_interval))
2320-
ensureFlowInit(reactors[activeIndex], true)
2320+
                end
2321-
if upgate then
2321+
            else
2322-
upgate.setSignalLowFlow(CHARGE_FLOW)
2322+
                if keyb.isControlDown() then
2323
                    upgate.setSignalLowFlow(sub(infcord.flow, cfg.ctrl_interval))
2324-
infcord.flow.value = CHARGE_FLOW
2324+
                else
2325-
if infcord.flow.x then
2325+
                    upgate.setSignalLowFlow(sub(infcord.flow, cfg.default_interval))
2326-
guiWrite(infcord.flow.x,infcord.flow.y,color.red,color.grey,"%s",numformat(infcord.flow.value))
2326+
                end
2327
            end
2328
            guiWrite(infcord.flow.x, infcord.flow.y, color.blue, color.grey, "%s", numformat(infcord.flow.value))
2329-
if chargeHint.visible and chargeHint.x and chargeHint.y then
2329+
        end
2330-
guiWrite(chargeHint.x, chargeHint.y, color.white, color.grey, "%s", string.rep(" ", chargeHint.w))
2330+
2331-
guiWrite(chargeHint.x, chargeHint.y + 1, color.white, color.grey, "%s", string.rep(" ", chargeHint.w))
2331+
        if not autostate then
2332-
chargeHint.visible = false
2332+
            if x >= button.autooff.x and x <= button.autooff.x + textWidth(button.autooff.name) - 1 and y == button.autooff.y then
2333-
chargeHintDismissed = true
2333+
                gpu.set(button.autooff.x, button.autooff.y, "        ")
2334
                autostate = true
2335-
guiWrite(button.charge.x,button.charge.y,-1,color.grey,"                 ",button.charge.name)
2335+
                guiWrite(button.autoon.x, button.autoon.y, color.green, color.black, "%s\n", button.autoon.name)
2336-
button.charge.visible = false
2336+
            end
2337-
if not usedNativeCharge then
2337+
        else
2338-
	local currentReactor = reactors[activeIndex]
2338+
            if x >= button.autoon.x and x <= button.autoon.x + textWidth(button.autoon.name) - 1 and y == button.autoon.y then
2339-
	if currentReactor and currentReactor.reactorAdr then
2339+
                gpu.set(button.autoon.x, button.autoon.y, "       ")
2340-
		local chargeUntil = computer.uptime() + CHARGE_DURATION
2340+
                autostate = false
2341-
		currentReactor.chargeRequested = chargeUntil
2341+
                guiWrite(button.autooff.x, button.autooff.y, color.red, color.black, "%s\n", button.autooff.name)
2342-
		chargeRequestByAdr[currentReactor.reactorAdr] = chargeUntil
2342+
            end
2343-
	end
2343+
        end
2344
        do
2345
            local w = button.charge.w or textWidth(button.charge.name)
2346
            if button.charge.x and button.charge.y and x >= button.charge.x and x <= button.charge.x + w - 1 and y == button.charge.y then
2347-
if button.start.visible then
2347+
                local usedNativeCharge = false
2348-
local w = button.start.w or textWidth(button.start.name)
2348+
                if reactor and reactor.chargeReactor then
2349-
if x >= button.start.x and x <= button.start.x + w - 1 and y == button.start.y then
2349+
                    local ok = pcall(reactor.chargeReactor)
2350-
ensureFlowInit(reactors[activeIndex])
2350+
                    if ok then
2351-
reactor.activateReactor()
2351+
                        usedNativeCharge = true
2352-
if reactors[activeIndex] then
2352+
                    end
2353-
autoStopped[reactors[activeIndex].reactorAdr] = nil
2353+
                end
2354
                if not usedNativeCharge then
2355-
guiWrite(button.start.x,button.start.y,-1,color.grey,"                 ",button.start.name)
2355+
                    ensureFlowInit(reactors[activeIndex], true)
2356-
button.start.visible = false
2356+
                    if upgate then
2357
                        upgate.setSignalLowFlow(CHARGE_FLOW)
2358
                    end
2359-
if button.stop.visible then
2359+
                    infcord.flow.value = CHARGE_FLOW
2360-
local w = button.stop.w or textWidth(button.stop.name)
2360+
                    if infcord.flow.x then
2361-
if x >= button.stop.x and x <= button.stop.x + w - 1 and y == button.stop.y then
2361+
                        guiWrite(infcord.flow.x, infcord.flow.y, color.red, color.grey, "%s", numformat(infcord.flow.value))
2362-
reactor.stopReactor()
2362+
                    end
2363-
guiWrite(button.stop.x,button.stop.y,-1,color.grey,"                 ",button.stop.name)
2363+
                end
2364-
button.stop.visible = false
2364+
                if chargeHint.visible and chargeHint.x and chargeHint.y then
2365
                    guiWrite(chargeHint.x, chargeHint.y, color.white, color.grey, "%s", string.rep(" ", chargeHint.w))
2366
                    guiWrite(chargeHint.x, chargeHint.y + 1, color.white, color.grey, "%s", string.rep(" ", chargeHint.w))
2367-
--меню
2367+
                    chargeHint.visible = false
2368-
if x>= menuItem.options.x and x <= (menuItem.options.x + (menuItem.options.w or #menuItem.options.name) - 1) and y == menuItem.options.y then
2368+
                    chargeHintDismissed = true
2369-
screenOptions()
2369+
                end
2370-
return
2370+
                guiWrite(button.charge.x, button.charge.y, -1, color.grey, "                 ", button.charge.name)
2371
                button.charge.visible = false
2372-
if x>= menuItem.overview.x and x <= (menuItem.overview.x + (menuItem.overview.w or #menuItem.overview.name) - 1) and y == menuItem.overview.y then
2372+
                if not usedNativeCharge then
2373-
syncActive()
2373+
                    local currentReactor = reactors[activeIndex]
2374-
screenOverview()
2374+
                    if currentReactor and currentReactor.reactorAdr then
2375-
return
2375+
                        local chargeUntil = computer.uptime() + CHARGE_DURATION
2376
                        currentReactor.chargeRequested = chargeUntil
2377-
if x>= menuItem.refresh.x and x <= (menuItem.refresh.x + (menuItem.refresh.w or #menuItem.refresh.name) - 1) and y == menuItem.refresh.y then
2377+
                        chargeRequestByAdr[currentReactor.reactorAdr] = chargeUntil
2378-
refreshReactors(true)
2378+
                    end
2379-
return
2379+
                end
2380
            end
2381-
if x>= menuItem.gates.x and x <= (menuItem.gates.x + (menuItem.gates.w or #menuItem.gates.name) - 1) and y == menuItem.gates.y then
2381+
        end
2382-
resetAssignState()
2382+
        if button.start.visible then
2383-
screenAssign()
2383+
            local w = button.start.w or textWidth(button.start.name)
2384-
return
2384+
            if x >= button.start.x and x <= button.start.x + w - 1 and y == button.start.y then
2385
                ensureFlowInit(reactors[activeIndex])
2386-
for i=1,#reactors do
2386+
                reactor.activateReactor()
2387-
local tab = reactors[i].tab
2387+
                if reactors[activeIndex] then
2388-
if tab.x and x >= tab.x and x <= tab.x + tab.w - 1 and y == tab.y then
2388+
                    autoStopped[reactors[activeIndex].reactorAdr] = nil
2389-
syncActive()
2389+
                end
2390-
setActive(i)
2390+
                guiWrite(button.start.x, button.start.y, -1, color.grey, "                 ", button.start.name)
2391-
screenMain()
2391+
                button.start.visible = false
2392-
return
2392+
            end
2393
        end
2394
        if button.stop.visible then
2395-
if x == 1 and y == 1 then
2395+
            local w = button.stop.w or textWidth(button.stop.name)
2396-
event.ignore("touch",tcall)
2396+
            if x >= button.stop.x and x <= button.stop.x + w - 1 and y == button.stop.y then
2397-
prog = false
2397+
                reactor.stopReactor()
2398
                guiWrite(button.stop.x, button.stop.y, -1, color.grey, "                 ", button.stop.name)
2399
                button.stop.visible = false
2400-
-- Экран обзора
2400+
            end
2401-
if handleOverview then
2401+
        end
2402-
if x>= menuItem.options.x and x <= (menuItem.options.x + (menuItem.options.w or #menuItem.options.name) - 1) and y == menuItem.options.y then
2402+
        if x >= menuItem.options.x and x <= (menuItem.options.x + (menuItem.options.w or #menuItem.options.name) - 1) and y == menuItem.options.y then
2403-
screenOptions()
2403+
            screenOptions()
2404-
return
2404+
            return
2405
        end
2406-
if x>= menuItem.refresh.x and x <= (menuItem.refresh.x + (menuItem.refresh.w or #menuItem.refresh.name) - 1) and y == menuItem.refresh.y then
2406+
        if x >= menuItem.overview.x and x <= (menuItem.overview.x + (menuItem.overview.w or #menuItem.overview.name) - 1) and y == menuItem.overview.y then
2407-
refreshReactors(true)
2407+
            syncActive()
2408-
return
2408+
            screenOverview()
2409
            return
2410-
if x>= menuItem.gates.x and x <= (menuItem.gates.x + (menuItem.gates.w or #menuItem.gates.name) - 1) and y == menuItem.gates.y then
2410+
        end
2411-
resetAssignState()
2411+
        if x >= menuItem.refresh.x and x <= (menuItem.refresh.x + (menuItem.refresh.w or #menuItem.refresh.name) - 1) and y == menuItem.refresh.y then
2412-
screenAssign()
2412+
            refreshReactors(true)
2413-
return
2413+
            return
2414
        end
2415-
for i=1,#reactors do
2415+
        if x >= menuItem.gates.x and x <= (menuItem.gates.x + (menuItem.gates.w or #menuItem.gates.name) - 1) and y == menuItem.gates.y then
2416-
local tab = reactors[i].tab
2416+
            resetAssignState()
2417-
if tab.x and x >= tab.x and x <= tab.x + tab.w - 1 and y == tab.y then
2417+
            screenAssign()
2418-
syncActive()
2418+
            return
2419-
setActive(i)
2419+
        end
2420-
screenMain()
2420+
        for i = 1, #reactors do
2421-
return
2421+
            local tab = reactors[i].tab
2422
            if tab.x and x >= tab.x and x <= tab.x + tab.w - 1 and y == tab.y then
2423-
local ctrl = reactors[i].control
2423+
                syncActive()
2424-
if ctrl and ctrl.dec and x >= ctrl.dec.x and x <= ctrl.dec.x + ctrl.dec.w - 1 and y == ctrl.dec.y then
2424+
                setActive(i)
2425-
local flow = getGateFlow(reactors[i].upgate)
2425+
                screenMain()
2426-
reactors[i].upgate.setSignalLowFlow(flow - cfg.default_interval)
2426+
                return
2427-
return
2427+
            end
2428
        end
2429-
if ctrl and ctrl.inc and x >= ctrl.inc.x and x <= ctrl.inc.x + ctrl.inc.w - 1 and y == ctrl.inc.y then
2429+
        if x == 1 and y == 1 then
2430-
local flow = getGateFlow(reactors[i].upgate)
2430+
            event.ignore("touch", tcall)
2431-
reactors[i].upgate.setSignalLowFlow(flow + cfg.default_interval)
2431+
            prog = false
2432-
return
2432+
        end
2433
    end
2434-
if ctrl and ctrl.auto and x >= ctrl.auto.x and x <= ctrl.auto.x + ctrl.auto.w - 1 and y == ctrl.auto.y then
2434+
    if handleOverview then
2435-
reactors[i].autostate = not reactors[i].autostate
2435+
        if x >= menuItem.options.x and x <= (menuItem.options.x + (menuItem.options.w or #menuItem.options.name) - 1) and y == menuItem.options.y then
2436-
if i == activeIndex then
2436+
            screenOptions()
2437-
autostate = reactors[i].autostate
2437+
            return
2438
        end
2439-
refreshOverview()
2439+
        if x >= menuItem.refresh.x and x <= (menuItem.refresh.x + (menuItem.refresh.w or #menuItem.refresh.name) - 1) and y == menuItem.refresh.y then
2440-
return
2440+
            refreshReactors(true)
2441
            return
2442-
local btn = reactors[i].powerBtn
2442+
        end
2443-
if btn.x and x >= btn.x and x <= btn.x + btn.w - 1 and y == btn.y then
2443+
        if x >= menuItem.gates.x and x <= (menuItem.gates.x + (menuItem.gates.w or #menuItem.gates.name) - 1) and y == menuItem.gates.y then
2444-
if btn.action == "start" then
2444+
            resetAssignState()
2445-
ensureFlowInit(reactors[i])
2445+
            screenAssign()
2446-
reactors[i].reactor.activateReactor()
2446+
            return
2447-
autoStopped[reactors[i].reactorAdr] = nil
2447+
        end
2448-
else
2448+
        for i = 1, #reactors do
2449-
reactors[i].reactor.stopReactor()
2449+
            local tab = reactors[i].tab
2450
            if tab.x and x >= tab.x and x <= tab.x + tab.w - 1 and y == tab.y then
2451-
return
2451+
                syncActive()
2452
                setActive(i)
2453
                screenMain()
2454-
if x == 1 and y == 1 then
2454+
                return
2455-
event.ignore("touch",tcall)
2455+
            end
2456-
prog = false
2456+
            local ctrl = reactors[i].control
2457
            if ctrl and ctrl.dec and x >= ctrl.dec.x and x <= ctrl.dec.x + ctrl.dec.w - 1 and y == ctrl.dec.y then
2458
                local flow = getGateFlow(reactors[i].upgate)
2459-
-- Экран настроек
2459+
                reactors[i].upgate.setSignalLowFlow(flow - cfg.default_interval)
2460-
if handleOptions then
2460+
                return
2461-
-- Работа со значениями
2461+
            end
2462-
if canedit then
2462+
            if ctrl and ctrl.inc and x >= ctrl.inc.x and x <= ctrl.inc.x + ctrl.inc.w - 1 and y == ctrl.inc.y then
2463-
if x >= OptionDefault.x and x <= OptionDefault.x + #tostring(OptionDefault.value)-1 and y == OptionDefault.y then
2463+
                local flow = getGateFlow(reactors[i].upgate)
2464-
canclose = false
2464+
                reactors[i].upgate.setSignalLowFlow(flow + cfg.default_interval)
2465-
canedit = false
2465+
                return
2466-
editOption(OptionDefault)
2466+
            end
2467
            if ctrl and ctrl.auto and x >= ctrl.auto.x and x <= ctrl.auto.x + ctrl.auto.w - 1 and y == ctrl.auto.y then
2468-
if x >= OptionCtrl.x and x <= OptionCtrl.x + #tostring(OptionCtrl.value)-1 and y == OptionCtrl.y then
2468+
                reactors[i].autostate = not reactors[i].autostate
2469-
canclose = false
2469+
                if i == activeIndex then
2470-
canedit = false
2470+
                    autostate = reactors[i].autostate
2471-
editOption(OptionCtrl)
2471+
                end
2472
                refreshOverview()
2473-
if x >= OptionShift.x and x <= OptionShift.x + #tostring(OptionShift.value)-1 and y == OptionShift.y then
2473+
                return
2474-
canclose = false
2474+
            end
2475-
canedit = false
2475+
            local btn = reactors[i].powerBtn
2476-
editOption(OptionShift)
2476+
            if btn.x and x >= btn.x and x <= btn.x + btn.w - 1 and y == btn.y then
2477
                if btn.action == "start" then
2478-
if x >= OptionCtrlShift.x and x <= OptionCtrlShift.x + #tostring(OptionCtrlShift.value)-1 and y == OptionCtrlShift.y then
2478+
                    ensureFlowInit(reactors[i])
2479-
canclose = false
2479+
                    reactors[i].reactor.activateReactor()
2480-
canedit = false
2480+
                    autoStopped[reactors[i].reactorAdr] = nil
2481-
editOption(OptionCtrlShift)
2481+
                else
2482
                    reactors[i].reactor.stopReactor()
2483-
if x >= OptionShield.x and x <= OptionShield.x + #tostring(OptionShield.value)-1 and y == OptionShield.y then
2483+
                end
2484-
canclose = false
2484+
                return
2485-
canedit = false
2485+
            end
2486-
editOption(OptionShield)
2486+
        end
2487
        if x == 1 and y == 1 then
2488-
if x >= OptionFuelStop.x and x <= OptionFuelStop.x + #tostring(OptionFuelStop.value)-1 and y == OptionFuelStop.y then
2488+
            event.ignore("touch", tcall)
2489-
canclose = false
2489+
            prog = false
2490-
canedit = false
2490+
        end
2491-
editOption(OptionFuelStop)
2491+
    end
2492
    if handleOptions then
2493
        if canedit then
2494-
-- меню
2494+
            if x >= OptionDefault.x and x <= OptionDefault.x + #tostring(OptionDefault.value) - 1 and y == OptionDefault.y then
2495-
if canclose then
2495+
                canclose = false
2496-
if x>= menuItem.optionsBack.x and x <= (menuItem.optionsBack.x + (menuItem.optionsBack.w or #menuItem.optionsBack.name) - 1) and y == menuItem.optionsBack.y then
2496+
                canedit = false
2497-
screenOverview()
2497+
                editOption(OptionDefault)
2498-
return
2498+
            end
2499
            if x >= OptionCtrl.x and x <= OptionCtrl.x + #tostring(OptionCtrl.value) - 1 and y == OptionCtrl.y then
2500-
if x>= menuItem.save.x and x <= (menuItem.save.x + (menuItem.save.w or #menuItem.save.name) - 1) and y == menuItem.save.y then
2500+
                canclose = false
2501-
cfg.default_interval = OptionDefault.value
2501+
                canedit = false
2502-
cfg.ctrl_interval = OptionCtrl.value
2502+
                editOption(OptionCtrl)
2503-
cfg.shift_interval = OptionShift.value
2503+
            end
2504-
cfg.ctrlShift_interval = OptionCtrlShift.value
2504+
            if x >= OptionShift.x and x <= OptionShift.x + #tostring(OptionShift.value) - 1 and y == OptionShift.y then
2505-
cfg.shield = OptionShield.value
2505+
                canclose = false
2506-
cfg.fuelStopPct = OptionFuelStop.value
2506+
                canedit = false
2507
                editOption(OptionShift)
2508-
screenOverview()
2508+
            end
2509-
return
2509+
            if x >= OptionCtrlShift.x and x <= OptionCtrlShift.x + #tostring(OptionCtrlShift.value) - 1 and y == OptionCtrlShift.y then
2510
                canclose = false
2511-
if x>= menuItem.cancel.x and x <= (menuItem.cancel.x + (menuItem.cancel.w or #menuItem.cancel.name) - 1) and y == menuItem.cancel.y then
2511+
                canedit = false
2512-
OptionDefault.value = cfg.default_interval
2512+
                editOption(OptionCtrlShift)
2513-
OptionCtrl.value = cfg.ctrl_interval
2513+
            end
2514-
OptionShift.value = cfg.shift_interval
2514+
            if x >= OptionShield.x and x <= OptionShield.x + #tostring(OptionShield.value) - 1 and y == OptionShield.y then
2515-
OptionCtrlShift.value = cfg.ctrlShift_interval
2515+
                canclose = false
2516-
OptionShield.value = cfg.shield
2516+
                canedit = false
2517-
OptionFuelStop.value = cfg.fuelStopPct or 98
2517+
                editOption(OptionShield)
2518-
screenOverview()
2518+
            end
2519-
return
2519+
            if x >= OptionFuelStop.x and x <= OptionFuelStop.x + #tostring(OptionFuelStop.value) - 1 and y == OptionFuelStop.y then
2520
                canclose = false
2521
                canedit = false
2522
                editOption(OptionFuelStop)
2523-
-- Экран гейтов
2523+
            end
2524-
-- gates screen
2524+
        end
2525-
if handleAssign then
2525+
        if canclose then
2526-
if assignMode ~= "manual" and assignMode ~= "easy" then
2526+
            if x >= menuItem.optionsBack.x and x <= (menuItem.optionsBack.x + (menuItem.optionsBack.w or #menuItem.optionsBack.name) - 1) and y == menuItem.optionsBack.y then
2527-
if easyAssign.backBtn.x and x>= easyAssign.backBtn.x and x <= easyAssign.backBtn.x + easyAssign.backBtn.w - 1 and y == easyAssign.backBtn.y then
2527+
                screenOverview()
2528-
assignMode = nil
2528+
                return
2529-
easyAssign.active = false
2529+
            end
2530-
screenOverview()
2530+
            if x >= menuItem.save.x and x <= (menuItem.save.x + (menuItem.save.w or #menuItem.save.name) - 1) and y == menuItem.save.y then
2531-
return
2531+
                cfg.default_interval = OptionDefault.value
2532
                cfg.ctrl_interval = OptionCtrl.value
2533-
if easyAssign.heavyBtn.x and x >= easyAssign.heavyBtn.x and x <= easyAssign.heavyBtn.x + easyAssign.heavyBtn.w - 1 and y == easyAssign.heavyBtn.y then
2533+
                cfg.shift_interval = OptionShift.value
2534-
assignMode = "manual"
2534+
                cfg.ctrlShift_interval = OptionCtrlShift.value
2535-
resetAssignState()
2535+
                cfg.shield = OptionShield.value
2536-
screenAssignManual()
2536+
                cfg.fuelStopPct = OptionFuelStop.value
2537-
return
2537+
                configWrite(cfgName)
2538
                screenOverview()
2539-
if easyAssign.easyBtn.x and x >= easyAssign.easyBtn.x and x <= easyAssign.easyBtn.x + easyAssign.easyBtn.w - 1 and y == easyAssign.easyBtn.y then
2539+
                return
2540-
assignMode = "easy"
2540+
            end
2541-
startEasyAssign()
2541+
            if x >= menuItem.cancel.x and x <= (menuItem.cancel.x + (menuItem.cancel.w or #menuItem.cancel.name) - 1) and y == menuItem.cancel.y then
2542-
if not easyAssign.active then
2542+
                OptionDefault.value = cfg.default_interval
2543-
assignMode = nil
2543+
                OptionCtrl.value = cfg.ctrl_interval
2544-
screenAssignChoice()
2544+
                OptionShift.value = cfg.shift_interval
2545-
else
2545+
                OptionCtrlShift.value = cfg.ctrlShift_interval
2546-
screenAssignEasy()
2546+
                OptionShield.value = cfg.shield
2547
                OptionFuelStop.value = cfg.fuelStopPct or 98
2548-
return
2548+
                screenOverview()
2549
                return
2550-
return
2550+
            end
2551-
elseif assignMode == "easy" then
2551+
        end
2552-
if easyAssign.backBtn.x and x>= easyAssign.backBtn.x and x <= easyAssign.backBtn.x + easyAssign.backBtn.w - 1 and y == easyAssign.backBtn.y then
2552+
    end
2553-
if easyAssign.saved and easyAssign.core then
2553+
    if handleAssign then
2554-
clearAssignedByAdr(easyAssign.core)
2554+
        if assignMode ~= "manual" and assignMode ~= "easy" then
2555
            if easyAssign.backBtn.x and x >= easyAssign.backBtn.x and x <= easyAssign.backBtn.x + easyAssign.backBtn.w - 1 and y == easyAssign.backBtn.y then
2556-
easyAssign.active = false
2556+
                assignMode = nil
2557-
easyAssign.step = "reactor"
2557+
                easyAssign.active = false
2558-
easyAssign.core = nil
2558+
                screenOverview()
2559-
easyAssign.shield = nil
2559+
                return
2560-
easyAssign.output = nil
2560+
            end
2561-
easyAssign.saved = false
2561+
            if easyAssign.heavyBtn.x and x >= easyAssign.heavyBtn.x and x <= easyAssign.heavyBtn.x + easyAssign.heavyBtn.w - 1 and y == easyAssign.heavyBtn.y then
2562-
easyAssign.message = nil
2562+
                assignMode = "manual"
2563-
assignMode = nil
2563+
                resetAssignState()
2564-
screenAssignChoice()
2564+
                screenAssignManual()
2565-
return
2565+
                return
2566
            end
2567-
if easyAssign.step == "done" then
2567+
            if easyAssign.easyBtn.x and x >= easyAssign.easyBtn.x and x <= easyAssign.easyBtn.x + easyAssign.easyBtn.w - 1 and y == easyAssign.easyBtn.y then
2568-
if easyAssign.continueBtn.x and x >= easyAssign.continueBtn.x and x <= easyAssign.continueBtn.x + easyAssign.continueBtn.w - 1 and y == easyAssign.continueBtn.y then
2568+
                assignMode = "easy"
2569-
startEasyAssign()
2569+
                startEasyAssign()
2570-
screenAssignEasy()
2570+
                if not easyAssign.active then
2571-
return
2571+
                    assignMode = nil
2572
                    screenAssignChoice()
2573-
if easyAssign.finishBtn.x and x >= easyAssign.finishBtn.x and x <= easyAssign.finishBtn.x + easyAssign.finishBtn.w - 1 and y == easyAssign.finishBtn.y then
2573+
                else
2574-
easyAssign.active = false
2574+
                    screenAssignEasy()
2575-
assignMode = nil
2575+
                end
2576-
refreshReactors(false)
2576+
                return
2577-
screenOverview()
2577+
            end
2578-
return
2578+
            return
2579
        elseif assignMode == "easy" then
2580
            if easyAssign.backBtn.x and x >= easyAssign.backBtn.x and x <= easyAssign.backBtn.x + easyAssign.backBtn.w - 1 and y == easyAssign.backBtn.y then
2581-
return
2581+
                if easyAssign.saved and easyAssign.core then
2582
                    clearAssignedByAdr(easyAssign.core)
2583-
if x>= menuItem.back.x and x <= (menuItem.back.x + (menuItem.back.w or #menuItem.back.name) - 1) and y == menuItem.back.y then
2583+
                end
2584-
if not assignState.reactorIndex and not assignState.shieldGateIdx and not assignState.outGateIdx then
2584+
                easyAssign.active = false
2585-
resetAssignState()
2585+
                easyAssign.step = "reactor"
2586-
assignMode = nil
2586+
                easyAssign.core = nil
2587-
screenOverview()
2587+
                easyAssign.shield = nil
2588-
return
2588+
                easyAssign.output = nil
2589
                easyAssign.saved = false
2590-
assignState.message = "Выбери гейты!"
2590+
                easyAssign.message = nil
2591-
screenAssign()
2591+
                assignMode = nil
2592-
return
2592+
                screenAssignChoice()
2593
                return
2594-
if assignUi.reset and x>= assignUi.reset.x and x <= assignUi.reset.x + assignUi.reset.w - 1 and y == assignUi.reset.y then
2594+
            end
2595-
if assignState.reactorIndex then
2595+
            if easyAssign.step == "done" then
2596-
clearAssignedGates(assignState.reactorIndex)
2596+
                if easyAssign.continueBtn.x and x >= easyAssign.continueBtn.x and x <= easyAssign.continueBtn.x + easyAssign.continueBtn.w - 1 and y == easyAssign.continueBtn.y then
2597-
reactors = buildReactors() or reactors
2597+
                    startEasyAssign()
2598-
resetAssignState()
2598+
                    screenAssignEasy()
2599-
screenAssign()
2599+
                    return
2600
                end
2601-
return
2601+
                if easyAssign.finishBtn.x and x >= easyAssign.finishBtn.x and x <= easyAssign.finishBtn.x + easyAssign.finishBtn.w - 1 and y == easyAssign.finishBtn.y then
2602
                    easyAssign.active = false
2603-
for i=1,#assignUi.reactors do
2603+
                    assignMode = nil
2604-
local btn = assignUi.reactors[i]
2604+
                    refreshReactors(false)
2605-
if btn and x >= btn.x and x <= btn.x + btn.w - 1 and y == btn.y then
2605+
                    screenOverview()
2606-
assignState.reactorIndex = i
2606+
                    return
2607-
assignState.reactorAdr = assignUi.reactorAddrs[i]
2607+
                end
2608-
assignState.shieldGateIdx = nil
2608+
            end
2609-
assignState.shieldGateAdr = nil
2609+
            return
2610-
assignState.outGateIdx = nil
2610+
        end
2611-
assignState.outGateAdr = nil
2611+
        if x >= menuItem.back.x and x <= (menuItem.back.x + (menuItem.back.w or #menuItem.back.name) - 1) and y == menuItem.back.y then
2612-
assignState.step = "shield"
2612+
            if not assignState.reactorIndex and not assignState.shieldGateIdx and not assignState.outGateIdx then
2613-
screenAssign()
2613+
                resetAssignState()
2614-
return
2614+
                assignMode = nil
2615
                screenOverview()
2616
                return
2617-
for i=1,#assignUi.gates do
2617+
            end
2618-
local btn = assignUi.gates[i]
2618+
            assignState.message = "Выбери гейты!"
2619-
if btn and x >= btn.x and x <= btn.x + btn.w - 1 and y == btn.y then
2619+
            screenAssign()
2620-
local gateAdr = assignUi.gateAddrs[i]
2620+
            return
2621-
if assignState.step == "reactor" then
2621+
        end
2622-
return
2622+
        if assignUi.reset and x >= assignUi.reset.x and x <= assignUi.reset.x + assignUi.reset.w - 1 and y == assignUi.reset.y then
2623
            if assignState.reactorIndex then
2624-
if gateAdr and assignUi.gateUse[gateAdr] and assignUi.gateUse[gateAdr] ~= assignUi.selectedAdr then
2624+
                clearAssignedGates(assignState.reactorIndex)
2625-
return
2625+
                reactors = buildReactors() or reactors
2626
                resetAssignState()
2627-
local selectedEntry = assignUi.selectedEntry
2627+
                screenAssign()
2628-
if not assignState.reactorIndex then
2628+
            end
2629-
assignState.step = "reactor"
2629+
            return
2630-
screenAssign()
2630+
        end
2631-
return
2631+
        for i = 1, #assignUi.reactors do
2632
            local btn = assignUi.reactors[i]
2633-
if assignState.step == "shield" then
2633+
            if btn and x >= btn.x and x <= btn.x + btn.w - 1 and y == btn.y then
2634-
assignState.shieldGateIdx = i
2634+
                assignState.reactorIndex = i
2635-
assignState.shieldGateAdr = gateAdr
2635+
                assignState.reactorAdr = assignUi.reactorAddrs[i]
2636-
assignState.step = "output"
2636+
                assignState.shieldGateIdx = nil
2637-
screenAssign()
2637+
                assignState.shieldGateAdr = nil
2638-
return
2638+
                assignState.outGateIdx = nil
2639-
elseif assignState.step == "output" then
2639+
                assignState.outGateAdr = nil
2640-
if assignState.shieldGateAdr and assignState.shieldGateAdr == gateAdr then
2640+
                assignState.step = "shield"
2641-
assignState.message = "Нужны два разных гейта!"
2641+
                screenAssign()
2642-
screenAssign()
2642+
                return
2643-
return
2643+
            end
2644
        end
2645-
assignState.outGateIdx = i
2645+
        for i = 1, #assignUi.gates do
2646-
assignState.outGateAdr = gateAdr
2646+
            local btn = assignUi.gates[i]
2647-
if not assignState.reactorAdr and assignState.reactorIndex then
2647+
            if btn and x >= btn.x and x <= btn.x + btn.w - 1 and y == btn.y then
2648-
assignState.reactorAdr = assignUi.reactorAddrs[assignState.reactorIndex]
2648+
                local gateAdr = assignUi.gateAddrs[i]
2649
                if assignState.step == "reactor" then
2650-
if not assignState.shieldGateAdr and assignState.shieldGateIdx then
2650+
                    return
2651-
assignState.shieldGateAdr = assignUi.gateAddrs[assignState.shieldGateIdx]
2651+
                end
2652
                if gateAdr and assignUi.gateUse[gateAdr] and assignUi.gateUse[gateAdr] ~= assignUi.selectedAdr then
2653-
local saved = saveAssignedGates(assignState.reactorAdr, assignState.shieldGateAdr, assignState.outGateAdr)
2653+
                    return
2654-
if not saved then
2654+
                end
2655-
assignState.message = "Не удалось сохранить гейты!"
2655+
                local selectedEntry = assignUi.selectedEntry
2656-
screenAssign()
2656+
                if not assignState.reactorIndex then
2657-
return
2657+
                    assignState.step = "reactor"
2658
                    screenAssign()
2659-
local targetAdr = assignState.reactorAdr
2659+
                    return
2660-
resetAssignState()
2660+
                end
2661-
assignMode = nil
2661+
                if assignState.step == "shield" then
2662-
handleAssign = false
2662+
                    assignState.shieldGateIdx = i
2663-
handleMain = true
2663+
                    assignState.shieldGateAdr = gateAdr
2664-
handleOverview = false
2664+
                    assignState.step = "output"
2665-
reactors = buildReactors() or reactors
2665+
                    screenAssign()
2666-
local idx = 1
2666+
                    return
2667-
if targetAdr then
2667+
                elseif assignState.step == "output" then
2668-
for j=1,#reactors do
2668+
                    if assignState.shieldGateAdr and assignState.shieldGateAdr == gateAdr then
2669-
if reactors[j].reactorAdr == targetAdr then
2669+
                        assignState.message = "Нужны два разных гейта!"
2670-
idx = j
2670+
                        screenAssign()
2671-
break
2671+
                        return
2672
                    end
2673
                    assignState.outGateIdx = i
2674
                    assignState.outGateAdr = gateAdr
2675-
setActive(idx)
2675+
                    if not assignState.reactorAdr and assignState.reactorIndex then
2676-
if not reactors or #reactors == 0 or not reactor or not upgate or not downgate then
2676+
                        assignState.reactorAdr = assignUi.reactorAddrs[assignState.reactorIndex]
2677-
screenOverview()
2677+
                    end
2678-
return
2678+
                    if not assignState.shieldGateAdr and assignState.shieldGateIdx then
2679
                        assignState.shieldGateAdr = assignUi.gateAddrs[assignState.shieldGateIdx]
2680-
screenMain()
2680+
                    end
2681-
return
2681+
                    local saved = saveAssignedGates(assignState.reactorAdr, assignState.shieldGateAdr, assignState.outGateAdr)
2682
                    if not saved then
2683
                        assignState.message = "Не удалось сохранить гейты!"
2684
                        screenAssign()
2685-
if x == 1 and y == 1 then
2685+
                        return
2686-
event.ignore("touch",tcall)
2686+
                    end
2687-
prog = false
2687+
                    local targetAdr = assignState.reactorAdr
2688
                    resetAssignState()
2689
                    assignMode = nil
2690
                    handleAssign = false
2691
                    handleMain = true
2692-
event.listen("touch",tcall)
2692+
                    handleOverview = false
2693
                    reactors = buildReactors() or reactors
2694
                    local idx = 1
2695
                    if targetAdr then
2696-
screen.overview()
2696+
                        for j = 1, #reactors do
2697
                            if reactors[j].reactorAdr == targetAdr then
2698
                                idx = j
2699-
local now = computer.uptime()
2699+
                                break
2700-
if handleMain and now - lastDetailUpdate >= 0.2 then
2700+
                            end
2701-
lastDetailUpdate = now
2701+
                        end
2702-
if not pcall(refreshInfo) then
2702+
                    end
2703-
autostate = false
2703+
                    setActive(idx)
2704-
if not pcall(screenStart) then
2704+
                    if not reactors or #reactors == 0 or not reactor or not upgate or not downgate then
2705-
break
2705+
                        screenOverview()
2706
                        return
2707-
if not pcall(screenMain) then
2707+
                    end
2708
                    screenMain()
2709-
if not pcall(screenMain) then
2709+
                    return
2710-
break
2710+
                end
2711
            end
2712
        end
2713
        if x == 1 and y == 1 then
2714-
elseif handleOverview and now - lastOverviewUpdate >= 0.5 then
2714+
            event.ignore("touch", tcall)
2715-
lastOverviewUpdate = now
2715+
            prog = false
2716-
if not pcall(refreshOverview) then
2716+
        end
2717-
if not pcall(screenOverview) then
2717+
    end
2718-
break
2718+
2719
2720
event.listen("touch", tcall)
2721
event.listen("component_added", handleComponentAdded)
2722-
if reactors and #reactors > 0 then
2722+
2723-
for i=1,#reactors do
2723+
2724-
autoForReactor(reactors[i], reactors[i].autostate)
2724+
    screen.overview()
2725
end
2726
while prog do
2727-
pollEasyAssign()
2727+
    local now = computer.uptime()
2728-
os.sleep(0)
2728+
    if handleMain and now - lastDetailUpdate >= 0.2 then
2729
        lastDetailUpdate = now
2730
        if not pcall(refreshInfo) then
2731
            autostate = false
2732-
gpu.setResolution(xz,yz)
2732+
            if not pcall(screenStart) then
2733
                break
2734
            end
2735
            if not pcall(screenMain) then
2736
                screenStart()
2737
                if not pcall(screenMain) then
2738
                    break
2739
                end
2740
            end
2741
        end
2742
    elseif handleOverview and now - lastOverviewUpdate >= 0.5 then
2743
        lastOverviewUpdate = now
2744
        if not pcall(refreshOverview) then
2745
            if not pcall(screenOverview) then
2746
                break
2747
            end
2748
        end
2749
    end
2750
    if reactors and #reactors > 0 then
2751
        for i = 1, #reactors do
2752
            autoForReactor(reactors[i], reactors[i].autostate)
2753
        end
2754
    end
2755
    pollEasyAssign()
2756
    os.sleep(0)
2757
end
2758
gpu.setBackground(rback)
2759
gpu.setForeground(rfore)
2760
gpu.setResolution(xz, yz)
2761
term.clear()
2762