2019-03-13 17:57:59 +00:00
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 ) \ \ \
2019-03-13 21:05:50 +00:00
info.x = info.x + ( 4 / stage.panelWidth ) * info.direction \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x , info.y , 20 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 \ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x + info.direction , info.y , 20 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
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 \ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x + info.direction , info.y , 20 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
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 ) \ \ \
2019-03-13 21:05:50 +00:00
info.x = info.x + ( 4 / stage.panelWidth ) * info.direction \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 ) \ \ \
2019-03-13 21:05:50 +00:00
info.x = info.x + ( 4 / stage.panelWidth ) * info.direction \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 \ \ \
2019-03-13 21:05:50 +00:00
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 ) \ \ \
2019-03-13 17:57:59 +00:00
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 = { } , { } \ \ \
\ \ \
2019-03-13 21:05:50 +00:00
-- recommended at 0.1 for netplay, which you'll be doing all the time so yeah\\\
local gameDelayInit = 0.1 \ \ \
\ \ \
2019-03-13 17:57:59 +00:00
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 , \ \ \
2019-03-13 21:05:50 +00:00
paused = false , \ \ \
turnNumber = 0 \ \ \
2019-03-13 17:57:59 +00:00
} \ \ \
\ \ \
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 ( ) \ \ \
2019-03-13 21:05:50 +00:00
term.setCursorPos ( 0.5 + scr_x / 2 - # text / 2 , y or ( scr_y / 2 ) ) \ \ \
2019-03-13 17:57:59 +00:00
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 = { \ \ \
2019-03-13 21:05:50 +00:00
[ 1 ] = { \ \ \
2019-03-13 17:57:59 +00:00
{ \ \ \ " 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 \\ \" }, \\ \
2019-03-13 21:05:50 +00:00
{ \ \ \ " boomer1 \\ \" , \\ \" c \\ \" }, \\ \
2019-03-13 17:57:59 +00:00
{ \ \ \ " 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) \\ \
\ \ \
2019-03-13 21:05:50 +00:00
term.setTextColor ( colors.white ) \ \ \
term.setBackgroundColor ( colors.black ) \ \ \
2019-03-13 17:57:59 +00:00
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 \ \ \
\ \ \
2019-03-13 21:05:50 +00:00
if game.custom == game.customMax and FRAME % 16 <= 12 and not game.inChipSelect then \ \ \
2019-03-13 17:57:59 +00:00
cwrite ( \ \ \ " PUSH ' \\ \" .. revKeys[control.custom]:upper() .. \\ \" '! \\ \" , 2) \\ \
end \ \ \
2019-03-13 21:05:50 +00:00
term.setTextColor ( colors.lightGray ) \ \ \
2019-03-13 17:57:59 +00:00
term.setCursorPos ( 6 , 1 ) \ \ \
2019-03-13 21:05:50 +00:00
term.write ( \ \ \ " CUSTOM \\ \" ) \\ \
term.setTextColor ( colors.white ) \ \ \
term.write ( \ \ \ " [ \\ \" ) \\ \
local barLength = scr_x - 18 \ \ \
2019-03-13 17:57:59 +00:00
if game.custom == game.customMax then \ \ \
2019-03-13 21:05:50 +00:00
term.setTextColor ( colors.gray ) \ \ \
2019-03-13 17:57:59 +00:00
term.setBackgroundColor ( colors.lime ) \ \ \
else \ \ \
2019-03-13 21:05:50 +00:00
term.setTextColor ( colors.gray ) \ \ \
2019-03-13 17:57:59 +00:00
term.setBackgroundColor ( colors.green ) \ \ \
end \ \ \
for i = 1 , barLength do \ \ \
if ( i / barLength ) <= ( game.custom / game.customMax ) then \ \ \
2019-03-13 21:05:50 +00:00
if game.custom == game.customMax then \ \ \
term.write ( \ \ \ " @ \\ \" ) \\ \
else \ \ \
term.write ( \ \ \ " = \\ \" ) \\ \
end \ \ \
2019-03-13 17:57:59 +00:00
else \ \ \
2019-03-13 21:05:50 +00:00
term.setBackgroundColor ( colors.black ) \ \ \
2019-03-13 17:57:59 +00:00
term.write ( \ \ \ " \\ \" ) \\ \
end \ \ \
end \ \ \
2019-03-13 21:05:50 +00:00
term.setTextColor ( colors.white ) \ \ \
term.setBackgroundColor ( colors.black ) \ \ \
2019-03-13 17:57:59 +00:00
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 \ \ \
2019-03-13 21:05:50 +00:00
keysDown = { } \ \ \
miceDown = { } \ \ \
2019-03-13 17:57:59 +00:00
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 \ \ \
2019-03-13 21:05:50 +00:00
cwrite ( \ \ \ " Turn \\ \" .. game.turnNumber .. \\ \" , Select Chips: \\ \" , 3) \\ \
2019-03-13 17:57:59 +00:00
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 \ \ \
2019-03-13 21:05:50 +00:00
render ( ) \ \ \
2019-03-13 17:57:59 +00:00
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 ( ) \ \ \
2019-03-13 21:05:50 +00:00
sleep ( 0.35 ) \ \ \
2019-03-13 17:57:59 +00:00
while true do \ \ \
FRAME = FRAME + 1 \ \ \
\ \ \
if game.inChipSelect then \ \ \
2019-03-13 21:05:50 +00:00
game.turnNumber = game.turnNumber + 1 \ \ \
2019-03-13 17:57:59 +00:00
chipSelectScreen ( ) \ \ \
if isHost then \ \ \
game.custom = 0 \ \ \
local msg \ \ \
2019-03-13 21:05:50 +00:00
render ( ) \ \ \
cwrite ( \ \ \ " Waiting for other player... \\ \" , scr_y - 3) \\ \
\ \ \
transmit ( { \ \ \
gameID = gameID , \ \ \
command = \ \ \ " turn_ready \\ \" , \\ \
pID = you , \ \ \
} ) \ \ \
\ \ \
2019-03-13 17:57:59 +00:00
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 \\ \" , \\ \
2019-03-13 21:05:50 +00:00
pID = 1 , \ \ \
2019-03-13 17:57:59 +00:00
} ) \ \ \
2019-03-13 21:05:50 +00:00
term.clearLine ( ) \ \ \
cwrite ( \ \ \ " READY! \\ \" , scr_y - 3) \\ \
sleep ( 0.5 ) \ \ \
2019-03-13 17:57:59 +00:00
else \ \ \
transmit ( { \ \ \
gameID = gameID , \ \ \
command = \ \ \ " turn_ready \\ \" , \\ \
pID = you , \ \ \
chipQueue = players [ you ] . chipQueue , \ \ \
folder = players [ you ] . folder , \ \ \
} ) \ \ \
2019-03-13 21:05:50 +00:00
render ( ) \ \ \
cwrite ( \ \ \ " Waiting for other player... \\ \" , scr_y - 3) \\ \
2019-03-13 17:57:59 +00:00
repeat \ \ \
msg = receive ( ) \ \ \
msg = type ( msg ) == \ \ \ " table \\ \" and msg or {} \\ \
until ( \ \ \
msg.gameID == gameID and \ \ \
msg.command == \ \ \ " turn_ready \\ \" and \\ \
players [ msg.pID ] \ \ \
) \ \ \
2019-03-13 21:05:50 +00:00
term.clearLine ( ) \ \ \
cwrite ( \ \ \ " READY! \\ \" , scr_y - 3) \\ \
sleep ( 0.5 ) \ \ \
2019-03-13 17:57:59 +00:00
end \ \ \
2019-03-13 21:05:50 +00:00
game.inChipSelect = false \ \ \
2019-03-13 17:57:59 +00:00
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 \ \ \
2019-03-13 21:05:50 +00:00
render ( ) \ \ \
movePlayers ( ) \ \ \
2019-03-13 17:57:59 +00:00
sleep ( gameDelayInit ) \ \ \
2019-03-13 21:05:50 +00:00
game.custom = math.min ( game.customMax , game.custom + 1 ) \ \ \
2019-03-13 17:57:59 +00:00
transmit ( { \ \ \
gameID = gameID , \ \ \
command = \ \ \ " get_state \\ \" , \\ \
players = players , \ \ \
projectiles = projectiles , \ \ \
objects = objects , \ \ \
game = game , \ \ \
stageDamage = stage.damage , \ \ \
stagePanels = stage.panels , \ \ \
id = id \ \ \
} ) \ \ \
2019-03-13 21:05:50 +00:00
reduceCooldowns ( ) \ \ \
2019-03-13 17:57:59 +00:00
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 \ \ \
2019-03-13 21:05:50 +00:00
render ( ) \ \ \
2019-03-13 17:57:59 +00:00
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 \ \ \
\ \ \
2019-03-13 21:05:50 +00:00
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 \ \ \
\ \ \
2019-03-13 17:57:59 +00:00
local titleScreen = function ( ) \ \ \
local menuOptions = { \ \ \
\ \ \ " Start Game \\ \" , \\ \
2019-03-13 21:05:50 +00:00
\ \ \ " How to Play \\ \" , \\ \
2019-03-13 17:57:59 +00:00
\ \ \ " 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 \ \ \
2019-03-13 21:05:50 +00:00
howToPlay ( ) \ \ \
elseif choice == 3 then \ \ \
2019-03-13 17:57:59 +00:00
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 ) \ \ \
\ \ \
2019-03-13 21:05:50 +00:00
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 ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 \ \ \
2019-03-13 21:05:50 +00:00
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 ) \ \ \
2019-03-13 17:57:59 +00:00
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 = { \ \ \
2019-03-13 21:05:50 +00:00
name = \ \ \ " Recov150 \\ \" , \\ \
2019-03-13 17:57:59 +00:00
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 \ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x , info.y , 50 , info.owner , 1 , false ) \ \ \
2019-03-13 17:57:59 +00:00
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 = { \ \ \
2019-03-13 21:05:50 +00:00
name = \ \ \ " Recov200 \\ \" , \\ \
2019-03-13 17:57:59 +00:00
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 ) \ \ \
\ \ \
2019-03-13 21:05:50 +00:00
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 ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 ) \ \ \
2019-03-13 21:05:50 +00:00
info.x = info.x + ( 4 / stage.panelWidth ) * info.direction \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x , info.y , 40 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 \ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x + info.direction , info.y , 40 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
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 \ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x + info.direction , info.y , 40 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
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 ) \ \ \
2019-03-13 21:05:50 +00:00
info.x = info.x + ( 4 / stage.panelWidth ) * info.direction \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x , info.y , 40 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
local struckPlayer , struckObject = act.projectile . checkProjectileCollisions ( info ) \ \ \
\ \ \
if info.frame > 50 or struckPlayer or struckObject then \ \ \
if struckPlayer or struckObject then \ \ \
2019-03-13 21:05:50 +00:00
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 ) \ \ \
2019-03-13 17:57:59 +00:00
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 = { \ \ \
2019-03-13 21:05:50 +00:00
name = \ \ \ " Recov80 \\ \" , \\ \
2019-03-13 17:57:59 +00:00
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 ) \ \ \
2019-03-13 21:05:50 +00:00
info.x = info.x + ( 4 / stage.panelWidth ) * info.direction \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x , info.y , 30 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 \ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x + info.direction , info.y , 30 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
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 \ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x + info.direction , info.y , 30 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
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 ) \ \ \
\ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x + info.direction , info.y , 80 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
return false \ \ \
end \ \ \
} \ " , \
[ \ " ccbn-data/chipdata/recov50 \" ] = \" local stage, players, objects, projectiles, act, images = ... \\ \
return { \ \ \
info = { \ \ \
2019-03-13 21:05:50 +00:00
name = \ \ \ " Recov50 \\ \" , \\ \
2019-03-13 17:57:59 +00:00
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 \ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x , info.y , 80 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
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 ) \ \ \
2019-03-13 21:05:50 +00:00
info.x = info.x + ( 4 / stage.panelWidth ) * info.direction \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x , info.y , 30 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 \ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x + x , info.y + y , 30 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
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 ) \ \ \
\ \ \
2019-03-13 21:05:50 +00:00
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 ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 = { \ \ \
2019-03-13 21:05:50 +00:00
name = \ \ \ " Recov30 \\ \" , \\ \
2019-03-13 17:57:59 +00:00
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 ) \ \ \
2019-03-13 21:05:50 +00:00
info.x = info.x + ( 4 / stage.panelWidth ) * info.direction \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 ) \ \ \
2019-03-13 21:05:50 +00:00
info.x = info.x + ( 4 / stage.panelWidth ) * info.direction \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x , info.y , 30 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
local struckPlayer , struckObject = act.projectile . checkProjectileCollisions ( info ) \ \ \
\ \ \
if info.frame > 50 or struckPlayer or struckObject then \ \ \
if struckPlayer or struckObject then \ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x , info.y , 30 , info.owner , 1 ) \ \ \
act.stage . setDamage ( info.x + info.direction , info.y , 30 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
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 \ \ \
2019-03-13 21:05:50 +00:00
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 ) \ \ \
2019-03-13 17:57:59 +00:00
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 = { \ \ \
2019-03-13 21:05:50 +00:00
name = \ \ \ " Recov300 \\ \" , \\ \
2019-03-13 17:57:59 +00:00
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 ) \ \ \
2019-03-13 21:05:50 +00:00
info.x = info.x + ( 4 / stage.panelWidth ) * info.direction \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x , info.y , 30 , info.owner , 1 ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
local struckPlayer , struckObject = act.projectile . checkProjectileCollisions ( info ) \ \ \
\ \ \
if info.frame > 50 or struckPlayer or struckObject then \ \ \
if struckPlayer or struckObject then \ \ \
2019-03-13 21:05:50 +00:00
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 ) \ \ \
2019-03-13 17:57:59 +00:00
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 \ \ \
2019-03-13 21:05:50 +00:00
info.panelOwner = stage.panels [ info.y ] [ info.x + info.direction ] . owner \ \ \
2019-03-13 17:57:59 +00:00
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 ) \ \ \
\ \ \
2019-03-13 21:05:50 +00:00
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 ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 \ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x + x , info.y + y , 90 , info.owner , 1 , false ) \ \ \
2019-03-13 17:57:59 +00:00
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 ) \ \ \
2019-03-13 21:05:50 +00:00
info.x = info.x + ( 4 / stage.panelWidth ) * info.direction \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 ) \ \ \
\ \ \
2019-03-13 21:05:50 +00:00
act.stage . setDamage ( info.x + info.direction , info.y , math.min ( info.player . maxHealth - info.player . health , 1000 ) , info.owner , 1 , false ) \ \ \
2019-03-13 17:57:59 +00:00
\ \ \
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 = { \ \ \
2019-03-13 21:05:50 +00:00
name = \ \ \ " Recov120 \\ \" , \\ \
2019-03-13 17:57:59 +00:00
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 ( " '. " )