1
0
mirror of https://github.com/LDDestroier/CC/ synced 2024-11-06 01:56:22 +00:00
ldd-CC/CCBN/ccbn.lua

1655 lines
43 KiB
Lua
Raw Normal View History

2019-03-09 21:09:52 +00:00
local scr_x, scr_y = term.getSize()
local keysDown, miceDown = {}, {}
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")
2019-03-09 21:09:52 +00:00
local players = {}
local objects = {}
2019-03-09 21:09:52 +00:00
local projectiles = {}
local game = {
custom = 0,
customMax = 200,
customSpeed = 1,
inChipSelect = true,
paused = false
}
2019-03-09 21:09:52 +00:00
local you = 1
2019-03-11 04:10:00 +00:00
local yourID = os.getComputerID()
local revKeys = {}
for k,v in pairs(keys) do
revKeys[v] = k
end
-- recommended at 0.1 for netplay, which you'll be doing all the time so yeah
2019-03-12 21:02:26 +00:00
local gameDelayInit = 0.05
local gameID = math.random(0, 2^30)
2019-03-11 04:10:00 +00:00
local waitingForGame = false
local isHost = true
local channel = 1024
2019-03-09 21:09:52 +00:00
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
})
2019-03-09 21:09:52 +00:00
local FRAME = 0
local useSkynet = argList.skynet
local showDebug = argList.debug
2019-03-09 21:09:52 +00:00
local stage = {
panels = {},
2019-03-10 20:12:49 +00:00
damage = {},
2019-03-09 21:09:52 +00:00
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
2019-03-09 21:09:52 +00:00
-- 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
2019-03-09 22:24:33 +00:00
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)
2019-03-09 22:20:14 +00:00
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
2019-03-09 21:09:52 +00:00
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"
2019-03-11 04:10:00 +00:00
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
2019-03-11 04:10:00 +00:00
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
2019-03-11 04:10:00 +00:00
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
2019-03-11 04:10:00 +00:00
end
end
local transmit = function(msg)
if useSkynet then
skynet.send(channel, msg)
2019-03-11 04:10:00 +00:00
else
modem.transmit(channel, channel, msg)
end
end
local receive = function()
if useSkynet then
return ({skynet.receive(channel)})[2]
2019-03-11 04:10:00 +00:00
else
return ({os.pullEvent("modem_message")})[5]
2019-03-11 04:10:00 +00:00
end
end
2019-03-09 21:09:52 +00:00
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 ",
},
},
2019-03-09 21:09:52 +00:00
panel = {
normal = {{"—ƒƒƒƒ”","•€€‚•","€€€€€€"},{"eeeee7","e78877","eeeeee"},{"77777e","78888e","eeeeee"}},
cracked = {{"—››››”","•™™™™•","€€€€€€"},{"eeeee7","e88888","eeeeee"},{"77777e","87777e","eeeeee"}},
broken = {{"—ƒƒƒƒ”","•—•","€€€€€€"},{"eeeeef","eff8f7","eeeeee"},{" e","788f8e","eeeeee"}}
2019-03-09 21:09:52 +00:00
},
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"}},
2019-03-09 21:09:52 +00:00
cannon = {{"‡‹","‹‡"},{"ff","77"},{"77"," ",}},
buster = {{"‘"},{"f4"},{"4f"}}
2019-03-09 21:09:52 +00:00
}
local cwrite = function(text, y)
local cx, cy = term.getCursorPos()
term.setCursorPos(scr_x / 2 - #text / 2, y or (scr_y / 2))
term.write(text)
end
local act = {stage = {}, player = {}, projectile = {}, object = {}}
2019-03-09 21:09:52 +00:00
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),
2019-03-09 21:09:52 +00:00
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
2019-03-09 21:09:52 +00:00
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)
2019-03-10 20:12:49 +00:00
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 {}
2019-03-10 20:12:49 +00:00
}
stageChanged = true
2019-03-09 21:09:52 +00:00
end
act.stage.getDamage = function(x, y, pID, oID, pIDsafeCheck, oIDsafeCheck)
2019-03-10 20:12:49 +00:00
local totalDamage = 0
local flinching = false
x, y = round(x), round(y)
2019-03-10 20:12:49 +00:00
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
2019-03-10 20:12:49 +00:00
end
2019-03-09 21:09:52 +00:00
end
end
end
return totalDamage, flinching
2019-03-09 21:09:52 +00:00
end
local premadeFolders = {
[1] = { -- BN2 starting folder, modified slightly
{"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"},
{"vulcan1", "c"},
{"geddon1", "f"},
{"shotgun", "d"},
{"shotgun", "d"},
{"vgun", "d"},
{"vgun", "d"},
{"spreader", "d"},
}
}
2019-03-11 04:10:00 +00:00
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
2019-03-09 21:09:52 +00:00
},
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)]
2019-03-09 21:09:52 +00:00
}
return pID
2019-03-09 21:09:52 +00:00
end
act.object.newObject = function(x, y, owner, direction, objectType)
local oID = #objects + 1
objects[oID] = {
x = x,
y = y,
2019-03-12 04:58:47 +00:00
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,
2019-03-12 04:58:47 +00:00
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
2019-03-12 04:58:47 +00:00
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
2019-03-12 21:02:26 +00:00
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] = {
2019-03-09 21:09:52 +00:00
x = x,
y = y,
safeObjects = {},
safePlayers = {},
type = "projectile",
initX = x,
initY = y,
id = id,
owner = player.owner,
player = player,
2019-03-11 04:10:00 +00:00
direction = player.direction,
frame = 0,
noFlinch = noFlinch, -- overwrite a projectile's flinchingness
altDamage = altDamage, -- overwrite a projectile's damage
chipType = chipType
2019-03-09 21:09:52 +00:00
}
return id
2019-03-09 21:09:52 +00:00
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
2019-03-12 21:02:26 +00:00
local stageImageStitch
local makeStageImageStitch = function()
local buffer, im = {}
2019-03-12 21:02:26 +00:00
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
2019-03-12 21:02:26 +00:00
end
end
end
return merge(table.unpack(buffer))
end
local render = function(extraImage)
2019-03-09 21:09:52 +00:00
local buffer, im = {}
local sx, sy
if stageChanged or true then
2019-03-12 21:02:26 +00:00
stageImageStitch = makeStageImageStitch()
stageChanged = false
2019-03-12 21:02:26 +00:00
end
local sortedList = {}
2019-03-11 04:10:00 +00:00
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
2019-03-11 04:10:00 +00:00
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
2019-03-11 04:10:00 +00:00
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
2019-03-11 04:10:00 +00:00
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)
}
2019-03-09 21:09:52 +00:00
end
end
2019-03-12 21:02:26 +00:00
buffer[#buffer + 1] = {
stageImageStitch,
stage.scrollX + 1,
stage.scrollY + 1
}
2019-03-09 21:09:52 +00:00
buffer[#buffer + 1] = {makeRectangle(scr_x, scr_y, "f", "f", "f"), 1, 1}
drawImage(colorSwap(merge(table.unpack(buffer)), {[" "] = "f"}), 1, 1)
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
2019-03-09 21:16:36 +00:00
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
term.setTextColor(colors.white)
term.setBackgroundColor(colors.black)
if game.custom == game.customMax and FRAME % 8 <= 5 then
cwrite("PUSH '" .. revKeys[control.custom]:upper() .. "'!", 2)
end
term.setBackgroundColor(colors.gray)
term.setCursorPos(6, 1)
term.write("[CUSTOM][")
local barLength = scr_x - 20
if game.custom == game.customMax then
term.setBackgroundColor(colors.lime)
else
term.setBackgroundColor(colors.green)
end
for i = 1, barLength do
if (i / barLength) <= (game.custom / game.customMax) then
term.write("=")
else
term.setBackgroundColor(colors.gray)
term.write(" ")
end
end
term.setBackgroundColor(colors.gray)
term.write("]")
if showDebug then
term.setCursorPos(1, scr_y - 1)
term.write("Frame: " .. FRAME .. ", isHost = " .. tostring(isHost) .. ", you = " .. tostring(you))
end
2019-03-09 21:09:52 +00:00
end
local getInput = function()
local evt
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
2019-03-09 21:09:52 +00:00
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(" 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
while true do
-- render()
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
2019-03-09 21:09:52 +00:00
local runGame = function()
local evt, getStateInfo
render()
sleep(0.5)
2019-03-09 21:09:52 +00:00
while true do
FRAME = FRAME + 1
render()
if game.inChipSelect then
chipSelectScreen()
if isHost then
game.inChipSelect = false
game.custom = 0
local msg
cwrite("Waiting...", scr_y - 3)
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 = you,
})
else
transmit({
gameID = gameID,
command = "turn_ready",
pID = you,
chipQueue = players[you].chipQueue,
folder = players[you].folder,
})
cwrite("Waiting...", 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]
)
end
end
2019-03-11 04:10:00 +00:00
if isHost then
game.custom = math.min(game.customMax, game.custom + 1)
2019-03-11 04:10:00 +00:00
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
2019-03-09 21:09:52 +00:00
end
2019-03-11 04:10:00 +00:00
for y = 1, #stage.panels do
for x = 1, #stage.panels[y] do
stage.panels[y][x].reserved = false
2019-03-11 04:10:00 +00:00
end
2019-03-09 21:09:52 +00:00
end
2019-03-11 04:10:00 +00:00
for id, player in pairs(players) do
if not player.isDead then
if player.canMove then
stage.panels[player.y][player.x].reserved = id
2019-03-11 04:10:00 +00:00
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
2019-03-11 04:10:00 +00:00
end
end
2019-03-09 21:16:36 +00:00
end
2019-03-09 21:09:52 +00:00
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)
2019-03-12 04:58:47 +00:00
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
2019-03-12 04:58:47 +00:00
end
end
object.frame = object.frame + 1
if object.frame > 1 and object.frame % object.delayedTime == 0 then
object.delayedFunc(object)
end
2019-03-12 04:58:47 +00:00
end
end
2019-03-11 04:10:00 +00:00
reduceCooldowns()
movePlayers()
if players[you] then
if players[you].control.custom and game.custom == game.customMax then
game.inChipSelect = true
end
end
2019-03-12 21:02:26 +00:00
sleep(gameDelayInit)
2019-03-11 04:10:00 +00:00
transmit({
gameID = gameID,
command = "get_state",
players = players,
projectiles = projectiles,
2019-03-12 04:58:47 +00:00
objects = objects,
game = game,
stageDamage = stage.damage,
stagePanels = stage.panels,
2019-03-11 04:10:00 +00:00
id = id
})
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
evt, getStateInfo = os.pullEvent("ccbn_get_state")
players = getStateInfo.players
projectiles = getStateInfo.projectiles
2019-03-12 04:58:47 +00:00
objects = getStateInfo.objects
game = getStateInfo.game
stage.damage = getStateInfo.stageDamage
stage.panels = getStateInfo.stagePanels
2019-03-09 21:09:52 +00:00
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)
2019-03-09 21:09:52 +00:00
end
end
2019-03-11 04:10:00 +00:00
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
2019-03-12 21:04:46 +00:00
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
2019-03-11 04:10:00 +00:00
end
else
if msg.command == "get_state" then
os.queueEvent("ccbn_get_state", {
players = msg.players,
projectiles = msg.projectiles,
2019-03-12 04:58:47 +00:00
objects = msg.objects,
game = msg.game,
stageDamage = msg.stageDamage,
stagePanels = msg.stagePanels
})
2019-03-11 04:10:00 +00:00
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
2019-03-11 04:10:00 +00:00
transmit({
gameID = gameID,
command = "find_game",
respond = false,
id = yourID,
time = time,
-- chips = chips
2019-03-11 04:10:00 +00:00
})
local msg
waitingForGame = true
term.clear()
cwrite("Waiting for game...")
2019-03-11 04:10:00 +00:00
repeat
msg = receive()
until interpretNetMessage(msg)
gameID = isHost and gameID or msg.gameID
-- chips = isHost and chips or msg.chips
2019-03-11 04:10:00 +00:00
transmit({
gameID = gameID,
command = "find_game",
respond = true,
id = yourID,
time = isHost and math.huge or -math.huge,
-- chips = isHost and chips
2019-03-11 04:10:00 +00:00
})
waitingForGame = false
parallel.waitForAny(runGame, networking)
2019-03-11 04:10:00 +00:00
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 titleScreen = function()
local menuOptions = {
"Start Game",
"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
return
end
end
end
titleScreen()
term.setBackgroundColor(colors.black)
term.clear()
cwrite("Thanks for playing!")
term.setCursorPos(1, scr_y)