forked from pyrex/chameleonic
1876 lines
63 KiB
Lua
1876 lines
63 KiB
Lua
pico-8 cartridge // http://www.pico-8.com
|
|
version 39
|
|
__lua__
|
|
-- setup
|
|
modules={}
|
|
real_modules={}
|
|
|
|
frame=0
|
|
function _init()
|
|
_doall("init") end
|
|
function _update()
|
|
frame+=1
|
|
if (frame%1==0) _doall("update") end
|
|
function _draw()
|
|
_doall("draw") end
|
|
|
|
mnames={}
|
|
function names(root)
|
|
local n=mnames[root]
|
|
if(n)return all(n)
|
|
n={root.."0", root, root.."2", root.."3"}
|
|
mnames[root]=n
|
|
return all(n)
|
|
end
|
|
|
|
function _doall(x)
|
|
for n in names(x) do
|
|
for mod in all(modules) do
|
|
local f=mod[n]
|
|
if (f) f(mod)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- source: https://www.lexaloffle.com/bbs/?pid=78990
|
|
gaps=split"57,23,10,4,1"
|
|
--{701,301,132,57,23,10,4,1}
|
|
function shellsort(a)
|
|
for gap in all(gaps) do
|
|
for i=gap+1,#a do
|
|
local x,j=a[i],i-gap
|
|
while j>=1 and a[j].key>x.key do
|
|
a[j+gap]=a[j]
|
|
j-=gap
|
|
end
|
|
a[j+gap]=x
|
|
end
|
|
end
|
|
end
|
|
|
|
function linefill(ax,ay,bx,by,r,c)
|
|
if(c) color(c)
|
|
local dx,dy=bx-ax,by-ay
|
|
-- avoid overflow
|
|
-- credits: https://www.lexaloffle.com/bbs/?tid=28999
|
|
local d=max(abs(dx),abs(dy))
|
|
local n=min(abs(dx),abs(dy))/d
|
|
d*=sqrt(n*n+1)
|
|
if(d<0.001) return
|
|
local ca,sa=dx/d,-dy/d
|
|
|
|
-- polygon points
|
|
local s={
|
|
{0,-r},{d,-r},{d,r},{0,r}
|
|
}
|
|
local u,v,spans=s[4][1],s[4][2],{}
|
|
local x0,y0=ax+u*ca+v*sa,ay-u*sa+v*ca
|
|
for i=1,4 do
|
|
local u,v=s[i][1],s[i][2]
|
|
local x1,y1=ax+u*ca+v*sa,ay-u*sa+v*ca
|
|
local _x1,_y1=x1,y1
|
|
if(y0>y1) x0,y0,x1,y1=x1,y1,x0,y0
|
|
local dx=(x1-x0)/(y1-y0)
|
|
if(y0<0) x0-=y0*dx y0=-1
|
|
local cy0=y0\1+1
|
|
-- sub-pix shift
|
|
x0+=(cy0-y0)*dx
|
|
for y=y0\1+1,min(y1\1,127) do
|
|
-- open span?
|
|
local span=spans[y]
|
|
if span then
|
|
rectfill(x0,y,span,y)
|
|
else
|
|
spans[y]=x0
|
|
end
|
|
x0+=dx
|
|
end
|
|
x0,y0=_x1,_y1
|
|
end
|
|
end
|
|
|
|
function _apply(x,ts,a)
|
|
local t=deli(ts,1)
|
|
for k,v in pairs(t) do
|
|
if k=="update" then
|
|
if not v(x,a) then
|
|
add(ts,t,1)
|
|
end
|
|
else
|
|
x[k]=v
|
|
end
|
|
end
|
|
end
|
|
|
|
function sgn0(x)
|
|
if (x==0) return x
|
|
return sgn(x)
|
|
end
|
|
|
|
function _mnmx(x,y)
|
|
if (x>y)return y,x
|
|
return x,y
|
|
end
|
|
|
|
-->8
|
|
-- input
|
|
kbd={}
|
|
add(real_modules,kbd)
|
|
function kbd:init()
|
|
self.prev_real=btn()
|
|
self.down=0
|
|
end
|
|
|
|
function kbd:update()
|
|
local now=btn()
|
|
local pressed=now&~self.prev_real
|
|
self.down&=now
|
|
self.down|=pressed
|
|
self.prev_real=now
|
|
end
|
|
|
|
function kbd:btn(i)
|
|
return self.down&(1<<i)!=0
|
|
end
|
|
|
|
function kbd:release(i)
|
|
self.down&=~(1<<i)
|
|
end
|
|
|
|
-->8
|
|
-- title screen
|
|
title={}
|
|
add(modules,title)
|
|
|
|
function title:init()
|
|
end
|
|
|
|
function title:draw()
|
|
cls(0)
|
|
-- this is right for 72x32
|
|
spr(3,28,56,9,2)
|
|
print("pyrex",32,73,7)
|
|
print("[nyeogmi]",62,73,7)
|
|
print("kistaro",32,79,7)
|
|
end
|
|
|
|
function title:update()
|
|
if btn()!=0 then
|
|
modules=real_modules
|
|
_init()
|
|
music(0)
|
|
end
|
|
end
|
|
-->8
|
|
--level behaviors
|
|
level={}
|
|
add(real_modules,level)
|
|
|
|
function level:init()
|
|
level:reinit(0)
|
|
end
|
|
|
|
function level:reinit(n)
|
|
self.ix=n
|
|
self.todo={}
|
|
self.bigx=(n%16)
|
|
self.bigy=(n\16)
|
|
|
|
self:load_dynobjs()
|
|
self:recollide()
|
|
self:reanchor(true)
|
|
self:spawn_exit()
|
|
end
|
|
|
|
function level:restart()
|
|
self:reinit(self.ix)
|
|
end
|
|
|
|
function level:advance()
|
|
self:reinit(self.ix+1)
|
|
end
|
|
|
|
pitpal = {[0]=1, [7]=0}
|
|
function level:draw()
|
|
cls(1)
|
|
pal(1,0)
|
|
map(
|
|
self.bigx*16,self.bigy*16,
|
|
0,0,16,16,
|
|
64 -- flag 6: visible
|
|
)
|
|
for _,pit in pairs(self._pits) do
|
|
spr(pit.s,pit.px,pit.py)
|
|
if pit.contents then
|
|
pal(pitpal)
|
|
palt(0,false)
|
|
spr(pit.contents,pit.px,pit.py)
|
|
pal()
|
|
pal(1,0)
|
|
end
|
|
for _,crate in pairs(self._crates) do
|
|
spr(crate.s,crate.px,crate.py)
|
|
end
|
|
end
|
|
pal()
|
|
end
|
|
|
|
function level:busy()
|
|
for _,crate in pairs(self.crates) do
|
|
if (#crate.todo>0) return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function level:update()
|
|
_apply(self, self.todo)
|
|
|
|
local remove={}
|
|
for cix,crate in pairs(self._crates) do
|
|
_apply(crate, crate.todo)
|
|
|
|
if #crate.todo==0 then
|
|
local pit=self._pits[_mix(crate.mx,crate.my)]
|
|
if pit and not pit.contents then
|
|
add(remove,cix)
|
|
crate.dead=true
|
|
pit.contents=crate.s
|
|
end
|
|
end
|
|
end
|
|
for cix in all(remove) do
|
|
self._crates[cix]=nil
|
|
end
|
|
if #remove>0 then
|
|
self:recollide()
|
|
self:reanchor(true)
|
|
end
|
|
end
|
|
|
|
function level:load_dynobjs()
|
|
self._crates={}
|
|
self._pits={}
|
|
|
|
for mx=0,15,1 do
|
|
for my=0,15,1 do
|
|
local mxy=_mix(mx,my)
|
|
local px,py=mx*8,my*8
|
|
local s=self:_mget(mx,my)
|
|
local def=self:_get_cratedef(s)
|
|
if def then
|
|
self._crates[mxy]={
|
|
s=s,def=def,
|
|
mx=mx,my=my,
|
|
px=px,py=py,
|
|
todo={}
|
|
}
|
|
end
|
|
|
|
if s==28 then -- pit
|
|
self._pits[mxy]={
|
|
s=s,
|
|
mx=mx,my=my,
|
|
px=px,py=py,
|
|
contents=nil
|
|
}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function level:recollide()
|
|
self._coll={}
|
|
for mx=0,15 do
|
|
for my=0,15 do
|
|
local mxy=_mix(mx,my)
|
|
self._coll[mxy]=
|
|
fget(self:_mget(mx,my),7) or
|
|
self._crates[mxy]!=nil
|
|
end
|
|
end
|
|
end
|
|
|
|
function level:reanchor(remove)
|
|
if remove or not self._anch then
|
|
self._anch={}
|
|
end
|
|
|
|
for ax0=0,31 do
|
|
local ax1 = ax0-1+2*(ax0%2)
|
|
local mx0,mx1 = ax0\2,ax1\2
|
|
for ay0=0,31 do
|
|
local ay1=ay0-1+2*(ay0%2)
|
|
local my0,my1=ay0\2,ay1\2
|
|
|
|
if (
|
|
not self:mcoll(mx0,my0) and
|
|
not self:mcoll(mx0,my1) and
|
|
not self:mcoll(mx1,my0) and
|
|
self:mcoll(mx1,my1)
|
|
) then
|
|
local px0,py0=level:a2p(ax0,ay0)
|
|
self._anch[_amix(ax0,ay0)]={ax=ax0,ay=ay0,x=px0,y=py0}
|
|
end
|
|
end
|
|
end
|
|
|
|
for _,cr in pairs(self._crates) do
|
|
for ax in all{cr.mx*2-1,cr.mx*2+2} do
|
|
for ay in all{cr.my*2-1,cr.my*2+2} do
|
|
local px,py=self:a2p(ax,ay)
|
|
self._anch[_amix(ax,ay)]={ax=ax0,ay=ay0,x=px,y=py}
|
|
end
|
|
end
|
|
end
|
|
|
|
if (player.rope!=nil) player.rope:make_dirty()
|
|
end
|
|
|
|
function level:win_at(mx,my)
|
|
return self._wins[_mix(mx,my)]
|
|
end
|
|
function level:anchor_points()
|
|
return pairs(self._anch)
|
|
end
|
|
|
|
function level:anchors_in(px0,py0,px1,py1)
|
|
local anch,ax,xlim,sy,ylim=self._anch,px0\4,(px1+3)\4,py0\4,(py1+3)\4
|
|
local ay=sy-1
|
|
return function()
|
|
while true do
|
|
ay+=1
|
|
if(ay>ylim)ay,ax=sy,ax+1
|
|
if(ax>xlim)return nil
|
|
local anc=anch[_amix(ax,ay)]
|
|
if (anc) return anc
|
|
end
|
|
end
|
|
end
|
|
|
|
function level:get_open_pit(mx,my)
|
|
local pit=self._pits[_mix(mx,my)]
|
|
if (pit and pit.contents==nil) return pit
|
|
end
|
|
|
|
function level:point_anchor(px,py)
|
|
local ax,ay=self:p2a(px,py)
|
|
local anc=self._anch[_amix(ax,ay)]
|
|
return anc
|
|
end
|
|
|
|
function level:spawn_exit()
|
|
self._wins={}
|
|
local spawned=false
|
|
local spawn_at=function(x,y)
|
|
if (self:_mget(x,y)!=1) return
|
|
assert(not spawned,x..","..y)
|
|
spawned=true
|
|
player:reinit(x,y)
|
|
player.orientx=-1
|
|
if (x<8) player.orientx=1
|
|
end
|
|
local win_at=function(x,y)
|
|
if (self:_mget(x,y)!=18) return
|
|
for n in all(neighbors{x=x,y=y}) do
|
|
if n.x<0 or n.y<0 or n.x>15 or n.y>15 then
|
|
self._wins[_mix(n.x,n.y)]=true
|
|
end
|
|
end
|
|
end
|
|
for f in all{spawn_at,win_at} do
|
|
for x=1,14 do f(x,0) f(x,15) end
|
|
for y=0,15 do f(0,y) f(15,y) end
|
|
end
|
|
assert(spawned)
|
|
end
|
|
|
|
function level:p2a(px,py)
|
|
return px\4,py\4
|
|
end
|
|
|
|
function level:a2p(ax,ay)
|
|
local px=ax*4+3*(ax%2)
|
|
local py=ay*4+3*(ay%2)
|
|
return px,py
|
|
end
|
|
|
|
function level:mcoll(mx,my)
|
|
return self._coll[_mix(mx,my)]!=false
|
|
end
|
|
|
|
function level:pcoll(px,py)
|
|
return self:mcoll(px\8,py\8)
|
|
end
|
|
|
|
function level:get_crate(mx,my)
|
|
return self._crates[_mix(mx,my)]
|
|
end
|
|
|
|
function level:_mget(mx,my)
|
|
return mget(
|
|
self.bigx*16+mx,
|
|
self.bigy*16+my
|
|
)
|
|
end
|
|
|
|
function _amix(ax,ay)
|
|
return ax..","..ay
|
|
--if (ax<0 or ay<0 or ax>31 or ay>31) return nil
|
|
--return ay*32+ax
|
|
end
|
|
|
|
function _mix(mx,my)
|
|
return mx..","..my
|
|
--if (mx<0 or my<0 or mx>15 or my>15) return nil
|
|
--return my*16+mx
|
|
end
|
|
|
|
function level:_get_cratedef(s)
|
|
if (s<64 or s>=80) return nil
|
|
|
|
local s2=s-64
|
|
return {
|
|
up=s2&1!=0,
|
|
right=s2&2!=0,
|
|
down=s2&4!=0,
|
|
left=s2&8!=0
|
|
}
|
|
end
|
|
|
|
function level:get_latch(dx,dy,px,py)
|
|
local mx,my=px\8,py\8
|
|
local mxy=_mix(mx,my)
|
|
|
|
local crate=self._crates[mxy]
|
|
local dx1,dy1=-sgn0(dx),-sgn0(dy)
|
|
|
|
if crate then
|
|
if
|
|
(crate.def.up and dy>0) or
|
|
(crate.def.down and dy<0) or
|
|
(crate.def.left and dx>0) or
|
|
(crate.def.right and dx<0)
|
|
then
|
|
return {
|
|
el="crate",
|
|
dx=dx1,dy=dy1,
|
|
px_offset=px-crate.px+dx1,
|
|
py_offset=py-crate.py+dy1,
|
|
rec=crate
|
|
}
|
|
end
|
|
end
|
|
|
|
local m=self:_mget(mx,my)
|
|
|
|
if
|
|
(m==60 and dy1<0) or
|
|
(m==61 and dx1>0) or
|
|
(m==62 and dy1>0) or
|
|
(m==63 and dx1<0)
|
|
then
|
|
return {
|
|
el="eyehook",
|
|
dx=dx1,dy=dy1,
|
|
mx=mx,my=my
|
|
}
|
|
end
|
|
end
|
|
|
|
function level:can_move(
|
|
is_player,
|
|
mx0,my0,dmx,dmy,exclude_src,exclude_dst
|
|
)
|
|
if is_player and self:win_at(mx0+dmx,my0+dmy) then
|
|
return true
|
|
end
|
|
|
|
if self:mcoll(mx0+dmx,my0+dmy) then
|
|
return false
|
|
end
|
|
|
|
if player.x==mx0+dmx and player.y==my0+dmy then
|
|
return false
|
|
end
|
|
|
|
-- todo: check tongue collision
|
|
if player.rope then
|
|
local px,py=mx0*8,my0*8
|
|
local chk=false
|
|
if dmx==0 and dmy==-1 then
|
|
chk=player.rope:collide_rect(px+3,py-5,px+4,py+5,exclude_src,exclude_dst)
|
|
elseif dmx==0 and dmy==1 then
|
|
chk=player.rope:collide_rect(px+3,py+3,px+4,py+13,exclude_src,exclude_dst)
|
|
elseif dmx==-1 and dmy==0 then
|
|
chk=player.rope:collide_rect(px-5,py+3,px+5,py+4,exclude_src,exclude_dst)
|
|
elseif dmx==1 and dmy==0 then
|
|
chk=player.rope:collide_rect(px+3,py+3,px+13,py+4,exclude_src,exclude_dst)
|
|
end
|
|
|
|
if (chk) return false
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function level:tug_crate(mx0,my0,dmx,dmy)
|
|
local mxy0=_mix(mx0,my0)
|
|
local existing=self._crates[mxy0]
|
|
if (existing==nil) return
|
|
|
|
self._crates[mxy0]=nil
|
|
|
|
local mx1,my1=mx0+dmx,my0+dmy
|
|
local mxy1=_mix(mx1,my1)
|
|
existing.mx=mx1
|
|
existing.my=my1
|
|
existing.todo={
|
|
{px=mx0*8+dmx*2,py=my0*8+dmy*2},
|
|
{px=mx0*8+dmx*7,py=my0*8+dmy*7},
|
|
{px=mx1*8,py=my1*8,update=function()
|
|
self:reanchor(true)
|
|
return true
|
|
end}
|
|
}
|
|
|
|
self._crates[mxy1]=existing
|
|
self:recollide()
|
|
self:reanchor(false)
|
|
end
|
|
-->8
|
|
--player handling
|
|
player={}
|
|
add(real_modules,player)
|
|
|
|
function player:init()
|
|
--self:reinit(8,14)
|
|
|
|
-- don't change this on reinit:
|
|
-- it stays the same when the level is changed or reloaded
|
|
self.vanish_frame=0
|
|
end
|
|
|
|
function player:reinit(x,y)
|
|
self.x=x
|
|
self.y=y
|
|
self.px=0
|
|
self.py=0
|
|
self.todo={}
|
|
|
|
self.fall_frame=0
|
|
self.reset_frame=0
|
|
|
|
self.orientx=-1
|
|
self.orienty=0
|
|
|
|
self.rope=nil
|
|
end
|
|
|
|
function player:any_busy()
|
|
if (#self.todo>0) return true
|
|
if (level:busy()) return true
|
|
if (self.rope!=nil and self.rope:busy()) return true
|
|
return false
|
|
end
|
|
|
|
function player:update()
|
|
local _addall=function(t,xs)
|
|
for i in all(xs) do
|
|
add(t,i)
|
|
end
|
|
end
|
|
|
|
local f4 = function(xs)
|
|
-- todo: other anim stuff
|
|
xs[#xs].px=0
|
|
xs[#xs].py=0
|
|
return xs
|
|
end
|
|
|
|
-- this is a non-gameplay action that takes precedence over
|
|
-- all gameplay actions
|
|
self:_vanish_if_requested()
|
|
|
|
if not self:any_busy() then
|
|
if level:win_at(self.x,self.y) then
|
|
level:advance()
|
|
return
|
|
end
|
|
if level:get_open_pit(self.x,self.y) then
|
|
self.todo={{update=self._fall}}
|
|
return
|
|
end
|
|
|
|
if kbd:btn(0) then
|
|
if level:can_move(true,self.x,self.y,-1,0,0,2) then
|
|
self.todo=f4({{orientx=-1,orienty=0,px=-2},{px=-7},{x=self.x-1}})
|
|
else
|
|
self.orientx=-1
|
|
self.orienty=0
|
|
end
|
|
elseif kbd:btn(1) then
|
|
if level:can_move(true,self.x,self.y,1,0,0,2) then
|
|
self.todo=f4({{orientx=1,orienty=0,px=2},{px=7},{x=self.x+1}})
|
|
else
|
|
self.orientx=1
|
|
self.orienty=0
|
|
end
|
|
elseif kbd:btn(2) then
|
|
if level:can_move(true,self.x,self.y,0,-1,0,2) then
|
|
self.todo=f4({{orienty=-1,py=-2},{py=-7},{y=self.y-1}})
|
|
else
|
|
self.orienty=-1
|
|
end
|
|
elseif kbd:btn(3) then
|
|
if level:can_move(true,self.x,self.y,0,1,0,2) then
|
|
self.todo=f4({{orienty=1,py=2},{py=7},{y=self.y+1}})
|
|
else
|
|
self.orienty=1
|
|
end
|
|
elseif kbd:btn(4) then
|
|
if self.rope==nil then
|
|
local rx,ry,rx2,ry2=self:_rope_pos()
|
|
local dx,dy=12*self.orientx,12*self.orienty
|
|
if (dy!=0) dx=0
|
|
self.rope=rope:new(rx,ry,rx2,ry2,dx,dy)
|
|
|
|
self.todo={{
|
|
update=function()
|
|
return self.rope==nil or self.rope:latched()
|
|
end
|
|
},{},{}}
|
|
else
|
|
self.rope:tug()
|
|
self.todo={{},{},{}}
|
|
end
|
|
elseif kbd:btn(5) then
|
|
if self.rope!=nil then
|
|
self.rope:destroy()
|
|
end
|
|
end
|
|
end
|
|
|
|
if (self.rope) self.rope:prevent_highlight(#self.todo>0)
|
|
_apply(self,self.todo)
|
|
|
|
if self.rope then
|
|
self.rope:update()
|
|
local rx,ry=self:_rope_pos()
|
|
self.rope:drag_dst(rx,ry)
|
|
|
|
local tdx,tdy=self.rope:tug_orientxy()
|
|
if (tdx!=0) self.orientx=tdx
|
|
if (tdy!=0) self.orienty=tdy
|
|
|
|
if self.rope:done() then
|
|
self.rope=nil
|
|
add(self.todo,{})
|
|
add(self.todo,{})
|
|
add(self.todo,{})
|
|
end
|
|
end
|
|
end
|
|
|
|
function player:_vanish_if_requested()
|
|
if kbd:btn(5) then
|
|
self.vanish_frame+=1
|
|
|
|
if (self.fall_frame>0 or self.vanish_frame>20) then
|
|
level:restart()
|
|
kbd:release(5)
|
|
self.vanish_frame=20
|
|
end
|
|
else
|
|
self.vanish_frame-=1
|
|
end
|
|
|
|
self.vanish_frame=max(self.vanish_frame,0)
|
|
end
|
|
|
|
function player:_fall()
|
|
if (self.fall_frame<10) self.fall_frame+=1
|
|
end
|
|
|
|
function player:_rope_pos()
|
|
local px=self.x*8+self.px+4
|
|
local px2=px
|
|
local py=self.y*8+self.py+3
|
|
local py2=py
|
|
return px,py,px2,py2
|
|
end
|
|
|
|
function player:draw()
|
|
local px=self.x*8+self.px
|
|
local py=self.y*8+self.py
|
|
|
|
local head=1-self.orienty
|
|
|
|
local vanish_level=max((self.vanish_frame-4)/16,0)
|
|
local invis_level=max(self.fall_frame/10,4*(vanish_level-0.75))
|
|
if (invis_level>=1.0) return
|
|
|
|
--px+=sin(vanish_level*16)*max(vanish_level-0.1,0)*1
|
|
local HEAD=14--3
|
|
local BODY=12--12
|
|
local TAIL=14--14
|
|
local IRIS=7--9
|
|
local PUPIL=0--0
|
|
|
|
local setpal=function()
|
|
-- base colors
|
|
pal{
|
|
[2]=HEAD,
|
|
[3]=HEAD,
|
|
[4]=BODY,
|
|
[5]=BODY,
|
|
[9]=IRIS,
|
|
[10]=PUPIL,
|
|
[12]=BODY,
|
|
[13]=TAIL,
|
|
[14]=TAIL,
|
|
[15]=TAIL,
|
|
}
|
|
|
|
-- vanish colors
|
|
local vanish=split"13,15,14,5,4,12,2,3,9,10"
|
|
for i,ilc in ipairs(vanish) do
|
|
if (vanish_level>i/#vanish) pal(ilc,1)
|
|
end
|
|
|
|
if self.fall_frame>3 then
|
|
local zc=@0x5f00&0xf0
|
|
for i=0x5f00,0x5f0c,4 do poke4(i,0x0101.0101) end
|
|
poke(0x5f00,zc|0x01)
|
|
end
|
|
end
|
|
|
|
if self.orientx==-1 then
|
|
setpal()
|
|
spr(16,px+6,py-2,1,1)
|
|
spr(17,px+1,py,1,1)
|
|
if (self.rope and invis_level<=0.25) pal() self.rope:draw(-2,-1) setpal()
|
|
spr(head,px-3,py-3,1,1)
|
|
else
|
|
setpal()
|
|
spr(16,px-6,py-2,1,1,true)
|
|
spr(17,px-1,py,1,1,true)
|
|
if (self.rope and invis_level<=0.25) pal() self.rope:draw(2,-1) setpal()
|
|
spr(head,px+3,py-3,1,1,true)
|
|
end
|
|
pal()
|
|
|
|
end
|
|
-->8
|
|
-- rope physics
|
|
rope={}
|
|
rope.__index=rope
|
|
|
|
function rope:new(
|
|
x,y,src_x,src_y,dx,dy
|
|
)
|
|
local r={
|
|
id=0,
|
|
src={x=src_x,y=src_y,todo={}},
|
|
ancs={},
|
|
dst={x=x,y=y,todo={}},
|
|
state={name="cast",dx=dx,dy=dy},
|
|
dirty=true,
|
|
latch=nil,
|
|
latch_frame=0,
|
|
}
|
|
setmetatable(r,rope)
|
|
return r
|
|
end
|
|
|
|
function rope:latched()
|
|
return self.state.name=="latched"
|
|
end
|
|
|
|
function rope:done()
|
|
return self.state.name=="done"
|
|
end
|
|
|
|
function rope:busy()
|
|
for i=0,#self.ancs+1 do
|
|
if (#(self:_anc(i).todo)>0) return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function rope:update()
|
|
local was_busy=self:busy()
|
|
for i=0,#self.ancs+1 do
|
|
local anc=self:_anc(i)
|
|
_apply(anc,anc.todo,i)
|
|
end
|
|
local is_busy=self:busy()
|
|
if (was_busy and not is_busy) self.dirty=true
|
|
|
|
if self.state.name=="cast" then
|
|
self:continue_cast()
|
|
elseif self.state.name=="latched" then
|
|
self.latch_frame+=1
|
|
if self.latch_frame>=10 then
|
|
self.latch_frame=10
|
|
end
|
|
|
|
if (self.latch==nil) self:destroy() return
|
|
|
|
if
|
|
self.latch!=nil and
|
|
self.latch.rec!=nil
|
|
then
|
|
self:drag_src(
|
|
self.latch.rec.px+self.latch.px_offset,
|
|
self.latch.rec.py+self.latch.py_offset
|
|
)
|
|
|
|
if #self.latch.rec.todo==0 then
|
|
if self.latch.rec.dead==true then
|
|
self:destroy()
|
|
end
|
|
end
|
|
end
|
|
|
|
if (not is_busy) self:_tidy_up_gen()
|
|
elseif self.state.name=="destroy" then -- destroy
|
|
self.state.frame+=1
|
|
if (self.state.frame>=5) self.state={name="done"}
|
|
else
|
|
-- done state
|
|
end
|
|
end
|
|
|
|
function rope:destroy()
|
|
if (self.state.name=="destroy" or self.state.name=="done") return
|
|
self.state={name="destroy",frame=0}
|
|
end
|
|
|
|
function rope:continue_cast()
|
|
local dx,dy=self.state.dx,self.state.dy
|
|
local x0=self.src.x
|
|
local y0=self.src.y
|
|
local x1=x0+dx
|
|
local y1=y0+dy
|
|
|
|
for x,y in self:_rast(
|
|
x0,y0,x1,y1
|
|
) do
|
|
local latch=
|
|
level:get_latch(dx,dy,x,y)
|
|
|
|
if latch!=nil or level:pcoll(x,y) then
|
|
self.latch=latch
|
|
self.state={name="latched"}
|
|
break
|
|
end
|
|
self.src={x=x,y=y,todo={},dirty=true}
|
|
end
|
|
end
|
|
|
|
function rope:_reindex()
|
|
self.src.ix=0
|
|
self.dst.ix=#self.ancs
|
|
for i,anc in ipairs(self.ancs) do
|
|
anc.ix=i
|
|
end
|
|
end
|
|
|
|
function rope:draw(artificial_dx,artificial_dy)
|
|
local points,highlight=self:_tug(true)
|
|
if (self:busy() or self._prevent_highlight) highlight=nil
|
|
if (self.state.name=="done") return
|
|
local perc_to_show=1.0
|
|
if (self.state.name=="destroy") perc_to_show=(1.0-self.state.frame/5)^2
|
|
|
|
points[#points]={x=points[#points].x+artificial_dx,y=points[#points].y+artificial_dy}
|
|
|
|
local len=0
|
|
for i=1,#points-1 do
|
|
len+=distance(points[i],points[i+1])
|
|
end
|
|
local len_to_show=perc_to_show*len
|
|
|
|
local len_cumulative=0
|
|
for i=#points-1,1,-1 do
|
|
local src=points[i]
|
|
local dst=points[i+1]
|
|
|
|
local x,y=dst.x,dst.y
|
|
local dx,dy=src.x-x,src.y-y
|
|
|
|
local len_here=len_to_show-len_cumulative
|
|
local dist_base=distance_dxy(dx,dy)
|
|
len_cumulative+=dist_base
|
|
|
|
if len_here>0 and dist_base>0 then
|
|
local coef=min(len_here/dist_base,1.0)
|
|
dx,dy=dx*coef,dy*coef
|
|
|
|
local color=8
|
|
if (highlight==i) color=12
|
|
|
|
linefill(x,y,x+0.25*dx,y+0.25*dy,1.0,color)
|
|
linefill(x+0.25*dx,y+0.25*dy,x+1*dx,y+1*dy,0.5,color)
|
|
linefill(x+0.9*dx,y+0.9*dy,x+dx,y+dy,1.0,color)
|
|
circfill(x+dx+0.5,y+dy+0.5,1.0,color)
|
|
end
|
|
end
|
|
|
|
-- draw latch
|
|
if self.latch!=nil and perc_to_show>=1.0 then
|
|
local x,y=points[1].x,points[1].y
|
|
local ldx,ldy=self.latch.dx,self.latch.dy
|
|
local color=8
|
|
if (highlight==0) color=12
|
|
if self.latch.dx==-1 and self.latch.dy==0 then
|
|
rectfill(x+1,y,x+3,y+1,color)
|
|
elseif self.latch.dx==1 and self.latch.dy==0 then
|
|
rectfill(x-1,y,x-3,y+1,color)
|
|
elseif self.latch.dx==0 and self.latch.dy==-1 then
|
|
rectfill(x,y+1,x-1,y+3,color)
|
|
elseif self.latch.dx==0 and self.latch.dy==1 then
|
|
rectfill(x,y-1,x-1,y-3,color)
|
|
end
|
|
end
|
|
|
|
--[[
|
|
for i=0,#self.ancs+1 do
|
|
p=self:_anc(i)
|
|
local c=12
|
|
if (p.dirty) c=13
|
|
rectfill(p.x-1,p.y-1,p.x+1,p.y+1,c)
|
|
print(tostr(p.id)..":"..p.x..","..p.y..","..#p.todo,0,-8+i*8,9)
|
|
end
|
|
for _,p in pairs(level._anch) do
|
|
pset(p.x,p.y,11)
|
|
end
|
|
print("dirty:"..tostr(self.dirty),32,0,9)
|
|
print("busy:"..tostr(self:busy()),32,7,9)
|
|
print("state:"..tostr(self.state.name),32,14,9)
|
|
if self.all_ops!=nil then
|
|
for i,o in ipairs(self.all_ops) do
|
|
rect(o.mx*8,o.my*8,o.mx*8+7,o.my*8+7,4)
|
|
--print(o.mx..","..o.my,0,i*8,3)
|
|
end
|
|
end
|
|
]]--
|
|
end
|
|
|
|
function rope:_anc(i)
|
|
if (i==0) return self.src
|
|
if (i==#self.ancs+1) return self.dst
|
|
return self.ancs[i]
|
|
end
|
|
|
|
function rope:drag_dst(x,y)
|
|
self:drag(function() return #self.ancs+1 end,x,y)
|
|
end
|
|
|
|
function rope:drag_src(x,y)
|
|
self:drag(function() return 0 end,x,y)
|
|
end
|
|
|
|
function rope:drag(
|
|
i,x,y
|
|
)
|
|
local anc=self:_anc(i())
|
|
local busy=self:busy()
|
|
|
|
for x,y in self:_rast(
|
|
anc.x,anc.y,x,y
|
|
) do
|
|
local a=self:_anc(i())
|
|
if not (_point_eq(a,{x=x,y=y})) then
|
|
a.x=x
|
|
a.y=y
|
|
a.dirty=true
|
|
self.dirty=true
|
|
if (not busy) self:_tidy_up_gen()
|
|
end
|
|
end
|
|
end
|
|
|
|
function rope:make_dirty()
|
|
for a=0,#self.ancs+1 do
|
|
self:_anc(a).dirty=true
|
|
end
|
|
self.dirty=true
|
|
end
|
|
|
|
function rope:_tidy_up_gen()
|
|
local invalid=false
|
|
for i=0,#self.ancs do
|
|
local a0=self:_anc(i)
|
|
local a1=self:_anc(i+1)
|
|
if not self:_can_stretch(a0,a1) then
|
|
invalid=true
|
|
break
|
|
end
|
|
end
|
|
if (invalid) self:make_dirty()
|
|
|
|
local busy=self:busy()
|
|
if (not self:latched()) return
|
|
if (not self.dirty) return
|
|
|
|
local settled=true
|
|
local loop=function(f)
|
|
local a=0
|
|
while a<=#self.ancs+1 do
|
|
local anc=self:_anc(a)
|
|
if anc.dirty then
|
|
anc.seen=true
|
|
if self[f](self,a,busy) then
|
|
settled=false anc.changed=true
|
|
end
|
|
end
|
|
a+=1
|
|
end
|
|
end
|
|
|
|
local mark_unseen=function()
|
|
touched={}
|
|
for a=0,#self.ancs+1,1 do
|
|
local anc=self:_anc(a)
|
|
anc.seen=false
|
|
anc.changed=false
|
|
end
|
|
end
|
|
|
|
local propagate_dirty=function(f)
|
|
for a=0,#self.ancs+1,1 do
|
|
local a1=self:_anc(a)
|
|
if a1.dirty then
|
|
local a0=self:_anc(a-1)
|
|
if (a0!=nil) a0.dirty=true
|
|
|
|
local a2=self:_anc(a+1)
|
|
if (a2!=nil) a2.dirty=true
|
|
end
|
|
end
|
|
end
|
|
|
|
while true do
|
|
settled=true
|
|
|
|
mark_unseen()
|
|
propagate_dirty()
|
|
|
|
loop("_find_needed_anchors")
|
|
loop("_find_touched_anchors")
|
|
loop("_elide_point")
|
|
|
|
for a=0,#self.ancs+1,1 do
|
|
local anc=self:_anc(a)
|
|
if (anc.seen) anc.dirty=anc.changed
|
|
if (anc.dirty) settled=false
|
|
end
|
|
|
|
if (settled) break
|
|
end
|
|
|
|
if (self:busy()) return
|
|
|
|
for i=0,#self.ancs do
|
|
local a0=self:_anc(i)
|
|
local a1=self:_anc(i+1)
|
|
if not self:_can_stretch(a0,a1) then
|
|
self:destroy()
|
|
end
|
|
end
|
|
|
|
self.dirty=false
|
|
end
|
|
|
|
function rope:_find_needed_anchors(i)
|
|
if (i<=0) return false
|
|
if (#self.ancs+1<i) return false
|
|
|
|
local a0=self:_anc(i-1)
|
|
local a2=self:_anc(i)
|
|
|
|
if (level:pcoll(a2.x,a2.y)) return false
|
|
if (level:pcoll(a0.x,a0.y)) return false
|
|
if (self:_can_stretch(a0,a2)) return false
|
|
|
|
local anchors_bydist={}
|
|
local x0,x2=_mnmx(a0.x,a2.x)
|
|
local y0,y2=_mnmx(a0.y,a2.y)
|
|
for a1 in level:anchors_in(x0-1,y0-1,x2+1,y2+1) do
|
|
add(anchors_bydist,{el=a1,key=_linedist(a0,a1,a2)})
|
|
end
|
|
shellsort(anchors_bydist)
|
|
|
|
for a1 in all(anchors_bydist) do
|
|
a1=a1.el
|
|
if self:_can_stretch(a0,a1) and
|
|
self:_can_stretch(a1,a2)
|
|
then
|
|
local id=self.id
|
|
add(self.ancs,{id=id,x=a1.x,y=a1.y,dirty=true,todo={}},i)
|
|
self.id+=1
|
|
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
function rope:_find_touched_anchors(i)
|
|
if (i<=0) return false
|
|
if (#self.ancs<i) return false
|
|
|
|
local a0=self:_anc(i-1)
|
|
local a2=self:_anc(i)
|
|
|
|
if (level:pcoll(a0.x,a0.y)) return false
|
|
if (level:pcoll(a2.x,a2.y)) return false
|
|
|
|
for bx,by in self:_rast(a0.x,a0.y,a2.x,a2.y) do
|
|
local a1=level:point_anchor(bx,by)
|
|
if
|
|
a1!=nil and not _point_eq(a0,a1) and not _point_eq(a1,a2)
|
|
and _linedist(a0,a1,a2) == 0.0
|
|
-- and self:_can_stretch(p,a2)
|
|
then
|
|
local id=self.id
|
|
add(self.ancs,{id=id,x=a1.x,y=a1.y,dirty=true,todo={}},i)
|
|
self.id+=1
|
|
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function rope:_elide_point(i,busy)
|
|
if (i<=0) return false
|
|
if (#self.ancs<i) return false
|
|
|
|
local a0=self:_anc(i-1)
|
|
local a1=self:_anc(i)
|
|
local a2=self:_anc(i+1)
|
|
|
|
local level_anc=level:point_anchor(a1.x,a1.y)
|
|
if _point_eq(a0,a1) or _point_eq(a1,a2) or (not busy and level_anc==nil) then
|
|
-- do it unconditionally
|
|
else
|
|
if _linedist(a0,a1,a2) < 0.01 then
|
|
return false
|
|
end
|
|
|
|
if not self:_can_stretch(a0,a2) then
|
|
return false
|
|
end
|
|
|
|
local midpoint={
|
|
x=(a0.x+a2.x)\2,
|
|
y=(a0.y+a2.y)\2
|
|
}
|
|
|
|
if not self:_can_move_midpoint(a0,a1,midpoint,a2) then
|
|
return false
|
|
end
|
|
end
|
|
|
|
deli(self.ancs,i)
|
|
a0.dirty=true a0.changed=true
|
|
a2.dirty=true a2.changed=true
|
|
return true
|
|
end
|
|
|
|
function rope:_can_move_midpoint(a0,a1_0,a1_1,a2)
|
|
if (level:pcoll(a0.x,a0.y)) return false
|
|
if (level:pcoll(a2.x,a2.y)) return false
|
|
if (level:pcoll(a1_0.x,a1_0.y)) return false
|
|
if (level:pcoll(a1_1.x,a1_1.y)) return false
|
|
|
|
if not self:_can_stretch(a1_0, a1_1) then
|
|
return false
|
|
end
|
|
if not self:_can_stretch(a0,a1_1) then
|
|
return false
|
|
end
|
|
if not self:_can_stretch(a1_1,a2) then
|
|
return false
|
|
end
|
|
for x,y in self:_rastn(a1_0.x,a1_0.y,a1_1.x,a1_1.y,8,8) do
|
|
local tm={x=x,y=y}
|
|
if not self:_can_stretch(a0,tm) then
|
|
return false
|
|
end
|
|
if not self:_can_stretch(tm,a2) then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function _linedist(x0,v,x1)
|
|
return 100 * (sum_distance(x0,v,x1)-distance(x0,x1))/distance(x0,x1)
|
|
end
|
|
|
|
function _vec_ang_diff(x0,y0,x1,y1)
|
|
local ang0=atan2(x0,y0)
|
|
local ang1=atan2(x1,y1)
|
|
return _ang_diff(ang0,ang1)
|
|
end
|
|
|
|
function _ang_diff(ang0,ang1)
|
|
return abs((ang1-ang0+0.5)%1-0.5)
|
|
end
|
|
|
|
function sum_distance(x,y,z)
|
|
return distance(x,y) + distance(y,z)
|
|
end
|
|
|
|
function distance_dxy(dx,dy)
|
|
return sqrt(dx*dx+dy*dy)
|
|
end
|
|
|
|
function distance(p1,p2)
|
|
local dx=p2.x-p1.x
|
|
local dy=p2.y-p1.y
|
|
return sqrt(dx*dx+dy*dy)
|
|
end
|
|
|
|
function rope:collide_rect(x1,y1,x2,y2,exclude_src,exclude_dst)
|
|
local last=#self.ancs-exclude_dst
|
|
for i=exclude_src,last,1 do
|
|
local a0=self:_anc(i)
|
|
local a1=self:_anc(i+1)
|
|
if (_line_line(a0.x,a0.y,a1.x,a1.y,x1,y1,x2,y1)) return true
|
|
if (_line_line(a0.x,a0.y,a1.x,a1.y,x1,y1,x1,y2)) return true
|
|
if (_line_line(a0.x,a0.y,a1.x,a1.y,x1,y2,x2,y2)) return true
|
|
if (_line_line(a0.x,a0.y,a1.x,a1.y,x2,y1,x2,y2)) return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function _line_line(x1,y1,x2,y2,x3,y3,x4,y4)
|
|
local denom=((y4-y3)*(x2-x1)-(x4-x3)*(y2-y1))
|
|
|
|
local ua=
|
|
((x4-x3)*(y1-y3)-(y4-y3)*(x1-x3))/denom
|
|
if (ua<0 or ua>1) return false
|
|
|
|
local ub=
|
|
((x2-x1)*(y1-y3)-(y2-y1)*(x1-x3))/denom
|
|
if (ub<0 or ub>1) return false
|
|
|
|
return true
|
|
end
|
|
|
|
function rope:_can_stretch(
|
|
p1,p2
|
|
)
|
|
-- faster implementation for straight lines
|
|
if p1.y\8==p2.y\8 then
|
|
local my=p2.y\8
|
|
for mx=p1.x\8,p2.x\8 do
|
|
if (level:mcoll(mx,my)) return false
|
|
end
|
|
end
|
|
|
|
if p1.x\8==p2.x\8 then
|
|
local mx=p2.x\8
|
|
for my=p1.y\8,p2.y\8 do
|
|
if (level:mcoll(mx,my)) return false
|
|
end
|
|
end
|
|
|
|
if (level:pcoll(p1.x,p1.y)) return false
|
|
if (level:pcoll(p2.x,p2.y)) return false
|
|
|
|
local res=true
|
|
for x,y in self:_rastn(p1.x,p1.y,p2.x,p2.y,8,8) do
|
|
if level:pcoll(x,y) then
|
|
res=false
|
|
break
|
|
end
|
|
end
|
|
|
|
return res
|
|
end
|
|
|
|
function rope:_rastn(
|
|
x0,y0,x1,y1,dx,dy
|
|
)
|
|
-- todo: more optimized implementation?
|
|
local iter=self:_rast(x0,y0,x1,y1)
|
|
local prevx,prevy=nil,nil
|
|
|
|
local done=false
|
|
return function()
|
|
while not done do
|
|
local x,y=iter()
|
|
|
|
if (x==nil) done=true return x1, y1
|
|
|
|
local x8 = x\dx
|
|
local y8 = y\dy
|
|
if not (x8==prevx and y8==prevy) then
|
|
prevx,prevy=x8,y8
|
|
return x,y
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function rope:_rast(
|
|
x0,y0,x1,y1
|
|
)
|
|
local dx=abs(x1-x0)
|
|
local dy=abs(y1-y0)
|
|
local x=x0
|
|
local y=y0
|
|
|
|
local sx=-1
|
|
local sy=-1
|
|
if (x0<x1) sx=1
|
|
if (y0<y1) sy=1
|
|
|
|
local done=false,err
|
|
if dx>dy then
|
|
err=dx/2.0
|
|
return function()
|
|
if (done) return
|
|
if (x==x1) done=true return x1,y1
|
|
local oldx,oldy=x,y
|
|
err-=dy
|
|
if (err<0) y+=sy err+=dx
|
|
x+=sx
|
|
return oldx,oldy
|
|
end
|
|
else
|
|
err=dy/2.0
|
|
return function()
|
|
if (done) return
|
|
if (y==y1) done=true return x1,y1
|
|
local oldx,oldy=x,y
|
|
err-=dx
|
|
if (err<0) x+=sx err+=dy
|
|
y+=sy
|
|
return oldx,oldy
|
|
end
|
|
end
|
|
end
|
|
|
|
function _point_eq(p1,p2)
|
|
return p1.x==p2.x and p1.y==p2.y
|
|
end
|
|
|
|
function neighbors(p)
|
|
local r={}
|
|
for dx=-1,1,1 do
|
|
for dy=-1,1,1 do
|
|
if dx!=0 or dy!=0 then
|
|
add(r,{x=p.x+dx,y=p.y+dy})
|
|
end
|
|
end
|
|
end
|
|
return r
|
|
end
|
|
|
|
-->8
|
|
-- moved here because it's complicated
|
|
|
|
function rope:tug_orientxy()
|
|
local a1=self:_anc(#self.ancs+1)
|
|
local a0=self:_anc(#self.ancs)
|
|
local dx=a0.x-a1.x
|
|
local tdx=0
|
|
if (dx>3) tdx=1
|
|
if (dx<-3) tdx=-1
|
|
|
|
local dy=a0.y-a1.y
|
|
local tdy=0
|
|
if abs(dy)>abs(dx)/2 then
|
|
if (dy>3) tdy=1
|
|
if (dy<-3) tdy=-1
|
|
end
|
|
return tdx,tdy
|
|
end
|
|
|
|
function rope:tug()
|
|
self:_tidy_up_gen()
|
|
if (not self:latched()) return
|
|
self:_tug()
|
|
self:_tidy_up_gen()
|
|
end
|
|
|
|
function rope:prevent_highlight(prevent)
|
|
if prevent then
|
|
local points,highlight=self:_tug(true)
|
|
if (self:busy() or highlight==nil) self._prevent_highlight=true
|
|
else
|
|
self._prevent_highlight=false
|
|
end
|
|
end
|
|
|
|
function rope:_tug(hypothetically)
|
|
local ancs=self:_anchors_simplified()
|
|
local touched={}
|
|
|
|
for i=#ancs-1,2,-1 do
|
|
local ops_before_trash,hit_end1=self:_calc_push(ancs[i+1],ancs[i],ancs[i-1],ancs[i-2])
|
|
local ops_to_do,corners={},{}
|
|
if #ops_before_trash>0 then
|
|
ops_to_do=ops_before_trash
|
|
corners[i-1]=true
|
|
corners[i]=hit_end1
|
|
else
|
|
local ops_after_trash,hit_end2=self:_calc_push(ancs[i-2],ancs[i-1],ancs[i],ancs[i+1])
|
|
ops_to_do=ops_after_trash
|
|
corners[i-1]=true
|
|
corners[i]=hit_end1
|
|
end
|
|
|
|
local ops=ops_to_do
|
|
|
|
if #ops>0 then
|
|
if (hypothetically) return ancs,i-1
|
|
|
|
local dmx,dmy=ops[1].dmx,ops[1].dmy
|
|
for o in all(ops) do
|
|
level:tug_crate(
|
|
o.mx,o.my,dmx,dmy
|
|
)
|
|
end
|
|
for node=ancs[i-1].ix,ancs[i].ix do
|
|
local anc=self:_anc(node)
|
|
local x0,y0=anc.x,anc.y
|
|
|
|
local upd=function(x,y,force)
|
|
return {update=function(s,i)
|
|
if force or not level:pcoll(x,y) then
|
|
s.x=x
|
|
s.y=y
|
|
end
|
|
s.dirty=true
|
|
self.dirty=true
|
|
return true
|
|
end}
|
|
end
|
|
local dmxh,dmyh=dmx,dmy
|
|
if (not corners[node]) dmxh,dmyh=0,0
|
|
anc.todo={
|
|
{},
|
|
upd(x0+dmxh*2,y0+dmyh*2),
|
|
upd(x0+dmxh*7,y0+dmyh*7),
|
|
upd(x0+dmxh*8,y0+dmyh*8),
|
|
}
|
|
end
|
|
for node=ancs[i-1].ix-1,ancs[i].ix+1 do
|
|
local anc=self:_anc(node)
|
|
end
|
|
return
|
|
end
|
|
end
|
|
|
|
local latch=self.latch
|
|
if (latch==nil) return ancs,nil
|
|
|
|
if latch.el=="crate" then
|
|
local dmx,dmy=
|
|
sgn0(latch.dx),
|
|
sgn0(latch.dy)
|
|
local obj_anc=ancs[1]
|
|
local pull_anc=ancs[2]
|
|
|
|
local pull_dx=pull_anc.x-obj_anc.x
|
|
local pull_dy=pull_anc.y-obj_anc.y
|
|
|
|
local mx0=latch.rec.mx
|
|
local my0=latch.rec.my
|
|
|
|
local mxa=(pull_anc.x+dmx)\8
|
|
local mya=(pull_anc.y+dmy)\8
|
|
|
|
local invalid_move=false
|
|
if
|
|
(dmx!=0 and sgn0(pull_dx)!=dmx) or
|
|
(dmy!=0 and sgn0(pull_dy)!=dmy) or
|
|
|
|
_vec_ang_diff(pull_anc.x\8-mx0,pull_anc.y\8-my0,dmx,dmy) >= 0.135 or
|
|
|
|
sgn0(mx0-mxa)!=
|
|
sgn0(mx0+dmx-mxa) or
|
|
|
|
sgn0(my0-mya)!=
|
|
sgn0(my0+dmy-mya)
|
|
then
|
|
invalid_move=true
|
|
end
|
|
|
|
if not invalid_move and
|
|
level:can_move(false,mx0,my0,dmx,dmy,1,0)
|
|
then
|
|
if (hypothetically) return ancs,0
|
|
|
|
level:tug_crate(
|
|
mx0,my0,
|
|
dmx,dmy
|
|
)
|
|
-- be busy for 4 ticks while the crate moves
|
|
self:_anc(0).todo={{},{},{},{},{}}
|
|
end
|
|
end
|
|
|
|
return ancs,nil
|
|
end
|
|
|
|
function rope:_calc_push(
|
|
an,a0,a1,af
|
|
)
|
|
local ops={}
|
|
if (an==nil) return ops
|
|
local pull_ang=atan2(
|
|
a0.x\8-an.x\8,
|
|
a0.y\8-an.y\8
|
|
)
|
|
local needs_good_pull=af==nil
|
|
|
|
if a0.x==a1.x then
|
|
-- no far side applying pressure?
|
|
local y0,y1=_mnmx(a0.y,a1.y)
|
|
local my0,my1,smy=(y0+1)\8,(y1-1)\8,1
|
|
if a0.y>a1.y then
|
|
my0,my1=my1,my0
|
|
smy=-smy
|
|
end
|
|
|
|
local mx,dmx
|
|
if a0.x%8==0 and a0.x>an.x+7 then
|
|
needs_good_pull=needs_good_pull or af.x>=a1.x
|
|
if (needs_good_pull and _ang_diff(pull_ang,0.0)>=0.165) return {}
|
|
|
|
-- push left
|
|
mx=(a0.x-1)\8
|
|
dmx=-1
|
|
elseif a0.x%8==7 and a0.x<an.x-7 then
|
|
needs_good_pull=needs_good_pull or af.x<=a1.x
|
|
if (needs_good_pull and _ang_diff(pull_ang,0.5)>=0.165) return {}
|
|
|
|
-- push right
|
|
mx=(a0.x+1)\8
|
|
dmx=1
|
|
else
|
|
return {}
|
|
end
|
|
|
|
for my=my0,my1,smy do
|
|
add(ops,{mx=mx,my=my,dmx=dmx,dmy=0})
|
|
end
|
|
end
|
|
|
|
if a0.y==a1.y then
|
|
local x0,x1=_mnmx(a0.x,a1.x)
|
|
local mx0,mx1,smx=(x0+1)\8,(x1-1)\8,1
|
|
if a0.x>a1.x then
|
|
mx0,mx1=mx1,mx0
|
|
smx=-smx
|
|
end
|
|
|
|
local my,dmy
|
|
if a0.y%8==0 and a0.y>an.y+6 then
|
|
needs_good_pull=needs_good_pull or af.y>=a1.y
|
|
if (needs_good_pull and _ang_diff(pull_ang,0.75)>=0.135) return {}
|
|
|
|
-- push up
|
|
my=(a0.y-1)\8
|
|
dmy=-1
|
|
|
|
elseif a0.y%8==7 and a0.y<an.y-6 then
|
|
needs_good_pull=needs_good_pull or af.y<=a1.y
|
|
if (needs_good_pull and _ang_diff(pull_ang,0.25)>=0.135) return {}
|
|
|
|
-- push down
|
|
my=(a0.y+1)\8
|
|
dmy=1
|
|
else
|
|
return {}
|
|
end
|
|
|
|
for mx=mx0,mx1,smx do
|
|
add(ops,{mx=mx,my=my,dmx=0,dmy=dmy})
|
|
end
|
|
end
|
|
|
|
local hit_end=true
|
|
local ops2={}
|
|
for o in all(ops) do
|
|
if not level:mcoll(o.mx,o.my) then
|
|
-- great!
|
|
else
|
|
local crate=level:get_crate(o.mx,o.my)
|
|
if crate==nil then
|
|
hit_end=false
|
|
break
|
|
else
|
|
if not level:can_move(false,o.mx,o.my,o.dmx,o.dmy,0,0) then
|
|
hit_end=false
|
|
break
|
|
end
|
|
end
|
|
add(ops2,o)
|
|
end
|
|
end
|
|
return ops2,hit_end
|
|
end
|
|
|
|
function rope:_anchors_simplified()
|
|
-- todo: cache this
|
|
self:_reindex()
|
|
|
|
local points={}
|
|
local _slope = function(p0,p1)
|
|
return atan2(p1.y-p0.y,p1.x-p0.x)
|
|
end
|
|
for i=0,#self.ancs+1,1 do
|
|
local anc=self:_anc(i)
|
|
if #points<=1 then
|
|
add(points,anc)
|
|
elseif abs(
|
|
_slope(points[#points-1],points[#points])-
|
|
_slope(points[#points],anc)
|
|
)==0 then -- epsilon?
|
|
points[#points]=anc
|
|
else
|
|
add(points,anc)
|
|
end
|
|
end
|
|
|
|
return points
|
|
end
|
|
|
|
|
|
__gfx__
|
|
000030000000002200003000000cc0cc0cccccccccccccccccccccccccccccccc0bb0000000000000000000000000000dddddddd000000000005000000000000
|
|
003333300000332200333330000cc0cc0000cc0000000000000000000cc0000000bb0bb0bbbb0bbbbb0bbbbb0bbb0000dddddddd000000000000500000000000
|
|
099333990039932009333339000cc0cc0cc0cc0cc0cccccccc0ccccc0cc0ccccc0bb0bb000bb0000bb0bb0bb0bb0b000dddddddd000000000000000000000000
|
|
09a333a9033a932009333339000cc0cc0cc0cc0cc0cc0cc0cc0000cc0cc0cc0cc0bb0bb0bb000bbbbb0bbb000bb0b000dddddddd000000005005005000000000
|
|
023333323333320000222220000cc0cc0cc0cc0cc0cc0cc0cc0ccccc0cc0ccccc0bb0bb0bbbb0bbbbb0bb0bb0bbbb000dddddddd000000000500500500000000
|
|
002222200000220000222220000cc0cc0cc0000cc0cc0cc0cc0cc0cc0cc0cc0000bb0000000000000000000000000000dddddddd000000000000000000000000
|
|
000222c002222c0000022200000ccccc0ccccc0cc0cc0cc0cc0ccccc0cc0ccccc0bbbbbbbbbbbbbbbbbbbbbbbbbbb000dddddddd000000000005000000000000
|
|
00000cc00000cc0000000cc0000000000000000000000000000000000000000000000000000000000000000000000000dddddddd000000000000500000000000
|
|
0000ff00000000000000000088888888888888888888880aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa11111111000000000000000000000000
|
|
000f00f0000000000aa00aa00088000000088000000000000000000000000aa00000000000000000aa0000000000000011111111000000000000000000000000
|
|
00d0000f000000000aaaaaa000880888880880888880880aaa00aaa0aaaa0aa0aaaaa0aa0a0aaaa0aa0aa0aaaaa0aaa011111111000000000000000000000000
|
|
00d0d00f00c040500aaaaaa000880880880880000880880aa0a0aa00aa000aa0aa0aa0aa0a0aa000aa0aa0aa0aa0aa0a11111111000000000000000000000000
|
|
00dd00ee00c445500099990000880880880880888880880aa0a0aa0000aa0aa0aaa000aa0a0aa000aa0aa0aa0aa0aa0a11111111000000000000000000000000
|
|
00000ee00c44455500aaaa0000880880880880880880880aaaa0aaa0aaaa0aa0aa0aa0aaaa0aaaa0aa0aa0aaaaa0aa0a11111111000000000000000000000000
|
|
00eeee000c004005000aa00000880888880880888880880000000000000000000000000000000000000000000000000011111111000000000000000000000000
|
|
eeee0000cc0440550044440000000000000000000000888888800000000000000000000000000000000000000000000011111111000000000000000000000000
|
|
00000000000a90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
00000aaaaaaa91000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
0000aaaaaa1a91100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
0aaaaaaaaa1a91110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
0aaaaaaaa41a91a10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
0a000aa4441a91a10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
00a0044449a110a10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
000aa111991111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
000000009910000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddd00ddddddddddddddddddddddddddd
|
|
000000009900000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddd00ddddddddddddddddddddddddddd
|
|
000000009900000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddd77ddddddddddddddddddddddddddd
|
|
000000000900000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddd00dddddd00700ddd00ddd00700ddd
|
|
00000000aa00000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddd00dddddd00700ddd00ddd00700ddd
|
|
0000000077a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddddddddddddddddddd77ddddddddddd
|
|
00000007777a000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddddddddddddddddddd00ddddddddddd
|
|
000444444444440000000000000000000000000000000000000000000000000000000000000000000000000000000000ddddddddddddddddddd00ddddddddddd
|
|
77077077777007777707707777700777770770777770077777077077777007777707707777700777770770777770077777077077777007777707707777700777
|
|
77777777777007777777777777700777777777777770077777777777777007777777777777700777777777777770077777777777777007777777777777700777
|
|
07777770077777700777777707777777077777700777777007777777077777777777777077777770777777777777777777777770777777707777777777777777
|
|
77700777777007777770070077700700777007777770077777700700777007000070077700700777007007000070070000700777007007770070070000700700
|
|
77700777777007777770070077700700777007777770077777700700777007000070077700700777007007000070070000700777007007770070070000700700
|
|
07777770077777700777777707777777077777700777777007777777077777777777777077777770777777777777777777777770777777707777777777777777
|
|
77777777777777777777777777777777777007777770077777700777777007777777777777777777777777777777777777700777777007777770077777700777
|
|
77077077770770777707707777077077777007777770077777700777777007777707707777077077770770777707707777700777777007777770077777700777
|
|
__label__
|
|
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
|
|
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
|
|
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
|
|
77766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777
|
|
77766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777
|
|
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
|
|
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
|
|
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77766777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077766777
|
|
77766777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077766777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000777777777777777700000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000777777777777777700000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000777777777777777700000000000000000000000000000000000000000000000077777777
|
|
77766777000000000000000000000000000000000000000000000000777667777776677700000000000000000000000000000000000000000000000077766777
|
|
77766777000000000000000000000000000000000000000000000000777667777776677700000000000000000000000000000000000000000000000077766777
|
|
77777777000000000000000000000000000000000000000000000000777777777777777700000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000777777777777777700000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000777777777777777700000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000077777777000000000000000000000000000000000000000000000000000000000000000077777777000000000000000077777777
|
|
77777777000000000000000077777777000000000000000000000000000000000000000000000000000000000000000077777777000000000000000077777777
|
|
77777777000000000000000077777777000000000000000000000000000000000000000000000000000000000000000077777777000000000000000077777777
|
|
77766777000000000000000077766777000000000000000000000000000000000000000000000000000000000000000077766777000000000000000077766777
|
|
77766777000000000000000077766777000000000000000000000000000000000000000000000000000000000000000077766777000000000000000077766777
|
|
77777777000000000000000077777777000000000000000000000000000000000000000000000000000000000000000077777777000000000000000077777777
|
|
77777777000000000000000077777777000000000000000000000000000000000000000000000000000000000000000077777777000000000000000077777777
|
|
77777777000000000000000077777777000000000000000000000000000000000000000000000000000000000000000077777777000000000000000077777777
|
|
77777777000000000000000000000000000000000000000077777777000000000000000077777777000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000077777777000000000000000077777777000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000077777777000000000000000077777777000000000000000000000000000000000000000077777777
|
|
77766777000000000000000000000000000000000000000077766777000000000000000077766777000000000000000000000000000000000000000077766777
|
|
77766777000000000000000000000000000000000000000077766777000000000000000077766777000000000000000000000000000000000000000077766777
|
|
77777777000000000000000000000000000000000000000077777777000000000000000077777777000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000077777777000000000000000077777777000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000077777777000000000000000077777777000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77766777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077766777
|
|
77766777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077766777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777000000007777777700000000777777770000000000000000000000000000000000000000000000007777777700000000777777770000000077777777
|
|
77777777000000007777777700000000777777770000000000000000000000000000000000000000000000007777777700000000777777770000000077777777
|
|
77777777000000007777777700000000777777770000000000000000000000000000000000000000000000007777777700000000777777770000000077777777
|
|
77766777000000007776677700000000777667770000000000000000000000000000000000000000000000007776677700000000777667770000000077766777
|
|
77766777000000007776677700000000777667770000000000000000000000000000000000000000000000007776677700000000777667770000000077766777
|
|
77777777000000007777777700000000777777770000000000000000000000000000000000000000000000007777777700000000777777770000000077777777
|
|
77777777000000007777777700000000777777770000000000000008000000000000000080000000000000007777777700000000777777770000000077777777
|
|
77777777000000007777777700000000777777770000000000000088888888888888888888000000000000007777777700000000777777770000000077777777
|
|
77777777000000000000000000000000000000000000000000000088888877777778888888800000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000088877777777777777788880000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000088877777777777777708888000000000000000000000000000000000000000000077777777
|
|
77766777000000000000000000000000000000000000000000000088877667777776677700888800000000000000000000000000000000000000000077766777
|
|
77766777000000000000000000000000000000000000000000000088777667777776677700088880000000000000000000000000000000000000000077766777
|
|
77777777000000000000000000000000000000000000000000000088777777777777777700008888000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000088777777777777777700000888000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000088777777777777777700000008880000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000088777777777777777700000000888000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000088777777777777777700000000088800000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000088777777777777777700000000008880000000000000000000000000000000000077777777
|
|
77766777000000000000000000000000000000000000000000000088777667777776677700000000000888000000000000000000000000000000000077766777
|
|
77766777000000000000000000000000000000000000000000000088877667777776677700000000000088800000000000000000000000000000000077766777
|
|
77777777000000000000000000000000000000000000000000000088877777777777777700000000000008880000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000088877777777777777700000000000000888000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000088877777777777777700000000000000088800000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000088880000000000000000000000000000008880000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000088888800000000000000000000000000000888000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000088888000000000000000000000000000088800000000000000000000000000077777777
|
|
77766777000000000000000000000000000000000000000000000000000088880000000000000000000000000000888000000000000000000000000077766777
|
|
77766777000000000000000000000000000000000000000000000000000000088880000000000000000000000000888800000000000000000000000077766777
|
|
77777777000000000000000000000000000000000000000000000000000000000888880000000000000000000000088880000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000008888880000000000000000000008888000000033000000000000077777777
|
|
777777770000000000000000000000000000000000000000000000000000000000000888880000000000000000000008883330003bb300000000000077777777
|
|
777777770000000077777777000000007777777700000000000000007777777777777778880000000000000077777777833b33003ab337770000000077777777
|
|
77777777000000007777777700000000777777770000000000000000777777777777777888800000000000007777777733333300331137770000000077777777
|
|
77777777000000007777777700000000777777770000000000000000777777777777777788800000000000007777777700883330711337770000000077777777
|
|
77766777000000007776677700000000777667770000000000000000777667777776677788800000000000007776677703333333733367770000000077766777
|
|
77766777000000007776677700000000777667770000000000000000777667777776677708880000000000007776677700333330333667770000000077766777
|
|
77777777000000007777777700000000777777770000000000000000777777777777777700880000000000007777777700033133311777770000000077777777
|
|
77777777000000007777777700000000777777770000000000000000777777777777777700888000000000007777777700003100317777770000000077777777
|
|
77777777000000007777777700000000777777770000000000000000777777777777777700088000000000007777777700033103317777770000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000088800000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000008880000000000000000000000000000000000000000077777777
|
|
77766777000000000000000000000000000000000000000000000000000000000000000000000888000000000000000000000000000000000000000077766777
|
|
77766777000000000000000000000000000000000000000000000000000000000000000000000888000000000000000000000000000000000000000077766777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000888800000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000088800000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000088880000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000077777777000000000000000077777778880000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000077777777000000000000000077777778880000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000077777777000000000000000077777778800000000000000000000000000000000000000077777777
|
|
77766777000000000000000000000000000000000000000077766777000000000000000077766778800000000000000000000000000000000000000077766777
|
|
77766777000000000000000000000000000000000000000077766777000000000000000077766778800000000000000000000000000000000000000077766777
|
|
77777777000000000000000000000000000000000000000077777777000000000000000077777778800000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000077777777000000000000000077777778880000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000077777777000000000000000077777778880000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000777777777777777700000088880000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000777777777777777700000888800000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000777777777777777700008888000000000000000000000000000000000000000077777777
|
|
77766777000000000000000000000000000000000000000000000000777667777776677700088800000000000000000000000000000000000000000077766777
|
|
77766777000000000000000000000000000000000000000000000000777667777776677700880000000000000000000000000000000000000000000077766777
|
|
77777777000000000000000000000000000000000000000000000000777777777777777708800000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000777777777777777788000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000777777777777778880000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000888800000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000008888000000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000008880000000000000000000000000000000000000000000000000077777777
|
|
77766777000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000077766777
|
|
77766777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077766777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
|
|
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
|
|
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
|
|
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
|
|
77766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777
|
|
77766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777
|
|
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
|
|
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
|
|
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
|
|
|
|
__gff__
|
|
000000000808080808080808c00000000000000008080808080808080000000040400000080808080808080800000000404000000808080808080808c0c0c0c000000000080808080808080800000000000000000808080808080808000000000000000008080808080808080000000000000000080808080808080800000000
|
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
__map__
|
|
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e
|
|
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
0c000000000044000c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
0c0000000000000000000000000000000c00000000000000000000000000000c000000000000000000000000000000000e00000000000e0e0e0e0000000000000e000000000e000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
0c00000000001c0000000000000000000000000000000000000000000000000c000000000000000000000000000000000e00000000000000000e0000000000000e000000000e000e00000000000000000e0000000000000000000000000000000e0000000000000e0e000000000000000e00000000000e0e0e0e000000000000
|
|
0c0000000000000000000000000000410000000000000000000000000000000c0000000000000e0e0e000000000000000e00000000000000000e0000000000000e000000000e000e00000000000000000e00000000000e0e0e000000000000000e00000000000e0000000000000000000e00000000000000000e000000000000
|
|
0c000000000000000c0c0c0c0c0c0c0c0c00000000000020210000000000000c00000000000e00000e0e0000000000000e0000000000000e0e0e0000000000000e000000000e0e0e0e0e0000000000000e00000000000e0000000000000000000e00000000000e0e0e000000000000000e000000000000000e00000000000000
|
|
0c0c0c0c0c0c00000000000c0c0c0c0c0c00000000000030310000000000000c000000000000000e0e000000000000000e00000000000000000e0000000000000e0000000000000e00000000000000000e00000000000e0e0e000000000000000e00000000000e00000e0000000000000e0000000000000e0000000000000000
|
|
0c00000000000c0c004f000c0c0c0c0c0c00000000000000000000000000000c0000000000000e0e00000000000000000e00000000000e0e0e0e0000000000000e0000000000000e00000000000000000e000000000000000e000000000000000e0000000000000e0e000000000000000e0000000000000e0000000000000000
|
|
0c00000c4f00000c00000000000000120100000000000000000000000000000c00000000000e0e0e0e0e0000000000000e0000000000000000000000000000000e0000000000000e00000000000000000e00000000000e0e0e000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
3d0000000000003f0c000c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
0c0000000000000000000c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
010000000000000c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
0c0c0c0c00000c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
0c0c0c0c00410c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e
|
|
000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
0000000000000e0e00000000000000000e00000000000e0e00000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000e000000000000000000000e000000000000000000000000000000
|
|
00000000000e00000e000000000000000e000000000e00000e000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e00000000000e0000000e0e000000000e000000000e0000000e0000000000000e000000000e00000e0e0e0000000000
|
|
00000000000e00000e000000000000000e000000000e00000e000000000000000e00000000000e000000000e000000000e0000000000000e0000000e000000000e00000000000e00000e0e00000000000e00000000000e00000000000e0000000e000000000e0000000e000e000000000e000000000e00000e00000000000000
|
|
0000000000000e0e00000000000000000e00000000000e0e0e000000000000000e00000000000e0000000e000e0000000e0000000000000e0000000e000000000e00000000000e000000000e000000000e00000000000e0000000e0e000000000e000000000e0000000e0e0e0e0000000e000000000e00000e0e0e0000000000
|
|
00000000000e00000e000000000000000e000000000000000e000000000000000e00000000000e0000000e000e0000000e0000000000000e0000000e000000000e00000000000e0000000e00000000000e00000000000e00000000000e0000000e000000000e00000000000e000000000e000000000e000000000e0000000000
|
|
00000000000e00000e000000000000000e00000000000e0e00000000000000000e00000000000e000000000e000000000e0000000000000e0000000e000000000e00000000000e00000e0e0e000000000e00000000000e0000000e0e000000000e000000000e00000000000e000000000e000000000e000000000e0000000000
|
|
0000000000000e0e00000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e00000000000e0000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000e00000e0e0e0000000000
|
|
000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
|
|
0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e
|
|
__sfx__
|
|
01280000050550c05511055180551d05500000000000000000055070550c0550f055130550f0550c0550705501055080550d055140551905500000000000000000055070550f0551305518055130550f0550c055
|
|
0128000000000000001f0001f055200551f0551d055180551b055000000000000000000000000000000000000000000000000001b0551d0551b05519055140551805500000000000000000000000000000000000
|
|
01280000050550c05511055180551d05518055110550d0550c055130551b055240552b0551b05518055130550a055110551a05522055290550e0550a05505055000550705510055180551f055100550c05507055
|
|
012800000000000000130001f055220552005500000270551f0550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
012800001d4521d452050550c05514055110551f452204522445224452050550c055140551105526452264522745227452080550f055180551405526452244522245222452030550a0551f4521f4521b4521b452
|
|
012800001d4521d4520105508055110550d0551f452204522445224452050550c055140551105526452264522745227452070550e0551f4521f4522645226452244522445200055070550f0520f0550e0550c055
|
|
00280000000000000000000000000505500000050550c055000000000000000050050505500000050550c055000000000000000000000805500000080550f05500000000000000000000030550a0550205509055
|
|
012800000122401222000000000001055000000105508055052220522200000000000505500000050550c05507222072220000000000022220222202222022220022200222000000000000055070550005507055
|
|
012800001d3541f3542035420300203040000027354273501f350000001d3001d3541b354000001f354000001d3541f3542035422354243542635027354293502b3540000024354000002935429350293502b350
|
|
012800000000000000010550805501055080050105508055000550800000000070550005507055000550705500000000000105508055010550805501055080550005500000070550000000055000000705500000
|
|
01280010183541a3541b3540000000000000002235400000213540000026354000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
01281000080050f005080550f05501055000000f055000000e3550000013355000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
__music__
|
|
01 00014344
|
|
00 02034344
|
|
00 04064344
|
|
00 05074344
|
|
00 08094344
|
|
02 0a0b4344
|
|
|