mirror of
https://github.com/LDDestroier/CC/
synced 2024-12-14 12:10:29 +00:00
3163 lines
96 KiB
Lua
3163 lines
96 KiB
Lua
local tArg = {...}
|
||
local outputPath, file = tArg[1] and fs.combine(shell.dir(), tArg[1]) or shell.getRunningProgram()
|
||
local safeColorList = {[colors.white] = true,[colors.lightGray] = true,[colors.gray] = true,[colors.black] = true}
|
||
local stc = function(color) if (term.isColor() or safeColorList[color]) then term.setTextColor(color) end end
|
||
local archive = textutils.unserialize("{\
|
||
mainFile = \"ccbn.lua\",\
|
||
compressed = false,\
|
||
data = {\
|
||
[ \"ccbn-data/chipdata/vulcan_internal\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Vulcan_Internal\\\",\\\
|
||
description = \\\"Internal component of Vulcan1 through 3 and SuperVulcan.\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (3 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 10, info.owner, 1, info.noFlinch)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 10, info.owner, 1, info.noFlinch)\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/doubleshot\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"DoubleShot\\\",\\\
|
||
description = \\\"Fires two panels forwards!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
act.projectile.newProjectile(info.x, info.y, info.player, \\\"panelshot\\\", false, info.altDamage)\\\
|
||
act.projectile.newProjectile(info.x + info.direction, info.y, info.player, \\\"panelshot\\\", true, info.altDamage)\\\
|
||
\\\
|
||
return false\\\
|
||
\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/triplecrack\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"TripleCrack\\\",\\\
|
||
description = \\\"Destroys three panels in front!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
act.stage.crackPanel(info.x + info.direction, info.y - 1, 2)\\\
|
||
act.stage.crackPanel(info.x + info.direction, info.y, 2)\\\
|
||
act.stage.crackPanel(info.x + info.direction, info.y + 1, 2)\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/airshot1\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"AirShot1\\\",\\\
|
||
description = \\\"Fires a pushing shot forwards!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (4 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 20, info.owner, 1)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
if struckPlayer then\\\
|
||
if act.player.movePlayer(struckPlayer, info.direction, 0, true) then\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 20, info.owner, 1)\\\
|
||
end\\\
|
||
elseif struckObject then\\\
|
||
if objects[struckObject].doYeet then\\\
|
||
objects[struckObject].xvel = (4 / stage.panelWidth) * info.direction\\\
|
||
else\\\
|
||
if act.object.moveObject(struckObject, info.direction, 0) then\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 20, info.owner, 1)\\\
|
||
end\\\
|
||
end\\\
|
||
end\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/boomer1\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Boomer1\\\",\\\
|
||
description = \\\"Boomerang that orbits stage!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 5\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
if info.direction == 1 then\\\
|
||
if info.frame == 0 then\\\
|
||
info.x = 0\\\
|
||
info.y = 3\\\
|
||
end\\\
|
||
if info.y > 1 then\\\
|
||
if info.x <= 6 then\\\
|
||
info.x = info.x + (2 / stage.panelWidth)\\\
|
||
else\\\
|
||
info.y = info.y - (2 / stage.panelHeight)\\\
|
||
end\\\
|
||
elseif info.x > 0 then\\\
|
||
info.x = info.x - (2 / stage.panelWidth)\\\
|
||
else\\\
|
||
return false\\\
|
||
end\\\
|
||
elseif info.direction == -1 then\\\
|
||
if info.frame == 0 then\\\
|
||
info.x = 7\\\
|
||
info.y = 3\\\
|
||
end\\\
|
||
if info.y > 1 then\\\
|
||
if info.x > 1 then\\\
|
||
info.x = info.x - (2 / stage.panelWidth)\\\
|
||
else\\\
|
||
info.y = info.y - (2 / stage.panelHeight)\\\
|
||
end\\\
|
||
elseif info.x <= 7 then\\\
|
||
info.x = info.x + (2 / stage.panelWidth)\\\
|
||
else\\\
|
||
return false\\\
|
||
end\\\
|
||
end\\\
|
||
\\\
|
||
local struckObject = act.object.checkObjectAtPos(info.x, info.y)\\\
|
||
if struckObject then\\\
|
||
info.safeObjects[struckObject] = true\\\
|
||
end\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 60, info.owner, 2, false, {}, info.safeObjects)\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/hicannon\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"HiCannon\\\",\\\
|
||
description = \\\"Fires a better shot forwards!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (4 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 60, info.owner, 1)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/areagrab\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"AreaGrab\\\",\\\
|
||
description = \\\"Grabs three panels from enemy!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
if info.frame == 0 then\\\
|
||
if info.owner == 1 then\\\
|
||
info.x = 5\\\
|
||
for y = 1, 3 do\\\
|
||
for x = 2, 5 do\\\
|
||
if stage.panels[y][x].owner ~= info.owner then\\\
|
||
info.x = math.min(info.x, x)\\\
|
||
break\\\
|
||
end\\\
|
||
end\\\
|
||
end\\\
|
||
else\\\
|
||
info.x = 2\\\
|
||
for y = 1, 3 do\\\
|
||
for x = 5, 2, -1 do\\\
|
||
if stage.panels[y][x].owner ~= info.owner then\\\
|
||
info.x = math.max(info.x, x)\\\
|
||
break\\\
|
||
end\\\
|
||
end\\\
|
||
end\\\
|
||
end\\\
|
||
end\\\
|
||
\\\
|
||
for y = 1, 3 do\\\
|
||
act.projectile.newProjectile(info.x, y, info.player, \\\"panelgrab_internal\\\")\\\
|
||
end\\\
|
||
\\\
|
||
return false\\\
|
||
\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/crossgun\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"CrossGun\\\",\\\
|
||
description = \\\"Shoots four diagonal panels around enemy!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (4 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 30, info.owner, 2)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
if struckPlayer or struckObject then\\\
|
||
act.stage.setDamage(info.x - 1, info.y - 1, 30, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + 1, info.y - 1, 30, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x - 1, info.y + 1, 30, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + 1, info.y + 1, 30, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x, info.y, 30, info.owner, 1)\\\
|
||
end\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/vulcan2\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Vulcan2\\\",\\\
|
||
description = \\\"Fires five shots that damages panel behind!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
if info.frame == 0 then\\\
|
||
info.player.canMove = false\\\
|
||
info.player.canShoot = false\\\
|
||
else\\\
|
||
if info.frame == 5 * 2 + 1 then\\\
|
||
info.player.canMove = true\\\
|
||
info.player.canShoot = true\\\
|
||
info.player.cooldown.shoot = 6\\\
|
||
info.player.cooldown.shoot = 4\\\
|
||
return false\\\
|
||
elseif info.frame % 2 == 0 then\\\
|
||
act.projectile.newProjectile(info.x, info.y, info.player, \\\"vulcan_internal\\\", info.frame < 5 * 2)\\\
|
||
end\\\
|
||
end\\\
|
||
return true\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn.lua\" ] = \"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)\",\
|
||
[ \"ccbn-data/chipdata/geddon1\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Geddon1\\\",\\\
|
||
description = \\\"Cracks all panels!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
for y, row in pairs(stage.panels) do\\\
|
||
for x, panel in pairs(row) do\\\
|
||
act.stage.crackPanel(x, y, 1)\\\
|
||
end\\\
|
||
end\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/rockcube\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"RockCube\\\",\\\
|
||
description = \\\"Creates a cube-shaped rock!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
if act.stage.checkIfWalkable(info.x + info.direction, info.y) then\\\
|
||
act.object.newObject(info.x + info.direction, info.y, info.owner, info.direction, \\\"rockcube\\\")\\\
|
||
end\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/widesword\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"WideSword\\\",\\\
|
||
description = \\\"Slash column in front!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 5\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y - 1, 80, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 80, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y + 1, 80, info.owner, 1)\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/crossbomb\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"CrossBomb\\\",\\\
|
||
description = \\\"Lob a cross-shaped bomb 2 panels forward!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 5\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
local maxDist = 3\\\
|
||
local maxFrames = 10\\\
|
||
local parabola = math.sin((math.pi / maxFrames) * info.frame) * 2\\\
|
||
if parabola < 0.1 and info.frame > 3 then\\\
|
||
act.stage.setDamage(info.x, info.y - 1, 70, info.owner, 1, false)\\\
|
||
act.stage.setDamage(info.x, info.y, 70, info.owner, 1, false)\\\
|
||
act.stage.setDamage(info.x, info.y + 1, 70, info.owner, 1, false)\\\
|
||
act.stage.setDamage(info.x - 1, info.y, 70, info.owner, 1, false)\\\
|
||
act.stage.setDamage(info.x + 1, info.y, 70, info.owner, 1, false)\\\
|
||
return false\\\
|
||
else\\\
|
||
info.x = info.x + (maxDist / maxFrames) * info.direction\\\
|
||
end\\\
|
||
return true, {{images.cannon, info.x, info.y - parabola}}\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/recov150\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Recov150\\\",\\\
|
||
description = \\\"Gives you 150 health!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 2\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.player.health = math.min(info.player.health + 150, info.player.maxHealth)\\\
|
||
return false\\\
|
||
end,\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/minibomb\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"MiniBomb\\\",\\\
|
||
description = \\\"Lob a small bomb 2 panels forward!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 5\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
local maxDist = 3\\\
|
||
local maxFrames = 10\\\
|
||
local parabola = math.sin((math.pi / maxFrames) * info.frame) * 2\\\
|
||
if parabola < 0.1 and info.frame > 3 then\\\
|
||
act.stage.setDamage(info.x, info.y, 50, info.owner, 1, false)\\\
|
||
return false\\\
|
||
else\\\
|
||
info.x = info.x + (maxDist / maxFrames) * info.direction\\\
|
||
end\\\
|
||
return true, {{images.cannon, info.x, info.y - parabola}}\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/recov200\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Recov200\\\",\\\
|
||
description = \\\"Gives you 200 health!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 2\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.player.health = math.min(info.player.health + 200, info.player.maxHealth)\\\
|
||
return false\\\
|
||
end,\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/vulcan1\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Vulcan1\\\",\\\
|
||
description = \\\"Fires three shots that damages panel behind!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
if info.frame == 0 then\\\
|
||
info.player.canMove = false\\\
|
||
info.player.canShoot = false\\\
|
||
else\\\
|
||
if info.frame == 3 * 2 + 1 then\\\
|
||
info.player.canMove = true\\\
|
||
info.player.canShoot = true\\\
|
||
info.player.cooldown.shoot = 6\\\
|
||
info.player.cooldown.shoot = 4\\\
|
||
return false\\\
|
||
elseif info.frame % 2 == 0 then\\\
|
||
act.projectile.newProjectile(info.x, info.y, info.player, \\\"vulcan_internal\\\", info.frame < 3 * 2)\\\
|
||
end\\\
|
||
end\\\
|
||
return true\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/lifesword\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"LifeSword\\\",\\\
|
||
description = \\\"Slash 2x3 area with devastating power!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 5\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y - 1, 400, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction * 2, info.y - 1, 400, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 400, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction * 2, info.y, 400, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y + 1, 400, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction * 2, info.y + 1, 400, info.owner, 1)\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/airshot3\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"AirShot3\\\",\\\
|
||
description = \\\"Fires a powerful, pushing shot forwards!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (4 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 40, info.owner, 1)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
if struckPlayer then\\\
|
||
if act.player.movePlayer(struckPlayer, info.direction, 0, true) then\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 40, info.owner, 1)\\\
|
||
end\\\
|
||
elseif struckObject then\\\
|
||
if objects[struckObject].doYeet then\\\
|
||
objects[struckObject].xvel = (4 / stage.panelWidth) * info.direction\\\
|
||
else\\\
|
||
if act.object.moveObject(struckObject, info.direction, 0) then\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 40, info.owner, 1)\\\
|
||
end\\\
|
||
end\\\
|
||
end\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/doublecrack\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"DoubleCrack\\\",\\\
|
||
description = \\\"Destroys two panels in front!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
act.stage.crackPanel(info.x + info.direction, info.y, 2)\\\
|
||
act.stage.crackPanel(info.x + info.direction * 2, info.y, 2)\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/invis\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Invis\\\",\\\
|
||
description = \\\"Makes you invincible for a short time!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 5\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.player.cooldown.iframe = 50\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/vgun\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"V-Gun\\\",\\\
|
||
description = \\\"Hits enemy as well as two diagonal panels back!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (4 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 40, info.owner, 1)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
if struckPlayer or struckObject then\\\
|
||
act.stage.setDamage(info.x, info.y, 30, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y - 1, 30, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y + 1, 30, info.owner, 1)\\\
|
||
end\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/mcannon\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"M-Cannon\\\",\\\
|
||
description = \\\"Fires a powerful shot forwards!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (2 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 80, info.owner, 1)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/recov80\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Recov80\\\",\\\
|
||
description = \\\"Gives you 80 health!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 2\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.player.health = math.min(info.player.health + 80, info.player.maxHealth)\\\
|
||
return false\\\
|
||
end,\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/airshot2\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"AirShot2\\\",\\\
|
||
description = \\\"Fires a better, pushing shot forwards!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (4 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 30, info.owner, 1)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
if struckPlayer then\\\
|
||
if act.player.movePlayer(struckPlayer, info.direction, 0, true) then\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 30, info.owner, 1)\\\
|
||
end\\\
|
||
elseif struckObject then\\\
|
||
if objects[struckObject].doYeet then\\\
|
||
objects[struckObject].xvel = (4 / stage.panelWidth) * info.direction\\\
|
||
else\\\
|
||
if act.object.moveObject(struckObject, info.direction, 0) then\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 30, info.owner, 1)\\\
|
||
end\\\
|
||
end\\\
|
||
end\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/sword\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Sword\\\",\\\
|
||
description = \\\"Slash forwards 1 panel!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 80, info.owner, 1)\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/recov50\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Recov50\\\",\\\
|
||
description = \\\"Gives you 50 health!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 2\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.player.health = math.min(info.player.health + 50, info.player.maxHealth)\\\
|
||
return false\\\
|
||
end,\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/recov10\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Recov10\\\",\\\
|
||
description = \\\"Gives you 10 health!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 2\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.player.health = math.min(info.player.health + 10, info.player.maxHealth)\\\
|
||
return false\\\
|
||
end,\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/panelgrab_internal\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"PanelGrab_Internal\\\",\\\
|
||
description = \\\"Internal for PanelGrab and AreaGrab.\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
if not stage.panels[info.y] then\\\
|
||
return false\\\
|
||
end\\\
|
||
\\\
|
||
if info.frame == 0 then\\\
|
||
info.yadj = 5\\\
|
||
end\\\
|
||
\\\
|
||
info.yadj = math.max(0, info.yadj - 0.5)\\\
|
||
\\\
|
||
if info.yadj == 0 then\\\
|
||
act.stage.setDamage(info.x, info.y, 80, info.owner, 1)\\\
|
||
if not act.player.checkPlayerAtPos(info.x, info.y) then\\\
|
||
stage.panels[info.y][info.x].owner = info.owner\\\
|
||
stage.panels[info.y][info.x].cooldown.owner = 500\\\
|
||
end\\\
|
||
return false\\\
|
||
end\\\
|
||
\\\
|
||
return true, {{images.cannon, info.x, info.y - info.yadj}}\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/spreader\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Spreader\\\",\\\
|
||
description = \\\"Hits enemy and all surrounding panels!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (4 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 30, info.owner, 1)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
if struckPlayer or struckObject then\\\
|
||
for y = -1, 1 do\\\
|
||
for x = -1, 1 do\\\
|
||
act.stage.setDamage(info.x + x, info.y + y, 30, info.owner, 1)\\\
|
||
end\\\
|
||
end\\\
|
||
end\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/fightersword\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"FighterSword\\\",\\\
|
||
description = \\\"Slash forwards 3 panels!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 100, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction * 2, info.y, 100, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction * 3, info.y, 100, info.owner, 1)\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/dash\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Dash\\\",\\\
|
||
description = \\\"Dash forwards to deal massive damage!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 2\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
if info.frame == 0 then\\\
|
||
info.player.canMove = false\\\
|
||
info.player.canShoot = false\\\
|
||
info.playerInitX = info.player.x\\\
|
||
info.playerInitY = info.player.y\\\
|
||
end\\\
|
||
if info.frame > 2 then -- start on frame 3\\\
|
||
if info.player.x > 7 or info.player.x < 0 then\\\
|
||
info.player.x = info.playerInitX\\\
|
||
info.player.y = info.playerInitY\\\
|
||
info.player.cooldown.shoot = 6\\\
|
||
info.player.cooldown.move = 2\\\
|
||
info.player.canMove = true\\\
|
||
info.player.canShoot = true\\\
|
||
return false\\\
|
||
else\\\
|
||
info.player.x = info.player.x + (5 / stage.panelWidth) * info.player.direction\\\
|
||
act.stage.setDamage(info.player.x, info.player.y, 80, info.owner, 4, false)\\\
|
||
return true\\\
|
||
end\\\
|
||
else\\\
|
||
return true\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/recov30\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Recov30\\\",\\\
|
||
description = \\\"Gives you 30 health!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 2\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.player.health = math.min(info.player.health + 30, info.player.maxHealth)\\\
|
||
return false\\\
|
||
end,\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/shockwave\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"ShockWave\\\",\\\
|
||
description = \\\"Piercing ground wave!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 14,\\\
|
||
move = 8\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
if info.frame == 0 then\\\
|
||
info.x = info.x + info.direction / 2\\\
|
||
end\\\
|
||
info.x = info.x + (3 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 60, info.owner, 10, false, {}, info.safeObjects)\\\
|
||
\\\
|
||
local struckObject = act.object.checkObjectAtPos(info.x, info.y)\\\
|
||
if struckObject then\\\
|
||
info.safeObjects[struckObject] = true\\\
|
||
end\\\
|
||
\\\
|
||
if info.frame > 50 or not act.stage.checkIfSolid(info.x, info.y) then\\\
|
||
return false\\\
|
||
else\\\
|
||
return true\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/buster\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"MegaBuster\\\",\\\
|
||
description = \\\"Fires a weak shot forwards!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 4,\\\
|
||
move = 2\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (4 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, info.player.busterPower or 1, info.owner, 1, true)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.buster, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/shotgun\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Shotgun\\\",\\\
|
||
description = \\\"Hits enemy as well as the panel behind!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (4 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 30, info.owner, 1)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
if struckPlayer or struckObject then\\\
|
||
act.stage.setDamage(info.x, info.y, 30, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 30, info.owner, 1)\\\
|
||
end\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/lilbomb\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"LilBomb\\\",\\\
|
||
description = \\\"Lob a little bomb 2 panels forward!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 5\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
local maxDist = 3\\\
|
||
local maxFrames = 10\\\
|
||
local parabola = math.sin((math.pi / maxFrames) * info.frame) * 2\\\
|
||
if parabola < 0.1 and info.frame > 3 then\\\
|
||
act.stage.setDamage(info.x, info.y - 1, 50, info.owner, 1, false)\\\
|
||
act.stage.setDamage(info.x, info.y, 50, info.owner, 1, false)\\\
|
||
act.stage.setDamage(info.x, info.y + 1, 50, info.owner, 1, false)\\\
|
||
return false\\\
|
||
else\\\
|
||
info.x = info.x + (maxDist / maxFrames) * info.direction\\\
|
||
end\\\
|
||
return true, {{images.cannon, info.x, info.y - parabola}}\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/objectdata/rockcube\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
image = images.rockcube,\\\
|
||
friendlyFire = true, -- can it hit its owner?\\\
|
||
health = 500, -- amount of damage before disintegrating\\\
|
||
maxHealth = 500, -- just a formality\\\
|
||
smackDamage = 200, -- amount of damage it will do if launched at enemy\\\
|
||
doYeet = true, -- whether or not to fly backwards and do smackDamage to target\\\
|
||
delayedTime = 400, -- amount of frames before running delayedFunc()\\\
|
||
delayedFunc = function() -- will run every delayedTime frames\\\
|
||
-- rockcubes do what rock cubes do\\\
|
||
end,\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/supervulcan\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"SuperVulcan\\\",\\\
|
||
description = \\\"Fires twelve shots that damages panel behind!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
if info.frame == 0 then\\\
|
||
info.player.canMove = false\\\
|
||
info.player.canShoot = false\\\
|
||
else\\\
|
||
if info.frame == 12 * 2 + 1 then\\\
|
||
info.player.canMove = true\\\
|
||
info.player.canShoot = true\\\
|
||
info.player.cooldown.shoot = 6\\\
|
||
info.player.cooldown.shoot = 4\\\
|
||
return false\\\
|
||
elseif info.frame % 2 == 0 then\\\
|
||
act.projectile.newProjectile(info.x, info.y, info.player, \\\"vulcan_internal\\\", frame < 12 * 2)\\\
|
||
end\\\
|
||
end\\\
|
||
return true\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/recov300\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Recov300\\\",\\\
|
||
description = \\\"Gives you 300 health!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 2\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.player.health = math.min(info.player.health + 300, info.player.maxHealth)\\\
|
||
return false\\\
|
||
end,\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/crackout\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"CrackOut\\\",\\\
|
||
description = \\\"Destroys panel in front!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
act.stage.crackPanel(info.x + info.direction, info.y, 2)\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/sidegun\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"SideGun\\\",\\\
|
||
description = \\\"Hits enemy as well as panels above and below!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (4 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, 30, info.owner, 1)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
if struckPlayer or struckObject then\\\
|
||
act.stage.setDamage(info.x, info.y, 30, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x, info.y - 1, 30, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x, info.y + 1, 30, info.owner, 1)\\\
|
||
end\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/busterup\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"BusterUp\\\",\\\
|
||
description = \\\"Raises your buster power by 1!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
info.player.busterPower = info.player.busterPower + 1\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/panelshot\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"CrackShot\\\",\\\
|
||
description = \\\"Fires a panel forwards!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
if info.frame == 0 then\\\
|
||
if act.stage.checkIfSolid(info.x + info.direction, info.y) then\\\
|
||
info.panelType = stage.panels[info.y][info.x + info.direction].panelType\\\
|
||
info.panelOwner = stage.panels[info.y][info.x + info.direction].owner\\\
|
||
act.stage.crackPanel(info.x + info.direction, info.y, 2)\\\
|
||
info.x = info.x + info.direction\\\
|
||
else\\\
|
||
return false\\\
|
||
end\\\
|
||
elseif info.panelType then\\\
|
||
info.x = info.x + (3 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, info.altDamage or 60, info.owner, 1, info.noFlinch)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.panel[info.panelType], info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
return {{images.panel[info.panelType], info.x, info.y}}\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/tripleshot\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"TripleShot\\\",\\\
|
||
description = \\\"Fires three panels forwards!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
act.projectile.newProjectile(info.x, info.y - 1, info.player, \\\"panelshot\\\", false, info.altDamage or 100)\\\
|
||
act.projectile.newProjectile(info.x, info.y, info.player, \\\"panelshot\\\", true, info.altDamage or 100)\\\
|
||
act.projectile.newProjectile(info.x, info.y + 1, info.player, \\\"panelshot\\\", false, info.altDamage or 100)\\\
|
||
\\\
|
||
return false\\\
|
||
\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/geddon2\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Geddon2\\\",\\\
|
||
description = \\\"Breaks all panels!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
for y, row in pairs(stage.panels) do\\\
|
||
for x, panel in pairs(row) do\\\
|
||
act.stage.crackPanel(x, y, 2)\\\
|
||
end\\\
|
||
end\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/panelreturn\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"PanelReturn\\\",\\\
|
||
description = \\\"Fixes all of your panels!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
for y, row in pairs(stage.panels) do\\\
|
||
for x, panel in pairs(row) do\\\
|
||
if panel.owner == info.owner then\\\
|
||
act.stage.crackPanel(x, y, -2)\\\
|
||
end\\\
|
||
end\\\
|
||
end\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/longsword\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"LongSword\\\",\\\
|
||
description = \\\"Slash forwards 2 panels!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, 80, info.owner, 1)\\\
|
||
act.stage.setDamage(info.x + info.direction * 2, info.y, 80, info.owner, 1)\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/bigbomb\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"BigBomb\\\",\\\
|
||
description = \\\"Lob a 3x3 grenade 2 panels forward!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 5\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
local maxDist = 3\\\
|
||
local maxFrames = 10\\\
|
||
local parabola = math.sin((math.pi / maxFrames) * info.frame) * 2\\\
|
||
if parabola < 0.1 and info.frame > 3 then\\\
|
||
for y = -1, 1 do\\\
|
||
for x = -1, 1 do\\\
|
||
act.stage.setDamage(info.x + x, info.y + y, 90, info.owner, 1, false)\\\
|
||
end\\\
|
||
end\\\
|
||
return false\\\
|
||
else\\\
|
||
info.x = info.x + (maxDist / maxFrames) * info.direction\\\
|
||
end\\\
|
||
return true, {{images.cannon, info.x, info.y - parabola}}\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/panelgrab\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"PanelGrab\\\",\\\
|
||
description = \\\"Grabs one panel from enemy!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
if info.frame == 0 then\\\
|
||
if info.owner == 1 then\\\
|
||
info.x = 5\\\
|
||
for x = 2, 5 do\\\
|
||
if stage.panels[info.y][x].owner ~= info.owner then\\\
|
||
info.x = x\\\
|
||
break\\\
|
||
end\\\
|
||
end\\\
|
||
else\\\
|
||
info.x = 2\\\
|
||
for x = 5, 2, -1 do\\\
|
||
if stage.panels[info.y][x].owner ~= info.owner then\\\
|
||
info.x = x\\\
|
||
break\\\
|
||
end\\\
|
||
end\\\
|
||
end\\\
|
||
end\\\
|
||
\\\
|
||
act.projectile.newProjectile(info.x, info.y, info.player, \\\"panelgrab_internal\\\")\\\
|
||
\\\
|
||
return false\\\
|
||
\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/cannon\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Cannon\\\",\\\
|
||
description = \\\"Fires a shot forwards!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.x = info.x + (4 / stage.panelWidth) * info.direction\\\
|
||
\\\
|
||
act.stage.setDamage(info.x, info.y, info.altDamage or 40, info.owner, 1, info.noFlinch)\\\
|
||
\\\
|
||
local struckPlayer, struckObject = act.projectile.checkProjectileCollisions(info)\\\
|
||
\\\
|
||
if info.frame > 50 or struckPlayer or struckObject then\\\
|
||
return false\\\
|
||
else\\\
|
||
return true, {{images.cannon, info.x, info.y}}\\\
|
||
end\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/muramasa\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Muramasa\\\",\\\
|
||
description = \\\"Slash for as much damage as you have taken!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 8,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
\\\
|
||
act.stage.setDamage(info.x + info.direction, info.y, math.min(info.player.maxHealth - info.player.health, 1000), info.owner, 1, false)\\\
|
||
\\\
|
||
return false\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/vulcan3\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Vulcan3\\\",\\\
|
||
description = \\\"Fires seven shots that damages panel behind!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 4\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
if info.frame == 0 then\\\
|
||
info.player.canMove = false\\\
|
||
info.player.canShoot = false\\\
|
||
else\\\
|
||
if info.frame == 7 * 2 + 1 then\\\
|
||
info.player.canMove = true\\\
|
||
info.player.canShoot = true\\\
|
||
info.player.cooldown.shoot = 6\\\
|
||
info.player.cooldown.shoot = 4\\\
|
||
return false\\\
|
||
elseif info.frame % 2 == 0 then\\\
|
||
act.projectile.newProjectile(info.x, info.y, info.player, \\\"vulcan_internal\\\", info.frame < 7 * 2)\\\
|
||
end\\\
|
||
end\\\
|
||
return true\\\
|
||
end\\\
|
||
}\",\
|
||
[ \"ccbn-data/chipdata/recov120\" ] = \"local stage, players, objects, projectiles, act, images = ...\\\
|
||
return {\\\
|
||
info = {\\\
|
||
name = \\\"Recov120\\\",\\\
|
||
description = \\\"Gives you 120 health!\\\",\\\
|
||
cooldown = {\\\
|
||
shoot = 6,\\\
|
||
move = 2\\\
|
||
}\\\
|
||
},\\\
|
||
logic = function(info)\\\
|
||
info.player.health = math.min(info.player.health + 120, info.player.maxHealth)\\\
|
||
return false\\\
|
||
end,\\\
|
||
}\",\
|
||
},\
|
||
}")
|
||
if fs.isReadOnly(outputPath) then
|
||
error("Output path is read-only.")
|
||
elseif fs.getFreeSpace(outputPath) <= #archive then
|
||
error("Insufficient space.")
|
||
end
|
||
fs.delete(shell.getRunningProgram()) -- saves space
|
||
for name, contents in pairs(archive.data) do
|
||
stc(colors.lightGray)
|
||
write("'" .. name .. "'...")
|
||
if contents == true then -- indicates empty directory
|
||
fs.makeDir(fs.combine(outputPath, name))
|
||
else
|
||
file = fs.open(fs.combine(outputPath, name), "w")
|
||
if file then
|
||
file.write(contents)
|
||
file.close()
|
||
end
|
||
end
|
||
if file then
|
||
stc(colors.green)
|
||
print("good")
|
||
else
|
||
stc(colors.red)
|
||
print("fail")
|
||
end
|
||
end
|
||
stc(colors.white)
|
||
write("Unpacked to '")
|
||
stc(colors.yellow)
|
||
write(outputPath .. "/")
|
||
stc(colors.white)
|
||
print("'.")
|