causes x offset to reverse for negative aim; may need to be careful with how I make aiming guns actually work, but this should work for deriving player guns from enemy guns (by using negative aim)!
2269 lines
67 KiB
Lua
2269 lines
67 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
|
|
|
|
-- intrusive singly-linked list.
|
|
-- cannot be nested!
|
|
linked_list = mknew{
|
|
is_linked_list=true,
|
|
init = function(x)
|
|
x.next=nil
|
|
x.tail=x
|
|
end,
|
|
}
|
|
|
|
function linked_list:push_back(x)
|
|
self.tail.next = x
|
|
self.tail = x
|
|
end
|
|
|
|
function linked_list:push_front(x)
|
|
if (not self.next) self.tail = x
|
|
x.next = self.next
|
|
self.next = x
|
|
end
|
|
|
|
-- vore eats another linked list
|
|
-- by appending its contents.
|
|
-- the ingested linked is empty.
|
|
function linked_list:vore(x)
|
|
if (not x.next) return
|
|
self.tail.next = x.next
|
|
self.tail = x.tail
|
|
x.next = nil
|
|
x.tail = x
|
|
end
|
|
|
|
-- strip calls f(x) for each
|
|
-- node, removing each node for
|
|
-- which f(x) returns true. it
|
|
-- returns the new tail; nil
|
|
-- if the list is now empty.
|
|
function linked_list:strip(f)
|
|
local p, n = self, self.next
|
|
while n do
|
|
if f(n) then
|
|
p.next = n.next
|
|
else
|
|
p = n
|
|
end
|
|
n = n.next
|
|
end
|
|
self.tail = p
|
|
return p
|
|
end
|
|
|
|
-- optimized special case -
|
|
-- could be done with strip but
|
|
-- this avoids extra function
|
|
-- calls and comparisions since
|
|
-- draw isn't allowed to kill
|
|
-- the item
|
|
function linked_list:draw()
|
|
local n = self.next
|
|
while n do
|
|
n:draw()
|
|
n = n.next
|
|
end
|
|
end
|
|
|
|
|
|
function linked_list:pop_front()
|
|
local ret = self.next
|
|
if (not ret) return
|
|
self.next = ret.next
|
|
if (not ret.next) ret.tail = nil
|
|
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)
|
|
new_events:push_back{
|
|
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()
|
|
pships = linked_list.new()
|
|
pships:push_back(primary_ship)
|
|
eships = linked_list.new()
|
|
pbullets = linked_list.new()
|
|
ebullets = linked_list.new()
|
|
intangibles_fg = linked_list.new()
|
|
intangibles_bg = linked_list.new()
|
|
events = linked_list.new()
|
|
new_events = linked_list.new()
|
|
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()
|
|
end
|
|
|
|
function call_f(x)
|
|
return x:f()
|
|
end
|
|
|
|
function call_move(x)
|
|
return x:move()
|
|
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()
|
|
if (primary_ship.xp >= primary_ship.xptarget) and (gframe - primary_ship.last_xp_frame > 0x0.000f) and (not primary_ship.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(0, 0, min(ones(waves_complete)\2, 4))
|
|
end
|
|
events:vore(new_events)
|
|
events:strip(call_move)
|
|
for _, lst in ipairs{intangibles_bg, pships, eships, pbullets, ebullets} do
|
|
lst:strip(call_move)
|
|
end
|
|
|
|
pships:strip(
|
|
function(ps)
|
|
local pbox, pded = hurtbox(ps), false
|
|
eships:strip(
|
|
function(es)
|
|
if (not collides(pbox, hurtbox(es))) return
|
|
pded = pded or ps:hitship(es)
|
|
return es:hitship(ps)
|
|
end
|
|
)
|
|
return pded
|
|
end
|
|
)
|
|
pships:strip(
|
|
function(ps)
|
|
local pbox, pded = hurtbox(ps), false
|
|
ebullets:strip(
|
|
function(eb)
|
|
if (not collides(pbox, hurtbox(eb))) return
|
|
pded = pded or ps:hitbullet(eb)
|
|
return eb:hitship(ps)
|
|
end
|
|
)
|
|
return pded
|
|
end
|
|
)
|
|
|
|
-- many bullets and many enemy ships;
|
|
-- use bucket collider for efficiency
|
|
local pbullet_collider = collider.new()
|
|
local p, n = pbullets, pbullets.next
|
|
while n do
|
|
n.prev = p
|
|
pbullet_collider:insert(n)
|
|
p = n
|
|
n = p.next
|
|
end
|
|
|
|
eships:strip(
|
|
function(es)
|
|
for pb in all(pbullet_collider:get_collisions(es)) do
|
|
if pb:hitship(es) then
|
|
pbullet_collider:hide(pb)
|
|
pb.prev.next = pb.next
|
|
if pb.next then
|
|
pb.next.prev = pb.prev
|
|
else
|
|
pbullets.tail = pb.prev
|
|
end
|
|
end
|
|
if (es:hitbullet(pb)) return true
|
|
end
|
|
end
|
|
)
|
|
|
|
intangibles_fg:strip(call_move)
|
|
|
|
if waves_complete == 32767 and not eships.next and not ebullets.next and not events.next then
|
|
game_state = win
|
|
end
|
|
if (not pships.next) game_state = lose
|
|
|
|
if primary_ship.xp >= primary_ship.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()
|
|
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.." "
|
|
|
|
if item.is_linked_list then
|
|
local ret,n = "linked_list <",0
|
|
item:strip(function(x)
|
|
n += 1
|
|
ret ..= xpfx..tostr(n)..": "..puke(x, indent+2, seen, "next")
|
|
end)
|
|
return ret..pfx..">"
|
|
end
|
|
|
|
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 slist in all{intangibles_bg, pbullets, pships, eships, ebullets, intangibles_fg} do
|
|
slist:draw()
|
|
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()
|
|
self:refresh_shield()
|
|
local dx, dy, shoot_spec1, shoot_spec2 = self:act()
|
|
dx = self:constrain(self.x, self.xmomentum, self.xmin, self.xmax, dx)
|
|
dy = self:constrain(self.y, self.ymomentum, self.ymin, self.ymax, dy)
|
|
self:maybe_shoot(self.main_gun)
|
|
if (shoot_spec1 and self.special_guns) self:maybe_shoot(self.special_guns[1])
|
|
if (shoot_spec2 and self.special_guns) self:maybe_shoot(self.special_guns[2])
|
|
spark(self.sparks, self.x + 4*self.size, self.y + 4*self.size, dx*2.5, dy*2.5, self.sparkodds)
|
|
self.xmomentum = self:calc_velocity(self.xmomentum, dx)
|
|
self.ymomentum = self:calc_velocity(self.ymomentum, dy)
|
|
|
|
self.x += self.xmomentum
|
|
self.y += self.ymomentum
|
|
|
|
return false
|
|
end
|
|
|
|
function ship_m:draw()
|
|
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
|
|
return {
|
|
x=ship.x + h.x_off,
|
|
y=ship.y + h.y_off,
|
|
width=h.width,
|
|
height=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
|
|
-- die -- on-removal event,
|
|
-- default no-op
|
|
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,
|
|
}
|
|
|
|
-- 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
|
|
|
|
-- default firing behavior:
|
|
-- single shot
|
|
function gun_base:actually_shoot(x, y)
|
|
self.munition.new{}:spawn_at(x, y)
|
|
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(_)
|
|
self:die()
|
|
return true
|
|
end
|
|
|
|
function bullet_base:die()
|
|
end
|
|
|
|
function bullet_base:move()
|
|
self.x += self.dx
|
|
self.y += self.dy
|
|
if (self.f) self.f -= 1
|
|
if (self.y > 145) or (self.y < -8 * self.height) or (self.f and self.f < 0) then
|
|
self:die()
|
|
return true
|
|
end
|
|
return false
|
|
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
|
|
self.category():push_back(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
|
|
|
|
trig_gun = mknew(gun_base.new{
|
|
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
|
|
})
|
|
|
|
function trig_gun: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 = unpack(s)
|
|
v = v or veloc
|
|
xo = xo or 0
|
|
-- reverse x-offset for negative base angle
|
|
if (aim < 0) xo = -xo
|
|
a += aim
|
|
-- 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{}
|
|
-- todo: automatically make
|
|
-- high velocity shots do
|
|
-- multiple collision checks
|
|
m.dy = sin(a) * veloc
|
|
m.dx = cos(a) * veloc
|
|
m:spawn_at(x+(xo or 0), y)
|
|
end
|
|
end
|
|
|
|
|
|
-->8
|
|
-- bullets and guns
|
|
|
|
zap_e = mknew(bullet_base.new{
|
|
--shape
|
|
sprite = 9, --index of ammo sprite
|
|
width = 1, --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 = 8,
|
|
|
|
damage = 1,
|
|
|
|
hitship = const_fxn(true),
|
|
|
|
category = enemy_blt_cat,
|
|
})
|
|
|
|
zap_p = mknew(zap_e.new{
|
|
sprite = 8,
|
|
y_off = 0,
|
|
category = player_blt_cat,
|
|
})
|
|
|
|
zap_gun_e = mknew(trig_gun.new{
|
|
cooldown = 0x0.0020, -- frames between shots
|
|
veloc = 4,
|
|
munition = zap_e,
|
|
})
|
|
|
|
zap_gun_p = mknew(zap_gun_e.new{
|
|
icon = 19,
|
|
munition = zap_p,
|
|
veloc = 8,
|
|
aim = 0.25,
|
|
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()
|
|
new_events:push_back{
|
|
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
|
|
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,
|
|
dym = 0.5, -- gun sets dy;
|
|
-- this is mult
|
|
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
|
|
})
|
|
|
|
function protron_gun_e:actually_shoot(x, y)
|
|
local m = self.munition.dym
|
|
for i=1,3 do
|
|
local b = self.munition.new{
|
|
dx = i*m,
|
|
dy = (4-i)*m,
|
|
}
|
|
b:spawn_at(x,y)
|
|
local b2 = self.munition.new{
|
|
dx = -i*m,
|
|
dy = (4-i)*m,
|
|
}
|
|
b2:spawn_at(x,y)
|
|
end
|
|
local bup = self.munition.new{
|
|
dx=0,
|
|
dy=4*m,
|
|
}
|
|
bup:spawn_at(x,y)
|
|
end
|
|
|
|
protron_gun_p = mknew(protron_gun_e.new{
|
|
munition = protron_p,
|
|
maxammo = 20,
|
|
cooldown = 0x0.0018,
|
|
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 = 1, --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 = 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(trig_gun.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: x, y, width, height
|
|
|
|
function collides(box1, box2)
|
|
return not (
|
|
box1.x>box2.x+box2.width
|
|
or box1.y>box2.y+box2.height
|
|
or box1.x+box1.width<box2.x
|
|
or box1.y+box1.height<box2.y)
|
|
end
|
|
|
|
collider = mknew{
|
|
init = function(x)
|
|
x.suppress = {}
|
|
end,
|
|
}
|
|
|
|
function collider_indexes(box)
|
|
local ret = {}
|
|
for x = box.x\8, (box.x+box.width)\8 do
|
|
for y = box.y\8, (box.y+box.height)\8 do
|
|
add(ret, x+256*y)
|
|
end
|
|
end
|
|
return ret
|
|
end
|
|
|
|
function collider:insert(item)
|
|
-- todo: separate "big items" list?
|
|
local bdx = collider_indexes(hurtbox(item))
|
|
for i in all(bdx) do
|
|
local x = self[i]
|
|
if not x then
|
|
x = {}
|
|
self[i] = x
|
|
end
|
|
add(x, item)
|
|
end
|
|
end
|
|
|
|
function collider:hide(item)
|
|
self.suppress[item]=true
|
|
end
|
|
|
|
function collider:get_collisions(item)
|
|
local found = { }
|
|
local seen = { }
|
|
local box = hurtbox(item)
|
|
local bucket_ids = collider_indexes(box)
|
|
for b_idx in all(bucket_ids) do
|
|
local bucket = self[b_idx]
|
|
if bucket then
|
|
for candidate in all(bucket) do
|
|
if not (seen[candidate] or self.suppress[candidate]) then
|
|
seen[candidate] = true
|
|
if (collides(box, hurtbox(candidate))) add(found, candidate)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return found
|
|
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()
|
|
eships:push_back(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 true
|
|
self.frames -= 1
|
|
if self.frames < 0 then
|
|
self.obj.fx_pal = nil
|
|
return true
|
|
end
|
|
return false
|
|
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()
|
|
events:push_back(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 true
|
|
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)
|
|
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:push_back(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
|
|
|
|
-- todo: "magnetic" behavior
|
|
-- when near player ship
|
|
|
|
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
|
|
000000006506506500000000001111000b0b5050090920200c0000c00055550037000000a2000000008882000048420003bbbb30028888200000000000000000
|
|
00000000650000650000000000000000000b50000009200000c0cc00000000003b00000082000000000820000008200000333300002222000000000000000000
|
|
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__
|
|
00006b6b00006f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
7b6a00006a7b6e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
7778686878776c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
6767777767676c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
7877676777787d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|