From 9ee9c530c2e34731c9facddfefa8f956cfd20fb7 Mon Sep 17 00:00:00 2001 From: LDDestroier Date: Fri, 29 Mar 2019 13:48:43 -0400 Subject: [PATCH] Delete ccbn.lua --- CCBN/ccbn.lua | 1804 ------------------------------------------------- 1 file changed, 1804 deletions(-) delete mode 100644 CCBN/ccbn.lua diff --git a/CCBN/ccbn.lua b/CCBN/ccbn.lua deleted file mode 100644 index d82fe93..0000000 --- a/CCBN/ccbn.lua +++ /dev/null @@ -1,1804 +0,0 @@ -local scr_x, scr_y = term.getSize() -local keysDown, miceDown = {}, {} - --- recommended at 0.1 for netplay, which you'll be doing all the time so yeah -local gameDelayInit = 0.1 - -local useAbsoluteMainDir = false - -local config = { - mainDir = useAbsoluteMainDir and "ccbn-data" or fs.combine(fs.getDir(shell.getRunningProgram()), "ccbn-data") -} -config.chipDir = fs.combine(config.mainDir, "chipdata") -config.objectDir = fs.combine(config.mainDir, "objectdata") - -local players = {} -local objects = {} -local projectiles = {} -local game = { - custom = 0, - customMax = 200, - customSpeed = 1, - inChipSelect = true, - paused = false, - turnNumber = 0 -} - -local you = 1 -local yourID = os.getComputerID() - -local revKeys = {} -for k,v in pairs(keys) do - revKeys[v] = k -end - -local gameID = math.random(0, 2^30) -local waitingForGame = false -local isHost = true -local channel = 1024 - -local chips, objectTypes = {}, {} - -local interpretArgs = function(tInput, tArgs) - local output = {} - local errors = {} - local usedEntries = {} - for aName, aType in pairs(tArgs) do - output[aName] = false - for i = 1, #tInput do - if not usedEntries[i] then - if tInput[i] == aName and not output[aName] then - if aType then - usedEntries[i] = true - if type(tInput[i+1]) == aType or type(tonumber(tInput[i+1])) == aType then - usedEntries[i+1] = true - if aType == "number" then - output[aName] = tonumber(tInput[i+1]) - else - output[aName] = tInput[i+1] - end - else - output[aName] = nil - errors[1] = errors[1] and (errors[1] + 1) or 1 - errors[aName] = "expected " .. aType .. ", got " .. type(tInput[i+1]) - end - else - usedEntries[i] = true - output[aName] = true - end - end - end - end - end - for i = 1, #tInput do - if not usedEntries[i] then - output[#output+1] = tInput[i] - end - end - return output, errors -end - -local argList = interpretArgs({...}, { - ["skynet"] = false, -- use Skynet HTTP multiplayer - ["debug"] = false, -- show various variable values -}) - -local FRAME = 0 -local useSkynet = argList.skynet -local showDebug = argList.debug - -local stage = { - panels = {}, - damage = {}, - panelWidth = 6, - panelHeight = 2, - scrollX = 0, - scrollY = 6 -} - -stage.scrollX = -1 + (scr_x - (6 * stage.panelWidth)) / 2 - -local stageChanged = true - -local round = function(num) - return math.floor(0.5 + num) -end - --- ripped from NFTE -local deepCopy -deepCopy = function(tbl) - local output = {} - for k,v in pairs(tbl) do - if type(v) == "table" then - output[k] = deepCopy(v) - else - output[k] = v - end - end - return output -end -local getSize = function(image) - local x, y = 0, #image[1] - for y = 1, #image[1] do - x = math.max(x, #image[1][y]) - end - return x, y -end -local colorSwap = function(image, text, back) - local output = {{},{},{}} - for y = 1, #image[1] do - output[1][y] = image[1][y] - output[2][y] = image[2][y]:gsub(".", text) - output[3][y] = image[3][y]:gsub(".", back or text) - end - return output -end -local makeRectangle = function(width, height, char, text, back) - local output = {{},{},{}} - for y = 1, height do - output[1][y] = (char or " "):rep(width) - output[2][y] = (text or " "):rep(width) - output[3][y] = (back or " "):rep(width) - end - return output -end -local stretchImage = function(_image, sx, sy, noRepeat) - local output = {{},{},{}} - local image = deepCopy(_image) - sx, sy = math.abs(sx), math.abs(sy) - local imageX, imageY = getSize(image) - local tx, ty - if sx == 0 or sy == 0 then - for y = 1, math.max(sy, 1) do - output[1][y] = "" - output[2][y] = "" - output[3][y] = "" - end - return output - else - for y = 1, sy do - for x = 1, sx do - tx = round((x / sx) * imageX) - ty = math.ceil((y / sy) * imageY) - if not noRepeat then - output[1][y] = (output[1][y] or "")..image[1][ty]:sub(tx,tx) - else - output[1][y] = (output[1][y] or "").." " - end - output[2][y] = (output[2][y] or "")..image[2][ty]:sub(tx,tx) - output[3][y] = (output[3][y] or "")..image[3][ty]:sub(tx,tx) - end - end - if noRepeat then - for y = 1, imageY do - for x = 1, imageX do - if image[1][y]:sub(x,x) ~= " " then - tx = round(((x / imageX) * sx) - ((0.5 / imageX) * sx)) - ty = round(((y / imageY) * sy) - ((0.5 / imageY) * sx)) - output[1][ty] = stringWrite(output[1][ty], tx, image[1][y]:sub(x,x)) - end - end - end - end - return output - end -end -local merge = function(...) - local images = {...} - local output = {{},{},{}} - local imageX, imageY = 0, 0 - local imSX, imSY - for i = 1, #images do - imageY = math.max( - imageY, - #images[i][1][1] + (images[i][3] == true and 0 or (images[i][3] - 1)) - ) - for y = 1, #images[i][1][1] do - imageX = math.max( - imageX, - #images[i][1][1][y] + (images[i][2] == true and 0 or (images[i][2] - 1)) - ) - end - end - -- if either coordinate is true, center it - for i = 1, #images do - imSX, imSY = getSize(images[i][1]) - if images[i][2] == true then - images[i][2] = round(1 + (imageX / 2) - (imSX / 2)) - end - if images[i][3] == true then - images[i][3] = round(1 + (imageY / 2) - (imSY / 2)) - end - end - - -- will later add code to adjust X/Y positions if negative values are given - - local image, xadj, yadj - local tx, ty - for y = 1, imageY do - output[1][y] = {} - output[2][y] = {} - output[3][y] = {} - for x = 1, imageX do - for i = #images, 1, -1 do - image, xadj, yadj = images[i][1], images[i][2], images[i][3] - tx, ty = x-(xadj-1), y-(yadj-1) - output[1][y][x] = output[1][y][x] or " " - output[2][y][x] = output[2][y][x] or " " - output[3][y][x] = output[3][y][x] or " " - if image[1][ty] then - if (image[1][ty]:sub(tx,tx) ~= "") and (tx >= 1) then - output[1][y][x] = (image[1][ty]:sub(tx,tx) == " " and output[1][y][x] or image[1][ty]:sub(tx,tx)) - output[2][y][x] = (image[2][ty]:sub(tx,tx) == " " and output[2][y][x] or image[2][ty]:sub(tx,tx)) - output[3][y][x] = (image[3][ty]:sub(tx,tx) == " " and output[3][y][x] or image[3][ty]:sub(tx,tx)) - end - end - end - end - output[1][y] = table.concat(output[1][y]) - output[2][y] = table.concat(output[2][y]) - output[3][y] = table.concat(output[3][y]) - end - return output -end -local pixelateImage = function(image, amntX, amntY) - local imageX, imageY = getSize(image) - return stretchImage(stretchImage(image,imageX/math.max(amntX,1), imageY/math.max(amntY,1)), imageX, imageY) -end -local drawImage = function(image, x, y, terminal) - terminal = terminal or term.current() - local cx, cy = terminal.getCursorPos() - for iy = 1, #image[1] do - terminal.setCursorPos(x, y + (iy - 1)) - terminal.blit(image[1][iy], image[2][iy], image[3][iy]) - end - terminal.setCursorPos(cx,cy) -end - -local skynet -local skynetPath = "skynet" -local skynetURL = "https://raw.githubusercontent.com/osmarks/skynet/master/client.lua" - -local modem -local getModem = function() - if useSkynet then - if skynet then - local isOpen = false - for i = 1, #skynet.open_channels do - if skynet.open_channels == channel then - isOpen = true - end - end - if not isOpen then - skynet.open(channel) - end - return skynet - else - if fs.exists(skynetPath) then - skynet = dofile(skynetPath) - skynet.open(channel) - else - local prog = http.get(skynetURL) - if prog then - local file = fs.open(skynetPath, "w") - file.write(prog.readAll()) - file.close() - skynet = dofile(skynetPath) - skynet.open(channel) - else - error("Skynet can't be downloaded! Use modems instead.") - end - end - end - else - local modems = {peripheral.find("modem")} - if #modems == 0 then - if ccemux then - ccemux.attach("top", "wireless_modem") - modem = peripheral.wrap("top") - else - error("A modem is needed.") - end - else - modem = modems[1] - end - modem.open(channel) - return modem - end -end - -local transmit = function(msg) - if useSkynet then - skynet.send(channel, msg) - else - modem.transmit(channel, channel, msg) - end -end - -local receive = function() - if useSkynet then - return ({skynet.receive(channel)})[2] - else - return ({os.pullEvent("modem_message")})[5] - end -end - -local images = { - logo = { - { - " ‡’——””€” •€ƒ‚••••ƒ€ƒ•—ƒ•—””‡’•—””ƒ‚•—ƒƒ€ƒ ", - " € Ÿ••••€‹ž”•€ƒ•••• € •—•—””€ Ÿ•—””€ƒ€•—ƒ € ", - " ‹‡‚Ž Š… ‚Ž  ŠŒŠ…Š…‹‡Š…Š…€Š…  ", - " —œŒ‹ŸœŒ‹ˆŒƒŒ„Œ“œŒ—”€€ƒŒŒ„€€‡ƒƒƒƒƒƒƒ ", - " •ŠŸ•Š€€€€€€€••€••€€€€—€€€€€€€€€€‹€", - " ••€€••€€€€€€€€••€••€€€€€€€€€€€€€˜†€€€”‚", - " Ÿ•ŠŸ••€€€€€€€€••€•Š€€€€€€˜†€€€€€•€", - "—ƒ€€—”ƒŒŒ„Œ“œŒ—”€€€€€—”‡œƒƒŒ“ƒ€‡„€€€˜†€€€€€€€…Ÿ", - "•€’••€€€••€€Ÿ€ŸŸ€€€••€……€€”€€€€€€€€€€‡€ ", - "•€€‹•€€€€€••€€‚‚ƒ‚€€€••€€••€‚‚€€ƒ€€€Ÿ‡‡ ", - "Š€€Š…ŒŒ„€Š…€€€Š…€Š…€€‹€Š…€Š…‡ƒ‹‡ƒ ", - }, - { - " f3ff3f333 f333ff3f3333f33f3f3f3ff3f3f3ff333333 ", - " b ffbfbbbbfbbbbfbfb b fbbfbfbb ffbfbbbbfbb b ", - " bbbbbbbb bbb bbbb b bbbbbbbbbbbbbbbfbbb b ", - " a11aa11a11a111a11a1aaa111aaaaaaaaaa3fa ", - " aaa1aaa1aa1aaaa1aa1aa1aaaaeeeeeeee33aaa", - " a1a1a1a1aa1aaaa1aa1aa1aaaeeeeeee00eeeef", - " faaa1a1a1aa1aaaa1aaaa11aa1eeeee00eeeeeea", - "faaaa1a1111a11a1aaaaaa1a1a1a1a1aaa1eee00eeeeeeeea", - "f1a1a11aaaaa1aaa1a11a1a1aa11aa11a1aa33eeeeeeeeea ", - "f1a1a11aaaaa1aa1aa1aa1a1aa11aa111aaa33aeeeeeeea ", - "a1aa111111a11aaa11a11aa11111a111a11aaaaaaaaaa ", - }, - { - " 3f33f3f3f 3f3f33f3ff3f3ff3f3f3f33f3f3f33ffff3f ", - " b bbfbfbffbfbffbfbf b bffbfbfb bbfbfbfbbff b ", - " ffffffff fff ffff f fffffffffffffffffff f ", - " 1aa11aa1aa1aaa1aa1aaa1aaaaaeeeeeee3aaf ", - " 111a1111aa1aaa1aa1aaa111aeeeeeeeee333af", - " 1aa11aa1aa1aaa1aa1aaa1aaaeeeeeeeeeeeeaa", - " a111a1aa1aa1aaa1aa111a111aeeeeeeeeeeeeaa", - "a1aa1a1aaaa1aa1aaaaaa1a1a1a1a1a1a1aeeeeeeeeeeeeaf", - "a11a1a111aa1aaa1a11a1aa1a1a111a11aa333eeeeeeeeaa ", - "a1aa1a1aaaa1aaaa11a11aa1a1a1a1a1a1aaaaeeeeaaaaf ", - " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaffffffffff ", - }, - }, - win = { - { - "€• €•‡€€€‚€• €• €• €•€€€€€•€Š €•—€‚", - "‚‡€…€— ‚€•€• €• €• •€ €• €• €€‚ €••€€", - " ‹€Ÿ €• €•€• €• €• €€• €• €• €•‹€‹€•Š€Ÿ", - " €• €Š Ÿ€•€• €• •€•€•€•€ €• €• ‚€• ‹", - " €• ‹€€€Ÿ‹€€€Ÿ €€•€€€• €€€€€•€• €• €•", - }, - { - "55 55f555f555 55 55 555555555f 55f5f", - "ff5f5555 55555 55 55 f5 55 55 55f5 55f55", - " 5555 55 5555 55 55 555 55 55 5555f55555", - " 55 5f f5555 55 f5f5f5f5 55 55 5f55 55", - " 55 555555555555 555f555 55555555 55 55", - }, - { - "5f 5f55555f5f 5f 5f 5f55555f55 5f555", - "55f55f5f f5f5f 5f 5f 55 5f 5f 555f 5f555", - " f5ff 5f 5f5f 5f 5f 55f 5f 5f 5ff555ff5f", - " 5f 55 55f5f 5f 55555555 5f 5f f55f ff", - " 5f f555fff555ff 55ff55f 55555f5f 5f 5f", - }, - }, - lose = { - { - "€€€‚‹ €€€€€•€• €€€€€•€€€€€•€€€€€•€€€‚‹ ", - "€• ‹€•€• €• €• €• €• €• ‹€•", - "€• €•€Ÿ… €• €Ÿ… €• €Ÿ… €• €•", - "€• ‡€•€• €• €• €• €• €• ‡€•", - "€€€Ÿ‡ €€€€€•€€€€€•€€€€€• €• €€€€€•€€€Ÿ‡ ", - }, - { - "111ff 11111111 111111111111111111111ff ", - "11 11111 11 11 11 11 11 111", - "11 1111111 11 11111 11 11111 11 11", - "11 f1111 11 11 11 11 11 f11", - "11111 111111111111111111 11 11111111111 ", - }, - { - "11111 11111f1f 11111f11111f11111f11111 ", - "1f f1f1f 1f 1f 1f 1f 1f f1f", - "1f 1f1ffff 1f 1ffff 1f 1ffff 1f 1f", - "1f 11f1f 1f 1f 1f 1f 1f 11f", - "111ff 11111f11111f11111f 1f 11111f111ff ", - }, - }, - panel = { - normal = {{"—ƒƒƒƒ”","•€€‚•","€€€€€€"},{"eeeee7","e78877","eeeeee"},{"77777e","78888e","eeeeee"}}, - cracked = {{"—››››”","•™™™™•","€€€€€€"},{"eeeee7","e88888","eeeeee"},{"77777e","87777e","eeeeee"}}, - broken = {{"—ƒƒƒƒ”","•—•","€€€€€€"},{"eeeeef","eff8f7","eeeeee"},{" e","788f8e","eeeeee"}} - }, - player = { - ["6"] = {{"‡Ÿ‹","€ ƒ","€ž‹","€ €","‹‚‡"},{"f5ff","4 4","66ff","2 2","affa"},{"5f55","4 f","6f66","2 2"," aaf"}}, - ["7"] = {{"€€"," ‡Ÿ","…ˆ","ƒ”—ƒ"," •• "},{"5555"," f4","ffff","2f22"," fa "},{"5ff5"," 4f","6666"," 2ff"," af "}}, - }, - rockcube = {{"ˆ‡‹„","€€‘","ˆ‹‡„"},{"7887","8777","7777"},{"8778","7778","8888"}}, - cannon = {{"‡‹","‹‡"},{"ff","77"},{"77"," ",}}, - buster = {{"‘"},{"f4"},{"4f"}} -} - -local cwrite = function(text, y) - local cx, cy = term.getCursorPos() - term.setCursorPos(0.5 + scr_x / 2 - #text / 2, y or (scr_y / 2)) - term.write(text) -end - -local act = {stage = {}, player = {}, projectile = {}, object = {}} -act.stage.newPanel = function(x, y, panelType, owner) - stage.panels[y] = stage.panels[y] or {} - stage.panels[y][x] = { - panelType = panelType, - reserved = false, - crackedLevel = 0, -- 0 is okay, 1 is cracked, 2 is broken - owner = owner or (x > 3 and 2 or 1), - originalOwner = owner or (x > 3 and 2 or 1), - cooldown = { - owner = 0, - broken = 0, - } - } -end -act.player.checkPlayerAtPos = function(x, y, ignoreThisOne) - x, y = round(x), round(y) - for id, player in pairs(players) do - if id ~= ignoreThisOne then - if player.x == x and player.y == y then - return id - end - end - end -end -act.stage.checkExist = function(x, y) - if stage.panels[y] then - if stage.panels[y][x] then - return true - end - end - return false -end -act.stage.crackPanel = function(x, y, amount) - local maxCrack - if act.stage.checkExist(x, y) then - if act.player.checkPlayerAtPos(x, y) then - maxCrack = 1 - else - maxCrack = 2 - end - if math.max(0, math.min(maxCrack, stage.panels[y][x].crackedLevel + amount)) ~= stage.panels[y][x].crackedLevel then - stage.panels[y][x].crackedLevel = math.max(0, math.min(maxCrack, stage.panels[y][x].crackedLevel + amount)) - if stage.panels[y][x].crackedLevel == 2 then - stage.panels[y][x].cooldown.broken = 300 - else - stage.panels[y][x].cooldown.broken = 0 - end - stageChanged = true - end - end -end -act.stage.setDamage = function(x, y, damage, owner, time, noFlinch, safePlayers, safeObjects) - x, y = round(x), round(y) - stage.damage[y] = stage.damage[y] or {} - stage.damage[y][x] = stage.damage[y][x] or {} - stage.damage[y][x][owner] = { - owner = owner, - time = time, - damage = damage, - flinching = not noFlinch, - safePlayers = safePlayers or {}, - safeObjects = safeObjects or {} - } - stageChanged = true -end -act.stage.getDamage = function(x, y, pID, oID, pIDsafeCheck, oIDsafeCheck) - local totalDamage = 0 - local flinching = false - x, y = round(x), round(y) - if stage.damage[y] then - if stage.damage[y][x] then - for k, v in pairs(stage.damage[y][x]) do - if k ~= (players[pID] or {}).owner and k ~= (objects[oID] or {}).owner and v.damage then - if not (v.safePlayers[pIDsafeCheck] or v.safeObjects[oIDsafeCheck]) then - totalDamage = totalDamage + v.damage - flinching = flinching or v.flinching - end - end - end - end - end - return totalDamage, flinching -end - -local premadeFolders = { - [1] = { - {"cannon", "a"}, - {"cannon", "a"}, - {"hicannon", "b"}, - {"hicannon", "b"}, - {"shotgun", "b"}, - {"shotgun", "b"}, - {"vgun", "l"}, - {"vgun", "l"}, - {"crossgun", "l"}, - {"minibomb", "b"}, - {"minibomb", "b"}, - {"lilbomb", "b"}, - {"recov120", "a"}, - {"recov120", "a"}, - {"recov80", "l"}, - {"recov50", "l"}, - {"recov50", "l"}, - {"sword", "s"}, - {"sword", "s"}, - {"sword", "s"}, - {"panelreturn", "s"}, - {"widesword", "s"}, - {"widesword", "s"}, - {"longsword", "s"}, - {"busterup", "s"}, - {"crackout", "b"}, - {"shockwave", "b"}, - {"areagrab", "s"}, - {"areagrab", "s"}, - {"panelgrab", "s"}, - }, - [2] = { - {"cannon", "a"}, - {"cannon", "a"}, - {"hicannon", "a"}, - {"hicannon", "a"}, - {"mcannon", "a"}, - {"mcannon", "a"}, - {"airshot1", "a"}, - {"airshot1", "a"}, - {"airshot2", "a"}, - {"vulcan1", "c"}, - {"vulcan1", "c"}, - {"shockwave", "c"}, - {"minibomb", "c"}, - {"minibomb", "c"}, - {"crossbomb", "c"}, - {"panelreturn", "s"}, - {"sword", "s"}, - {"sword", "s"}, - {"longsword", "s"}, - {"busterup", "s"}, - {"widesword", "s"}, - {"rockcube", "a"}, - {"areagrab", "s"}, - {"areagrab", "s"}, - {"panelgrab", "s"}, - {"panelshot", "s"}, - {"panelshot", "s"}, - {"recov50", "l"}, - {"recov50", "l"}, - {"recov50", "l"}, - }, - [3] = { - {"cannon", "a"}, - {"hicannon", "a"}, - {"mcannon", "b"}, - {"airshot2", "a"}, - {"airshot2", "a"}, - {"rockcube", "s"}, - {"shockwave", "a"}, - {"lilbomb", "l"}, - {"lilbomb", "l"}, - {"areagrab", "s"}, - {"areagrab", "s"}, - {"fightersword", "f"}, - {"panelreturn", "s"}, - {"panelreturn", "s"}, - {"panelshot", "f"}, - {"panelshot", "f"}, - {"doubleshot", "f"}, - {"tripleshot", "f"}, - {"invis", "l"}, - {"recov30", "l"}, - {"recov30", "l"}, - {"vulcan2", "c"}, - {"vulcan1", "c"}, - {"boomer1", "c"}, - {"geddon1", "f"}, - {"shotgun", "d"}, - {"shotgun", "d"}, - {"vgun", "d"}, - {"vgun", "d"}, - {"spreader", "d"}, - } -} - -act.player.newPlayer = function(x, y, owner, direction, image) - local pID = #players + 1 - players[pID] = { - x = x, -- X and Y positions are relative to grid, not screen - y = y, -- ditto my man - owner = owner, -- Either 1 or 2, indicates the red/blue alignment - type = "player", -- Used for quickly identifying a player/object/projectile at a glance - direction = direction or 1, -- Either -1 or 1, indicates facing left or right - health = 600, -- Once it hits 0, your player is deleted - maxHealth = 600, -- You cannot heal past this value - image = image, -- Because of CC limitations, I'm just going to have one player sprite - canMove = true, -- If false, pushing the move buttons won't do diddly fuck - canShoot = true, -- If false, pushing the shoot buttons won't do fuckly didd - isDead = false, -- If true, the current game is over and the opponent wins - busterPower = 2, -- Strength of MegaBuster - cooldown = { -- All cooldown values are decremented every tick - move = 0, -- If above 0, you cannot move - shoot = 0, -- If above 0, you cannot shoot - iframe = 0 -- If above 0, you will flash and be indestructible - }, - control = { - moveUp = false, - moveDown = false, - moveLeft = false, - moveRight = false, - buster = false, - chip = false, - custom = false - }, - chipQueue = {}, -- Attacks are used in a queue, which is filled each turn - folder = premadeFolders[math.random(1, 3)] - } - return pID -end - -act.object.newObject = function(x, y, owner, direction, objectType) - local oID = #objects + 1 - objects[oID] = { - x = x, - y = y, - image = objectTypes[objectType].image, - friendlyFire = objectTypes[objectType].friendlyFire or true, - health = objectTypes[objectType].health or 500, - maxHealth = objectTypes[objectType].maxHealth or 500, - smackDamage = objectTypes[objectType].smackDamage or 100, - doYeet = objectTypes[objectType].doYeet or false, - delayedTime = objectTypes[objectType].delayedTime or math.huge, - delayedFunc = objectTypes[objectType].delayedFunc or function() end, - xvel = 0, - yvel = 0, - owner = owner, - direction = direction, - type = "object", - objectType = objectType, - frame = 0, - cooldown = { - iframe = 0, - } - } - return oID -end - -act.object.checkObjectAtPos = function(x, y, ignoreThisOne) - x, y = round(x), round(y) - for id, obj in pairs(objects) do - if id ~= ignoreThisOne then - if obj.x == x and obj.y == y then - return id - end - end - end - return false -end - -local control = { - moveUp = keys.up, - moveDown = keys.down, - moveLeft = keys.left, - moveRight = keys.right, - buster = keys.z, - chip = keys.x, - custom = keys.c -} - -local getControls = function() - if players[you] then - for k,v in pairs(control) do - players[you].control[k] = keysDown[v] or false - end - end -end - -act.stage.checkIfSolid = function(x, y) - x, y = round(x), round(y) - if stage.panels[y] then - if stage.panels[y][x] then - if stage.panels[y][x].crackedLevel < 2 then - return true - end - end - end - return false -end - -act.stage.checkIfWalkable = function(x, y, pID, oID) - if x >= 1 and x <= 6 then - x, y = round(x), round(y) - if act.stage.checkIfSolid(x, y) then - if not act.object.checkObjectAtPos(x, y, oID) then - if not act.player.checkPlayerAtPos(x, y, pID) and (not pID or stage.panels[y][x].owner == players[pID].owner) then - return true - end - end - end - end - return false -end - -act.player.movePlayer = function(pID, xmove, ymove, doCooldown) - local player = players[pID] - if (xmove ~= 0 or ymove ~= 0) and act.stage.checkIfWalkable(player.x + xmove, player.y + ymove, pID) then - player.x = player.x + xmove - player.y = player.y + ymove - if doCooldown then - if gameDelayInit < 0.1 then - player.cooldown.move = 3 - else - player.cooldown.move = 2 - end - end - if stage.panels[player.y - ymove][player.x - xmove].crackedLevel == 1 then - act.stage.crackPanel(player.x - xmove, player.y - ymove, 1) - end - return true - else - return false - end -end - -act.object.moveObject = function(oID, xmove, ymove) - local object = objects[oID] - if (xmove ~= 0 or ymove ~= 0) and act.stage.checkIfWalkable(object.x + xmove, object.y + ymove, nil, oID) then - object.x = object.x + xmove - object.y = object.y + ymove - return true - else - return false - end -end - -local movePlayers = function() - local xmove, ymove, p - for i = 1, #players do - xmove, ymove = 0, 0 - p = players[i] - if p.canMove then - if p.cooldown.move == 0 then - if p.control.moveUp then - ymove = -1 - elseif p.control.moveDown then - ymove = 1 - elseif p.control.moveRight then - xmove = 1 - elseif p.control.moveLeft then - xmove = -1 - end - act.player.movePlayer(i, xmove, ymove, true) - end - if stage.panels[p.y] then - if stage.panels[p.y][p.x] then - if stage.panels[p.y][p.x].owner ~= p.owner then - repeat - if p.owner == 1 then - p.x = p.x - 1 - else - p.x = p.x + 1 - end - until stage.panels[p.y][p.x].owner == p.owner - end - end - end - end - end -end - -local reduceCooldowns = function() - for id, player in pairs(players) do - for k,v in pairs(player.cooldown) do - - players[id].cooldown[k] = math.max(0, v - 1) - - end - end - for id, object in pairs(objects) do - for k,v in pairs(object.cooldown) do - - objects[id].cooldown[k] = math.max(0, v - 1) - - end - end - for y, row in pairs(stage.damage) do - for x, panel in pairs(row) do - for owner, damageData in pairs(panel) do - - stage.damage[y][x][owner].time = math.max(0, damageData.time - 1) - if damageData.time == 0 then - stage.damage[y][x][owner] = nil - end - - end - end - end - for y, row in pairs(stage.panels) do - for x, panel in pairs(row) do - for k,v in pairs(panel.cooldown) do - - stage.panels[y][x].cooldown[k] = math.max(0, v - 1) - if k == "owner" then - if stage.panels[y][x].owner == stage.panels[y][x].originalOwner then - stage.panels[y][x].cooldown.owner = 0 - elseif v == 0 then - stageChanged = true - stage.panels[y][x].owner = stage.panels[y][x].originalOwner - end - elseif k == "broken" and v == 0 and panel.crackedLevel == 2 then - stageChanged = true - stage.panels[y][x].crackedLevel = 0 - end - - end - end - end -end - -act.projectile.checkProjectileCollisions = function(info) - - local struckPlayer = false - local struckObject = false - local cPlayer = act.player.checkPlayerAtPos(info.x, info.y) --, info.owner) - local cObject = act.object.checkObjectAtPos(info.x, info.y) --, info.owner) - - if cPlayer then - if players[cPlayer].cooldown.iframe == 0 and players[cPlayer].owner ~= info.owner then - struckPlayer = cPlayer - end - end - if cObject then - if objects[cObject].cooldown.iframe == 0 then - struckObject = cObject - end - end - return struckPlayer, struckObject -end - -local readFile = function(path) - if fs.exists(path) then - local file = fs.open(path, "r") - local contents = file.readAll() - file.close() - return contents - end -end - -act.projectile.newProjectile = function(x, y, player, chipType, noFlinch, altDamage) - local id = #projectiles + 1 - projectiles[id] = { - x = x, - y = y, - safeObjects = {}, - safePlayers = {}, - type = "projectile", - initX = x, - initY = y, - id = id, - owner = player.owner, - player = player, - direction = player.direction, - frame = 0, - noFlinch = noFlinch, -- overwrite a projectile's flinchingness - altDamage = altDamage, -- overwrite a projectile's damage - chipType = chipType - } - return id -end - --- loads all chips and objects from file -local loadChips = function(env) - local cList = fs.list(config.chipDir) - local oList = fs.list(config.objectDir) - local contents - local cOutput, oOutput = {}, {} - for i = 1, #cList do - if not fs.isDir(fs.combine(config.chipDir, cList[i])) then - cOutput[cList[i]] = loadfile( fs.combine(config.chipDir, cList[i]))( - stage, - players, - objects, - projectiles, - act, - images - ) - end - end - for i = 1, #oList do - if not fs.isDir(fs.combine(config.objectDir, oList[i])) then - oOutput[oList[i]] = loadfile( fs.combine(config.objectDir, oList[i]))( - stage, - players, - objects, - projectiles, - act, - images - ) - end - end - return cOutput, oOutput -end - -local stageImageStitch - -local makeStageImageStitch = function() - local buffer, im = {} - for y = #stage.panels, 1, -1 do - if stage.panels[y] then - for x = 1, #stage.panels[y] do - if stage.panels[y][x] then - if stage.panels[y][x].crackedLevel == 0 then - im = images.panel[stage.panels[y][x].panelType] - elseif stage.panels[y][x].crackedLevel == 1 then - im = images.panel.cracked - elseif stage.panels[y][x].crackedLevel == 2 then - im = images.panel.broken - end - if stage.panels[y][x].owner == 2 then - im = colorSwap(im, {e = "b"}) - end - if act.stage.getDamage(x, y) > 0 then - im = colorSwap(im, {["7"] = "4", ["8"] = "4"}) - end - buffer[#buffer + 1] = { - im, - (x - 1) * stage.panelWidth + 1, - (y - 1) * stage.panelHeight + 1 - } - end - end - end - end - return merge(table.unpack(buffer)) -end - -local render = function(extraImage) - local buffer, im = {} - local sx, sy - if stageChanged or true then - stageImageStitch = makeStageImageStitch() - stageChanged = false - end - local sortedList = {} - for k,v in pairs(projectiles) do - sortedList[#sortedList+1] = v - end - for k,v in pairs(players) do - sortedList[#sortedList+1] = v - end - for k,v in pairs(objects) do - sortedList[#sortedList+1] = v - end - table.sort(sortedList, function(a,b) return a.y >= b.y end) - if extraImage then - buffer[#buffer + 1] = { - colorSwap(extraImage[1], {["f"] = " "}), - extraImage[2], - extraImage[3] - } - end - for k,v in pairs(sortedList) do - if v.type == "player" then - if not v.isDead then - if v.cooldown.iframe == 0 or (FRAME % 2 == 0) then - sx = (v.x - 1) * stage.panelWidth + 2 - sy = (v.y - 1) * stage.panelHeight - 2 - buffer[#buffer + 1] = { - colorSwap(images.player[v.image], {["f"] = " "}), - sx + stage.scrollX, - sy + stage.scrollY - } - end - end - elseif v.type == "projectile" then - sx = math.floor((v.x - 1) * stage.panelWidth + 4) - sy = math.floor((v.y - 1) * stage.panelHeight) - if sx >= -1 and sx <= scr_x and v.imageData then - - for kk, imd in pairs(v.imageData) do - buffer[#buffer + 1] = { - colorSwap(imd[1], {["f"] = " "}), - math.floor((imd[2] - 1) * stage.panelWidth + 4 + stage.scrollX), - math.floor((imd[3] - 1) * stage.panelHeight + 1 + stage.scrollY) - } - end - - end - elseif v.type == "object" then - sx = (v.x - 1) * stage.panelWidth + 3 - sy = (v.y - 1) * stage.panelHeight - buffer[#buffer + 1] = { - colorSwap(v.image, {["f"] = " "}), - math.floor(sx + stage.scrollX), - math.floor(sy + stage.scrollY) - } - end - end - buffer[#buffer + 1] = { - stageImageStitch, - stage.scrollX + 1, - stage.scrollY + 1 - } - buffer[#buffer + 1] = {makeRectangle(scr_x, scr_y, "f", "f", "f"), 1, 1} - drawImage(colorSwap(merge(table.unpack(buffer)), {[" "] = "f"}), 1, 1) - - term.setTextColor(colors.white) - term.setBackgroundColor(colors.black) - if players[you] then - if chips[players[you].chipQueue[1]] then - term.setCursorPos(1, scr_y) - term.write(chips[players[you].chipQueue[1]].info.name) - end - end - - local HPs = {{},{}} - for id, player in pairs(players) do - HPs[player.owner] = HPs[player.owner] or {} - HPs[player.owner][#HPs[player.owner] + 1] = player.health - - if player.owner == 1 then - term.setCursorPos(1, #HPs[player.owner]) - term.write(player.health) - else - term.setCursorPos(scr_x - 3, #HPs[player.owner]) - term.write(player.health) - end - end - - if game.custom == game.customMax and FRAME % 16 <= 12 and not game.inChipSelect then - cwrite("PUSH '" .. revKeys[control.custom]:upper() .. "'!", 2) - end - term.setTextColor(colors.lightGray) - term.setCursorPos(6, 1) - term.write("CUSTOM") - term.setTextColor(colors.white) - term.write("[") - local barLength = scr_x - 18 - if game.custom == game.customMax then - term.setTextColor(colors.gray) - term.setBackgroundColor(colors.lime) - else - term.setTextColor(colors.gray) - term.setBackgroundColor(colors.green) - end - for i = 1, barLength do - if (i / barLength) <= (game.custom / game.customMax) then - if game.custom == game.customMax then - term.write("@") - else - term.write("=") - end - else - term.setBackgroundColor(colors.black) - term.write(" ") - end - end - term.setTextColor(colors.white) - term.setBackgroundColor(colors.black) - term.write("]") - - if showDebug then - term.setCursorPos(1, scr_y - 1) - term.write("Frame: " .. FRAME .. ", isHost = " .. tostring(isHost) .. ", you = " .. tostring(you)) - end -end - -local getInput = function() - local evt - keysDown = {} - miceDown = {} - while true do - evt = {os.pullEvent()} - if evt[1] == "key" then - keysDown[evt[2]] = true - if keysDown[keys.leftCtrl] and keysDown[keys.t] then - if skynet and useSkynet then - skynet.socket.close() - end - return - end - elseif evt[1] == "key_up" then - keysDown[evt[2]] = nil - elseif evt[1] == "mouse_click" or evt[1] == "mouse_drag" then - miceDown[evt[2]] = {evt[3], evt[4]} - elseif evt[1] == "mouse_up" then - miceDown[evt[2]] = nil - end - end -end - -local chipSelectScreen = function() - local inQueue = {} -- selected chips in menu, by folder position - local pile = {} -- chips for you to choose from, by folder position - local rPile, r = {} - local player = players[you] - for i = 1, 5 do - repeat - r = math.random(1, #player.folder) - until not rPile[r] - pile[#pile + 1] = r - rPile[r] = true - end - local cursor = 1 - - local checkIfChoosable = function(c) - local chip, compareChip = player.folder[pile[c]] - local isSameChip = true - local isSameCode = true - for i = 1, #inQueue do - compareChip = player.folder[inQueue[i]] - if compareChip[1] ~= chip[1] then - isSameChip = false - end - if compareChip[2] ~= chip[2] then - isSameCode = false - end - end - return isSameCode or isSameChip - end - - local renderMenu = function() - local chip - term.setBackgroundColor(colors.gray) - term.setTextColor(colors.yellow) - for y = 4, scr_y - 2 do - term.setCursorPos(3, y) - term.write((" "):rep(scr_x - 4)) - end - cwrite(" Turn " .. game.turnNumber .. ", Select Chips: ", 3) - term.setTextColor(colors.lightGray) - cwrite(" (Push '" .. revKeys[control.chip]:upper() .. "' to add / '" .. revKeys[control.buster]:upper() .. "' to remove) ", 4) - cwrite(" (Push ENTER to confirm loadout) ", 5) - for y = 1, #pile do - if checkIfChoosable(y) then - if y == cursor then - term.setBackgroundColor(colors.lightGray) - term.setTextColor(colors.white) - else - term.setBackgroundColor(colors.gray) - term.setTextColor(colors.white) - end - else - if y == cursor then - term.setBackgroundColor(colors.lightGray) - term.setTextColor(colors.gray) - else - term.setBackgroundColor(colors.gray) - term.setTextColor(colors.lightGray) - end - end - chip = player.folder[pile[y]] - term.setCursorPos(4, y + 5) - term.write(chips[chip[1]].info.name .. " " .. chip[2]:upper()) - end - term.setBackgroundColor(colors.gray) - term.setTextColor(colors.lightBlue) - for y = 1, #inQueue do - chip = player.folder[inQueue[y]] - term.setCursorPos(20, y + 5) - term.write(chips[chip[1]].info.name .. " " .. chip[2]:upper()) - end - term.setTextColor(colors.white) - if player.folder[pile[cursor]] then - term.setCursorPos(5, 12) - term.write("Description:") - term.setCursorPos(4, 13) - term.write(chips[player.folder[pile[cursor]][1]].info.description) - end - end - - local evt - render() - while true do - renderMenu() - evt = {os.pullEvent()} - if evt[1] == "key" then - if evt[2] == keys.up then - cursor = math.max(cursor - 1, 1) - elseif evt[2] == keys.down then - cursor = math.min(cursor + 1, #pile) - elseif evt[2] == control.chip then - if pile[cursor] then - if checkIfChoosable(cursor) then - table.insert(inQueue, pile[cursor]) - table.remove(pile, cursor) - end - end - elseif evt[2] == control.buster then - if #inQueue > 0 then - table.insert(pile, inQueue[#inQueue]) - table.remove(inQueue, #inQueue) - end - elseif evt[2] == keys.enter then - player.chipQueue = {} - for i = 1, #inQueue do - player.chipQueue[#player.chipQueue + 1] = player.folder[inQueue[i]][1] - end - table.sort(inQueue, function(a,b) return a > b end) - for i = 1, #inQueue do - table.remove(inQueue, i) - end - return - end - cursor = math.min(math.max(cursor, 1), #pile) - end - end -end - -local checkDeadPlayers = function() - local deadPlayers, thereIsDead = {}, false - for id, player in pairs(players) do - if player.isDead then - deadPlayers[id] = true - thereIsDead = true - end - end - return thereIsDead, deadPlayers -end - -local waitingForClientChipSelection = false -local runGame = function() - local evt, getStateInfo - render() - sleep(0.35) - while true do - FRAME = FRAME + 1 - - if game.inChipSelect then - game.turnNumber = game.turnNumber + 1 - chipSelectScreen() - if isHost then - game.custom = 0 - local msg - render() - cwrite("Waiting for other player...", scr_y - 3) - - transmit({ - gameID = gameID, - command = "turn_ready", - pID = you, - }) - - repeat - sleep(0) - until cliChipSelect - - players[cliChipSelect.pID].chipQueue = cliChipSelect.chipQueue - players[cliChipSelect.pID].folder = cliChipSelect.folder - cliChipSelect = false - - transmit({ - gameID = gameID, - command = "turn_ready", - pID = 1, - }) - term.clearLine() - cwrite("READY!", scr_y - 3) - sleep(0.5) - else - transmit({ - gameID = gameID, - command = "turn_ready", - pID = you, - chipQueue = players[you].chipQueue, - folder = players[you].folder, - }) - render() - cwrite("Waiting for other player...", scr_y - 3) - repeat - msg = receive() - msg = type(msg) == "table" and msg or {} - until ( - msg.gameID == gameID and - msg.command == "turn_ready" and - players[msg.pID] - ) - term.clearLine() - cwrite("READY!", scr_y - 3) - sleep(0.5) - end - game.inChipSelect = false - end - - if isHost then - getControls() - for id, proj in pairs(projectiles) do - local success, imageData = chips[proj.chipType].logic(proj) - if success then - projectiles[id].imageData = imageData - projectiles[id].frame = proj.frame + 1 - else - projectiles[id] = nil - end - end - - for y = 1, #stage.panels do - for x = 1, #stage.panels[y] do - stage.panels[y][x].reserved = false - end - end - - for id, player in pairs(players) do - if not player.isDead then - if player.canMove then - stage.panels[player.y][player.x].reserved = id - end - local dmg, flinching = act.stage.getDamage(player.x, player.y, id) - if player.cooldown.iframe == 0 and dmg > 0 then - player.health = math.max(0, player.health - dmg) - if player.health == 0 then - player.isDead = true - elseif flinching then - player.cooldown.iframe = 16 - player.cooldown.move = 8 - player.cooldown.shoot = 6 - end - elseif player.cooldown.shoot == 0 then - if player.canShoot then - if player.control.chip then - if player.chipQueue[1] then - if chips[player.chipQueue[1]] then - act.projectile.newProjectile(player.x, player.y, player, player.chipQueue[1]) - for k,v in pairs(chips[player.chipQueue[1]].info.cooldown or {}) do - player.cooldown[k] = v - end - if true then - table.remove(player.chipQueue, 1) - else - player.chipQueue[#player.chipQueue + 1] = player.chipQueue[1] - table.remove(player.chipQueue, 1) - end - end - end - elseif player.control.buster then - act.projectile.newProjectile(player.x, player.y, player, "buster") - for k,v in pairs(chips.buster.info.cooldown or {}) do - player.cooldown[k] = v - end - end - end - end - end - end - for id, object in pairs(objects) do - local dmg, flinching = act.stage.getDamage(object.x, object.y, nil, not object.friendlyFire and id, nil, id) - if object.cooldown.iframe == 0 and dmg > 0 then - object.health = object.health - dmg - if object.health <= 0 then - table.remove(objects, id) - else - object.cooldown.iframe = 2 - end - end - if objects[id] then - if object.xvel ~= 0 or object.yvel ~= 0 then - if not act.object.moveObject(id, object.xvel, object.yvel) then - if act.player.checkPlayerAtPos(object.x + object.xvel, object.y) or act.object.checkObjectAtPos(object.x + object.xvel, object.y) then - act.stage.setDamage(object.x + object.xvel, object.y + object.yvel, object.smackDamage, 0, 2, false) - table.remove(objects, id) - else - object.xvel = 0 - object.yvel = 0 - object.x = round(object.x) - object.y = round(object.y) - end - end - end - object.frame = object.frame + 1 - if object.frame > 1 and object.frame % object.delayedTime == 0 then - object.delayedFunc(object) - end - end - end - if players[you] then - if players[you].control.custom and game.custom == game.customMax then - game.inChipSelect = true - end - end - render() - movePlayers() - sleep(gameDelayInit) - game.custom = math.min(game.customMax, game.custom + 1) - transmit({ - gameID = gameID, - command = "get_state", - players = players, - projectiles = projectiles, - objects = objects, - game = game, - stageDamage = stage.damage, - stagePanels = stage.panels, - id = id - }) - reduceCooldowns() - else - getControls() - if players[you] then - transmit({ - gameID = gameID, - command = "set_controls", - id = yourID, - pID = you, - control = players[you].control - }) - end - if players[you] then - if players[you].control.custom and game.custom == game.customMax then - transmit({ - gameID = gameID, - command = "chip_select", - id = yourID, - }) - end - end - render() - evt, getStateInfo = os.pullEvent("ccbn_get_state") - players = getStateInfo.players - projectiles = getStateInfo.projectiles - objects = getStateInfo.objects - game = getStateInfo.game - stage.damage = getStateInfo.stageDamage - stage.panels = getStateInfo.stagePanels - end - - if checkDeadPlayers() then - render() - break - end - - end - - local thereIsDead, deadPlayers = checkDeadPlayers() - if thereIsDead then - sleep(0.5) - parallel.waitForAny(function() - while true do - if deadPlayers[you] then - render({images.lose, true, 6}) - else - render({images.win, true, 6}) - end - sleep(1) - render() - sleep(0.5) - end - end, function() os.pullEvent("key") end) - sleep(0.05) - end -end - -local interpretNetMessage = function(msg) - if waitingForGame then - if msg.command == "find_game" then - local time = os.epoch("utc") - if msg.time > time then - isHost = false - you = 2 - else - isHost = true - you = 1 - end - return true - end - elseif msg.gameID == gameID then - if isHost then - if msg.command == "set_controls" then - if players[msg.pID] then - players[msg.pID].control = msg.control - end - elseif msg.command == "chip_select" then - if game.custom == game.customMax then - game.inChipSelect = true - end - elseif msg.command == "turn_ready" then - if ( - type(msg.chipQueue) == "table" and - players[msg.pID] and - type(msg.folder) == "table" - ) then - cliChipSelect = { - folder = msg.folder, - chipQueue = msg.chipQueue, - pID = msg.pID - } - end - end - else - if msg.command == "get_state" then - os.queueEvent("ccbn_get_state", { - players = msg.players, - projectiles = msg.projectiles, - objects = msg.objects, - game = msg.game, - stageDamage = msg.stageDamage, - stagePanels = msg.stagePanels - }) - end - end - end -end - -local networking = function() - local msg - while true do - msg = receive() - if type(msg) == "table" then - interpretNetMessage(msg) - end - end -end - -local startGame = function() - getModem() - local time = os.epoch("utc") - chips, objectTypes = loadChips(getfenv()) - stage.panels = {} - stage.damage = {} - players = {} - objects = {} - projectiles = {} - game.custom = 0 - game.customSpeed = 1 - game.inChipSelect = true - game.paused = false - act.player.newPlayer(2, 2, 1, 1, "6") - act.player.newPlayer(5, 2, 2, -1, "7") - for y = 1, 3 do - for x = 1, 6 do - act.stage.newPanel(x, y, "normal") - end - end - transmit({ - gameID = gameID, - command = "find_game", - respond = false, - id = yourID, - time = time, --- chips = chips - }) - local msg - waitingForGame = true - term.clear() - cwrite("Waiting for game...") - repeat - msg = receive() - until interpretNetMessage(msg) - gameID = isHost and gameID or msg.gameID --- chips = isHost and chips or msg.chips - transmit({ - gameID = gameID, - command = "find_game", - respond = true, - id = yourID, - time = isHost and math.huge or -math.huge, --- chips = isHost and chips - }) - waitingForGame = false - parallel.waitForAny(runGame, networking) -end - -local makeMenu = function(x, y, options, _cpos) - local cpos = _cpos or 1 - local cursor = "> " - local lastPos = cpos - local rend = function() - for i = 1, #options do - if i == cpos then - term.setCursorPos(x, y + (i - 1)) - term.setTextColor(colors.white) - term.write(cursor .. options[i]) - else - if i == lastPos then - term.setCursorPos(x, y + (i - 1)) - term.write((" "):rep(#cursor)) - lastPos = nil - else - term.setCursorPos(x + #cursor, y + (i - 1)) - end - term.setTextColor(colors.gray) - term.write(options[i]) - end - end - end - local evt - rend() - while true do - evt = {os.pullEvent()} - if evt[1] == "key" then - if evt[2] == keys.up then - lastPos = cpos - cpos = (cpos - 2) % #options + 1 - elseif evt[2] == keys.down then - lastPos = cpos - cpos = (cpos % #options) + 1 - elseif evt[2] == keys.home then - lastPos = cpos - cpos = 1 - elseif evt[2] == keys["end"] then - lastPos = cpos - cpos = #options - elseif evt[2] == keys.enter then - return cpos - end - elseif evt[1] == "mouse_click" then - if evt[4] >= y and evt[4] < y+#options then - if cpos == evt[4] - (y - 1) then - return cpos - else - lastPos = cpos - cpos = evt[4] - (y - 1) - rend() - end - end - end - if lastPos ~= cpos then - rend() - end - end -end - -local howToPlay = function() - local help = { - " (Scroll with mousewheel / arrows)", - " (Exit with 'Q')", - ("="):rep(scr_x), - "", - " If you're not familiar with", - " Megaman Battle Network, buckle up.", - "", - " Battles are separated into 'turns'.", - " At the beginning of each turn, you", - " select one or more battlechips to use", - " during that turn.", - "", - " Selecting battlechips has certain rules.", - " Battlechips are given alphabetic codes", - " You can only pick two or more battlechips", - " that have the same code, or are of the same", - " chip type. That means you can pick a", - " Cannon A and a Minibomb A, but you can't", - " add an extra Cannon B without removing", - " the Minibomb B.", - " ____ ____ ____ ", - "| | | | | ^ | ", - "| "..revKeys[control.buster]:upper().." | | "..revKeys[control.chip]:upper().." | | | | ", - "|____| |____| |____| ", - " ____ ____ ____ ", - " | | | | | | | ", - " | <- | | V | | -> | ", - " |____| |____| |____| ", - "", - " To move, use the ARROW KEYS.", - " Fire the MegaBuster with '"..revKeys[control.buster]:upper().."'. It's a free", - " action, but not very strong.", - " Use the currently selected battlechip", - " (indicated in the bottom-left corner)", - " with '"..revKeys[control.chip]:upper().."'.", - "", - " Once you use up all your chips, you will", - " need to wait for the Custom bar to refill.", - " Once it is full, push '"..revKeys[control.custom]:upper().."' and the turn will", - " end, and you can pick more battlechips.", - "", - " Keep in mind that this erases all currently", - " loaded battlechips, and that the opponent", - " can also end the turn without warning, so", - " make sure that your battlechips are used", - " before the bar fills!", - "", - " ___________________________________", - " |yours|yours|yours|enemy|enemy|enemy|", - " |_____|_____|_____|_____|_____|_____|", - " |yours|yours|yours|enemy|enemy|enemy|", - " |_____|_____|_____|_____|_____|_____|", - " |yours|yours|yours|enemy|enemy|enemy|", - " |_____|_____|_____|_____|_____|_____|", - "", - " The stage that you stand on can also be", - " manipulated. Some chips, such as AreaGrab", - " can take away ownership of one or more", - " panels from the enemy for a short while.", - " Some chips, such as CrackShot, will break", - " panels, rendering them unusable for a short", - " while. Some chips will crack panels, such", - " as Geddon1. Stepping off of a cracked panel", - " will cause it to break.", - "", - " That's all I can think of. Sorry for all that", - " wall of text, and I hope you enjoy the game!", - "", - " ___ __ __ _ _ ", - "/ \\ | | | | | \\ | | | / \\ | / | ", - "| ___ | | | | | | | | | | |/\\ | ", - "\\__| |__| |__| |_/ |__ \\_/ \\_/ | \\ . ", - } - - local scroll = 0 - local maxScroll = #help - scr_y + 2 - - local rend = function(scroll) - term.setBackgroundColor(colors.black) - term.setTextColor(colors.white) - for y = 1, scr_y do - term.setCursorPos(1,y) - term.clearLine() - term.write(help[y + scroll] or "") - end - end - - local evt - while true do - evt = {os.pullEvent()} - if evt[1] == "key" then - if evt[2] == keys.q then - return - elseif evt[2] == keys.up then - scroll = scroll - 1 - elseif evt[2] == keys.down then - scroll = scroll + 1 - elseif evt[2] == keys.pageUp then - scroll = scroll - scr_y - elseif evt[2] == keys.pageDown then - scroll = scroll + scr_y - elseif evt[2] == keys.home then - scroll = 0 - elseif evt[2] == keys["end"] then - scroll = maxScroll - end - elseif evt[1] == "mouse_scroll" then - scroll = scroll + evt[2] - end - scroll = math.min(maxScroll, math.max(0, scroll)) - rend(scroll) - end - - sleep(0.1) - os.pullEvent("key") -end - -local titleScreen = function() - local menuOptions = { - "Start Game", - "How to Play", - "Exit" - } - local choice - while true do - term.setBackgroundColor(colors.black) - term.clear() - drawImage(images.logo, 2, 2) - if useSkynet then - term.setTextColor(colors.lightGray) - cwrite("Skynet Enabled", 2 + #images.logo[1]) - end - choice = makeMenu(2, scr_y - #menuOptions, menuOptions) - if choice == 1 then - parallel.waitForAny(startGame, getInput) - elseif choice == 2 then - howToPlay() - elseif choice == 3 then - return - end - end -end - -titleScreen() - -term.setBackgroundColor(colors.black) -term.clear() -cwrite("Thanks for playing!") -term.setCursorPos(1, scr_y)