Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb2f011b19 | ||
|
|
70871ee4fd | ||
|
|
2f7647c5ba | ||
|
|
f536173dea | ||
|
|
9488dc61f9 | ||
|
|
6f74595305 | ||
|
|
a1f32ca333 | ||
|
|
45ab91267f | ||
|
|
3472ccc73d | ||
|
|
a9789b1c21 | ||
|
|
20095c01d1 | ||
|
|
653b256253 | ||
|
|
a9a66bf21e | ||
|
|
2fd310baed | ||
|
|
ef94e1bf3a | ||
|
|
fe91265f62 | ||
|
|
b8a9c42a3b | ||
|
|
b0ecb28b48 | ||
|
|
6cb81b461b | ||
|
|
9b44971de8 | ||
|
|
c8908f38fb | ||
|
|
d7c721ae5b | ||
|
|
4d3d00bc58 | ||
|
|
5eaeaaa79f | ||
|
|
d77af59521 | ||
|
|
b5093d19f4 | ||
|
|
ef14e8b38c | ||
|
|
0f3c234ca0 | ||
|
|
563d820fbe | ||
|
|
d15757dcc2 | ||
|
|
9d28505140 | ||
|
|
ce91e75cd2 | ||
|
|
4809d4193e | ||
|
|
9ee310e73f | ||
|
|
1380fa768c | ||
|
|
0ea58e0858 | ||
|
|
d1c1631bae | ||
|
|
ef2b845837 | ||
|
|
e252364c59 | ||
|
|
bc14c6f625 | ||
|
|
bcc1b25023 | ||
|
|
5f609f41a5 | ||
|
|
38589fbebe | ||
|
|
356316aaa3 | ||
|
|
b554409b32 |
@@ -40,7 +40,12 @@ local cmds={
|
||||
local sizeLimit=gc.getSystemLimits().texturesize
|
||||
return function(L)
|
||||
gc.push()
|
||||
local canvas=gc.newCanvas(math.min(L[1],sizeLimit),math.min(L[2],sizeLimit))
|
||||
::REPEAT_tryAgain::
|
||||
local success,canvas=pcall(gc.newCanvas,math.min(L[1],sizeLimit),math.min(L[2],sizeLimit))
|
||||
if not success then
|
||||
sizeLimit=math.floor(sizeLimit*.8)
|
||||
goto REPEAT_tryAgain
|
||||
end
|
||||
gc.setCanvas(canvas)
|
||||
gc.origin()
|
||||
gc.setColor(1,1,1)
|
||||
|
||||
@@ -415,7 +415,7 @@ function love.errorhandler(msg)
|
||||
ins(ERRDATA,{mes=err,scene=scn})
|
||||
|
||||
--Write messages to log file
|
||||
love.filesystem.append("conf/error.log",
|
||||
love.filesystem.append('conf/error.log',
|
||||
os.date("%Y/%m/%d %A %H:%M:%S\n")..
|
||||
#ERRDATA.." crash(es) "..SYSTEM.."-"..VERSION.string.." scene: "..scn.."\n"..
|
||||
table.concat(err,"\n",1,c-2).."\n\n"
|
||||
|
||||
@@ -60,12 +60,24 @@ local mesIcon={
|
||||
local MES={}
|
||||
|
||||
function MES.new(icon,str,time)
|
||||
if type(icon)=='string'then icon=mesIcon[icon]end
|
||||
local backColor={.5,.5,.5,.7}
|
||||
if type(icon)=='string'then
|
||||
if icon=='check'then
|
||||
backColor={.3,.6,.3,.7}
|
||||
elseif icon=='broadcast'then
|
||||
backColor={.3,.3,.6,.8}
|
||||
elseif icon=='warn'then
|
||||
backColor={.4,.4,.2,.9}
|
||||
elseif icon=='error'then
|
||||
backColor={.4,.2,.2,.9}
|
||||
end
|
||||
icon=mesIcon[icon]
|
||||
end
|
||||
local t=gc.newText(getFont(30),str)
|
||||
local w=math.max(t:getWidth()+(icon and 45 or 5),200)+20
|
||||
local h=math.max(t:getHeight(),46)+3
|
||||
local L={w,h,
|
||||
{'clear',.5,.5,.5,.7},
|
||||
{'clear',backColor},
|
||||
{'setCL',.7,.7,.7},
|
||||
{'setLW',2},
|
||||
{'dRect',1,1,w-2,h-2},
|
||||
|
||||
@@ -81,6 +81,11 @@ do--function STRING.urlEncode(s)
|
||||
end
|
||||
end
|
||||
|
||||
function STRING.readLine(str)
|
||||
local p=str:find("\n")
|
||||
return str:sub(1,p-1),str:sub(p+1)
|
||||
end
|
||||
|
||||
function STRING.packBin(s)
|
||||
return data.encode('string','base64',data.compress('string','zlib',s))
|
||||
end
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
local gc=love.graphics
|
||||
local setColor,setWidth=gc.setColor,gc.setLineWidth
|
||||
local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth
|
||||
local gc_draw,gc_line=gc.draw,gc.line
|
||||
local gc_rectangle,gc_circle=gc.rectangle,gc.circle
|
||||
|
||||
local sin,cos=math.sin,math.cos
|
||||
local max,min=math.max,math.min
|
||||
local rnd=math.random
|
||||
@@ -45,26 +48,35 @@ function FXupdate.cell(S,dt)
|
||||
end
|
||||
FXupdate.line=normUpdate
|
||||
|
||||
local tapLight=DOGC{64,64,
|
||||
{'clear',1,1,1,0},
|
||||
{'setCL',1,1,1,.1},
|
||||
{'fCirc',32,32,5+10},
|
||||
{'fCirc',32,32,5+15},
|
||||
{'fCirc',32,32,5+20},
|
||||
{'fCirc',32,32,5+25},
|
||||
}
|
||||
|
||||
local FXdraw={}
|
||||
function FXdraw.badge(S)
|
||||
setColor(1,1,1,S.t<.2 and S.t*.6 or S.t<.8 and 1 or(1-S.t)*.6)
|
||||
gc.draw(IMG.badgeIcon,S.x,S.y)
|
||||
gc_setColor(1,1,1,S.t<.2 and S.t*.6 or S.t<.8 and 1 or(1-S.t)*.6)
|
||||
gc_draw(IMG.badgeIcon,S.x,S.y)
|
||||
end
|
||||
function FXdraw.attack(S)
|
||||
setColor(S.r*2,S.g*2,S.b*2,S.a*min(4-S.t*4,1))
|
||||
gc_setColor(S.r*2,S.g*2,S.b*2,S.a*min(4-S.t*4,1))
|
||||
|
||||
setWidth(S.wid)
|
||||
gc_setLineWidth(S.wid)
|
||||
local t1,t2=max(5*S.t-4,0),min(S.t*4,1)
|
||||
gc.line(
|
||||
gc_line(
|
||||
S.x1*(1-t1)+S.x2*t1,
|
||||
S.y1*(1-t1)+S.y2*t1,
|
||||
S.x1*(1-t2)+S.x2*t2,
|
||||
S.y1*(1-t2)+S.y2*t2
|
||||
)
|
||||
|
||||
setWidth(S.wid*.6)
|
||||
gc_setLineWidth(S.wid*.6)
|
||||
t1,t2=max(4*S.t-3,0),min(S.t*5,1)
|
||||
gc.line(
|
||||
gc_line(
|
||||
S.x1*(1-t1)+S.x2*t1,
|
||||
S.y1*(1-t1)+S.y2*t1,
|
||||
S.x1*(1-t2)+S.x2*t2,
|
||||
@@ -73,42 +85,39 @@ function FXdraw.attack(S)
|
||||
end
|
||||
function FXdraw.tap(S)
|
||||
local t=S.t
|
||||
setWidth(2)
|
||||
setColor(1,1,1,1-t)
|
||||
gc.circle('line',S.x,S.y,t*(2-t)*30)
|
||||
setColor(1,1,1,(1-t)*.5)
|
||||
gc.circle('fill',S.x,S.y,t*30)
|
||||
gc_setColor(1,1,1,(1-t)*.4)
|
||||
gc_circle('fill',S.x,S.y,(900-900*t)^.5)
|
||||
|
||||
setColor(1,1,1,1-t)
|
||||
for i=1,10 do
|
||||
gc_setColor(1,1,1,1-t)
|
||||
for i=1,12 do
|
||||
local p=S.ptc[i]
|
||||
local T=t^.5
|
||||
gc.rectangle('fill',p[1]*(1-T)+p[3]*T-5,p[2]*(1-T)+p[4]*T-5,11,11)
|
||||
gc_draw(tapLight,p[1]*(1-T)+p[3]*T-5,p[2]*(1-T)+p[4]*T-5,nil,.4-T*.26,nil,32,32)
|
||||
end
|
||||
end
|
||||
function FXdraw.ripple(S)
|
||||
local t=S.t
|
||||
setWidth(2)
|
||||
setColor(1,1,1,1-t)
|
||||
gc.circle('line',S.x,S.y,t*(2-t)*S.r)
|
||||
gc_setLineWidth(2)
|
||||
gc_setColor(1,1,1,1-t)
|
||||
gc_circle('line',S.x,S.y,t*(2-t)*S.r)
|
||||
end
|
||||
function FXdraw.rectRipple(S)
|
||||
setWidth(6)
|
||||
setColor(1,1,1,1-S.t)
|
||||
gc_setLineWidth(6)
|
||||
gc_setColor(1,1,1,1-S.t)
|
||||
local r=(10*S.t)^1.2
|
||||
gc.rectangle('line',S.x-r,S.y-r,S.w+2*r,S.h+2*r)
|
||||
gc_rectangle('line',S.x-r,S.y-r,S.w+2*r,S.h+2*r)
|
||||
end
|
||||
function FXdraw.shade(S)
|
||||
setColor(S.r,S.g,S.b,1-S.t)
|
||||
gc.rectangle('fill',S.x,S.y,S.w,S.h,2)
|
||||
gc_setColor(S.r,S.g,S.b,1-S.t)
|
||||
gc_rectangle('fill',S.x,S.y,S.w,S.h,2)
|
||||
end
|
||||
function FXdraw.cell(S)
|
||||
setColor(1,1,1,1-S.t)
|
||||
gc.draw(S.image,S.x,S.y,nil,S.size,nil,S.cx,S.cy)
|
||||
gc_setColor(1,1,1,1-S.t)
|
||||
gc_draw(S.image,S.x,S.y,nil,S.size,nil,S.cx,S.cy)
|
||||
end
|
||||
function FXdraw.line(S)
|
||||
setColor(1,1,1,S.a*(1-S.t))
|
||||
gc.line(S.x1,S.y1,S.x2,S.y2)
|
||||
gc_setColor(1,1,1,S.a*(1-S.t))
|
||||
gc_line(S.x1,S.y1,S.x2,S.y2)
|
||||
end
|
||||
|
||||
local SYSFX={}
|
||||
@@ -157,8 +166,8 @@ function SYSFX.newTap(rate,x,y)
|
||||
x=x,y=y,
|
||||
ptc={},
|
||||
}
|
||||
for i=1,10 do
|
||||
local d=40+50*rnd()
|
||||
for i=1,12 do
|
||||
local d=50+40*rnd()
|
||||
local ang=rnd()*6.2832
|
||||
T.ptc[i]={x,y,x+d*cos(ang),y+d*sin(ang)}
|
||||
end
|
||||
|
||||
@@ -224,6 +224,7 @@ while true do--Running
|
||||
end
|
||||
]]
|
||||
|
||||
local type=type
|
||||
local timer=love.timer.getTime
|
||||
local CHN=love.thread.newChannel()
|
||||
local CHN_getCount,CHN_push,CHN_pop=CHN.getCount,CHN.push,CHN.pop
|
||||
@@ -314,12 +315,17 @@ local OPname={
|
||||
[10]='pong',
|
||||
}
|
||||
function WS.send(name,message,op)
|
||||
local ws=wsList[name]
|
||||
if ws.real and ws.status=='running'then
|
||||
CHN_push(ws.sendCHN,op and OPcode[op]or 2)--2=binary
|
||||
CHN_push(ws.sendCHN,message)
|
||||
ws.lastPingTime=timer()
|
||||
ws.sendTimer=1
|
||||
if type(message)=='string'then
|
||||
local ws=wsList[name]
|
||||
if ws.real and ws.status=='running'then
|
||||
CHN_push(ws.sendCHN,op and OPcode[op]or 2)--2=binary
|
||||
CHN_push(ws.sendCHN,message)
|
||||
ws.lastPingTime=timer()
|
||||
ws.sendTimer=1
|
||||
end
|
||||
else
|
||||
MES.new('error',"Attempt to send non-string value!")
|
||||
MES.traceback()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ local kb=love.keyboard
|
||||
local next=next
|
||||
local int,ceil,abs=math.floor,math.ceil,math.abs
|
||||
local max,min=math.max,math.min
|
||||
local sub,ins=string.sub,table.insert
|
||||
local sub,ins,rem=string.sub,table.insert,table.remove
|
||||
local getFont,setFont,mStr=getFont,setFont,mStr
|
||||
local mDraw,mDraw_X,mDraw_Y=ADRAW.draw,ADRAW.simpX,ADRAW.simpY
|
||||
local xOy=SCR.xOy
|
||||
@@ -402,7 +402,7 @@ function switch:press()
|
||||
self.code()
|
||||
if self.sound then SFX.play('move')end
|
||||
end
|
||||
function WIDGET.newSwitch(D)--name,x,y[,fText][,color][,font=30][,sound=true][,disp],code,hide
|
||||
function WIDGET.newSwitch(D)--name,x,y[,fText][,color][,font=30][,sound=true][,disp],code[,hideF][,hide]
|
||||
local _={
|
||||
name= D.name or"_",
|
||||
|
||||
@@ -929,7 +929,7 @@ function textBox:push(t)
|
||||
end
|
||||
function textBox:press(x,y)
|
||||
if not(x and y)then return end
|
||||
self:drag(nil,nil,nil,0)
|
||||
self:drag(0,0,0,0)
|
||||
if not self.fix and x>self.x+self.w-40 and y<self.y+40 then
|
||||
if self.sure>0 then
|
||||
self:clear()
|
||||
@@ -1085,10 +1085,25 @@ end
|
||||
function listBox:push(t)
|
||||
ins(self.list,t)
|
||||
end
|
||||
function listBox:pop()
|
||||
if #self.list>0 then
|
||||
rem(self.list)
|
||||
listBox:drag(0,0,0,0)
|
||||
end
|
||||
end
|
||||
function listBox:remove()
|
||||
if self.selected then
|
||||
rem(self.list,self.selected)
|
||||
if not self.list[self.selected]then
|
||||
self:arrowKey('up')
|
||||
end
|
||||
self:drag(0,0,0,0)
|
||||
end
|
||||
end
|
||||
function listBox:press(x,y)
|
||||
x,y=x-self.x,y-self.y
|
||||
if not(x and y and x>0 and y>0 and x<=self.w and y<=self.h)then return end
|
||||
self:drag(nil,nil,nil,0)
|
||||
self:drag(0,0,0,0)
|
||||
y=int((y+self.scrollPos)/self.lineH)+1
|
||||
if self.list[y]then
|
||||
if self.selected~=y then
|
||||
@@ -1145,7 +1160,7 @@ function listBox:draw()
|
||||
local pos=int(scrollPos/lineH)
|
||||
gc_translate(0,-(scrollPos%lineH))
|
||||
for i=pos+1,min(pos+cap+1,#list)do
|
||||
self.drawF(i==self.selected,i,list[i])
|
||||
self.drawF(list[i],i,i==self.selected)
|
||||
gc_translate(0,lineH)
|
||||
end
|
||||
gc_setStencilTest()
|
||||
@@ -1154,7 +1169,7 @@ end
|
||||
function listBox:getInfo()
|
||||
return("x=%d,y=%d,w=%d,h=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h)
|
||||
end
|
||||
function WIDGET.newListBox(D)--name,x,y,w,h[,lineH],hide,drawF
|
||||
function WIDGET.newListBox(D)--name,x,y,w,h,lineH[,hideF][,hide][,drawF]
|
||||
local _={
|
||||
name= D.name or"_",
|
||||
|
||||
|
||||
10
conf.lua
10
conf.lua
@@ -1,9 +1,9 @@
|
||||
VERSION={
|
||||
build=338,
|
||||
code=1504,
|
||||
short="V0.15.4",
|
||||
string="Alpha V0.15.4",
|
||||
name="近地轨道 Low Earth Orbit",
|
||||
build=342,
|
||||
code=1505,
|
||||
short="V0.15.5",
|
||||
string="Alpha V0.15.5",
|
||||
name="姿态调整 RCS Control",
|
||||
}
|
||||
function love.conf(t)
|
||||
t.identity='Techmino'--Saving folder
|
||||
|
||||
83
main.lua
83
main.lua
@@ -221,7 +221,6 @@ for _,v in next,fs.getDirectoryItems("parts/backgrounds")do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Load scene files from SOURCE ONLY
|
||||
for _,v in next,fs.getDirectoryItems("parts/scenes")do
|
||||
if fs.getRealDirectory("parts/scenes/"..v)~=SAVEDIR then
|
||||
@@ -230,6 +229,13 @@ for _,v in next,fs.getDirectoryItems("parts/scenes")do
|
||||
LANG.addScene(sceneName)
|
||||
end
|
||||
end
|
||||
--Load mode files
|
||||
for i=1,#MODES do
|
||||
local m=MODES[i]--Mode template
|
||||
local M=require("parts.modes."..m.name)--Mode file
|
||||
for k,v in next,m do M[k]=v end
|
||||
MODES[m.name],MODES[i]=M
|
||||
end
|
||||
|
||||
--Update data
|
||||
do
|
||||
@@ -246,6 +252,10 @@ do
|
||||
fs.remove('conf/user')
|
||||
fs.remove('conf/key')
|
||||
end
|
||||
if STAT.version<1505 then
|
||||
fs.remove('record/bigbang.rec')
|
||||
fs.remove('conf/replay')
|
||||
end
|
||||
if STAT.version~=VERSION.code then
|
||||
STAT.version=VERSION.code
|
||||
needSave=true
|
||||
@@ -267,20 +277,19 @@ do
|
||||
needSave=true
|
||||
end
|
||||
end
|
||||
local modeTable={attacker_h="attacker_hard",attacker_u="attacker_ultimate",blind_e="blind_easy",blind_h="blind_hard",blind_l="blind_lunatic",blind_n="blind_normal",blind_u="blind_ultimate",c4wtrain_l="c4wtrain_lunatic",c4wtrain_n="c4wtrain_normal",defender_l="defender_lunatic",defender_n="defender_normal",dig_100l="dig_100",dig_10l="dig_10",dig_400l="dig_400",dig_40l="dig_40",dig_h="dig_hard",dig_u="dig_ultimate",drought_l="drought_lunatic",drought_n="drought_normal",marathon_h="marathon_hard",marathon_n="marathon_normal",pc_h="pcchallenge_hard",pc_l="pcchallenge_lunatic",pc_n="pcchallenge_normal",pctrain_l="pctrain_lunatic",pctrain_n="pctrain_normal",round_e="round_1",round_h="round_2",round_l="round_3",round_n="round_4",round_u="round_5",solo_e="solo_1",solo_h="solo_2",solo_l="solo_3",solo_n="solo_4",solo_u="solo_5",sprint_10l="sprint_10",sprint_20l="sprint_20",sprint_40l="sprint_40",sprint_400l="sprint_400",sprint_100l="sprint_100",sprint_1000l="sprint_1000",survivor_e="survivor_easy",survivor_h="survivor_hard",survivor_l="survivor_lunatic",survivor_n="survivor_normal",survivor_u="survivor_ultimate",tech_finesse_f="tech_finesse2",tech_h_plus="tech_hard2",tech_h="tech_hard",tech_l_plus="tech_lunatic2",tech_l="tech_lunatic",tech_n_plus="tech_normal2",tech_n="tech_normal",techmino49_e="techmino49_easy",techmino49_h="techmino49_hard",techmino49_u="techmino49_ultimate",techmino99_e="techmino99_easy",techmino99_h="techmino99_hard",techmino99_u="techmino99_ultimate",tsd_e="tsd_easy",tsd_h="tsd_hard",tsd_u="tsd_ultimate",master_extra="GM"}
|
||||
for k,v in next,modeTable do
|
||||
if RANKS[v]then
|
||||
RANKS[k]=RANKS[v]
|
||||
RANKS[v]=nil
|
||||
for k,v in next,oldModeNameTable do
|
||||
if RANKS[k]then
|
||||
RANKS[v]=RANKS[k]
|
||||
RANKS[k]=nil
|
||||
end
|
||||
v="record/"..v
|
||||
if fs.getInfo(v..".dat")then
|
||||
fs.write("record/"..k..".rec",fs.read(v..".dat"))
|
||||
fs.remove(v..".dat")
|
||||
k="record/"..k
|
||||
if fs.getInfo(k..".dat")then
|
||||
fs.write("record/"..v..".rec",fs.read(k..".dat"))
|
||||
fs.remove(k..".dat")
|
||||
end
|
||||
if fs.getInfo(v..".rec")then
|
||||
fs.write("record/"..k..".rec",fs.read(v..".rec"))
|
||||
fs.remove(v..".rec")
|
||||
if fs.getInfo(k..".rec")then
|
||||
fs.write("record/"..v..".rec",fs.read(k..".rec"))
|
||||
fs.remove(k..".rec")
|
||||
end
|
||||
end
|
||||
if not RANKS.sprint_10l then
|
||||
@@ -297,6 +306,50 @@ do
|
||||
love.event.quit('restart')
|
||||
end
|
||||
end
|
||||
|
||||
LANG.set(SETTING.lang)
|
||||
VK.setShape(SETTING.VKSkin)
|
||||
VK.setShape(SETTING.VKSkin)
|
||||
--Load replays
|
||||
for _,fileName in next,fs.getDirectoryItems("replay")do
|
||||
if fileName:sub(12,12):match("[a-zA-Z]")then
|
||||
local date,mode,version,player,seed,setting,mod
|
||||
local fileData=fs.read('replay/'..fileName)
|
||||
date, fileData=STRING.readLine(fileData)date=date:gsub("[a-zA-Z]","")
|
||||
mode, fileData=STRING.readLine(fileData)mode=oldModeNameTable[mode]or mode
|
||||
version,fileData=STRING.readLine(fileData)
|
||||
player, fileData=STRING.readLine(fileData)if player=="Local Player"then player="Stacker"end
|
||||
local success
|
||||
success,fileData=pcall(love.data.decompress,'string','zlib',fileData)
|
||||
if not success then goto BREAK_cannotParse end
|
||||
seed, fileData=STRING.readLine(fileData)
|
||||
setting,fileData=STRING.readLine(fileData)setting=JSON.decode(setting)
|
||||
mod, fileData=STRING.readLine(fileData)mod=JSON.decode(mod)
|
||||
if
|
||||
not setting or
|
||||
not mod or
|
||||
not mode or
|
||||
#mode==0
|
||||
then goto BREAK_cannotParse end
|
||||
|
||||
fs.remove('replay/'..fileName)
|
||||
local newName=fileName:sub(1,10)..fileName:sub(15)
|
||||
fs.write('replay/'..newName,
|
||||
love.data.compress('string','zlib',
|
||||
JSON.encode{
|
||||
date=date,
|
||||
mode=mode,
|
||||
version=version,
|
||||
player=player,
|
||||
seed=seed,
|
||||
setting=setting,
|
||||
mod=mod,
|
||||
}.."\n"..
|
||||
fileData
|
||||
)
|
||||
)
|
||||
fileName=newName
|
||||
end
|
||||
::BREAK_cannotParse::
|
||||
local rep=DATA.parseReplay('replay/'..fileName)
|
||||
table.insert(REPLAY,rep)
|
||||
end
|
||||
table.sort(REPLAY,function(a,b)return a.fileName>b.fileName end)
|
||||
BIN
media/BGM/rectification.ogg
Normal file
BIN
media/BGM/rectification.ogg
Normal file
Binary file not shown.
@@ -1,4 +1,5 @@
|
||||
local loveCompress=love.data.compress
|
||||
local loveDecompress=love.data.decompress
|
||||
|
||||
local int=math.floor
|
||||
local char,byte=string.char,string.byte
|
||||
@@ -336,7 +337,7 @@ function DATA.pumpRecording(str,L)
|
||||
p=p+1
|
||||
end
|
||||
end
|
||||
do--function DATA.saveRecording()
|
||||
do--function DATA.saveReplay()
|
||||
local noRecList={"custom","solo","round","techmino"}
|
||||
local function getModList()
|
||||
local res={}
|
||||
@@ -347,7 +348,7 @@ do--function DATA.saveRecording()
|
||||
end
|
||||
return res
|
||||
end
|
||||
function DATA.saveRecording()
|
||||
function DATA.saveReplay()
|
||||
--Filtering modes that cannot be saved
|
||||
for _,v in next,noRecList do
|
||||
if GAME.curModeName:find(v)then
|
||||
@@ -357,27 +358,72 @@ do--function DATA.saveRecording()
|
||||
end
|
||||
|
||||
--Write file
|
||||
local fileName=os.date("replay/%Y_%m_%d_%a_%H%M%S.rep")
|
||||
local fileName=os.date("replay/%Y_%m_%d_%H%M%S.rep")
|
||||
if not love.filesystem.getInfo(fileName)then
|
||||
local fileHead=
|
||||
os.date("%Y/%m/%d %A %H:%M:%S\n")..
|
||||
GAME.curModeName.."\n"..
|
||||
VERSION.string.."\n"..
|
||||
"Local Player"
|
||||
local fileBody=
|
||||
GAME.seed.."\n"..
|
||||
JSON.encode(GAME.setting).."\n"..
|
||||
JSON.encode(getModList()).."\n"..
|
||||
DATA.dumpRecording(GAME.rep)
|
||||
|
||||
love.filesystem.write(fileName,fileHead.."\n"..loveCompress('string','zlib',fileBody))
|
||||
ins(REPLAY,fileName)
|
||||
FILE.save(REPLAY,'conf/replay')
|
||||
love.filesystem.write(fileName,
|
||||
loveCompress('string','zlib',
|
||||
JSON.encode{
|
||||
date=os.date("%Y/%m/%d %H:%M:%S"),
|
||||
mode=GAME.curModeName,
|
||||
version=VERSION.string,
|
||||
player=USERS.getUsername(USER.uid),
|
||||
seed=GAME.seed,
|
||||
setting=GAME.setting,
|
||||
mod=getModList(),
|
||||
}.."\n"..
|
||||
DATA.dumpRecording(GAME.rep)
|
||||
)
|
||||
)
|
||||
ins(REPLAY,1,DATA.parseReplay(fileName))
|
||||
return true
|
||||
else
|
||||
MES.new('error',"Save failed: File already exists")
|
||||
end
|
||||
end
|
||||
end
|
||||
function DATA.parseReplay(fileName,ifFull)
|
||||
local fileData,success,metaData,rep
|
||||
|
||||
--Read file
|
||||
fileData=love.filesystem.read(fileName)
|
||||
if not(fileData and #fileData>0)then goto BREAK_cannotParse end
|
||||
|
||||
--Decompress file
|
||||
success,fileData=pcall(loveDecompress,'string','zlib',fileData)
|
||||
if not success then goto BREAK_cannotParse end
|
||||
|
||||
--Load metadata
|
||||
metaData,fileData=STRING.readLine(fileData)
|
||||
metaData=JSON.decode(metaData)
|
||||
if not metaData then goto BREAK_cannotParse end
|
||||
|
||||
--Convert ancient replays
|
||||
metaData.mode=oldModeNameTable[metaData.mode]or metaData.mode
|
||||
if not MODES[metaData.mode]then goto BREAK_cannotParse end
|
||||
|
||||
--Create replay object
|
||||
rep={
|
||||
fileName=fileName,
|
||||
available=true,
|
||||
|
||||
date=metaData.date,
|
||||
mode=metaData.mode,
|
||||
version=metaData.version,
|
||||
player=metaData.player,
|
||||
|
||||
seed=metaData.seed,
|
||||
setting=metaData.setting,
|
||||
mod=metaData.mod,
|
||||
}
|
||||
if ifFull then rep.data=fileData end
|
||||
do return rep end
|
||||
|
||||
--Create unavailable replay object
|
||||
::BREAK_cannotParse::
|
||||
return{
|
||||
fileName=fileName,
|
||||
available=false,
|
||||
}
|
||||
end
|
||||
|
||||
return DATA
|
||||
@@ -224,26 +224,33 @@ function applyCustomGame()--Apply CUSTOMENV, BAG, MISSION
|
||||
GAME.modeEnv.mission=nil
|
||||
end
|
||||
end
|
||||
function loadGame(M,ifQuickPlay,ifNet)--Load a mode and go to game scene
|
||||
function loadGame(mode,ifQuickPlay,ifNet)--Load a mode and go to game scene
|
||||
freshDate()
|
||||
if legalGameTime()then
|
||||
if MODES[M].score then STAT.lastPlay=M end
|
||||
GAME.curModeName=M
|
||||
GAME.curMode=MODES[M]
|
||||
GAME.modeEnv=GAME.curMode.env
|
||||
if MODES[mode].score then STAT.lastPlay=mode end
|
||||
GAME.init=true
|
||||
GAME.fromRepMenu=false
|
||||
GAME.curModeName=mode
|
||||
GAME.curMode=MODES[mode]
|
||||
GAME.modeEnv=GAME.curMode.env
|
||||
GAME.net=ifNet
|
||||
if ifNet then
|
||||
SCN.go('net_game','swipeD')
|
||||
else
|
||||
drawableText.modeName:set((text.modes[M][1]or M).." "..(text.modes[M][2]or""))
|
||||
drawableText.modeName:set((text.modes[mode][1]or mode).." "..(text.modes[mode][2]or""))
|
||||
SCN.go('game',ifQuickPlay and'swipeD'or'fade_togame')
|
||||
SFX.play('enter')
|
||||
end
|
||||
end
|
||||
end
|
||||
function gameOver()--Save record
|
||||
if GAME.replaying then return end
|
||||
if GAME.replaying then
|
||||
local R=GAME.curMode.getRank
|
||||
if R then
|
||||
R=R(PLAYERS[1])
|
||||
if R and R>0 then GAME.rank=R end
|
||||
end
|
||||
end
|
||||
trySave()
|
||||
|
||||
local M=GAME.curMode
|
||||
@@ -384,7 +391,7 @@ do--function dumpBasicConfig()
|
||||
'skin','face',
|
||||
|
||||
--Graphic
|
||||
'block','ghost','center','bagLine',
|
||||
'ghostType','block','ghost','center','bagLine',
|
||||
'dropFX','moveFX','shakeFX',
|
||||
'text','highCam','nextPos',
|
||||
|
||||
@@ -419,7 +426,7 @@ do--function resetGameData(args)
|
||||
end
|
||||
local gameSetting={
|
||||
--Tuning
|
||||
'das','arr','dascut','sddas','sdarr',
|
||||
'das','arr','dascut','dropcut','sddas','sdarr',
|
||||
'ihs','irs','ims','RS','swap',
|
||||
|
||||
--System
|
||||
@@ -446,6 +453,7 @@ do--function resetGameData(args)
|
||||
trySave()
|
||||
|
||||
GAME.result=false
|
||||
GAME.rank=0
|
||||
GAME.warnLVL0=0
|
||||
GAME.warnLVL=0
|
||||
if args:find'r'then
|
||||
@@ -463,7 +471,6 @@ do--function resetGameData(args)
|
||||
GAME.recording=true
|
||||
GAME.statSaved=false
|
||||
GAME.replaying=false
|
||||
GAME.rank=0
|
||||
math.randomseed(TIME())
|
||||
end
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ GAME={--Global game data
|
||||
net=false, --If play net game
|
||||
|
||||
result=false, --Game result (string)
|
||||
rank=false, --Rank reached
|
||||
rank=0, --Rank reached
|
||||
pauseTime=0, --Time paused
|
||||
pauseCount=0, --Pausing count
|
||||
warnLVL0=0, --Warning level
|
||||
@@ -314,6 +314,7 @@ SETTING={--Settings
|
||||
face={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
|
||||
--Graphic
|
||||
ghostType='gray',
|
||||
block=true,ghost=.3,center=1,
|
||||
smooth=true,grid=.16,
|
||||
upEdge=true,
|
||||
@@ -417,4 +418,4 @@ VK_org=FILE.load('conf/virtualkey')or{--Virtualkey layout, refresh all VKs' posi
|
||||
{ava=false, x=900, y=50, r=80},--addToLeft
|
||||
{ava=false, x=1000, y=50, r=80},--addToRight
|
||||
}
|
||||
REPLAY=FILE.load('conf/replay')or{}
|
||||
REPLAY={}--Replay objects (not include stream data)
|
||||
@@ -71,6 +71,8 @@ return{
|
||||
highScore="Personal Bests",
|
||||
newRecord="New Record!",
|
||||
|
||||
replayBroken="Cannot load replay",
|
||||
|
||||
getNoticeFail="Failed fetching announcements...",
|
||||
oldVersion="Version $1 is now available!",
|
||||
needUpdate="Newer version required!",
|
||||
@@ -108,7 +110,7 @@ return{
|
||||
|
||||
errorMsg="Techmino ran into a problem and needs to restart.\nYou can send the error log to the devs.",
|
||||
|
||||
modInstruction="Choose your modifiers!\nMods allow you to change the game.\nThey may also break it in weird ways.\nBeware, some mods will cause your game to be unranked!",
|
||||
modInstruction="Choose your modifiers!\nMods allow you to change the game.\nThey may also break it in weird ways.\nBeware, the mods will cause your game to be unranked!",
|
||||
modInfo={
|
||||
next="NEXT\nOverrides the number of Next pieces.",
|
||||
hold="HOLD\nOverrides the number of Hold pieces.",
|
||||
@@ -210,7 +212,7 @@ return{
|
||||
stat="Statistics",
|
||||
music="Music & SE",
|
||||
dict="Zictionary",
|
||||
manual="Manual",
|
||||
replays="Replays",
|
||||
},
|
||||
main_simple={
|
||||
sprint="Sprint",
|
||||
@@ -320,6 +322,7 @@ return{
|
||||
upEdge="3D Block",
|
||||
bagLine="Bag Separator",
|
||||
|
||||
ghostType="Ghost Type",
|
||||
ghost="Ghost",
|
||||
grid="Grid",
|
||||
center="Center",
|
||||
@@ -546,7 +549,6 @@ return{
|
||||
stat={
|
||||
path="Open Data Folder",
|
||||
save="Data Management",
|
||||
replays="Saved Replays",
|
||||
},
|
||||
music={
|
||||
title="Music Room",
|
||||
@@ -922,4 +924,4 @@ return{
|
||||
{C.Y,"O-Spin Triple!"},
|
||||
{C.Z,"What? ",C.lC,"Xspin?"},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@ return{
|
||||
highScore="Mejores puntajes",
|
||||
newRecord="¡Nuevo Récord!",
|
||||
|
||||
-- replayBroken="Cannot load replay",
|
||||
|
||||
getNoticeFail="Error al buscar novedades.",
|
||||
oldVersion="¡Está disponible la nueva versión $1!",
|
||||
versionNotMatch="¡Las versiones no coinciden!",
|
||||
@@ -185,7 +187,7 @@ return{
|
||||
stat="Estadísticas",
|
||||
music="Música y SFX",
|
||||
dict="Zictionary",
|
||||
manual="Manual",
|
||||
-- replays="Replays",
|
||||
},
|
||||
main_simple={
|
||||
sprint="Sprint",
|
||||
@@ -295,6 +297,7 @@ return{
|
||||
upEdge="Bloques en 3D",
|
||||
bagLine="Línea de Bag de Pzas.",
|
||||
|
||||
-- ghostType="Ghost Type",
|
||||
ghost="Fantasma",
|
||||
grid="Grilla",
|
||||
center="Centrar",
|
||||
@@ -501,7 +504,6 @@ return{
|
||||
stat={
|
||||
path="Abrir carpeta del juego",
|
||||
save="Manejo de Datos",
|
||||
-- replays="Saved Replays",
|
||||
},
|
||||
music={
|
||||
title="Sala de Música",
|
||||
|
||||
@@ -70,6 +70,8 @@ return{
|
||||
highScore="Records personnels",
|
||||
newRecord="Nouveau record !",
|
||||
|
||||
-- replayBroken="Cannot load replay",
|
||||
|
||||
getNoticeFail="Echec de l'obtention de la notice",
|
||||
oldVersion="La version $1 est disponible !",
|
||||
-- versionNotMatch="Version do not match!",
|
||||
@@ -185,7 +187,7 @@ return{
|
||||
stat="Statistiques",
|
||||
-- music="Music & SE",
|
||||
dict="Zictionary",
|
||||
manual="Manuel",
|
||||
-- replays="Replays",
|
||||
},
|
||||
mode={
|
||||
mod="Mods (F1)",
|
||||
@@ -293,6 +295,7 @@ return{
|
||||
upEdge="Bloc 3D",
|
||||
bagLine="Ligne du Sac",
|
||||
|
||||
-- ghostType="Ghost Type",
|
||||
ghost="Pièce fantôme",
|
||||
grid="Grille",
|
||||
center="Centre",
|
||||
@@ -500,7 +503,6 @@ return{
|
||||
stat={
|
||||
path="Ouvrir dossier des données",
|
||||
save="Gestion des données",
|
||||
-- replays="Saved Replays",
|
||||
},
|
||||
music={
|
||||
title="Salon musical",
|
||||
|
||||
@@ -70,6 +70,8 @@ return{
|
||||
highScore="Melhor pessoal",
|
||||
newRecord="Novo recorde",
|
||||
|
||||
-- replayBroken="Cannot load replay",
|
||||
|
||||
getNoticeFail="Não conseguiu ter anúncios",
|
||||
oldVersion="Versão $1 esta disponível agora!",
|
||||
-- versionNotMatch="Version do not match!",
|
||||
@@ -209,7 +211,7 @@ return{
|
||||
stat="Stats",
|
||||
-- music="Music & SE",
|
||||
dict="Zictionary",
|
||||
manual="Manual",
|
||||
-- replays="Replays",
|
||||
},
|
||||
main_simple={
|
||||
sprint="Sprint",
|
||||
@@ -319,6 +321,7 @@ return{
|
||||
upEdge="3D bloco",
|
||||
bagLine="Linha da bolsa",
|
||||
|
||||
-- ghostType="Ghost Type",
|
||||
ghost="Fantasma",
|
||||
grid="Rede",
|
||||
center="Centro",
|
||||
@@ -543,7 +546,6 @@ return{
|
||||
stat={
|
||||
path="Abrir Pasta De Data",
|
||||
save="Gestão De Dados",
|
||||
-- replays="Saved Replays",
|
||||
},
|
||||
music={
|
||||
title="Sala De Música",
|
||||
|
||||
@@ -54,6 +54,8 @@ return{
|
||||
highScore="__&:",
|
||||
newRecord="^!!!^",
|
||||
|
||||
replayBroken=">x.",
|
||||
|
||||
errorMsg="An e??o? h@s occ^__ed @nd Techmino n__ds to r_st@rt.\n&**o* in#o h@$ b==n cre@ted, @nd y0u c@n $&nd it to the @uth0r.",
|
||||
|
||||
pauseStat={
|
||||
@@ -102,7 +104,7 @@ return{
|
||||
stat="=___",
|
||||
music="~~~ & =><=",
|
||||
dict="z",
|
||||
manual="???",
|
||||
replays="=~~~",
|
||||
},
|
||||
mode={
|
||||
mod="?!?!?!(F1)",
|
||||
@@ -148,6 +150,7 @@ return{
|
||||
upEdge="[]`",
|
||||
bagLine="123|123",
|
||||
|
||||
ghostType="__↓?__",
|
||||
ghost="__↓__",
|
||||
grid="#",
|
||||
center="+",
|
||||
@@ -357,7 +360,6 @@ return{
|
||||
stat={
|
||||
path="%$%",
|
||||
save="%0123%",
|
||||
replays="%0101%",
|
||||
},
|
||||
music={
|
||||
title="(~~~~)",
|
||||
|
||||
@@ -256,7 +256,7 @@ return{
|
||||
['defender_l']= {"防守", "疯狂", "防守练习"},
|
||||
['dig_h']= {"挖掘", "困难", "挖掘练习"},
|
||||
['dig_u']= {"挖掘", "极限", "挖掘练习"},
|
||||
['bigbang']= {"大爆炸", "简单", "All-spin 入门教程\n未制作完成,落块即通"},
|
||||
['bigbang']= {"大爆炸", "简单", "All-spin 入门教程\n施工中"},
|
||||
['c4wtrain_n']= {"C4W练习", "普通", "无 限 连 击"},
|
||||
['c4wtrain_l']= {"C4W练习", "疯狂", "无 限 连 击"},
|
||||
['pctrain_n']= {"全清训练", "普通", "随便打打"},
|
||||
|
||||
@@ -71,6 +71,8 @@ return{
|
||||
highScore="最佳成绩",
|
||||
newRecord="打破纪录",
|
||||
|
||||
replayBroken="无法加载该录像",
|
||||
|
||||
getNoticeFail="拉取公告失败",
|
||||
oldVersion="最新版本$1可以下载了!",
|
||||
needUpdate="请更新游戏!",
|
||||
@@ -210,7 +212,7 @@ return{
|
||||
stat="统计信息",
|
||||
music="音乐&音效",
|
||||
dict="小Z词典",
|
||||
manual="说明书",
|
||||
replays="录像回放",
|
||||
},
|
||||
main_simple={
|
||||
sprint="40行",
|
||||
@@ -320,6 +322,7 @@ return{
|
||||
upEdge="3D方块",
|
||||
bagLine="包分界线",
|
||||
|
||||
ghostType="阴影样式",
|
||||
ghost="阴影不透明度",
|
||||
grid="网格不透明度",
|
||||
center="旋转中心不透明度",
|
||||
@@ -623,7 +626,6 @@ return{
|
||||
stat={
|
||||
path="打开存储目录",
|
||||
save="用户档案管理",
|
||||
replays="录像菜单",
|
||||
},
|
||||
login={
|
||||
title="登录",
|
||||
@@ -768,7 +770,7 @@ return{
|
||||
['defender_l']= {"防守", "疯狂", "防守练习"},
|
||||
['dig_h']= {"挖掘", "困难", "挖掘练习"},
|
||||
['dig_u']= {"挖掘", "极限", "挖掘练习"},
|
||||
['bigbang']= {"大爆炸", "简单", "All-spin 入门教程\n未制作完成,落块即通"},
|
||||
['bigbang']= {"大爆炸", "简单", "All-spin 入门教程\n施工中"},
|
||||
['c4wtrain_n']= {"C4W练习", "普通", "无 限 连 击"},
|
||||
['c4wtrain_l']= {"C4W练习", "疯狂", "无 限 连 击"},
|
||||
['pctrain_n']= {"全清训练", "普通", "简易PC题库,熟悉全清定式的组合"},
|
||||
@@ -851,6 +853,7 @@ return{
|
||||
"别问游戏名怎么取的,问就是随便想的",
|
||||
"不同人打40行最合适的方式不一样,s1w/63/散消/s2w...",
|
||||
"不同游戏(甚至不同模式)中不同战术的能力都不一样,并没有绝对的强弱之分",
|
||||
"不希望激烈的零和竞争充斥整个游戏",
|
||||
"不要悲伤,不要心急",
|
||||
"不知道有多少人玩游戏的时候会关心游戏是谁做的",
|
||||
"部分手机系统开启震动会导致严重卡顿",
|
||||
@@ -901,7 +904,6 @@ return{
|
||||
"很有精神!",
|
||||
"混合消除即将到来!",
|
||||
"基础堆叠和挖掘能力非常重要,忽视这两项的人都后悔了(确信)",
|
||||
"激烈的竞争不应充斥整个游戏",
|
||||
"即使被顶到天上了也不要放弃,每一行垃圾都有可能成为你的武器",
|
||||
"极简率决定了你大概的速度上限和相等手速下的放块速度",
|
||||
"假如生活欺骗了你,不要悲伤,不要心急,还有块陪着你",
|
||||
@@ -1004,10 +1006,10 @@ return{
|
||||
"自定义场地可以画图实现逐页演示",
|
||||
"总共有将近400条tip哦",
|
||||
"作者40行sub26了",
|
||||
"作者电脑上装了10个方块",
|
||||
"作者电脑上装了11个方块",
|
||||
"作者浏览器收藏夹里有6个方块",
|
||||
"做,做碌鸠啊做,打块先啦!",
|
||||
"做点击特效的时候真没想抄Phigros!想法另有出处,做完了才突然发现好像(",
|
||||
"做点击特效的时候真没想抄Phigros!想法另有出处,做完了才突然发现有点像(",
|
||||
"ALLSPIN!",
|
||||
"Am G F G",
|
||||
"B2B2B???",
|
||||
|
||||
@@ -190,7 +190,7 @@ return{
|
||||
['defender_l']= {"防守", "疯狂", "防守练习"},
|
||||
['dig_h']= {"挖掘", "困难", "挖掘练习"},
|
||||
['dig_u']= {"挖掘", "极限", "挖掘练习"},
|
||||
['bigbang']= {"大爆炸", "简单", "All-spin 入门教程\n未制作完成,落块即通"},
|
||||
['bigbang']= {"大爆炸", "简单", "All-spin 入门教程\n施工中"},
|
||||
['c4wtrain_n']= {"中四宽练习", "普通", "无 限 连 击"},
|
||||
['c4wtrain_l']= {"中四宽练习", "疯狂", "无 限 连 击"},
|
||||
['pctrain_n']= {"全清训练", "普通", "简易全清题库,熟悉全清定式的组合"},
|
||||
|
||||
@@ -286,6 +286,72 @@ do--SCS(spinCenters)
|
||||
{[0]=D,D,D,D},--O1
|
||||
}
|
||||
end
|
||||
oldModeNameTable={
|
||||
attacker_hard="attacker_h",
|
||||
attacker_ultimate="attacker_u",
|
||||
blind_easy="blind_e",
|
||||
blind_hard="blind_h",
|
||||
blind_lunatic="blind_l",
|
||||
blind_normal="blind_n",
|
||||
blind_ultimate="blind_u",
|
||||
c4wtrain_lunatic="c4wtrain_l",
|
||||
c4wtrain_normal="c4wtrain_n",
|
||||
defender_lunatic="defender_l",
|
||||
defender_normal="defender_n",
|
||||
dig_100="dig_100l",
|
||||
dig_10="dig_10l",
|
||||
dig_400="dig_400l",
|
||||
dig_40="dig_40l",
|
||||
dig_hard="dig_h",
|
||||
dig_ultimate="dig_u",
|
||||
drought_lunatic="drought_l",
|
||||
drought_normal="drought_n",
|
||||
marathon_hard="marathon_h",
|
||||
marathon_normal="marathon_n",
|
||||
pcchallenge_hard="pc_h",
|
||||
pcchallenge_lunatic="pc_l",
|
||||
pcchallenge_normal="pc_n",
|
||||
pctrain_lunatic="pctrain_l",
|
||||
pctrain_normal="pctrain_n",
|
||||
round_1="round_e",
|
||||
round_2="round_h",
|
||||
round_3="round_l",
|
||||
round_4="round_n",
|
||||
round_5="round_u",
|
||||
solo_1="solo_e",
|
||||
solo_2="solo_h",
|
||||
solo_3="solo_l",
|
||||
solo_4="solo_n",
|
||||
solo_5="solo_u",
|
||||
sprint_10="sprint_10l",
|
||||
sprint_20="sprint_20l",
|
||||
sprint_40="sprint_40l",
|
||||
sprint_400="sprint_400l",
|
||||
sprint_100="sprint_100l",
|
||||
sprint_1000="sprint_1000l",
|
||||
survivor_easy="survivor_e",
|
||||
survivor_hard="survivor_h",
|
||||
survivor_lunatic="survivor_l",
|
||||
survivor_normal="survivor_n",
|
||||
survivor_ultimate="survivor_u",
|
||||
tech_finesse2="tech_finesse_f",
|
||||
tech_hard2="tech_h_plus",
|
||||
tech_hard="tech_h",
|
||||
tech_lunatic2="tech_l_plus",
|
||||
tech_lunatic="tech_l",
|
||||
tech_normal2="tech_n_plus",
|
||||
tech_normal="tech_n",
|
||||
techmino49_easy="techmino49_e",
|
||||
techmino49_hard="techmino49_h",
|
||||
techmino49_ultimate="techmino49_u",
|
||||
techmino99_easy="techmino99_e",
|
||||
techmino99_hard="techmino99_h",
|
||||
techmino99_ultimate="techmino99_u",
|
||||
tsd_easy="tsd_e",
|
||||
tsd_hard="tsd_h",
|
||||
tsd_ultimate="tsd_u",
|
||||
GM="master_extra",
|
||||
}
|
||||
rankColor={
|
||||
{.6,.3,.3},
|
||||
{.7,.5,.3},
|
||||
|
||||
@@ -3,24 +3,21 @@ return{
|
||||
env={
|
||||
drop=1e99,lock=1e99,
|
||||
holdCount=0,
|
||||
dropPiece=function(P)P:lose()end,
|
||||
task=function(P)
|
||||
while not P.control do YIELD()end
|
||||
P:pressKey(6)
|
||||
P:lose()
|
||||
end,
|
||||
bg='bg1',bgm='new era',
|
||||
},
|
||||
pauseLimit=true,
|
||||
load=function()
|
||||
PLY.newPlayer(1)
|
||||
end,
|
||||
score=function(P)return{P.modeData.event,P.stat.finesseRate*20/P.stat.piece}end,
|
||||
score=function(P)return{P.modeData.event,P.stat.finesseRate*.2/P.stat.piece}end,
|
||||
scoreDisp=function(D)return("%d Stage %.2f%%"):format(D[1],D[2])end,
|
||||
comp=function(a,b)return a[1]>b[1]or a[1]==b[1]and a[2]>b[2]end,
|
||||
getRank=function(P)
|
||||
local W=P.modeData.event
|
||||
return
|
||||
W>=150 and 5 or
|
||||
W>=100 and 4 or
|
||||
W>=70 and 3 or
|
||||
W>=40 and 2 or
|
||||
W>=20 and 1 or
|
||||
1
|
||||
getRank=function()
|
||||
return 1
|
||||
end,
|
||||
}
|
||||
@@ -13,7 +13,7 @@ local function score(P)
|
||||
if D.pt%100==99 then
|
||||
SFX.play('blip_1')
|
||||
elseif D.pt>=D.target then--Level up!
|
||||
s=D.target/100
|
||||
s=D.target/100--range from 1 to 9
|
||||
local E=P.gameEnv
|
||||
if s<4 then
|
||||
P:showTextF(text.stage:gsub("$1",s),0,-120,80,'fly')
|
||||
@@ -23,12 +23,12 @@ local function score(P)
|
||||
if s~=3 then E.fall=E.fall-1 end
|
||||
D.target=D.target+100
|
||||
elseif s<10 then
|
||||
if s==5 then BGM.play('distortion')end
|
||||
P:showTextF(text.stage:gsub("$1",s),0,-120,60,'fly',1.26)
|
||||
if s==4 or s==7 then E.das=E.das-1 end
|
||||
s=s%3
|
||||
if s==0 then E.lock=E.lock-1
|
||||
elseif s==1 then E.wait=E.wait-1
|
||||
elseif s==2 then E.fall=E.fall-1
|
||||
if s%3==0 then E.lock=E.lock-1
|
||||
elseif s%3==1 then E.wait=E.wait-1
|
||||
elseif s%3==2 then E.fall=E.fall-1
|
||||
end
|
||||
D.target=D.target+100
|
||||
else
|
||||
@@ -53,7 +53,7 @@ return{
|
||||
end,
|
||||
freshLimit=15,
|
||||
easyFresh=false,bone=true,
|
||||
bg='lightning',bgm='distortion',
|
||||
bg='lightning',bgm='rectification',
|
||||
},
|
||||
slowMark=true,
|
||||
load=function()
|
||||
|
||||
@@ -75,7 +75,7 @@ local function _parse(res)
|
||||
if mesType[res.type]then
|
||||
return res
|
||||
else
|
||||
MES.new('warn',("%s: %s"):format(res.type or"[?]",res.reason or"[NO Message]"))
|
||||
MES.new('warn',("[%s] %s"):format(res.type or"?",res.reason or"[NO Message]"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -65,7 +65,22 @@ local posLists={
|
||||
local posList
|
||||
local function _placeSort(a,b)return a.place<b.place end
|
||||
|
||||
local PLYlist,PLYmap={},{}
|
||||
local netPLY
|
||||
|
||||
local nullIndex={
|
||||
__index=function(self,k)
|
||||
MES.new('error',"User not loaded: "..k)
|
||||
netPLY.add{
|
||||
uid=k,
|
||||
username="Stacker",
|
||||
sid=-1,
|
||||
mode=0,
|
||||
config="",
|
||||
}
|
||||
return self[k]
|
||||
end
|
||||
}
|
||||
local PLYlist,PLYmap=setmetatable({},nullIndex),setmetatable({},nullIndex)
|
||||
local function freshPos()
|
||||
table.sort(PLYlist,_placeSort)
|
||||
if #PLYlist<=5 then
|
||||
@@ -80,7 +95,7 @@ local function freshPos()
|
||||
posList=posLists[5]
|
||||
end
|
||||
end
|
||||
local netPLY={
|
||||
netPLY={
|
||||
list=PLYlist,
|
||||
map=PLYmap,
|
||||
freshPos=freshPos,
|
||||
@@ -90,10 +105,17 @@ function netPLY.clear()
|
||||
TABLE.cut(PLYlist)
|
||||
TABLE.clear(PLYmap)
|
||||
end
|
||||
function netPLY.add(p)
|
||||
p.connected=false
|
||||
p.place=1e99
|
||||
p.stat=false
|
||||
function netPLY.add(d)
|
||||
local p={
|
||||
uid=d.uid,
|
||||
username=d.username,
|
||||
sid=d.sid,
|
||||
mode=d.mode,
|
||||
config=d.config,
|
||||
connected=false,
|
||||
place=1e99,
|
||||
stat=false,
|
||||
}
|
||||
local a=rnd()*6.2832
|
||||
p.x,p.y,p.w,p.h=640+2600*cos(a),360+2600*sin(a),47,47
|
||||
|
||||
@@ -104,7 +126,7 @@ end
|
||||
function netPLY.remove(sid)
|
||||
for i=1,#PLYlist do
|
||||
if PLYlist[i].sid==sid then
|
||||
PLYmap[PLYlist[i].sid]=nil
|
||||
PLYmap[PLYlist[i].uid]=nil
|
||||
rem(PLYlist,i)
|
||||
freshPos()
|
||||
break
|
||||
@@ -191,12 +213,17 @@ function netPLY.draw()
|
||||
gc_translate(p.x,p.y)
|
||||
--Rectangle
|
||||
gc_setColor(COLOR[
|
||||
p.mode==0 and'Z'or
|
||||
p.mode==1 and(p.connected and"N"or"G")or
|
||||
p.mode==2 and(p.connected and"Y"or"F")
|
||||
p.mode==0 and'lH'or
|
||||
p.mode==1 and'N'or
|
||||
p.mode==2 and'F'
|
||||
])
|
||||
gc_setLineWidth(2)
|
||||
gc_rectangle('line',0,0,p.w,p.h)
|
||||
if p.connected then
|
||||
local c=COLOR[p.mode==1 and'N'or'F']
|
||||
gc_setColor(c[1],c[2],c[3],.26)
|
||||
gc_rectangle('fill',0,0,p.w,p.h)
|
||||
end
|
||||
|
||||
--Stencil
|
||||
stencilW,stencilH=p.w,p.h
|
||||
|
||||
@@ -109,4 +109,5 @@ return{
|
||||
{font=25,name="凌月"},
|
||||
{font=25,name="e"},
|
||||
{font=25,name="爱吃麻薯的幽幽子"},
|
||||
{font=25,name="[*梅]"},
|
||||
}
|
||||
@@ -205,16 +205,68 @@ local function drawFXs(P)
|
||||
gc_rectangle('fill',150-x*150,15-S[1]*30-y*15,300*x,y*30)
|
||||
end
|
||||
end
|
||||
local function drawGhost(P,clr,alpha)
|
||||
gc_setColor(1,1,1,alpha)
|
||||
local texture=SKIN.curText
|
||||
local CB=P.cur.bk
|
||||
for i=1,#CB do for j=1,#CB[1]do
|
||||
if CB[i][j]then
|
||||
gc_draw(texture[clr],30*(j+P.curX-1)-30,-30*(i+P.ghoY-1))
|
||||
end
|
||||
end end
|
||||
end
|
||||
local drawGhost={
|
||||
color=function(P,clr,alpha)
|
||||
gc_setColor(1,1,1,alpha)
|
||||
local texture=SKIN.curText
|
||||
local CB=P.cur.bk
|
||||
for i=1,#CB do for j=1,#CB[1]do
|
||||
if CB[i][j]then
|
||||
gc_draw(texture[clr],30*(j+P.curX-1)-30,-30*(i+P.ghoY-1))
|
||||
end
|
||||
end end
|
||||
end,
|
||||
gray=function(P,_,alpha)
|
||||
gc_setColor(1,1,1,alpha)
|
||||
local texture=SKIN.curText
|
||||
local CB=P.cur.bk
|
||||
for i=1,#CB do for j=1,#CB[1]do
|
||||
if CB[i][j]then
|
||||
gc_draw(texture[21],30*(j+P.curX-1)-30,-30*(i+P.ghoY-1))
|
||||
end
|
||||
end end
|
||||
end,
|
||||
colorLine=function(P,clr,alpha)
|
||||
clr=minoColor[clr]
|
||||
gc_setColor(clr[1],clr[2],clr[3],alpha)
|
||||
gc_setLineWidth(4)
|
||||
local CB=P.cur.bk
|
||||
for i=1,#CB do for j=1,#CB[1]do
|
||||
if CB[i][j]then
|
||||
gc_rectangle('line',30*(j+P.curX-1)-30+2,-30*(i+P.ghoY-1)+2,26,26)
|
||||
end
|
||||
end end
|
||||
end,
|
||||
grayLine=function(P,_,alpha)
|
||||
gc_setColor(1,1,1,alpha)
|
||||
gc_setLineWidth(4)
|
||||
local CB=P.cur.bk
|
||||
for i=1,#CB do for j=1,#CB[1]do
|
||||
if CB[i][j]then
|
||||
gc_rectangle('line',30*(j+P.curX-1)-30+2,-30*(i+P.ghoY-1)+2,26,26)
|
||||
end
|
||||
end end
|
||||
end,
|
||||
colorCell=function(P,clr,alpha)
|
||||
clr=minoColor[clr]
|
||||
gc_setColor(clr[1],clr[2],clr[3],alpha)
|
||||
local CB=P.cur.bk
|
||||
for i=1,#CB do for j=1,#CB[1]do
|
||||
if CB[i][j]then
|
||||
gc_rectangle('fill',30*(j+P.curX-1)-30,-30*(i+P.ghoY-1),30,30)
|
||||
end
|
||||
end end
|
||||
end,
|
||||
greyCell=function(P,_,alpha)
|
||||
gc_setColor(1,1,1,alpha)
|
||||
local CB=P.cur.bk
|
||||
for i=1,#CB do for j=1,#CB[1]do
|
||||
if CB[i][j]then
|
||||
gc_rectangle('fill',30*(j+P.curX-1)-30,-30*(i+P.ghoY-1),30,30)
|
||||
end
|
||||
end end
|
||||
end,
|
||||
}
|
||||
local function drawBlockOutline(P,texture,trans)
|
||||
shader_alpha:send("a",trans)
|
||||
gc_setShader(shader_alpha)
|
||||
@@ -268,6 +320,10 @@ local function drawBuffer(P)
|
||||
--Timing
|
||||
gc_setColor(attackColor[A.lv][1])
|
||||
gc_rectangle('fill',303,599-h,11,-bar)
|
||||
gc_setColor(1,1,1)
|
||||
for j=30,A.cd0-30,30 do
|
||||
gc_rectangle('fill',303,599-h-bar*(j/A.cd0),6,2)
|
||||
end
|
||||
gc_setColor(attackColor[A.lv][2])
|
||||
gc_rectangle('fill',303,599-h-bar,11,bar*(1-A.countdown/A.cd0))
|
||||
else
|
||||
@@ -611,7 +667,7 @@ function draw.norm(P)
|
||||
|
||||
--Draw ghost & rotation center
|
||||
if ENV.ghost then
|
||||
drawGhost(P,curColor,ENV.ghost)
|
||||
drawGhost[ENV.ghostType](P,curColor,ENV.ghost)
|
||||
if ENV.center then
|
||||
gc_setColor(1,1,1,ENV.center)
|
||||
gc_draw(spinCenterImg,centerX,-30*(P.ghoY+P.cur.sc[1])+15,nil,nil,nil,4,4)
|
||||
@@ -819,7 +875,7 @@ function draw.demo(P)
|
||||
drawField(P)
|
||||
drawFXs(P)
|
||||
if P.cur and P.waiting==-1 then
|
||||
if ENV.ghost then drawGhost(P,curColor,ENV.ghost)end
|
||||
if ENV.ghost then drawGhost[ENV.ghostType](P,curColor,ENV.ghost)end
|
||||
if ENV.block then
|
||||
local dy=ENV.smooth and P.ghoY~=P.curY and(P.dropDelay/ENV.drop-1)*30 or 0
|
||||
gc_translate(0,-dy)
|
||||
|
||||
@@ -5,6 +5,7 @@ return{
|
||||
ihs=true,irs=true,ims=true,
|
||||
swap=true,
|
||||
|
||||
ghostType='gray',
|
||||
block=true,ghost=.3,center=1,
|
||||
smooth=false,grid=.16,
|
||||
upEdge=true,
|
||||
|
||||
@@ -1867,7 +1867,7 @@ function Player:act_hardDrop()
|
||||
self.keyPressing[6]=false
|
||||
elseif self.control and self.waiting==-1 and self.cur then
|
||||
if self.lastPiece.autoLock and self.frameRun-self.lastPiece.frame<ENV.dropcut then
|
||||
SFX.play('drop_cancel')
|
||||
SFX.play('drop_cancel',.3)
|
||||
else
|
||||
if self.curY>self.ghoY then
|
||||
local CB=self.cur.bk
|
||||
|
||||
@@ -295,7 +295,7 @@ local commands={}do
|
||||
|
||||
--System
|
||||
commands.crash={
|
||||
code=error,
|
||||
code=function()error("ERROR")end,
|
||||
description="Manually crash the game",
|
||||
}
|
||||
commands.mes={
|
||||
@@ -311,24 +311,16 @@ local commands={}do
|
||||
else
|
||||
log{C.A,"Show a message on the up-left corner"}
|
||||
log""
|
||||
log{C.A,"Usage: mes <check|info|broadcast|warn|error> [message]"}
|
||||
log{C.A,"Usage: mes <check|info|broadcast|warn|error>"}
|
||||
end
|
||||
end,
|
||||
description="Show a message",
|
||||
details={
|
||||
"Show a message on the up-left corner",
|
||||
"",
|
||||
"Usage: mes <check|info|warn|error> [message]",
|
||||
"Usage: mes <check|info|warn|error>",
|
||||
},
|
||||
}
|
||||
commands.warn={
|
||||
code=function(str)MES.new('warn',str,6)end,
|
||||
description="Show a warn message",
|
||||
}
|
||||
commands.error={
|
||||
code=function(str)MES.new('error',str,6)end,
|
||||
description="Show an error message",
|
||||
}
|
||||
commands.openurl={
|
||||
code=function(url)
|
||||
if url~=""then
|
||||
|
||||
@@ -177,7 +177,7 @@ function scene.draw()
|
||||
--Confirm reset
|
||||
if sure>0 then
|
||||
gc.setColor(1,1,1,sure*.02)
|
||||
gc.draw(TEXTURE.question,920,50)
|
||||
gc.draw(TEXTURE.sure,920,50)
|
||||
end
|
||||
gc.translate(0, WIDGET.scrollPos)
|
||||
end
|
||||
|
||||
@@ -425,7 +425,7 @@ function scene.draw()
|
||||
--Confirm reset
|
||||
if sure>0 then
|
||||
gc.setColor(1,1,1,sure*.02)
|
||||
gc.draw(TEXTURE.question,1070,490)
|
||||
gc.draw(TEXTURE.sure,1070,490)
|
||||
end
|
||||
|
||||
--Block name
|
||||
|
||||
@@ -181,7 +181,7 @@ function scene.draw()
|
||||
--Confirm reset
|
||||
if sure>0 then
|
||||
gc.setColor(1,1,1,sure*.02)
|
||||
gc.draw(TEXTURE.question,980,600)
|
||||
gc.draw(TEXTURE.sure,980,600)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ function scene.draw()
|
||||
--Confirm reset
|
||||
if sure>0 then
|
||||
gc.setColor(1,1,1,sure*.02)
|
||||
gc.draw(TEXTURE.question,1050,430,nil,.6)
|
||||
gc.draw(TEXTURE.sure,1050,430,nil,.6)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -128,21 +128,14 @@ local loadingThread=coroutine.wrap(function()
|
||||
}YIELD()
|
||||
|
||||
upFloor()
|
||||
for i=1,#MODES do
|
||||
local m=MODES[i]--Mode template
|
||||
local M=require("parts.modes."..m.name)--Mode file
|
||||
MODES[m.name],MODES[i]=M
|
||||
for k,v in next,m do
|
||||
M[k]=v
|
||||
end
|
||||
M.records=FILE.load("record/"..m.name..".rec")or M.score and{}
|
||||
if m.icon then
|
||||
if not modeIcons[m.icon]then
|
||||
modeIcons[m.icon]=gc.newImage("media/image/modeicon/"..m.icon..".png")
|
||||
for _,M in next,MODES do
|
||||
M.records=FILE.load("record/"..M.name..".rec")or M.score and{}
|
||||
if M.icon then
|
||||
if not modeIcons[M.icon]then
|
||||
modeIcons[M.icon]=gc.newImage("media/image/modeicon/"..M.icon..".png")
|
||||
end
|
||||
M.icon=modeIcons[m.icon]
|
||||
M.icon=modeIcons[M.icon]
|
||||
end
|
||||
if i%5==0 then YIELD()end
|
||||
end
|
||||
|
||||
upFloor()
|
||||
|
||||
@@ -94,7 +94,7 @@ function scene.keyDown(key,isRep)
|
||||
end
|
||||
elseif key==","then
|
||||
if testButton(8)then
|
||||
SCN.go('manual')
|
||||
SCN.go('replays')
|
||||
end
|
||||
elseif key=="2"then
|
||||
if testButton(9)then
|
||||
@@ -182,12 +182,12 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="setting",x=2480,y=210,w=800,h=100, color='lO',font=40,align='L',edge=30,code=pressKey"-"},
|
||||
WIDGET.newButton{name="stat", x=2480,y=330,w=800,h=100, color='lL',font=40,align='L',edge=30,code=pressKey"p"},
|
||||
WIDGET.newButton{name="dict", x=2480,y=450,w=800,h=100, color='lG',font=40,align='L',edge=30,code=pressKey"l"},
|
||||
WIDGET.newButton{name="manual", x=2480,y=570,w=800,h=100, color='lC',font=40,align='L',edge=30,code=pressKey","},
|
||||
WIDGET.newButton{name="replays",x=2480,y=570,w=800,h=100, color='lC',font=40,align='L',edge=30,code=pressKey","},
|
||||
|
||||
WIDGET.newButton{name="music", x=130,y=80,w=200,h=90, color='lO',font=35,code=pressKey"2"},
|
||||
WIDGET.newButton{name="lang", x=300,y=80,w=90,h=90, color='lN',font=40,code=pressKey"3",fText=TEXTURE.language},
|
||||
WIDGET.newButton{name="about", x=-110,y=670,w=600,h=70, color='lB',font=35,align='R',edge=30,code=pressKey"x",fText=TEXTURE.info},
|
||||
WIDGET.newButton{name="back", x=1390,y=670,w=600,h=70, color='lR',fText=TEXTURE.back,align='L',edge=30,code=backScene},
|
||||
WIDGET.newButton{name="manual", x=1390,y=670,w=600,h=70, color='lR',fText=TEXTURE.question,align='L',edge=30,code=goScene'manual'},
|
||||
}
|
||||
|
||||
return scene
|
||||
@@ -22,7 +22,7 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="marathon",x=640,y=480,w=260,font=50,code=function()loadGame('marathon_n',true)end},
|
||||
WIDGET.newButton{name="setting",x=1000,y=400,w=120,fText=TEXTURE.setting,font=50,code=goScene'setting_game'},
|
||||
WIDGET.newButton{name="lang", x=1000,y=560,w=120,fText=TEXTURE.language,font=40,code=goScene'lang'},
|
||||
WIDGET.newButton{name="manual", x=1160,y=400,w=120,fText=TEXTURE.question,font=80,code=goScene'manual'},
|
||||
WIDGET.newButton{name="manual", x=1160,y=400,w=120,fText=TEXTURE.sure,font=80,code=goScene'manual'},
|
||||
WIDGET.newButton{name="quit", x=1160,y=560,w=120,fText=TEXTURE.quit,font=70,code=function()VOC.play('bye')SCN.swapTo('quit','slowFade')end},
|
||||
}
|
||||
|
||||
|
||||
@@ -288,13 +288,13 @@ function scene.draw()
|
||||
--Ready & Set mark
|
||||
setFont(50)
|
||||
if NET.roomReadyState=='allReady'then
|
||||
gc_setColor(0,1,.5,.9)
|
||||
gc_setColor(1,.85,.6,.9)
|
||||
mStr(text.ready,640,15)
|
||||
elseif NET.roomReadyState=='connecting'then
|
||||
gc_setColor(.1,1,.8,.9)
|
||||
gc_setColor(.6,1,.9,.9)
|
||||
mStr(text.connStream,640,15)
|
||||
elseif NET.roomReadyState=='waitConn'then
|
||||
gc_setColor(0,.8,1,.9)
|
||||
gc_setColor(.6,.95,1,.9)
|
||||
mStr(text.waitStream,640,15)
|
||||
end
|
||||
|
||||
|
||||
@@ -13,9 +13,10 @@ local compatibleVer={
|
||||
"V0.15.2",
|
||||
"V0.15.3",
|
||||
"V0.15.4",
|
||||
"V0.15.5",
|
||||
}
|
||||
|
||||
local roomList=WIDGET.newListBox{name="roomList",x=50,y=50,w=800,h=440,lineH=40,drawF=function(ifSel,id,item)
|
||||
local roomList=WIDGET.newListBox{name="roomList",x=50,y=50,w=800,h=440,lineH=40,drawF=function(item,id,ifSel)
|
||||
setFont(35)
|
||||
if ifSel then
|
||||
gc_setColor(1,1,1,.3)
|
||||
@@ -29,7 +30,7 @@ local roomList=WIDGET.newListBox{name="roomList",x=50,y=50,w=800,h=440,lineH=40,
|
||||
gc_print(id,45,-4)
|
||||
|
||||
if item.start then
|
||||
gc_setColor(0,.4,.1)
|
||||
gc_setColor(.1,.5,.2)
|
||||
else
|
||||
gc_setColor(1,1,.7)
|
||||
end
|
||||
@@ -114,13 +115,13 @@ function scene.draw()
|
||||
gc_setColor(1,1,.7)
|
||||
gc_printf(R.roomInfo.name,10,0,365)
|
||||
setFont(20)
|
||||
gc_setColor(.8,.8,.8)
|
||||
gc_setColor(COLOR.lH)
|
||||
gc_printf(R.roomInfo.description or"[No description]",10,55,365)
|
||||
if R.start then
|
||||
gc_setColor(0,1,.2)
|
||||
gc_setColor(COLOR.lA)
|
||||
gc_print(text.started,10,300)
|
||||
end
|
||||
gc_setColor(1,.2,0)
|
||||
gc_setColor(COLOR.lN)
|
||||
gc_printf(R.roomInfo.version,10,300,365,'right')
|
||||
gc_translate(-870,-220)
|
||||
end
|
||||
@@ -138,9 +139,9 @@ scene.widgetList={
|
||||
WIDGET.newKey{name="setting",fText=TEXTURE.setting,x=1200,y=160,w=90,h=90,code=pressKey"s"},
|
||||
WIDGET.newText{name="refreshing",x=450,y=240,font=45,hideF=function()return not NET.getlock('fetchRoom')end},
|
||||
WIDGET.newText{name="noRoom", x=450,y=245,font=40,hideF=function()return roomList:getLen()>0 or NET.getlock('fetchRoom')end},
|
||||
WIDGET.newKey{name="refresh", x=250,y=630,w=140,h=120,font=35,code=fetchRoom,hideF=function()return fetchTimer>7 end},
|
||||
WIDGET.newKey{name="new", x=510,y=630,w=260,h=120,font=30,code=pressKey"n"},
|
||||
WIDGET.newKey{name="join", x=780,y=630,w=140,h=120,font=40,code=pressKey"return",hideF=function()return roomList:getLen()==0 or NET.getlock('enterRoom')end},
|
||||
WIDGET.newKey{name="refresh", x=250,y=630,w=140,h=120,code=fetchRoom,hideF=function()return fetchTimer>7 end},
|
||||
WIDGET.newKey{name="new", x=510,y=630,w=260,h=120,code=pressKey"n"},
|
||||
WIDGET.newKey{name="join", x=780,y=630,w=140,h=120,code=pressKey"return",hideF=function()return roomList:getLen()==0 or NET.getlock('enterRoom')end},
|
||||
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
|
||||
}
|
||||
|
||||
|
||||
@@ -130,11 +130,15 @@ function scene.keyDown(key,isRep)
|
||||
elseif key=="escape"then
|
||||
SCN.swapTo(GAME.result and'game'or'depause','none')
|
||||
elseif key=="s"then
|
||||
GAME.prevBG=BG.cur
|
||||
SCN.go('setting_sound')
|
||||
if not GAME.fromRepMenu then
|
||||
GAME.prevBG=BG.cur
|
||||
SCN.go('setting_sound')
|
||||
end
|
||||
elseif key=="r"then
|
||||
resetGameData()
|
||||
SCN.swapTo('game','none')
|
||||
if not GAME.fromRepMenu then
|
||||
resetGameData()
|
||||
SCN.swapTo('game','none')
|
||||
end
|
||||
elseif key=="p"then
|
||||
if(GAME.result or GAME.replaying)and #PLAYERS==1 then
|
||||
resetGameData('r')
|
||||
@@ -142,8 +146,9 @@ function scene.keyDown(key,isRep)
|
||||
end
|
||||
elseif key=="o"then
|
||||
if(GAME.result or GAME.replaying)and #PLAYERS==1 and not GAME.saved then
|
||||
if DATA.saveRecording()then
|
||||
if DATA.saveReplay()then
|
||||
GAME.saved=true
|
||||
SFX.play('connected')
|
||||
end
|
||||
end
|
||||
else
|
||||
@@ -308,11 +313,11 @@ function scene.draw()
|
||||
end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newButton{name="setting", x=1120,y=70,w=240,h=90, color='lB',code=pressKey"s"},
|
||||
WIDGET.newButton{name="setting", x=1120,y=70,w=240,h=90, color='lB',code=pressKey"s",hideF=function()return GAME.fromRepMenu end},
|
||||
WIDGET.newButton{name="replay", x=535,y=250,w=200,h=100,color='lY',code=pressKey"p",hideF=function()return not(GAME.result or GAME.replaying)or #PLAYERS>1 end},
|
||||
WIDGET.newButton{name="save", x=745,y=250,w=200,h=100,color='G',code=pressKey"o",hideF=function()return not(GAME.result or GAME.replaying)or #PLAYERS>1 or GAME.saved end},
|
||||
WIDGET.newButton{name="save", x=745,y=250,w=200,h=100,color='lP',code=pressKey"o",hideF=function()return not(GAME.result or GAME.replaying)or #PLAYERS>1 or GAME.saved end},
|
||||
WIDGET.newButton{name="resume", x=640,y=367,w=240,h=100,color='lG',code=pressKey"escape"},
|
||||
WIDGET.newButton{name="restart", x=640,y=483,w=240,h=100,color='lR',code=pressKey"r"},
|
||||
WIDGET.newButton{name="restart", x=640,y=483,w=240,h=100,color='lR',code=pressKey"r",hideF=function()return GAME.fromRepMenu end},
|
||||
WIDGET.newButton{name="quit", x=640,y=600,w=240,h=100,font=35,code=backScene},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,116 @@
|
||||
local gc=love.graphics
|
||||
local gc_setColor=gc.setColor
|
||||
local gc_draw,gc_rectangle=gc.draw,gc.rectangle
|
||||
local gc_print,gc_printf=gc.print,gc.printf
|
||||
|
||||
local setFont=setFont
|
||||
|
||||
local listBox=WIDGET.newListBox{name="list",x=50,y=50,w=1200,h=520,lineH=40,drawF=function(rep,id,ifSel)
|
||||
if ifSel then
|
||||
gc_setColor(1,1,1,.3)
|
||||
gc_rectangle('fill',0,0,1200,40)
|
||||
end
|
||||
|
||||
setFont(30)
|
||||
gc_setColor(.8,.8,.8)
|
||||
gc_print(id,10,-2)
|
||||
|
||||
if rep.available then
|
||||
gc_setColor(.9,.9,1)
|
||||
local modeName=text.modes[rep.mode]
|
||||
gc_print(modeName and modeName[1].." "..modeName[2]or rep.mode,310,-2)
|
||||
setFont(20)
|
||||
gc_setColor(1,1,.8)
|
||||
gc_print(rep.date,80,6)
|
||||
gc_setColor(1,.4,.4,.6)
|
||||
gc_printf(rep.version,0,6,1190,'right')
|
||||
gc_setColor(1,1,1)
|
||||
gc_printf(rep.player,0,6,960,'right')
|
||||
else
|
||||
gc_setColor(.6,.6,.6)
|
||||
gc_print(rep.fileName,80,-2)
|
||||
end
|
||||
end}
|
||||
|
||||
local scene={}
|
||||
|
||||
local sure
|
||||
|
||||
local function replay(fileName)
|
||||
local rep=DATA.parseReplay(fileName,true)
|
||||
if not rep.available then
|
||||
MES.new('error',text.replayBroken)
|
||||
elseif MODES[rep.mode]then
|
||||
GAME.seed=rep.seed
|
||||
GAME.setting=rep.setting
|
||||
GAME.mod=rep.mod
|
||||
GAME.rep={}
|
||||
DATA.pumpRecording(rep.data,GAME.rep)
|
||||
|
||||
loadGame(rep.mode,true)
|
||||
resetGameData('r')
|
||||
GAME.init=false
|
||||
GAME.saved=true
|
||||
GAME.fromRepMenu=true
|
||||
else
|
||||
MES.new('error',("No mode id: [%s]"):format(rep.mode))
|
||||
end
|
||||
end
|
||||
|
||||
function scene.sceneInit()
|
||||
sure=0
|
||||
listBox:setList(REPLAY)
|
||||
end
|
||||
|
||||
function scene.keyDown(key)
|
||||
if key=="return"then
|
||||
local rep=listBox:getSel()
|
||||
if rep then
|
||||
replay(rep.fileName)
|
||||
end
|
||||
elseif key=="escape"then
|
||||
SCN.back()
|
||||
elseif key=="delete"then
|
||||
local rep=listBox:getSel()
|
||||
if rep then
|
||||
if sure>20 then
|
||||
sure=0
|
||||
listBox:remove()
|
||||
love.filesystem.remove(rep.fileName)
|
||||
for i=1,#REPLAY do
|
||||
if REPLAY[i].fileName==rep.fileName then
|
||||
table.remove(REPLAY,i)
|
||||
break
|
||||
end
|
||||
end
|
||||
SFX.play('finesseError',.7)
|
||||
else
|
||||
sure=50
|
||||
end
|
||||
end
|
||||
else
|
||||
WIDGET.keyPressed(key)
|
||||
end
|
||||
end
|
||||
|
||||
function scene.update()
|
||||
if sure>0 then sure=sure-1 end
|
||||
end
|
||||
|
||||
function scene.draw()
|
||||
--Confirm delete
|
||||
if sure>0 then
|
||||
gc_setColor(1,1,1,sure*.02)
|
||||
gc_draw(TEXTURE.sure,910,610)
|
||||
end
|
||||
end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
|
||||
listBox,
|
||||
WIDGET.newButton{name="play",x=700,y=640,w=170,h=80,color='lY',code=pressKey"return",hideF=function()return listBox:getLen()==0 end,fText=DOGC{50,50,{'fPoly',10,0,49,24,10,49}}},
|
||||
WIDGET.newButton{name="delete",x=850,y=640,w=80,h=80,color='lR',code=pressKey"delete",hideF=function()return listBox:getLen()==0 end,fText=DOGC{50,50,{'setLW',8},{'line',5,5,45,45},{'line',5,45,45,5}}},
|
||||
WIDGET.newButton{name="back",x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
|
||||
WIDGET.newButton{name="back",x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
|
||||
}
|
||||
|
||||
return scene
|
||||
@@ -18,6 +18,7 @@ function scene.draw()
|
||||
gc.draw(SKIN.curText[b%16+1],410,540,t%6.2832,2,nil,15,15)
|
||||
end
|
||||
|
||||
scene.widgetScrollHeight=200
|
||||
scene.widgetList={
|
||||
WIDGET.newText{name="title", x=640,y=15,font=80},
|
||||
|
||||
@@ -33,7 +34,7 @@ scene.widgetList={
|
||||
WIDGET.newSwitch{name="autoPause", x=1060, y=310, disp=SETval("autoPause"), code=SETrev("autoPause")},
|
||||
WIDGET.newSwitch{name="swap", x=1060, y=380, disp=SETval("swap"), code=SETrev("swap")},
|
||||
WIDGET.newSwitch{name="fine", x=1060, y=450, disp=SETval("fine"), code=function()SETTING.fine=not SETTING.fine if SETTING.fine then SFX.play('finesseError',.6)end end},
|
||||
WIDGET.newSwitch{name="simpMode", x=1060, y=520, disp=SETval("simpMode"),
|
||||
WIDGET.newSwitch{name="simpMode", x=500, y=800, disp=SETval("simpMode"),
|
||||
code=function()
|
||||
SETTING.simpMode=not SETTING.simpMode
|
||||
for i=1,#SCN.stack,2 do
|
||||
|
||||
@@ -15,36 +15,37 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="game", x=1080,y=80,w=240,h=80,color='lC',font=35,code=swapScene('setting_game','swipeL')},
|
||||
|
||||
WIDGET.newSwitch{name="block", x=380,y=180,disp=SETval("block"),code=SETrev("block")},
|
||||
WIDGET.newSwitch{name="smooth", x=380,y=230,disp=SETval("smooth"),code=SETrev("smooth")},
|
||||
WIDGET.newSwitch{name="upEdge", x=380,y=280,disp=SETval("upEdge"),code=SETrev("upEdge")},
|
||||
WIDGET.newSwitch{name="bagLine", x=380,y=330,disp=SETval("bagLine"),code=SETrev("bagLine")},
|
||||
WIDGET.newSwitch{name="smooth", x=380,y=250,disp=SETval("smooth"),code=SETrev("smooth")},
|
||||
WIDGET.newSwitch{name="upEdge", x=380,y=320,disp=SETval("upEdge"),code=SETrev("upEdge")},
|
||||
WIDGET.newSwitch{name="bagLine", x=380,y=390,disp=SETval("bagLine"),code=SETrev("bagLine")},
|
||||
|
||||
WIDGET.newSlider{name="ghost", x=740,y=180,w=350,unit=.6, disp=SETval("ghost"),show="percent",code=SETsto("ghost")},
|
||||
WIDGET.newSlider{name="grid", x=740,y=260,w=350,unit=.4, disp=SETval("grid"),show="percent", code=SETsto("grid")},
|
||||
WIDGET.newSlider{name="center", x=740,y=340,w=350,unit=1, disp=SETval("center"), code=SETsto("center")},
|
||||
WIDGET.newSelector{name="ghostType",x=915,y=180,w=350,list={'color','gray','colorLine','grayLine','colorCell','greyCell'},disp=SETval("ghostType"),code=SETsto("ghostType")},
|
||||
WIDGET.newSlider{name="ghost", x=740,y=240,w=350,unit=1, disp=SETval("ghost"),show="percent",code=SETsto("ghost")},
|
||||
WIDGET.newSlider{name="grid", x=740,y=320,w=350,unit=.4, disp=SETval("grid"),show="percent", code=SETsto("grid")},
|
||||
WIDGET.newSlider{name="center", x=740,y=400,w=350,unit=1, disp=SETval("center"), code=SETsto("center")},
|
||||
|
||||
WIDGET.newSlider{name="lockFX", x=330,y=400,w=540,unit=5, disp=SETval("lockFX"), code=SETsto("lockFX")},
|
||||
WIDGET.newSlider{name="dropFX", x=330,y=460,w=540,unit=5, disp=SETval("dropFX"), code=SETsto("dropFX")},
|
||||
WIDGET.newSlider{name="moveFX", x=330,y=520,w=540,unit=5, disp=SETval("moveFX"), code=SETsto("moveFX")},
|
||||
WIDGET.newSlider{name="clearFX", x=330,y=580,w=540,unit=5, disp=SETval("clearFX"), code=SETsto("clearFX")},
|
||||
WIDGET.newSlider{name="splashFX", x=330,y=640,w=540,unit=5, disp=SETval("splashFX"),code=SETsto("splashFX")},
|
||||
WIDGET.newSlider{name="shakeFX", x=330,y=700,w=540,unit=5, disp=SETval("shakeFX"), code=SETsto("shakeFX")},
|
||||
WIDGET.newSlider{name="atkFX", x=330,y=760,w=540,unit=5, disp=SETval("atkFX"), code=SETsto("atkFX")},
|
||||
WIDGET.newSelector{name="frame", x=600,y=830,w=460,list={8,10,13,17,22,29,37,47,62,80,100},disp=SETval("frameMul"),code=SETsto("frameMul")},
|
||||
WIDGET.newSlider{name="lockFX", x=330,y=460,w=540,unit=5, disp=SETval("lockFX"), code=SETsto("lockFX")},
|
||||
WIDGET.newSlider{name="dropFX", x=330,y=520,w=540,unit=5, disp=SETval("dropFX"), code=SETsto("dropFX")},
|
||||
WIDGET.newSlider{name="moveFX", x=330,y=580,w=540,unit=5, disp=SETval("moveFX"), code=SETsto("moveFX")},
|
||||
WIDGET.newSlider{name="clearFX", x=330,y=640,w=540,unit=5, disp=SETval("clearFX"), code=SETsto("clearFX")},
|
||||
WIDGET.newSlider{name="splashFX", x=330,y=700,w=540,unit=5, disp=SETval("splashFX"),code=SETsto("splashFX")},
|
||||
WIDGET.newSlider{name="shakeFX", x=330,y=760,w=540,unit=5, disp=SETval("shakeFX"), code=SETsto("shakeFX")},
|
||||
WIDGET.newSlider{name="atkFX", x=330,y=820,w=540,unit=5, disp=SETval("atkFX"), code=SETsto("atkFX")},
|
||||
WIDGET.newSelector{name="frame", x=600,y=890,w=460,list={8,10,13,17,22,29,37,47,62,80,100},disp=SETval("frameMul"),code=SETsto("frameMul")},
|
||||
|
||||
WIDGET.newSwitch{name="text", x=450,y=920,disp=SETval("text"), code=SETrev("text")},
|
||||
WIDGET.newSwitch{name="score", x=450,y=970,disp=SETval("score"), code=SETrev("score")},
|
||||
WIDGET.newSwitch{name="bufferWarn", x=450,y=1040,disp=SETval("bufferWarn"), code=SETrev("bufferWarn")},
|
||||
WIDGET.newSwitch{name="showSpike", x=450,y=1090,disp=SETval("showSpike"), code=SETrev("showSpike")},
|
||||
WIDGET.newSwitch{name="nextPos", x=450,y=1160,disp=SETval("nextPos"), code=SETrev("nextPos")},
|
||||
WIDGET.newSwitch{name="highCam", x=450,y=1210,disp=SETval("highCam"), code=SETrev("highCam")},
|
||||
WIDGET.newSwitch{name="warn", x=450,y=1280,disp=SETval("warn"), code=SETrev("warn")},
|
||||
WIDGET.newSwitch{name="text", x=450,y=980,disp=SETval("text"), code=SETrev("text")},
|
||||
WIDGET.newSwitch{name="score", x=450,y=1030,disp=SETval("score"), code=SETrev("score")},
|
||||
WIDGET.newSwitch{name="bufferWarn", x=450,y=1100,disp=SETval("bufferWarn"), code=SETrev("bufferWarn")},
|
||||
WIDGET.newSwitch{name="showSpike", x=450,y=1150,disp=SETval("showSpike"), code=SETrev("showSpike")},
|
||||
WIDGET.newSwitch{name="nextPos", x=450,y=1220,disp=SETval("nextPos"), code=SETrev("nextPos")},
|
||||
WIDGET.newSwitch{name="highCam", x=450,y=1270,disp=SETval("highCam"), code=SETrev("highCam")},
|
||||
WIDGET.newSwitch{name="warn", x=450,y=1340,disp=SETval("warn"), code=SETrev("warn")},
|
||||
|
||||
WIDGET.newSwitch{name="clickFX", x=950,y=920,disp=SETval("clickFX"), code=SETrev("clickFX")},
|
||||
WIDGET.newSwitch{name="power", x=950,y=1010,disp=SETval("powerInfo"), code=SETrev("powerInfo")},
|
||||
WIDGET.newSwitch{name="clean", x=950,y=1100,disp=SETval("cleanCanvas"),code=SETrev("cleanCanvas")},
|
||||
WIDGET.newSwitch{name="fullscreen", x=950,y=1190,disp=SETval("fullscreen"), code=switchFullscreen},
|
||||
WIDGET.newSwitch{name="bg", x=950,y=1280,disp=SETval("bg"),
|
||||
WIDGET.newSwitch{name="clickFX", x=950,y=980,disp=SETval("clickFX"), code=SETrev("clickFX")},
|
||||
WIDGET.newSwitch{name="power", x=950,y=1070,disp=SETval("powerInfo"), code=SETrev("powerInfo")},
|
||||
WIDGET.newSwitch{name="clean", x=950,y=1160,disp=SETval("cleanCanvas"),code=SETrev("cleanCanvas")},
|
||||
WIDGET.newSwitch{name="fullscreen", x=950,y=1250,disp=SETval("fullscreen"), code=switchFullscreen},
|
||||
WIDGET.newSwitch{name="bg", x=950,y=1340,disp=SETval("bg"),
|
||||
code=function()
|
||||
BG.set('none')
|
||||
SETTING.bg=not SETTING.bg
|
||||
|
||||
@@ -102,7 +102,6 @@ end
|
||||
scene.widgetList={
|
||||
WIDGET.newButton{name="path", x=800,y=540,w=250,h=80,font=25,code=function()love.system.openURL(SAVEDIR)end,hide=MOBILE},
|
||||
WIDGET.newButton{name="save", x=800,y=640,w=250,h=80,font=25,code=goScene'savedata'},
|
||||
WIDGET.newButton{name="replays",x=1100,y=540,w=250,h=80,font=25,code=goScene'replays'},
|
||||
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,9 @@ local function NSC(x,y)--New & Set Canvas
|
||||
end
|
||||
local TEXTURE={}
|
||||
|
||||
|
||||
gc.origin()
|
||||
gc.setDefaultFilter('nearest','nearest')
|
||||
|
||||
|
||||
|
||||
--Mini blocks
|
||||
gc.setColor(1,1,1)
|
||||
TEXTURE.miniBlock={}
|
||||
@@ -64,10 +62,8 @@ for i=0,9 do
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
gc.setDefaultFilter('linear','linear')
|
||||
|
||||
|
||||
--Title image
|
||||
local titleTriangles={}
|
||||
for i=1,8 do titleTriangles[i]=love.math.triangulate(title[i])end
|
||||
@@ -111,8 +107,8 @@ for i=1,8 do
|
||||
gc.translate(-12*i,i==1 and -8 or -14)
|
||||
end
|
||||
|
||||
--Question mark
|
||||
TEXTURE.question=DOGC{48,64,
|
||||
--Sure mark
|
||||
TEXTURE.sure=DOGC{48,64,
|
||||
{'fRect',0,0,10,27},
|
||||
{'fRect',0,0,48,10},
|
||||
{'fRect',38,10,10,15},
|
||||
@@ -154,6 +150,13 @@ TEXTURE.info=DOGC{50,50,
|
||||
{'fRect',22,20,6,20},
|
||||
}
|
||||
|
||||
--Question mark
|
||||
TEXTURE.question=DOGC{50,50,
|
||||
{'setLW',5},
|
||||
{'dCirc',25,25,22},
|
||||
{'print',"?",16,-6},
|
||||
}
|
||||
|
||||
--More mark
|
||||
TEXTURE.more=DOGC{60,15,
|
||||
{'fCirc',10,7,6},
|
||||
|
||||
@@ -19,17 +19,37 @@ return STRING.split([=[
|
||||
Tetra-link; 速算(前缀后缀表达式,二八十六进制)
|
||||
连连看; 求合体; 坦克大战; 扫雷; 接水管
|
||||
其他未来内容:
|
||||
阴影样式; 可调场地宽度; 可调攻击系统; 组队战; 实时数据可视化
|
||||
可调场地宽度; 可调攻击系统; 组队战; 实时数据可视化
|
||||
重做模式选择UI; 重做模组UI; 高级自定义序列
|
||||
XRS; 全部方块位移动画; 更好的手柄支持
|
||||
spike相关统计数据; 模式数据分析
|
||||
手势操作; 特殊控件(虚拟摇杆等)
|
||||
音效包; 手势操作; 特殊控件(虚拟摇杆等)
|
||||
区分各种消除(隔断/架空/混合/彩色/穿墙)
|
||||
更复杂的攻击(数量/可抵消延时/不可抵消延时/反击/攻击/防御/洞数/连接/炸弹/厚度)
|
||||
更细节的DAS选项; 成就系统; 拓展主题系统
|
||||
工程编译到字节码; task-Z(新AI)
|
||||
等级系统; 收集向抽奖玩法; 自适应UI
|
||||
录像回放菜单; 自动跳帧; 多方块; 超60帧
|
||||
自动跳帧; 多方块; 超60帧
|
||||
|
||||
0.15.5: 姿态调整 RCS Control
|
||||
新增:
|
||||
新增录像回放菜单,自动升级旧版本录像格式,可以看以前保存的录像了
|
||||
可选六种阴影样式
|
||||
攻击缓冲条中的攻击显示时间刻度(0.5秒一格)
|
||||
新BGM:Rectification(用于master-final的前500台)
|
||||
改动:
|
||||
玩家准备颜色改为天蓝色,连接成功改为半透明填充
|
||||
MES模块的默认消息类型会带上颜色
|
||||
调整房间内准备状态文本颜色
|
||||
优化sysFX模块绘制性能,新的点击特效
|
||||
极简菜单开关放到屏幕外减少误触
|
||||
减轻误硬降打断音量
|
||||
代码:
|
||||
REPLAY不再需要保存到本地的数据,每次启动自动刷新录像文件列表
|
||||
字符串拓展模块和DATA模块新增方法
|
||||
修复:
|
||||
DOGC模块创建超过系统限制大小的画布导致报错
|
||||
玩家退出房间时移除键错误导致崩溃
|
||||
|
||||
0.15.4: 近地轨道 Low Earth Orbit
|
||||
新增:
|
||||
@@ -55,7 +75,6 @@ return STRING.split([=[
|
||||
修复:
|
||||
c4w模式一直响警报
|
||||
1/30的概率死亡后濒死音效错误播放
|
||||
DOGC模块创建超过系统限制大小的画布导致报错
|
||||
服务器传来警告/错误信息时弹出消息的奇怪格式
|
||||
序列编辑粘贴不当格式数据会导致后续错误
|
||||
开启3D方块时消行特效也会有两个叠在一起
|
||||
|
||||
Reference in New Issue
Block a user