Shots that miss are most likely to not be there yet, so check Y-top first. If I assume shots will never be larger than 16 pixels per side, there is no reason to check the ship's genuine width and height.
2147 lines
66 KiB
Lua
2147 lines
66 KiB
Lua
pico-8 cartridge // http://www.pico-8.com
|
|
version 42
|
|
__lua__
|
|
-- vacuum gambit
|
|
-- by kistaro windrider
|
|
|
|
game = 1
|
|
win = 2
|
|
lose = 3
|
|
|
|
function usplit(str)
|
|
return unpack(split(str))
|
|
end
|
|
function csv(s)
|
|
local ret=split(s,"\n")
|
|
for i,v in ipairs(ret) do
|
|
ret[i] = type(v) == "string" and split(v) or {v}
|
|
end
|
|
return ret
|
|
end
|
|
function const_fxn(x)
|
|
return function()
|
|
return x
|
|
end
|
|
end
|
|
|
|
-- generate standard "overlay"
|
|
-- constructor for type tt.
|
|
-- if tt.init is defined, generated
|
|
-- new calls tt.init(ret) after
|
|
-- ret is definitely not nil,
|
|
-- after calling setmetatable.
|
|
-- use to initialize mutables.
|
|
--
|
|
-- if there was a previous new,
|
|
-- it is invoked before
|
|
-- setting tt's metatable, so
|
|
-- each new will see its
|
|
-- inheritance chain.
|
|
function mknew(tt)
|
|
local mt,oldinit,more = {__index=tt},tt.superinit,rawget(tt, "init")
|
|
tt.new=function(ret)
|
|
if(not ret) ret = {}
|
|
ret.new = false
|
|
setmetatable(ret, mt)
|
|
if(oldinit) oldinit(ret)
|
|
if (more) more(ret)
|
|
return ret
|
|
end
|
|
|
|
if oldinit and more then
|
|
tt.superinit = function(ret)
|
|
oldinit(ret)
|
|
more(ret)
|
|
end
|
|
elseif more then
|
|
tt.superinit = more
|
|
end
|
|
return tt
|
|
end
|
|
|
|
-- call f on everything on list
|
|
-- and return a new list of
|
|
-- items for which f was true.
|
|
function filtered(list, f)
|
|
local ret, n = {}, 0
|
|
for v in all(list) do
|
|
if f(v) then
|
|
n += 1
|
|
ret[n] = v
|
|
end
|
|
end
|
|
return ret
|
|
end
|
|
|
|
-- call :move on everything on
|
|
-- src and dump everything
|
|
-- for which it returned true
|
|
-- onto dest.
|
|
function appendmove(dest, src)
|
|
local n = #dest
|
|
for v in all(src) do
|
|
if v:move() then
|
|
n += 1
|
|
dest[n] = v
|
|
end
|
|
end
|
|
end
|
|
|
|
-- like filtered, but calls
|
|
-- :move on stuff in the list
|
|
-- instead of taking a func arg.
|
|
function filtermoved(list)
|
|
local ret, n = {}, 0
|
|
for v in all(list) do
|
|
if v:move() then
|
|
n += 1
|
|
ret[n] = v
|
|
end
|
|
end
|
|
return ret
|
|
end
|
|
|
|
function _init()
|
|
mode = game_mode
|
|
init_blip_pals()
|
|
wipe_game() -- redundant?
|
|
game_state = game
|
|
pal(2,129)
|
|
pal()
|
|
end
|
|
|
|
function once_next_frame(f)
|
|
add(new_events, {
|
|
move = function()
|
|
f()
|
|
return true
|
|
end,
|
|
})
|
|
end
|
|
|
|
-- health gradients for 1..5 hp
|
|
-- exactly, then all "more".
|
|
hpcols_lut = csv[[36
|
|
34, 136
|
|
34, 130, 136
|
|
34, 34, 130, 136
|
|
34, 34, 130, 130, 136]]
|
|
|
|
-- call after any change to maxhp
|
|
-- configures health gradient
|
|
function init_hpcols()
|
|
hpcols = hpcols_lut[min(primary_ship.maxhp,6)]
|
|
end
|
|
|
|
function wipe_game()
|
|
xpwhoosh = nil
|
|
primary_ship = player.new()
|
|
init_hpcols()
|
|
eships = {}
|
|
pbullets ={}
|
|
ebullets ={}
|
|
intangibles_fg = {}
|
|
intangibles_bg = {}
|
|
events = {}
|
|
new_events = {}
|
|
primary_ship.main_gun = zap_gun_p.new()
|
|
primary_ship.main_gun:peel()
|
|
gframe = 0
|
|
interlude = 0
|
|
waves_complete = 0
|
|
current_wave = nil
|
|
end
|
|
|
|
function _update60()
|
|
mode:update()
|
|
ustat = stat(1)
|
|
end
|
|
|
|
function ones(n)
|
|
local ret = 0
|
|
while n != 0 do
|
|
if (n&0x0.0001) ret += 1
|
|
n >>= 1
|
|
end
|
|
return ret
|
|
end
|
|
|
|
function updategame()
|
|
local ps = primary_ship
|
|
if (ps.xp >= ps.xptarget) and (gframe - ps.last_xp_frame > 0x0.000f) and (not ps.dead) then
|
|
mode = rearm_mode.new()
|
|
return _update60()
|
|
end
|
|
gframe += 0x0.0001
|
|
if current_wave then
|
|
if current_wave:update() then
|
|
-- end of stage
|
|
waves_complete += 1
|
|
current_wave = nil
|
|
if waves_complete < 32767 then
|
|
interlude = 59 -- plus one dead frame with load_level but no update
|
|
else
|
|
-- you maxed out the level
|
|
-- counter. what the fuck
|
|
-- is wrong with you?
|
|
-- go outside.
|
|
--
|
|
-- do not spawn more levels.
|
|
interlude = 32767
|
|
end
|
|
end
|
|
elseif interlude > 0 then
|
|
interlude -= 1
|
|
else
|
|
current_wave = flotilla.new()
|
|
current_wave:load(rnd() > 0.5 and 7 or 0, 0, min(ones(waves_complete)\2, 4))
|
|
end
|
|
events = filtermoved(events)
|
|
appendmove(events, new_events)
|
|
new_events = {}
|
|
intangibles_bg = filtermoved(intangibles_bg)
|
|
eships = filtermoved(eships)
|
|
|
|
-- eship collider will be used
|
|
-- both for pship and pbullets.
|
|
local eship_collider = collider.new{from=eships}
|
|
|
|
if not ps.dead then
|
|
ps:move()
|
|
local pbox = hurtbox(ps)
|
|
for es in eship_collider:iterate_collisions(pbox) do
|
|
ps:hitship(es)
|
|
es:hitship(ps)
|
|
end
|
|
ebullets = filtered(ebullets, function(eb)
|
|
if (not eb:move()) return
|
|
if (not collides(pbox, hurtbox(eb))) return true
|
|
ps:hitbullet(eb)
|
|
return not eb:hitship(ps)
|
|
end)
|
|
else
|
|
ebullets=filtermoved(ebullets)
|
|
end
|
|
|
|
pbullets = filtered(pbullets, function(pb)
|
|
if (not pb:move()) return
|
|
for es in eship_collider:iterate_collisions(hurtbox(pb)) do
|
|
es:hitbullet(pb)
|
|
if (pb:hitship(es)) return
|
|
end
|
|
return true
|
|
end)
|
|
|
|
intangibles_fg = filtermoved(intangibles_fg)
|
|
|
|
if waves_complete == 32767 and #eships == 0 and #ebullets == 0 and #events == 0 then
|
|
game_state = win
|
|
end
|
|
if (ps.dead) game_state = lose
|
|
|
|
if ps.xp >= ps.xptarget then
|
|
if not xpwhoosh then
|
|
xpwhoosh = 0
|
|
else
|
|
xpwhoosh += 1
|
|
if (xpwhoosh > 60) xpwhoosh = 0
|
|
end
|
|
else
|
|
xpwhoosh = nil
|
|
end
|
|
end
|
|
|
|
function _draw()
|
|
mode:draw()
|
|
local ds = stat(1)
|
|
print(tostr(ustat).." + "..tostr(ds-ustat), 0, 122, 7)
|
|
end
|
|
|
|
function drawgame_top()
|
|
camera()
|
|
fillp(0)
|
|
drawgame()
|
|
if (game_state == game) fadelvl = -45
|
|
if (game_state == win) dropshadow("win",50,61,11)
|
|
if (game_state == lose) dropshadow("fail",48,61,8)
|
|
fadescreen()
|
|
end
|
|
|
|
game_mode = {
|
|
update = updategame,
|
|
draw = drawgame_top,
|
|
}
|
|
|
|
fadetable = split"0,1.5,1025.5,1029.5,1285.5,1413.5,9605.5,9637.5,-23130.5,-23066.5,-18970.5,-18954.5,-2570.5,-2568.5,-520.5,-8.5,-0.5"
|
|
|
|
function fadescreen()
|
|
fadelvl += 0.25
|
|
if (fadelvl < 1) return
|
|
local i = min(flr(fadelvl), #fadetable)
|
|
fillp(fadetable[#fadetable+1-i])
|
|
rectfill(0,0,128,128,0)
|
|
end
|
|
|
|
-- puke emits a verbose string
|
|
-- describing item, indented to
|
|
-- the specified depth (0 by
|
|
-- default). used for table
|
|
-- debugging. table-type keys
|
|
-- are not legible here
|
|
function puke(item, indent, seen, hidekey)
|
|
if (type(item) ~= "table") return tostr(item)
|
|
|
|
seen = seen or {}
|
|
if (seen[item]) return "<<...>>"
|
|
seen[item] = true
|
|
|
|
indent = indent or 0
|
|
local pfx = "\n"
|
|
for _=1,indent do
|
|
pfx ..= " "
|
|
end
|
|
local xpfx = pfx.." "
|
|
|
|
local ret = "{"
|
|
for k, v in pairs(item) do
|
|
if (k ~= hidekey) ret ..= xpfx..tostr(k)..": "..puke(v, indent+2, seen)
|
|
end
|
|
return ret..pfx.."}"
|
|
end
|
|
|
|
-- convenience for debugging
|
|
function puketh(item, ...)
|
|
printh(puke(item), ...)
|
|
end
|
|
|
|
function pukeboard(item)
|
|
puketh(item, "@clip")
|
|
end
|
|
|
|
function drawgame()
|
|
clip(0,0,112,128)
|
|
rectfill(0,0,112,128,0)
|
|
for drawables in all{intangibles_bg, pbullets, {primary_ship}, eships, ebullets, intangibles_fg} do
|
|
for d in all(drawables) do
|
|
d:draw()
|
|
end
|
|
end
|
|
clip(0,0,128,128)
|
|
drawhud()
|
|
end
|
|
|
|
powcols=split"170,154,153,148,68"
|
|
shlcols = split"204,220,221"
|
|
function drawhud()
|
|
-- 112-and-right is hud zone
|
|
rectfill(112, 0, 127, 127,0x56)
|
|
rect(112,0,127,127,7)
|
|
line(127,1,127,127,5)
|
|
line(113,127)
|
|
|
|
draw_gun_info("❎",1,116,3,1)
|
|
draw_gun_info("🅾️",1,116,29,2)
|
|
|
|
inset(114,57,119,118)
|
|
rectfill(119,57,124,58,13)
|
|
inset(120,64,125,125)
|
|
rectfill(114,124,120,125,7)
|
|
print("XP",119,55,1)
|
|
print("HP",114,122,1)
|
|
fillp(0x5a5a)
|
|
if xpwhoosh then
|
|
clip(115,58,4,60)
|
|
rectfill(115,58,118,117,0xaa)
|
|
local voff = 5*xpwhoosh+6
|
|
rectfill(115,118-voff,118,117-voff+10,0xbb)
|
|
rectfill(115,118-voff+11,118,117-voff+20,0xba)
|
|
clip()
|
|
else
|
|
vertmeter(115,58,118,117,primary_ship.xp, primary_ship.xptarget, powcols)
|
|
end
|
|
-- 60 px vertically. note that
|
|
-- there was at one point an
|
|
-- off-by-one and I'm not sure
|
|
-- it's actually fixed
|
|
local mxs, cs, mxh, ch = primary_ship.maxshield, primary_ship.shield, primary_ship.maxhp, primary_ship.hp
|
|
if (mxs > 0) and (mxh > 0) then
|
|
local split = 59 * (mxs / (mxs + mxh)) \ 1 + 64
|
|
line(121, split, 124, split, 0xba)
|
|
vertmeter(121,65,124,split-1,cs, mxs,shlcols)
|
|
vertmeter(121,split+1,124,124,ch, mxh, hpcols)
|
|
elseif mxs > 0 then
|
|
vertmeter(121,65,124,124,cs,mxs,shlcols)
|
|
elseif mxh > 0 then
|
|
vertmeter(121,65,124,124,ch,mxh,hpcols)
|
|
else
|
|
print("!", 122, 93, 9)
|
|
print("!", 121, 92, 8)
|
|
end
|
|
fillp(0)
|
|
end
|
|
|
|
function draw_gun_info(lbl,fgc,x,y,gn)
|
|
dropshadow(lbl,x,y,fgc)
|
|
inset(114,y+7,125,y+18)
|
|
inset(114,y+20,125,y+24)
|
|
if (not primary_ship.special_guns) return
|
|
local gun = primary_ship.special_guns[gn]
|
|
if (not gun) return
|
|
spr(gun.icon,116,y+9,1,1)
|
|
--115 to 124 - ammo bar. round up
|
|
if gun.ammo == nil then
|
|
fillp(0xa5a5)
|
|
rectfill(115,y+21,124,y+23,0xea)
|
|
fillp(0)
|
|
elseif gun.ammo > 0 then
|
|
rectfill(
|
|
115,y+21,
|
|
115+flr(9*gun.ammo/gun.maxammo),
|
|
y+23,10)
|
|
else
|
|
line(118, y+22, 121, y+22, 2)
|
|
end
|
|
end
|
|
|
|
function vertmeter(x0,y0,x1,y1,val,maxval,cols)
|
|
if ((val <= 0) or (maxval <= 0)) return
|
|
if val < 0x0.001 or maxval < 0x0.001 then
|
|
val *= 16
|
|
maxval *= 16
|
|
end
|
|
val=min(val, maxval)
|
|
local h = y1-y0
|
|
local px = val*h/maxval \ 1
|
|
local ncols = #cols
|
|
local firstcol = ((h-px)*ncols\h)+1
|
|
local lastbottom = y0+(h*firstcol\ncols)
|
|
rectfill(x0, y1-px, x1, lastbottom, cols[firstcol])
|
|
for i=firstcol+1,ncols do
|
|
local bottom = y0+h*i\ncols
|
|
rectfill(x0,lastbottom,x1,bottom,cols[i])
|
|
lastbottom = bottom
|
|
end
|
|
end
|
|
|
|
function inset(x0,y0,x1,y1)
|
|
rectfill(x0,y0,x1,y1,0)
|
|
-- use "wide colors" to draw
|
|
-- monochrome regardless of
|
|
-- fillp
|
|
rect(x0,y0,x1,y1,119)
|
|
line(x1,y0,x0,y0,85)
|
|
line(x0,y1-1,85)
|
|
end
|
|
|
|
function dropshadow(str, x, y, col)
|
|
print(str, x+1, y+1, 5)
|
|
print(str, x, y, col)
|
|
end
|
|
|
|
-->8
|
|
--ship behavior
|
|
|
|
-- generic full sprite hurtbox
|
|
box8 = {
|
|
x_off = 0,
|
|
y_off = 1,
|
|
width = 8,
|
|
height = 8
|
|
}
|
|
|
|
scrollrate = 0.25 --in px/frame
|
|
|
|
ship_m = mknew{
|
|
|
|
-- ships have no shield by default
|
|
shield = 0,
|
|
maxshield = 0,
|
|
shieldcooldown = 0x0.003c,--1s
|
|
shieldpenalty = 0x0.012c, --5s
|
|
shield_refresh_ready = 0,
|
|
|
|
xmomentum = 0,
|
|
ymomentum = 0,
|
|
|
|
-- xmin, xmax, ymin, ymax:
|
|
-- movement constraints
|
|
-- enforced by `constrain`.
|
|
xmin = 0, xmax = 104,
|
|
-- ymin, ymax default to nil
|
|
-- pship needs more constraint
|
|
}
|
|
|
|
function ship_m:die()
|
|
self.dead = true
|
|
if (self.hp >= 0) return
|
|
|
|
-- blow up and drop xp
|
|
local sz4 = self.size * 4
|
|
local cx, cy, xp, z = self.x + sz4, self.y + sz4, self.xp or 0, 0
|
|
boom(cx, cy, 3*sz4, self.boss)
|
|
if xp > 0x0.01f3 then -- dec 499
|
|
-- spawn a huge gem with all
|
|
-- overage XP, min 100
|
|
spawn_xp_at(cx, cy, 0, xp-0x0.018f)
|
|
xp = 0x0.018f -- dec 399
|
|
z += 2
|
|
end
|
|
-- 100, 25, 5, 1
|
|
for gsz in all{0x0.0064, 0x0.0019, 0x0.0005, 0x0.0001} do
|
|
while xp >= gsz do
|
|
spawn_xp_at(cx, cy, z, gsz)
|
|
xp -= gsz
|
|
z += 2
|
|
end
|
|
end
|
|
end
|
|
|
|
function ship_m:calc_velocity(v0, t)
|
|
v0 = mid(v0 + t, self.maxspd, -self.maxspd)
|
|
return v0 - mid(self.drag, -self.drag, v0)
|
|
end
|
|
|
|
function ship_m:brake_dist(v0)
|
|
local brake_max = self.thrust + self.drag
|
|
local tri_frames = abs(v0\brake_max)
|
|
local chunks = tri_frames * (tri_frames - 1) >> 1
|
|
local chunk_zone = chunks * brake_max
|
|
local overage = abs(v0) - tri_frames * brake_max
|
|
return (chunk_zone + overage * (tri_frames + 1)) * sgn(v0), (overage > 0) and tri_frames + 1 or tri_frames
|
|
end
|
|
|
|
function ship_m:constrain(p, dp, pmin, pmax, want)
|
|
if (not pmin) return want
|
|
local v1, bd, bf, bp
|
|
function calc_targets()
|
|
-- velocity after move
|
|
v1 = self:calc_velocity(dp, want)
|
|
-- brake distance and frames
|
|
bd, bf = self:brake_dist(v1)
|
|
-- brake point
|
|
bp = p + bd + v1
|
|
end
|
|
calc_targets()
|
|
if bp < pmin then
|
|
-- undershoot. max thrust,
|
|
-- then treat as overshoot
|
|
-- targeting minimum bound
|
|
want, pmax = self.thrust, pmin
|
|
calc_targets()
|
|
end
|
|
if (bp <= pmax) return want
|
|
-- spread overshoot across frames
|
|
want -= (bp - pmax)/max(bf,1)
|
|
return max(want, -self.thrust)
|
|
end
|
|
|
|
function ship_m:move()
|
|
if (self.dead) return;
|
|
self:refresh_shield()
|
|
local dx, dy, shoot_spec1, shoot_spec2 = self:act()
|
|
local sg, xm, ym = self.special_guns, self.xmomentum, self.ymomentum
|
|
dx = self:constrain(self.x, xm, self.xmin, self.xmax, dx)
|
|
dy = self:constrain(self.y, ym, self.ymin, self.ymax, dy)
|
|
self:maybe_shoot(self.main_gun)
|
|
if sg then
|
|
if (shoot_spec1) self:maybe_shoot(sg[1])
|
|
if (shoot_spec2) self:maybe_shoot(sg[2])
|
|
end
|
|
spark(self.sparks, self.x + 4*self.size, self.y + 4*self.size, dx*2.5, dy*2.5, self.sparkodds)
|
|
xm = self:calc_velocity(xm, dx)
|
|
ym = self:calc_velocity(ym, dy)
|
|
|
|
self.x += xm
|
|
self.y += ym
|
|
self.xmomentum = xm
|
|
self.ymomentum = ym
|
|
|
|
return true
|
|
end
|
|
|
|
function ship_m:draw()
|
|
if (self.dead) return
|
|
if(self.fx_pal) pal(self.fx_pal)
|
|
spr(self.sprite, self.x, self.y, self.size, self.size)
|
|
pal()
|
|
end
|
|
|
|
function hurtbox(ship)
|
|
local h = ship.hurt
|
|
local x1,y1 = ship.x + h.x_off, ship.y+h.y_off
|
|
return {x1=x1, y1=y1, x2=x1+h.width, y2=y1+h.height}
|
|
end
|
|
|
|
function ship_m:maybe_shoot(gun)
|
|
if (not gun) return
|
|
return gun:shoot(self.x + self.fire_off_x, self.y + self.fire_off_y)
|
|
end
|
|
|
|
function ship_m:hitship(other)
|
|
return self:hitsomething(1)
|
|
end
|
|
|
|
function ship_m:hitbullet(b)
|
|
return self:hitsomething(b.damage)
|
|
end
|
|
|
|
function ship_m:hitsomething(dmg)
|
|
if (dmg <= 0) return false
|
|
self.shield_refresh_ready = gframe + self.shieldpenalty
|
|
if self.shield > 0 then
|
|
self.shield -= dmg
|
|
if self.shield > 0 then
|
|
blip(self,12)
|
|
else
|
|
self.shield = 0
|
|
blip(self,7)
|
|
end
|
|
return false
|
|
end
|
|
self.hp -= dmg
|
|
if self.hp < 0 then
|
|
self:die()
|
|
return true
|
|
end
|
|
blip(self, self.friendly and 8 or 7)
|
|
return false
|
|
end
|
|
|
|
function ship_m:refresh_shield()
|
|
if (self.shield >= self.maxshield) return
|
|
if (gframe < self.shield_refresh_ready) return
|
|
self.shield += 1
|
|
self.shield = min(self.shield, self.maxshield)
|
|
self.shield_refresh_ready = gframe + self.shieldcooldown
|
|
end
|
|
|
|
-->8
|
|
-- bullet and gun behaviors
|
|
|
|
function player_blt_cat()
|
|
return pbullets
|
|
end
|
|
|
|
function enemy_blt_cat()
|
|
return ebullets
|
|
end
|
|
|
|
-- x, y: position
|
|
-- dx, dy: movement (linear)
|
|
-- f: frames remaining; nil for no limit
|
|
-- sprite: what sprite to draw
|
|
-- hurt -- hurtbox
|
|
-- width, height -- in sprites
|
|
-- x_off, y_off -- how to
|
|
-- initially position relative
|
|
-- to firing point. weird
|
|
-- details, check impl
|
|
-- damage -- damage to do to
|
|
-- a ship that gets hit
|
|
-- category -- function that
|
|
-- returns which bullet list
|
|
-- to spawn onto
|
|
-- hitship -- event handler,
|
|
-- takes ship as argument.
|
|
-- default: die, return true.
|
|
-- returns whether to delete
|
|
-- the bullet
|
|
bullet_base = mknew{}
|
|
|
|
gun_base = mknew{
|
|
shoot_ready = -32768,
|
|
new_clip = -32768,
|
|
clip_size = false,
|
|
clip_remain = 0,
|
|
clip_interval = 0x0.80,
|
|
icon = 20,
|
|
ammobonus = 1,
|
|
|
|
-- fractional frames of
|
|
-- cooldown reduction from
|
|
-- upgrades, not yet applied
|
|
cd_remainder = 0,
|
|
|
|
veloc = 1,
|
|
aim = 0.75, -- down; 0.25, or -0.75, is up
|
|
shot_idx = 0,
|
|
-- shots: list<list<[3]num>>
|
|
-- describing a cycling
|
|
-- firing pattern. shot_idx
|
|
-- tracks offset into pattern.
|
|
-- each nested list: a burst
|
|
-- of shots to fire; takes
|
|
-- 1 ammo; sequential
|
|
-- each shot: angle (turns,
|
|
-- relative to `aim`),
|
|
-- firing x-offset, velocity;
|
|
-- if x-offset is nil, use 0;
|
|
-- if velocity is nil, use
|
|
-- self.veloc instead
|
|
|
|
init = function(self)
|
|
if (not self.shots) self.shots = {{{0}}}
|
|
end
|
|
}
|
|
|
|
-- gun_base subtypes are
|
|
-- level-up options that,
|
|
-- as an action, assign
|
|
-- themselves to the player
|
|
function gun_base:action()
|
|
local item = self.new()
|
|
item:peel()
|
|
item.ammo = item.maxammo
|
|
if not primary_ship.special_guns then
|
|
primary_ship.special_guns = {item}
|
|
else
|
|
add(primary_ship.special_guns, item)
|
|
end
|
|
end
|
|
|
|
-- make shot type unique so
|
|
-- stat modifications do not
|
|
-- damage base data
|
|
function gun_base:peel()
|
|
self.munition = mknew(self.munition.new())
|
|
end
|
|
|
|
-- upgrade
|
|
function gun_base:small_upgrade_opts()
|
|
local ret = {
|
|
self:ammo_upgrade_opt(),
|
|
self:rate_upgrade_opt(),
|
|
}
|
|
local s = self.special_upgrade_opt
|
|
if (s) add(ret, s(self))
|
|
return ret
|
|
end
|
|
|
|
function gun_base:ammo_upgrade_opt()
|
|
local a=self.maxammo
|
|
local x=a\10+self.ammobonus
|
|
return {
|
|
icon=self.icon,
|
|
hdr=self.hdr,
|
|
body=[[--------AMMO
|
|
|
|
more shots
|
|
before you
|
|
run out.
|
|
|
|
is: ]]..tostr(a)..[[
|
|
add: ]]..tostr(x)..[[
|
|
----------
|
|
total: ]]..tostr(a+x),
|
|
action=function()
|
|
self.maxammo+=x
|
|
self.ammo+=x
|
|
end,
|
|
}
|
|
end
|
|
|
|
function gun_base:rate_upgrade_opt()
|
|
local c=self.cooldown<<16
|
|
local rawnewc=0.85*(c-self.cd_remainder)
|
|
local newc=ceil(rawnewc)
|
|
return {
|
|
icon=self.icon,
|
|
hdr=self.hdr,
|
|
body=[[--------RATE
|
|
|
|
reduce delay
|
|
between each
|
|
shot when
|
|
firing.
|
|
|
|
is: ]]..tostr(c)..[[f
|
|
minus: ]]..tostr(c-newc)..[[f
|
|
----------
|
|
total: ]]..tostr(newc)..[[f
|
|
|
|
remainder:
|
|
]]..sub(tostr(newc-rawnewc),0,5),
|
|
action=function()
|
|
self.cooldown=newc>>16
|
|
self.cd_remainder=newc-rawnewc
|
|
end,
|
|
}
|
|
end
|
|
|
|
function bullet_base:hitship(_)
|
|
return true
|
|
end
|
|
|
|
function bullet_base:move()
|
|
local x,y = self.x + self.dx, self.y+self.dy
|
|
self.x,self.y=x,y
|
|
return (y<=128) and (y >= -16) and (x <= 128) and (x >= -16)
|
|
end
|
|
|
|
function bullet_base:draw()
|
|
spr(self.sprite, self.x, self.y, self.width, self.height)
|
|
end
|
|
|
|
function bullet_base:spawn_at(x, y)
|
|
self.x = x - self.x_off
|
|
self.y = y - self.y_off
|
|
add(self.category(), self)
|
|
end
|
|
|
|
function gun_base:shoot(x, y)
|
|
if (gframe < self.shoot_ready) return false
|
|
local csz,crm = self.clip_size, self.clip_remain
|
|
if csz then
|
|
if crm < csz and gframe >= self.new_clip then
|
|
self.clip_remain = csz
|
|
self.new_clip = gframe + self.clip_interval
|
|
elseif crm == 0 then
|
|
return false
|
|
end
|
|
end
|
|
if self.ammo then
|
|
if (self.ammo <= 0) return false
|
|
self.ammo -= 1
|
|
end
|
|
if csz then
|
|
self.clip_remain -= 1
|
|
end
|
|
self.shoot_ready = gframe + self.cooldown
|
|
self:actually_shoot(x, y)
|
|
return true
|
|
end
|
|
|
|
function gun_base:actually_shoot(x, y)
|
|
local shots,veloc,aim,munition = self.shots,self.veloc,self.aim,self.munition
|
|
local idx = self.shot_idx % #shots + 1
|
|
self.shot_idx = idx
|
|
shots = shots[idx]
|
|
for s in all(shots) do
|
|
local a,xo,v = s[1]+aim, s[2] or 0, s[3] or veloc
|
|
-- reverse x-offset for negative base angle
|
|
if (aim < 0) xo = -xo
|
|
-- todo: switch munition
|
|
-- depending on angle
|
|
-- (allows for non-round
|
|
-- sprites and hitboxes on
|
|
-- shots from guns with
|
|
-- widely varying angles)
|
|
local m = munition.new{
|
|
dx=cos(a)*v,
|
|
dy=sin(a)*v
|
|
}
|
|
m:spawn_at(x+xo, y)
|
|
end
|
|
end
|
|
|
|
|
|
-->8
|
|
-- bullets and guns
|
|
|
|
zap_p = mknew(bullet_base.new{
|
|
--shape
|
|
sprite = 8, --index of ammo sprite
|
|
width = 0.25, --in 8x8 blocks
|
|
height = 1,
|
|
hurt = { -- hurtbox - where this ship can be hit
|
|
x_off = 0, -- upper left corner
|
|
y_off = 0, -- relative to sprite
|
|
width = 2,
|
|
height = 8,
|
|
},
|
|
x_off = 1, -- how to position by ship
|
|
y_off = 0,
|
|
damage = 1,
|
|
|
|
hitship = const_fxn(true),
|
|
|
|
category = player_blt_cat,
|
|
})
|
|
|
|
zap_gun_p = mknew(gun_base.new{
|
|
icon = 19,
|
|
cooldown = 0x0.0020, -- frames between shots
|
|
veloc = 7,
|
|
aim = 0.25,
|
|
munition = zap_p,
|
|
hdr = "mAIN gUN",
|
|
})
|
|
|
|
blast = mknew(bullet_base.new{
|
|
--shape
|
|
sprite = 12, --index of player ammo sprite
|
|
width = 1, --in 8x8 blocks
|
|
height = 1,
|
|
hurt = { -- hurtbox - where this ship can be hit
|
|
x_off = 1, -- upper left corner
|
|
y_off = 1, -- relative to sprite
|
|
width = 6,
|
|
height = 6
|
|
},
|
|
x_off = 4, -- how to position by ship
|
|
y_off = 0,
|
|
|
|
damage = 4,
|
|
dx = 0, -- px/frame
|
|
dy = -1,
|
|
awaitcancel = false,
|
|
|
|
-- disable damage for 4 frames
|
|
-- when hitting something
|
|
-- todo: rewrite all ship hit
|
|
-- logic so i can avoid
|
|
-- repeating hits to the
|
|
-- same ship instead of
|
|
-- using a cooldown
|
|
hitship = function(self, _)
|
|
if self.damage > 0 and not self.awaitcancel then
|
|
self.awaitcancel = true
|
|
once_next_frame(function()
|
|
add(new_events, {
|
|
wait = 4,
|
|
obj = self,
|
|
saved_dmg = self.damage,
|
|
move = function(self)
|
|
self.wait -= 1
|
|
if self.wait <= 0 then
|
|
self.obj.damage = self.saved_dmg
|
|
return true
|
|
end
|
|
end,
|
|
})
|
|
self.damage = 0
|
|
self.awaitcancel = false
|
|
end)
|
|
end
|
|
end,
|
|
category=player_blt_cat
|
|
})
|
|
|
|
blast_gun = mknew(gun_base.new{
|
|
icon = 13,
|
|
cooldown = 0x0.0078, -- 120 frames between shots
|
|
aim = -0.75,
|
|
ammo = 5,
|
|
maxammo = 5,
|
|
munition = blast,
|
|
hdr = "bLASTER",
|
|
body= [[---------GUN
|
|
|
|
plasma orb
|
|
cuts through
|
|
enemies.
|
|
slow.
|
|
|
|
ammo: 5
|
|
rate: 1/2sec
|
|
dmg: 4
|
|
]],
|
|
})
|
|
|
|
protron_e = mknew(bullet_base.new{
|
|
--shape
|
|
sprite = 24,
|
|
width = 1, --in 8x8 blocks
|
|
height = 1,
|
|
hurt = { -- hurtbox - where this ship can be hit
|
|
x_off = 1, -- upper left corner
|
|
y_off = 1, -- relative to sprite
|
|
width = 2,
|
|
height = 2
|
|
},
|
|
x_off = 1, -- how to position by ship
|
|
y_off = 4,
|
|
|
|
damage = 1,
|
|
category = enemy_blt_cat,
|
|
})
|
|
|
|
protron_p = mknew(protron_e.new{
|
|
sprite=23,
|
|
dym = -1,
|
|
y_off = 0,
|
|
category=player_blt_cat,
|
|
})
|
|
|
|
protron_gun_e = mknew(gun_base.new{
|
|
icon = 25,
|
|
cooldown = 0x0.0040, -- frames between shots
|
|
ammo = nil,
|
|
maxammo = nil,
|
|
munition = protron_e,
|
|
veloc = 2,
|
|
shots = {{{-0.25}, {-0.165}, {-0.0825}, {0}, {0.0825}, {0.165}, {0.25}}}
|
|
})
|
|
|
|
protron_gun_p = mknew(protron_gun_e.new{
|
|
munition = protron_p,
|
|
maxammo = 20,
|
|
cooldown = 0x0.0018,
|
|
veloc = 4,
|
|
aim = -0.75,
|
|
hdr = "pROTRON",
|
|
body = [[---------GUN
|
|
|
|
spray shots
|
|
in a dense
|
|
arc.
|
|
|
|
ammo: 20
|
|
rate: 2/sec
|
|
dmg: 1
|
|
]],
|
|
})
|
|
|
|
vulcan_e = mknew(bullet_base.new{
|
|
--shape
|
|
sprite = 21,
|
|
width = 0.125, --in 8x8 blocks
|
|
height = 0.5,
|
|
hurt = { -- hurtbox - where this ship can be hit
|
|
x_off = 0, -- upper left corner
|
|
y_off = 0, -- relative to sprite
|
|
width = 1,
|
|
height = 4
|
|
},
|
|
x_off = 0.5, -- how to position by ship
|
|
y_off = 0,
|
|
|
|
damage = 0.5,
|
|
category=enemy_blt_cat
|
|
})
|
|
|
|
vulcan_p = mknew(vulcan_e.new{
|
|
sprite=22,
|
|
y_off = 4,
|
|
category=player_blt_cat
|
|
})
|
|
|
|
vulcan_gun_e = mknew(gun_base.new{
|
|
icon = 37,
|
|
cooldown = 0x0.0003, -- frames between shots
|
|
ammo = nil,
|
|
maxammo = nil,
|
|
munition=vulcan_e,
|
|
veloc = 2,
|
|
shots = {{{0.02, 2}}, {{-0.02,0}}, {{-0.03, -2}}, {{0.03, 2}}, {{0.02, 0}}, {{-0.02, -2}}}
|
|
})
|
|
|
|
machine_gun_e = mknew(vulcan_gun_e.new{
|
|
icon = 38,
|
|
clip_size = 12,
|
|
clip_interval = 0x0.005a,
|
|
shots = {{{0, 2}}, {{0, -2}}}
|
|
})
|
|
|
|
vulcan_gun_p = mknew(vulcan_gun_e.new{
|
|
munition=vulcan_p,
|
|
maxammo = 100,
|
|
aim=-0.75,
|
|
veloc=4,
|
|
hdr = "vULCAN",
|
|
body = [[---------GUN
|
|
|
|
rapidly fire
|
|
in a v.
|
|
|
|
ammo: 100
|
|
rate: 20/sec
|
|
dmg: 0.5
|
|
]],
|
|
})
|
|
|
|
-->8
|
|
--ships, including player
|
|
|
|
firespark = split"9, 8, 2, 5, 1"
|
|
smokespark = split"13, 13, 5, 5"
|
|
|
|
player = mknew(ship_m.new{
|
|
friendly=true,
|
|
--shape
|
|
sprite = 1, --index of ship sprite
|
|
size = 1, --all ships are square; how many 8x8 sprites?
|
|
hurt = { -- hurtbox - where this ship can be hit
|
|
x_off = 3, -- upper left corner
|
|
y_off = 2, -- relative to ship ulc
|
|
width = 1,
|
|
height = 3
|
|
},
|
|
sparks = firespark, -- see tab 9
|
|
sparkodds = 2,
|
|
boss = true, -- dramatic special effects
|
|
|
|
-- health
|
|
hp = 3, -- current health, non-regenerating
|
|
maxhp = 3, -- player only; other ships never heal
|
|
shield = 2, -- regenerates
|
|
maxshield = 2,
|
|
|
|
-- xp in increments of 0x0.0001
|
|
xp = 0,
|
|
xptarget = 0x0.0004,
|
|
last_xp_frame = 0,
|
|
level = 1,
|
|
magnet = 10,
|
|
|
|
-- gun
|
|
main_gun = nil, -- assign at spawn time
|
|
special_guns = nil,
|
|
fire_off_x = 4, -- offset where bullets come from
|
|
fire_off_y = 0,
|
|
|
|
-- position
|
|
x=52, -- x and y are for upper left corner
|
|
y=96,
|
|
xmomentum = 0,
|
|
ymomentum = 0,
|
|
maxspd = 1.5, -- momentum cap
|
|
thrust = 0.1875, -- momentum added from button
|
|
ymin = 0, ymax = 120, -- stay on screen
|
|
drag = 0.0625, -- momentum lost per frame
|
|
act = function(self) -- fetch buttons
|
|
local b,th = btn(),self.thrust
|
|
local blr = b&0x3
|
|
if blr == 1 then
|
|
self.sprite=17
|
|
elseif blr==2 then
|
|
self.sprite=18
|
|
else
|
|
self.sprite=1
|
|
end
|
|
--dx, dy, shoot_spec, shoot_main
|
|
return (((b&0x2)>>1) - (b&0x1)) * th, (((b&0x8)>>3) - ((b&0x4)>>2)) * th, (b&0x10) > 0, (b&0x20) > 0
|
|
end,
|
|
|
|
init = function(p)
|
|
p.main_gun = zap_gun_p.new()
|
|
-- ONE HIT MODE
|
|
--
|
|
-- p.hp = 0
|
|
-- p.maxhp = 0
|
|
-- p.shield = 0
|
|
-- p.maxshield = 0
|
|
end,
|
|
})
|
|
|
|
function player:small_upgrade_opts()
|
|
local cdr, pr = (self.shieldcooldown - 0x0.000f) / 8, (self.shieldpenalty - 0x0.003c) / 9
|
|
if (cdr == 0 and self.shieldcooldown > 0x0.000f) cdr = 0x0.0001
|
|
if (pr == 0 and self.shieldpenalty > 0x0.003c) pr = 0x0.0001
|
|
|
|
local ret = {{
|
|
icon=53,
|
|
hdr="hull",
|
|
body=[[--------SHIP
|
|
|
|
survive more
|
|
unshielded
|
|
hits.
|
|
|
|
+2 hp]],
|
|
action=function()
|
|
self.maxhp += 2
|
|
self.hp += 2
|
|
end,
|
|
},{
|
|
icon=52,
|
|
hdr="capacity",
|
|
body=[[------SHIELD
|
|
|
|
shield can
|
|
absorb more
|
|
hits before
|
|
recharging.
|
|
|
|
+1 hp]],
|
|
action=function()
|
|
self.maxshield += 1
|
|
self.shield += 1
|
|
end,
|
|
},{
|
|
icon=1,
|
|
hdr="thrusters",
|
|
body=[[--------SHIP
|
|
|
|
move faster,
|
|
steer more
|
|
sharply.]],
|
|
action=function()
|
|
--maxspd thrust drag
|
|
self.maxspd += 0.5
|
|
self.thrust += 0.0625
|
|
self.drag += 0.03125
|
|
end,
|
|
},{
|
|
icon=20,
|
|
hdr="magnet",
|
|
body=[[--------SHIP
|
|
|
|
pick up xp
|
|
from further
|
|
away.]],
|
|
action=function ()
|
|
self.magnet += 2
|
|
end,
|
|
},
|
|
self.main_gun:rate_upgrade_opt(),
|
|
}
|
|
|
|
if cdr > 0 then
|
|
add(ret, {
|
|
icon = 6,
|
|
hdr = "recharge",
|
|
body=[[------SHIELD
|
|
|
|
shield will
|
|
recharge at
|
|
a faster
|
|
pace.
|
|
|
|
]] .. tostr(ceil(100 * cdr / self.shieldcooldown)) .. "% faster",
|
|
action = function()
|
|
self.shieldcooldown -= cdr
|
|
end
|
|
})
|
|
end
|
|
|
|
if pr > 0 then
|
|
add(ret, {
|
|
icon = 6,
|
|
hdr = "recovery",
|
|
body=[[------SHIELD
|
|
|
|
reduce the
|
|
delay after
|
|
a hit before
|
|
shield will
|
|
start to
|
|
recharge.
|
|
|
|
]] .. tostr(ceil(100 * pr / self.shieldpenalty)) .. "% shorter",
|
|
action = function()
|
|
self.shieldpenalty -= pr
|
|
end
|
|
})
|
|
end
|
|
|
|
return ret
|
|
end
|
|
|
|
-- original prototype leftover;
|
|
-- likely to be the basis of a
|
|
-- standard raider type, so
|
|
-- i am keeping it around
|
|
chasey = mknew(ship_m.new{
|
|
sprite = 5,
|
|
xp = 0x0.0004,
|
|
size = 1,
|
|
hurt = {
|
|
x_off = 1,
|
|
y_off = 2,
|
|
width = 6,
|
|
height = 5,
|
|
},
|
|
sparks = smokespark,
|
|
sparkodds = 8,
|
|
hp = 1.5,
|
|
shield = 1,
|
|
maxshield = 1,
|
|
|
|
fire_off_x = 4,
|
|
fire_off_y = 7,
|
|
|
|
maxspd = 2,
|
|
thrust = 0.2,
|
|
drag = 0.075,
|
|
|
|
init = function(ship)
|
|
--ship.main_gun=ship.main_gun or zap_gun_e.new{}
|
|
end
|
|
})
|
|
|
|
function chasey:act()
|
|
self.xmin = max(primary_ship.x-8, 0)
|
|
self.xmax = min(primary_ship.x + 8, 112 - 8*self.size)
|
|
return 0, 0, false, self.y > 10 and self.x - 16 < primary_ship.x and self.x + 16 > primary_ship.x
|
|
end
|
|
|
|
xl_chasey=mknew(chasey.new{
|
|
size=2,
|
|
xp = 0x0.000a,
|
|
maxspd=1.25,
|
|
hurt = {
|
|
x_off = 2,
|
|
y_off = 4,
|
|
width = 12,
|
|
height = 10
|
|
},
|
|
fire_off_x = 8,
|
|
fire_off_y = 15,
|
|
hp = 19.5,
|
|
shield = 5,
|
|
boss = true,
|
|
act = function(self)
|
|
local dx,dy,shoot_spec,shoot_main = chasey.act(self)
|
|
if (self.y < 4) dy=self.thrust
|
|
return dx,dy,shoot_spec,shoot_main
|
|
end,
|
|
draw = function(self)
|
|
if(self.fx_pal) pal(self.fx_pal)
|
|
sspr(40, 0, 8, 8, self.x, self.y, 16, 16)
|
|
pal()
|
|
end,
|
|
})
|
|
|
|
-- flotilla ships
|
|
|
|
ship_f = mknew(ship_m.new{
|
|
-- sprite required
|
|
size = 1,
|
|
hurt = box8,
|
|
-- no sparks
|
|
hp = 0.5,
|
|
xp = 0x0.0001,
|
|
fire_off_x = 4,
|
|
fire_off_y = 4,
|
|
|
|
maxspd = 3,
|
|
thrust = 0.1,
|
|
drag = 0.05,
|
|
act = function(self)
|
|
local wx,wy=self.want_x,self.want_y
|
|
self.xmin,self.xmax,self.ymin,self.ymax = wx,wx,wy,wy
|
|
return 0,0,false,false
|
|
end,
|
|
init = function(self)
|
|
if (self.gun_proto) self.main_gun = self.gun_proto.new()
|
|
end
|
|
})
|
|
|
|
ship_mook = mknew(ship_f.new{
|
|
sprite=103
|
|
})
|
|
ship_defender = mknew(ship_f.new{
|
|
sprite=105,
|
|
hp = 2.5,
|
|
xp = 0x0.0003,
|
|
})
|
|
ship_turret = mknew(ship_f.new{
|
|
sprite=106,
|
|
xp = 0x0.0002,
|
|
gun_proto = machine_gun_e,
|
|
})
|
|
ship_skirmisher = mknew(ship_f.new{
|
|
sprite=107,
|
|
xp = 0x0.0004,
|
|
sparks = smokespark,
|
|
sparkodds = 3,
|
|
fire_off_y = 7,
|
|
})
|
|
|
|
function rnd_spawn_loc()
|
|
local x,y = flr(rnd(304)), flr(rnd(32))
|
|
if (x<184) return x-40,-y-8
|
|
if (x<244) return -y-8,x-184
|
|
return 112+y, x-244
|
|
end
|
|
|
|
-->8
|
|
-- collisions
|
|
|
|
-- box: x1, y1, x2, y2
|
|
function collides(b1, b2)
|
|
return
|
|
b1.y1<=b2.y2
|
|
and b1.y2>=b2.y1
|
|
and b1.x1<=b2.x2
|
|
and b1.x2>=b2.x1
|
|
end
|
|
|
|
collider = mknew{
|
|
init = function(x)
|
|
local from = x.from
|
|
for n in all(from) do
|
|
-- insert
|
|
for i in all(collider_indexes(hurtbox(n))) do
|
|
local a = x[i]
|
|
if not a then
|
|
a = {}
|
|
x[i] = a
|
|
end
|
|
add(a, n)
|
|
end
|
|
end
|
|
end,
|
|
}
|
|
|
|
function collider_indexes(box)
|
|
local ret, ylo, yhi = {}, box.y1\8, box.y2\8
|
|
for x = box.x1\8, box.x2\8 do
|
|
for y = ylo, yhi do
|
|
add(ret, x+(y<<8))
|
|
end
|
|
end
|
|
return ret
|
|
end
|
|
|
|
function collider:iterate_collisions(box)
|
|
local seen = { }
|
|
local bucket_ids = collider_indexes(box)
|
|
local bii, bidl, bucket, bi, blen = 1, #bucket_ids, false, 1, 0
|
|
return function()
|
|
while bii <= bidl do
|
|
if not bucket then
|
|
bucket,blen = self[bucket_ids[bii]],0
|
|
if (bucket) blen=#bucket
|
|
end
|
|
while bi <= blen do
|
|
local candidate = bucket[bi]
|
|
bi += 1
|
|
if not seen[candidate] then
|
|
seen[candidate] = true
|
|
if (not candidate.dead and collides(box, hurtbox(candidate))) return candidate
|
|
end
|
|
end -- done with this bucket
|
|
bi=1
|
|
bii += 1
|
|
end
|
|
end -- end of closure def
|
|
end
|
|
|
|
-->8
|
|
-- flotillas
|
|
|
|
-- a template for a wave, read
|
|
-- from the map. each ship can
|
|
-- alternate between "attack"
|
|
-- and "formation" modes, like
|
|
-- galaxian or galaga. ships
|
|
-- with different roles have
|
|
-- different rules for becoming
|
|
-- aggressive, but aggression
|
|
-- ramps up during the wave.
|
|
|
|
-- flotilla placeholders are
|
|
-- defined by sprite flags.
|
|
-- see obsidian vault for
|
|
-- full docs.
|
|
|
|
flotilla = mknew{
|
|
use_var = 0x1111,
|
|
opt_odds = split"0.5,0.5,0.5,0.5",
|
|
init=function(this)
|
|
this.ship_bases={
|
|
[0]=mknew(ship_mook.new{ship_t=0}),
|
|
[1]=mknew(ship_mook.new{ship_t=1, sprite=104}),
|
|
[4]=mknew(ship_defender.new{ship_t=4}),
|
|
[5]=mknew(ship_defender.new{ship_t=5, sprite=10}),
|
|
[8]=mknew(ship_turret.new{ship_t=8}),
|
|
[9]=mknew(ship_turret.new{ship_t=9, sprite=4}),
|
|
[12]=mknew(ship_skirmisher.new{ship_t=12}),
|
|
[13]=mknew(ship_skirmisher.new{ship_t=13, sprite=26}),
|
|
}
|
|
end,
|
|
}
|
|
|
|
function flotilla:load(ulc_cx, ulc_cy, lvl)
|
|
local rows,cy,uv,counts={},ulc_cy,self.use_var,{
|
|
[0]=0,
|
|
[1]=0,
|
|
[4]=0,
|
|
[5]=0,
|
|
[8]=0,
|
|
[9]=0,
|
|
[12]=0,
|
|
[13]=0,
|
|
}
|
|
repeat
|
|
local row,cx,opt,f,mode= {},ulc_cx,{},0,0
|
|
for i,v in ipairs(self.opt_odds) do
|
|
opt[i*4-4]=rnd()<v
|
|
end
|
|
repeat
|
|
f=fget(mget(cx, cy))
|
|
-- bits 0x03: control mark or ship?
|
|
mode = f&0x03
|
|
if mode==2 then
|
|
-- bits 0x0c: ship class
|
|
local ship_t = f&0x0c
|
|
-- bit 0x20: optional?
|
|
if f&0x20 == 0 or opt[ship_t] then
|
|
-- bit 0x10: alternate ship?
|
|
-- increment ship id if
|
|
-- alternate is requested
|
|
-- and we allow alternates
|
|
-- for this type of ship
|
|
ship_t+=(uv>>ship_t&0x1)&((f&0x10)>>4)
|
|
add(row, self.ship_bases[ship_t].new{col=cx-ulc_cx})
|
|
end
|
|
end
|
|
cx += 1
|
|
until mode==1
|
|
-- mode 1: end of line control mark
|
|
-- bits 0x18: what size flotilla is this row used for?
|
|
if (f&0x18)>>3 <= lvl then
|
|
-- keep the row; count it
|
|
for s in all(row) do
|
|
counts[s.ship_t] += 1
|
|
s.x,s.y=rnd_spawn_loc()
|
|
add(eships, s)
|
|
end
|
|
add(rows, row)
|
|
end
|
|
cy += 1
|
|
-- control mark bit 0x04: end of flotilla
|
|
until f&0x04 > 0
|
|
self.rows=rows
|
|
self:statisfy(counts)
|
|
end
|
|
|
|
function flotilla:statisfy(counts)
|
|
-- TODO: now that we know how
|
|
-- many ships of each kind
|
|
-- exist, build ships to match
|
|
-- difficulty target
|
|
--
|
|
-- no difficulty model is yet
|
|
-- implemented, though, so
|
|
-- just use base ships only
|
|
-- for this prototype
|
|
end
|
|
|
|
function flotilla:update()
|
|
-- algorithm: redistribute
|
|
-- TODO: alternate flotilla movement algorithms
|
|
|
|
-- find effective width and height
|
|
local min_col,max_col,live_rows=999,0,0
|
|
for row in all(self.rows) do
|
|
local row_alive=false
|
|
for ship in all(row) do
|
|
if not ship.dead then
|
|
row_alive=true
|
|
local col=ship.col
|
|
if (col < min_col) min_col = col
|
|
if (col > max_col) max_col = col
|
|
end
|
|
end -- scanned row
|
|
if (row_alive) live_rows += 1
|
|
end -- extent search
|
|
|
|
if (live_rows == 0) return true -- done
|
|
|
|
-- distribute across box:
|
|
-- x = [4, 100)
|
|
-- y = [4, 60)
|
|
|
|
local x_interval,x_offset = 0,52
|
|
if min_col < max_col then
|
|
x_interval=96/(max_col-min_col)
|
|
x_offset = 4-min_col*x_interval
|
|
end
|
|
|
|
local y_interval,y_offset=0,40
|
|
if live_rows > 1 then
|
|
y_interval=52/(live_rows-1)
|
|
y_offset=4-y_interval
|
|
end
|
|
|
|
-- now assign target locations
|
|
local real_row=0
|
|
for row in all(self.rows) do
|
|
local row_alive = false
|
|
for ship in all(row) do
|
|
if not ship.dead then
|
|
if not row_alive then
|
|
real_row += 1
|
|
row_alive = true
|
|
end
|
|
ship.want_x = ship.col * x_interval + x_offset
|
|
ship.want_y = real_row * y_interval + y_offset
|
|
end -- ship updated
|
|
end -- row updated
|
|
end -- table updated
|
|
|
|
return false -- some ships remain
|
|
end
|
|
|
|
-->8
|
|
-- standard events
|
|
|
|
blip_fx = mknew{
|
|
cancel=false
|
|
}
|
|
|
|
function blip_fx:move()
|
|
if (self.cancel) return
|
|
self.frames -= 1
|
|
if self.frames < 0 then
|
|
self.obj.fx_pal = nil
|
|
return
|
|
end
|
|
return true
|
|
end
|
|
|
|
function blip_fx:abort()
|
|
self.cancel=true
|
|
end
|
|
|
|
blip_pals = {}
|
|
function init_blip_pals()
|
|
for i=0,15 do
|
|
local pp = {[0]=0}
|
|
for j=1,15 do
|
|
pp[j] = i
|
|
end
|
|
blip_pals[i]=pp
|
|
end
|
|
end
|
|
|
|
function blip(obj, col)
|
|
obj.fx_pal = blip_pals[col]
|
|
if (obj.___fx_pal_event) obj.___fx_pal_event:abort()
|
|
add(events, blip_fx.new{frames=3, obj=obj})
|
|
end
|
|
|
|
bossspark = split"7,7,10,10,9,9,9,8,8,8,2,2,5,5"
|
|
|
|
function boom(x,y,boominess,is_boss)
|
|
local sp = firespark
|
|
if is_boss then
|
|
boominess *= 10
|
|
sp = bossspark
|
|
end
|
|
local boombase = min(0.023 * boominess, 0.25)
|
|
local boombonus = min(0.05 * boominess, 1.25)
|
|
for _=1,boominess do
|
|
local angle = rnd(1)
|
|
spark(sp,x+4,y+4,cos(angle), sin(angle),boombase+rnd(boombonus),1, true)
|
|
end
|
|
return
|
|
end
|
|
|
|
spark_particle=mknew{}
|
|
|
|
function spark_particle:move()
|
|
if (rnd(4) < 1) self.sidx += 1
|
|
if (self.sidx > #self.sprs) return
|
|
self.x += self.dx
|
|
self.y += self.dy
|
|
self.dx -= mid(0.05,-0.05, self.dx)
|
|
self.dy -= mid(0.05,-0.05, self.dy)
|
|
return true
|
|
end
|
|
function spark_particle:draw()
|
|
pset(self.x,self.y,self.sprs[self.sidx])
|
|
end
|
|
|
|
function spark(sprs, x, y, dx, dy, odds, fg)
|
|
if (sprs==nil or flr(rnd(odds) or (abs(dx) < 0.5 and abs(dy))) ~= 0) return
|
|
local target = fg and intangibles_fg or intangibles_bg
|
|
target[#target+1] = spark_particle.new{
|
|
x = x + rnd(4) - 2,
|
|
y = y + rnd(4) - 2,
|
|
sprs = sprs,
|
|
sidx = 1,
|
|
dx = dx * rnd(2),
|
|
dy = dy * rnd(2),
|
|
}
|
|
end
|
|
-->8
|
|
-- powerups
|
|
|
|
xp_gem = mknew(bullet_base.new{
|
|
dx = 0,
|
|
dy = 0.75,
|
|
width=1, -- not used for spr but
|
|
height=1,-- bullet_base uses it
|
|
category = enemy_blt_cat,
|
|
damage = 0,
|
|
hurt = {
|
|
x_off = -2,
|
|
y_off = -2,
|
|
width = 8,
|
|
height = 8,
|
|
},
|
|
x_off = 2,
|
|
y_off = 2,
|
|
})
|
|
|
|
function xp_gem:draw()
|
|
local s,qx,qy = self.qsprite,0,0
|
|
-- sprite map position:
|
|
-- sprite id to x and y,
|
|
-- offset shifts specific low
|
|
-- bits of gframe up to the the
|
|
-- bit with value 4 as a cheap
|
|
-- way to pick an anim frame
|
|
if (gframe&0x0.003 == 0) qx, qy = (gframe&0x0.0004)<<16, (gframe&0x0.0008)<<15
|
|
sspr(
|
|
(s%16<<3)+qx,
|
|
(s\16<<3)+qy,
|
|
4, 4,
|
|
self.x, self.y
|
|
)
|
|
end
|
|
|
|
function xp_gem:move()
|
|
if not primary_ship.dead and abs(self.x + 1 - primary_ship.x - primary_ship.hurt.x_off) <= primary_ship.magnet and abs(self.y + 1 - primary_ship.y - primary_ship.hurt.y_off) <= primary_ship.magnet then
|
|
if (self.x < primary_ship.x + 3) self.x += 1
|
|
if (self.x > primary_ship.x + 5) self.x -= 1
|
|
if (self.y < primary_ship.y + 3) self.y += 1
|
|
if (self.y > primary_ship.y + 5) self.y -= 1
|
|
end
|
|
return bullet_base.move(self)
|
|
end
|
|
|
|
function xp_gem:hitship(ship)
|
|
if (ship ~= primary_ship or primary_ship.dead) return false
|
|
primary_ship.xp += self.val
|
|
primary_ship.last_xp_frame = gframe
|
|
return true
|
|
end
|
|
|
|
-- small gems for 1, 5, 25
|
|
-- exactly; else huge
|
|
function spawn_xp_at(x, y, off, amt)
|
|
x += rnd(off+off)-off
|
|
y += rnd(off+off)-off
|
|
xp_gem.new{
|
|
qsprite=amt == 0x0.0001 and 32 or amt == 0x0.0005 and 33 or amt == 0x0.0019 and 34 or 35,
|
|
val = amt,
|
|
}:spawn_at(mid(x, 0, 124),mid(y,-4,125))
|
|
end
|
|
|
|
-->8
|
|
-- upgrade options
|
|
|
|
-- all these return
|
|
-- a [2] of rearm_t:
|
|
--
|
|
-- icon: sprite id
|
|
-- hdr: title text
|
|
-- body: text
|
|
-- action: callback
|
|
-- (method)
|
|
|
|
spec_gunt = {
|
|
protron_gun_p,
|
|
vulcan_gun_p,
|
|
blast_gun,
|
|
}
|
|
|
|
-- picks n random items from
|
|
-- tbl; permutes tbl, selected
|
|
-- items at end
|
|
function pick(tbl, n)
|
|
local ret, top={}, #tbl
|
|
for x=top,top-n,-1 do
|
|
local idx = 1+rnd(x)\1
|
|
add(ret, tbl[idx])
|
|
tbl[idx]=tbl[x]
|
|
tbl[x]=ret[#ret]
|
|
end
|
|
return ret
|
|
end
|
|
|
|
-- add a new gun
|
|
function spec_gun_opts()
|
|
-- todo: avoid duplicates
|
|
return pick(spec_gunt, 2)
|
|
end
|
|
|
|
-- major upgrades
|
|
function big_opts()
|
|
return {{
|
|
icon=1,
|
|
hdr="placeholder",
|
|
body="placeholder",
|
|
action = function() end,
|
|
},
|
|
{
|
|
icon=1,
|
|
hdr="placeholder",
|
|
body="placeholder",
|
|
action = function() end,
|
|
}}
|
|
end
|
|
|
|
-- ordinary upgrades
|
|
function small_opts()
|
|
if(not primary_ship.special_guns) return pick(primary_ship:small_upgrade_opts(), 2)
|
|
local opts = {rnd(primary_ship:small_upgrade_opts())}
|
|
for g in all(primary_ship.special_guns) do
|
|
add(opts, rnd(g:small_upgrade_opts()))
|
|
end
|
|
return pick(opts, 2)
|
|
end
|
|
|
|
-->8
|
|
-- rearm screen
|
|
|
|
rearm_mode = mknew{
|
|
sel=1,
|
|
bfm=1,
|
|
crt_frm = 0,
|
|
pos=-1,
|
|
init=function(this)
|
|
poke(0x5f5c, 255) --no btnp repeat
|
|
rearm_mode.shuffle(this)
|
|
end,
|
|
}
|
|
|
|
crt={-91,-166,-2641,-1441,-23041,23295,-20491,24570}
|
|
|
|
function rearm_mode:glow_box(x0, y0, x1, y1, c, cf)
|
|
for i,v in ipairs{c[1],c[2],c[1],0} do
|
|
i -= 1
|
|
rect(x0+i,y0+i,x1-i,y1-i,v)
|
|
end
|
|
fillp(crt[1+(self.crt_frm&7)])
|
|
rectfill(x0+4, y0+4, x1-4, y1-4, cf)
|
|
fillp()
|
|
end
|
|
|
|
function easeoutbounce(t)
|
|
local n1=7.5625
|
|
local d1=2.75
|
|
|
|
if (t<1/d1) then
|
|
return n1*t*t;
|
|
elseif(t<2/d1) then
|
|
t-=1.5/d1
|
|
return n1*t*t+.75;
|
|
elseif(t<2.5/d1) then
|
|
t-=2.25/d1
|
|
return n1*t*t+.9375;
|
|
else
|
|
t-=2.625/d1
|
|
return n1*t*t+.984375;
|
|
end
|
|
end
|
|
|
|
|
|
function rearm_mode:frame_col(hot)
|
|
if (not hot) return {4,10}
|
|
if (self.bfm<=16) return {14,7}
|
|
return {2,8}
|
|
end
|
|
|
|
function rearm_mode:draw_option(id)
|
|
local rec = self.options[id]
|
|
self:glow_box(0,0,55,101,self:frame_col(self.sel == id),1)
|
|
spr(rec.icon,5, 5)
|
|
print(rec.hdr, 13, 8, 7)
|
|
print(rec.body, 5, 15, 6)
|
|
end
|
|
|
|
function rearm_mode:pos_frac()
|
|
local pos = self.pos
|
|
if (not pos) return
|
|
if (pos < 0) return 1-easeoutbounce(1+pos)
|
|
if (pos > 0) return (1-pos)*(1-pos)
|
|
return 0
|
|
end
|
|
|
|
function rearm_mode:shuffle()
|
|
-- these will be placeholders
|
|
-- until the upgrade deck
|
|
-- is a thing that exists
|
|
local lev = primary_ship.level + 1
|
|
|
|
-- for testing: more guns really early
|
|
-- if lev == 4 or lev == 12 then
|
|
if lev == 2 or lev == 3 then
|
|
self.options = spec_gun_opts()
|
|
elseif lev % 4 == 0 then
|
|
self.options = big_opts()
|
|
else
|
|
self.options = small_opts()
|
|
end
|
|
end
|
|
|
|
function rearm_mode:draw()
|
|
drawgame_top()
|
|
local frac = self:pos_frac()
|
|
camera(frac * 55, 0)
|
|
self:draw_option(1)
|
|
camera(frac * -128 + (1-frac) * -56, 0)
|
|
self:draw_option(2)
|
|
camera(0, -28 * frac)
|
|
self:glow_box(0,102,111,127,self:frame_col(self.sel < 0),1)
|
|
spr(96,15,107,4,2)
|
|
print("full ammo\nfull shield\n+50% health",54, 107, 6)
|
|
end
|
|
|
|
function rearm_mode:update_pos()
|
|
local pos = self.pos
|
|
if (not pos) return
|
|
if (pos == 0) then
|
|
if (primary_ship.xp < primary_ship.xptarget) self.pos = 1
|
|
xpwhoosh = nil
|
|
return
|
|
end
|
|
if (pos < 0) pos = min(pos + 0x0.05, 0)
|
|
if pos > 0 then
|
|
pos -= 0x0.1
|
|
if (pos <= 0) pos = 999
|
|
end
|
|
self.pos = pos
|
|
end
|
|
|
|
function rearm_mode:update()
|
|
self.crt_frm+=0.25
|
|
self:update_pos()
|
|
if self.pos > 1 then
|
|
mode = game_mode
|
|
return -- do not advance frame
|
|
end
|
|
local sel, bfm = self.sel, self.bfm
|
|
if (btn(3) and sel > 0 or btn(2) and sel < 0) sel=-sel
|
|
if (btn(0)) sel = 1
|
|
if (btn(1)) sel = 2
|
|
if (btn()&0xF ~= 0) and bfm >= 10 or bfm >= 30 then
|
|
bfm = 1
|
|
else
|
|
bfm += 1
|
|
end
|
|
self.bfm = bfm
|
|
|
|
if primary_ship.xp < primary_ship.xptarget then
|
|
sel = 0
|
|
elseif btnp(4) or btnp(5) and self.pos == 0 then
|
|
if sel < 0 then
|
|
-- todo: sound: rearm
|
|
primary_ship.shield = primary_ship.maxshield
|
|
-- todo: rewrite for three guns
|
|
local specs = primary_ship.special_guns
|
|
if specs then
|
|
specs[1].ammo = specs[1].maxammo
|
|
if (specs[2]) specs[2].ammo = specs[2].maxammo
|
|
end
|
|
primary_ship.hp = min(primary_ship.maxhp, primary_ship.hp + primary_ship.maxhp/2)
|
|
primary_ship.xp -= primary_ship.xptarget / 2
|
|
else
|
|
local c = self.options[sel]
|
|
if c then
|
|
-- todo: sound: upgrade
|
|
c:action()
|
|
primary_ship.xp -= primary_ship.xptarget
|
|
primary_ship.xptarget += primary_ship.level * 0x0.0002
|
|
primary_ship.level += 1
|
|
if (primary_ship.xp >= primary_ship.xptarget) self:shuffle()
|
|
end
|
|
end
|
|
end
|
|
self.sel = sel
|
|
end
|
|
|
|
__gfx__
|
|
00000000000650000000000000000000bb0b50b59909209200cc0c00000000003b00000082000000e00e8002e00e800200333300002222000000000000000000
|
|
00000000006765000000000000cccc00b50b3055920940220c0000c000bbbb0037000000a2000000e0e8880240e8480403bbbb30028888200000000000000000
|
|
00700700006d6500000000000cddddd00b33335009444420c00c000c0b333330b7000000a8000000e88e2882e48e24823bbaabb3288aa8820000000000000000
|
|
00077000067c665000000000cdd10cd10b3dd350094dd42000c0000cb3350b35b7000000a8000000e88e2882484e24423ba77ab328a77a820000000000000000
|
|
00077000067d665000000000cd10cdd100b3350000944200c0000000b350b335b7000000a8000000e88e2882e84e28823ba77ab328a77a820000000000000000
|
|
0070070065666765000000000ddddd100b33355009444220c000000c03333350b7000000a800000008888820048488203bbaabb3288aa8820000000000000000
|
|
000000006506506500000000001111000b0b5050090920200c0000c000555500b7000000a2000000008882000048420003bbbb30028888200000000000000000
|
|
00000000650000650000000000000000000b50000009200000c0cc0000000000b700000082000000000820000008200000333300002222000000000000000000
|
|
0000000000065000000650000003b0000070070080000000700000000bb0000008800000000000000009200000000000cccccccd000650000000000000000000
|
|
000000000067500000076500000370000005500080000000b0000000b76300008a920000000000009009200200000000c111111d006765000000000000000000
|
|
00000000006d6500006d6500000b7000700660079000000030000000b663000089920000000550009994444200000000c111111d006d65000000000000000000
|
|
00000000067c6650067c6650000b7000056ccd50a000000030000000033000000220000000576d009446544200000000c111111d067c66500000000000000000
|
|
00000000067d6650067d6650000b7000056ccd500000000000000000000000000000000000566d009244442200000000c111111d067d66500000000000000000
|
|
000000005666657576667650000b7000700dd00700000000000000000000000000000000000dd0009092220200000000c111111d656667650000000000000000
|
|
000000005656506666565650000370000005500000000000000000000000000000000000000000000090020000000000c111111d650650650000000000000000
|
|
0000000056500056650006500003b00000700700000000000000000000000000000000000000000000a00a0000000000cddddddd650000650000000000000000
|
|
060007000600070006600770766c777c0000000000a0008000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
6cd07cd06cd07cd06ccd7ccd6ccd7ccd000000000090008000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
0d000d006cd07cd06ccd7ccd6ccd7ccd0000000000800a0000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
000000000d000d000dd00dd0cdd1cdd0000000000080090000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
0600060006000600066006607667766c00000000000a080000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
67d06c7067d06c70677d6cc7677d6cc7000000000009080000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
0d00070067d06c7067cd6cc767cd6cc7000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
000000000d0007000dd007707dd1c771000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
00000000000000000000000000000000cccccccccccccccc77000000007700000000770000000077000000000000000000000000000000000000000000000000
|
|
00000000000000000000000000000000c116611dc11ee11d70000000077000000007700000000770000000070000000000000000000000000000000000000000
|
|
00000000000000000000000000000000c1611c1dc11ee11d00000000770000000077000000007700000000770000000700000000000000000000000000000000
|
|
00000000000000000000000000000000c61111cdceeeeeed00000000700000000770000000077000000007700000007700000000000000000000000000000000
|
|
00000000000000000000000000000000c6111bcdceeeeeed00000000000000007700000000770000000077000000077000000007000000000000000000000000
|
|
00000000000000000000000000000000c161bbbdc11ee11d00000000000000007000000007700000000770000000770000000077000000000000000000000000
|
|
00000000000000000000000000000000c11ccb1dc11ee11d00000000000000000000000077000000007700000007700000000770000000070000000000000000
|
|
00000000000000000000000000000000cdddddddcddddddd00000000000000000000000070000000077000000077000000007700000000770000000000000000
|
|
cccccccccccc0000cccccccccccc0000cccccccccccc0000cccccccccccc0000cccccccccccc0000cccccccccccc0000cccccccccccc0000cccccccccccc0000
|
|
c1111111111d0000c1111111111d0000c1111111111d0000c1111111111d0000c1111111111d0000c111eeee111d0000ceee2222eeed0000c2221111222d0000
|
|
c1111111111d0000c1111111111d0000c1111111111d0000c1111111111d0000c111eeee111d0000c1ee2222ee1d0000ce22111122ed0000c2111111112d0000
|
|
c1111111111d0000c1111111111d0000c1111111111d0000c111eeee111d0000c11e2222e11d0000c1e211112e1d0000ce21111112ed0000c2111111112d0000
|
|
c1111111111d0000c1111111111d0000c1111ee1111d0000c11ee22ee11d0000c1e221122e1d0000ce21111112ed0000c2111111112d0000c1111111111d0000
|
|
c1111111111d0000c1111ee1111d0000c111e22e111d0000c11e2112e11d0000c1e211112e1d0000ce21111112ed0000c2111111112d0000c1111111111d0000
|
|
c1111111111d0000c1111ee1111d0000c111e22e111d0000c11e2112e11d0000c1e211112e1d0000ce21111112ed0000c2111111112d0000c1111111111d0000
|
|
c1111111111d0000c1111111111d0000c1111ee1111d0000c11ee22ee11d0000c1e221122e1d0000ce21111112ed0000c2111111112d0000c1111111111d0000
|
|
c1111111111d0000c1111111111d0000c1111111111d0000c111eeee111d0000c11e2222e11d0000c1e211112e1d0000ce21111112ed0000c2111111112d0000
|
|
c1111111111d0000c1111111111d0000c1111111111d0000c1111111111d0000c111eeee111d0000c1ee2222ee1d0000ce22111122ed0000c2111111112d0000
|
|
c1111111111d0000c1111111111d0000c1111111111d0000c1111111111d0000c1111111111d0000c111eeee111d0000ceee2222eeed0000c2221111222d0000
|
|
cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
044444000444444400000000000000000000000000000000000000000000000000000000000000000000000000000000000bb000000aa0000009900000088000
|
|
447777700477777a0000000000000000000000000000000000000000000666000077700008888800000ab00006000060000bb000000aa0000009900000088000
|
|
477aaa7a0477aaaa0000000000000000000000000000000000000000006ddd5007fff70008eeee20000ab00006c006d0000bb000000aa0000009900000088000
|
|
47a0047a047a0000000000000000000000000000000000000000000006dd7d5007ffff4008eeee200aaabbb006ccccd0000bb000000aa0000009900000088000
|
|
47a0447a047a0000000000000000000000000000000000000000000006d7dd5007ffff4008eeee200bbb333006ccccd0000bb000000aa0000009900000088000
|
|
47a4477a047a4440000000000000000000000000000000000000000006ddd500004fff4008eeee20000b300006d00cd0000bb000000aa0000009900000088000
|
|
477777a00477777a0000000000000000000000000000000000000000005550000004440002222200000b30000d0000d0000bb000000aa0000009900000088000
|
|
477770000422aaaa22220002000002000000000000000000000000000000000000000000000000000000000000000000000bb000000aa0000009900000088000
|
|
47a77700022ee0002eeee002e00022e00000000000000000000000000000000000000000000000000000000000000000000bb000000aa0000009900000088000
|
|
47a4777002ea2e002e002e02ee022ee00000000000000000000000000005600000474000028282000004b000060000000bbbbbb00aaaaaa00999999008888880
|
|
47a0477a22ea2e002e002e02e2e2e2e0000000000000000000000000005d0d0004f0f400080e0e00000a000000c000d00b0000b00a0000a00900009008000080
|
|
47a0047a2e2222e02e222e02e02e02e000000000000000000000000005d07050070f0f2002e0e02004a0b0b0060c0c000b0bb0b00a0aa0a00909909008088080
|
|
47a0047a2eeeeeea2eeee002e02e02e000000000000000000000000006070d1004f0f040080e0e000b0b035000c0c0d00b0bb0b00a0aa0a00909909008088080
|
|
0aa000aa2e7aa2ea2e00e002e02e02e000000000000000000000000000d0d100002f0f2002e0e0200000300006000c000b0000b00a0000a00900009008000080
|
|
000000002e0002e02e002e02e02e02e0000000000000000000000000000510000002420002020200000b5000000000d00bbbbbb00aaaaaa00999999008888880
|
|
000000000e0000e00e000e00e00e00e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
__label__
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007777777777777777
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666611111666665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666115151166665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666111611156665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666115161156665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666611111556665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666665555566665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007655555555555565
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007650b000000b0765
|
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765000bbbb000765
|
|
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076500b0000b00765
|
|
00000000000000000000000000000000000000000000e00e800200000000000000000000000000000000000000000000000000000000000076500b0bb0b00765
|
|
00000000000000000000000050000000000000000000e0e8880200000000000000000000000000000000000000000000000000000000000076500b0bb0b00765
|
|
00000000000000000000000000000000000000000000e88e288200000000000000000000000000000000000000000000000000000000000076500b0000b00765
|
|
00000000000000000000000000000000000000000d00e88e2882000000000000000000000000000000000000000000000000000000000000765000bbbb000765
|
|
00000000000000000000000000000000000000000000e88e28820000000000000000000000000000000000000000000000000000000000007650b000000b0765
|
|
00000000000000000000000000000000000000000000088888200000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
00000000000000000000000000000000000000000000008882000000000000000000000000000000000000000000000000000000000000007657777777777765
|
|
00000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000007666666666666665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007655555555555565
|
|
0000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000765aeaeaeaeae765
|
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765eaeaeaeaea765
|
|
0000000000000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000765aeaeaeaeae765
|
|
00000000000000000000000000000000000000000000000000000009909209200000000000000000000000000000000000000000000000007657777777777765
|
|
00000000000000000000000000000000000000000000000000000009209402200000000000000000000000000000000000000000000000007666666666666665
|
|
00000000000000000000000000000000000000000000000000000000944442000000000000000000000000000000000000000000000000007666666666666665
|
|
0000000000000000000000000000000000000000000000000000000094dd42000000000000000000000000000000000000000000000000007666666666666665
|
|
00000000000000000000000000000000000000000000000000000000094420000000000000000000000000000000000000000000000000007666622222666665
|
|
00000000000000000000000000000000000000000000000000500000944422000000000000000000000000000000000000000000000000007666225552266665
|
|
00000000000000000000000000000000000000000000000000000000909202000000000000000000000000000000000000000000000000007666225262256665
|
|
00000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000007666225652256665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666622222556665
|
|
00000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666665555566665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007655555555555565
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
00000000000000000005000000009200000000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
00000000050000000000000009009200200000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
000000000000000000d0000009994444200000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
00000000000000000000000009446544200000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
00000000000000000000000009244442200000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
0000000000000000000000000909222020000000000000000bbbb000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
000000000000000000000000000900200000000000000000b3333300000000000000000000000000000000000000000000000000000000007650000000000765
|
|
000000000000000000000000000a00a0000000000000000b3350b350000000000000000000000000000000000000000000000000000000007650000000000765
|
|
00000000000000000000000000000000000000000000000b350b3350000000000000000000000000000000000000000000000000000000007657777777777765
|
|
00000000000000000000000000000000000000000000000033333500000000000000000000000000000000000000000000000000000000007666666666666665
|
|
00000000000000000000000000000000088000000000000005555000000000000000000000000000000000000000000000000000000000007655555555555565
|
|
000000000000000000000000000000058a9200000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
00000000000000000000000000000000899200000000000000000000008200000000000000000000000000000000000000000000000000007650000000000765
|
|
0000000000000000000000000000000002200000000000000000000000a200000000000000000000000000000000000000000000000000007650000000000765
|
|
0000000000000000000500000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007657777777777765
|
|
0000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007666666666666665
|
|
0000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007666666666666665
|
|
0000000000000000000000000088000000000050000000000000000000a800000000000000000000000000000000000000000000000000007666666666666665
|
|
20000000000000000000000008a9200000000000000000000000000000a200000000000000000000000000000000000000000000000000007611161616111665
|
|
20000000000000000000000008992000000000000000000000000000008200000000000000000000000000000000000000000000000000007615151515151565
|
|
000000000000000000000000002200000d0000000000000000000000000000000000000000000000000000000000000000000000000000007611151515116565
|
|
0000000000000000000000000000000000000e00e800200000000000e00e80020000000000000000000000000000000000000000000000007615551115151665
|
|
0000000000000000000000000000000d00000e0e8880200000000000e0e888020000000000000000000000000000000000000000000000007615661115151565
|
|
0000000000000000000000000000000000d00e88e2882000000d0000e88e28820000000000000000000000000000000000000000000000007665666555656565
|
|
0000088000000000000880000000000000000e88e288200000000000e88e28820000000000000000000000000000000000000000000000007666666666666665
|
|
00008a9200000000008a92000000000000000e88e288200000000000e88e28820000000000000000000000000000000000000000000000007655555555555565
|
|
0000899200000000008992000000000000000088888200000000000008888820000000000000000000000000000000000000000000000000765aaaaaaaaaa765
|
|
0000022000000000000220000000000000000008882000000000000000888200000000000000000000000000000000000000000000000000765aaaaaaaaaa765
|
|
0000000000000000000000000000000000000000820000000000000000082000000000000000000000000000000000000000000000000000765aaaaaaaaaa765
|
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765aaaaaaaaaa765
|
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765a9a9a9a9a9765
|
|
00000000000088000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007659a9a9a9a9a765
|
|
000000000008a920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765a9a9a9a9a9765
|
|
00000000000899200000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000007659a9a9a9a9a765
|
|
0000000000002200000000000000000000008a92000000000000000000000000000000000000000000000000000000000000000000000000765a9a9a9a9a9765
|
|
00000000000000000000000000000000000089920000000000000000000000000000000000000000000000000000000000000000000000007659999999999765
|
|
00000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000000000000007659999999999765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007659999999999765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007659999999999765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007659999999999765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654949494949765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007659494949494765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654949494949765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007659494949494765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654949494949765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654444444444765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654444444444765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654444444444765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654444444444765
|
|
00000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000007654444444444765
|
|
0000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000007654444444444765
|
|
0000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007657777777777765
|
|
0000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007666666666666665
|
|
0000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007666666666666665
|
|
0000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007666666666666665
|
|
0000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000007666666666666665
|
|
00000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000007616166666611665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007615156666165565
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007611156666111665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007615156666651565
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007615156666116565
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007665656666655665
|
|
00000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000007666666666666665
|
|
0000000000000000000000000000000000000000000000000000000000000000008a920000000000000000000000000000000000000000007655555555555565
|
|
00000000000000000000000000000000000000000000000000000000000000000089920000000000000000000000000000000000000000007652222750000765
|
|
00000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000007652222750000765
|
|
00000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000007652222750000765
|
|
00000000000000000000000000000000000000000000000000000000067650000000000000000000000000000000000000000000000000007652222750000765
|
|
0000000000000000000000000000000000000000000000000000000006d650000000000000000000000000000000000000000000000000007652222750000765
|
|
0000000000000000000000000000000000000000000000000000000067c665000000000000000000000000000000000000000000000000007652222750000765
|
|
0000000000000000000000000000000000000000000000000000000067d665000000000000000000000000000000000000000000000000007652828750000765
|
|
00000000000000000000000000000000000000000000000000000006566676500000000000000000000000000000000000000000000000007658282750000765
|
|
00000000000000000000000000000000000000000000000000000006506506500000000000000000000000000000000000000000000000007652828750000765
|
|
00000000000000000000000000000000000000000000000000000006500006500000000000000000000000000000000000000000000000007658282750000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007652828750000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658282750000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007657777757777765
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007555555555555555
|
|
|
|
__gff__
|
|
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000212060a0e01091119000000000000002232363a3e050d151d
|
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
__map__
|
|
00006b6b00006f6a6a6a6a6a6a6a6a6a6a6a6f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
7b6a00006a7b6e6a6a6a6a6a6a6a6a6a6a6a6f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
7778686878776c6a6a6a6a6a6a6a6a6a6a6a6e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
6767777767676c6a6a6a6a6a6a6a6a6a6a6a6e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
7877676777787d6a6a6a6a6a6a6a6a6a6a6a6d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
000000000000006a6a6a6a6a6a6a6a6a6a6a6d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
000000000000006a6a6a6a6a6a6a6a6a6a6a6c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
000000000000006a6a6a6a6a6a6a6a6a6a6a7c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|