├── .gitignore ├── palette.aseprite ├── screenshot.png ├── spritesheet.png ├── void-protocol.lua.png ├── void-protocol.p8.png ├── dist ├── itch.io │ ├── banner.png │ └── bg-stars.png └── index.html ├── scripts ├── utilities │ ├── palette.lua │ ├── audio.lua │ ├── menu.lua │ ├── text.lua │ ├── tables.lua │ ├── logging.lua │ ├── timers.lua │ ├── sprites.lua │ └── animation.lua ├── entities │ ├── wall.lua │ ├── target.lua │ ├── level_text.lua │ ├── enemies │ │ ├── bubble.lua │ │ ├── bubbler.lua │ │ └── diver.lua │ ├── gate_with_button.lua │ ├── breach.lua │ ├── portal.lua │ ├── particle.lua │ ├── button.lua │ ├── star.lua │ ├── screen.lua │ ├── enemy.lua │ ├── space.lua │ ├── gate.lua │ ├── projectile.lua │ ├── player.lua │ └── dialog.lua ├── object.lua ├── scenes │ ├── splash.lua │ ├── credits.lua │ ├── gameover.lua │ ├── win.lua │ ├── transition.lua │ ├── level.lua │ ├── title.lua │ ├── tutorial.lua │ └── breach.lua ├── main.lua └── entity.lua ├── data └── levels.lua ├── README.md └── void-protocol.p8 /.gitignore: -------------------------------------------------------------------------------- 1 | /media 2 | log.p8l 3 | *.zip -------------------------------------------------------------------------------- /palette.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinthompson/void-protocol-p8/HEAD/palette.aseprite -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinthompson/void-protocol-p8/HEAD/screenshot.png -------------------------------------------------------------------------------- /spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinthompson/void-protocol-p8/HEAD/spritesheet.png -------------------------------------------------------------------------------- /void-protocol.lua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinthompson/void-protocol-p8/HEAD/void-protocol.lua.png -------------------------------------------------------------------------------- /void-protocol.p8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinthompson/void-protocol-p8/HEAD/void-protocol.p8.png -------------------------------------------------------------------------------- /dist/itch.io/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinthompson/void-protocol-p8/HEAD/dist/itch.io/banner.png -------------------------------------------------------------------------------- /dist/itch.io/bg-stars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinthompson/void-protocol-p8/HEAD/dist/itch.io/bg-stars.png -------------------------------------------------------------------------------- /scripts/utilities/palette.lua: -------------------------------------------------------------------------------- 1 | function set_palette() 2 | pal() 3 | pal(1, 128, 1) 4 | pal(4, 130, 1) 5 | pal(13, 141, 1) 6 | palt(0, false) 7 | palt(11, true) 8 | palt(15, true) 9 | end -------------------------------------------------------------------------------- /scripts/utilities/audio.lua: -------------------------------------------------------------------------------- 1 | crossfade_music = function(song, duration) 2 | duration = duration or 500 3 | factor = duration / 1000 4 | 5 | music(-1, duration) 6 | wait(factor * 60, function() 7 | music(song, duration / 2) 8 | end) 9 | end -------------------------------------------------------------------------------- /scripts/entities/wall.lua: -------------------------------------------------------------------------------- 1 | entities.wall = entity:constructor({ 2 | type = "wall", 3 | persist = true, 4 | solid = true, 5 | 6 | x = 0, 7 | 8 | hitbox = { 9 | x = 0, 10 | y = 0, 11 | width = 7, 12 | height = 127, 13 | }, 14 | }) -------------------------------------------------------------------------------- /scripts/entities/target.lua: -------------------------------------------------------------------------------- 1 | entities.target = entity:constructor({ 2 | type = "target", 3 | solid = true, 4 | layer = 4, 5 | 6 | hitbox = { 7 | x = 0, 8 | y = 0, 9 | width = 16, 10 | height = 6, 11 | }, 12 | 13 | draw = function(self) 14 | spr(9, self.x, self.y, 2, 1) 15 | end, 16 | }) -------------------------------------------------------------------------------- /scripts/object.lua: -------------------------------------------------------------------------------- 1 | object = { 2 | new = function(self, table) 3 | return self:constructor(table) 4 | end, 5 | 6 | constructor = function(self, table) 7 | self.__index = self 8 | return setmetatable(table or {}, self) 9 | end, 10 | 11 | init = function(self) 12 | end, 13 | 14 | update = function(self) 15 | end, 16 | 17 | draw = function(self) 18 | end 19 | } -------------------------------------------------------------------------------- /scripts/utilities/menu.lua: -------------------------------------------------------------------------------- 1 | function set_menu_items(items) 2 | items = items or {} 3 | 4 | for i=1,5 do 5 | menuitem(i) 6 | end 7 | 8 | for item in all(items) do 9 | menuitem(item[1], item[2], item[3]) 10 | end 11 | 12 | menuitem(5, debug and "debug off" or "debug on", function() 13 | debug = not debug 14 | set_menu_items(items) 15 | end) 16 | end -------------------------------------------------------------------------------- /scripts/utilities/text.lua: -------------------------------------------------------------------------------- 1 | function print_centered(str, y, c) 2 | y = y or 64 3 | c = c or 7 4 | local x = 64-flr((#str * 4) / 2) 5 | print(str, x, y, c) 6 | end 7 | 8 | function pad(string, length) 9 | local string = tostr(string) 10 | local string_length = #string 11 | for i=1, length - string_length do 12 | string = "0" .. string 13 | end 14 | 15 | return string 16 | end -------------------------------------------------------------------------------- /data/levels.lua: -------------------------------------------------------------------------------- 1 | levels = { 2 | { 3 | "bubble,bubble,bubble", 4 | "bubble,bubble,diver", 5 | "bubble,bubble,diver", 6 | }, 7 | 8 | { 9 | "bubble,bubble,diver", 10 | "diver,diver,bubble", 11 | "bubbler,diver,bubble", 12 | }, 13 | 14 | { 15 | "bubbler,diver,bubble", 16 | "bubbler,bubbler,bubble", 17 | "bubbler,bubbler,diver,diver,bubble", 18 | } 19 | } -------------------------------------------------------------------------------- /scripts/entities/level_text.lua: -------------------------------------------------------------------------------- 1 | entities.level_text = entity:constructor({ 2 | y = 24, 3 | height = 0, 4 | text = "sector alpha-1", 5 | layer = 70, 6 | 7 | draw = function(self) 8 | local y = self.y + 8 - (self.height / 2) 9 | rect(0, y, 128, y + self.height, 6) 10 | rectfill(0, y + 1, 128, y + self.height - 1, 7) 11 | if (self.height >= 4) rect(-1, y + 2, 129, y + self.height - 2, 0) 12 | if (self.height >= 12) print_centered(self.text, y + 6, 0) 13 | end 14 | }) -------------------------------------------------------------------------------- /scripts/utilities/tables.lua: -------------------------------------------------------------------------------- 1 | -- quicksort by JWinslow23 2 | 3 | function quick_sort_hp(tbl,lo,hi) 4 | lo,hi=lo or 1,hi or #tbl 5 | if lo=p 9 | repeat j-=1 until tbl[j].layer<=p 10 | if (i>=j) break 11 | tbl[i],tbl[j]=tbl[j],tbl[i] 12 | end 13 | quick_sort_hp(tbl,lo,j) 14 | quick_sort_hp(tbl,j+1,hi) 15 | end 16 | end -------------------------------------------------------------------------------- /scripts/utilities/logging.lua: -------------------------------------------------------------------------------- 1 | function log(any, overwrite) 2 | printh(tostr(any), logfile or "log", overwrite) 3 | end 4 | 5 | _tostr = tostr 6 | 7 | function tostr(any, prefix) 8 | prefix = prefix or "" 9 | 10 | if type(any) == "table" then 11 | local str="{" 12 | local add_comma=false 13 | 14 | for k,v in pairs(any) do 15 | str=str..(add_comma and "," or "") 16 | str=str.."\n "..prefix..k.." = "..tostr(v, " ") 17 | add_comma=true 18 | end 19 | 20 | return str.."\n"..prefix.."}" 21 | else 22 | return _tostr(any) 23 | end 24 | end -------------------------------------------------------------------------------- /scripts/entities/enemies/bubble.lua: -------------------------------------------------------------------------------- 1 | entities.bubble = entities.enemy:constructor({ 2 | attack = function(self) 3 | self.vx = 0 4 | self.vy = 0 5 | self.y += sin(t()) / 4 6 | 7 | if player.health > 0 and player.control then 8 | self.vx = self.x == player.x and 0 or sgn(player.x - self.x) / 2 9 | self.vy = self.y == player.y and 0 or sgn(player.y - self.y) / 2 10 | end 11 | end, 12 | 13 | draw = function(self) 14 | circfill(self.x + 8, self.y + 8, 7, 0) 15 | circ(self.x + 4, self.y + 4, 1, 7) 16 | circ(self.x + 8, self.y + 8, 7, 8) 17 | end 18 | }) -------------------------------------------------------------------------------- /scripts/utilities/timers.lua: -------------------------------------------------------------------------------- 1 | timers = object:new({ 2 | pool = {}, 3 | 4 | new = function(self, frames, callback) 5 | local coroutine = cocreate(function() 6 | for i = frames, 0, -1 do 7 | i -= 1 8 | yield() 9 | end 10 | 11 | callback() 12 | end) 13 | 14 | add(self.pool, coroutine) 15 | end, 16 | 17 | update = function(self) 18 | for coroutine in all(self.pool) do 19 | if costatus(coroutine) != "dead" then 20 | coresume(coroutine) 21 | else 22 | del(self.pool, coroutine) 23 | end 24 | end 25 | end 26 | }) -------------------------------------------------------------------------------- /scripts/entities/gate_with_button.lua: -------------------------------------------------------------------------------- 1 | entities.gate_with_button = entities.gate:constructor({ 2 | init = function(self) 3 | entities.gate.init(self) 4 | 5 | self.button = entities.button:new({ 6 | layer = 63, 7 | x = self.right_door.x + 36, 8 | y = self.y + 10, 9 | }) 10 | end, 11 | 12 | update = function(self) 13 | entities.gate.update(self) 14 | 15 | self.button.x = self.right_door.x + 36 16 | self.button.y = self.y + 10 17 | end, 18 | 19 | on_destroy = function(self) 20 | entities.gate.on_destroy(self) 21 | 22 | self.button:destroy() 23 | end, 24 | }) -------------------------------------------------------------------------------- /scripts/utilities/sprites.lua: -------------------------------------------------------------------------------- 1 | function mapr(x,y,rot,mx,my,w,flip,scale) 2 | flip = flip or false 3 | scale = scale or 1 4 | w+=.8 5 | local halfw, cx = scale*-w/2, mx + w/2 -.4 6 | local cs, ss, cy = cos(rot)/scale, -sin(rot)/scale, my-halfw/scale-.4 7 | local sx, sy, hx, hy = cx + cs*halfw, cy - ss*halfw, w*(flip and -4 or 4)*scale, w*4*scale 8 | 9 | for py = y-hy, y+hy do 10 | tline(x-hx, py, x+hx, py, sx + ss*halfw, sy + cs*halfw, cs/8, -ss/8) 11 | halfw+=1/8 12 | end 13 | end 14 | 15 | function transparent(func) 16 | if flr((t() * 1000)) % 2 == 0 then 17 | func() 18 | end 19 | end -------------------------------------------------------------------------------- /scripts/entities/breach.lua: -------------------------------------------------------------------------------- 1 | entities.breach = entity:constructor({ 2 | type = "breach", 3 | x = 32, 4 | y = 12, 5 | 6 | hitbox = { 7 | x = 0, 8 | y = 0, 9 | width = 64, 10 | height = 48, 11 | }, 12 | 13 | draw = function(self) 14 | spr(102, self.x + rnd(2), self.y + rnd(2), 8, 6) 15 | end, 16 | 17 | on_destroy = function(self) 18 | breach = nil 19 | 20 | for i = 1, 60 do 21 | entities.particle:new({ 22 | x = self.x + rnd(64), 23 | y = self.y + rnd(48), 24 | size = rnd({0,1}), 25 | vx = rnd(4) - 2, 26 | vy = rnd(4), 27 | frames = flr(rnd(240)), 28 | scheme = 2 29 | }) 30 | end 31 | end 32 | }) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Void Protocol 2 | 3 | ![](https://github.com/kevinthompson/void-protocol-p8/blob/master/screenshot.png) 4 | 5 | ----- 6 | 7 | This branch is for ongoing development of Void Protocol. If you're interested 8 | in the version that was submitted to the Eggplant Show community game jam, 9 | [check out the `eggplant-game-jam-02-2021` branch](https://github.com/kevinthompson/void-protocol-p8/tree/eggplant-game-jam-02-2021). 10 | 11 | ----- 12 | 13 | Fight your way through nine levels, firing and collecting your projectile. 14 | The game is available to play at [https://kevinthompson.itch.io/void-protocol](https://kevinthompson.itch.io/void-protocol) or [on the PICO-8 forums](https://www.lexaloffle.com/bbs/?tid=42752). -------------------------------------------------------------------------------- /scripts/entities/portal.lua: -------------------------------------------------------------------------------- 1 | entities.portal = entity:constructor({ 2 | type = "portal", 3 | 4 | solid = false, 5 | layer = 35, 6 | y = -8, 7 | offset = 0, 8 | direction = "down", 9 | 10 | hitbox = { 11 | x = 16, 12 | y = 8, 13 | width = 96, 14 | height = 10 15 | }, 16 | 17 | draw = function(self) 18 | local x, y, offset = self.x, self.y, self.offset 19 | local overlay_y = self.direction == "down" and -4 or 4 20 | 21 | ovalfill(x, y - offset + 9, x + 127, y + 6 + offset, 0) 22 | transparent(function() 23 | for i = 0, 2 do 24 | oval(x, y + i - offset + 9, x + 127, y + 6 - i + offset, 7 - i) 25 | end 26 | end) 27 | 28 | rectfill(x, y + overlay_y, x + 127, y + 12 + overlay_y, 0) 29 | end 30 | }) -------------------------------------------------------------------------------- /scripts/entities/particle.lua: -------------------------------------------------------------------------------- 1 | entities.particle = entity:constructor({ 2 | size = 1, 3 | speed = 1, 4 | frames = 60, 5 | frame = 0, 6 | layer = -1, 7 | vx = 0, 8 | vy = space.speed, 9 | persist = true, 10 | schemes = {{7,6,5}, {8,2,4}}, 11 | scheme = 1, 12 | 13 | init = function(self) 14 | self.color = self.schemes[self.scheme][1] 15 | end, 16 | 17 | update = function(self) 18 | self:move() 19 | self.frame += 1 20 | if (self.frame > self.frames * .33) self.color = self.schemes[self.scheme][2] 21 | if (self.frame > self.frames * .66) self.color = self.schemes[self.scheme][3] 22 | if (self.frame >= self.frames) self:destroy() 23 | end, 24 | 25 | draw = function(self) 26 | circfill(self.x, self.y, self.size, self.color) 27 | end 28 | }) -------------------------------------------------------------------------------- /scripts/entities/button.lua: -------------------------------------------------------------------------------- 1 | entities.button = entity:constructor({ 2 | type = "button", 3 | solid = true, 4 | layer = 63, 5 | 6 | hitbox = { 7 | x = 0, 8 | y = 0, 9 | width = 24, 10 | height = 6, 11 | }, 12 | 13 | init = function(self) 14 | local this = self 15 | 16 | self.target = entities.target:new({ 17 | x = self.x + 4, 18 | y = self.y + 5, 19 | on_hit = function(self) 20 | self:flash(5) 21 | this:on_hit() 22 | sfx(21) 23 | end 24 | }) 25 | end, 26 | 27 | update = function(self) 28 | self.target.x = self.x + 4 29 | self.target.y = self.y + 5 30 | end, 31 | 32 | draw = function(self) 33 | spr(6, self.x, self.y, 3, 1) 34 | end, 35 | 36 | on_destroy = function(self) 37 | self.target:destroy() 38 | end 39 | }) -------------------------------------------------------------------------------- /scripts/entities/star.lua: -------------------------------------------------------------------------------- 1 | entities.star = entity:constructor({ 2 | layer = -1, 3 | persist = true, 4 | color = 5, 5 | 6 | init = function(self) 7 | self.x = flr(rnd(127)) 8 | self.y = flr(rnd(148) - 20) 9 | self.speed = rnd(6) 10 | end, 11 | 12 | update = function(self) 13 | local mx = player and (player.vx * .05) or 0 14 | local my = player and (player.vy * -.1) or 0 15 | 16 | self.x -= mx * self.speed 17 | self.y += (self.speed * space.speed) + (my * self.speed) 18 | 19 | if self.y > 128 then 20 | self.x = flr(rnd(127)) 21 | self.y = -20 22 | end 23 | end, 24 | 25 | draw = function(self) 26 | line( 27 | self.x, 28 | self.y, 29 | self.x, 30 | self.y - flr(self.speed * space.speed / 2), 31 | self.color 32 | ) 33 | end 34 | }) -------------------------------------------------------------------------------- /scripts/entities/enemies/bubbler.lua: -------------------------------------------------------------------------------- 1 | entities.bubbler = entities.enemy:constructor({ 2 | health = 3, 3 | bubble_timer = 180, 4 | exclusive = true, 5 | vx = 0.75, 6 | vy = 0.75, 7 | sprite = 80, 8 | bubbles = {}, 9 | 10 | init = function(self) 11 | self.bubbles = {} 12 | end, 13 | 14 | attack = function(self) 15 | if self.bubble_timer <= 0 and player.health > 0 then 16 | if #self.bubbles < 3 then 17 | local bubbler = self 18 | local bubble = entities.bubble:new({ 19 | x = self.x, 20 | y = self.y, 21 | 22 | on_destroy = function(self) 23 | del(bubbler.bubbles, self) 24 | end 25 | }) 26 | 27 | add(enemies, bubble) 28 | add(self.bubbles, bubble) 29 | end 30 | 31 | self.bubble_timer = 180 32 | else 33 | self.bubble_timer -= 1 34 | end 35 | end, 36 | }) -------------------------------------------------------------------------------- /scripts/scenes/splash.lua: -------------------------------------------------------------------------------- 1 | scenes.splash = object:new({ 2 | init = function(self) 3 | wait(120, function() 4 | load_scene "title" 5 | end) 6 | 7 | music(0, 2000) 8 | end, 9 | 10 | update = function(self) 11 | if (btnp(5)) then 12 | load_scene "title" 13 | end 14 | end, 15 | 16 | draw = function(self) 17 | line(50, 64, 77, 64, 2) 18 | line(51, 65, 76, 65) 19 | 20 | for i = 0, 5 do 21 | local j = i * 2 22 | line(52 + j, 66 + i, 75 - j, 66 + i, 2) 23 | rectfill(52 + j, 46 - i, 75 - j, 65 + i, 8) 24 | end 25 | 26 | rect(51, 47, 76, 64, 8) 27 | rectfill(50, 48, 77, 63) 28 | rectfill(56, 51, 60, 60, 7) 29 | 30 | for i = 0, 4 do 31 | line(63 + i, 55 - i, 68 + i, 55 - i) 32 | line(63 + i, 56 + i, 68 + i, 56 + i) 33 | end 34 | 35 | ? "@", 36, 80, 6 36 | ? "kevinthompson", 41, 80, 7 37 | end 38 | }) -------------------------------------------------------------------------------- /scripts/scenes/credits.lua: -------------------------------------------------------------------------------- 1 | scenes.credits = object:new({ 2 | init = function(self) 3 | player:animate({ x = 52, y = 76 }, 60, easeoutovershoot) 4 | entities.gate_with_button:new() 5 | end, 6 | 7 | update = function(self) 8 | if btnp(5) then 9 | load_scene "title" 10 | end 11 | end, 12 | 13 | draw = function(self) 14 | local credits = { 15 | { "art code sfx", "@kevinthompson" }, 16 | { "music", "@gruber_music" } 17 | } 18 | 19 | local offset = 0 20 | local origin = 48 - ((#credits - 1) * 24) 21 | 22 | for credit in all(credits) do 23 | print_centered(credit[1], origin + offset, 5) 24 | print_centered(credit[2], origin + offset + 8, 7) 25 | offset += 24 26 | end 27 | 28 | print_centered("/ /", 24, 6) 29 | print_centered("return to title", 108, 7) 30 | spr(11, 24, 108) 31 | spr(11, 95, 108, 1, 1, true) 32 | end, 33 | }) -------------------------------------------------------------------------------- /scripts/scenes/gameover.lua: -------------------------------------------------------------------------------- 1 | scenes.gameover = object:new({ 2 | init = function(self) 3 | crossfade_music(15) 4 | player:disable() 5 | player.iframes = 60 6 | player:animate({ y = 144 }, 60, linear, function() 7 | if (player.projectile) player.projectile:destroy() 8 | end) 9 | 10 | input_enabled = false 11 | level_text = entities.level_text:new { text = "mission failed" } 12 | level_text:animate({ height = 16 }, 15, easeoutquad) 13 | 14 | wait(120, function() 15 | input_enabled = true 16 | end) 17 | end, 18 | 19 | update = function(self) 20 | if input_enabled and btnp(5) then 21 | input_enabled = false 22 | crossfade_music(0) 23 | wait(60, function() 24 | load_scene "title" 25 | end) 26 | end 27 | end, 28 | 29 | draw = function(self) 30 | if input_enabled then 31 | print_centered("return to title", 108, 7) 32 | spr(11, 24, 108) 33 | spr(11, 95, 108, 1, 1, true) 34 | end 35 | end, 36 | }) -------------------------------------------------------------------------------- /scripts/entities/enemies/diver.lua: -------------------------------------------------------------------------------- 1 | entities.diver = entities.enemy:constructor({ 2 | mode = "seek", 3 | health = 2, 4 | exclusive = true, 5 | 6 | init = function(self) 7 | self.vx = 0.5 * rnd({ -1, 1 }) 8 | self.oy = self.y 9 | end, 10 | 11 | attack = function(self) 12 | if self.mode == "seek" and player.control and self.x + 8 > player.x + 4 and self.x + 8 < player.x + 20 then 13 | self.y += sin(t()) 14 | self.mode = "windup" 15 | self.vx = 0 16 | self.vy = -0.2 17 | elseif self.mode == "windup" and self.y < self.oy - 5 then 18 | self.mode = "dive" 19 | self.vy = 4 20 | elseif self.mode == "dive" and self.y > 104 then 21 | self.mode = "return" 22 | self.vy = -1 23 | elseif self.mode == "return" and self.y <= self.oy then 24 | self.y = self.oy 25 | self.vx = 0.5 26 | self.vy = 0 27 | self.mode = "seek" 28 | end 29 | end, 30 | 31 | on_hit = function(self, other) 32 | entities.enemy.on_hit(self, other) 33 | 34 | if other.type == "wall" then 35 | self.vy = -0.5 36 | end 37 | end 38 | }) -------------------------------------------------------------------------------- /scripts/entities/screen.lua: -------------------------------------------------------------------------------- 1 | screen = entity:new({ 2 | persist = true, 3 | offset = 0, 4 | layer = 100, 5 | 6 | init = function() 7 | entities.wall:new({ x = -8 }) 8 | entities.wall:new({ x = 128 }) 9 | entities.wall:new({ hitbox = { x = 0, y = -8, width = 128, height = 7 }}) 10 | entities.wall:new({ hitbox = { x = 0, y = 128, width = 128, height = 7 }}) 11 | end, 12 | 13 | update = function(self) 14 | local fade = 0.95 15 | 16 | self.offset *= fade 17 | if self.offset<0.05 then 18 | self.offset=0 19 | end 20 | 21 | if (flash_frames > 0) flash_frames -= 1 22 | end, 23 | 24 | draw = function(self) 25 | local offset_x = (16 - rnd(32)) * self.offset 26 | local offset_y = (16 - rnd(32)) * self.offset 27 | 28 | camera(offset_x,offset_y) 29 | 30 | if flash_frames > 0 then 31 | cls(flash_color) 32 | end 33 | end, 34 | 35 | flash = function(self, color, frames) 36 | flash_frames = frames or 5 37 | flash_color = color or 7 38 | end, 39 | 40 | shake = function(self, amount) 41 | self.offset = mid(0, self.offset + amount, 1) 42 | end 43 | }) -------------------------------------------------------------------------------- /scripts/entities/enemy.lua: -------------------------------------------------------------------------------- 1 | entities.enemy = entity:constructor({ 2 | type = "enemy", 3 | exclusive = false, 4 | 5 | health = 1, 6 | iframes = 0, 7 | max_iframes = 5, 8 | sprite = 48, 9 | 10 | hitbox = { 11 | x = 2, 12 | y = 2, 13 | width = 12, 14 | height = 12 15 | }, 16 | 17 | update = function(self) 18 | self.iframes = mid(0, self.iframes - 1, self.max_iframes) 19 | if (player.control) self:attack() 20 | self:move_and_collide(function(other, axis) 21 | if other == player then 22 | other:hit(self) 23 | elseif other.solid then 24 | if (axis == "x") self.vx *= -1 25 | if (axis == "y") self.vy *= -1 26 | end 27 | end) 28 | end, 29 | 30 | attack = function(self) 31 | end, 32 | 33 | draw = function(self) 34 | sspr((self.sprite % 16) * 8, (self.sprite \ 16) * 8, 16, 16, self.x, self.y + sin(t() * 2) * 2, 16, 16 - sin(t() * 2) * 2) 35 | end, 36 | 37 | on_hit = function(self) 38 | if self.iframes == 0 then 39 | sfx(24 - min(self.health, 3)) 40 | self:flash(5) 41 | self.health -= 1 42 | self.iframes = self.max_iframes 43 | 44 | if self.health == 0 then 45 | self:destroy() 46 | end 47 | end 48 | end, 49 | 50 | destroy = function(self) 51 | for i = 1, 5 do 52 | entities.particle:new({ 53 | size = rnd(3), 54 | x = self.x + 4 + rnd(8), 55 | y = self.y + 4 + rnd(8), 56 | vx = rnd(3) - 1.5, 57 | vy = -0.5 - rnd(1), 58 | scheme = 2, 59 | }) 60 | end 61 | 62 | del(enemies, self) 63 | entity.destroy(self) 64 | end 65 | }) -------------------------------------------------------------------------------- /scripts/scenes/win.lua: -------------------------------------------------------------------------------- 1 | scenes.win = object:new({ 2 | init = function(self) 3 | player:disable() 4 | if (ending != "eggplant") then 5 | player:animate({ x = 52, y = 72 }, 60, easeoutquad) 6 | else 7 | projectile.persist = false 8 | end 9 | 10 | input_enabled = false 11 | display_time = false 12 | 13 | local word = "contained" 14 | if (ending == "charged") word = "transmuted" 15 | if (ending == "eggplant") word = "destabilized" 16 | 17 | level_text = entities.level_text:new({ text = "breach " .. word .. "!" }) 18 | level_text:animate({ height = 24 }, 15, easeoutquad, function() 19 | display_time = true 20 | end) 21 | 22 | wait(120, function() 23 | input_enabled = true 24 | end) 25 | end, 26 | 27 | update = function(self) 28 | if input_enabled and btnp(5) then 29 | load_scene "title" 30 | if (ending == "eggplant") then 31 | crossfade_music(0) 32 | end 33 | end 34 | end, 35 | 36 | draw = function(self) 37 | if input_enabled then 38 | if ending == "eggplant" then 39 | pal(8,7) 40 | pal(2,5) 41 | end 42 | 43 | print_centered("return to title", 108, 7) 44 | spr(11, 24, 108) 45 | spr(11, 95, 108, 1, 1, true) 46 | 47 | set_palette() 48 | end 49 | 50 | if display_time then 51 | local total_time = end_time - start_time 52 | local minutes = total_time \ 60 53 | local seconds = flr(total_time % 60) 54 | local ms = flr((total_time % 1) * 1000) 55 | print_centered("total time: " .. pad(minutes, 2) .. ":" .. pad(seconds, 2) .. "." .. pad(ms, 3), 34, 5) 56 | end 57 | end, 58 | }) -------------------------------------------------------------------------------- /scripts/scenes/transition.lua: -------------------------------------------------------------------------------- 1 | scenes.transition = object:new({ 2 | init = function(self) 3 | local exit_gate_class 4 | 5 | if previous_scene != scenes.title then 6 | for e in all(entity.pool) do 7 | if e.type == "projectile" and e != player.projectile then 8 | e:animate({ y = 132 }, 30, linear, function() 9 | e:destroy() 10 | end) 11 | end 12 | end 13 | end 14 | 15 | player:disable() 16 | space:animate({ speed = 5 }, 30, easeinquad) 17 | space:spawn_streaks() 18 | 19 | if previous_scene == scenes.tutorial 20 | or previous_scene == scenes.title then 21 | exit_gate_class = "gate_with_button" 22 | else 23 | exit_gate_class = "gate" 24 | end 25 | 26 | gate = entities[exit_gate_class]:new({ is_open = previous_scene != scenes.title }) 27 | if (previous_scene == scenes.title) gate:open() 28 | gate:animate({ y = 144 }, 30, easeoutquad) 29 | 30 | if player.y < 32 then 31 | player:animate({ x = 52, y = 88 }, 60, easeinoutquad) 32 | else 33 | player:animate({ x = 52, y = 48 }, 20, easeinoutquad, function() 34 | player:animate({ x = 52, y = 88 }, 30, easeinoutquad) 35 | end) 36 | end 37 | 38 | local prefixes = { "alpha", "beta", "charlie", "delta" } 39 | local level_name = "sector "..prefixes[level_id] 40 | 41 | if level_id > #levels[world] then 42 | level_name = "breach" 43 | crossfade_music(17) 44 | end 45 | 46 | level_text = entities.level_text:new({ text = level_name }) 47 | level_text:animate({ height = 16 }, 15, easeoutquad) 48 | 49 | wait(90, function() 50 | level_text:animate({ height = 0 }, 15, easeoutquad, function() 51 | load_scene(level_id > #levels[world] and "breach" or "level") 52 | end) 53 | end) 54 | end, 55 | }) -------------------------------------------------------------------------------- /scripts/main.lua: -------------------------------------------------------------------------------- 1 | poke(0x5f2e,1) 2 | cartdata "kevinthompson_void_protocol_0" 3 | noop = function() end 4 | 5 | -- progress 6 | tutorial_complete = dget(0) == 1 7 | 8 | -- data structures 9 | scenes = {} 10 | entities = {} 11 | 12 | -- initial values 13 | start_time = t() 14 | end_time = t() 15 | flash_frames = 0 16 | flash_color = 7 17 | world = 1 18 | 19 | function _init() 20 | set_palette() 21 | load_scene "splash" 22 | end 23 | 24 | function _update60() 25 | quick_sort_hp(entity.pool) 26 | entity.all "update" 27 | current_scene:update() 28 | animation:update() 29 | timers:update() 30 | end 31 | 32 | function _draw() 33 | cls() 34 | entity.all "draw" 35 | current_scene:draw() 36 | 37 | --[[ 38 | if debug then 39 | for e in all (entity.pool) do 40 | if e.hitbox then 41 | rect( 42 | e.x + e.hitbox.x, 43 | e.y + e.hitbox.y, 44 | e.x + e.hitbox.x + e.hitbox.width, 45 | e.y + e.hitbox.y + e.hitbox.height, 46 | 10 47 | ) 48 | end 49 | end 50 | end 51 | --]] 52 | end 53 | 54 | -- helpers 55 | 56 | function say(text, callback) 57 | dialog:queue(text, callback) 58 | end 59 | 60 | function load_scene(name) 61 | next_scene = scenes[name] 62 | 63 | if current_scene != next_scene then 64 | previous_scene = current_scene 65 | 66 | timers.pool = {} 67 | dialog:reset() 68 | 69 | if next_scene != scenes.gameover then 70 | for entity in all(entity.pool) do 71 | if (not entity.persist) entity:destroy() 72 | end 73 | end 74 | 75 | if (current_scene) current_scene.entities = {} 76 | current_scene = next_scene 77 | current_scene:init() 78 | end 79 | 80 | next_scene = nil 81 | end 82 | 83 | function flash(color) 84 | color = color or 7 85 | screen:shake(0.25) 86 | screen:flash(color) 87 | sfx(38) 88 | end 89 | 90 | function wait(frames, callback) 91 | timers:new(frames, callback) 92 | end -------------------------------------------------------------------------------- /scripts/entities/space.lua: -------------------------------------------------------------------------------- 1 | space = entity:new({ 2 | layer = -1, 3 | speed = 0.5, 4 | particle_pool = {}, 5 | particles = false, 6 | persist = true, 7 | 8 | init = function(self) 9 | for i=1,15 do 10 | entities.star:new() 11 | end 12 | end, 13 | 14 | update = function(self) 15 | if self.particles and #self.particle_pool < 20 then 16 | for i = #self.particle_pool, 20 do 17 | self:spawn_particle() 18 | end 19 | end 20 | end, 21 | 22 | spawn_streaks = function(self) 23 | for i = 1, 6 do 24 | entity:new({ 25 | layer = 45, 26 | 27 | init = function(self) 28 | self:reset_values() 29 | end, 30 | 31 | update = function(self) 32 | self.y += self.speed 33 | 34 | if (self.y - 96 > 128) then 35 | if current_scene != scenes.transition then 36 | self:destroy() 37 | else 38 | self:reset_values() 39 | end 40 | end 41 | end, 42 | 43 | draw = function(self) 44 | transparent(function() 45 | rectfill(self.x, self.y, self.x + self.width, self.y - 96, 7) 46 | end) 47 | end, 48 | 49 | reset_values = function(self) 50 | self.x = 8 + rnd(112) 51 | self.y = 0 - rnd(128) 52 | self.speed = 8 + rnd(8) 53 | self.width = rnd({0,1}) 54 | end 55 | }) 56 | end 57 | end, 58 | 59 | spawn_particle = function(self, y) 60 | add(self.particle_pool, entities.particle:new({ 61 | x = rnd(128), 62 | y = rnd(32) - 16, 63 | size = rnd({0,1}), 64 | vy = rnd(2) * self.speed, 65 | frames = flr(rnd(240)), 66 | scheme = breach and 2 or 1, 67 | 68 | on_destroy = function(self) 69 | del(space.particle_pool, self) 70 | end 71 | })) 72 | end, 73 | 74 | draw = function() 75 | if breach_destabilized then 76 | rectfill(0,0,128,128, 8) 77 | end 78 | end 79 | }) -------------------------------------------------------------------------------- /scripts/scenes/level.lua: -------------------------------------------------------------------------------- 1 | scenes.level = object:new({ 2 | init = function(self) 3 | local level = self 4 | 5 | space.particles = false 6 | space:animate({ speed = 1 }, 30, easeoutquad) 7 | 8 | enemies = {} 9 | level_complete = false 10 | 11 | bottom_gate = entities.gate:new({ y = -32, is_open = true, effects = false, direction = "up" }) 12 | bottom_gate:animate({ y = 120 }, 30, easeoutquad) 13 | wait(10, function() bottom_gate:close() end) 14 | 15 | gate = entities.gate:new({ y = -32, is_open = true }) 16 | gate:animate({ y = -8 }, 30, easeoutquad) 17 | wait(12, function() gate:close() end) 18 | 19 | gate.portal.on_hit = function(self, other) 20 | if other == player 21 | and player.projectile 22 | and level_complete then 23 | level_id += 1 24 | load_scene "transition" 25 | gate.portal.on_hit = noop 26 | end 27 | end 28 | 29 | local world = 1 30 | if (player.projectile.charged) world = 2 31 | if (player.projectile.eggplant) world = 3 32 | local current_level = levels[world][level_id] 33 | local pool = split(current_level) 34 | local positions = { 35 | {18,16}, {32,16}, {56,16}, {80,16}, {104,16}, 36 | {18,40}, {32,40}, {56,40}, {80,40}, {104,40}, 37 | } 38 | 39 | for i = 1, 3 do 40 | local enemy_type = rnd(pool) 41 | local position = rnd(positions) 42 | del(positions, position) 43 | 44 | if (entities[enemy_type].exclusive) del(pool, enemy_type) 45 | 46 | add(enemies, entities[enemy_type]:new({ 47 | x = position[1], 48 | y = position[2], 49 | on_destroy = function(self) 50 | del(enemies, self) 51 | end 52 | })) 53 | end 54 | 55 | player:animate({ x = 52, y = 88 }, 30, easeoutquad, function() 56 | player:enable() 57 | end) 58 | 59 | for e in all(enemies) do 60 | local tx, ty = e.x, e.y 61 | e.x = 52 62 | e.y = -48 63 | e:animate({ x = tx, y = ty }, 30, easeoutquad) 64 | end 65 | end, 66 | 67 | update = function(self) 68 | if #enemies == 0 and not level_complete then 69 | gate:open() 70 | level_complete = true 71 | end 72 | 73 | if player.health <= 0 then 74 | load_scene "gameover" 75 | end 76 | end 77 | }) -------------------------------------------------------------------------------- /scripts/scenes/title.lua: -------------------------------------------------------------------------------- 1 | scenes.title = object:new({ 2 | init = function(self) 3 | level_id = 1 4 | menu_items = {} 5 | menu_item = 1 6 | breach_destabilized = false 7 | 8 | if (not player.projectile) player:spawn_projectile() 9 | player.health = player.max_health 10 | player:disable() 11 | player:animate({ x = 52, y = 68 }, 60, easeoutovershoot) 12 | space:animate({ speed = 0.5 }, 30, easeinquad) 13 | space.particles = false 14 | 15 | entities.gate_with_button:new({ 16 | y = previous_scene != scenes.credits and -32 or -8 17 | }):animate({ y = -8 }, 30, easeoutquad) 18 | 19 | if tutorial_complete then 20 | menu_items = { 21 | { 22 | "start game", 23 | function() 24 | music(player.projectile.charged and 7 or 1, 500) 25 | start_time = t() 26 | load_scene "transition" 27 | end 28 | }, 29 | { 30 | "tutorial", 31 | function() 32 | load_scene "tutorial" 33 | end 34 | }, 35 | { 36 | "credits", 37 | function() 38 | load_scene "credits" 39 | end 40 | } 41 | } 42 | else 43 | menu_items = { 44 | { 45 | "press to start", 46 | function() 47 | load_scene "tutorial" 48 | end 49 | } 50 | } 51 | end 52 | end, 53 | 54 | update = function(self) 55 | local items = menu_items 56 | local selected = menu_item 57 | 58 | if btnp(5) then 59 | menu_items[menu_item][2]() 60 | end 61 | 62 | if btnp(2) and menu_item > 1 then 63 | menu_item -= 1 64 | sfx(11) 65 | end 66 | 67 | if btnp(3) and menu_item < #menu_items then 68 | menu_item += 1 69 | sfx(12) 70 | end 71 | end, 72 | 73 | draw = function(self) 74 | spr(192, 38, 20, 6, 2) 75 | spr(224, 7, 40, 16, 2) 76 | 77 | for i = 0, #menu_items - 1 do 78 | local item = menu_items[i + 1] 79 | local selected = i + 1 == menu_item 80 | local y = 112 - (#menu_items / 2 * 8) + 8 * i 81 | print_centered(item[1], y, selected and 7 or 5) 82 | 83 | if selected then 84 | spr(11, 54 - flr((#item[1] * 4) / 2), y) 85 | spr(11, 65 + flr((#item[1] * 4) / 2), y, 1, 1, true) 86 | end 87 | end 88 | 89 | if not tutorial_complete then 90 | ? "❎", 54, 108, 8 91 | end 92 | end 93 | }) -------------------------------------------------------------------------------- /scripts/entities/gate.lua: -------------------------------------------------------------------------------- 1 | entities.gate = entity:constructor({ 2 | door_animation_frames = 15, 3 | y = -8, 4 | effects = true, 5 | is_open = false, 6 | layer = 62, 7 | 8 | init = function(self) 9 | local gate = self 10 | 11 | self.left_door = self.left_door or entity:new({ 12 | x = self.is_open and -80 or -32, 13 | y = self.y, 14 | layer = 60, 15 | solid = true, 16 | hitbox = { 17 | x = 0, 18 | y = 0, 19 | width = 96, 20 | height = 16, 21 | }, 22 | 23 | draw = function(self) 24 | spr(36, self.x, self.y, 12, 2) 25 | set_palette() 26 | end 27 | }) 28 | 29 | self.right_door = self.right_door or self.left_door:new({ 30 | x = self.is_open and 110 or 62, 31 | layer = 61, 32 | 33 | draw = function(self) 34 | spr(36, self.x, self.y, 12, 2) 35 | end 36 | }) 37 | 38 | self.portal = entities.portal:new({ 39 | y = self.y, 40 | 41 | direction = self.direction, 42 | offset = self.is_open and 10 or 0 43 | }) 44 | end, 45 | 46 | update = function(self) 47 | self.portal.y = self.y 48 | self.left_door.y = self.y 49 | self.right_door.y = self.y 50 | end, 51 | 52 | draw = function(self) 53 | local x, y = self.right_door.x, self.right_door.y 54 | 55 | for i = 1, player.max_health do 56 | local offset = (i - 1) * 6 57 | spr(player.health >= i and 15 or 14, x + 64 - player.max_health * 6 + offset, y) 58 | end 59 | 60 | spr(12, x + 56 - player.max_health * 6, y) 61 | end, 62 | 63 | open = function(self) 64 | if not self.is_open then 65 | space.particles = true 66 | 67 | if self.effects then 68 | screen:shake(0.1) 69 | sfx(19) 70 | end 71 | 72 | self.is_open = true 73 | self.portal:animate({ offset = 10 }, self.door_animation_frames, easeoutquad) 74 | self.left_door:animate({ x = -80 }, self.door_animation_frames, easeoutquad) 75 | self.right_door:animate({ x = 112 }, self.door_animation_frames, easeoutquad) 76 | end 77 | end, 78 | 79 | close = function(self) 80 | if self.is_open then 81 | if (self.effects) sfx(19) 82 | self.is_open = false 83 | self.portal:animate({ offset = 0 }, self.door_animation_frames, easeinquad) 84 | self.left_door:animate({ x = -32 }, self.door_animation_frames, easeinquad) 85 | self.right_door:animate({ x = 62 }, self.door_animation_frames, easeinquad, function() 86 | if self.effects then 87 | screen:shake(0.15) 88 | sfx(20) 89 | end 90 | end) 91 | end 92 | end, 93 | 94 | on_destroy = function(self) 95 | self.portal:destroy() 96 | self.left_door:destroy() 97 | self.right_door:destroy() 98 | end 99 | }) -------------------------------------------------------------------------------- /scripts/entities/projectile.lua: -------------------------------------------------------------------------------- 1 | entities.projectile = entity:constructor({ 2 | persist = true, 3 | 4 | type = "projectile", 5 | vx = 0, 6 | vy = 0, 7 | 8 | float_speed = 1.5, 9 | 10 | sprite = 4, 11 | rotation = 1, 12 | layer = 40, 13 | 14 | floating = false, 15 | 16 | on_pickup = noop, 17 | 18 | hitbox = { 19 | x = -1, 20 | y = -1, 21 | width = 10, 22 | height = 10, 23 | }, 24 | 25 | update = function(self) 26 | if self.player then 27 | self.floating = false 28 | end 29 | 30 | if self.eggplant or self.floating then 31 | self.rotation = t() * 0.5 32 | else 33 | self.rotation = 1 34 | end 35 | 36 | self:move_and_collide(function(other, axis) 37 | if current_scene == scenes.tutorial 38 | and other.type == "target" 39 | and not self.floating then 40 | self.floating = true 41 | self.vy = self.float_speed 42 | self.vx = -self.float_speed 43 | other:hit(self) 44 | elseif other.type == "player" then 45 | if self.floating and other.control and not other.projectile then 46 | player:pickup(self) 47 | self.floating = false 48 | self.vx = 0 49 | self.vy = 0 50 | self:on_pickup() 51 | end 52 | else 53 | if (other.solid or (not self.floating and other.type == "enemy" and not self.player)) then 54 | self:deflect(other, axis) 55 | self.floating = true 56 | other:hit(self) 57 | elseif not self.floating then 58 | other:hit(self) 59 | self.floating = true 60 | end 61 | end 62 | end) 63 | end, 64 | 65 | draw = function(self) 66 | local x, y = self.x, self.y 67 | 68 | if not self.player then 69 | if self.eggplant then 70 | mapr(x + 4, y + 4, self.rotation, 3, 0, 2) 71 | 72 | if self.floating then 73 | transparent(function() 74 | circ(x + 4, y + 4, 12, 7) 75 | end) 76 | end 77 | else 78 | if self.charged then 79 | pal(9,2) 80 | pal(14,8) 81 | else 82 | pal(9,6) 83 | pal(14,7) 84 | end 85 | 86 | if self.floating then 87 | transparent(function() 88 | circ(x + 4, y + 4, 8, 7) 89 | end) 90 | 91 | mapr(x + 4, y + 4, self.rotation, 0, 0, 2) 92 | else 93 | sspr(36, 2, 8, 11, x, y) 94 | end 95 | end 96 | end 97 | 98 | set_palette() 99 | end, 100 | 101 | deflect = function(self, other, axis) 102 | if axis == "y" then 103 | if not self.floating then 104 | local offset = (self.x + self.hitbox.x + (self.hitbox.width / 2)) - (other.x + other.hitbox.x + (other.hitbox.width / 2)) 105 | self.vx = abs(offset) < 2 and 0 or sgn(offset) * self.float_speed 106 | end 107 | 108 | self.vy = sgn(self.vy) * -self.float_speed 109 | else 110 | self.vx *= -1 111 | end 112 | end, 113 | 114 | on_destroy = function(self) 115 | if (self.player) self.player.projectile = nil 116 | end, 117 | 118 | convert_to_eggplant = function(self) 119 | self.float_speed = 0.25 120 | self.eggplant = true 121 | self.vx = self.float_speed 122 | self.vy = self.float_speed 123 | self.floating = true 124 | end 125 | }) -------------------------------------------------------------------------------- /scripts/scenes/tutorial.lua: -------------------------------------------------------------------------------- 1 | scenes.tutorial = object:new({ 2 | step = 1, 3 | complete = false, 4 | exit_warning_displayed = false, 5 | 6 | init = function(self) 7 | tutorial_complete = false 8 | gate = entities.gate_with_button:new() 9 | self:step_one() 10 | end, 11 | 12 | draw = function(self) 13 | if not player.control and not tutorial_complete then 14 | line(1,0,126,0,7) 15 | line(0,1,0,126,7) 16 | line(127,1,127,126,7) 17 | line(1,127,126,127,7) 18 | end 19 | end, 20 | 21 | step_one = function(self) 22 | self.projectile = player.projectile 23 | 24 | player:animate({ x = 52, y = 64 }, 30, easeoutquad) 25 | say "hostile entities have opened a breach in the delta quadrant." 26 | say("you're going to have to seal it.", function() 27 | gate.button.on_hit = function() 28 | gate:open() 29 | gate.button.on_hit = noop 30 | self:step_two() 31 | end 32 | end) 33 | 34 | say "these slip gates will help you move quickly between sectors." 35 | say("line your ship up with the gate control and hit the ❎ button...", function() 36 | player:enable() 37 | end) 38 | end, 39 | 40 | step_two = function(self) 41 | player:disable() 42 | player:animate({ x = 96, y = 64 }, 30, easeoutquad) 43 | say("perfect! the gate's open... grab your void cell and get moving.", function() 44 | player:enable() 45 | 46 | gate.portal.on_hit = function(portal, other) 47 | if other == player then 48 | if not player.projectile then 49 | if not self.exit_warning_displayed then 50 | say "if you leave without a void cell the whole mission is over..." 51 | self.exit_warning_displayed = true 52 | end 53 | elseif tutorial_complete then 54 | gate.portal.on_hit = noop 55 | player.health = 3 56 | start_time = t() 57 | load_scene "transition" 58 | end 59 | end 60 | end 61 | 62 | self.projectile.on_pickup = function() 63 | self:step_three() 64 | self.projectile.on_pickup = noop 65 | end 66 | end) 67 | end, 68 | 69 | step_three = function(self) 70 | player:disable() 71 | player:animate({ x = 52, y = 64 }, 90, easeoutovershoot) 72 | 73 | say "your void containment cell isn't charged yet, so it's virtually indestructible." 74 | say "you can use it to clear a path if anything gets in your way." 75 | say("just don't lose it... we're going to need it to seal the breach.", function() 76 | music(-1, 4000) 77 | 78 | enemy = entities.bubble:new({ 79 | x = 64, 80 | y = -64, 81 | 82 | on_destroy = function() 83 | self:step_four() 84 | end, 85 | }) 86 | 87 | enemy:animate({ x = 56, y = 24 }, 90, easeoutovershoot, function() 88 | gate:close() 89 | end) 90 | 91 | space:animate({ speed = 1 }, 90) 92 | music(1) 93 | end) 94 | 95 | say "heads up! one of the entities made it through. the gate's locking down." 96 | say "that gate wont open again until you clear the area." 97 | say("take out that entity and head into the gate!", function() 98 | player:animate({ x = 52, y = 88 }, 30, easeoutquad, function() 99 | enemy:move() 100 | player:enable() 101 | end) 102 | end) 103 | end, 104 | 105 | step_four = function(self) 106 | dset(0, 1) 107 | tutorial_complete = true 108 | gate:open() 109 | end, 110 | 111 | unload = function(self) 112 | gate:destroy() 113 | end 114 | }) -------------------------------------------------------------------------------- /scripts/entity.lua: -------------------------------------------------------------------------------- 1 | entity = object:new({ 2 | pool = {}, 3 | animations = {}, 4 | persist = false, 5 | 6 | type = "entity", 7 | solid = false, 8 | layer = 0, 9 | x = 0, 10 | y = 0, 11 | 12 | vx = 0, 13 | vy = 0, 14 | 15 | width = 0, 16 | height = 0, 17 | 18 | hitbox = nil, 19 | flash_frames = 0, 20 | 21 | new = function(self, table) 22 | local new_entity = self:constructor(table) 23 | new_entity.animations = {} 24 | new_entity:init() 25 | 26 | add(self.pool, new_entity) 27 | 28 | return new_entity 29 | end, 30 | 31 | destroy = function(self) 32 | if (self.on_destroy) self:on_destroy() 33 | del(entity.pool, self) 34 | end, 35 | 36 | on_destroy = noop, 37 | 38 | all = function(method) 39 | for entity in all(entity.pool) do 40 | entity["_"..method](entity) 41 | end 42 | end, 43 | 44 | _update = function(self) 45 | for key, animation in pairs(self.animations) do 46 | if animation then 47 | self[key] = animation.value 48 | 49 | if animation.done then 50 | self.animations[key] = nil 51 | end 52 | end 53 | end 54 | 55 | self:update() 56 | end, 57 | 58 | _draw = function(self) 59 | self:with_flash(function() 60 | self:draw() 61 | end) 62 | end, 63 | 64 | hit = function(self, other) 65 | self:on_hit(other) 66 | end, 67 | 68 | on_hit = noop, 69 | 70 | flash = function(self, frames) 71 | self.flash_frames = frames 72 | end, 73 | 74 | with_flash = function(self, func) 75 | if self.flash_frames > 0 then 76 | for i=0,15 do 77 | pal(i,7) 78 | end 79 | 80 | self.flash_frames -= 1 81 | end 82 | 83 | func() 84 | 85 | set_palette() 86 | end, 87 | 88 | // animation 89 | 90 | animate = function(self, attributes, frames, easing, callback) 91 | self.animation_ended_at = nil 92 | 93 | for key, value in pairs(attributes) do 94 | local func = callback 95 | 96 | self.animations[key] = animation:new(self[key], value, frames, easing, function() 97 | if (func) func() 98 | self.animation_ended_at = t() 99 | end) 100 | 101 | callback = noop 102 | end 103 | end, 104 | 105 | // movement 106 | 107 | collide = function(self, other) 108 | if (not self.hitbox or not other.hitbox) return false 109 | 110 | return other.x + other.hitbox.x < self.x + self.hitbox.x + self.hitbox.width - 1 111 | and other.x + other.hitbox.x + other.hitbox.width - 1 > self.x + self.hitbox.x 112 | and other.y + other.hitbox.y < self.y + self.hitbox.y + self.hitbox.height - 1 113 | and other.y + other.hitbox.y + other.hitbox.height > self.y + self.hitbox.y 114 | end, 115 | 116 | move = function(self) 117 | local angle = atan2(self.vx, self.vy) 118 | local nvx = cos(angle) * abs(self.vx) 119 | local nvy = sin(angle) * abs(self.vy) 120 | 121 | self.x += nvx 122 | self.y += nvy 123 | end, 124 | 125 | move_and_collide = function(self, callback) 126 | if (not self.hitbox) return 127 | 128 | callback = callback or noop 129 | 130 | local angle = atan2(self.vx, self.vy) 131 | local nvx = cos(angle) * abs(self.vx) 132 | local nvy = sin(angle) * abs(self.vy) 133 | 134 | if nvx != 0 or nvy != 0 then 135 | local steps = ceil(max(abs(nvx), abs(nvy))) 136 | local step = 1/steps 137 | 138 | for i = 1, steps do 139 | local ox = self.x 140 | local oy = self.y 141 | 142 | if nvx != 0 then 143 | self.x += nvx * step 144 | 145 | for other in all(entity.pool) do 146 | if other != self and self:collide(other) then 147 | callback(other, "x") 148 | 149 | if other.solid then 150 | self.x = ox 151 | nvx = 0 152 | end 153 | end 154 | end 155 | end 156 | 157 | if nvy != 0 then 158 | self.y += nvy * step 159 | 160 | for other in all(entity.pool) do 161 | if other != self and self:collide(other) then 162 | callback(other, "y") 163 | 164 | if other.solid then 165 | self.y = oy 166 | nvy = 0 167 | end 168 | end 169 | end 170 | end 171 | 172 | if (nvx == 0 and nvy == 0) break 173 | end 174 | end 175 | end 176 | }) -------------------------------------------------------------------------------- /scripts/utilities/animation.lua: -------------------------------------------------------------------------------- 1 | -- easing function cheatsheet 2 | -- by valeradhd 3 | -- source: https://www.lexaloffle.com/bbs/?tid=40577 4 | 5 | animation = { 6 | pool = {}, 7 | 8 | new = function(self, from, to, frames, easing, callback) 9 | frames = frames or 30 10 | easing = easing or linear 11 | callback = callback or function() end 12 | 13 | local anim = { 14 | done = false, 15 | 16 | update = function(self) 17 | if costatus(self.coroutine) != "dead" then 18 | coresume(self.coroutine) 19 | else 20 | callback() 21 | self:destroy() 22 | end 23 | end, 24 | 25 | destroy = function(self) 26 | del(animation.pool, self) 27 | self.done = true 28 | end, 29 | 30 | value = from 31 | } 32 | 33 | anim.coroutine = cocreate(function(from, to, frames, easing) 34 | for frame=1,frames do 35 | anim.value = lerp(from, to, easing(frame/frames)) 36 | yield() 37 | end 38 | end) 39 | 40 | coresume(anim.coroutine, from, to, frames, easing) 41 | add(self.pool, anim) 42 | 43 | return anim 44 | end, 45 | 46 | update = function(self) 47 | for a in all(self.pool) do 48 | a:update() 49 | end 50 | end 51 | } 52 | 53 | function linear(t) 54 | return t 55 | end 56 | 57 | --quadratics 58 | function easeinquad(t) 59 | return t*t 60 | end 61 | 62 | function easeoutquad(t) 63 | t-=1 64 | return 1-t*t 65 | end 66 | 67 | function easeinoutquad(t) 68 | if(t<.5) then 69 | return t*t*2 70 | else 71 | t-=1 72 | return 1-t*t*2 73 | end 74 | end 75 | 76 | --[[ 77 | 78 | function easeoutinquad(t) 79 | if t<.5 then 80 | t-=.5 81 | return .5-t*t*2 82 | else 83 | t-=.5 84 | return .5+t*t*2 85 | end 86 | end 87 | 88 | --quartics 89 | function easeinquart(t) 90 | return t*t*t*t 91 | end 92 | 93 | function easeoutquart(t) 94 | t-=1 95 | return 1-t*t*t*t 96 | end 97 | 98 | function easeinoutquart(t) 99 | if t<.5 then 100 | return 8*t*t*t*t 101 | else 102 | t-=1 103 | return (1-8*t*t*t*t) 104 | end 105 | end 106 | 107 | function easeoutinquart(t) 108 | if t<.5 then 109 | t-=.5 110 | return .5-8*t*t*t*t 111 | else 112 | t-=.5 113 | return .5+8*t*t*t*t 114 | end 115 | end 116 | 117 | --overshooting functions 118 | function easeinovershoot(t) 119 | return 2.7*t*t*t-1.7*t*t 120 | end 121 | 122 | --]] 123 | 124 | function easeoutovershoot(t) 125 | t-=1 126 | return 1+2.7*t*t*t+1.7*t*t 127 | end 128 | 129 | --[[ 130 | 131 | function easeinoutovershoot(t) 132 | if t<.5 then 133 | return (2.7*8*t*t*t-1.7*4*t*t)/2 134 | else 135 | t-=1 136 | return 1+(2.7*8*t*t*t+1.7*4*t*t)/2 137 | end 138 | end 139 | 140 | function easeoutinovershoot(t) 141 | if t<.5 then 142 | t-=.5 143 | return (2.7*8*t*t*t+1.7*4*t*t)/2+.5 144 | else 145 | t-=.5 146 | return (2.7*8*t*t*t-1.7*4*t*t)/2+.5 147 | end 148 | end 149 | 150 | --elastics 151 | function easeinelastic(t) 152 | if(t==0) return 0 153 | return 2^(10*t-10)*cos(2*t-2) 154 | end 155 | 156 | function easeoutelastic(t) 157 | if(t==1) return 1 158 | return 1-2^(-10*t)*cos(2*t) 159 | end 160 | 161 | function easeinoutelastic(t) 162 | if t<.5 then 163 | return 2^(10*2*t-10)*cos(2*2*t-2)/2 164 | else 165 | t-=.5 166 | return 1-2^(-10*2*t)*cos(2*2*t)/2 167 | end 168 | end 169 | 170 | function easeoutinelastic(t) 171 | if t<.5 then 172 | return .5-2^(-10*2*t)*cos(2*2*t)/2 173 | else 174 | t-=.5 175 | return 2^(10*2*t-10)*cos(2*2*t-2)/2+.5 176 | end 177 | end 178 | 179 | --bouncing 180 | function easeinbounce(t) 181 | t=1-t 182 | local n1=7.5625 183 | local d1=2.75 184 | 185 | if (t<1/d1) then 186 | return 1-n1*t*t; 187 | elseif(t<2/d1) then 188 | t-=1.5/d1 189 | return 1-n1*t*t-.75; 190 | elseif(t<2.5/d1) then 191 | t-=2.25/d1 192 | return 1-n1*t*t-.9375; 193 | else 194 | t-=2.625/d1 195 | return 1-n1*t*t-.984375; 196 | end 197 | end 198 | 199 | function easeoutbounce(t) 200 | local n1=7.5625 201 | local d1=2.75 202 | 203 | if (t<1/d1) then 204 | return n1*t*t; 205 | elseif(t<2/d1) then 206 | t-=1.5/d1 207 | return n1*t*t+.75; 208 | elseif(t<2.5/d1) then 209 | t-=2.25/d1 210 | return n1*t*t+.9375; 211 | else 212 | t-=2.625/d1 213 | return n1*t*t+.984375; 214 | end 215 | end 216 | 217 | --]] 218 | 219 | --other useful functions: 220 | --(linear interpolation between a/b) 221 | function lerp(a,b,t) 222 | return a+(b-a)*t 223 | end 224 | 225 | --[[ 226 | 227 | --(finds the t value that would 228 | --return v in a lerp between a/b) 229 | function invlerp(a,b,v) 230 | return (v-a)/(b-a) 231 | end 232 | 233 | --]] -------------------------------------------------------------------------------- /scripts/entities/player.lua: -------------------------------------------------------------------------------- 1 | player = entity:new({ 2 | type = "player", 3 | persist = true, 4 | 5 | -- position 6 | x = 52, 7 | y = 144, 8 | layer = 50, 9 | 10 | -- movement 11 | control = false, 12 | vx = 0, 13 | vy = 0, 14 | accel = 0.25, 15 | friction = 0.1, 16 | max_speed = 2.5, 17 | 18 | -- collision 19 | hitbox = { 20 | x = 6, 21 | y = 4, 22 | width = 11, 23 | height = 12, 24 | }, 25 | 26 | -- health 27 | max_health = 3, 28 | max_iframes = 60, 29 | 30 | -- projectile 31 | projectile_speed = -4, 32 | projectile_kickback = 1.4, 33 | 34 | init = function(self) 35 | self.health = self.max_health 36 | self.iframes = 0 37 | self.disabled_at = t() 38 | self.animation_ended_at = t() 39 | self:spawn_projectile() 40 | end, 41 | 42 | update = function(self) 43 | if self.control then 44 | if btnp(5) and #dialog.dialog_queue == 0 then 45 | self:fire_projectile() 46 | end 47 | 48 | self:handle_input() 49 | else 50 | if not self.animations.x then 51 | local timestamp = self.animation_ended_at or self.disabled_at 52 | self.x += timestamp and cos((t() - timestamp)/3) * .25 or 0 53 | end 54 | 55 | self.y += self.animation_ended_at and cos((t() - self.animation_ended_at)/4) * .1 or 0 56 | end 57 | 58 | if self.projectile then 59 | self.projectile.x = self.x + 8 60 | self.projectile.y = self.y 61 | end 62 | 63 | self:move_and_collide(function(other, axis) 64 | if other.type == "portal" then 65 | other:hit(self) 66 | elseif other.type == "enemy" then 67 | self:hit() 68 | elseif other.solid then 69 | if (axis == "x") self.vx = 0 70 | if (axis == "y") self.vy = 0 71 | end 72 | end) 73 | 74 | self.iframes = mid(0, self.iframes - 1, self.max_iframes) 75 | end, 76 | 77 | draw = function(self) 78 | local x = self.x 79 | local y = self.y 80 | 81 | if self.iframes % 4 == 0 then 82 | if self.projectile then 83 | if self.projectile.eggplant then 84 | palt(15, false) 85 | pal(15, 3) 86 | pal(14,4) 87 | pal(9,2) 88 | elseif self.projectile.charged then 89 | pal(9,6) 90 | pal(14,8) 91 | else 92 | pal(9,6) 93 | pal(14,7) 94 | end 95 | 96 | sspr(36, 2, 8, 11, x + 8, y) 97 | 98 | set_palette() 99 | end 100 | 101 | pal(14, self.projectile and 6 or 7) 102 | spr(1, x, y, 3, 3) 103 | pal(14,8) 104 | 105 | transparent(function() 106 | oval(x + 9, y + 18, x + 14, y + 21, 7) 107 | end) 108 | end 109 | end, 110 | 111 | hit = function(self, other) 112 | if self.iframes == 0 then 113 | screen:flash(8, 3) 114 | screen:shake(.25) 115 | self.health -= 1 116 | self.iframes = self.max_iframes 117 | sfx(24) 118 | end 119 | end, 120 | 121 | fire_projectile = function(self) 122 | if self.projectile then 123 | sfx(10) 124 | self.projectile.persist = false 125 | self.projectile.vy = self.projectile_speed 126 | self.projectile.player = nil 127 | self.projectile = nil 128 | self.vy += self.projectile_kickback 129 | screen:shake(0.1) 130 | else 131 | sfx(9) 132 | end 133 | end, 134 | 135 | enable = function(self) 136 | self.control = true 137 | self.disabled_at = nil 138 | end, 139 | 140 | disable = function(self) 141 | self.disabled_at = t() 142 | self.control = false 143 | self.vx = 0 144 | self.vy = 0 145 | end, 146 | 147 | handle_input = function(self) 148 | local vx, vy, accel, friction, max_speed = self.vx, self.vy, self.accel, self.friction, self.max_speed 149 | 150 | if btn(0) then 151 | vx = vx > 0 and -accel or vx - accel 152 | elseif btn(1) then 153 | vx = vx < 0 and accel or vx + accel 154 | elseif vx != 0 then 155 | vx += min(abs(vx), friction) * -sgn(vx) 156 | end 157 | 158 | if btn(2) then 159 | vy = vy > 0 and -accel or vy - accel 160 | elseif btn(3) then 161 | vy = vy < 0 and accel or vy + accel 162 | elseif vy != 0 then 163 | vy += min(abs(vy), friction) * -sgn(vy) 164 | end 165 | 166 | self.vx = mid(-max_speed, vx, max_speed) 167 | self.vy = mid(-max_speed, vy, max_speed) 168 | end, 169 | 170 | spawn_projectile = function(self) 171 | if not self.projectile then 172 | self.projectile = entities.projectile:new({ 173 | x = self.x + 8, 174 | y = self.y 175 | }) 176 | self.projectile.player = self 177 | end 178 | end, 179 | 180 | pickup = function(self, projectile) 181 | sfx(8) 182 | self.projectile = projectile 183 | projectile.persist = true 184 | projectile.floating = false 185 | projectile.player = self 186 | end 187 | }) -------------------------------------------------------------------------------- /scripts/scenes/breach.lua: -------------------------------------------------------------------------------- 1 | scenes.breach = object:new({ 2 | init = function(self) 3 | space:animate({ speed = 1 }, 30, easeoutquad) 4 | 5 | ending = "basic" 6 | breach_destabilized = false 7 | projectile = player.projectile 8 | 9 | gate = entities.gate:new({ y = -32, is_open = true, direction = "up" }) 10 | gate:animate({ y = 120 }, 30, easeoutquad) 11 | wait(10, function() 12 | gate:close() 13 | space.particles = true 14 | bottom_gate:close() 15 | end) 16 | 17 | breach = entities.breach:new({ y = -64 }) 18 | breach:animate({ y = 12 }, 60, easeoutquad) 19 | breach.on_hit = function(breach, other) 20 | if other == projectile then 21 | end_time = t() 22 | 23 | breach.on_hit = nil 24 | projectile.vy = 0 25 | projectile.floating = false 26 | projectile:animate({ x = 60, y = breach.y + 20 }, 30, easeoutquad, function() 27 | projectile.floating = true 28 | end) 29 | gate:animate({ y = 132 }) 30 | 31 | player:disable() 32 | player:animate({ x = 52, y = 64 }, 30, easeoutquad) 33 | 34 | if projectile.eggplant then 35 | self:play_eggplant_ending() 36 | elseif projectile.charged then 37 | self:play_charged_ending() 38 | else 39 | self:play_basic_ending() 40 | end 41 | end 42 | end 43 | 44 | player:animate({ x = 52, y = 80 }, 30, easeoutquad, function() 45 | player:enable() 46 | end) 47 | end, 48 | 49 | play_basic_ending = function(self) 50 | say("keep back. the containment cell is powering up.", function() 51 | flash() 52 | 53 | wait(60, function() 54 | flash() 55 | 56 | wait(45, function() 57 | flash() 58 | 59 | for i = 1, 60 do 60 | timers:new(i * 10, function() 61 | entities.particle:new({ 62 | layer = 10, 63 | x = 32 + rnd(64), 64 | y = 16 + rnd(8), 65 | scheme = 2, 66 | }):animate({ x = projectile.x + 4, y = projectile.y + 4 }, 60, easeoutquad) 67 | end) 68 | end 69 | 70 | say "the cell is absorbing energy from the breach." 71 | say("you've almost got this under control!", function() 72 | flash(8) 73 | wait(60, function() 74 | flash(8) 75 | wait(30, function() 76 | timers.pool = {} 77 | space.particles = false 78 | breach:destroy() 79 | flash(8) 80 | crossfade_music(0) 81 | projectile.charged = true 82 | projectile.floating = true 83 | projectile:animate({ x = 60, y = 64 }, 15, linear, function() 84 | player:pickup(projectile) 85 | end) 86 | 87 | say "the breach has been contained. that was easier than expected!" 88 | say "be sure to dispose of that charged cell someplace safe." 89 | say("we'll need someone with your experience when the next breach appears.", function() 90 | load_scene "win" 91 | end) 92 | end) 93 | end) 94 | end) 95 | end) 96 | end) 97 | end) 98 | end, 99 | 100 | play_charged_ending = function(self) 101 | ending = "charged" 102 | 103 | say "did you just fire a charged containment cell into the breach!?" 104 | say("that's going to create an unstable reaction...", flash) 105 | 106 | say("the breach could expand and swallow this entire univ... wait...", flash) 107 | 108 | say("the energy from the charged cell is... transmuting the breach...", function() 109 | flash(2) 110 | end) 111 | 112 | say("the breach is becoming...", function() 113 | flash(13) 114 | breach:destroy() 115 | 116 | entities.projectile:new({ 117 | x = 60, 118 | y = 8, 119 | float_speed = 0.5, 120 | vx = 0.5, 121 | vy = 0.5, 122 | eggplant = true, 123 | floating = true 124 | }) 125 | 126 | projectile.charged = false 127 | projectile:animate({ x = 60, y = 64 }, 30, easeinquad, function() 128 | player:pickup(projectile) 129 | end) 130 | end) 131 | 132 | say("... an eggplant?", function() 133 | load_scene "win" 134 | end) 135 | end, 136 | 137 | play_eggplant_ending = function(self) 138 | ending = "eggplant" 139 | 140 | say("what are you doing!? where's the containment cell!?", function() 141 | flash(8) 142 | end) 143 | 144 | say("did you really just fire an eggplant into the breach?", function() 145 | flash(8) 146 | 147 | wait(60, function() 148 | say "... I... just... what did you think that would do?" 149 | say("it's over... the breach is destabilizing...", function() 150 | flash(8) 151 | player.iframes = 60 152 | player:animate({ y = 144 }, 60) 153 | 154 | wait(30, function() 155 | flash(8) 156 | breach_destabilized = true 157 | projectile.persist = true 158 | projectile.float_speed = 0.5 159 | projectile.vx = 0.5 160 | projectile.vy = 0.5 161 | projectile.floating = true 162 | 163 | crossfade_music(15) 164 | 165 | wait(60, function() 166 | load_scene "win" 167 | end) 168 | end) 169 | end) 170 | end) 171 | end) 172 | end 173 | }) -------------------------------------------------------------------------------- /scripts/entities/dialog.lua: -------------------------------------------------------------------------------- 1 | dialog = entity:new({ 2 | persist = true, 3 | x = 8, 4 | y = 103, 5 | color = 7, 6 | max_chars_per_line = 27, 7 | max_lines = 3, 8 | dialog_queue = {}, 9 | blinking_counter = 0, 10 | layer = 100, 11 | 12 | reset = function(self) 13 | self.animation_loop = nil 14 | self.pause_dialog = false 15 | self.current_line_count = 1 16 | self.current_message = '' 17 | self.dialog_queue = {} 18 | end, 19 | 20 | queue = function(self, message, callback) 21 | callback = callback or function() end 22 | add(self.dialog_queue, { message = message, callback = callback }) 23 | 24 | if (#self.dialog_queue == 1) then 25 | self:trigger( 26 | self.dialog_queue[1].message, 27 | self.dialog_queue[1].callback 28 | ) 29 | end 30 | end, 31 | 32 | trigger = function(self, message, callback) 33 | self.callback = callback 34 | self.current_message = '' 35 | self.messages_by_line = nil 36 | self.animation_loop = nil 37 | self.current_line_in_table = 1 38 | self.current_line_count = 1 39 | self.pause_dialog = false 40 | self:format_message(message) 41 | self.animation_loop = cocreate(self.animate_text) 42 | end, 43 | 44 | format_message = function(self, message) 45 | local total_msg = {} 46 | local word = '' 47 | local letter = '' 48 | local current_line_msg = '' 49 | 50 | for i = 1, #message do 51 | -- get the current letter add 52 | letter = sub(message, i, i) 53 | 54 | -- keep track of the current word 55 | word ..= letter 56 | 57 | -- if it's a space or the end of the message, 58 | -- determine whether we need to continue the current message 59 | -- or start it on a new line 60 | if letter == ' ' or i == #message then 61 | -- get the potential line length if this word were to be added 62 | local line_length = #current_line_msg + #word 63 | -- if this would overflow the dialog width 64 | if line_length > self.max_chars_per_line then 65 | -- add our current line to the total message table 66 | add(total_msg, current_line_msg) 67 | -- and start a new line with this word 68 | current_line_msg = word 69 | else 70 | -- otherwise, continue adding to the current line 71 | current_line_msg ..= word 72 | end 73 | 74 | -- if this is the last letter and it didn't overflow 75 | -- the dialog width, then go ahead and add it 76 | if i == #message then 77 | add(total_msg, current_line_msg) 78 | end 79 | 80 | -- reset the word since we've written 81 | -- a full word to the current message 82 | word = '' 83 | end 84 | end 85 | 86 | self.messages_by_line = total_msg 87 | end, 88 | 89 | animate_text = function(self) 90 | -- for each line, write it out letter by letter 91 | -- if we each the max lines, pause the coroutine 92 | -- wait for input in update before proceeding 93 | for k, line in pairs(self.messages_by_line) do 94 | self.current_line_in_table = k 95 | for i = 1, #line do 96 | self.current_message ..= sub(line, i, i) 97 | 98 | -- press btn 5 to skip to the end of the current passage 99 | -- otherwise, print 1 character per frame 100 | -- with sfx about every 5 frames 101 | if (not btnp(5)) then 102 | if (i % 5 == 0) sfx(0) 103 | yield() 104 | end 105 | end 106 | 107 | self.current_message ..= '\n' 108 | self.current_line_count += 1 109 | 110 | if ((self.current_line_count > self.max_lines) or (self.current_line_in_table == #self.messages_by_line)) then 111 | self.pause_dialog = true 112 | self.blinking_counter = 30 113 | yield() 114 | end 115 | end 116 | end, 117 | 118 | shift = function (t) 119 | local n=#t 120 | for i = 1, n do 121 | if i < n then 122 | t[i] = t[i + 1] 123 | else 124 | t[i] = nil 125 | end 126 | end 127 | end, 128 | 129 | -- helper function to add delay in coroutines 130 | delay = function(frames) 131 | for i = 1, frames do 132 | yield() 133 | end 134 | end, 135 | 136 | update = function(self) 137 | if (self.animation_loop and costatus(self.animation_loop) != 'dead') then 138 | if (not self.pause_dialog) then 139 | coresume(self.animation_loop, self) 140 | else 141 | if btnp(5) then 142 | self:progress_dialog() 143 | end 144 | end 145 | elseif (self.animation_loop and self.current_message) then 146 | self.animation_loop = nil 147 | end 148 | 149 | if (not self.animation_loop and #self.dialog_queue > 0) then 150 | self.shift(self.dialog_queue, 1) 151 | if (#self.dialog_queue > 0) then 152 | self:trigger( 153 | self.dialog_queue[1].message, 154 | self.dialog_queue[1].callback 155 | ) 156 | coresume(self.animation_loop, self) 157 | end 158 | end 159 | 160 | self.blinking_counter += 1 161 | if self.blinking_counter > 60 then self.blinking_counter = 0 end 162 | end, 163 | 164 | draw = function(self) 165 | local screen_width = 128 166 | 167 | -- display message 168 | if (self.current_message and self.current_message != "") then 169 | rectfill(self.x - 4, self.y - 4, screen_width - 5, screen_width - 5, 0) 170 | rect(self.x - 4, self.y - 4, screen_width - 5, screen_width - 5, 7) 171 | print(self.current_message, self.x, self.y, self.color) 172 | end 173 | 174 | -- draw blinking cursor at the bottom right 175 | if (self.pause_dialog) then 176 | if self.blinking_counter > 30 then 177 | if (self.current_line_in_table == #self.messages_by_line) then 178 | for x = -1, 1 do 179 | for y = -1, 1 do 180 | ? "❎", screen_width - 14 + x, screen_width - 7 + y, 0 181 | end 182 | end 183 | 184 | ? "❎", screen_width - 14, screen_width - 7 , 7 185 | else 186 | -- draw arrow 187 | line(screen_width - 13, screen_width - 5, screen_width - 7,screen_width - 5, 0) 188 | line(screen_width - 12, screen_width - 6, screen_width - 8,screen_width - 6, 7) 189 | line(screen_width - 11, screen_width - 5, screen_width - 9,screen_width - 5, 7) 190 | line(screen_width - 10, screen_width - 4, screen_width - 10,screen_width - 4, 7) 191 | end 192 | end 193 | end 194 | end, 195 | 196 | progress_dialog = function(self) 197 | self.pause_dialog = false 198 | self.current_line_count = 1 199 | self.current_message = '' 200 | if(self.callback) self.callback() 201 | end 202 | }) -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | PICO-8 Cartridge 3 | 4 | 678 | 679 | 736 | 737 | 738 | 739 | 740 |
741 | 742 | 743 | 744 | 745 | 746 |
747 |
748 |
749 | 750 |
751 |
752 |
753 |
754 |
755 | 756 |
759 | 760 |
761 | 763 |
764 | 765 | 804 | 805 |
806 | 807 |
808 |
809 | 810 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 |
845 | 846 | 847 | -------------------------------------------------------------------------------- /void-protocol.p8: -------------------------------------------------------------------------------- 1 | pico-8 cartridge // http://www.pico-8.com 2 | version 32 3 | __lua__ 4 | -- void protocol 5 | -- by @kevinthompson 6 | 7 | -- game logic 8 | #include scripts/object.lua 9 | #include scripts/main.lua 10 | 11 | -- scenes 12 | #include scripts/scenes/breach.lua 13 | #include scripts/scenes/credits.lua 14 | #include scripts/scenes/gameover.lua 15 | #include scripts/scenes/level.lua 16 | #include scripts/scenes/splash.lua 17 | #include scripts/scenes/title.lua 18 | #include scripts/scenes/transition.lua 19 | #include scripts/scenes/tutorial.lua 20 | #include scripts/scenes/win.lua 21 | 22 | -- entities 23 | #include scripts/entity.lua 24 | #include scripts/entities/target.lua 25 | #include scripts/entities/button.lua 26 | #include scripts/entities/dialog.lua 27 | #include scripts/entities/enemy.lua 28 | #include scripts/entities/gate.lua 29 | #include scripts/entities/gate_with_button.lua 30 | #include scripts/entities/projectile.lua 31 | #include scripts/entities/player.lua 32 | #include scripts/entities/wall.lua 33 | #include scripts/entities/screen.lua 34 | #include scripts/entities/star.lua 35 | #include scripts/entities/space.lua 36 | #include scripts/entities/portal.lua 37 | #include scripts/entities/level_text.lua 38 | #include scripts/entities/breach.lua 39 | #include scripts/entities/particle.lua 40 | 41 | -- enemies 42 | #include scripts/entities/enemies/bubble.lua 43 | #include scripts/entities/enemies/bubbler.lua 44 | #include scripts/entities/enemies/diver.lua 45 | 46 | -- utiltiies 47 | #include scripts/utilities/animation.lua 48 | #include scripts/utilities/audio.lua 49 | --#include scripts/utilities/logging.lua 50 | --#include scripts/utilities/menu.lua 51 | #include scripts/utilities/palette.lua 52 | #include scripts/utilities/sprites.lua 53 | #include scripts/utilities/tables.lua 54 | #include scripts/utilities/text.lua 55 | #include scripts/utilities/timers.lua 56 | 57 | -- data 58 | #include data/levels.lua 59 | 60 | __gfx__ 61 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbfbfbbbbbbb777777666677776677777777bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 62 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbfbbbbbbbb777677777777777777767777b22222222222222bbbbbbb8bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 63 | bb7bb7bbbbbbbbbb7bbbbbb7bbbbbbbbbbbbbbb77bbbbbbb7767777777777777777767772000000000000002bbbbbb88bb5b5bbbbbbbbbbbb5b5bbbbb2b2bbbb 64 | bbb77bbbbbbbbbb707bbbb707bbbbbbbbbbbbb7007bbbbbb7777777777777777777777770888888888888880bbbbbb82bb555bbbbbbbbbbb56565bbb27282bbb 65 | bbb77bbbbbbbbb70707bb70707bbbbbbbbbbb70ee07bbbbb6777755555555555555777768887778888888888bbbbbb2bb55555bbbbbbbbbb56665bbb28882bbb 66 | bb7bb7bbbbbbbb70707ee70707bbbbbbbbbbb70ee07bbbbb6777500000000000000577768888888888888888bbbbbbbbb55555bbbbbbbbbbb565bbbbb282bbbb 67 | bbbbbbbbbbbbbb7070e00e0707bbbbbbbbbb70eeee07bbbb66750bbbbbbbbbbbbbb05766b88888888888888bbbbbbbbbbb555bbbbbbbbbbbbb5bbbbbbb2bbbbb 68 | bbbbbbbbbbbbb70770077007707bbbbbbbbb70e00e07bbbbb665bbbbbbbbbbbbbbbb666bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 69 | bbbbbbbbbbbb7077707777077707bbbbbbbb70099007bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 70 | bbbbbbbbbbb707607070070706707bbbbbbb709ee907bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 71 | bbbbbbbbbbb707607700007706707bbbbbbb70eeee07bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 72 | bbbbbbbbbbb707607766667706707bbbbbbbb700007bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 73 | bbbbbbbbbbb706077777777770607bbbbbbbbb7777bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 74 | bbbbbbbbbbb707777767767777707bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 75 | bbbbbbbbbbbb7007760000677007bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 76 | bbbbbbbbbbbbb77060777706077bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 77 | bbbbbbbbbbbbbbb7070000707bbbbbbbbb5666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 78 | bbbbbbbbbbbbbbbb70555507bbbbbbbbbb5777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777776 79 | bbbbbbbbbbbbbbbbb700007bbbbbbbbbbb5776777777667777777777677677777766677777777776667677777776666777776777667777777777776677767776 80 | bbbbbbbbbbbbbbbbbb7777bbbbbbbbbb6777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777775bb 81 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb6777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777775bb 82 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb6777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777775bb 83 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb5777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777776 84 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb5777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777776 85 | bb777777777777bbbbbbbbbbbbbbbbbbbb5777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777776 86 | b70000000000007bbbbbbbbbbbbbbbbb6777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777775bb 87 | b70777007707707bbbbbbbbbbbbbbbbb6777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777775bb 88 | b70700000000707bbbbbbbbbbbbbbbbb6777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777775bb 89 | b70700000070707bbbbbbbbbbbbbbbbbbb5766677777776776777777777777766777777777777777767677777777777777776766767777777777777777777776 90 | b70770000000707bbbbbbbbbbbbbbbbbbb5777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777776 91 | b70700000000707bbbbbbbbbbbbbbbbbbb5666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 92 | b70770777007707bbbbbbbbbbbbbbbbbbb5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555 93 | b70000000000007bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 94 | bb777777777777bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 95 | bbb8888288828bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 96 | bbbb27782888bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 97 | bbbb82888288bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 98 | bbbbb828882bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 99 | bbbbbb8288bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 100 | bbbbbbb82bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 101 | bbbbb888888bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 102 | bbb8877777788bbbbb777777777777bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 103 | bb877000000778bbb77000000000076bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 104 | b87007777770078bb70777077777706bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 105 | 8870700000070788b70787777878706bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 106 | 8707000000007078b70787787777706bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 107 | 8707000000007078b70787777778706bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 108 | 8770000000000778b70777777777706bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 109 | 8707000000007078b70787070700006bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 110 | 8707000000007078b70777770777706bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb8bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 111 | 88707000000707d8b77000000000076bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb8888bbbbbbbbbbbbbbbbbbbbb88bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 112 | 2870077777700782b77777777777776bbbbbbbbbbbbbbbbbbbbbbbbbb8888bbbbbb8822887777bbbbbbbbbbbbbbb882bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 113 | 2287700000077822b77888888888876bbbbbbbbbbbbbbbbbbbbbbbbbb82228bbbb822bb288887777777bbbbbbbb882bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 114 | b22887777778822bb77877888888876bbbbbbbbbbbbbbbbbbbbbbbbb88bbb88bb88bbbb7288888888887bbbbbb882bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 115 | bbb2288888822bbbb67888888888876bbbbbbbbbbbbbbbbbbbbbbbbb22bbb288888bbb7288888888888877777882bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 116 | bbbbb222222bbbbbbb622222222226bbbbbbbbbbbbbbbbbbb8bbbbbbbbbbbb22228b77288888888888888888882bbbbbbbbbbbbbbbb888bbbbbbbbbbbbbbbbbb 117 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb288bbbbbbbbbbbbbb8822888888888888888888827bbbbbbbbbbbbbb88822bbbbbbbbbbbbbbbbbb 118 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb288888bbbbbbbbbb7288888888888888888888887bbbbbbbbbbbbb8822bbbbbbbbbbbbbbbbbbbb 119 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb222228bbbbbbbb728888888888888888888888887bbbbbbbbbbb882bbbbbbbbbbbbbbbbbbbbbb 120 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb8b8bbbbbb72888888888888888888888888887bbbbbbbbb882bbbbbbbbbbbbbbbbbbbbbbb 121 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb8b88bbbb728888888888888888888888888887bbbbbbb8822bbbbbbbbbbbbbbbbbbbbbbbb 122 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb8b8888b728888888888888888888888888887bbbbb8882bbbbbbbbbbbbbbbbbbbbbbbbbb 123 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb88bbb8872888888888878888888888888888777788822bbbbbbbbbbbbbbbbbbbbbbbbbbb 124 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb8bbbb8828888888887b77777888888888888888222bbbbbbbbbbbbbbbbbbbbbbbbbbbbb 125 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb7728888888887bbbbbb778888888888882bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 126 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb8bbbb72288888888887bbbbbbbb77777788888887bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 127 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb88bbb7288888888888887bbbbbbbbbbbbb788888887bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 128 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb888888bbbb728888888888888887bbbbbbbbbbbb7888888887bbbbbbbbbbbbbbbbbbbbbbbbbbbbb 129 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb22222888bb7288888888888888887bbbbbbbbbbb7888888887bbbbbbbbbbbbbbbbbbbbbbbbbbbbb 130 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb22888888888888888888888877777bbbbbbb7888888887bbbbbbbbbbbbbbbbbbbbbbbbbbbb 131 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb22288888888888888888888888877777bb78888888887bbbbbbbbbbbbbbbbbbbbbbbbbbb 132 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb72888888877777788888888888888887bb78888888887bbbbbbbbbbbbbbbbbbbbbbbbbbb 133 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb728888887bbbbbb778888888888888887788888888887bbbbbbbbbbbbbbbbbbbbbbbbbbb 134 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb7288888887bbbbbbb7888888888888888888888888887bbbbbbbbbbbbbbbbbbbbbbbbbbb 135 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb7288888888777bbbbb788888888888888888888888887bbbbbbbbbbbbbbbbbbbbbbbbbbb 136 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb7288888888887777b788888888888888888888888887bbbbbbbbbbbbbbbbbbbbbbbbbbb 137 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb7288888888888887888888888888888888888888827bbbbbbbbbbbbbbbbbbbbbbbbbbb 138 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb728888888888888888888888888888888888888827bbbbbbbbbbbbbbbbbbbbbbbbbbbb 139 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb7288888888888888888878888888888888888877bbbbbbbbbbbbbbbbbbbbbbbbbbbbb 140 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb7288888888888888887b778888888888888887bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 141 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb7888888888888888887bbb7778888888888888bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 142 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb88828888888888888887bbbbbb77788888888288bbbbbbbbbbbbbbbbbbbbbbbbbbbbb 143 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb88227288888888888888877bbbbbbb788888877288bbbbbbbbbbbbbbbbbbbbbbbbbbbb 144 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb882bbb72888888888888888877bbbbbb7888877bb2888bbbbbbbbbbbbbbbbbbbbbbbbbb 145 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb882bbbbb728888888888888888877777788887bbbbb228888bbbbbbbbbbbbbbbbbbbbbbb 146 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb882bbbbbbb7288888888888888888888888887bbbbbbbb22288bbbbbbbbbbbbbbbbbbbbbb 147 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb8882bbbbbbbbb72288888888888888888888887bbbbbbbbbbbb288bbbbbbbbbbbbbbbbbbbbb 148 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb8888822bbbbbbbbbbb772288888888888888888887bbbbbbbbbbbbbb28bbbbbbbbbbbbbbbbbbbbb 149 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb2288888bbbbbbbbbbbbb7722888888888888888827bbbbbbbbbbbbbbb88bbbbbbbbbbbbbbbbbbbb 150 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb22222888bbbbbbbbbbbb7288888888882222287bbbbbbbbbbbbbbbb22bbbbbbbbbbbbbbbbbbbb 151 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb22288bbbbbb88888882888888227777728bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 152 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb288888888222222722888277bbbbb288bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 153 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb22222222bbbbbbb772227bbbbbbbb2888bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 154 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb777bbbbbbbbbb228bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 155 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb88bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 156 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb22bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 157 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb222222222222222222222222222222222222222222222222222222222222222bbbbbbbbbbbbbbbb 158 | b7777bbbbbb777bbbbb777777bbbbbb777b7777777bbbbbbbbb888888888998888899888888888888888888888888888888888888888888bbbbbbbbbbbbbbbbb 159 | bb777bbbbb7777bbb7777777777bbbb777b777777777bbbbbbbbbbb8889998888999888889888888898888888988888888888888898888bbbbb3bbbbbbbbbbbb 160 | bb777bbbbb777bbb777777777777bbb777b7777777777bbbbbbbbbbb8898888888888888899888888988888889888888888888899988bbbbbb33333bbbbbbbbb 161 | bb7777bbbb777bb77777bbbb77777bb777b777bbbb7777bbbbbbbbbbb8888bb8eeeee888898888888998ee88898888888888888988bbbbbbbbb33424bbbbbbbb 162 | bbb777bbb7777bb777bbbbbbbb777bb777b777bbbbb777bbbbbbbbbbb88bbbbbbbbbbbbb8988bbbb898bbbb8898b88eeee8888998bbbbbbbbbb343222bbbbbbb 163 | bbb777bbb777bb7777bbbbbbbb7777b777b777bbbbbb777bbbbbbbbbbb8bbbbbbbbb8bbb888bbbb8898bbbbb888bbbbbbbb8888bbbbbbbbbbbb4222222bbbbbb 164 | bbb7777bb777bb777bbbbbbbbbb777b777b777bbbbbb777bbbbbbbbbbbbbbbbbbbbbbbb888ebbbb8888bbbbbb88bbbb8bbb8888bbbbbbbbbbbb4222222222bbb 165 | bbbb777b7777bb777bbbbbbbbbb777b777b777bbbbbb777bbbbbbbbbbbbbbbbbbbbbbbb88bebbbb888bebbbbb88bbbbbbbbb888bbbbbbbbbbbb44222222d22bb 166 | bbbb666b666bbb666bbbbbbbbbb666b666b666bbbbbb666bbbbbbbbbbbbbebbbbbbbbbbb8bbbbbb8bbbbbbbbb8ebbbbbbbbb88bbbbbbbbbbbbbb44222222d22b 167 | bbbb666b666bbb6666bbbbbbbb6666b666b666bbbbbb666bbbbbbbbbbbbbbbbbbbbbbbb88bbbbbb8bb8bbbbbbebb8bbebbbb8bbbbbbbbbbbbbbb44222222dd2b 168 | bbbbb666666bbbb666bbbbbbbb666bb666b666bbbbb666bbbbbbbbbbbebbbbbbb8bbbbbbbbbbbbbb8bbbbbbbbbebbbbbbbbbbbbbbbbbbbbbbbbbb4442222d22b 169 | bbbbb66666bbbbb66666bbbb66666bb666b666bbbb6666bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb44222d222b 170 | bbbbb66666bbbbbb666666666666bbb666b6666666666bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb44422244b 171 | bbbbbb6666bbbbbbb6666666666bbbb666b666666666bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb444444bb 172 | bbbbbb666bbbbbbbbbb666666bbbbbb666b6666666bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 173 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 174 | b77777777bbbbb77777777bbbbbbbbbb777777bbbbb777777777777bbbbb777777bbbbbbbbbbb777777bbbbbbbb777777bbbbbb777bbbbbbbbbbbbbbbbbbbbbb 175 | b7777777777bbb7777777777bbbbbb7777777777bbb777777777777bbb7777777777bbbbbbb7777777777bbbb7777777777bbbb777bbbbbbbbbbbbbbbbbbbbbb 176 | b77777777777bb77777777777bbbb777777777777bb777777777777bb777777777777bbbbb77777777777bbb777777777777bbb777bbbbbbbbbbbbbbbbbbbbbb 177 | b777bbbbb777bb777bbbbb777bbb77777bbbb77777bbbbbb777bbbbb77777bbbb77777bbb77777bbbb77bbb77777bbbb77777bb777bbbbbbbbbbbbbbbbbbbbbb 178 | b777bbbbbb777b777bbbbbb777bb777bbbbbbbb777bbbbbb777bbbbb777bbbbbbbb777bbb777bbbbbbbbbbb777bbbbbbbb777bb777bbbbbbbbbbbbbbbbbbbbbb 179 | b777bbbbbb777b777bbbbbb777b7777bbbbbbbb7777bbbbb777bbbb7777bbbbbbbb7777b7777bbbbbbbbbb7777bbbbbbbb7777b777bbbbbbbbbbbbbbbbbbbbbb 180 | b777bbbbbb777b777bbbbbb777b777bbbbbbbbbb777bbbbb777bbbb777bbbbbbbbbb777b777bbbbbbbbbbb777bbbbbbbbbb777b777bbbbbbbbbbbbbbbbbbbbbb 181 | b777bbbbbb777b777bbbbbb777b777bbbbbbbbbb777bbbbb777bbbb777bbbbbbbbbb777b777bbbbbbbbbbb777bbbbbbbbbb777b777bbbbbbbbbbbbbbbbbbbbbb 182 | b666bbbbb666bb666bbbbb666bb666bbbbbbbbbb666bbbbb666bbbb666bbbbbbbbbb666b666bbbbbbbbbbb666bbbbbbbbbb666b666bbbbbbbbbbbbbbbbbbbbbb 183 | b66666666666bb66666666666bb6666bbbbbbbb6666bbbbb666bbbb6666bbbbbbbb6666b6666bbbbbbbbbb6666bbbbbbbb6666b666bbbbbbbbbbbbbbbbbbbbbb 184 | b6666666666bbb6666666666bbbb666bbbbbbbb666bbbbbb666bbbbb666bbbbbbbb666bbb666bbbbbbbbbbb666bbbbbbbb666bb666bbbbbbbbbbbbbbbbbbbbbb 185 | b66666666bbbbb666666666bbbbb66666bbbb66666bbbbbb666bbbbb66666bbbb66666bbb66666bbbb66bbb66666bbbb66666bb666bbbbbbbbbbbbbbbbbbbbbb 186 | b666bbbbbbbbbb666bbbb666bbbbb666666666666bbbbbbb666bbbbbb666666666666bbbbb66666666666bbb666666666666bbb66666666666bbbbbbbbbbbbbb 187 | b666bbbbbbbbbb666bbbb666bbbbbb6666666666bbbbbbbb666bbbbbbb6666666666bbbbbbb6666666666bbbb6666666666bbbb66666666666bbbbbbbbbbbbbb 188 | b666bbbbbbbbbb666bbbb6666bbbbbbb666666bbbbbbbbbb666bbbbbbbbb666666bbbbbbbbbbb666666bbbbbbbb666666bbbbbb66666666666bbbbbbbbbbbbbb 189 | __label__ 190 | 77777777777777777777777777777777777777777777777777777777777777765777777777777777777777777777777777777777777777777777777777777777 191 | 77777777777777777777777777777777777777777777777777777777777775677777777777777777777777777777777777777777777777777777777777777777 192 | 77777777777777777777777777777777777777777777777777777777777775677777777777777777777777777777777777777777666677776677777777777777 193 | 77777777777777777777777777777777777777777777777777777777777775677777777777777777777777777777777777777677777777777777767777777777 194 | 67777777777777777676777777777777777767667677777777777777777777765766677777776776777777777777766777776777777777777777776777777777 195 | 77777777777777777777777777777777777777777777777777777777777777765777777777777777777777777777777777777777777777777777777777777777 196 | 66666666666666666666666666666666666666666666666666666666666666665666666666666666666666666666666666677775555555555555577776666666 197 | 55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555677750000000000000057776555555 198 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000667502222222222222205766000000 199 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066520000000000000026660000000 200 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000008888888888888800000000000 201 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000088877788888888880000000000 202 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000088888888888888880000000000 203 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008888888888888800000000000 204 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 205 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 206 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 207 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 208 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 209 | 00000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 210 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 211 | 00000000000000000000000000000000000000077770000007770000077777700000077707777777000000000000000000000000000000000000000000000000 212 | 00000000000000000000000000000000000000007770000077770007777777777000077707777777770000000000000000000000000000000000000000000000 213 | 00000000000000000000000000000000000000007770000077700077777777777700077707777777777000000000000000000000000000000000000000000000 214 | 00000000000000000000000000000000000000007777000077700777770000777770077707770000777700000000000000000000000000000000000000000000 215 | 00000000000000000000000000000000000000000777000777700777000000007770077707770000077700000000000000000000000000000000000000000000 216 | 00000000000000000000000000000000000000000777000777007777000000007777077707770000007770000000000000000000000000000000000000000000 217 | 00000000000000000000000000000000000000000777700777007770000000000777077707770000007770000000000000000000000000000000000000000000 218 | 00000000000000000000000000000000000000000077707777007770000000000777077707770000007770000000000000000000000000000000000000000000 219 | 00000000000000000000000000000000000000000066606660006660000000000666066606660000006660000000000000000000000000000000000000000000 220 | 00000000000000000000000000000000000000000066606660006666000000006666066606660000006660000000000000000000000000000000000000000000 221 | 00000000000000000000000000000000000000000006666660000666000000006660066606660000066600000000000000000000000000000000000000000000 222 | 00000000000000000000000000000000000000000006666600000666660000666660066606660000666600000000000000000000000000000000000000000000 223 | 00000000500000000000000000000000000000000006666600000066666666666600066606666666666000000000000000000000000000000000000000000000 224 | 00000000000000000000000000000000000000000000666600000006666666666000066606666666660000000000000000000000000000000000000000000000 225 | 00000000000000000000000000000000000000000000666000000000066666600000066606666666000000000000000000000000000000000000000000000000 226 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 227 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 228 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 229 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 230 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 231 | 00000000777777770000077777777000000000077777700000777777777777000007777770000000000077777700000000777777000000777000000000000000 232 | 00000000777777777700077777777770000007777777777000777777777777005777777777700000007777777777000077777777770000777000000000000000 233 | 00000000777777777770077777777777000077777777777700777777777777007777777777770000077777777777000777777777777000777000000000000000 234 | 00000000777000007770077700000777000777770000777770000007770000077777000077777000777770000770007777700007777700777000000000000000 235 | 00000000777000000777077700000077700777000000007770000007770000077700000000777000777000000000007770000000077700777000000000000000 236 | 00000000777000000777077700000077707777000000007777000007770000777700000000777707777000000000077770000000077770777000000000000000 237 | 00000000777000000777077700000077707770000000000777000007770000777000000000077707770000000000077700000000007770777000000000000000 238 | 00000000777000000777077700000077707770000000000777000007770000777000000000077707770000000000077700000000007770777000000000000050 239 | 00000000666000006660066600000666006660000000000666000006660000666000000000066606660000000000066600000000006660666000000000000050 240 | 00000000666666666660066666666666006666000000006666000006660000666600000000666606666000000000066660000000066660666000000000000000 241 | 00000000666666666600066666666660000666000000006660000006660000066600000000666000666000000000006660000000066600666000000000000000 242 | 00000000666666660000066666666600000666660000666660000006660000066666000066666000666660000660006666600006666600666000000000000000 243 | 00000000666000000000066600006660000066666666666600000006660000006666666666660000066666666666000666666666666000666666666660000000 244 | 00000000666000000000066600006660000006666666666000000006660000000666666666600000006666666666000066666666660000666666666660000000 245 | 00000000666000000000066600006666000000066666600000000006660000000006666660000000000066666600000000666666000000666666666660000000 246 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 247 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 248 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 249 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 250 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 251 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 252 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 253 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 254 | 00000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 255 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 256 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 257 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 258 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 259 | 00000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000 260 | 00000000000000000000000000000000000000000000000000000000000000070070000000000000000000000000000000000000000000000000000000000000 261 | 00000000000000000000000000000000000000000000000000000000000007707707700000000000000000000000000000000000000000000000000000000000 262 | 00000000000000000000000000000000000000000000000000000000000070707707070000000000000000000000000000000000000000000000000000000000 263 | 00000000000000000000000000000000000000000000000000000000000707077770707000000000000000000000000000000000000000000000000000000000 264 | 00000000000000000000000000000000000000000000000000000000000707076670707000000000000000000000000000000000000000000000000000000000 265 | 00000000000000000000000000000000000000000000000000000000000707060060707000000000000000000000000000000000000000000000000000000000 266 | 00000000000000000000000000000000000000000000000000000000007077007700770700000000000000000000000000000000000000000000000000000000 267 | 00000000000000000000000000000000000000000000000000000000070777077770777070000000000000000000000000000000000000000000000000000000 268 | 00000000000000000000000000000000000000000000000000000000707607070070706707000000000000000000000000000000000000000000000000000000 269 | 00000000000000000000000000000000000000000000000000000000707607700007706707000000000000000000000000000000000000000000000000000000 270 | 00000000500000000000000000000000000000000000000000000000707607766667706707000000000000000000000000000000000000000000000000000000 271 | 00000000500000000000000000000000000000000000000000000000706077777777770607000000000000000000000000000000000000000000000000000000 272 | 00000000000000000000000000000000000000000000000000000000707777767767777707000000000000000000000000000000000000000000000000000000 273 | 00000000000000000000000000000000000000000000000000000000070077600006770070000000000000000000000000000000000000000000000000000000 274 | 00000000000000000000000000000000000000000000000000000000007706077770607700000000000000000000000000000000000000000000000000000000 275 | 00000000000000000000000000000000000000000000000000000000000070700007070000000000000000000000000000000000000000000000000000000000 276 | 00000000000000000000000000000000000000000000000000000000000007055550700000000000000000000000000000000000000000000000000000000000 277 | 00000000000000000000000000000000000000000000000000000000000000700007000000000000000000000000000000000000000000000000000000000000 278 | 00000000000000000000000000000000000000000000000000000000000000077770000000000000000000000000000000000000000000000000000000000000 279 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 280 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 281 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 282 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 283 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 284 | 00000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000 285 | 00000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000 286 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 287 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 288 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 289 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 290 | 00000000000000000000000000000000000000000000077077707770777077700000077077707770777000000000000000000000000000000000000000000000 291 | 00000000000000000000000000000000000000008000700007007070707007000000700070707770700000800000000000000000000000000000000000000000 292 | 00000000000000000000000000000000000000008800777007007770770007000000700077707070770008800000000000000000000000000000000000000000 293 | 00000000000000000000000000000000000000008200007007007070707007000000707070707070700002800000000000000000000000000000000000000000 294 | 00000000000000000000000000000050000000002000770007007070707007000000777070707070777000200000000000000000000000000000000000000000 295 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 296 | 00000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 297 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 298 | 00000000000000000000000000000000000000000000000055505050555005505550555055505000000000000000000000000000000000000000000000000000 299 | 00000000000000000000000000000000000000000000000005005050050050505050050050505000000000000000000000000000000000000000000000000000 300 | 00000000000000000000000000000000000000000000000005005050050050505500050055505000000000000000000000000000000000000000000000000000 301 | 00000000000000000000000000000000000000000000000005005050050050505050050050505000000000000000000000000000000000000000000000000000 302 | 00000000000000000000000000000000000000000000000005000550050055005050555050505550000000000000000000000000000000000000000000000000 303 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 304 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 305 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 306 | 00000000000000000000000000000000000000000000000000055055505550550055505550055000000000000000000000000000000000000000000000000000 307 | 00000000000000000000000000000000000000000000000000500050505000505005000500500000000000000000000000000000000000000000000000000000 308 | 00000000000000000000000000000000000000000000000000500055005500505005000500555000000000000000000000000000000000000000000000000000 309 | 00000000000000000000000000000000000000000000000000500050505000505005000500005000000000000000000000000000000000000000000000000000 310 | 00000000000000000000000000000000000000000000000000055050505550555055500500550000000000000000000000000000000000000000000000000000 311 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 312 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 313 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 314 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 315 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 316 | 00000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 317 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 318 | 319 | __map__ 320 | 040500cecf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 321 | 141500dedf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 322 | __sfx__ 323 | 0103000002553035250651300503005030050311503135031a5031f50320503005030050300503005030050300503005030050300503005030050300503005030050300503005030050300503005030050300503 324 | 010200200c724007510c721007510c721007510c721007510c731007510c731007510c731007510c731007510c741007510c741007510c741007510c741007510c731007510c731007510c731007510c73100751 325 | 014600010061300600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600 326 | 010200200c724007510c721007510c721007510c721007510c731007510c731007510c731007510c731007510c741007510c741007510c741007510c741007510c731007510c731007510c731007510c73100751 327 | 010200213c5143f524245003c5143f514245003c3143f314245003c3143f314245003b5243e514245003c5143f514245003c5143f514245003c3143f314245003c7143f714245003b5143e5143f3243c3143f514 328 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 329 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 330 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 331 | 0002000002070050700a0700165006000060000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500 332 | 000700000045500405004550140600406004060140600406004060040600406004060040600406004060040600406004060040600406004060040600406004060040600406004060040600406004060040600406 333 | 000200000c07002070030000000006000060000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500 334 | 01010000055500c5500e5000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500 335 | 010100000c550065500e5000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500 336 | 010e00000c043102151021524303246101861524303102150c043243031021510215246101203403041000410c043001051021510215246101861510215003040c04310215000051021524610000140c02118031 337 | 010e00000c0450015500140000350c043001400003500324001550014000035001400c0431861512215003240c0450015500140000350c043001400003500324001550014000035001400c043186151221500324 338 | 010e00000c0430010500100000050c0430010000005003040c0430010000005001000c0431202403031000310c0430010500100000050c0430010000005003040c0430010000005001000c043000140c01118021 339 | 010e00000c0450015500140000350015500140000350032400155001400003500140000351861430600003240c045001550014000035001550014000035003240015500140000350014000035186143060000324 340 | 010e00000c043102151021500005246101861500005102150c043001001021510215246101200403000000000c043001051021510215246101861510215003040c04310215000051021524610000040c00018000 341 | 010e00000c0450015500150000050c043001500000500304001550015000005001500c0431861512215003040c0450015500150000050c043001500000500304001550015000005001500c043186151221500304 342 | 000200000277002770027700277002770027700277002770027000270002700027000270002700027000270000700027000270002700027000270002700027000270002700027000270002700027000270002700 343 | 000200000007003070000700500005000040000400004000040000300003000030000500003000030000300003000050000300003000030000300002000010000100001000010000200003000030000400004000 344 | 000200000057003570005700320004200045000450004500045000350003500035000550003500035000350003500055000350003500035000350002500015000150001500015000250003500035000450004500 345 | 000200000157005570045700720009200045000450004500045000350003500035000550003500035000350003500055000350003500035000350002500015000150001500015000250003500035000450004500 346 | 000200000357007570095701020013200045000450004500045000350003500035000550003500035000350003500055000350003500035000350002500015000150001500015000250003500035000450004500 347 | 000100000a0700c0700d0700047000470014700147002470014700060000600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600 348 | 010d00000c0530445504255134453f6150445513245044550c0531344513245044553f6150445513245134450c0530445504255134453f6150445513245044550c0531344513245044553f615044551324513445 349 | 010d000028555234452d2352b5552a4452b2352f55532245395303725536540374353b2503954537430342553654034235325552f2402d5352b2502a4452b530284552624623530214551f24023535284302a245 350 | 010d00002b5552a4452823523555214451f2351e5551c4452b235235552a445232352d5552b4452a2352b555284452a235285552644523235215551f4451c2351a555174451e2351a5551c4451e2351f55523235 351 | 010d00000c0530045500255104453f6150045510245004550c0530044500245104553f6150045510245104450c0530045500255104453f6150045510245004550c0531044510245004553f615004551024500455 352 | 010d00000c0530245502255124453f6150245512245024550c0531244512245024553f6150245502255124450c0530245502255124453f6150245512245024550c0530244512245024553f615124550224512445 353 | 010d00002b5552a45528255235552b5452a44528545235452b5352a03528535235352b0352a03528735237352b0352a03528735237351f7251e7251c725177251f7151e7151c715177151371512715107150b715 354 | 018800000074400730007320073200730007300073200732007300073200730007320073000732007320073200732007300073000730007320073000730007300073200732007300073000732007300073200732 355 | 01640020070140801107011060110701108011070110601100013080120701106511070110801707012060110c013080120701106011050110801008017005350053408010070110601100535080170701106011 356 | 018800000073000730007320073200730007300073200732007300073200730007320073000732007320073200732007300073000730007320073000730007300073200732007300073000732007300073200732 357 | 0164002006510075110851707512060110c0130801207011060110501108017070120801107011060110701108011075110651100523080120701108017005350053408012070110601100535080170701106511 358 | 012800202ec202dc0125c2130c0131c011dc012dc212dc0130c0126c0132c2132c0120c212fc012fc0122c0132c2124c0132c212fc012fc012fc0132c2131c0119c2131c0132c212fc002fc2131c011ec2130c00 359 | 010c00201800018000180002ec2439c2525c0530c0531c05180001800018000000002fc163ac1625c0530c0531c0524c052fc163ac1625c0530c0532c052fc0523c052fc0532c0531c0531c203cc210000000000 360 | 01b100010cb2118803188031880318803188031880318803188031880318803188031880318803188031880318803188031880318803188031880318803188031880318803188031880318803188031880318803 361 | 0001000005650096500e6500645003450024501440014400006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600 362 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 363 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 364 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 365 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 366 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 367 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 368 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 369 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 370 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 371 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 372 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 373 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 374 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 375 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 376 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 377 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 378 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 379 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 380 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 381 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 382 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 383 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 384 | 018c00200c9600d9510c9410e9510b9610d9510c9410e9510c9610d9510c9410e9510b9610d9510c9410e9510c9610d9510c9410e9510b9610d9510c9410e9510c9610d9510c9410e9510b9610d9510c9410e951 385 | 01b4001f0171002711017110371100711027110171103711017210272101711037110071102711017110371101711027110171103711007110271101711037110171102711017110371100721027210171103711 386 | 0178002000a1400a1500a1418a250090400a1418a1500a1400a150090400a140ca1518a1400a1500a1418a1500a1400a25009040ca1400a1500a2400a15009040ca1418a1500a2400a150090400a140ca2500000 387 | __music__ 388 | 03 3d3e3f47 389 | 01 0f104344 390 | 00 0f104344 391 | 00 0d0e4344 392 | 00 4d0e4344 393 | 00 51124344 394 | 02 11124344 395 | 01 19424344 396 | 00 1c424344 397 | 00 1d424344 398 | 00 19424344 399 | 00 191b4344 400 | 00 1c1b4344 401 | 00 1d1a4344 402 | 02 191e4344 403 | 01 1f204344 404 | 03 21224344 405 | 03 23242544 406 | 407 | --------------------------------------------------------------------------------