Compare commits

...

45 Commits

Author SHA1 Message Date
MrZ626
cb2f011b19 修复DOGC画布尺寸受限时报错 2021-06-28 16:25:53 +08:00
MrZ626
70871ee4fd 加载TEXTURE模块时强制重置坐标系尝试修复miniBlock材质变形问题 2021-06-28 16:16:46 +08:00
MrZ626
2f7647c5ba 修改更新历史和build号 2021-06-28 16:12:03 +08:00
MrZ626
f536173dea 减轻误硬降打断音量 2021-06-28 16:11:54 +08:00
MrZ626
9488dc61f9 兼容部分特殊存档格式 2021-06-28 16:06:33 +08:00
MrZ626
6f74595305 再次更新录像加载和转换流程 2021-06-28 15:44:50 +08:00
MrZ626
a1f32ca333 添加一些录像文件解析错误的保护 2021-06-28 15:23:09 +08:00
MrZ626
45ab91267f 修复录像播放结束时如果没有段位会报错 2021-06-28 13:36:43 +08:00
MrZ626
3472ccc73d 修改更新历史 2021-06-28 04:03:31 +08:00
MrZ626
a9789b1c21 攻击缓冲条中的攻击显示时间刻度 2021-06-28 04:03:30 +08:00
MrZ626
20095c01d1 微调点击特效粒子尺寸和分布 2021-06-28 04:03:30 +08:00
MrZ626
653b256253 可选六种阴影样式,默认贴图 2021-06-28 03:42:57 +08:00
MrZ626
a9a66bf21e 极简菜单开关放到屏幕外减少误触 2021-06-28 03:21:46 +08:00
MrZ626
2fd310baed 优化sysFX模块绘制性能,修改点击特效 2021-06-28 03:18:29 +08:00
MrZ626
ef94e1bf3a 修改更新历史和build号 2021-06-28 02:55:53 +08:00
MrZ626
fe91265f62 赞助列表添加一位 2021-06-28 02:55:47 +08:00
MrZ626
b8a9c42a3b 新BGM:Rectification(用于master-final的前500台) 2021-06-28 02:55:21 +08:00
MrZ626
b0ecb28b48 升级录像格式,完善录像回放菜单 2021-06-28 02:43:47 +08:00
MrZ626
6cb81b461b listBox:remove最后一个元素时会尝试自动将光标上移防止光标消失 2021-06-28 02:40:43 +08:00
MrZ626
9b44971de8 把dropcut加入录像需要记录的设置(之前忘了) 2021-06-27 20:24:26 +08:00
MrZ626
c8908f38fb 修改几个tip 2021-06-27 20:16:17 +08:00
MrZ626
d7c721ae5b 修改MES模块消息默认底色 2021-06-27 20:14:22 +08:00
MrZ626
4d3d00bc58 控制台移除warn和error命令,修改mes命令说明,修改crash命令效果 2021-06-27 19:01:10 +08:00
MrZ626
5eaeaaa79f 提前LANG.set时机,防止后续FILE模块尝试输出时报错 2021-06-27 14:41:47 +08:00
MrZ626
d77af59521 修复录像文件保存格式错误,多了个换行 2021-06-27 14:09:38 +08:00
MrZ626
b5093d19f4 修改更新历史和build号 2021-06-27 03:18:43 +08:00
MrZ626
ef14e8b38c 调整房间内准备状态文本颜色 2021-06-27 03:18:43 +08:00
MrZ626
0f3c234ca0 整理操作GAME变量的代码,新增录像回放菜单(需要后续测试) 2021-06-27 03:18:43 +08:00
MrZ626
563d820fbe 微调保存录像的流程 2021-06-27 03:18:43 +08:00
MrZ626
d15757dcc2 listBox控件新增pop和remove方法 2021-06-27 03:18:43 +08:00
MrZ626
9d28505140 ws模块添加发送非字符串信息的检测 2021-06-27 02:36:39 +08:00
MrZ626
ce91e75cd2 调整listBox的drawF参数顺序 2021-06-26 21:37:38 +08:00
MrZ626
4809d4193e 修复玩家退出房间时移除的键错误导致崩溃 2021-06-26 21:36:55 +08:00
MrZ_26
9ee310e73f Merge pull request #93 from Not-A-Normal-Robot/patch-1
Fix text inaccuracy in mod menu
2021-06-26 21:35:56 +08:00
Not-A-Normal-Robot
1380fa768c Fixed text inaccuracy in mod menu
![image](https://user-images.githubusercontent.com/76723917/123514347-d0c99680-d6bc-11eb-85dd-2ba90d1fcdf1.png)
0.15.4 made every mod cause the game to be unranked, so this should be changed to:
`Beware, the mods will cause your game to be unranked!`
2021-06-26 20:34:31 +07:00
MrZ626
0ea58e0858 整理代码,添加最新版本兼容 2021-06-26 14:20:48 +08:00
MrZ626
d1c1631bae 尝试防止一个找不到用户对象的报错并展示uid信息 2021-06-26 02:58:37 +08:00
MrZ626
ef2b845837 微调房间列表ui 2021-06-26 02:56:56 +08:00
MrZ626
e252364c59 添加更新日志,修改版本号 2021-06-26 02:37:50 +08:00
MrZ626
bc14c6f625 大爆炸结束方式改为自动,删除旧排行数据 2021-06-26 02:36:56 +08:00
MrZ626
bcc1b25023 调整主菜单按钮和对应图标(移除返回,添加录像回放)(回放暂未实现,只是添加入口) 2021-06-26 02:24:12 +08:00
MrZ626
5f609f41a5 准备颜色改为天蓝色,连接成功由变色改为半透明填充 2021-06-26 02:07:26 +08:00
MrZ626
38589fbebe 调整ws收到警告/错误消息后输出的提醒消息格式 2021-06-26 01:43:36 +08:00
MrZ626
356316aaa3 MES.new会根据部分基础消息类型添加背景色 2021-06-26 01:42:18 +08:00
MrZ626
b554409b32 创建画布失败后会降低尺寸上限然后重试而不是报错 2021-06-26 01:35:20 +08:00
47 changed files with 681 additions and 247 deletions

View File

@@ -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)

View File

@@ -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"

View File

@@ -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},

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"_",

View File

@@ -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

View File

@@ -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

Binary file not shown.

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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?"},
}
}
}

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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="(~~~~)",

View File

@@ -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']= {"全清训练", "普通", "随便打打"},

View File

@@ -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???",

View File

@@ -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']= {"全清训练", "普通", "简易全清题库,熟悉全清定式的组合"},

View File

@@ -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},

View File

@@ -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,
}

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -109,4 +109,5 @@ return{
{font=25,name="凌月"},
{font=25,name="e"},
{font=25,name="爱吃麻薯的幽幽子"},
{font=25,name="[*梅]"},
}

View File

@@ -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)

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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},
}

View File

@@ -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

View File

@@ -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},
}

View File

@@ -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},
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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},
}

View File

@@ -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},

View File

@@ -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方块时消行特效也会有两个叠在一起