diff --git a/src/resources/assets/warpdrive/lua/startup b/src/resources/assets/warpdrive/lua/startup new file mode 100644 index 00000000..38d5e6f0 --- /dev/null +++ b/src/resources/assets/warpdrive/lua/startup @@ -0,0 +1,2035 @@ +monitor_textScale = 0.5 + +-- set alarm side if you need this +alarm_side = "top" + +Style = { + CDefault = colors.white, + BGDefault = colors.blue, + + CTitle = colors.black, + BGTitle = colors.cyan, + + CWarning = colors.white, + BGWarning = colors.red, + + CSuccess = colors.white, + BGSuccess = colors.lime, + + CDisabled = colors.gray, + BGDisabled = colors.blue, + + CRadarmap = colors.gray, + BGRadarmap = colors.green, + + CRadarborder = colors.white, + BGRadarborder = colors.black, + + CRadarself = colors.white, + BGRadarself = colors.lime, + TextRadarself = "R", + + CRadarother = colors.black, + BGRadarother = colors.red, + TextRadarother = "#" +} + +if not term.isColor() then + print("Advanced computer required") + exit() +end + +----------- Monitor support + +function SetMonitorColorFrontBack(frontColor, backgroundColor) + term.setBackgroundColor(backgroundColor) + term.setTextColor(frontColor) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + monitor.setTextColor(frontColor) + monitor.setBackgroundColor(backgroundColor) + end + end +end + +function Write(text) + term.write(text) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + if key ~= data.radar_monitorIndex then + monitor.write(text) + end + end + end +end + +function SetCursorPos(x, y) + term.setCursorPos(x, y) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + if key ~= data.radar_monitorIndex then + monitor.setCursorPos(x, y) + end + end + end +end + +function SetColorDefault() + SetMonitorColorFrontBack(Style.CDefault, Style.BGDefault) +end + +function SetColorTitle() + SetMonitorColorFrontBack(Style.CTitle, Style.BGTitle) +end + +function SetColorWarning() + SetMonitorColorFrontBack(Style.CWarning, Style.BGWarning) +end + +function SetColorSuccess() + SetMonitorColorFrontBack(Style.CSuccess, Style.BGSuccess) +end + +function SetColorDisabled() + SetMonitorColorFrontBack(Style.CDisabled, Style.BGDisabled) +end + +function SetColorRadarmap() + SetMonitorColorFrontBack(Style.CRadarmap, Style.BGRadarmap) +end + +function SetColorRadarborder() + SetMonitorColorFrontBack(Style.CRadarborder, Style.BGRadarborder) +end + +function Clear() + clearWarningTick = -1 + SetColorDefault() + term.clear() + if monitors ~= nil then + for key,monitor in pairs(monitors) do + if key ~= data.radar_monitorIndex then + monitor.clear() + end + end + end + SetCursorPos(1, 1) +end + +function ClearLine() + SetColorDefault() + term.clearLine() + if monitors ~= nil then + for key,monitor in pairs(monitors) do + if key ~= data.radar_monitorIndex then + monitor.clearLine() + end + end + end + SetCursorPos(1, 1) +end + +function WriteLn(Text) + Write(Text) + local x, y = term.getCursorPos() + local width, height = term.getSize() + if y > height - 1 then + y = 1 + end + SetCursorPos(1, y + 1) +end + +function WriteCentered(y, text) + SetCursorPos((51 - text:len()) / 2, y) + term.write(text) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + if key ~= data.radar_monitorIndex then + local sizeX, sizeY = monitor.getSize() + monitor.setCursorPos((sizeX - text:len()) / 2, y) + monitor.write(text) + end + end + end + local xt, yt = term.getCursorPos() + SetCursorPos(1, yt + 1) +end + +function ShowTitle(text) + Clear() + SetColorTitle() + WriteCentered(1, text) + SetColorDefault() +end + +function ShowMenu(Text) + Write(Text) + local xt, yt = term.getCursorPos() + for i = xt, 51 do + Write(" ") + end + SetCursorPos(1, yt+1) +end + +local clearWarningTick = -1 +function ShowWarning(Text) + SetColorWarning() + SetCursorPos((51 - Text:len() - 2) / 2, 19) + Write(" "..Text.." ") + SetColorDefault() + clearWarningTick = 5 +end +function ClearWarning(Text) + if clearWarningTick > 0 then + clearWarningTick = clearWarningTick - 1 + elseif clearWarningTick == 0 then + SetColorDefault() + SetCursorPos(1, 19) + ClearLine() + end +end + +----------- Formatting & popups + +function FormatFloat(value, nbchar) + local str = "?" + if value ~= nil then + str = string.format("%f", value) + end + if nbchar ~= nil then + str = string.sub(" " .. str, -nbchar) + end + return str +end +function FormatInteger(value, nbchar) + local str = "?" + if value ~= nil then + str = string.format("%d", value) + end + if nbchar ~= nil then + str = string.sub(" " .. str, -nbchar) + end + return str +end + +function boolToYesNo(bool) + if bool then + return "YES" + else + return "no" + end +end + +function readInputNumber(currentValue) + local inputAbort = false + local input = string.format(currentValue) + if input == "0" then + input = "" + end + local x, y = term.getCursorPos() + repeat + ClearWarning() + SetColorDefault() + SetCursorPos(x, y) + Write(input .. " ") + input = string.sub(input, -9) + + local params = { os.pullEventRaw() } + local eventName = params[1] + local side = params[2] + if side == nil then side = "none" end + if eventName == "key" then + local keycode = params[2] + if keycode >= 2 and keycode <= 10 then -- 1 to 9 + input = input .. string.format(keycode - 1) + elseif keycode == 11 or keycode == 82 then -- 0 & keypad 0 + input = input .. "0" + elseif keycode >= 79 and keycode <= 81 then -- keypad 1 to 3 + input = input .. string.format(keycode - 78) + elseif keycode >= 75 and keycode <= 87 then -- keypad 4 to 6 + input = input .. string.format(keycode - 71) + elseif keycode >= 71 and keycode <= 73 then -- keypad 7 to 9 + input = input .. string.format(keycode - 64) + elseif keycode == 14 then -- Backspace + input = string.sub(input, 1, string.len(input) - 1) + elseif keycode == 211 then -- Delete + input = "" + elseif keycode == 28 then -- Enter + inputAbort = true + else + ShowWarning("Key " .. keycode .. " is invalid") + end + elseif eventName == "char" then + -- drop it + elseif eventName == "terminate" then + inputAbort = true + elseif not common_event(eventName, params[2]) then + ShowWarning("Event '" .. eventName .. "', " .. side .. " is unsupported") + end + until inputAbort + SetCursorPos(1, y + 1) + if input == "" then + return currentValue + else + return tonumber(input) + end +end + +function readInputText(currentValue) + local inputAbort = false + local input = string.format(currentValue) + local x, y = term.getCursorPos() + repeat + ClearWarning() + SetColorDefault() + SetCursorPos(x, y) + Write(input .. " ") + input = string.sub(input, -30) + + local params = { os.pullEventRaw() } + local eventName = params[1] + local side = params[2] + if side == nil then side = "none" end + if eventName == "key" then + local keycode = params[2] + if keycode == 14 then -- Backspace + input = string.sub(input, 1, string.len(input) - 1) + elseif keycode == 211 then -- Delete + input = "" + elseif keycode == 28 then -- Enter + inputAbort = true + else + -- ShowWarning("Key " .. keycode .. " is invalid") + end + elseif eventName == "char" then + local char = params[2] + if char >= ' ' and char <= '~' then -- 1 to 9 + input = input .. char + else + ShowWarning("Char #" .. string.byte(char) .. " is invalid") + end + elseif eventName == "terminate" then + inputAbort = true + elseif not common_event(eventName, params[2]) then + ShowWarning("Event '" .. eventName .. "', " .. side .. " is unsupported") + end + until inputAbort + SetCursorPos(1, y + 1) + if input == "" then + return currentValue + else + return input + end +end + +function readConfirmation() + ShowWarning("Are you sure? (y/n)") + repeat + local params = { os.pullEventRaw() } + local eventName = params[1] + local side = params[2] + if side == nil then side = "none" end + if eventName == "key" then + local keycode = params[2] + if keycode == 21 then -- Y + return true + else + return false + end + elseif eventName == "char" then + elseif eventName == "terminate" then + return false + elseif not common_event(eventName, params[2]) then + ShowWarning("Event '" .. eventName .. "', " .. side .. " is unsupported") + end + until false +end + +----------- commons: menu, event handlers, etc. + +function common_event(eventName, param) + if eventName == "redstone" then + redstone_event(param) + elseif eventName == "timer" then + if param == radar_timerId then + radar_timerEvent() + end + elseif eventName == "reactorPulse" then + reactor_pulse(param) +-- elseif eventName == "reactorDeactivation" then +-- ShowWarning("Reactor deactivated") +-- elseif eventName == "reactorActivation" then +-- ShowWarning("Reactor activated") + else + return false + end + return true +end + +function menu_common() + SetCursorPos(1, 18) + SetColorTitle() + ShowMenu("1 Reactor, 2 Cloak, 3 Mining, 4 Core, 5 Radar, eXit") +end + +----------- Redstone support + +local tblRedstoneState = {-- Remember redstone state on each side + ["top"] = rs.getInput("top"), + ["front"] = rs.getInput("front"), + ["left"] = rs.getInput("left"), + ["right"] = rs.getInput("right"), + ["back"] = rs.getInput("back"), + ["bottom"] = rs.getInput("bottom"), +} +local tblSides = {-- list all sides and offset coordinates + ["top" ] = { 3, 1}, + ["front" ] = { 1, 3}, + ["left" ] = { 3, 3}, + ["right" ] = { 5, 3}, + ["back" ] = { 5, 5}, + ["bottom"] = { 3, 5}, +} + +function redstone_event() + -- Event only returns nil so we need to check sides manually + local message = "" + for side, state in pairs(tblRedstoneState) do + if rs.getInput(side) ~= state then + -- print(side .. " is now " .. tostring(rs.getInput(side))) + message = message .. side .. " " + tblRedstoneState[side] = rs.getInput(side) + end + end + if message ~= "" then + message = "Redstone changed on " .. message + showWarning(message) + end +end + +----------- Cloaking support + +cloaking_highTier = false +cloaking_currentKey = 1 +function cloaking_key(keycode) + if keycode == 31 then -- S + cloaking_start() + return true + elseif keycode == 25 then -- P + cloaking_stop() + return true + elseif keycode == 20 then -- T + cloaking_highTier = not cloaking_highTier + return true + end + return false +end + +function cloaking_page() + ShowTitle(label .. " - Cloaking status") + + local cloakingcore = nil + if cloakingcores ~= nil then + if cloaking_currentKey > #cloakingcores then + cloaking_currentKey = 1 + end + cloakingcore = cloakingcores[cloaking_currentKey] + end + + SetCursorPos(1, 2) + if #cloakingcores == 0 then + SetColorDisabled() + Write("No cloaking core detected...") + elseif cloakingcore == nil then + SetColorWarning() + Write("Cloaking core " .. cloaking_currentKey .. " of " .. #cloakingcores .. " is invalid") + else + SetColorDefault() + Write("Cloaking core " .. cloaking_currentKey .. " of " .. #cloakingcores) + local isAssemblyValid = cloakingcore.isAssemblyValid() + local energy, energyMax = cloakingcore.getEnergyLevel() + local isEnabled = cloakingcore.enable() + + if not isAssemblyValid then + SetColorWarning() + SetCursorPos(1, 3) + Write("Invalid assembly!") + SetColorDefault() + SetCursorPos(1, 4) + print("In each direction, you need to place exactly 2 Cloaking device coils, for a total of 12 coils.") + print("The 6 inner coils shall be exactly one block away from the core.") + print("The cloaking field will extend 5 blocks past the outer 6 coils.") + print("Power consumption scales with the amount of cloaked blocks.") + else + SetCursorPos(1, 4) + Write("Assembly is valid") + + if energy < 50000 then + SetColorWarning() + else + SetColorDefault() + end + SetCursorPos(1, 6) + Write("Energy level is " .. energy .. " EU") + + SetCursorPos(1, 8) + if isEnabled then + if energy <= 100 then + SetColorWarning() + else + SetColorSuccess() + end + Write("Cloak is enabled") + else + SetColorNormal() + Write("Cloak is disabled") + end + end + end + sleep(0.1) + cloaking_currentKey = cloaking_currentKey + 1 + + SetColorDefault() + SetCursorPos(1, 12) + Write(" -----------------------------------------------") + SetCursorPos(1, 13) + if cloaking_highTier then + Write("Cloak tier: HIGH") + else + Write("Cloak tier: low") + end + + SetColorTitle() + SetCursorPos(1, 16) + ShowMenu("S - Start cloaking, P - stoP cloaking") + SetCursorPos(1, 17) + ShowMenu("T - change low/high Tier") +end + +function cloaking_start() + for key,cloakingcore in pairs(cloakingcores) do + cloakingcore.enable(false) + if cloaking_highTier then + cloakingcore.tier(2) + else + cloakingcore.tier(1) + end + cloakingcore.enable(true) + end +end + +function cloaking_stop() + for key,cloakingcore in pairs(cloakingcores) do + cloakingcore.enable(false) + end +end + +----------- Mining lasers support + +mining_currentKey = 1 +mining_layerOffset = 1 +mining_mineAll = true +mining_useDeuterium = false +function mining_key(keycode) + if keycode == 31 then -- S + mining_start() + return true + elseif keycode == 25 then -- P + mining_stop() + return true + elseif keycode == 30 then -- A + mining_mineAll = not mining_mineAll + return true + elseif keycode == 32 then -- D + mining_useDeuterium = not mining_useDeuterium + return true + elseif keycode == 74 then -- - + mining_layerOffset = mining_layerOffset - 1 + if mining_layerOffset < 1 then + mining_layerOffset = 1 + end + return true + elseif keycode == 78 then -- + + mining_layerOffset = mining_layerOffset + 1 + return true + elseif keycode == 46 then -- C + mining_page_config() + return true + end + return false +end + +function mining_page() + ShowTitle(label .. " - Mining status") + + local mininglaser = nil + if mininglasers ~= nil then + if mining_currentKey > #mininglasers then + mining_currentKey = 1 + end + mininglaser = mininglasers[mining_currentKey] + end + + SetCursorPos(1, 2) + if #mininglasers == 0 then + SetColorDisabled() + Write("No mining laser detected...") + elseif mininglaser == nil then + SetColorWarning() + Write("Mining laser " .. mining_currentKey .. " of " .. #mininglasers .. " is invalid") + else + SetColorDefault() + Write("Mining laser " .. mining_currentKey .. " of " .. #mininglasers) + local status, energy, currentLayer, mined, total = mininglaser.state() + SetCursorPos(1, 3) + Write("Status: " .. status .. " ") + SetCursorPos(1, 5) + Write("Energy level is " .. energy .. " EU") + SetCursorPos(1, 7) + Write("Mined " .. mined .. " out of " .. total .. " blocks at layer " .. currentLayer .. " ") + end + sleep(0.1) + mining_currentKey = mining_currentKey + 1 + + SetColorDefault() + SetCursorPos(1, 11) + Write(" -----------------------------------------------") + SetCursorPos(1, 12) + Write("Layer offset: " .. mining_layerOffset) + SetCursorPos(1, 13) + Write("Mine all: " .. boolToYesNo(mining_mineAll)) + SetCursorPos(1, 14) + Write("Use Deuterium: " .. boolToYesNo(mining_useDeuterium)) + + SetColorTitle() + SetCursorPos(1, 16) + ShowMenu("S - Start mining, P - stoP mining, A - mine All") + SetCursorPos(1, 17) + ShowMenu("D - use Deuterium, +/-/C - adjust offset") +end + +function mining_page_config() + ShowTitle(label .. " - Mining configuration") + Write(" Layer offset (".. mining_layerOffset ..") : ") + mining_layerOffset = readInputNumber(mining_layerOffset) + if mining_layerOffset < 1 then + mining_layerOffset = 1 + end +end + +function mining_start() + for key,mininglaser in pairs(mininglasers) do + if not mininglaser.isMining() then + mininglaser.offset(mining_layerOffset) + if mining_mineAll then + if mining_useDeuterium then + mininglaser.quarry(mining_useDeuterium) + else + mininglaser.quarry() + end + else + if mining_useDeuterium then + mininglaser.mine(mining_useDeuterium) + else + mininglaser.mine() + end + end + end + end +end + +function mining_stop() + if #mininglasers == 0 then + SetColorWarning() + Write("No mining laser detected") + else + for key,mininglaser in pairs(mininglasers) do + SetCursorPos(1, 2 + key) + if not mininglaser.isMining() then + SetColorDisabled() + Write("Mining laser " .. key .. " of " .. #mininglasers .. " is already stopped") + else + mininglaser.stop() + SetColorSuccess() + Write("Mining laser " .. key .. " of " .. #mininglasers .. " has been stopped") + end + end + end +end + +----------- Configuration + +function data_save() + local file = fs.open("shipdata.txt", "w") + file.writeLine(textutils.serialize(data)) + file.close() +end + +function data_read() + if fs.exists("shipdata.txt") then + local file = fs.open("shipdata.txt", "r") + data = textutils.unserialize(file.readAll()) + file.close() + else + data = { } + end + if data.core_summon == nil then data.core_summon = false; end + if data.core_distance == nil then data.core_distance = 0; end + if data.core_direction == nil then data.core_direction = 0; end + if data.reactor_mode == nil then data.reactor_mode = 0; end + if data.reactor_rate == nil then data.reactor_rate = 100; end + if data.reactor_targetStability == nil then data.reactor_targetStability = 50; end + if data.reactor_laserAmount == nil then data.reactor_laserAmount = 10000; end + if data.radar_monitorIndex == nil then data.radar_monitorIndex = 0; end + if data.radar_radius == nil then data.radar_radius = 500; end + if data.radar_autoscan == nil then data.radar_autoscan = false; end + if data.radar_autoscanDelay == nil then data.radar_autoscanDelay = 3; end + if data.radar_results == nil then data.radar_results = {}; end + if data.radar_scale == nil then data.radar_scale = 500; end + if data.radar_offsetX == nil then data.radar_offsetX = 0; end + if data.radar_offsetY == nil then data.radar_offsetY = 0; end +end + +function data_explode(separator, data) + local result, iCurrent, iNext + result = {} + iCurrent = 0 + if(#data == 1) then return {data} end + while true do + iNext = string.find(data, separator, iCurrent, true) + if iNext ~= nil then + table.insert(result, string.sub(data, iCurrent, iNext - 1)) + iCurrent = iNext + 1 + else + table.insert(result, string.sub(data, iCurrent)) + break + end + end + return result +end + +function data_setName() + if warpcore ~= nil then + ShowTitle("<==== Set ship name ====>") + else + ShowTitle("<==== Set name ====>") + end + + SetCursorPos(1, 2) + Write("Enter ship name: ") + label = readInputText(label) + os.setComputerLabel(label) + if warpcore ~= nil then + warpcore.coreFrequency(label) + end + os.reboot() +end + +----------- Warpcore support + +core_front = 0 +core_right = 0 +core_up = 0 +core_back = 0 +core_left = 0 +core_down = 0 +core_isInHyper = false +core_shipLength = 0 +core_realDistance = 0 +core_jumpCost = 0 +core_shipSize = 0 + +function core_boot() + if warpcore == nil then + return + end + + Write("Booting Warpdrive Core") + + if data.core_summon then + warpcore.summon_all() + end + + Write(".") + core_front, core_right, core_up = warpcore.dim_positive() + core_back, core_left, core_down = warpcore.dim_negative() + core_isInHyper = warpcore.isInHyperspace() + + Write(".") + repeat + pos = warpcore.pos() + sleep(0.3) + until pos ~= nil + X, Y, Z = warpcore.pos() + Write(".") + repeat + isAttached = warpcore.isAttached() + sleep(0.3) + until isAttached ~= false + + Write(".") + repeat + core_shipSize = warpcore.getShipSize() + sleep(0.3) + until core_shipSize ~= nil + + Write(".") + core_computeRealDistance() + + Write(".") + warpcore.mode(1) + WriteLn("") +end + +function core_writeDirection() + if data.core_direction == 1 then + WriteLn(" Direction = Up") + elseif data.core_direction == 2 then + WriteLn(" Direction = Down") + elseif data.core_direction == 0 then + WriteLn(" Direction = Front") + elseif data.core_direction == 180 then + WriteLn(" Direction = Back") + elseif data.core_direction == 90 then + WriteLn(" Direction = Left") + elseif data.core_direction == 255 then + WriteLn(" Direction = Right") + end +end + +function core_computeRealDistance() + if core_isInHyper then + core_shipLength = 0 + core_realDistance = data.core_distance * 100 + core_shipLength + core_jumpCost = (1000 * core_shipSize) + (1000 * data.core_distance) + else + if data.core_direction == 1 or data.core_direction == 2 then + core_shipLength = core_up + core_down + 1 + elseif data.core_direction == 0 or data.core_direction == 180 then + core_shipLength = core_front + core_back + 1 + elseif data.core_direction == 90 or data.core_direction == 255 then + core_shipLength = core_left + core_right + 1 + end + core_realDistance = data.core_distance + core_shipLength - 1 + core_jumpCost = (10 * core_shipSize) + (100 * data.core_distance) + end +end + +function core_computeNewCoordinates(cx, cy, cz) + local res = { x = cx, y = cy, z = cz } + if data.core_direction == 1 then + res.y = res.y + core_realDistance + elseif data.core_direction == 2 then + res.y = res.y - core_realDistance + end + local dx, dy, dz = warpcore.getOrientation() + if dx ~= 0 then + if data.core_direction == 0 then + res.x = res.x + (core_realDistance * dx) + elseif data.core_direction == 180 then + res.x = res.x - (core_realDistance * dx) + elseif data.core_direction == 90 then + res.z = res.z + (core_realDistance * dx) + elseif data.core_direction == 255 then + res.z = res.z - (core_realDistance * dx) + end + else + if data.core_direction == 0 then + res.z = res.z + (core_realDistance * dz) + elseif data.core_direction == 180 then + res.z = res.z - (core_realDistance * dz) + elseif data.core_direction == 90 then + res.x = res.x + (core_realDistance * dz) + elseif data.core_direction == 255 then + res.x = res.x - (core_realDistance * dz) + end + end + return res +end + +function core_warp() + rs.setOutput(alarm_side, true) + if readConfirmation() then + rs.setOutput(alarm_side, false) + warpcore.direction(data.core_direction) + warpcore.distance(data.core_distance) + if core_isInHyper then + warpcore.mode(2) + else + warpcore.mode(1) + end + warpcore.jump() + end + rs.setOutput(alarm_side, false) +end + +function core_page_setDistance() + ShowTitle("<==== Set distance ====>") + + core_computeRealDistance() + local maximumDistance = core_shipLength + 127 + local userEntry = core_realDistance + if userEntry <= 1 then + userEntry = 0 + end + repeat + SetCursorPos(1, 2) + if core_isInHyper then + Write("Distance * 100 (min " .. core_shipLength .. ", max " .. maximumDistance .. "): ") + else + Write("Distance (min " .. (core_shipLength + 1) .. ", max " .. maximumDistance .. "): ") + end + userEntry = readInputNumber(userEntry) + if userEntry <= core_shipLength or userEntry > maximumDistance then + ShowWarning("Wrong distance. Try again.") + end + until userEntry > core_shipLength and userEntry <= maximumDistance + + data.core_distance = userEntry - core_shipLength + 1 + core_computeRealDistance() +end + +function core_page_setDirection() + local drun = true + while(drun) do + ShowTitle("<==== Set direction ====>") + core_writeDirection() + term.setCursorPos(1, 16) + SetColorTitle() + ShowMenu("Use directional keys") + ShowMenu("W/S keys for Up/Down") + ShowMenu("Enter - confirm") + SetColorDefault() + local event, keycode = os.pullEvent("key") + if keycode == 200 then + data.core_direction = 0 + elseif keycode == 17 then + data.core_direction = 1 + elseif keycode == 203 then + data.core_direction = 90 + elseif keycode == 205 then + data.core_direction = 255 + elseif keycode == 208 then + data.core_direction = 180 + elseif keycode == 31 then + data.core_direction = 2 + elseif keycode == 28 then + drun = false + end + end +end + +function core_page_setDimensions() + ShowTitle("<==== Set dimensions ====>") + Write(" Front (".. core_front ..") : ") + core_front = readInputNumber(core_front) + Write(" Right (".. core_right ..") : ") + core_right = readInputNumber(core_right) + Write(" Up (".. core_up ..") : ") + core_up = readInputNumber(core_up) + Write(" Back (".. core_back ..") : ") + core_back = readInputNumber(core_back) + Write(" Left (".. core_left ..") : ") + core_left = readInputNumber(core_left) + Write(" Down (".. core_down ..") : ") + core_down = readInputNumber(core_down) + Write("Setting dimensions...") + warpcore.dim_positive(core_front, core_right, core_up) + warpcore.dim_negative(core_back, core_left, core_down) + core_shipSize = warpcore.getShipSize() + if core_shipSize == nil then core_shipSize = 0 end +end + +function core_page_summon() + ShowTitle("<==== Summon players ====>") + local playersString, playersArray = warpcore.getAttachedPlayers() + for i = 1, #playersArray do + Show(i..". "..playersArray[i]) + end + SetColorTitle() + ShowMenu("Enter player number") + ShowMenu("or press enter to summon everyone") + SetColorDefault() + + Write(":") + local input = readInputNumber("") + if input == "" then + warpcore.summon_all() + else + input = tonumber(input) + warpcore.summon(input - 1) + end +end + +function core_page_jumpToBeacon() + ShowTitle("<==== Jump to beacon ====>") + + Write("Enter beacon frequency: ") + local freq = readInputText("") + rs.setOutput(alarm_side, true) + if readConfirmation() then + rs.setOutput(alarm_side, false) + warpcore.mode(4) + warpcore.beaconFrequency(freq) + warpcore.jump() + end + rs.setOutput(alarm_side, false) +end + +function core_page_jumpToGate() + ShowTitle("<==== Jump to Jumpgate ====>") + + Write("Enter jumpgate name: ") + local name = readInputText("") + rs.setOutput(alarm_side, true) + if readConfirmation() then + rs.setOutput(alarm_side, false) + warpcore.mode(6) + warpcore.targetJumpgate(name) + warpcore.jump() + end + rs.setOutput(alarm_side, false) +end + +function core_page() + ShowTitle(label .. " - Warpcore status") + if warpcore ~= nil then + WriteLn("Core:") + WriteLn(" x, y, z = " .. X .. ", " .. Y .. ", " .. Z) + local energy, energyMax = warpcore.getEnergyLevel() + if energy == nil then energy = 0 end + if energyMax == nil then energyMax = 1 end + WriteLn(" Energy = " .. math.floor(energy / energyMax * 100) .. " % (" .. energy .. "EU)") + local playersString, playersArray = warpcore.getAttachedPlayers() + if playersString == "" then players = "-" end + WriteLn(" Attached players = " .. playersString) + WriteLn("Dimensions:") + WriteLn(" Front, Right, Up = " .. FormatInteger(core_front) .. ", " .. FormatInteger(core_right) .. ", " .. FormatInteger(core_up)) + WriteLn(" Back, Left, Down = " .. FormatInteger(core_back) .. ", " .. FormatInteger(core_left) .. ", " .. FormatInteger(core_down)) + WriteLn(" Size = " .. core_shipSize .. " blocks") + WriteLn("Warp data:") + core_writeDirection() + local dest = core_computeNewCoordinates(X, Y, Z) + WriteLn(" Distance = " .. core_realDistance .. " (" .. core_jumpCost .. "EU, " .. math.floor(energy / core_jumpCost) .. " jumps)") + WriteLn(" Dest.coordinates = " .. FormatInteger(dest.x) .. ", " .. FormatInteger(dest.y) .. ", " .. FormatInteger(dest.z)) + if data.core_summon then + WriteLn(" Summon after = Yes") + else + WriteLn(" Summon after = No") + end + else + ShowWarning("No warpcore controller detected") + end + + SetCursorPos(1, 15) + SetColorTitle() + ShowMenu("D - Dimensions, M - Toggle summon, N - Ship name") + ShowMenu("S - Set Warp Data, J - Jump, G - Jump to JumpGate") + ShowMenu("B - Jump to Beacon, H - Jump to Hyperspace") + ShowMenu("C - core_page_summon crew") +end + +function core_key(keycode) + if keycode == 31 then -- S + core_page_setDirection() + core_page_setDistance() + data_save() + return true + elseif keycode == 50 then -- M + if data.core_summon then + data.core_summon = false + else + data.core_summon = true + end + data_save() + return true + elseif keycode == 32 then -- D + core_page_setDimensions() + data_save() + return true + elseif keycode == 36 then -- J + core_warp() + return true + elseif keycode == 46 then -- C + core_page_summon() + return true + elseif keycode == 48 then -- B + core_page_jumpToBeacon() + return true + elseif keycode == 34 then -- G + core_page_jumpToGate() + return true + elseif keycode == 35 then -- H + rs.setOutput(alarm_side, true) + if readConfirmation() then + rs.setOutput(alarm_side, false) + warpcore.mode(5) + warpcore.jump() + end + rs.setOutput(alarm_side, false) + return true + elseif keycode == 49 then + data_setName() + return true + end + return false +end + +----------- Reactor support + +reactor_output = 0 + +function reactor_boot() + if reactor ~= nil then + WriteLn("Booting Reactor...") + local isActive, strMode, releaseRate = reactor.active() + if strMode == "OFF" then + data.reactor_mode = 0 + elseif strMode == "MANUAL" then + data.reactor_mode = 1 + elseif strMode == "ABOVE" then + data.reactor_mode = 2 + elseif strMode == "RATE" then + data.reactor_mode = 3 + else + data.reactor_mode = 0 + end + end +end + +function reactor_key(keycode) + if keycode == 31 then -- S + reactor_start() + return true + elseif keycode == 25 then -- P + reactor_stop() + return true + elseif keycode == 38 then -- L + reactor_laser() + return true + elseif keycode == 24 then -- O + data.reactor_mode = (data.reactor_mode + 1) % 4 + reactor_setMode() + data_save() + return true + elseif keycode == 34 then -- G + data.reactor_rate = data.reactor_rate / 10 + reactor_setMode() + data_save() + return true + elseif keycode == 20 then -- T + data.reactor_rate = data.reactor_rate * 10 + reactor_setMode() + data_save() + return true + elseif keycode == 36 then -- J + data.reactor_laserAmount = data.reactor_laserAmount / 10 + reactor_setLaser() + data_save() + return true + elseif keycode == 22 then -- U + data.reactor_laserAmount = data.reactor_laserAmount * 10 + reactor_setLaser() + data_save() + return true + elseif keycode == 74 then -- - + data.reactor_targetStability = data.reactor_targetStability - 1 + reactor_setTargetStability() + data_save() + return true + elseif keycode == 78 then -- + + data.reactor_targetStability = data.reactor_targetStability + 1 + reactor_setTargetStability() + data_save() + return true + elseif keycode == 46 then -- C + reactor_config() + data_save() + return true + end + return false +end + +function reactor_page() + ShowTitle(label .. " - Reactor status") + + SetCursorPos(1, 2) + if reactor == nil then + SetColorDisabled() + Write("Reactor not detected") + else + SetColorDefault() + Write("Reactor stability") + instabilities = { reactor.instability() } + average = 0 + for key,instability in pairs(instabilities) do + SetCursorPos(12, 2 + key) + stability = math.floor((100.0 - instability) * 10) / 10 + if stability >= data.reactor_targetStability then + SetColorSuccess() + else + SetColorWarning() + end + Write(FormatFloat(stability, 5) .. " %") + average = average + instability + end + average = average / #instabilities + + SetColorDefault() + local energy = { reactor.energy() } + SetCursorPos(1, 7) + Write("Energy : ") + if energy[1] ~= nil then + Write(FormatInteger(energy[1], 10) .. " / " .. energy[2] .. " RF +" .. FormatInteger(reactor_output, 5) .. " RF/t") + else + Write("???") + end + SetCursorPos(1, 8) + Write("Outputing: ") + if energy[1] ~= nil then + Write(energy[3] .. " RF/t") + end + + SetColorDefault() + SetCursorPos(1, 9) + Write("Activated: ") + isActive = reactor.active() + if isActive then SetColorSuccess() else SetColorDefault() end + Write(boolToYesNo(isActive)) + end + + if #reactorlasers == 0 then + SetColorDisabled() + SetCursorPos(30, 2) + Write("Lasers not detected") + else + SetColorDefault() + SetCursorPos(30, 2) + Write("Lasers") + + for key,reactorlaser in pairs(reactorlasers) do + local side = reactorlaser.side() + if side ~= nil then + side = side % 4 + SetColorDefault() + SetCursorPos(4, 3 + side) + Write("Side " .. side .. ":") + SetCursorPos(30, 3 + side) + local energy = reactorlaser.energy() + if not reactorlaser.hasReactor() then + SetColorDisabled() + elseif energy > 3 * data.reactor_laserAmount then + SetColorSuccess() + else + SetColorWarning() + end + Write(FormatInteger(reactorlaser.energy(), 6)) + end + end + end + + SetColorDefault() + SetCursorPos(1, 10) + Write(" -----------------------------------------------") + SetCursorPos(1, 11) + Write("Output mode : ") + if data.reactor_mode == 0 then + SetColorDisabled() + Write("hold") + elseif data.reactor_mode == 1 then + Write("manual/unlimited") + elseif data.reactor_mode == 2 then + Write("surplus above " .. data.reactor_rate .. " RF") + else + Write("rated at " .. data.reactor_rate .. " RF") + end + SetColorDefault() + SetCursorPos( 1, 12) + Write("Target stability: " .. data.reactor_targetStability .. "%") + SetCursorPos(30, 12) + Write("Laser amount: " .. data.reactor_laserAmount) + + SetColorTitle() + SetCursorPos(1, 14) + ShowMenu("S - Start reactor, P - Stop reactor, L - Use lasers") + SetCursorPos(1, 15) + ShowMenu("O - Output mode, C - Configuration") + SetCursorPos(1, 16) + ShowMenu("+/- - Target stability, U/J - Laser amount") + SetCursorPos(1, 17) + ShowMenu("G/T - Output rate/threshold") +end + +function reactor_setMode() + if data.reactor_rate < 1 then + data.reactor_rate = 1 + elseif data.reactor_rate > 100000 then + data.reactor_rate = 100000 + end + if reactor ~= nil then + if data.reactor_mode == 0 then + reactor.release(false) + elseif data.reactor_mode == 1 then + reactor.release(true) + elseif data.reactor_mode == 2 then + reactor.releaseAbove(data.reactor_rate) + else + reactor.releaseRate(data.reactor_rate) + end + end +end + +function reactor_setLaser() + if data.reactor_laserAmount < 1 then + data.reactor_laserAmount = 1 + elseif data.reactor_laserAmount > 100000 then + data.reactor_laserAmount = 100000 + end +end + +function reactor_setTargetStability() + if data.reactor_targetStability < 1 then + data.reactor_targetStability = 1 + elseif data.reactor_targetStability > 100 then + data.reactor_targetStability = 100 + end +end + +function reactor_start() + if reactor ~= nil then + reactor_setMode() + reactor.active(true) + end +end + +function reactor_stop() + if reactor ~= nil then + reactor.active(false) + end +end + +function reactor_laser(side) + for key,reactorlaser in pairs(reactorlasers) do + if (side == nil) or (reactorlaser.side() == side) then + reactorlaser.sendLaser(data.reactor_laserAmount) + end + end +end + +function reactor_pulse(output) + reactor_output = output + if reactor == nil then + os.reboot() + end + local instabilities = { reactor.instability() } + for key,instability in pairs(instabilities) do + local stability = math.floor((100.0 - instability) * 10) / 10 + if stability < data.reactor_targetStability then + reactor_laser(key - 1) + end + end +end + +function reactor_config() + ShowTitle(label .. " - Reactor configuration") + + SetCursorPos(1, 2) + if reactor == nil then + SetColorDisabled() + Write("Reactor not detected") + else + SetColorDefault() + SetCursorPos(1, 4) + Write("Reactor output rate (" .. data.reactor_rate .. " RF): ") + data.reactor_rate = readInputNumber(data.reactor_rate) + reactor_setMode() + SetCursorPos(1, 5) + Write("Reactor output rate set") + + SetCursorPos(1, 7) + Write("Laser energy level (" .. data.reactor_laserAmount .. "): ") + data.reactor_laserAmount = readInputNumber(data.reactor_laserAmount) + reactor_setLaser() + SetCursorPos(1, 8) + Write("Laser energy level set") + + SetCursorPos(1, 10) + Write("Reactor target stability (" .. data.reactor_targetStability .. "%): ") + data.reactor_targetStability = readInputNumber(data.reactor_targetStability) + reactor_setTargetStability() + SetCursorPos(1, 11) + Write("Reactor target stability set") + end +end + +----------- Radar support + +radar_listOffset = 0 +radar_timerId = -1 +radar_timerLength = 1 +radar_x = 0 +radar_y = 0 +radar_z = 0 + +function radar_boot() + if radar ~= nil then + WriteLn("Booting Radar...") + if data.radar_monitorIndex > 0 then + radar_x, radar_y, radar_z = radar.pos() + radar_drawMap() + end + if data.radar_autoscan then + radar_scan() + end + end +end + +function radar_key(keycode) + if keycode == 31 then -- S + data.radar_autoscan = false + radar_scan() + return true + elseif keycode == 30 then -- A + data.radar_autoscan = true + radar_scan() + return true + elseif keycode == 25 then -- P + data.radar_autoscan = false + return true + elseif keycode == 49 then -- N + radar_setMonitorIndex(data.radar_monitorIndex + 1) + data_save() + radar_drawMap() + return true + elseif keycode == 34 then -- G + radar_setRadius(data.radar_radius - 100) + data_save() + return true + elseif keycode == 20 then -- T + if data.radar_radius < 100 then + radar_setRadius(100) + else + radar_setRadius(data.radar_radius + 100) + end + data_save() + return true + elseif keycode == 36 then -- J + radar_listOffset = math.max(0, radar_listOffset - 3) + return true + elseif keycode == 22 then -- U + radar_listOffset = math.min(#data.radar_results - 1, radar_listOffset + 3) + return true + elseif keycode == 74 then -- - + data.radar_scale = math.min(10000, math.floor(data.radar_scale * 1.2 + 0.5)) + data_save() + radar_drawMap() + return true + elseif keycode == 78 then -- + + data.radar_scale = math.max(20, math.floor(data.radar_scale * 0.8 + 0.5)) + data_save() + radar_drawMap() + return true + elseif keycode == 199 then -- home + data.radar_offsetX = 0; + data.radar_offsetY = 0; + data.radar_scale = 20 + for i = 0, #data.radar_results - 1 do + data.radar_scale = math.max(data.radar_scale, math.max(math.abs(radar_x - data.radar_results[i].x), math.abs(radar_z - data.radar_results[i].z))) + end + data.radar_scale = math.min(10000, math.floor(data.radar_scale * 1.1 + 0.5)) + data_save() + radar_drawMap() + return true + elseif keycode == 203 then -- left + data.radar_offsetX = data.radar_offsetX - 0.20 * data.radar_scale; + data_save() + radar_drawMap() + return true + elseif keycode == 205 then -- right + data.radar_offsetX = data.radar_offsetX + 0.20 * data.radar_scale; + data_save() + radar_drawMap() + return true + elseif keycode == 200 then -- up + data.radar_offsetY = data.radar_offsetY - 0.20 * data.radar_scale; + data_save() + radar_drawMap() + return true + elseif keycode == 208 then -- down + data.radar_offsetY = data.radar_offsetY + 0.20 * data.radar_scale; + data_save() + radar_drawMap() + return true + elseif keycode == 46 then -- C + radar_page_config() + data_save() + return true + end + return false +end + +function radar_page() + local radar_resultsPerPage = 9 + + ShowTitle(label .. " - Radar map") + + SetCursorPos(1, 2) + if radar == nil then + SetColorDisabled() + Write("Radar not detected") + else + SetColorDefault() + if #data.radar_results == 0 then + Write("No contacts in range...") + else + local lastResultShown = radar_listOffset + radar_resultsPerPage - 1 + if lastResultShown >= #data.radar_results then + lastResultShown = #data.radar_results - 1 + end + Write("Displaying results " .. (radar_listOffset + 1) .. " to " .. (lastResultShown + 1) .. " of " .. #data.radar_results) + for i = radar_listOffset, lastResultShown do + SetCursorPos(4, 3 + i - radar_listOffset) + if data.radar_results ~= nil then + Write(FormatInteger(data.radar_results[i].x, 7) .. ", " .. FormatInteger(data.radar_results[i].y, 4) .. ", " .. FormatInteger(data.radar_results[i].z, 7)) + Write(": " .. data.radar_results[i].frequency) + else + Write("~nil~") + end + end + end + + SetColorDefault() + local energy = { radar.getEnergyLevel() } + SetCursorPos(1, 12) + Write("Energy: ") + if energy ~= nil then + if energy[1] > (data.radar_radius * data.radar_radius) then + SetColorSuccess() + else + SetColorWarning() + end + Write(FormatInteger(energy[1], 10) .. " EU") + else + SetColorDisabled() + Write("???") + end + SetColorDefault() + SetCursorPos(1, 13) + Write("Radius: " .. data.radar_radius) + + SetCursorPos(30, 13) + Write("Monitor# " .. data.radar_monitorIndex .. "/" .. #monitors) + + SetCursorPos(1, 14) + Write("Autoscan: ") + if data.radar_autoscan then SetColorSuccess() else SetColorDefault() end + Write(boolToYesNo(data.radar_autoscan)) + + SetColorDefault() + SetCursorPos(30, 14) + Write("Delay " .. data.radar_autoscanDelay .. "s") + end + + SetColorTitle() + SetCursorPos(1, 15) + ShowMenu("S - Scan once, A - Autoscan, P - Stop autoscan") + SetCursorPos(1, 16) + ShowMenu("T/G - Scan radius, U/J - Scroll list") + SetCursorPos(1, 17) + ShowMenu("+/- - Scale, N - Next monitor, C - Configuration") +end + +function radar_page_config() + ShowTitle(label .. " - Radar configuration") + + SetCursorPos(1, 2) + if radar == nil then + SetColorDisabled() + Write("No radar detected") + else + SetColorDefault() + SetCursorPos(1, 3) + Write("Radar scan radius (" .. data.radar_radius .. " blocks): ") + radar_setRadius(readInputNumber(data.radar_radius)) + + SetCursorPos(1, 5) + Write("Autoscan delay in seconds (" .. data.radar_autoscanDelay .. "): ") + radar_setAutoscanDelay(readInputNumber(data.radar_autoscanDelay)) + + SetCursorPos(1, 7) + Write("Output monitor (" .. data.radar_monitorIndex .. "/" .. #monitors .. "): ") + radar_setMonitorIndex(readInputNumber(data.radar_monitorIndex)) + + data_save() + end +end + +function radar_setRadius(newRadius) + if newRadius < 1 then + data.radar_radius = 1 + elseif newRadius >= 10000 then + data.radar_radius = 10000 + else + data.radar_radius = newRadius + end +end + +function radar_setAutoscanDelay(newAutoscanDelay) + if newAutoscanDelay < 1 then + data.radar_autoscanDelay = 1 + elseif newAutoscanDelay >= 3600 then -- 1 hour + data.radar_autoscanDelay = 3600 + else + data.radar_autoscanDelay = newAutoscanDelay + end +end + +function radar_setMonitorIndex(newIndex) + if #monitors == 0 or newIndex < 0 or newIndex > #monitors then + data.radar_monitorIndex = 0 + else + data.radar_monitorIndex = newIndex + end +end + +function radar_getMonitor() + if data.radar_monitorIndex > 0 and data.radar_monitorIndex <= #monitors then + return monitors[data.radar_monitorIndex] + else + return nil + end +end + +function radar_scan() + local monitor = radar_getMonitor() + if radar == nil then + draw_warning(monitor, "No radar") + return false + end + if radar.getEnergyLevel() < (data.radar_radius * data.radar_radius) then + draw_warning(monitor, "LOW POWER") + return false + end + if radar_timerId ~= -1 and radar.getResultsCount() == -1 then + draw_warning(monitor, "Already scanning...") + return false + end + radar_timerId = os.startTimer(radar_timerLength) + + radar.scanRadius(data.radar_radius); + draw_warning(monitor, "Scanning...") + return false +end + +function radar_scanDone() + local numResults = radar.getResultsCount(); + data.radar_results = {} + if (numResults ~= 0) then + for i = 0, numResults do + local frequency, x, y, z = radar.getResult(i) + if frequency == "default" then + frequency = "?" + end + data.radar_results[i] = { x = x, y = y, z = z, frequency = frequency, kind = "core" } + end + data.radar_scale = data.radar_radius + end + data_save() + radar_drawMap() +end + +function draw_text(monitor, x, y, text, textColor, backgroundColor) + if monitor == nil then + term.setCursorPos(x, y) + if textColor ~= nil then term.setTextColor(textColor) end + if backgroundColor ~= nil then term.setBackgroundColor(backgroundColor) end + term.write(text) + local xt, yt = term.getCursorPos() + term.setCursorPos(1, yt + 1) + else + monitor.setCursorPos(x, y) + if textColor ~= nil then monitor.setTextColor(textColor) end + if backgroundColor ~= nil then monitor.setBackgroundColor(backgroundColor) end + monitor.write(text) + local xt, yt = monitor.getCursorPos() + monitor.setCursorPos(1, yt + 1) + end +end + +function draw_warning(monitor, text) + local screenWidth, screenHeight + if monitor == nil then + screenWidth, screenHeight = term.getSize() + else + screenWidth, screenHeight = monitor.getSize() + end + local centerX = math.floor(screenWidth / 2); + local centerY = math.floor(screenHeight / 2); + local halfWidth = math.ceil(string.len(text) / 2); + local blank = string.sub(" ", - (string.len(text) + 2)) + + draw_text(monitor, centerX - halfWidth - 1, centerY - 1, blank, colors.white, colors.red); + draw_text(monitor, centerX - halfWidth - 1, centerY , " " .. text .. " ", colors.white, colors.red); + draw_text(monitor, centerX - halfWidth - 1, centerY + 1, blank, colors.white, colors.red); +end + +function draw_centeredText(monitor, y, text) + local screenWidth, screenHeight + if monitor == nil then + screenWidth, screenHeight = term.getSize() + else + screenWidth, screenHeight = monitor.getSize() + end + local x = math.floor(screenWidth / 2 - string.len(text) / 2 + 0.5); + + draw_text(monitor, x, y, text, nil, nil); +end + +function radar_drawContact(monitor, contact) + local screenWidth, screenHeight + if monitor == nil then + screenWidth, screenHeight = term.getSize() + else + screenWidth, screenHeight = monitor.getSize() + end + + local screenX = (radar_x + data.radar_offsetX - contact.x) / data.radar_scale + local screenY = (radar_z + data.radar_offsetY - contact.z) / data.radar_scale + local visible = true + + if screenX <= -1 or screenX >= 1 or screenY <= -1 or screenY >= 1 then + screenX = math.min(1, math.max(-1, screenX)) + screenY = math.min(1, math.max(-1, screenY)) + visible = false + end + + screenX = math.floor(screenX * (screenWidth - 3) / 2 + ((screenWidth - 1) / 2) + 1.5) + screenY = math.floor(screenY * (screenHeight - 3) / 2 + ((screenHeight - 1) / 2) + 1.5) + + if contact.kind == "self" then + draw_text(monitor, screenX, screenY, Style.TextRadarself, Style.CRadarself, Style.BGRadarself) + else + draw_text(monitor, screenX, screenY, Style.TextRadarother, Style.CRadarother, Style.BGRadarother) + end + if visible then + local text = contact.frequency + screenX = math.min(screenWidth - 1 - string.len(text), math.max(2, math.floor(screenX - string.len(text) / 2 + 0.5))) + if screenY == (screenHeight - 1) then + screenY = screenY - 1 + else + screenY = screenY + 1 + end + draw_text(monitor, screenX, screenY, text, Style.CRadarother, Style.BGRadarother) + end +end + +function radar_drawMap() + local screenWidth, screenHeight, x, y + local monitor = radar_getMonitor() + -- center area + SetColorRadarmap() + if monitor == nil then + term.clear() + screenWidth, screenHeight = term.getSize() + else + monitor.clear() + screenWidth, screenHeight = monitor.getSize() + end + -- borders + SetColorRadarborder() + for x = 1, screenWidth do + if monitor == nil then + term.setCursorPos(x, 1) + term.write(" ") + term.setCursorPos(x, screenHeight) + term.write(" ") + else + monitor.setCursorPos(x, 1) + monitor.write(" ") + monitor.setCursorPos(x, screenHeight) + monitor.write(" ") + end + end + for y = 2, screenHeight - 1 do + if monitor == nil then + term.setCursorPos(1, y) + term.write(" ") + term.setCursorPos(screenWidth, y) + term.write(" ") + else + monitor.setCursorPos(1, y) + monitor.write(" ") + monitor.setCursorPos(screenWidth, y) + monitor.write(" ") + end + end + -- title + local text = label .. " - Radar map" + if #data.radar_results == 0 then + text = text .. " (no contacts)" + else + text = text .. " (" .. #data.radar_results .. " contacts)" + end + draw_centeredText(monitor, 1, text) + -- status + local text = "Scan radius: " .. data.radar_radius + if radar ~= nil then + text = text .. " | Energy: " .. radar.getEnergyLevel() .. " EU" + end + text = text .. " | Scale: " .. data.radar_scale + draw_centeredText(monitor, screenHeight, text) + -- results + SetCursorPos(1, 12) + radar_drawContact(monitor, {x = radar_x, y = radar_y, z = radar_z, frequency = "", kind = "self"}) + for i = 0, #data.radar_results - 1 do + radar_drawContact(monitor, data.radar_results[i]) + end + + -- restore defaults + SetColorDefault() +end + +radar_waitingNextScan = false +function radar_timerEvent() + radar_timerId = -1 + if radar_waitingNextScan then + radar_waitingNextScan = false + radar_scan() -- will restart timer + else + local numResults = radar.getResultsCount(); + if numResults ~= -1 then + radar_scanDone() + if data.radar_autoscan then + radar_waitingNextScan = true + radar_timerId = os.startTimer(data.radar_autoscanDelay) + end + else -- still scanning + radar_timerId = os.startTimer(radar_timerLength) + end + end +end + +----------- Boot sequence +label = os.getComputerLabel() +if not label then + label = "" .. os.getComputerID() +end + +-- read configuration +data_read() + +-- initial scanning +monitors = {} +ShowTitle(label .. " - Connecting...") +WriteLn("") + +sides = peripheral.getNames() +reactor = nil +mininglasers = {} +reactorlasers = {} +cloakingcores = {} +warpcore = nil +radar = nil +for key,side in pairs(sides) do + sleep(0) + if peripheral.getType(side) == "monitor" then + WriteLn("Wrapping " .. side) + lmonitor = peripheral.wrap(side) + table.insert(monitors, lmonitor) + lmonitor.setTextScale(monitor_textScale) + elseif peripheral.getType(side) == "warpcore" then + WriteLn("Wrapping " .. side) + warpcore = peripheral.wrap(side) + elseif peripheral.getType(side) == "warpdriveReactor" then + WriteLn("Wrapping " .. side) + reactor = peripheral.wrap(side) + elseif peripheral.getType(side) == "warpdriveReactorLaser" then + WriteLn("Wrapping " .. side) + table.insert(reactorlasers, peripheral.wrap(side)) + elseif peripheral.getType(side) == "mininglaser" then + WriteLn("Wrapping " .. side) + table.insert(mininglasers, peripheral.wrap(side)) + elseif peripheral.getType(side) == "cloakingdevicecore" then + WriteLn("Wrapping " .. side) + table.insert(cloakingcores, peripheral.wrap(side)) + elseif peripheral.getType(side) == "radar" then + WriteLn("Wrapping " .. side) + radar = peripheral.wrap(side); + end +end +-- sleep(1) + +if not os.getComputerLabel() and (warpcore ~= nil or reactor ~= nil) then + data_setName() +end + +-- peripherals status +function connections_page() + ShowTitle(label .. " - Connections") + + WriteLn("") + if #monitors == 0 then + SetColorDisabled() + WriteLn("No Monitor detected") + elseif #monitors == 1 then + SetColorSuccess() + WriteLn("1 monitor detected") + else + SetColorSuccess() + WriteLn(#monitors .. " Monitors detected") + end + + if warpcore == nil then + SetColorDisabled() + WriteLn("No warpcore controller detected") + else + SetColorSuccess() + WriteLn("Warpcore controller detected") + end + + if reactor == nil then + SetColorDisabled() + WriteLn("No reactor detected") + else + SetColorSuccess() + WriteLn("Warpcore reactor detected") + end + + if #reactorlasers == 0 then + SetColorDisabled() + WriteLn("No reactor stabilisation laser detected") + elseif #reactorlasers == 1 then + SetColorSuccess() + WriteLn("1 reactor stabilisation laser detected") + else + SetColorSuccess() + WriteLn(#reactorlasers .. " reactor stabilisation lasers detected") + end + + if #mininglasers == 0 then + SetColorDisabled() + WriteLn("No mining laser detected") + elseif #mininglasers == 1 then + SetColorSuccess() + WriteLn("1 mining laser detected") + else + SetColorSuccess() + WriteLn(#mininglasers .. " mining lasers detected") + end + + if #cloakingcores == 0 then + SetColorDisabled() + WriteLn("No cloaking core detected") + elseif #cloakingcores == 1 then + SetColorSuccess() + WriteLn("1 cloaking core detected") + else + SetColorSuccess() + WriteLn(#cloakingcores .. " cloaking cores detected") + end + + if radar == nil then + SetColorDisabled() + WriteLn("No radar detected") + else + SetColorSuccess() + WriteLn("Warpcore radar detected") + end +end + +-- peripheral boot up +Clear() +connections_page() +SetColorDefault() +WriteLn("") +sleep(0) +radar_boot() +core_boot() +reactor_boot() +sleep(0) + +-- main loop +abort = false +refresh = true +page = connections_page +keyHandler = nil +repeat + ClearWarning() + if refresh then + Clear() + page() + menu_common() + refresh = false + end + params = { os.pullEventRaw() } + eventName = params[1] + side = params[2] + if side == nil then side = "none" end + if eventName == "key" then + keycode = params[2] + if keycode == 45 then -- x for eXit + os.pullEventRaw() + abort = true + elseif keycode == 11 or keycode == 82 then -- 0 + page = connections_page + keyHandler = nil + refresh = true + elseif keycode == 2 or keycode == 79 then -- 1 + page = reactor_page + keyHandler = reactor_key + refresh = true + elseif keycode == 3 or keycode == 80 then -- 2 + page = cloaking_page + keyHandler = cloaking_key + refresh = true + elseif keycode == 4 or keycode == 81 then -- 3 + page = mining_page + keyHandler = mining_key + refresh = true + elseif keycode == 5 or keycode == 75 then -- 4 + page = core_page + keyHandler = core_key + refresh = true + elseif keycode == 6 or keycode == 76 then -- 5 + page = radar_page + keyHandler = radar_key + refresh = true + elseif keyHandler ~= nil and keyHandler(keycode) then + refresh = true + os.sleep(0) + else + ShowWarning("Key " .. keycode .. " is invalid") + os.sleep(0.2) + end + -- func(unpack(params)) + -- abort, refresh = false, false + elseif eventName == "char" then + -- drop it + elseif eventName == "reactorPulse" then + reactor_pulse(params[2]) + refresh = (page == reactor_page) + elseif eventName == "terminate" then + abort = true + elseif not common_event(eventName, params[2]) then + ShowWarning("Event '" .. eventName .. "', " .. side .. " is unsupported") + refresh = true + os.sleep(0.2) + end +until abort + +-- deactivate summon all on exit +if data.core_summon then + data.core_summon = false + data_save() +end + +-- clear screens on exit +SetMonitorColorFrontBack(colors.white, colors.black) +term.clear() +if monitors ~= nil then + for key,monitor in pairs(monitors) do + monitor.clear() + end +end +SetCursorPos(1, 1) +Write("")