Compare commits

...

52 Commits

Author SHA1 Message Date
MrZ626
afa69ce9a4 版本推进 2021-11-27 04:24:41 +08:00
MrZ626
3226c0c831 重构字体模块,支持多字体
控制台应用等宽字体
2021-11-27 04:24:40 +08:00
MrZ626
4e759cad4c ultra模式重开时会重新播放bgm 2021-11-27 02:05:48 +08:00
MrZ626
291795928d 更多的设置修改的时候会触发警告 2021-11-26 21:52:10 +08:00
MrZ626
a1315e7f7f 修复一处遗留逻辑hold和序列生成相关的错误 2021-11-26 21:24:34 +08:00
MrZ626
657bc2b4e0 修正加载文件的时候会因为没有应用语言没法弹出消息而报错 2021-11-26 14:15:42 +08:00
MrZ626
d8b12fc55d 版本推进 2021-11-26 01:48:23 +08:00
MrZ626
6d11367ea4 新BGM:malate(暂未使用) 2021-11-26 01:47:14 +08:00
MrZ626
eb9e741b4f 关于界面的对称40行入口换成堆积模式 2021-11-26 00:59:23 +08:00
MrZ626
c47546d501 微调一些玩家动作逻辑
修复零ARE+非零lineARE的时候ihs失效
2021-11-26 00:55:29 +08:00
MrZ626
11aa178fc1 ultra模式计时器样式改为数字 2021-11-25 19:58:22 +08:00
MrZ626
f3a88ef269 游戏内再次封装saveFile和loadFile函数
原本的FILE模块更独立,不基于全局text变量和报错信息而是直接报错
2021-11-25 17:38:09 +08:00
MrZ626
720dc2131f 字符串扩展模块给默认string库补充两个方法repD和sArg 2021-11-25 17:37:46 +08:00
MrZ626
701ef17ae1 大爆炸改名清版竞速 2021-11-25 14:03:36 +08:00
MrZ626
1a689a5f07 修正当前方块显示条件 2021-11-25 09:57:45 +08:00
MrZ626
ef12ab0cee 版本推进 2021-11-25 02:43:57 +08:00
MrZ626
3d26db7a01 整理代码,修复消行延迟和出块延迟在极小时的错误行为 2021-11-25 02:42:25 +08:00
MrZ626
dd3df9981b TRS的J/L新增一个踢墙 2021-11-25 02:08:53 +08:00
MrZ626
5d04e83529 修正一个赞助id 2021-11-25 01:13:55 +08:00
MrZ626
7ed4626d71 微调logo 2021-11-24 21:34:26 +08:00
MrZ626
ecf5a29a71 添加一个赞助人 2021-11-24 20:36:52 +08:00
MrZ626
1a24b346a0 修正英文文本缺一个holdMode 2021-11-24 20:36:47 +08:00
MrZ626
72d06c7a02 软降n格的键也可以触发深降 2021-11-24 20:26:24 +08:00
MrZ626
26fde8c694 微调默认摇杆参数 2021-11-24 20:17:53 +08:00
MrZ626
8adeb99be7 修正标题图像素材首字母偏低 close #485 2021-11-24 19:39:38 +08:00
MrZ626
c92f15156b 虚拟按键显示开关移至菜单第一页
修改部分不常用设置时会显示警告
2021-11-24 19:33:08 +08:00
MrZ626
63f69d712b 修复自定义房间改不了锁外即死规则 close #484 2021-11-24 11:20:49 +08:00
MrZ626
55a1bd06f3 版本推进 2021-11-24 06:41:51 +08:00
MrZ626
6a29abf7f0 自定义hold数量为0时不显示hold模式选择器,顺便更新创建房间参数ui遗漏 close #483 2021-11-23 22:30:43 +08:00
MrZ626
83bdd9f2c4 【警告:可能有bug,需要测试】
较大规模整理玩家相关代码
较大规模整理玩家相关代码,重构出块延迟和消行延迟逻辑,现在0是真的无延迟,不再有1帧等待了
添加出块延迟打断(即ARE打断)(不包括消行延迟,默认为打断至无穷大,相当于无此功能)
自定义游戏和自定义房间ui跟进
close #471
2021-11-23 20:26:31 +08:00
MrZ626
95879827c8 调整游戏大logo为正体字 2021-11-23 18:13:45 +08:00
MrZ626
2ade518207 调整tip 2021-11-23 00:48:49 +08:00
MrZ626
36c8449e4d 内存过低的提示每次启动最多出现三次 2021-11-23 00:28:08 +08:00
MrZ626
3c04df69f3 移除手柄时自动松开所有按下了的键,整理代码 2021-11-23 00:27:57 +08:00
MrZ626
1224ee9a67 词典的新人引导条目链接向user670的翻译版本 close #482 2021-11-22 23:45:54 +08:00
MrZ626
fdd1d4463a 版本推进 2021-11-22 21:55:58 +08:00
MrZ626
940ac3736c 整理框架代码
整理手柄的摇杆/扳机支持代码
2021-11-22 15:59:57 +08:00
user670
d38897b54d (Experimental) Support controller axises, closes #466 (#477)
* (Experimental) Support controller axises

* Remove redundant variable; use more readable key event names

* Remove redundant comment; fix typo
2021-11-22 15:52:51 +08:00
MrZ626
90848c6654 全局默认使用5帧窒息延迟 2021-11-22 12:48:02 +08:00
NOT_A_ROBOT
0220d5aefc Make Strategy Ultimate have rhombus outline (#481) 2021-11-22 11:08:13 +08:00
MrZ626
f42032df07 更新赞助名单 2021-11-22 11:04:32 +08:00
MrZ626
05d7eb60bc 修正一处拼写问题导致报错消息识别错误 2021-11-21 21:45:37 +08:00
MrZ626
942416317c 小程序arm添加计时器和重置按钮,删除测试用的跳过按钮 2021-11-21 20:18:42 +08:00
MrZ626
576de945fb 添加一打tip 2021-11-21 05:25:55 +08:00
MrZ626
8b02084428 修复bgm模块清缓存导致报错 2021-11-21 05:11:01 +08:00
MrZ626
9f666d69db 调整大爆炸模式模板 2021-11-21 03:52:13 +08:00
MrZ626
a4c52d9162 修正玩家创建任务第一次初始化运行的时候报错没有任何提示 2021-11-21 03:08:34 +08:00
MrZ626
592b11366e table扩展模块新增两个去重方法和反转方法 2021-11-21 03:06:00 +08:00
MrZ626
07f50b9243 调整一些文本文件 2021-11-20 03:39:05 +08:00
MrZ626
ec74d55686 整理代码 2021-11-20 03:28:58 +08:00
MrZ626
4518513e87 应用1的语音偏移半径 2021-11-20 03:28:19 +08:00
MrZ626
7df4e2144f 语音模块支持设置轻微随机音调偏移半径(默认关闭) 2021-11-20 03:27:53 +08:00
68 changed files with 2051 additions and 1685 deletions

View File

@@ -40,10 +40,17 @@ local function check_curFadeOut(task,code,src)
return task.code==code and task.args[1]==src return task.code==code and task.args[1]==src
end end
local function _tryReleaseSources() local function _tryReleaseSources()
local n=#lastLoaded
while #lastLoaded>maxLoadedCount do while #lastLoaded>maxLoadedCount do
local n=lastLoaded[#lastLoaded] local name=lastLoaded[n]
SourceObjList[n].source=SourceObjList[n].source:release()and nil if SourceObjList[name].source:isPlaying()then
table.remove(lastLoaded) n=n-1
if n<=0 then return end
else
SourceObjList[name].source=SourceObjList[name].source:release()and nil
table.remove(lastLoaded,n)
return
end
end end
end end
function BGM.setDefault(bgm) function BGM.setDefault(bgm)
@@ -57,8 +64,16 @@ function BGM.setChange(func)
BGM.onChange=func BGM.onChange=func
end end
function BGM.setVol(v) function BGM.setVol(v)
assert(type(v)=='number'and v>=0 and v<=1) assert(type(v)=='number'and v>=0 and v<=1,'Wrong volume')
volume=v volume=v
if BGM.playing then
if volume>0 then
BGM.playing:setVolume(volume)
BGM.playing:play()
elseif BGM.nowPlay then
BGM.playing:pause()
end
end
end end
function BGM.init(list) function BGM.init(list)
BGM.init=nil BGM.init=nil
@@ -92,18 +107,6 @@ function BGM.init(list)
LOG("No BGM: "..name,5) LOG("No BGM: "..name,5)
end end
end end
function BGM.setVol(v)
assert(type(v)=='number'and v>=0 and v<=1)
volume=v
if BGM.playing then
if volume>0 then
BGM.playing:setVolume(volume)
BGM.playing:play()
elseif BGM.nowPlay then
BGM.playing:pause()
end
end
end
function BGM.play(name) function BGM.play(name)
name=name or BGM.default name=name or BGM.default
if not _tryLoad(name)then return end if not _tryLoad(name)then return end

View File

@@ -1,66 +1,60 @@
local fs=love.filesystem local fs=love.filesystem
local FILE={} local FILE={}
function FILE.load(name,mode) function FILE.load(name,args)
if not args then args=''end
if fs.getInfo(name)then if fs.getInfo(name)then
local F=fs.newFile(name) local F=fs.newFile(name)
if F:open'r'then assert(F:open'r','open error')
local s=F:read() local s=F:read()F:close()
F:close() if args:sArg'-luaon'or args==''and s:sub(1,6)=='return{'then
if mode=='luaon'or not mode and s:sub(1,6)=="return{"then local func=loadstring(s)
s=loadstring(s) if func then
if s then setfenv(func,{})
setfenv(s,{}) local res=func()
return s() return assert(res,'decode error')
end
elseif mode=='json'or not mode and s:sub(1,1)=="["and s:sub(-1)=="]"or s:sub(1,1)=="{"and s:sub(-1)=="}"then
local res=JSON.decode(s)
if res then
return res
end
elseif mode=='string'or not mode then
return s
else else
MES.new("No file loading mode called "..tostring(mode)) error('decode error')
end end
elseif args:sArg'-json'or args==''and s:sub(1,1)=='['and s:sub(-1)==']'or s:sub(1,1)=='{'and s:sub(-1)=='}'then
local res=JSON.decode(s)
if res then
return res
end
error('decode error')
elseif args:sArg'-string'or args==''then
return s
else else
MES.new('error',name.." "..text.loadError) error('unknown mode')
end end
else
error('no file')
end end
end end
function FILE.save(data,name,mode) function FILE.save(data,name,args)
if not mode then mode=""end if not args then args=''end
if args:sArg'-d'and fs.getInfo(name)then
error('duplicate')
end
if type(data)=='table'then if type(data)=='table'then
if mode:find'l'then if args:sArg'-luaon'then
data=TABLE.dump(data) data=TABLE.dump(data)
if not data then if not data then
MES.new('error',name.." "..text.saveError.."dump error") error('encode error')
return
end end
else else
data=JSON.encode(data) data=JSON.encode(data)
if not data then if not data then
MES.new('error',name.." "..text.saveError.."json error") error('encode error')
return
end end
end end
else else
data=tostring(data) data=tostring(data)
end end
if mode:find'd'and fs.getInfo(name)then
MES.new('error',text.saveError_duplicate)
return
end
local F=fs.newFile(name) local F=fs.newFile(name)
F:open'w' assert(F:open('w'),'open error')
local success,mes=F:write(data) F:write(data)F:flush()F:close()
F:flush()F:close()
if success then
return true
else
MES.new('error',text.saveError..(mes or"unknown error"))
MES.traceback()
end
end end
function FILE.clear(path) function FILE.clear(path)
if fs.getRealDirectory(path)==SAVEDIR and fs.getInfo(path).type=='directory'then if fs.getRealDirectory(path)==SAVEDIR and fs.getInfo(path).type=='directory'then

View File

@@ -1,67 +1,60 @@
local gc=love.graphics local gc=love.graphics
local set=gc.setFont local set=gc.setFont
local fontCache={} local fontFiles,fontCache={},{}
local currentFontSize local defaultFont,defaultFallBack
local curFont=false--Current using font object
local FONT={} local FONT={}
function FONT.set(s) function FONT.setDefault(name)defaultFont=name end
if s~=currentFontSize then function FONT.setFallback(name)defaultFallBack=name end
if not fontCache[s]then function FONT.rawget(s)
fontCache[s]=gc.setNewFont(s,'light',gc.getDPIScale()*SCR.k*2)
end
set(fontCache[s])
currentFontSize=s
end
end
function FONT.get(s)
if not fontCache[s]then if not fontCache[s]then
fontCache[s]=gc.setNewFont(s,'light',gc.getDPIScale()*SCR.k*2) fontCache[s]=gc.setNewFont(s,'light',gc.getDPIScale()*SCR.k*2)
end end
return fontCache[s] return fontCache[s]
end end
function FONT.reset() function FONT.rawset(s)
for s in next,fontCache do set(fontCache[s]or FONT.rawget(s))
fontCache[s]=gc.setNewFont(s,'light',gc.getDPIScale()*SCR.k*2)
end
end end
function FONT.load(fonts)
function FONT.load(mainFont,secFont) for name,path in next,fonts do
assert(love.filesystem.getInfo(mainFont),"Font file '"..mainFont.."' not exist!") assert(love.filesystem.getInfo(path),("Font file $1($2) not exist!"):repD(name,path))
mainFont=love.filesystem.newFile(mainFont) fontFiles[name]=love.filesystem.newFile(path)
if secFont and love.filesystem.getInfo(secFont)then fontCache[name]={}
secFont=love.filesystem.newFile(secFont)
else
secFont=false
end
function FONT.set(s)
if s~=currentFontSize then
if not fontCache[s]then
fontCache[s]=gc.setNewFont(mainFont,s,'light',gc.getDPIScale()*SCR.k*2)
if secFont then
fontCache[s]:setFallbacks(gc.setNewFont(secFont,s,'light',gc.getDPIScale()*SCR.k*2))
end
end
set(fontCache[s])
currentFontSize=s
end
end
function FONT.get(s)
if not fontCache[s]then
fontCache[s]=gc.setNewFont(mainFont,s,'light',gc.getDPIScale()*SCR.k*2)
if secFont then
fontCache[s]:setFallbacks(gc.setNewFont(secFont,s,'light',gc.getDPIScale()*SCR.k*2))
end
end
return fontCache[s]
end
function FONT.reset()
for s in next,fontCache do
fontCache[s]=gc.setNewFont(mainFont,s,'light',gc.getDPIScale()*SCR.k*2)
if secFont then
fontCache[s]:setFallbacks(gc.setNewFont(secFont,s,'light',gc.getDPIScale()*SCR.k*2))
end
end
end end
FONT.reset() FONT.reset()
end end
function FONT.get(size,name)
if not name then name=defaultFont end
local f=fontCache[name][size]
if not f then
f=gc.setNewFont(fontFiles[name],size,'light',gc.getDPIScale()*SCR.k*2)
if defaultFallBack and name~=defaultFallBack then
f:setFallbacks(FONT.get(size,defaultFallBack))
end
fontCache[name][size]=f
end
return f
end
function FONT.set(size,name)
if not name then name=defaultFont end
local f=fontCache[name][size]
if f~=curFont then
curFont=f or FONT.get(size,name)
set(curFont)
end
end
function FONT.reset()
for name,cache in next,fontCache do
if type(cache)=='table'then
for size in next,cache do
cache[size]=FONT.get(size,name)
end
else
fontCache[name]=FONT.rawget(name)
end
end
end
return FONT return FONT

View File

@@ -95,6 +95,7 @@ do--function GC.DO(L)
setLJ="setLineJoin", setLJ="setLineJoin",
print="print", print="print",
rawFT=function(...)FONT.rawset(...)end,
setFT=function(...)FONT.set(...)end, setFT=function(...)FONT.set(...)end,
mText=GC.mStr, mText=GC.mStr,
mDraw=GC.draw, mDraw=GC.draw,

View File

@@ -1,7 +1,6 @@
NONE={}function NULL()end NONE={}function NULL()end
EDITING="" EDITING=""
LOADED=false LOADED=false
ERRDATA={}
--Pure lua modules (basic) --Pure lua modules (basic)
MATH= require'Zframework.mathExtend' MATH= require'Zframework.mathExtend'
@@ -74,7 +73,8 @@ local xOy=SCR.xOy
local ITP=xOy.inverseTransformPoint local ITP=xOy.inverseTransformPoint
local mx,my,mouseShow=-20,-20,false local mx,my,mouseShow=-20,-20,false
joysticks={} local jsState={}--map, joystickID->axisStates: {axisName->axisVal}
local errData={}--list, each error create {mes={errMes strings},scene=sceneNameStr}
local devMode local devMode
@@ -288,18 +288,18 @@ function love.textinput(texts)
WIDGET.textinput(texts) WIDGET.textinput(texts)
end end
function love.joystickadded(JS) --analog sticks: -1, 0, 1 for neg, neutral, pos
table.insert(joysticks,JS) --triggers: 0 for released, 1 for pressed
MES.new('info',"Joystick added") local jsAxisEventName={
end leftx={'leftstick_left','leftstick_right'},
function love.joystickremoved(JS) lefty={'leftstick_up','leftstick_down'},
local i=TABLE.find(joysticks,JS) rightx={'rightstick_left','rightstick_right'},
if i then righty={'rightstick_up','rightstick_down'},
table.remove(joysticks,i) triggerleft='triggerleft',
MES.new('info',"Joystick removed") triggerright='triggerright'
end }
end local gamePadKeys={'a','b','x','y','back','guide','start','leftstick','rightstick','leftshoulder','rightshoulder','dpup','dpdown','dpleft','dpright'}
local keyMirror={ local dPadToKey={
dpup='up', dpup='up',
dpdown='down', dpdown='down',
dpleft='left', dpleft='left',
@@ -307,54 +307,92 @@ local keyMirror={
start='return', start='return',
back='escape', back='escape',
} }
function love.joystickadded(JS)
jsState[JS:getID()]={
_loveJSObj=JS,
leftx=0,lefty=0,
rightx=0,righty=0,
triggerleft=0,triggerright=0
}
MES.new('info',"Joystick added")
end
function love.joystickremoved(JS)
local js=jsState[JS:getID()]
if js then
for i=1,#gamePadKeys do
if JS:isGamepadDown(gamePadKeys[i])then
love.gamepadreleased(JS,gamePadKeys[i])
end
end
love.gamepadaxis(JS,'leftx',0)
love.gamepadaxis(JS,'lefty',0)
love.gamepadaxis(JS,'rightx',0)
love.gamepadaxis(JS,'righty',0)
love.gamepadaxis(JS,'triggerleft',-1)
love.gamepadaxis(JS,'triggerright',-1)
jsState[JS:getID()]=nil
MES.new('info',"Joystick removed")
end
end
function love.gamepadaxis(JS,axis,val)
local js=jsState[JS:getID()]
if js then
if axis=='leftx'or axis=='lefty'or axis=='rightx'or axis=='righty'then
local newVal=--range: [0,1]
val>.4 and 1 or
val<-.4 and -1 or
0
if newVal~=js[axis]then
if js[axis]==-1 then
love.gamepadreleased(JS,jsAxisEventName[axis][1])
elseif js[axis]~=0 then
love.gamepadreleased(JS,jsAxisEventName[axis][2])
end
if newVal==-1 then
love.gamepadpressed(JS,jsAxisEventName[axis][1])
elseif newVal==1 then
love.gamepadpressed(JS,jsAxisEventName[axis][2])
end
js[axis]=newVal
end
elseif axis=='triggerleft'or axis=='triggerright'then
local newVal=val>-.3 and 1 or 0--range: [-1,1]
if newVal~=js[axis]then
if newVal==1 then
love.gamepadpressed(JS,jsAxisEventName[axis])
else
love.gamepadreleased(JS,jsAxisEventName[axis])
end
js[axis]=newVal
end
end
end
end
function love.gamepadpressed(_,i) function love.gamepadpressed(_,i)
mouseShow=false mouseShow=false
if SCN.swapping then return end if SCN.swapping then return end
if SCN.gamepadDown then SCN.gamepadDown(i) if SCN.gamepadDown then SCN.gamepadDown(i)
elseif SCN.keyDown then SCN.keyDown(keyMirror[i]or i) elseif SCN.keyDown then SCN.keyDown(dPadToKey[i]or i)
elseif i=="back"then SCN.back() elseif i=="back"then SCN.back()
else WIDGET.gamepadPressed(keyMirror[i]or i) else WIDGET.gamepadPressed(dPadToKey[i]or i)
end end
end end
function love.gamepadreleased(_,i) function love.gamepadreleased(_,i)
if SCN.swapping then return end if SCN.swapping then return end
if SCN.gamepadUp then SCN.gamepadUp(i)end if SCN.gamepadUp then SCN.gamepadUp(i)end
end end
--[[
function love.joystickpressed(JS,k)
mouseShow=false
if SCN.swapping then return end
if SCN.gamepadDown then SCN.gamepadDown(i)
elseif SCN.keyDown then SCN.keyDown(keyMirror[i]or i)
elseif i=="back"then SCN.back()
else WIDGET.gamepadPressed(i)
end
end
function love.joystickreleased(JS,k)
if SCN.swapping then return end
if SCN.gamepadUp then SCN.gamepadUp(i)
end
end
function love.joystickaxis(JS,axis,val)
end
function love.joystickhat(JS,hat,dir)
end
function love.sendData(data)end
function love.receiveData(id,data)end
]]
function love.filedropped(file) function love.filedropped(file)
if SCN.fileDropped then SCN.fileDropped(file)end if SCN.fileDropped then SCN.fileDropped(file)end
end end
function love.directorydropped(dir) function love.directorydropped(dir)
if SCN.directoryDropped then SCN.directoryDropped(dir)end if SCN.directoryDropped then SCN.directoryDropped(dir)end
end end
local lastGCtime=0 local autoGCcount=0
function love.lowmemory() function love.lowmemory()
if love.timer.getTime()-lastGCtime>6.26 then collectgarbage()
collectgarbage() if autoGCcount<3 then
lastGCtime=love.timer.getTime() autoGCcount=autoGCcount+1
MES.new('check',"[auto GC] low MEM 设备内存过低") MES.new('check',"[auto GC] low MEM 设备内存过低")
end end
end end
@@ -379,7 +417,7 @@ end
function love.errorhandler(msg) function love.errorhandler(msg)
if type(msg)~='string'then if type(msg)~='string'then
msg="Unknown error" msg="Unknown error"
elseif msg:find("Invaild UTF-8")and text then elseif msg:find("Invalid UTF-8")and text then
msg=text.tryAnotherBuild msg=text.tryAnotherBuild
end end
@@ -403,20 +441,20 @@ function love.errorhandler(msg)
love.audio.stop() love.audio.stop()
gc.reset() gc.reset()
if LOADED and #ERRDATA<3 then if LOADED and #errData<3 then
BG.set('none') BG.set('none')
local scn=SCN and SCN.cur or"NULL" local scn=SCN and SCN.cur or"NULL"
table.insert(ERRDATA,{mes=err,scene=scn}) table.insert(errData,{mes=err,scene=scn})
--Write messages to log file --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").. os.date("%Y/%m/%d %A %H:%M:%S\n")..
#ERRDATA.." crash(es) "..love.system.getOS().."-"..VERSION.string.." scene: "..scn.."\n".. #errData.." crash(es) "..love.system.getOS().."-"..VERSION.string.." scene: "..scn.."\n"..
table.concat(err,"\n",1,c-2).."\n\n" table.concat(err,"\n",1,c-2).."\n\n"
) )
--Get screencapture --Get screencapture
gc.captureScreenshot(function(_)ERRDATA[#ERRDATA].shot=gc.newImage(_)end) gc.captureScreenshot(function(_)errData[#errData].shot=gc.newImage(_)end)
gc.present() gc.present()
--Create a new mainLoop thread to keep game alive --Create a new mainLoop thread to keep game alive
@@ -489,17 +527,17 @@ local wsBottomImage do
wsBottomImage=GC.DO(L) wsBottomImage=GC.DO(L)
end end
local ws_deadImg=GC.DO{20,20, local ws_deadImg=GC.DO{20,20,
{'setFT',20}, {'rawFT',20},
{'setCL',1,.3,.3}, {'setCL',1,.3,.3},
{'mText',"X",11,-1}, {'mText',"X",11,-1},
} }
local ws_connectingImg=GC.DO{20,20, local ws_connectingImg=GC.DO{20,20,
{'setFT',20}, {'rawFT',20},
{'setLW',3}, {'setLW',3},
{'mText',"C",11,-1}, {'mText',"C",11,-1},
} }
local ws_runningImg=GC.DO{20,20, local ws_runningImg=GC.DO{20,20,
{'setFT',20}, {'rawFT',20},
{'setCL',.5,1,0}, {'setCL',.5,1,0},
{'mText',"R",11,-1}, {'mText',"R",11,-1},
} }
@@ -539,7 +577,7 @@ function love.run()
--Scene Launch --Scene Launch
while #SCN.stack>0 do SCN.pop()end while #SCN.stack>0 do SCN.pop()end
SCN.push('quit','slowFade') SCN.push('quit','slowFade')
SCN.init(#ERRDATA==0 and'load'or'error') SCN.init(#errData==0 and'load'or'error')
return function() return function()
local _ local _
@@ -703,6 +741,9 @@ end
local Z={} local Z={}
Z.js=jsState
Z.errData=errData
function Z.setIfPowerInfo(func)showPowerInfo=func end function Z.setIfPowerInfo(func)showPowerInfo=func end
--[Warning] Color and line width is uncertain value, set it in the function. --[Warning] Color and line width is uncertain value, set it in the function.

View File

@@ -72,11 +72,11 @@ function SFX.getCount()
return #sfxList return #sfxList
end end
function SFX.setVol(v) function SFX.setVol(v)
assert(type(v)=='number'and v>=0 and v<=1) assert(type(v)=='number'and v>=0 and v<=1,'Wrong volume')
volume=v volume=v
end end
function SFX.setStereo(v) function SFX.setStereo(v)
assert(type(v)=='number'and v>=0 and v<=1) assert(type(v)=='number'and v>=0 and v<=1,'Wrong stereo')
stereo=v stereo=v
end end

View File

@@ -2,9 +2,25 @@ local data=love.data
local STRING={} local STRING={}
local assert,tostring,tonumber=assert,tostring,tonumber local assert,tostring,tonumber=assert,tostring,tonumber
local int,format=math.floor,string.format local int,format=math.floor,string.format
local find,sub,upper=string.find,string.sub,string.upper local find,sub,gsub,upper=string.find,string.sub,string.gsub,string.upper
local char,byte=string.char,string.byte local char,byte=string.char,string.byte
--"Replace dollars", replace all $n with ...
function string.repD(str,...)
local l={...}
for i=#l,1,-1 do
str=gsub(str,'$'..i,l[i])
end
return str
end
--"Scan arg", scan if str has the arg (format of str is like "-json -q", arg is like "-q")
function string.sArg(str,switch)
if find(str.." ",switch.." ")then
return true
end
end
do--function STRING.shiftChar(c) do--function STRING.shiftChar(c)
local shiftMap={ local shiftMap={
['1']='!',['2']='@',['3']='#',['4']='$',['5']='%', ['1']='!',['2']='@',['3']='#',['4']='$',['5']='%',

View File

@@ -1,4 +1,5 @@
local find=string.find local find=string.find
local rem=table.remove
local next,type=next,type local next,type=next,type
local TABLE={} local TABLE={}
@@ -83,7 +84,7 @@ function TABLE.complete(new,old)
end end
end end
--Remove positive integer index of table --Remove [1~#] of table
function TABLE.cut(G) function TABLE.cut(G)
for i=1,#G do for i=1,#G do
G[i]=nil G[i]=nil
@@ -97,16 +98,53 @@ function TABLE.clear(G)
end end
end end
--Remove duplicated value of [1~#]
function TABLE.trimDuplicate(org)
local cache={}
for i=1,#org,-1 do
if cache[org[i]]then
rem(org,i)
else
cache[org[i]]=true
end
end
end
--Discard duplicated value
function TABLE.remDuplicate(org)
local cache={}
for k,v in next,org do
if cache[v]then
org[k]=nil
else
cache[v]=true
end
end
end
--Reverse [1~#]
function TABLE.reverse(org)
local l=#org
for i=1,math.floor(l/2)do
org[i],org[l+1-i]=org[l+1-i],org[i]
end
end
--------------------------
--Find value in [1~#] --Find value in [1~#]
function TABLE.find(t,val) function TABLE.find(t,val)
for i=1,#t do if t[i]==val then return i end end for i=1,#t do if t[i]==val then return i end end
end end
--Retuen next value of [1~#] --Return next value of [1~#] (by value)
function TABLE.next(t,val) function TABLE.next(t,val)
for i=1,#t do if t[i]==val then return t[i%#t+1]end end for i=1,#t do if t[i]==val then return t[i%#t+1]end end
end end
--------------------------
--Find value in whole table --Find value in whole table
function TABLE.search(t,val) function TABLE.search(t,val)
for k,v in next,t do if v==val then return k end end for k,v in next,t do if v==val then return k end end
@@ -121,6 +159,8 @@ function TABLE.reIndex(org)
end end
end end
--------------------------
--Dump a simple lua table --Dump a simple lua table
do--function TABLE.dump(L,t) do--function TABLE.dump(L,t)
local tabs={ local tabs={

View File

@@ -1,5 +1,7 @@
local rnd=math.random
local volume=1
local diversion=0
local VOC={ local VOC={
vol=1,
getCount=function()return 0 end, getCount=function()return 0 end,
getQueueCount=function()return 0 end, getQueueCount=function()return 0 end,
load=function()error("Cannot load before init!")end, load=function()error("Cannot load before init!")end,
@@ -7,13 +9,16 @@ local VOC={
play=NULL, play=NULL,
update=NULL, update=NULL,
} }
function VOC.setDiversion(n)
assert(type(n)=='number'and n>0 and n<12,'Wrong div')
diversion=n
end
function VOC.setVol(v) function VOC.setVol(v)
assert(type(v)=='number'and v>=0 and v<=1) assert(type(v)=='number'and v>=0 and v<=1,'Wrong volume')
VOC.vol=v volume=v
end end
function VOC.init(list) function VOC.init(list)
VOC.init=nil VOC.init=nil
local rnd=math.random
local rem=table.remove local rem=table.remove
local voiceQueue={free=0} local voiceQueue={free=0}
local bank={}--{vocName1={SRC1s},vocName2={SRC2s},...} local bank={}--{vocName1={SRC1s},vocName2={SRC2s},...}
@@ -72,7 +77,7 @@ function VOC.init(list)
end end
function VOC.play(s,chn) function VOC.play(s,chn)
if VOC.vol>0 then if volume>0 then
local _=Source[s] local _=Source[s]
if not _ then return end if not _ then return end
if chn then if chn then
@@ -95,13 +100,15 @@ function VOC.init(list)
end end
elseif Q.s==1 then--Waiting load source elseif Q.s==1 then--Waiting load source
Q[1]=_getVoice(Q[1]) Q[1]=_getVoice(Q[1])
Q[1]:setVolume(VOC.vol) Q[1]:setVolume(volume)
Q[1]:setPitch(1.0594630943592953^(diversion*(rnd()*2-1)))
Q[1]:play() Q[1]:play()
Q.s=Q[2]and 2 or 4 Q.s=Q[2]and 2 or 4
elseif Q.s==2 then--Playing 1,ready 2 elseif Q.s==2 then--Playing 1,ready 2
if Q[1]:getDuration()-Q[1]:tell()<.08 then if Q[1]:getDuration()-Q[1]:tell()<.08 then
Q[2]=_getVoice(Q[2]) Q[2]=_getVoice(Q[2])
Q[2]:setVolume(VOC.vol) Q[2]:setVolume(volume)
Q[1]:setPitch(1.0594630943592953^(diversion*(rnd()*2-1)))
Q[2]:play() Q[2]:play()
Q.s=3 Q.s=3
end end

View File

@@ -29,7 +29,7 @@ local clearIcon=GC.DO{40,40,
{'fRect',11,14,18,21}, {'fRect',11,14,18,21},
} }
local sureIcon=GC.DO{40,40, local sureIcon=GC.DO{40,40,
{'setFT',35}, {'rawFT',35},
{'mText',"?",20,0}, {'mText',"?",20,0},
} }
local smallerThen=GC.DO{20,20, local smallerThen=GC.DO{20,20,
@@ -82,7 +82,7 @@ function text:draw()
end end
end end
end end
function WIDGET.newText(D)--name,x,y[,fText][,color][,font=30][,align='M'][,hideF][,hide] function WIDGET.newText(D)--name,x,y[,fText][,color][,font=30][,fType][,align='M'][,hideF][,hide]
local _={ local _={
name= D.name or"_", name= D.name or"_",
x= D.x, x= D.x,
@@ -91,6 +91,7 @@ function WIDGET.newText(D)--name,x,y[,fText][,color][,font=30][,align='M'][,hide
fText=D.fText, fText=D.fText,
color=D.color and(COLOR[D.color]or D.color)or COLOR.Z, color=D.color and(COLOR[D.color]or D.color)or COLOR.Z,
font= D.font or 30, font= D.font or 30,
fType=D.fType,
align=D.align or'M', align=D.align or'M',
hideF=D.hideF, hideF=D.hideF,
} }
@@ -139,7 +140,7 @@ function button:reset()
end end
function button:setObject(obj) function button:setObject(obj)
if type(obj)=='string'or type(obj)=='number'then if type(obj)=='string'or type(obj)=='number'then
self.obj=gc.newText(FONT.get(self.font),obj) self.obj=gc.newText(FONT.get(self.font,self.fType),obj)
elseif obj then elseif obj then
self.obj=obj self.obj=obj
end end
@@ -209,7 +210,7 @@ function button:draw()
end end
end end
function button:getInfo() function button:getInfo()
return("x=%d,y=%d,w=%d,h=%d,font=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h,self.font) return("x=%d,y=%d,w=%d,h=%d,font=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h,self.font,self.fType)
end end
function button:press(_,_,k) function button:press(_,_,k)
self.code(k) self.code(k)
@@ -225,7 +226,7 @@ function button:press(_,_,k)
SFX.play('button') SFX.play('button')
end end
end end
function WIDGET.newButton(D)--name,x,y,w[,h][,fText][,color][,font=30][,sound=true][,align='M'][,edge=0],code[,hideF][,hide] function WIDGET.newButton(D)--name,x,y,w[,h][,fText][,color][,font=30][,fType][,sound=true][,align='M'][,edge=0],code[,hideF][,hide]
if not D.h then D.h=D.w end if not D.h then D.h=D.w end
local _={ local _={
name= D.name or"_", name= D.name or"_",
@@ -246,6 +247,7 @@ function WIDGET.newButton(D)--name,x,y,w[,h][,fText][,color][,font=30][,sound=tr
fText=D.fText, fText=D.fText,
color=D.color and(COLOR[D.color]or D.color)or COLOR.Z, color=D.color and(COLOR[D.color]or D.color)or COLOR.Z,
font= D.font or 30, font= D.font or 30,
fType=D.fType,
align=D.align or'M', align=D.align or'M',
edge= D.edge or 0, edge= D.edge or 0,
sound=D.sound~=false, sound=D.sound~=false,
@@ -268,7 +270,7 @@ function key:reset()
end end
function key:setObject(obj) function key:setObject(obj)
if type(obj)=='string'or type(obj)=='number'then if type(obj)=='string'or type(obj)=='number'then
self.obj=gc.newText(FONT.get(self.font),obj) self.obj=gc.newText(FONT.get(self.font,self.fType),obj)
elseif obj then elseif obj then
self.obj=obj self.obj=obj
end end
@@ -331,7 +333,7 @@ function key:draw()
end end
end end
function key:getInfo() function key:getInfo()
return("x=%d,y=%d,w=%d,h=%d,font=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h,self.font) return("x=%d,y=%d,w=%d,h=%d,font=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h,self.font,self.fType)
end end
function key:press(_,_,k) function key:press(_,_,k)
self.code(k) self.code(k)
@@ -339,7 +341,7 @@ function key:press(_,_,k)
SFX.play('key') SFX.play('key')
end end
end end
function WIDGET.newKey(D)--name,x,y,w[,h][,fText][,fShade][,noFrame][,color][,font=30][,sound=true][,align='M'][,edge=0],code[,hideF][,hide] function WIDGET.newKey(D)--name,x,y,w[,h][,fText][,fShade][,noFrame][,color][,font=30][,fType][,sound=true][,align='M'][,edge=0],code[,hideF][,hide]
if not D.h then D.h=D.w end if not D.h then D.h=D.w end
local _={ local _={
name= D.name or"_", name= D.name or"_",
@@ -362,6 +364,7 @@ function WIDGET.newKey(D)--name,x,y,w[,h][,fText][,fShade][,noFrame][,color][,fo
noFrame=D.noFrame, noFrame=D.noFrame,
color= D.color and(COLOR[D.color]or D.color)or COLOR.Z, color= D.color and(COLOR[D.color]or D.color)or COLOR.Z,
font= D.font or 30, font= D.font or 30,
fType=D.fType,
sound= D.sound~=false, sound= D.sound~=false,
align= D.align or'M', align= D.align or'M',
edge= D.edge or 0, edge= D.edge or 0,
@@ -430,7 +433,7 @@ function switch:draw()
gc_draw(obj,x-12-ATV,y,nil,min(self.lim/obj:getWidth(),1),1,obj:getWidth(),obj:getHeight()*.5) gc_draw(obj,x-12-ATV,y,nil,min(self.lim/obj:getWidth(),1),1,obj:getWidth(),obj:getHeight()*.5)
end end
function switch:getInfo() function switch:getInfo()
return("x=%d,y=%d,font=%d"):format(self.x,self.y,self.font) return("x=%d,y=%d,font=%d"):format(self.x,self.y,self.font,self.fType)
end end
function switch:press() function switch:press()
self.code() self.code()
@@ -438,7 +441,7 @@ function switch:press()
SFX.play('touch') SFX.play('touch')
end end
end end
function WIDGET.newSwitch(D)--name,x,y[,lim][,fText][,color][,font=30][,sound=true][,disp],code[,hideF][,hide] function WIDGET.newSwitch(D)--name,x,y[,lim][,fText][,color][,font=30][,fType][,sound=true][,disp],code[,hideF][,hide]
local _={ local _={
name= D.name or"_", name= D.name or"_",
@@ -453,6 +456,7 @@ function WIDGET.newSwitch(D)--name,x,y[,lim][,fText][,color][,font=30][,sound=tr
fText=D.fText, fText=D.fText,
color=D.color and(COLOR[D.color]or D.color)or COLOR.Z, color=D.color and(COLOR[D.color]or D.color)or COLOR.Z,
font= D.font or 30, font= D.font or 30,
fType=D.fType,
sound=D.sound~=false, sound=D.sound~=false,
disp= D.disp, disp= D.disp,
code= D.code, code= D.code,
@@ -595,7 +599,7 @@ end
function slider:arrowKey(k) function slider:arrowKey(k)
self:scroll((k=="left"or k=="up")and -1 or 1) self:scroll((k=="left"or k=="up")and -1 or 1)
end end
function WIDGET.newSlider(D)--name,x,y,w[,lim][,fText][,color][,unit][,smooth][,font=30][,change],disp[,show],code,hide function WIDGET.newSlider(D)--name,x,y,w[,lim][,fText][,color][,unit][,smooth][,font=30][,fType][,change],disp[,show],code,hide
local _={ local _={
name= D.name or"_", name= D.name or"_",
@@ -617,6 +621,7 @@ function WIDGET.newSlider(D)--name,x,y,w[,lim][,fText][,color][,unit][,smooth][,
unit= D.unit or 1, unit= D.unit or 1,
smooth=false, smooth=false,
font= D.font or 30, font= D.font or 30,
fType=D.fType,
change=D.change, change=D.change,
disp= D.disp, disp= D.disp,
code= D.code, code= D.code,
@@ -863,7 +868,7 @@ function inputBox:draw()
--Drawable --Drawable
local f=self.font local f=self.font
FONT.set(f) FONT.set(f,self.fType)
if self.obj then if self.obj then
mDraw_Y(self.obj,x-12-self.obj:getWidth(),y+h*.5) mDraw_Y(self.obj,x-12-self.obj:getWidth(),y+h*.5)
end end
@@ -906,7 +911,7 @@ function inputBox:keypress(k)
self.value=t self.value=t
end end
end end
function WIDGET.newInputBox(D)--name,x,y,w[,h][,font=30][,secret][,regex][,limit],hide function WIDGET.newInputBox(D)--name,x,y,w[,h][,font=30][,fType][,secret][,regex][,limit],hide
local _={ local _={
name= D.name or"_", name= D.name or"_",
@@ -922,6 +927,7 @@ function WIDGET.newInputBox(D)--name,x,y,w[,h][,font=30][,secret][,regex][,limit
}, },
font= D.font or int(D.h/7-1)*5, font= D.font or int(D.h/7-1)*5,
fType=D.fType,
secret=D.secret==true, secret=D.secret==true,
regex= D.regex, regex= D.regex,
limit= D.limit, limit= D.limit,
@@ -1022,7 +1028,7 @@ function textBox:draw()
gc_rectangle('line',x,y,w,h,3) gc_rectangle('line',x,y,w,h,3)
--Texts --Texts
FONT.set(self.font) FONT.set(self.font,self.fType)
gc_push('transform') gc_push('transform')
gc_translate(x,y) gc_translate(x,y)
@@ -1054,7 +1060,7 @@ end
function textBox:getInfo() function textBox: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) 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 end
function WIDGET.newTextBox(D)--name,x,y,w,h[,font=30][,lineH][,fix],hide function WIDGET.newTextBox(D)--name,x,y,w,h[,font=30][,fType][,lineH][,fix],hide
local _={ local _={
name= D.name or"_", name= D.name or"_",
@@ -1076,6 +1082,7 @@ function WIDGET.newTextBox(D)--name,x,y,w,h[,font=30][,lineH][,fix],hide
h= D.h, h= D.h,
font= D.font or 30, font= D.font or 30,
fType=D.fType,
fix= D.fix, fix= D.fix,
texts={}, texts={},
hideF=D.hideF, hideF=D.hideF,

View File

@@ -44,8 +44,8 @@ N3TWORK is a registered trademark of N3TWORK Inc. © 2021 N3TWORK Inc.
GoldWave is a registered trademark of GoldWave, Inc. GoldWave is a registered trademark of GoldWave, Inc.
Linux is a registered trademark of Linus Torvalds. Linux is a registered trademark of Linus Torvalds.
Touhou Project © Team Shanghai Alice 2002-2021. Touhou Project © Team Shanghai Alice 2002-2021.
All other trademarks, logos, and copyrights are the properties of their respective owners. All other trademarks, logos, and copyrights are the properties of their respective owners.

View File

@@ -50,10 +50,17 @@ local _LOADTIME_=TIME()
--Load modules --Load modules
Z=require'Zframework' Z=require'Zframework'
FONT.load('parts/fonts/proportional.ttf') FONT.load{
norm='parts/fonts/proportional.ttf',
mono='parts/fonts/monospaced.ttf',
}
FONT.setDefault('norm')
FONT.setFallback('norm')
SCR.setSize(1280,720)--Initialize Screen size SCR.setSize(1280,720)--Initialize Screen size
BGM.setMaxSources(5) BGM.setMaxSources(5)
BGM.setChange(function(name)MES.new('music',text.nowPlaying..name,5)end) BGM.setChange(function(name)MES.new('music',text.nowPlaying..name,5)end)
VOC.setDiversion(1)
table.insert(_LOADTIMELIST_,("Load Zframework: %.3fs"):format(TIME()-_LOADTIME_)) table.insert(_LOADTIMELIST_,("Load Zframework: %.3fs"):format(TIME()-_LOADTIME_))
@@ -204,15 +211,15 @@ end
Z.setOnQuit(destroyPlayers) Z.setOnQuit(destroyPlayers)
--Load settings and statistics --Load settings and statistics
TABLE.cover (FILE.load('conf/user')or{},USER) TABLE.cover (loadFile('conf/user')or{},USER)
TABLE.cover (FILE.load('conf/unlock')or{},RANKS) TABLE.cover (loadFile('conf/unlock')or{},RANKS)
TABLE.update(FILE.load('conf/settings')or{},SETTING) TABLE.update(loadFile('conf/settings')or{},SETTING)
TABLE.coverR(FILE.load('conf/data')or{},STAT) TABLE.coverR(loadFile('conf/data')or{},STAT)
TABLE.cover (FILE.load('conf/key')or{},KEY_MAP) TABLE.cover (loadFile('conf/key')or{},KEY_MAP)
TABLE.cover (FILE.load('conf/virtualkey')or{},VK_ORG) TABLE.cover (loadFile('conf/virtualkey')or{},VK_ORG)
--Initialize fields, sequence, missions, gameEnv for cutsom game --Initialize fields, sequence, missions, gameEnv for cutsom game
local fieldData=FILE.load('conf/customBoards','string') local fieldData=loadFile('conf/customBoards','-string')
if fieldData then if fieldData then
fieldData=STRING.split(fieldData,"!") fieldData=STRING.split(fieldData,"!")
for i=1,#fieldData do for i=1,#fieldData do
@@ -221,15 +228,15 @@ if fieldData then
else else
FIELD[1]=DATA.newBoard() FIELD[1]=DATA.newBoard()
end end
local sequenceData=FILE.load('conf/customSequence','string') local sequenceData=loadFile('conf/customSequence','-string')
if sequenceData then if sequenceData then
DATA.pasteSequence(sequenceData) DATA.pasteSequence(sequenceData)
end end
local missionData=FILE.load('conf/customMissions','string') local missionData=loadFile('conf/customMissions','-string')
if missionData then if missionData then
DATA.pasteMission(missionData) DATA.pasteMission(missionData)
end end
local customData=FILE.load('conf/customEnv') local customData=loadFile('conf/customEnv')
if customData and customData['version']==VERSION.code then if customData and customData['version']==VERSION.code then
TABLE.complete(customData,CUSTOMENV) TABLE.complete(customData,CUSTOMENV)
end end
@@ -476,6 +483,10 @@ do
fs.remove('record/rhythm_h.rec') fs.remove('record/rhythm_h.rec')
fs.remove('record/rhythm_u.rec') fs.remove('record/rhythm_u.rec')
end end
if RANKS.bigbang then
RANKS.clearRush,RANKS.bigbang=RANKS.bigbang
fs.remove('record/bigbang.rec')
end
if STAT.version~=VERSION.code then if STAT.version~=VERSION.code then
for k,v in next,MODE_UPDATE_MAP do for k,v in next,MODE_UPDATE_MAP do
if RANKS[k]then if RANKS[k]then
@@ -628,9 +639,9 @@ if TABLE.find(arg,'--test')then
TASK.new(function() TASK.new(function()
while true do while true do
YIELD() YIELD()
if ERRDATA[1]then break end if Z.errData[1]then break end
end end
LOG("\27[91m\27[1mAutomatic Test Failed :(\27[0m\nThe error message is:\n"..table.concat(ERRDATA[1].mes,"\n").."\27[91m\nAborting\27[0m") LOG("\27[91m\27[1mAutomatic Test Failed :(\27[0m\nThe error message is:\n"..table.concat(Z.errData[1].mes,"\n").."\27[91m\nAborting\27[0m")
TEST.yieldN(60) TEST.yieldN(60)
love.event.quit(1) love.event.quit(1)
end) end)

BIN
media/music/malate.ogg Normal file

Binary file not shown.

View File

@@ -140,8 +140,8 @@ do
},--Z },--Z
false,--S false,--S
{ {
[01]={'+0+0','-1+0','-1+1','+0-2','+1+1','+0+1'}, [01]={'+0+0','-1+0','-1+1','+0-2','+1+1','+0+1','+0-1'},
[10]={'+0+0','+1+0','+1-1','+0+2','-1-1','+0-1'}, [10]={'+0+0','+1+0','+1-1','+0+2','-1-1','+0-1','+0+1'},
[03]={'+0+0','+1+0','+1+1','+0-2','+1-2','+1-1','+0+1'}, [03]={'+0+0','+1+0','+1+1','+0-2','+1-2','+1-1','+0+1'},
[30]={'+0+0','-1+0','-1-1','+0+2','-1+2','+0-1','-1+1'}, [30]={'+0+0','-1+0','-1-1','+0+2','-1+2','+0-1','-1+1'},
[12]={'+0+0','+1+0','+1-1','+1+1','-1+0','+0-1','+0+2','+1+2'}, [12]={'+0+0','+1+0','+1-1','+1+1','-1+0','+0-1','+0+2','+1+2'},

View File

@@ -61,7 +61,7 @@ function back.draw()
gc_setLineWidth(6) gc_setLineWidth(6)
gc_setColor(.8,.9,1,.3) gc_setColor(.8,.9,1,.3)
for i=1,8 do gc_polygon('line',SVG_TITLE_FAN[i])end for i=1,#SVG_TITLE_FAN do gc_polygon('line',SVG_TITLE_FAN[i])end
gc_setLineWidth(2) gc_setLineWidth(2)
gc_setColor(1,.5,.7,.3) gc_setColor(1,.5,.7,.3)

View File

@@ -12,7 +12,7 @@ local baseBot={
function baseBot.update(bot) function baseBot.update(bot)
local P=bot.P local P=bot.P
local keys=bot.keys local keys=bot.keys
if P.control and P.waiting==-1 then if P.control and P.waiting==0 then
bot.delay=bot.delay-1 bot.delay=bot.delay-1
if not keys[1]then if not keys[1]then
if bot.runningThread then if bot.runningThread then

View File

@@ -6,6 +6,8 @@ return{
lock=1e99, lock=1e99,
wait=0, wait=0,
fall=0, fall=0,
hang=5,
hurry=1e99,
--Control --Control
nextCount=6, nextCount=6,
@@ -13,7 +15,6 @@ return{
holdCount=1, holdCount=1,
infHold=true, infHold=true,
phyHold=false, phyHold=false,
hang=0,
--Visual --Visual
bone=false, bone=false,

View File

@@ -1,4 +1,5 @@
local function task_newBoard(P,init) local function task_newBoard(P,init)
local targetLine
local F,L={},{1} local F,L={},{1}
--TODO --TODO
P:pushNextList(L) P:pushNextList(L)
@@ -7,7 +8,7 @@ local function task_newBoard(P,init)
if not init then for _=1,26 do YIELD()end end if not init then for _=1,26 do YIELD()end end
P.control=true P.control=true
P.gameEnv.heightLimit=#F P.gameEnv.heightLimit=targetLine or #F
P:pushLineList(F) P:pushLineList(F)
end end
local function _check(P) local function _check(P)
@@ -23,7 +24,7 @@ local function _check(P)
end end
return{ return{
sequence='none', sequence='none',
RS="SRS", RS="TRS",
pushSpeed=5, pushSpeed=5,
mesDisp=function(P) mesDisp=function(P)
setFont(60) setFont(60)

View File

@@ -1,24 +1,34 @@
local gc=love.graphics local gc=love.graphics
local warnTime={60,90,105,115,116,117,118,119,120} local warnTime={60,90,105,115,116,117,118,119,120}
for i=1,#warnTime do warnTime[i]=warnTime[i]*60 end
return{ return{
mesDisp=function(P) mesDisp=function(P)
gc.setLineWidth(2) gc.setLineWidth(2)
gc.rectangle('line',55,110,32,402) gc.setColor(.98,.98,.98,.8)
local T=P.stat.frame/60/120 gc.rectangle('line',0,260,126,80,4)
gc.setColor(2*T,2-2*T,.2) gc.setColor(.98,.98,.98,.4)
gc.rectangle('fill',56,511,30,(T-1)*400) gc.rectangle('fill',0+2,260+2,126-4,80-4,2)
setFont(45)
local t=P.stat.frame/60
local T=("%.1f"):format(120-t)
gc.setColor(COLOR.dH)
mStr(T,65,270)
t=t/120
gc.setColor(1.7*t,2.3-2*t,.3)
mStr(T,63,268)
end, end,
task=function(P) task=function(P)
P.modeData.stage=1 BGM.seek(0)
P.modeData.section=1
while true do while true do
YIELD() YIELD()
if P.stat.frame/60>=warnTime[P.modeData.stage]then while P.stat.frame>=warnTime[P.modeData.section]do
if P.modeData.stage<9 then if P.modeData.section<9 then
P.modeData.stage=P.modeData.stage+1 P.modeData.section=P.modeData.section+1
playReadySFX(3,.7+P.modeData.stage*.03) playReadySFX(3,.7+P.modeData.section*.03)
else else
playReadySFX(0,.7+P.modeData.stage*.03) playReadySFX(0,.7+P.modeData.section*.03)
P:win('finish') P:win('finish')
return return
end end

View File

@@ -15,6 +15,48 @@ local playSFX=SFX.play
--System --System
do--function loadFile(name,args), function saveFile(data,name,args)
local t=setmetatable({},{__index=function()return"'$1' loading failed: $2"end})
function loadFile(name,args)
local text=text or t
if not args then args=''end
local res,mes=pcall(FILE.load,name,args)
if res then
return mes
else
if mes:find'open error'then
MES.new('error',text.loadError_open:repD(name,""))
elseif mes:find'unknown mode'then
MES.new('error',text.loadError_errorMode:repD(name,args))
elseif mes:find'no file'then
if not args:sArg'-canSkip'then
MES.new('error',text.loadError_noFile:repD(name,""))
end
elseif mes then
MES.new('error',text.loadError_other:repD(name,mes))
else
MES.new('error',text.loadError_unknown:repD(name,""))
end
end
end
function saveFile(data,name,args)
local text=text or t
local res,mes=pcall(FILE.save,data,name,args)
if res then
return mes
else
MES.new('error',
mes:find'duplicate'and
text.saveError_duplicate:repD(name)or
mes:find'encode error'and
text.saveError_encode:repD(name)or
mes and
text.saveError_other:repD(name,mes)or
text.saveError_unknown:repD(name)
)
end
end
end
function isSafeFile(file,mes) function isSafeFile(file,mes)
if love.filesystem.getRealDirectory(file)~=SAVEDIR then if love.filesystem.getRealDirectory(file)~=SAVEDIR then
return true return true
@@ -23,13 +65,13 @@ function isSafeFile(file,mes)
end end
end end
function saveStats() function saveStats()
return FILE.save(STAT,'conf/data') return saveFile(STAT,'conf/data')
end end
function saveProgress() function saveProgress()
return FILE.save(RANKS,'conf/unlock') return saveFile(RANKS,'conf/unlock')
end end
function saveSettings() function saveSettings()
return FILE.save(SETTING,'conf/settings') return saveFile(SETTING,'conf/settings')
end end
function applyLanguage() function applyLanguage()
text=LANG.get(SETTING.locale) text=LANG.get(SETTING.locale)
@@ -263,16 +305,16 @@ function setField(P,page)
end end
end end
end end
function freshDate(mode) function freshDate(args)
if not mode then if not args then
mode="" args=""
end end
local date=os.date("%Y/%m/%d") local date=os.date("%Y/%m/%d")
if STAT.date~=date then if STAT.date~=date then
STAT.date=date STAT.date=date
STAT.todayTime=0 STAT.todayTime=0
getItem('zTicket',1) getItem('zTicket',1)
if not mode:find'q'then if not args:find'q'then
MES.new('info',text.newDay) MES.new('info',text.newDay)
end end
saveStats() saveStats()
@@ -297,6 +339,15 @@ function legalGameTime()--Check if today's playtime is legal
end end
return true return true
end end
do--function trySettingWarn()
local lastWarnTime=0
function trySettingWarn()
if TIME()-lastWarnTime>2.6 then
MES.new('warn',text.settingWarn,5)
end
lastWarnTime=TIME()
end
end
function mergeStat(stat,delta)--Merge delta stat. to global stat. function mergeStat(stat,delta)--Merge delta stat. to global stat.
for k,v in next,delta do for k,v in next,delta do
@@ -466,7 +517,7 @@ function gameOver()--Save record
D.date=os.date("%Y/%m/%d %H:%M") D.date=os.date("%Y/%m/%d %H:%M")
ins(L,p+1,D) ins(L,p+1,D)
if L[11]then L[11]=nil end if L[11]then L[11]=nil end
FILE.save(L,('record/%s.rec'):format(M.name),'l') saveFile(L,('record/%s.rec'):format(M.name),'-luaon')
end end
end end
end end
@@ -818,13 +869,20 @@ do--function pressKey(k)
end end
do--CUS/SETXXX(k) do--CUS/SETXXX(k)
local CUSTOMENV=CUSTOMENV local CUSTOMENV=CUSTOMENV
local warnList={
'das','arr','dascut','dropcut','sddas','sdarr',
'ihs','irs','ims','RS',
'FTLock','frameMul','highCam',
'VKSwitch','VKIcon','VKTrack','VKDodge',
'simpMode',
}
function CUSval(k)return function()return CUSTOMENV[k]end end function CUSval(k)return function()return CUSTOMENV[k]end end
function ROOMval(k)return function()return ROOMENV[k]end end function ROOMval(k)return function()return ROOMENV[k]end end
function SETval(k)return function()return SETTING[k]end end function SETval(k)return function()return SETTING[k]end end
function CUSrev(k)return function()CUSTOMENV[k]=not CUSTOMENV[k]end end function CUSrev(k)return function()CUSTOMENV[k]=not CUSTOMENV[k]end end
function ROOMrev(k)return function()ROOMENV[k]=not ROOMENV[k]end end function ROOMrev(k)return function()ROOMENV[k]=not ROOMENV[k]end end
function SETrev(k)return function()SETTING[k]=not SETTING[k]end end function SETrev(k)return function()if TABLE.find(warnList,k)then trySettingWarn()end SETTING[k]=not SETTING[k]end end
function CUSsto(k)return function(i)CUSTOMENV[k]=i end end function CUSsto(k)return function(i)CUSTOMENV[k]=i end end
function ROOMsto(k)return function(i)ROOMENV[k]=i end end function ROOMsto(k)return function(i)ROOMENV[k]=i end end
function SETsto(k)return function(i)SETTING[k]=i end end function SETsto(k)return function(i)if TABLE.find(warnList,k)then trySettingWarn()end SETTING[k]=i end end
end end

View File

@@ -20,140 +20,129 @@ RANK_COLORS={
{1,.5,.4}, {1,.5,.4},
{.95,.5,.95}, {.95,.5,.95},
} }
do--SVG_TITLE do--SVG_TITLE_FILL, SVG_TITLE_LINE
SVG_TITLE={ SVG_TITLE_FILL={
{ {
53, 60, 0,0,
1035, 0, 0,34,
964, 218, 63,34,
660, 218, 63,227,
391, 1300, 97,227,
231, 1154, 97,34,
415, 218, 160,34,
0, 218, 160,0,
}, },
{ {
716, 290, 126,60,
1429, 290, 244,60,
1312, 462, 244,94,
875, 489, 160,94,
821, 695, 160,127,
1148, 712, 230,127,
1017, 902, 230,161,
761, 924, 160,161,
707, 1127, 160,194,
1106, 1101, 244,194,
1198, 1300, 244,227,
465, 1300, 126,227,
}, },
{ {
1516, 287, 262,82,
2102, 290, 283,60,
2036, 464, 385,60,
1598, 465, 385,94,
1322, 905, 296,94,
1395, 1102, 296,194,
1819, 1064, 385,194,
1743, 1280, 385,227,
1286, 1310, 283,227,
1106, 902, 262,206,
}, },
{ {
2179, 290, 404,60,
2411, 290, 437,60,
2272, 688, 437,127,
2674, 666, 505,127,
2801, 290, 505,60,
3041, 290, 538,60,
2693, 1280, 538,227,
2464, 1280, 505,227,
2601, 879, 505,161,
2199, 897, 437,161,
2056, 1280, 437,227,
1828, 1280, 404,227,
}, },
{ {
3123, 290, 558,60,
3480, 290, 604,60,
3496, 480, 640,153,
3664, 290, 676,60,
4017, 294, 722,60,
3682, 1280, 722,227,
3453, 1280, 688,227,
3697, 578, 688,108,
3458, 843, 655,194,
3304, 842, 625,194,
3251, 561, 591,108,
3001, 1280, 591,227,
2779, 1280, 558,227,
}, },
{ {
4088, 290, 743,60,
4677, 290, 777,60,
4599, 501, 777,227,
4426, 502, 743,227,
4219, 1069,
4388, 1070,
4317, 1280,
3753, 1280,
3822, 1068,
3978, 1068,
4194, 504,
4016, 504,
}, },
{ {
4747, 290, 798,60,
4978, 295, 831,60,
4921, 464, 899,173,
5186, 850, 899,60,
5366, 290, 933,60,
5599, 295, 933,227,
5288, 1280, 899,227,
5051, 1280, 831,115,
5106, 1102, 831,227,
4836, 709, 798,227,
4641, 1280,
4406, 1280,
}, },
{ {
5814, 290, 950,82,
6370, 295, 971,60,
6471, 415, 1064,60,
6238, 1156, 1085,82,
6058, 1280, 1085,206,
5507, 1280, 1064,227,
5404, 1154, 971,227,
5635, 416, 950,206,
-- 5814, 290, 950,82,
-- 5878, 463,
5770, 542, 984,94,
5617, 1030, 984,194,
5676, 1105, 1051,194,
5995, 1106, 1051,94,
6100, 1029, 984,94,
6255, 541,
6199, 465,
5878, 463,
}, },
} }
for _,C in next,SVG_TITLE do for _,C in next,SVG_TITLE_FILL do
for i=1,#C do for i=1,#C do
C[i]=C[i]*.1626 C[i]=C[i]*.94
end end
end end
SVG_TITLE_LINE=TABLE.shift(SVG_TITLE_FILL)
SVG_TITLE_LINE[8],SVG_TITLE_LINE[9]={},{}
for j=1,16 do SVG_TITLE_LINE[8][j]=SVG_TITLE_FILL[8][j]end
for j=19,#SVG_TITLE_FILL[8]-2 do SVG_TITLE_LINE[9][j-18]=SVG_TITLE_FILL[8][j]end
end end
do--SVG_TITLE_FAN do--SVG_TITLE_FAN
SVG_TITLE_FAN={} SVG_TITLE_FAN={}
local sin,cos=math.sin,math.cos local sin,cos=math.sin,math.cos
for i=1,8 do for i=1,9 do
local L={} local L=TABLE.copy(SVG_TITLE_LINE[i])
SVG_TITLE_FAN[i]=L SVG_TITLE_FAN[i]=L
for j=1,#SVG_TITLE[i]do
L[j]=SVG_TITLE[i][j]
end
for j=1,#L,2 do for j=1,#L,2 do
local x,y=L[j],L[j+1]--0<x<3041, 290<y<1280 local x,y=L[j],L[j+1]--0<x<988, 290<y<1280
x,y=-(x+240+y*.3)*.002,(y-580)*.9 x,y=-(x+280)*.002,(y-580)*.9--X=ang, Y=dist
x,y=y*cos(x),-y*sin(x)--Rec-Pol-Rec x,y=y*cos(x),-y*sin(x)--Rec-Pol-Rec
L[j],L[j+1]=x,y+300 L[j],L[j+1]=x,y+300
end end
@@ -547,13 +536,12 @@ do--Game data tables
ROOMENV={ ROOMENV={
--Room config --Room config
capacity=10, capacity=10,
FTLock=true,
--Basic --Basic
drop=30, drop=30,lock=60,
lock=60, wait=0,fall=0,
wait=0, hang=5,hurry=1e99,
fall=0,
FTLock=true,
--Control --Control
nextCount=6, nextCount=6,

View File

@@ -16,8 +16,8 @@ return{
{"To New Players", {"To New Players",
"guide newbie noob", "guide newbie noob",
"help", "help",
"To new players that want to get better at the game:\n\tTwo principles:\n\t1. find a version with good controls (e.g. Techmino, Tetr.io, Tetris Online, Jstris, Tetr.js). Do not use those version used for programming practice.\n\t2. Build foundations in your skills (stable Techrashes using next queue to aid decisions), don't go for fancy T-Spins from the start.\n\n\tTwo main techniques:\n\t1. familiarize yourself with spawn locations of pieces, and the controls to move the piece into each location\n\t2. Plan ahead of where to put the pieces\nHere is a article written by a well-known player in Chinese Tetris community talking about advices to new players. Click the globe if you can read simplified Chinese.", "To new players that want to get better at the game:\n\tTwo principles:\n\t1. find a version with good controls (e.g. Techmino, Tetr.io, Tetris Online, Jstris, Tetr.js). Do not use those version used for programming practice.\n\t2. Build foundations in your skills (stable Techrashes using next queue to aid decisions), don't go for fancy T-Spins from the start.\n\n\tTwo main techniques:\n\t1. familiarize yourself with spawn locations of pieces, and the controls to move the piece into each location\n\t2. Plan ahead of where to put the pieces\nHere is a article written by a well-known player in Chinese Tetris community talking about advices to new players. Click the globe to read the translated article by User670.",
"https://bilibili.com/read/cv2352939", "https://github.com/user670/temp/blob/master/tips_to_those_new_to_top.md",
}, },
{"Learning T-spins", {"Learning T-spins",
"tspin learning study guide tips", "tspin learning study guide tips",

View File

@@ -15,6 +15,7 @@ return{
newDay="A new day, a new beginning!", newDay="A new day, a new beginning!",
playedLong="You have been playing for a long time. Time to a break!", playedLong="You have been playing for a long time. Time to a break!",
playedTooMuch="You have been playing for far too long! Techmino is fun, but remember to have some rests!", playedTooMuch="You have been playing for far too long! Techmino is fun, but remember to have some rests!",
settingWarn="Modifing uncommon setting, be careful!",
atkModeName={"Random","Badges","K.O.s","Attackers"}, atkModeName={"Random","Badges","K.O.s","Attackers"},
royale_remain="$1 Players Remains", royale_remain="$1 Players Remains",
@@ -66,11 +67,19 @@ return{
switchSpawnSFX="Please turn on the block spawn SFX!", switchSpawnSFX="Please turn on the block spawn SFX!",
needRestart="Restart to apply all changes", needRestart="Restart to apply all changes",
loadError_errorMode="'$1' loading failed: no load mode '$2'",
loadError_read="'$1' loading failed: read failed",
loadError_noFile="'$1' loading failed no file:",
loadError_other="'$1' loading failed: $2",
loadError_unknown="'$1' loading failed: unknown reason",
saveError_duplicate="'$1' saving failed: duplicated filename",
saveError_encode="'$1' saving failed: encode failed",
saveError_other="'$1' saving failed: $2",
saveError_unknown="'$1' saving failed: unknown reason",
copyDone="Copied!", copyDone="Copied!",
saveDone="Data saved", saveDone="Data saved",
saveError="Failed to save:",
saveError_duplicate="Duplicated filename",
loadError="Failed to load:",
exportSuccess="Exported successfully", exportSuccess="Exported successfully",
importSuccess="Imported successfully", importSuccess="Imported successfully",
dataCorrupted="Data corrupted", dataCorrupted="Data corrupted",
@@ -296,6 +305,8 @@ return{
lock="Lock Delay", lock="Lock Delay",
wait="Entry Delay", wait="Entry Delay",
fall="Line Delay", fall="Line Delay",
hang="Death Delay",
hurry="ARE Interruption",
capacity="Capacity", capacity="Capacity",
create="Create", create="Create",
@@ -330,6 +341,7 @@ return{
ctrl="Control Settings", ctrl="Control Settings",
key="Key Mappings", key="Key Mappings",
touch="Touch Settings", touch="Touch Settings",
showVK="Show Virtual Keys",
reTime="Start Delay", reTime="Start Delay",
RS="Rotation System", RS="Rotation System",
menuPos="Menu Button Pos.", menuPos="Menu Button Pos.",
@@ -461,7 +473,6 @@ return{
norm="Normal", norm="Normal",
pro="Advanced", pro="Advanced",
hide="Show Virtual Keys",
icon="Icon", icon="Icon",
sfx="SFX", sfx="SFX",
vib="VIB", vib="VIB",
@@ -480,6 +491,7 @@ return{
wait="Entry Delay", wait="Entry Delay",
fall="Line Delay", fall="Line Delay",
hang="Death Delay", hang="Death Delay",
hurry="ARE Interruption",
bg="Background", bg="Background",
bgm="Music", bgm="Music",
@@ -498,6 +510,7 @@ return{
eventSet="Rule Set", eventSet="Rule Set",
holdMode="Hold Mode",
nextCount="Next", nextCount="Next",
holdCount="Hold", holdCount="Hold",
infHold="Infinite Hold", infHold="Infinite Hold",
@@ -729,7 +742,7 @@ return{
['defender_l']= {"Defender", "LUNATIC", "Practice your defencing skills!"}, ['defender_l']= {"Defender", "LUNATIC", "Practice your defencing skills!"},
['dig_h']= {"Driller", "HARD", "Digging practice!"}, ['dig_h']= {"Driller", "HARD", "Digging practice!"},
['dig_u']= {"Driller", "ULTIMATE", "Digging practice!"}, ['dig_u']= {"Driller", "ULTIMATE", "Digging practice!"},
['bigbang']= {"Big Bang", "EASY", "All-spin tutorial!\n[Under construction]"}, ['clearRush']= {"Clear Rush", "NORMAL", "All-spin tutorial!\n[Under construction]"},
['c4wtrain_n']= {"C4W Training", "NORMAL", "Infinite combos"}, ['c4wtrain_n']= {"C4W Training", "NORMAL", "Infinite combos"},
['c4wtrain_l']= {"C4W Training", "LUNATIC", "Infinite combos"}, ['c4wtrain_l']= {"C4W Training", "LUNATIC", "Infinite combos"},
['pctrain_n']= {"PC Training", "NORMAL", "Perfect Clear practice"}, ['pctrain_n']= {"PC Training", "NORMAL", "Perfect Clear practice"},

View File

@@ -5,6 +5,7 @@ return{
newDay="[Anti-adicción] ¡Nuevo día, nuevo comienzo!", newDay="[Anti-adicción] ¡Nuevo día, nuevo comienzo!",
playedLong="[Anti-adicción] Estuviste jugando un buen rato hoy. Recuerda descansar de vez en cuando.", playedLong="[Anti-adicción] Estuviste jugando un buen rato hoy. Recuerda descansar de vez en cuando.",
playedTooMuch="[Anti-adicción] ¡Has jugado mucho por hoy! No puedes jugar más.", playedTooMuch="[Anti-adicción] ¡Has jugado mucho por hoy! No puedes jugar más.",
-- settingWarn="Modifing uncommon setting, be careful!",
atkModeName={"Al azar","Medallas","KOs","Atacantes"}, atkModeName={"Al azar","Medallas","KOs","Atacantes"},
royale_remain="$1 Jugadores Restantes", royale_remain="$1 Jugadores Restantes",
@@ -55,11 +56,19 @@ return{
switchSpawnSFX="Habilita los sonidos de aparición de las piezas ;)", switchSpawnSFX="Habilita los sonidos de aparición de las piezas ;)",
needRestart="Reinicia Techmino para que los cambios tengan efecto.", needRestart="Reinicia Techmino para que los cambios tengan efecto.",
-- loadError_errorMode="'$1' loading failed: no load mode '$2'",
-- loadError_read="'$1' loading failed: read failed",
-- loadError_noFile="'$1' loading failed no file:",
-- loadError_other="'$1' loading failed: $2",
-- loadError_unknown="'$1' loading failed: unknown reason",
-- saveError_duplicate="'$1' saving failed: duplicated filename",
-- saveError_encode="'$1' saving failed: encode failed",
-- saveError_other="'$1' saving failed: $2",
-- saveError_unknown="'$1' saving failed: unknown reason",
-- copyDone="Copied!", -- copyDone="Copied!",
saveDone="Datos guardados", saveDone="Datos guardados",
saveError="Error al guardar:",
saveError_duplicate="Archivo ya existente",
loadError="Error al cargar:",
exportSuccess="Exportado con éxito", exportSuccess="Exportado con éxito",
importSuccess="Importado con éxito", importSuccess="Importado con éxito",
dataCorrupted="Los datos están corruptos.", dataCorrupted="Los datos están corruptos.",
@@ -262,6 +271,8 @@ return{
lock="Retraso de Bloqueo", lock="Retraso de Bloqueo",
wait="Retraso de Spawneo", wait="Retraso de Spawneo",
fall="Retraso de Línea", fall="Retraso de Línea",
-- hang="Death Delay",
-- hurry="ARE Interruption",
capacity="Capacidad", capacity="Capacidad",
create="Crear", create="Crear",
@@ -296,6 +307,7 @@ return{
ctrl="Sensibilidad", ctrl="Sensibilidad",
key="Teclas", key="Teclas",
touch="Controles Táctiles", touch="Controles Táctiles",
showVK="Mostrar Tec. Virtual",
reTime="Retraso de Inicio", reTime="Retraso de Inicio",
RS="Sistema de Rotación", RS="Sistema de Rotación",
menuPos="Pos. del Botón de Menú", menuPos="Pos. del Botón de Menú",
@@ -426,7 +438,6 @@ return{
norm="Normal", norm="Normal",
pro="Profesional", pro="Profesional",
hide="Mostrar Tec. Virtual",
icon="Ícono", icon="Ícono",
sfx="SFX", sfx="SFX",
vib="Vibr.", vib="Vibr.",
@@ -445,6 +456,7 @@ return{
wait="Retraso de Spawneo", wait="Retraso de Spawneo",
fall="Retraso de Línea", fall="Retraso de Línea",
-- hang="Death Delay", -- hang="Death Delay",
-- hurry="ARE Interruption",
bg="Fondo", bg="Fondo",
bgm="Música", bgm="Música",
@@ -611,6 +623,9 @@ return{
reset="Reiniciar", reset="Reiniciar",
invis="A ciegas", invis="A ciegas",
}, },
app_arithmetic={
reset="Reiniciar",
},
savedata={ savedata={
export="Exportar al portapapeles", export="Exportar al portapapeles",
import="Importar de portapapeles", import="Importar de portapapeles",
@@ -686,7 +701,7 @@ return{
['defender_l']= {"Defensor", "Lunático", "¡Practica la defensa!"}, ['defender_l']= {"Defensor", "Lunático", "¡Practica la defensa!"},
['dig_h']= {"Downstack", "Difícil", "¡Practica el downstackeo!"}, ['dig_h']= {"Downstack", "Difícil", "¡Practica el downstackeo!"},
['dig_u']= {"Downstack", "Supremo", "¡Practica el downstackeo!"}, ['dig_u']= {"Downstack", "Supremo", "¡Practica el downstackeo!"},
['bigbang']= {"Big Bang", "Fácil", "¡Tutorial de All-spins!\n[Sin finalizar]"}, -- ['clearRush']= {"Clear Rush", "NORMAL", "All-spin tutorial!\n[Under construction]"},
['c4wtrain_n']= {"Entrenar C4W", "Normal", "Combos infinitos."}, ['c4wtrain_n']= {"Entrenar C4W", "Normal", "Combos infinitos."},
['c4wtrain_l']= {"Entrenar C4W", "Lunático", "Combos infinitos."}, ['c4wtrain_l']= {"Entrenar C4W", "Lunático", "Combos infinitos."},
['pctrain_n']= {"Entrenar PC", "Normal", "Modo sencillo para practicar Perfect Clears."}, ['pctrain_n']= {"Entrenar PC", "Normal", "Modo sencillo para practicar Perfect Clears."},

View File

@@ -5,6 +5,7 @@ return{
newDay="[Anti-addiction] Nouveau jour, nouveau commencement !", newDay="[Anti-addiction] Nouveau jour, nouveau commencement !",
playedLong="[Anti-addiction] Vous avez joué pendant un bon bout de temps aujourd'hui. Faites des pauses.", playedLong="[Anti-addiction] Vous avez joué pendant un bon bout de temps aujourd'hui. Faites des pauses.",
playedTooMuch="[Anti-addiction] Vous avez joué trop longtemps ! Vous ne pouvez plus jouer.", playedTooMuch="[Anti-addiction] Vous avez joué trop longtemps ! Vous ne pouvez plus jouer.",
-- settingWarn="Modifing uncommon setting, be careful!",
atkModeName={"Aléatoire","Badges","K.O.s faciles","Attaquants"}, atkModeName={"Aléatoire","Badges","K.O.s faciles","Attaquants"},
royale_remain="$1 Joueurs restants", royale_remain="$1 Joueurs restants",
@@ -56,11 +57,19 @@ return{
switchSpawnSFX="Activez les effets sonores d'apparition des pièces pour jouer", switchSpawnSFX="Activez les effets sonores d'apparition des pièces pour jouer",
needRestart="Fonctionnera dès la prochaine partie", needRestart="Fonctionnera dès la prochaine partie",
-- loadError_errorMode="'$1' loading failed: no load mode '$2'",
-- loadError_read="'$1' loading failed: read failed",
-- loadError_noFile="'$1' loading failed no file:",
-- loadError_other="'$1' loading failed: $2",
-- loadError_unknown="'$1' loading failed: unknown reason",
-- saveError_duplicate="'$1' saving failed: duplicated filename",
-- saveError_encode="'$1' saving failed: encode failed",
-- saveError_other="'$1' saving failed: $2",
-- saveError_unknown="'$1' saving failed: unknown reason",
-- copyDone="Copied!", -- copyDone="Copied!",
saveDone="Données sauvegardées", saveDone="Données sauvegardées",
saveError="Sauvegarde échouée : ",
-- saveError_duplicate="Duplicate filename",
loadError="Lecture échouée : ",
exportSuccess="Exporté avec succès", exportSuccess="Exporté avec succès",
importSuccess="Importé avec succès", importSuccess="Importé avec succès",
dataCorrupted="Données corrompues", dataCorrupted="Données corrompues",
@@ -258,6 +267,8 @@ return{
lock="Délai de verrouillage", lock="Délai de verrouillage",
wait="Délai d'apparition", wait="Délai d'apparition",
fall="Délai de ligne", fall="Délai de ligne",
-- hang="Death Delay",
-- hurry="ARE Interruption",
-- capacity="Capacity", -- capacity="Capacity",
-- create="Create", -- create="Create",
@@ -293,6 +304,7 @@ return{
ctrl="Paramètres de contrôle", ctrl="Paramètres de contrôle",
key="Touches", key="Touches",
touch="Boutons virtuels", touch="Boutons virtuels",
showVK="Montrer les touches virtuelles",
reTime="Délai de démarrage", reTime="Délai de démarrage",
RS="Système de rotation", RS="Système de rotation",
-- menuPos="Menu button pos.", -- menuPos="Menu button pos.",
@@ -427,7 +439,6 @@ return{
norm="Normal", norm="Normal",
pro="Professionel", pro="Professionel",
hide="Montrer les touches virtuelles",
icon="Icône", icon="Icône",
sfx="Sons", sfx="Sons",
vib="Vib.", vib="Vib.",
@@ -446,6 +457,7 @@ return{
wait="Délai d'apparition", wait="Délai d'apparition",
fall="Délai de ligne", fall="Délai de ligne",
-- hang="Death Delay", -- hang="Death Delay",
-- hurry="ARE Interruption",
bg="Arrière-plan", bg="Arrière-plan",
bgm="Musique", bgm="Musique",
@@ -612,6 +624,9 @@ return{
reset="Réinitialiser", reset="Réinitialiser",
invis="Aveugler", invis="Aveugler",
}, },
app_arithmetic={
reset="Réinitialiser",
},
savedata={ savedata={
-- export="Export to clipboard", -- export="Export to clipboard",
-- import="Import from clipboard", -- import="Import from clipboard",
@@ -690,7 +705,7 @@ return{
['defender_l']= {"Défendant", "LUNATIQUE", "Soyez défensifs !"}, ['defender_l']= {"Défendant", "LUNATIQUE", "Soyez défensifs !"},
['dig_h']= {"Perceuse", "DIFFICILE", "Essayez de creuser !"}, ['dig_h']= {"Perceuse", "DIFFICILE", "Essayez de creuser !"},
['dig_u']= {"Perceuse", "ULTIME", "Essayez de creuser !"}, ['dig_u']= {"Perceuse", "ULTIME", "Essayez de creuser !"},
['bigbang']= {"Big Bang", "FACILE", "Tutoriel All-Spin\nEn construction..."}, -- ['clearRush']= {"Clear Rush", "NORMAL", "All-spin tutorial!\n[Under construction]"},
['c4wtrain_n']= {"Mode essai C4W", "NORMAL", "Combos infinis."}, ['c4wtrain_n']= {"Mode essai C4W", "NORMAL", "Combos infinis."},
['c4wtrain_l']= {"Mode essai C4W", "LUNATIQUE", "Combos infinis."}, ['c4wtrain_l']= {"Mode essai C4W", "LUNATIQUE", "Combos infinis."},
['pctrain_n']= {"Mode essai PC", "NORMAL", "Mode Perfect Clear simple"}, ['pctrain_n']= {"Mode essai PC", "NORMAL", "Mode Perfect Clear simple"},

View File

@@ -6,6 +6,7 @@ return{
newDay="[Anti-vício] Novo dia, um começo novo!", newDay="[Anti-vício] Novo dia, um começo novo!",
playedLong="[Anti-vício] Você andou jogando bastante hoje. Certifique-se de fazer pausas.", playedLong="[Anti-vício] Você andou jogando bastante hoje. Certifique-se de fazer pausas.",
playedTooMuch="[Anti-vício] Você esteve jogando demais hoje! Você não pode jogar mais.", playedTooMuch="[Anti-vício] Você esteve jogando demais hoje! Você não pode jogar mais.",
-- settingWarn="Modifing uncommon setting, be careful!",
atkModeName={"Aleatório","Emblemas","K.O.s","Atacantes"}, atkModeName={"Aleatório","Emblemas","K.O.s","Atacantes"},
royale_remain="$1 Jogadores restantes", royale_remain="$1 Jogadores restantes",
@@ -56,11 +57,19 @@ return{
switchSpawnSFX="Switch on spawn SFX to play", switchSpawnSFX="Switch on spawn SFX to play",
needRestart="Funciona após reiniciar", needRestart="Funciona após reiniciar",
-- loadError_errorMode="'$1' loading failed: no load mode '$2'",
-- loadError_read="'$1' loading failed: read failed",
-- loadError_noFile="'$1' loading failed no file:",
-- loadError_other="'$1' loading failed: $2",
-- loadError_unknown="'$1' loading failed: unknown reason",
-- saveError_duplicate="'$1' saving failed: duplicated filename",
-- saveError_encode="'$1' saving failed: encode failed",
-- saveError_other="'$1' saving failed: $2",
-- saveError_unknown="'$1' saving failed: unknown reason",
-- copyDone="Copied!", -- copyDone="Copied!",
saveDone="Data Salva", saveDone="Data Salva",
saveError="Falha ao salvar:",
-- saveError_duplicate="Duplicate filename",
loadError="Falha ao ler:",
exportSuccess="Exportado com sucesso", exportSuccess="Exportado com sucesso",
importSuccess="Importado com sucesso", importSuccess="Importado com sucesso",
dataCorrupted="Data corrompida", dataCorrupted="Data corrompida",
@@ -284,6 +293,8 @@ return{
lock="Delay Trava", lock="Delay Trava",
wait="Delay Entrada", wait="Delay Entrada",
fall="Delay Linha", fall="Delay Linha",
-- hang="Death Delay",
-- hurry="ARE Interruption",
-- capacity="Capacity", -- capacity="Capacity",
-- create="Create", -- create="Create",
@@ -318,6 +329,7 @@ return{
ctrl="Config. controle", ctrl="Config. controle",
key="Map. teclas", key="Map. teclas",
touch="Config. toque", touch="Config. toque",
showVK="Mostrar tecla virtual",
reTime="Demora iniciação", reTime="Demora iniciação",
RS="Sistema de rotação", RS="Sistema de rotação",
-- menuPos="Menu button pos.", -- menuPos="Menu button pos.",
@@ -449,7 +461,6 @@ return{
norm="Normal", norm="Normal",
pro="Professional", pro="Professional",
hide="Mostrar tecla virtual",
icon="Icone", icon="Icone",
sfx="SFX", sfx="SFX",
vib="VIB", vib="VIB",
@@ -468,6 +479,7 @@ return{
wait="Delay Entrada", wait="Delay Entrada",
fall="Delay Linha", fall="Delay Linha",
-- hang="Death Delay", -- hang="Death Delay",
-- hurry="ARE Interruption",
bg="Fundo", bg="Fundo",
bgm="Música", bgm="Música",
@@ -642,6 +654,9 @@ return{
reset="Resetar", reset="Resetar",
invis="Cego", invis="Cego",
}, },
app_arithmetic={
reset="Resetar",
},
savedata={ savedata={
-- export="Export to clipboard", -- export="Export to clipboard",
-- import="Import from clipboard", -- import="Import from clipboard",
@@ -720,7 +735,7 @@ return{
['defender_l']= {"Defensor", "LUNÁTICO", "Prática de defensiva!"}, ['defender_l']= {"Defensor", "LUNÁTICO", "Prática de defensiva!"},
['dig_h']= {"Cavador", "DIFÍCIL", "Prática de cavar!"}, ['dig_h']= {"Cavador", "DIFÍCIL", "Prática de cavar!"},
['dig_u']= {"Cavador", "ULTIMATE", "Prática de cavar!"}, ['dig_u']= {"Cavador", "ULTIMATE", "Prática de cavar!"},
['bigbang']= {"Big Bang", "FÁCIL", "Tutorial de todos giros!\n[Em construção]"}, -- ['clearRush']= {"Clear Rush", "NORMAL", "All-spin tutorial!\n[Under construction]"},
['c4wtrain_n']= {"Treinamento C4W", "NORMAL", "Combos infinitos."}, ['c4wtrain_n']= {"Treinamento C4W", "NORMAL", "Combos infinitos."},
['c4wtrain_l']= {"Treinamento C4W", "LUNÁTICO", "Combos infinitos."}, ['c4wtrain_l']= {"Treinamento C4W", "LUNÁTICO", "Combos infinitos."},
['pctrain_n']= {"Treinamento PC", "NORMAL", "Modo simples de limpeza perfeita."}, ['pctrain_n']= {"Treinamento PC", "NORMAL", "Modo simples de limpeza perfeita."},

View File

@@ -58,11 +58,19 @@ return{
ai_mission="X!!!", ai_mission="X!!!",
needRestart="!!*#R#*!!", needRestart="!!*#R#*!!",
loadError_errorMode="'$1' ↑x!: no load mode '$2'",
loadError_read="'$1' ↑x!: read failed",
loadError_noFile="'$1' ↑oading failed no file:",
loadError_other="'$1' ↑x!: $2",
loadError_unknown="'$1' ↑x!: unknown reason",
saveError_duplicate="'$1' ↓x!: duplicated filename",
saveError_encode="'$1' ↓x!: encode failed",
saveError_other="'$1' ↓x!: $2",
saveError_unknown="'$1' ↓x!: unknown reason",
-- copyDone="Copied!", -- copyDone="Copied!",
saveDone="~~~", saveDone="~~~",
saveError="x!:",
saveError_duplicate="X←→X ?",
loadError="x!:",
exportSuccess="~Out~", exportSuccess="~Out~",
importSuccess="~In~", importSuccess="~In~",
dataCorrupted="XXXXX", dataCorrupted="XXXXX",
@@ -190,6 +198,8 @@ return{
lock="↓_", lock="↓_",
wait="→=", wait="→=",
fall="↓=", fall="↓=",
hang=":(=",
hurry="_x",
capacity="<0/?>", capacity="<0/?>",
create=">", create=">",
@@ -225,6 +235,7 @@ return{
ctrl="=?=", ctrl="=?=",
key="=?", key="=?",
touch="_?", touch="_?",
showVK="--?",
reTime="3-2-1", reTime="3-2-1",
RS="''?", RS="''?",
menuPos="←M→?", menuPos="←M→?",
@@ -354,7 +365,6 @@ return{
norm="-", norm="-",
pro="+", pro="+",
hide="--?",
icon="@?", icon="@?",
sfx="#!#", sfx="#!#",
vib="=~=", vib="=~=",
@@ -373,6 +383,7 @@ return{
wait="→=", wait="→=",
fall="↓=", fall="↓=",
hang=":(=", hang=":(=",
hurry="_x",
bg="{~}", bg="{~}",
bgm="(~)", bgm="(~)",

View File

@@ -11,6 +11,7 @@ return{fallback='zh',
}, },
playedLong="玩很久了, 给我注意点", playedLong="玩很久了, 给我注意点",
playedTooMuch="特么再敢玩眼睛瞎掉, 爬!", playedTooMuch="特么再敢玩眼睛瞎掉, 爬!",
settingWarn="别乱动,小心点",
royale_remain="剩 $1 人", royale_remain="剩 $1 人",
cmb={nil,"1连","2连","3连","4连","5连","6连","7连","8连","9连","10连!","11连!","12连!","13连!","14连!","15连!","16连!","17连!","18连!","19连!","Very 连"}, cmb={nil,"1连","2连","3连","4连","5连","6连","7连","8连","9连","10连!","11连!","12连!","13连!","14连!","15连!","16连!","17连!","18连!","19连!","Very 连"},
@@ -253,7 +254,7 @@ return{fallback='zh',
['defender_l']= {"防守", "疯狂", "防守练习"}, ['defender_l']= {"防守", "疯狂", "防守练习"},
['dig_h']= {"挖掘", "困难", "挖掘练习"}, ['dig_h']= {"挖掘", "困难", "挖掘练习"},
['dig_u']= {"挖掘", "极限", "挖掘练习"}, ['dig_u']= {"挖掘", "极限", "挖掘练习"},
['bigbang']= {"大爆炸", "简单", "All-spin入门\n还没做好"}, ['clearRush']= {"清版竞速", "普通", "舒服"},
['c4wtrain_n']= {"C4W练习", "普通", "无 限 连 击"}, ['c4wtrain_n']= {"C4W练习", "普通", "无 限 连 击"},
['c4wtrain_l']= {"C4W练习", "疯狂", "无 限 连 击"}, ['c4wtrain_l']= {"C4W练习", "疯狂", "无 限 连 击"},
['pctrain_n']= {"全清训练", "普通", "随便打打"}, ['pctrain_n']= {"全清训练", "普通", "随便打打"},

View File

@@ -15,6 +15,7 @@ return{
newDay="新的一天,新的开始~", newDay="新的一天,新的开始~",
playedLong="已经玩很久了!注意休息!", playedLong="已经玩很久了!注意休息!",
playedTooMuch="今天玩太久啦!打块好玩但也要适可而止哦~", playedTooMuch="今天玩太久啦!打块好玩但也要适可而止哦~",
settingWarn="正在修改不常用设置,小心操作!",
atkModeName={"随机","徽章","击杀","反击"}, atkModeName={"随机","徽章","击杀","反击"},
royale_remain="剩余 $1 名玩家", royale_remain="剩余 $1 名玩家",
@@ -66,11 +67,19 @@ return{
switchSpawnSFX="请开启方块出生音效", switchSpawnSFX="请开启方块出生音效",
needRestart="重新开始以生效", needRestart="重新开始以生效",
loadError_errorMode="文件 '$1' 读取失败:无加载模式 '$2'",
loadError_read="文件 '$1' 读取失败:读取失败",
loadError_noFile="文件 '$1' 读取失败:没有文件",
loadError_other="文件 '$1' 读取失败:$2",
loadError_unknown="文件 '$1' 读取失败:原因未知",
saveError_duplicate="文件 '$1' 保存失败:文件已存在",
saveError_encode="文件 '$1' 保存失败:编码错误",
saveError_other="文件 '$1' 保存失败:$2",
saveError_unknown="文件 '$1' 保存失败:原因未知",
copyDone="复制成功!", copyDone="复制成功!",
saveDone="保存成功!", saveDone="保存成功!",
saveError="保存失败:",
saveError_duplicate="文件名重复",
loadError="读取失败:",
exportSuccess="导出成功", exportSuccess="导出成功",
importSuccess="导入成功", importSuccess="导入成功",
dataCorrupted="数据损坏", dataCorrupted="数据损坏",
@@ -296,6 +305,8 @@ return{
lock="锁定延迟", lock="锁定延迟",
wait="出块等待", wait="出块等待",
fall="消行延迟", fall="消行延迟",
hang="窒息延迟",
hurry="ARE打断",
capacity="房间容量", capacity="房间容量",
create="创建", create="创建",
@@ -330,6 +341,7 @@ return{
ctrl="控制设置", ctrl="控制设置",
key="键位设置", key="键位设置",
touch="触屏设置", touch="触屏设置",
showVK="显示虚拟按键",
reTime="开局等待时间", reTime="开局等待时间",
RS="旋转系统", RS="旋转系统",
menuPos="菜单按钮位置", menuPos="菜单按钮位置",
@@ -460,7 +472,6 @@ return{
norm="标准", norm="标准",
pro="专业", pro="专业",
hide="显示虚拟按键",
icon="图标", icon="图标",
sfx="按键音效", sfx="按键音效",
vib="按键振动", vib="按键振动",
@@ -479,6 +490,7 @@ return{
wait="出块等待", wait="出块等待",
fall="消行延迟", fall="消行延迟",
hang="窒息延迟", hang="窒息延迟",
hurry="ARE打断",
bg="背景", bg="背景",
bgm="音乐", bgm="音乐",
@@ -656,6 +668,9 @@ return{
reset="重置", reset="重置",
invis="盲打", invis="盲打",
}, },
app_arithmetic={
reset="重置",
},
savedata={ savedata={
export="导出到剪切板", export="导出到剪切板",
import="从剪切板导入", import="从剪切板导入",
@@ -732,7 +747,7 @@ return{
['defender_l']= {"防守", "疯狂", "防守练习"}, ['defender_l']= {"防守", "疯狂", "防守练习"},
['dig_h']= {"挖掘", "困难", "挖掘练习"}, ['dig_h']= {"挖掘", "困难", "挖掘练习"},
['dig_u']= {"挖掘", "极限", "挖掘练习"}, ['dig_u']= {"挖掘", "极限", "挖掘练习"},
['bigbang']= {"大爆炸", "简单", "All-spin 入门教程\n施工中"}, ['clearRush']= {"清版竞速", "普通", "All-spin 入门教程\n施工中"},
['c4wtrain_n']= {"C4W练习", "普通", "无 限 连 击"}, ['c4wtrain_n']= {"C4W练习", "普通", "无 限 连 击"},
['c4wtrain_l']= {"C4W练习", "疯狂", "无 限 连 击"}, ['c4wtrain_l']= {"C4W练习", "疯狂", "无 限 连 击"},
['pctrain_n']= {"全清训练", "普通", "简易PC题库熟悉全清定式的组合"}, ['pctrain_n']= {"全清训练", "普通", "简易PC题库熟悉全清定式的组合"},
@@ -902,7 +917,7 @@ return{
"快去打一把100%极简看看会怎样", "快去打一把100%极简看看会怎样",
"锟斤拷锟斤拷锟斤拷", "锟斤拷锟斤拷锟斤拷",
"来学编程,好玩的", "来学编程,好玩的",
"老牌益智游戏了属于是", "老牌益智游戏了",
"连续pc有大量知识要背不过背出来后随手10连pc不是问题", "连续pc有大量知识要背不过背出来后随手10连pc不是问题",
"六连块总共有……?那不重要,不会做的(大概", "六连块总共有……?那不重要,不会做的(大概",
"论如何正确使用Unicode私用区定制字体", "论如何正确使用Unicode私用区定制字体",
@@ -924,13 +939,13 @@ return{
"你们考虑过Z酱的感受吗没有你们只考虑你自己。", "你们考虑过Z酱的感受吗没有你们只考虑你自己。",
"你说彩蛋?嗯…算是有,可以找找", "你说彩蛋?嗯…算是有,可以找找",
"你有一个好", "你有一个好",
"你知道吗:看主页机器人玩可能比较费电", "你知道吗[001]看主页机器人玩可能比较费电",
"你知道吗:全程不使用任何旋转键完成40行模式是有可能的", "你知道吗[002]全程不使用任何旋转键完成40行模式是有可能的",
"你知道吗:全程不使用左右移动键完成40行模式是有可能的", "你知道吗[003]全程不使用左右移动键完成40行模式是有可能的",
"你知道吗:停留在模式地图界面很费电", "你知道吗[004]停留在模式地图界面很费电",
"你知道吗:在其他(方块)游戏相关场合提及本游戏是很不礼貌的", "你知道吗[005]在其他(方块)游戏相关场合提及本游戏是很不礼貌的",
"你知道吗:O-Spin是在0.8.20 (Fantastic Global Update II)中诞生的", "你知道吗[006]O-Spin是在0.8.20 (Fantastic Global Update II)中诞生的",
"你知道吗:TRS旋转系统的最初形态在0.0.091726版本就存在了", "你知道吗[007]TRS旋转系统的最初形态在0.0.091726版本就存在了",
"你准备好了吗?", "你准备好了吗?",
"其实很多时候“吃键”是玩家对游戏机制不了解或者自己的操作问题导致的", "其实很多时候“吃键”是玩家对游戏机制不了解或者自己的操作问题导致的",
"其实S和Z有四个方向(状态),虽然看起来只有两个", "其实S和Z有四个方向(状态),虽然看起来只有两个",
@@ -948,6 +963,25 @@ return{
"少女祈祷中", "少女祈祷中",
"少玩点游戏,多注意眨眼和休息", "少玩点游戏,多注意眨眼和休息",
"深降了解一下", "深降了解一下",
"时间碎片[000] 2021/11/21开始tip加入这个版块",
"时间碎片[001] V0.7.9加入O-spin",
"时间碎片[002] V0.7.19加入语音系统",
"时间碎片[003] V0.7.22加入平滑下落",
"时间碎片[004] V0.8.5加入模式地图",
"时间碎片[005] V0.8.19加入五连块",
"时间碎片[006] V0.9.0加入自定义序列和模式",
"时间碎片[007] V0.10.0加入录像回放",
"时间碎片[008] V0.11.1加入小z词典",
"时间碎片[009] V0.12.2加入mod系统",
"时间碎片[010] V0.13.0联网对战测试",
"时间碎片[011] V0.13.2加入任意场地高度",
"时间碎片[012] V0.13.3加入控制台",
"时间碎片[013] V0.14.4加入第一首不是用Beepbox制作的BGM",
"时间碎片[014] V0.14.5加入第一首社区玩家自制BGM",
"时间碎片[015] V0.15.5加入录像回放菜单",
"时间碎片[016] V0.16.0应该是单次更新内容最多的(起码更新历史最长)",
"时间碎片[017] V0.16.2加入打击垫样式的音效室",
"时间碎片[018] V0.17.0加入手柄的摇杆和扳机支持",
"使用固定堆叠方法达成20TSD难度很低", "使用固定堆叠方法达成20TSD难度很低",
"试试用跳舞毯打块", "试试用跳舞毯打块",
"适度游戏益脑,沉迷游戏伤身,合理安排时间,享受健康生活", "适度游戏益脑,沉迷游戏伤身,合理安排时间,享受健康生活",
@@ -1037,18 +1071,18 @@ return{
"e^(πi)=-1", "e^(πi)=-1",
"e^(πi/2)=i", "e^(πi/2)=i",
"e^(πi/4)=(1+i)/√2", "e^(πi/4)=(1+i)/√2",
"Farter:“成天被夸赞‘好玩’的”", "Farter评[01]“成天被夸赞‘好玩’的”",
"Farter:“可以形成方块圈子小中心话题,同作者一起衍生一些概念与梗的”", "Farter评[02]“可以形成方块圈子小中心话题,同作者一起衍生一些概念与梗的”",
"Farter:“论方块的软工意义(就算这么小个范围内,各种取舍蒙混翻车现象都总会以很易懂的方式出现(”", "Farter评[03]“论方块的软工意义(就算这么小个范围内,各种取舍蒙混翻车现象都总会以很易懂的方式出现(”",
"Farter:“民间微创新”", "Farter评[04]“民间微创新”",
"Farter:“民间音lè与图案”", "Farter评[05]“民间音lè与图案”",
"Farter:“民间游戏设计”", "Farter评[06]“民间游戏设计”",
"Farter:“是方块爱好者研究平台”", "Farter评[07]“是方块爱好者研究平台”",
"Farter:“是方块萌新入坑接收器”", "Farter评[08]“是方块萌新入坑接收器”",
"Farter:“是居家旅行装逼必备”", "Farter评[09]“是居家旅行装逼必备”",
"Farter:“是民间UI动效艺术作品”", "Farter评[10]“是民间UI动效艺术作品”",
"Farter:“是一滩散乱的代码组成的蜜汁结构”", "Farter评[11]“是一滩散乱的代码组成的蜜汁结构”",
"Farter:“它是现在的techmino已发布版本”", "Farter评[12]“它是现在的techmino已发布版本”",
"fin neo iso 是满足tspin条件的特殊t2的名字", "fin neo iso 是满足tspin条件的特殊t2的名字",
"git commit", "git commit",
"git push -f", "git push -f",

View File

@@ -142,21 +142,21 @@ return{
['defender_l']= {"防守", "疯狂", "防守练习"}, ['defender_l']= {"防守", "疯狂", "防守练习"},
['dig_h']= {"挖掘", "困难", "挖掘练习"}, ['dig_h']= {"挖掘", "困难", "挖掘练习"},
['dig_u']= {"挖掘", "极限", "挖掘练习"}, ['dig_u']= {"挖掘", "极限", "挖掘练习"},
['bigbang']= {"大爆炸", "简单", "All-spin 入门教程\n施工中"}, ['clearRush']= {"清版竞速", "普通", "所有块的回旋入门\n还没做好"},
['c4wtrain_n']= {"中四宽练习", "普通", "无 限 连 击"}, ['c4wtrain_n']= {"中四宽练习", "普通", "无 限 连 击"},
['c4wtrain_l']= {"中四宽练习", "疯狂", "无 限 连 击"}, ['c4wtrain_l']= {"中四宽练习", "疯狂", "无 限 连 击"},
['pctrain_n']= {"全清训练", "普通", "简易全清题库,熟悉全清定式的组合"}, ['pctrain_n']= {"全清训练", "普通", "简易全清题库,熟悉全清定式的组合"},
['pctrain_l']= {"全清训练", "疯狂", "困难PC题库,强算力者进"}, ['pctrain_l']= {"全清训练", "疯狂", "困难全清题库,强算力者进"},
['pc_n']= {"全清挑战", "普通", "100行内刷全清"}, ['pc_n']= {"全清挑战", "普通", "100行内刷全清"},
['pc_h']= {"全清挑战", "困难", "100行内刷全清"}, ['pc_h']= {"全清挑战", "困难", "100行内刷全清"},
['pc_l']= {"全清挑战", "疯狂", "100行内刷全清"}, ['pc_l']= {"全清挑战", "疯狂", "100行内刷全清"},
['pc_inf']= {"无尽全清挑战", "", "你能连续做多少PC?"}, ['pc_inf']= {"无尽全清挑战", "", "你能连续做多少全清?"},
['tech_n']= {"科研", "普通", "禁止断B2B"}, ['tech_n']= {"科研", "普通", "禁止断满贯"},
['tech_n_plus']= {"科研", "普通+", "仅允许回旋与全清"}, ['tech_n_plus']= {"科研", "普通+", "仅允许回旋与全清"},
['tech_h']= {"科研", "困难", "禁止断B2B"}, ['tech_h']= {"科研", "困难", "禁止断满贯"},
['tech_h_plus']= {"科研", "困难+", "仅允许回旋与全清"}, ['tech_h_plus']= {"科研", "困难+", "仅允许回旋与全清"},
['tech_l']= {"科研", "疯狂", "禁止断B2B"}, ['tech_l']= {"科研", "疯狂", "禁止断满贯"},
['tech_l_plus']= {"科研", "疯狂+", "仅允许spin与PC"}, ['tech_l_plus']= {"科研", "疯狂+", "仅允许回旋与全清"},
['tech_finesse']= {"科研", "极简", "强制最简操作"}, ['tech_finesse']= {"科研", "极简", "强制最简操作"},
['tech_finesse_f']= {"科研", "极简+", "禁止普通消除,强制最简操作"}, ['tech_finesse_f']= {"科研", "极简+", "禁止普通消除,强制最简操作"},
['tsd_e']= {"T2挑战", "简单", "你能连续做几个T旋双清?"}, ['tsd_e']= {"T2挑战", "简单", "你能连续做几个T旋双清?"},

View File

@@ -15,6 +15,7 @@ return{
newDay="新的一天,新的开始!", newDay="新的一天,新的开始!",
playedLong="你已经玩了很长时间了。一定要好好休息!", playedLong="你已经玩了很长时间了。一定要好好休息!",
playedTooMuch="你玩得太久了!玩方块游戏很有趣,但现在是休息的时候了。", playedTooMuch="你玩得太久了!玩方块游戏很有趣,但现在是休息的时候了。",
settingWarn="修改设置时,请小心!",
atkModeName={"随机的","徽章","击败","攻击者"}, atkModeName={"随机的","徽章","击败","攻击者"},
royale_remain="剩余$1球员", royale_remain="剩余$1球员",
@@ -66,11 +67,19 @@ return{
switchSpawnSFX="请打开繁殖特技效果", switchSpawnSFX="请打开繁殖特技效果",
needRestart="请重试以使更改生效", needRestart="请重试以使更改生效",
loadError_errorMode="'$1' 加载失败:无加载模式 '$2'",
loadError_read="'$1' 加载失败:读取失败",
loadError_noFile="'$1' 加载失败:没有文件",
loadError_other="'$1' 加载失败:$2",
loadError_unknown="'$1' 加载失败:原因未知",
saveError_duplicate="'$1' 保存失败:文件名重复",
saveError_encode="'$1' 保存失败:编码失败",
saveError_other="'$1' 保存失败:$2",
saveError_unknown="'$1' 保存失败:原因未知",
copyDone="收到了!", copyDone="收到了!",
saveDone="保存的数据", saveDone="保存的数据",
saveError="未能保存:",
saveError_duplicate="重复文件名",
loadError="未能加载:",
exportSuccess="成功导出", exportSuccess="成功导出",
importSuccess="导入成功", importSuccess="导入成功",
dataCorrupted="数据损坏", dataCorrupted="数据损坏",
@@ -294,6 +303,8 @@ return{
lock="锁定延迟", lock="锁定延迟",
wait="进入延迟", wait="进入延迟",
fall="线路延迟", fall="线路延迟",
hang="毁灭延迟",
hurry="是打扰吗",
capacity="容量", capacity="容量",
create="创造", create="创造",
@@ -328,6 +339,7 @@ return{
ctrl="控制设置", ctrl="控制设置",
key="键映射", key="键映射",
touch="触摸设置", touch="触摸设置",
showVK="显示虚拟密钥",
reTime="启动延迟", reTime="启动延迟",
RS="轮换制", RS="轮换制",
menuPos="菜单按钮位置", menuPos="菜单按钮位置",
@@ -413,7 +425,6 @@ return{
ihs="初始持有", ihs="初始持有",
irs="初始旋转", irs="初始旋转",
ims="初始运动", ims="初始运动",
reset="重置",
}, },
setting_key={ setting_key={
a1="向左移动", a1="向左移动",
@@ -459,7 +470,6 @@ return{
norm="正常", norm="正常",
pro="专业的", pro="专业的",
hide="显示虚拟密钥",
icon="偶像", icon="偶像",
sfx="特技效果", sfx="特技效果",
vib="振动", vib="振动",
@@ -478,6 +488,7 @@ return{
wait="进入延迟", wait="进入延迟",
fall="线路延迟", fall="线路延迟",
hang="毁灭延迟", hang="毁灭延迟",
hurry="是打扰吗",
bg="背景", bg="背景",
bgm="音乐", bgm="音乐",
@@ -614,7 +625,6 @@ return{
revKB="逆转", revKB="逆转",
}, },
app_schulteG={ app_schulteG={
reset="重置",
rank="大小", rank="大小",
invis="英维斯", invis="英维斯",
disappear="隐藏", disappear="隐藏",
@@ -626,30 +636,25 @@ return{
app_AtoZ={ app_AtoZ={
level="水平仪", level="水平仪",
keyboard="键盘", keyboard="键盘",
reset="重置",
}, },
app_2048={ app_2048={
reset="重置",
invis="英维斯", invis="英维斯",
tapControl="抽头控制", tapControl="抽头控制",
skip="跳转", skip="跳转",
}, },
app_ten={ app_ten={
reset="重置",
next="下一个", next="下一个",
invis="英维斯", invis="英维斯",
fast="快速的", fast="快速的",
}, },
app_dtw={ app_dtw={
reset="重置",
color="颜色", color="颜色",
mode="模式", mode="模式",
bgm="血糖监测", bgm="血糖监测",
arcade="游乐中心", arcade="游乐中心",
}, },
app_link={ app_link={
reset="重置",
invis="英维斯", invis="英维斯",
}, },
savedata={ savedata={
@@ -728,7 +733,7 @@ return{
['defender_l']= {"防守者", "疯子", "练习你的防守技巧!"}, ['defender_l']= {"防守者", "疯子", "练习你的防守技巧!"},
['dig_h']= {"钻机", "硬的", "挖掘练习!"}, ['dig_h']= {"钻机", "硬的", "挖掘练习!"},
['dig_u']= {"钻机", "终极", "挖掘练习!"}, ['dig_u']= {"钻机", "终极", "挖掘练习!"},
['bigbang']= {"大爆炸", "容易", "所有旋转教程\n[在建]"}, ['clearRush']= {"清晰的冲", "普通", "所有旋转教程\n[在建]"},
['c4wtrain_n']= {"C4W训练", "正常", "无限组合"}, ['c4wtrain_n']= {"C4W训练", "正常", "无限组合"},
['c4wtrain_l']= {"C4W训练", "疯子", "无限组合"}, ['c4wtrain_l']= {"C4W训练", "疯子", "无限组合"},
['pctrain_n']= {"电脑培训", "正常", "完美清晰的实践"}, ['pctrain_n']= {"电脑培训", "正常", "完美清晰的实践"},
@@ -760,7 +765,7 @@ return{
['infinite_dig']= {"无限:挖掘", "", "挖,挖,挖"}, ['infinite_dig']= {"无限:挖掘", "", "挖,挖,挖"},
['marathon_inf']= {"马拉松", "无尽", "无尽马拉松"}, ['marathon_inf']= {"马拉松", "无尽", "无尽马拉松"},
['custom_clear']= {"习俗", "正常"} , ['custom_clear']= {"习俗", "正常"},
['custom_puzzle']= {"习俗", "令人费解的"}, ['custom_puzzle']= {"习俗", "令人费解的"},
}, },
} }

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ Gameplay:
Play until the end or achieve the level's goal to win. Play until the end or achieve the level's goal to win.
Rotation system: Rotation system:
Uses Techmino's custom rotation system. Too lazy to write the details Uses TRS (Techmino Rotation System) by default. The game allows players to choose other commonly used rotation systems (generally unnecessary)
Spin detection: Spin detection:
Satisfies "3 corner" rule +2 points Satisfies "3 corner" rule +2 points
@@ -87,4 +87,4 @@ Custom mode:
empty cells can be in any state; empty cells can be in any state;
regular colored cells have to be made of the corresponding block; regular colored cells have to be made of the corresponding block;
garbage-colored cells can be any block but not air. garbage-colored cells can be any block but not air.
Once you make the shape, you will win. Once you make the shape, you will win.

View File

@@ -5,7 +5,7 @@
尝试存活更久,或者完成目标即胜利. 尝试存活更久,或者完成目标即胜利.
旋转系统: 旋转系统:
使用Techmino专属旋转系统,具体太复杂并且随时可能更改所以不写在这里,可以去parts/kicklist.lua看 默认使用Techmino专属旋转系统TRS,允许玩家自选其他较常用的旋转系统(一般不必要)
spin判定: spin判定:
满足三角判定+2分 满足三角判定+2分

View File

@@ -17,7 +17,7 @@ return{
{name='dig_100l', x=-600, y=-200, size=40,shape=1,icon="dig_sprint", unlock={'dig_400l'}}, {name='dig_100l', x=-600, y=-200, size=40,shape=1,icon="dig_sprint", unlock={'dig_400l'}},
{name='dig_400l', x=-800, y=-200, size=40,shape=1,icon="dig_sprint"}, {name='dig_400l', x=-800, y=-200, size=40,shape=1,icon="dig_sprint"},
{name='marathon_n', x=0, y=-600, size=60,shape=1,icon="marathon", unlock={'marathon_h','solo_e','round_e','blind_e','classic_e','survivor_e','bigbang','zen'}}, {name='marathon_n', x=0, y=-600, size=60,shape=1,icon="marathon", unlock={'marathon_h','solo_e','round_e','blind_e','classic_e','survivor_e','clearRush','zen'}},
{name='marathon_h', x=0, y=-800, size=50,shape=1,icon="marathon", unlock={'master_n','strategy_e'}}, {name='marathon_h', x=0, y=-800, size=50,shape=1,icon="marathon", unlock={'master_n','strategy_e'}},
{name='solo_e', x=-600, y=-1000, size=40,shape=1,icon="solo", unlock={'solo_n'}}, {name='solo_e', x=-600, y=-1000, size=40,shape=1,icon="solo", unlock={'solo_n'}},
@@ -48,7 +48,7 @@ return{
{name='strategy_e', x=-150, y=-1030, size=40,shape=3,icon="master"}, {name='strategy_e', x=-150, y=-1030, size=40,shape=3,icon="master"},
{name='strategy_h', x=-200, y=-1160, size=35,shape=3,icon="master"}, {name='strategy_h', x=-200, y=-1160, size=35,shape=3,icon="master"},
{name='strategy_u', x=-250, y=-1290, size=30,shape=3,icon="master"}, {name='strategy_u', x=-250, y=-1290, size=30,shape=2,icon="master"},
{name='blind_e', x=150, y=-700, size=40,shape=1,icon="hidden", unlock={'blind_n'}}, {name='blind_e', x=150, y=-700, size=40,shape=1,icon="hidden", unlock={'blind_n'}},
{name='blind_n', x=150, y=-800, size=40,shape=1,icon="hidden", unlock={'blind_h'}}, {name='blind_n', x=150, y=-800, size=40,shape=1,icon="hidden", unlock={'blind_h'}},
@@ -76,7 +76,7 @@ return{
{name='dig_h', x=700, y=-800, size=40,shape=1,icon="dig", unlock={'dig_u'}}, {name='dig_h', x=700, y=-800, size=40,shape=1,icon="dig", unlock={'dig_u'}},
{name='dig_u', x=700, y=-1000, size=40,shape=1,icon="dig"}, {name='dig_u', x=700, y=-1000, size=40,shape=1,icon="dig"},
{name='bigbang', x=400, y=-400, size=50,shape=1,icon="bigbang", unlock={'c4wtrain_n','pctrain_n','sprintAtk'}}, {name='clearRush', x=400, y=-400, size=50,shape=1,icon="bigbang", unlock={'c4wtrain_n','pctrain_n','sprintAtk'}},
{name='c4wtrain_n', x=700, y=-400, size=40,shape=1,icon="pc", unlock={'c4wtrain_l'}}, {name='c4wtrain_n', x=700, y=-400, size=40,shape=1,icon="pc", unlock={'c4wtrain_l'}},
{name='c4wtrain_l', x=900, y=-400, size=40,shape=1,icon="pc"}, {name='c4wtrain_l', x=900, y=-400, size=40,shape=1,icon="pc"},

View File

@@ -3,7 +3,7 @@ return{
das=8,arr=1, das=8,arr=1,
drop=30,lock=30, drop=30,lock=30,
holdCount=0, holdCount=0,
eventSet='bigbang', eventSet='clearRush',
bg='blockhole',bgm='peak', bg='blockhole',bgm='peak',
}, },
score=function(P)return{P.modeData.stage,P.stat.time}end, score=function(P)return{P.modeData.stage,P.stat.time}end,

View File

@@ -240,8 +240,8 @@ function NET.uploadSave()
{section=3,data=STRING.packTable(SETTING)}, {section=3,data=STRING.packTable(SETTING)},
{section=4,data=STRING.packTable(KEY_MAP)}, {section=4,data=STRING.packTable(KEY_MAP)},
{section=5,data=STRING.packTable(VK_ORG)}, {section=5,data=STRING.packTable(VK_ORG)},
{section=6,data=STRING.packTable(FILE.load('conf/vkSave1'))}, {section=6,data=STRING.packTable(loadFile('conf/vkSave1'))},
{section=7,data=STRING.packTable(FILE.load('conf/vkSave2'))}, {section=7,data=STRING.packTable(loadFile('conf/vkSave2'))},
}..'}}') }..'}}')
MES.new('info',"Uploading") MES.new('info',"Uploading")
end end
@@ -282,13 +282,13 @@ function NET.loadSavedData(sections)
applyAllSettings() applyAllSettings()
TABLE.cover(NET.cloudData.keyMap,KEY_MAP) TABLE.cover(NET.cloudData.keyMap,KEY_MAP)
success=success and FILE.save(KEY_MAP,'conf/key') success=success and saveFile(KEY_MAP,'conf/key')
TABLE.cover(NET.cloudData.VK_org,VK_ORG) TABLE.cover(NET.cloudData.VK_org,VK_ORG)
success=success and FILE.save(VK_ORG,'conf/virtualkey') success=success and saveFile(VK_ORG,'conf/virtualkey')
success=success and FILE.save(NET.cloudData.vkSave1,'conf/vkSave1') success=success and saveFile(NET.cloudData.vkSave1,'conf/vkSave1')
success=success and FILE.save(NET.cloudData.vkSave2,'conf/vkSave2') success=success and saveFile(NET.cloudData.vkSave2,'conf/vkSave2')
if success then if success then
MES.new('check',text.saveDone) MES.new('check',text.saveDone)
end end
@@ -460,7 +460,7 @@ function NET.updateWS_user()
if res.uid then if res.uid then
USER.uid=res.uid USER.uid=res.uid
USER.authToken=res.authToken USER.authToken=res.authToken
FILE.save(USER,'conf/user') saveFile(USER,'conf/user')
if SCN.cur=='login'then if SCN.cur=='login'then
SCN.back() SCN.back()
end end

View File

@@ -1,5 +1,6 @@
return{ return{
{font=100,name="☆★白羽★☆"}, {font=100,name="☆★白羽★☆"},
{font=100,name="[*浩]"},
{font=65,name="那没事了(T6300)"}, {font=65,name="那没事了(T6300)"},
{font=65,name="加油啊,钉钉动了的大哥哥(T3228)"}, {font=65,name="加油啊,钉钉动了的大哥哥(T3228)"},
@@ -28,6 +29,8 @@ return{
{font=65,name="怀沙"}, {font=65,name="怀沙"},
{font=65,name="星街书婉"}, {font=65,name="星街书婉"},
{font=65,name="老板来两份薯条"}, {font=65,name="老板来两份薯条"},
{font=65,name="[**昆]"},
{font=65,name="[**浩]"},
{font=25,name="八零哥"}, {font=25,name="八零哥"},
{font=25,name="蕴空之灵"}, {font=25,name="蕴空之灵"},
@@ -75,7 +78,7 @@ return{
{font=25,name="[*炎]"}, {font=25,name="[*炎]"},
{font=25,name="[*Y]"}, {font=25,name="[*Y]"},
{font=25,name="aaa222"}, {font=25,name="aaa222"},
{font=25,name="[**城]"}, {font=25,name="人偶"},
{font=25,name="cnDD"}, {font=25,name="cnDD"},
{font=25,name="红桃老给"}, {font=25,name="红桃老给"},
{font=25,name="昭庭玲秋"}, {font=25,name="昭庭玲秋"},
@@ -121,4 +124,7 @@ return{
{font=25,name="小丘"}, {font=25,name="小丘"},
{font=25,name="Techtris"}, {font=25,name="Techtris"},
{font=25,name="费尔特林"}, {font=25,name="费尔特林"},
{font=25,name="零醇丘卡"},
{font=25,name="Hathtiz"},
{font=25,name="江江江江17"},
} }

View File

@@ -170,7 +170,7 @@ local function _drawField(P,showInvis)
local V,F=P.visTime,P.field local V,F=P.visTime,P.field
local start=int((P.fieldBeneath+P.fieldUp)/30+1) local start=int((P.fieldBeneath+P.fieldUp)/30+1)
local texture=P.skinLib local texture=P.skinLib
if P.falling==-1 then--Blocks only if P.falling==0 then--Blocks only
if ENV.upEdge then if ENV.upEdge then
gc_setShader(shader_lighter) gc_setShader(shader_lighter)
gc_translate(0,-4) gc_translate(0,-4)
@@ -782,7 +782,7 @@ function draw.norm(P,repMode)
_drawFXs(P) _drawFXs(P)
--Draw current block --Draw current block
if P.cur and P.waiting==-1 then if P.alive and P.cur then
local C=P.cur local C=P.cur
local curColor=C.color local curColor=C.color
@@ -981,7 +981,6 @@ function draw.small(P)
end end
function draw.demo(P) function draw.demo(P)
local ENV=P.gameEnv local ENV=P.gameEnv
local curColor=P.cur.color
--Camera --Camera
gc_push('transform') gc_push('transform')
@@ -997,7 +996,8 @@ function draw.demo(P)
gc_translate(0,600) gc_translate(0,600)
_drawField(P) _drawField(P)
_drawFXs(P) _drawFXs(P)
if P.cur and P.waiting==-1 then if P.alive and P.cur then
local curColor=P.cur.color
if ENV.ghost then if ENV.ghost then
drawGhost[ENV.ghostType](P.cur.bk,P.curX,P.ghoY,ENV.ghost,P.skinLib,curColor) drawGhost[ENV.ghostType](P.cur.bk,P.curX,P.ghoY,ENV.ghost,P.skinLib,curColor)
end end

View File

@@ -3,7 +3,6 @@ return{
dascut=0,dropcut=0, dascut=0,dropcut=0,
sddas=2,sdarr=2, sddas=2,sdarr=2,
ihs=true,irs=true,ims=true, ihs=true,irs=true,ims=true,
hang=0,FTLock=true,
ghostType='gray', ghostType='gray',
block=true,ghost=.3,center=1, block=true,ghost=.3,center=1,
@@ -30,6 +29,7 @@ return{
drop=60,lock=60, drop=60,lock=60,
wait=0,fall=0, wait=0,fall=0,
hang=5,hurry=1e99,
bone=false, bone=false,
lockout=false, lockout=false,
fieldH=20,heightLimit=1e99, fieldH=20,heightLimit=1e99,
@@ -69,4 +69,5 @@ return{
bg='none',bgm='race', bg='none',bgm='race',
allowMod=true, allowMod=true,
FTLock=true,
} }

View File

@@ -36,54 +36,6 @@ local function _getNewStatTable()
end end
return T return T
end end
local playerActions={
Player.act_moveLeft, --1
Player.act_moveRight, --2
Player.act_rotRight, --3
Player.act_rotLeft, --4
Player.act_rot180, --5
Player.act_hardDrop, --6
Player.act_softDrop, --7
Player.act_hold, --8
Player.act_func1, --9
Player.act_func2, --10
Player.act_insLeft, --11
Player.act_insRight, --12
Player.act_insDown, --13
Player.act_down1, --14
Player.act_down4, --15
Player.act_down10, --16
Player.act_dropLeft, --17
Player.act_dropRight, --18
Player.act_zangiLeft, --19
Player.act_zangiRight,--20
}
local function _pressKey(P,keyID)
if P.keyAvailable[keyID]and P.alive then
P.keyPressing[keyID]=true
playerActions[keyID](P)
P.stat.key=P.stat.key+1
end
end
local function _releaseKey(P,keyID)
P.keyPressing[keyID]=false
end
local function _pressKey_Rec(P,keyID)
if P.keyAvailable[keyID]and P.alive then
local L=GAME.rep
ins(L,P.frameRun)
ins(L,keyID)
P.keyPressing[keyID]=true
playerActions[keyID](P)
P.stat.key=P.stat.key+1
end
end
local function _releaseKey_Rec(P,keyID)
local L=GAME.rep
ins(L,P.frameRun)
ins(L,32+keyID)
P.keyPressing[keyID]=false
end
local function _newEmptyPlayer(id,mini) local function _newEmptyPlayer(id,mini)
local P={id=id} local P={id=id}
PLAYERS[id]=P PLAYERS[id]=P
@@ -92,15 +44,6 @@ local function _newEmptyPlayer(id,mini)
--Inherit functions of Player class --Inherit functions of Player class
for k,v in next,Player do P[k]=v end for k,v in next,Player do P[k]=v end
--Set key/timer event
if P.id==1 and GAME.recording then
P.pressKey=_pressKey_Rec
P.releaseKey=_releaseKey_Rec
else
P.pressKey=_pressKey
P.releaseKey=_releaseKey
end
--Field position --Field position
P.swingOffset={--Shake FX P.swingOffset={--Shake FX
x=0,y=0, x=0,y=0,
@@ -195,7 +138,7 @@ local function _newEmptyPlayer(id,mini)
]] ]]
P.movDir,P.moving,P.downing=0,0,0--Last move key,DAS charging,downDAS charging P.movDir,P.moving,P.downing=0,0,0--Last move key,DAS charging,downDAS charging
P.dropDelay,P.lockDelay=0,0 P.dropDelay,P.lockDelay=0,0
P.waiting,P.falling=-1,-1 P.waiting,P.falling=0,0
P.freshTime=0 P.freshTime=0
P.spinLast=false P.spinLast=false
P.ctrlCount=0--Key press time, for finesse check P.ctrlCount=0--Key press time, for finesse check

View File

@@ -200,10 +200,321 @@ function Player:createBeam(R,send)
end end
--------------------------</FX>-------------------------- --------------------------</FX>--------------------------
--------------------------<Action>--------------------------
function Player:_deepDrop()
local CB=self.cur.bk
local y=self.curY-1
while self:ifoverlap(CB,self.curX,y)and y>0 do
y=y-1
end
if y>0 then
self.ghoY=y
self:createDropFX()
self.curY=y
self:freshBlock('move')
SFX.play('swipe')
end
end
function Player:act_moveLeft(auto)
if not auto then
self.ctrlCount=self.ctrlCount+1
end
self.movDir=-1
if self.control and self.waiting==0 then
if self.cur and not self:ifoverlap(self.cur.bk,self.curX-1,self.curY)then
self:createMoveFX('left')
self.curX=self.curX-1
self:freshBlock('move')
if not auto then
self.moving=0
end
self.spinLast=false
else
self.moving=self.gameEnv.das
end
else
self.moving=0
end
end
function Player:act_moveRight(auto)
if not auto then
self.ctrlCount=self.ctrlCount+1
end
self.movDir=1
if self.control and self.waiting==0 then
if self.cur and not self:ifoverlap(self.cur.bk,self.curX+1,self.curY)then
self:createMoveFX('right')
self.curX=self.curX+1
self:freshBlock('move')
if not auto then
self.moving=0
end
self.spinLast=false
else
self.moving=self.gameEnv.das
end
else
self.moving=0
end
end
function Player:act_rotRight()
if self.control and self.cur then
self.ctrlCount=self.ctrlCount+1
self:spin(1)
self.keyPressing[3]=false
end
end
function Player:act_rotLeft()
if self.control and self.cur then
self.ctrlCount=self.ctrlCount+1
self:spin(3)
self.keyPressing[4]=false
end
end
function Player:act_rot180()
if self.control and self.cur then
self.ctrlCount=self.ctrlCount+2
self:spin(2)
self.keyPressing[5]=false
end
end
function Player:act_hardDrop()
local ENV=self.gameEnv
if self.control and self.cur then
if self.lastPiece.autoLock and self.frameRun-self.lastPiece.frame<ENV.dropcut then
SFX.play('drop_cancel',.3)
else
if self.curY>self.ghoY then
self:createDropFX()
self.curY=self.ghoY
self.spinLast=false
if self.sound then
SFX.play('drop',nil,self:getCenterX()*.15)
if SETTING.vib>0 then VIB(SETTING.vib+1)end
end
end
if ENV.shakeFX then
self.swingOffset.vy=.6
self.swingOffset.va=self.swingOffset.va+self:getCenterX()*6e-4
end
self.lockDelay=-1
self.keyPressing[6]=false
self:drop()
end
end
end
function Player:act_softDrop()
self.downing=1
if self.control and self.cur then
if self.curY>self.ghoY then
self.curY=self.curY-1
self:freshBlock('fresh')
self.spinLast=false
self:checkTouchSound()
elseif self.gameEnv.deepdrop then
self:_deepdrop()
end
end
end
function Player:act_hold()
if self.control and self.cur then
if self:hold()then
self.keyPressing[8]=false
end
end
end
function Player:act_func1()
self.gameEnv.fkey1(self)
end
function Player:act_func2()
self.gameEnv.fkey2(self)
end
function Player:act_insLeft(auto)
if not self.cur then
return
end
local x0=self.curX
while not self:ifoverlap(self.cur.bk,self.curX-1,self.curY)do
self:createMoveFX('left')
self.curX=self.curX-1
self:freshBlock('move',true)
end
if self.curX~=x0 then
self.spinLast=false
self:checkTouchSound()
end
if self.gameEnv.shakeFX then
self.swingOffset.vx=-1.5
end
if auto then
if self.ctrlCount==0 then
self.ctrlCount=1
end
else
self.ctrlCount=self.ctrlCount+1
end
end
function Player:act_insRight(auto)
if not self.cur then
return
end
local x0=self.curX
while not self:ifoverlap(self.cur.bk,self.curX+1,self.curY)do
self:createMoveFX('right')
self.curX=self.curX+1
self:freshBlock('move',true)
end
if self.curX~=x0 then
self.spinLast=false
self:checkTouchSound()
end
if self.gameEnv.shakeFX then
self.swingOffset.vx=1.5
end
if auto then
if self.ctrlCount==0 then
self.ctrlCount=1
end
else
self.ctrlCount=self.ctrlCount+1
end
end
function Player:act_insDown()
if self.cur and self.curY>self.ghoY then
local ENV=self.gameEnv
self:createDropFX()
if ENV.shakeFX then
self.swingOffset.vy=.5
end
self.curY=self.ghoY
self.lockDelay=ENV.lock
self.spinLast=false
self:freshBlock('fresh')
self:checkTouchSound()
end
end
function Player:act_down1()
if self.cur then
if self.curY>self.ghoY then
self:createMoveFX('down')
self.curY=self.curY-1
self:freshBlock('fresh')
self.spinLast=false
elseif self.gameEnv.deepdrop then
self:_deepdrop()
end
end
end
function Player:act_down4()
if self.cur then
if self.curY>self.ghoY then
local ghoY0=self.ghoY
self.ghoY=max(self.curY-4,self.ghoY)
self:createDropFX()
self.curY,self.ghoY=self.ghoY,ghoY0
self:freshBlock('fresh')
self.spinLast=false
elseif self.gameEnv.deepdrop then
self:_deepdrop()
end
end
end
function Player:act_down10()
if self.cur then
if self.curY>self.ghoY then
local ghoY0=self.ghoY
self.ghoY=max(self.curY-0,self.ghoY)
self:createDropFX()
self.curY,self.ghoY=self.ghoY,ghoY0
self:freshBlock('fresh')
self.spinLast=false
elseif self.gameEnv.deepdrop then
self:_deepdrop()
end
end
end
function Player:act_dropLeft()
if self.cur then
self:act_insLeft()
self:act_hardDrop()
end
end
function Player:act_dropRight()
if self.cur then
self:act_insRight()
self:act_hardDrop()
end
end
function Player:act_zangiLeft()
if self.cur then
self:act_insLeft()
self:act_insDown()
self:act_insRight()
self:act_hardDrop()
end
end
function Player:act_zangiRight()
if self.cur then
self:act_insRight()
self:act_insDown()
self:act_insLeft()
self:act_hardDrop()
end
end
--------------------------</Action>--------------------------
--------------------------<Method>-------------------------- --------------------------<Method>--------------------------
local playerActions={
Player.act_moveLeft, --1
Player.act_moveRight, --2
Player.act_rotRight, --3
Player.act_rotLeft, --4
Player.act_rot180, --5
Player.act_hardDrop, --6
Player.act_softDrop, --7
Player.act_hold, --8
Player.act_func1, --9
Player.act_func2, --10
Player.act_insLeft, --11
Player.act_insRight, --12
Player.act_insDown, --13
Player.act_down1, --14
Player.act_down4, --15
Player.act_down10, --16
Player.act_dropLeft, --17
Player.act_dropRight, --18
Player.act_zangiLeft, --19
Player.act_zangiRight,--20
}function Player:pressKey(keyID)
if self.keyAvailable[keyID]and self.alive then
if self.waiting>self.gameEnv.hurry then
self.waiting=self.gameEnv.hurry
if self.waiting==0 and self.falling==0 then
self:popNext()
end
end
self.keyPressing[keyID]=true
playerActions[keyID](self)
self.stat.key=self.stat.key+1
if self.id==1 and GAME.recording then
local L=GAME.rep
ins(L,self.frameRun)
ins(L,keyID)
end
end
end
function Player:releaseKey(keyID)
self.keyPressing[keyID]=false
if self.id==1 and GAME.recording then
local L=GAME.rep
ins(L,self.frameRun)
ins(L,32+keyID)
end
end
function Player:newTask(code,...) function Player:newTask(code,...)
local thread=coroutine.create(code) local thread=coroutine.create(code)
resume(thread,self,...) assert(resume(thread,self,...))
if status(thread)~='dead'then if status(thread)~='dead'then
ins(self.tasks,{ ins(self.tasks,{
thread=thread, thread=thread,
@@ -719,6 +1030,16 @@ function Player:_removeClearedLines()
FREEROW.discard(rem(self.visTime,h)) FREEROW.discard(rem(self.visTime,h))
end end
end end
function Player:_updateFalling(val)
self.falling=val
if self.falling==0 then
local L=#self.clearingRow
if self.sound and self.gameEnv.fall>0 and #self.field+L>self.clearingRow[L]then
SFX.play('fall')
end
TABLE.cut(self.clearingRow)
end
end
function Player:removeTopClearingFX() function Player:removeTopClearingFX()
for i=#self.clearingRow,1,-1 do for i=#self.clearingRow,1,-1 do
if self.clearingRow[i]>#self.field then if self.clearingRow[i]>#self.field then
@@ -728,7 +1049,7 @@ function Player:removeTopClearingFX()
end end
end end
if self.clearingRow[1]then if self.clearingRow[1]then
self.falling=self.gameEnv.fall self:_updateFalling(self.gameEnv.fall)
return false return false
else else
return true return true
@@ -1004,12 +1325,13 @@ function Player:hold_swap(ifpre)
self.stat.hold=self.stat.hold+1 self.stat.hold=self.stat.hold+1
end end
function Player:hold(ifpre) function Player:hold(ifpre)
if self.holdTime>0 and(ifpre or self.waiting==-1)then if self.holdTime>0 and(ifpre or self.falling==0 and self.waiting==0)then
if self.gameEnv.holdMode=='hold'then if self.gameEnv.holdMode=='hold'then
self:hold_norm(ifpre) self:hold_norm(ifpre)
elseif self.gameEnv.holdMode=='swap'then elseif self.gameEnv.holdMode=='swap'then
self:hold_swap(ifpre) self:hold_swap(ifpre)
end end
return true
end end
end end
@@ -1039,9 +1361,9 @@ function Player:popNext(ifhold)--Pop nextQueue to hand
self.spinLast=false self.spinLast=false
self.ctrlCount=0 self.ctrlCount=0
self.cur=rem(self.nextQueue,1) if self.nextQueue[1]then
self.newNext() self.cur=rem(self.nextQueue,1)
if self.cur then self.newNext()
self.pieceCount=self.pieceCount+1 self.pieceCount=self.pieceCount+1
local pressing=self.keyPressing local pressing=self.keyPressing
@@ -1068,8 +1390,10 @@ function Player:popNext(ifhold)--Pop nextQueue to hand
self:act_hardDrop() self:act_hardDrop()
pressing[6]=false pressing[6]=false
end end
else elseif self.holdQueue[1]then--Force using hold
self:hold() self:hold()
else--Next queue is empty, force lose
self:lose(true)
end end
end end
@@ -1251,8 +1575,6 @@ do
piece.centX,piece.centY=self.curX+sc[2],self.curY+sc[1] piece.centX,piece.centY=self.curX+sc[2],self.curY+sc[1]
piece.frame,piece.autoLock=self.frameRun,autoLock piece.frame,piece.autoLock=self.frameRun,autoLock
self.waiting=ENV.wait
--Tri-corner spin check --Tri-corner spin check
if self.spinLast then if self.spinLast then
if C.id<6 then if C.id<6 then
@@ -1637,6 +1959,9 @@ do
end end
end end
--Fresh ARE
self.waiting=ENV.wait
--Prevent sudden death if hang>0 --Prevent sudden death if hang>0
if ENV.hang>ENV.wait and self.nextQueue[1]then if ENV.hang>ENV.wait and self.nextQueue[1]then
local B=self.nextQueue[1] local B=self.nextQueue[1]
@@ -1699,6 +2024,13 @@ do
else else
self:_triggerEvent('hook_drop') self:_triggerEvent('hook_drop')
end end
--Remove controling block
self.cur=nil
if self.waiting==0 and self.falling==0 then
self:popNext()
end
end end
function Player:clearFilledLines(start,height) function Player:clearFilledLines(start,height)
@@ -1708,7 +2040,7 @@ do
self:showText(text.clear[min(_cc,21)],0,0,75,'beat',.4) self:showText(text.clear[min(_cc,21)],0,0,75,'beat',.4)
if _cc>6 then self:showText(text.cleared:gsub("$1",_cc),0,55,30,'zoomout',.4)end if _cc>6 then self:showText(text.cleared:gsub("$1",_cc),0,55,30,'zoomout',.4)end
self:_removeClearedLines() self:_removeClearedLines()
self.falling=self.gameEnv.fall self:_updateFalling(self.gameEnv.fall)
self.stat.row=self.stat.row+_cc self.stat.row=self.stat.row+_cc
self.stat.dig=self.stat.dig+_gbcc self.stat.dig=self.stat.dig+_gbcc
self.stat.score=self.stat.score+clearSCR[_cc] self.stat.score=self.stat.score+clearSCR[_cc]
@@ -2014,7 +2346,7 @@ local function update_alive(P)
if P.movDir~=0 then if P.movDir~=0 then
local das,arr=ENV.das,ENV.arr local das,arr=ENV.das,ENV.arr
local mov=P.moving local mov=P.moving
if P.waiting==-1 then if P.cur then
if P.movDir==1 then if P.movDir==1 then
if P.keyPressing[2]then if P.keyPressing[2]then
if arr>0 then if arr>0 then
@@ -2098,26 +2430,25 @@ local function update_alive(P)
P.downing=0 P.downing=0
end end
local stopAtFalling
--Falling animation --Falling animation
if P.falling>=0 then if P.falling>0 then
P.falling=P.falling-1 stopAtFalling=true
if P.falling>=0 then P:_updateFalling(P.falling-1)
if P.falling>0 then
goto THROW_stop goto THROW_stop
else
local L=#P.clearingRow
if P.sound and ENV.fall>0 and #P.field+L>P.clearingRow[L]then
SFX.play('fall')
end
P.clearingRow={}
end end
end end
--Update block state --Update block state
if P.control then if P.control then
--Try spawn new block --Try spawn new block
if P.waiting>=0 then if not P.cur then
P.waiting=P.waiting-1 if not stopAtFalling and P.waiting>0 then
if P.waiting<0 then P.waiting=P.waiting-1
end
if P.waiting<=0 then
P:popNext() P:popNext()
end end
goto THROW_stop goto THROW_stop
@@ -2238,15 +2569,8 @@ local function update_dead(P)
P.swappingAtkMode=min(P.swappingAtkMode+2,30) P.swappingAtkMode=min(P.swappingAtkMode+2,30)
end end
if P.falling>=0 then if P.falling>0 then
P.falling=P.falling-1 P:_updateFalling(P.falling-1)
if P.falling<0 then
local L=#P.clearingRow
if P.sound and P.gameEnv.fall>0 and #P.field+L>P.clearingRow[L]then
SFX.play('fall')
end
P.clearingRow={}
end
end end
if P.b2b1>0 then if P.b2b1>0 then
P.b2b1=max(0,P.b2b1*.92-1) P.b2b1=max(0,P.b2b1*.92-1)
@@ -2466,254 +2790,4 @@ function Player:lose(force)
end end
--------------------------<\Event>-------------------------- --------------------------<\Event>--------------------------
--------------------------<Action>--------------------------
function Player:act_moveLeft(auto)
if not auto then
self.ctrlCount=self.ctrlCount+1
end
self.movDir=-1
if self.control and self.waiting==-1 then
if self.cur and not self:ifoverlap(self.cur.bk,self.curX-1,self.curY)then
self:createMoveFX('left')
self.curX=self.curX-1
self:freshBlock('move')
if not auto then
self.moving=0
end
self.spinLast=false
else
self.moving=self.gameEnv.das
end
else
self.moving=0
end
end
function Player:act_moveRight(auto)
if not auto then
self.ctrlCount=self.ctrlCount+1
end
self.movDir=1
if self.control and self.waiting==-1 then
if self.cur and not self:ifoverlap(self.cur.bk,self.curX+1,self.curY)then
self:createMoveFX('right')
self.curX=self.curX+1
self:freshBlock('move')
if not auto then
self.moving=0
end
self.spinLast=false
else
self.moving=self.gameEnv.das
end
else
self.moving=0
end
end
function Player:act_rotRight()
if self.control and self.waiting==-1 and self.cur then
self.ctrlCount=self.ctrlCount+1
self:spin(1)
self.keyPressing[3]=false
end
end
function Player:act_rotLeft()
if self.control and self.waiting==-1 and self.cur then
self.ctrlCount=self.ctrlCount+1
self:spin(3)
self.keyPressing[4]=false
end
end
function Player:act_rot180()
if self.control and self.waiting==-1 and self.cur then
self.ctrlCount=self.ctrlCount+2
self:spin(2)
self.keyPressing[5]=false
end
end
function Player:act_hardDrop()
local ENV=self.gameEnv
if 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',.3)
else
if self.curY>self.ghoY then
self:createDropFX()
self.curY=self.ghoY
self.spinLast=false
if self.sound then
SFX.play('drop',nil,self:getCenterX()*.15)
if SETTING.vib>0 then VIB(SETTING.vib+1)end
end
end
if ENV.shakeFX then
self.swingOffset.vy=.6
self.swingOffset.va=self.swingOffset.va+self:getCenterX()*6e-4
end
self.lockDelay=-1
self:drop()
self.keyPressing[6]=false
end
end
end
function Player:act_softDrop()
local ENV=self.gameEnv
self.downing=1
if self.control and self.waiting==-1 and self.cur then
if self.curY>self.ghoY then
self.curY=self.curY-1
self:freshBlock('fresh')
self.spinLast=false
self:checkTouchSound()
elseif ENV.deepDrop then
local CB=self.cur.bk
local y=self.curY-1
while self:ifoverlap(CB,self.curX,y)and y>0 do
y=y-1
end
if y>0 then
self.ghoY=y
self:createDropFX()
self.curY=y
self:freshBlock('move')
SFX.play('swipe')
end
end
end
end
function Player:act_hold()
if self.control then
if self.waiting==-1 then
self:hold()
self.keyPressing[8]=false
end
end
end
function Player:act_func1()
self.gameEnv.fkey1(self)
end
function Player:act_func2()
self.gameEnv.fkey2(self)
end
function Player:act_insLeft(auto)
if not self.cur then
return
end
local x0=self.curX
while not self:ifoverlap(self.cur.bk,self.curX-1,self.curY)do
self:createMoveFX('left')
self.curX=self.curX-1
self:freshBlock('move',true)
end
if self.curX~=x0 then
self.spinLast=false
self:checkTouchSound()
end
if self.gameEnv.shakeFX then
self.swingOffset.vx=-1.5
end
if auto then
if self.ctrlCount==0 then
self.ctrlCount=1
end
else
self.ctrlCount=self.ctrlCount+1
end
end
function Player:act_insRight(auto)
if not self.cur then
return
end
local x0=self.curX
while not self:ifoverlap(self.cur.bk,self.curX+1,self.curY)do
self:createMoveFX('right')
self.curX=self.curX+1
self:freshBlock('move',true)
end
if self.curX~=x0 then
self.spinLast=false
self:checkTouchSound()
end
if self.gameEnv.shakeFX then
self.swingOffset.vx=1.5
end
if auto then
if self.ctrlCount==0 then
self.ctrlCount=1
end
else
self.ctrlCount=self.ctrlCount+1
end
end
function Player:act_insDown()
if self.cur and self.curY>self.ghoY then
local ENV=self.gameEnv
self:createDropFX()
if ENV.shakeFX then
self.swingOffset.vy=.5
end
self.curY=self.ghoY
self.lockDelay=ENV.lock
self.spinLast=false
self:freshBlock('fresh')
self:checkTouchSound()
end
end
function Player:act_down1()
if self.cur and self.curY>self.ghoY then
self:createMoveFX('down')
self.curY=self.curY-1
self:freshBlock('fresh')
self.spinLast=false
end
end
function Player:act_down4()
if self.cur and self.curY>self.ghoY then
local ghoY0=self.ghoY
self.ghoY=max(self.curY-4,self.ghoY)
self:createDropFX()
self.curY,self.ghoY=self.ghoY,ghoY0
self:freshBlock('fresh')
self.spinLast=false
end
end
function Player:act_down10()
if self.cur and self.curY>self.ghoY then
local ghoY0=self.ghoY
self.ghoY=max(self.curY-10,self.ghoY)
self:createDropFX()
self.curY,self.ghoY=self.ghoY,ghoY0
self:freshBlock('fresh')
self.spinLast=false
end
end
function Player:act_dropLeft()
if self.cur then
self:act_insLeft()
self:act_hardDrop()
end
end
function Player:act_dropRight()
if self.cur then
self:act_insRight()
self:act_hardDrop()
end
end
function Player:act_zangiLeft()
if self.cur then
self:act_insLeft()
self:act_insDown()
self:act_insRight()
self:act_hardDrop()
end
end
function Player:act_zangiRight()
if self.cur then
self:act_insRight()
self:act_insDown()
self:act_insLeft()
self:act_hardDrop()
end
end
--------------------------</Action>--------------------------
return Player return Player

View File

@@ -256,9 +256,6 @@ local seqGenerators={
if seq[1]then if seq[1]then
P:getNext(rem(seq)) P:getNext(rem(seq))
else else
if not(P.cur or P.nextQueue[1]or P.holdQueue[1])then
P:lose(true)
end
break break
end end
end end

View File

@@ -10,7 +10,7 @@ end
function scene.mouseDown(x,y) function scene.mouseDown(x,y)
if x>55 and y>550 and x<510 and y<670 then if x>55 and y>550 and x<510 and y<670 then
loadGame('sprintSym',true) loadGame('stack_e',true)
end end
end end
scene.touchDown=scene.mouseDown scene.touchDown=scene.mouseDown
@@ -19,7 +19,7 @@ function scene.keyDown(key)
if key=="escape"then if key=="escape"then
SCN.back() SCN.back()
elseif key=="space"then elseif key=="space"then
loadGame('sprintSym',true) loadGame('stack_e',true)
end end
end end

View File

@@ -3,6 +3,8 @@ local rnd=math.random
local int,ceil=math.floor,math.ceil local int,ceil=math.floor,math.ceil
local char=string.char local char=string.char
local timing,time
local function b2(i) local function b2(i)
if i==0 then return 0 end if i==0 then return 0 end
local s="" local s=""
@@ -114,17 +116,27 @@ local levels={
local a=rnd(17,int(s/2)) local a=rnd(17,int(s/2))
return{COLOR.J,b16(a),COLOR.Z,"+",COLOR.J,b16(s-a)},s return{COLOR.J,b16(a),COLOR.Z,"+",COLOR.J,b16(s-a)},s
end,nil,nil, end,nil,nil,
function()return "Coming S∞n"..(rnd()<.5 and""or" "),1e99 end, function()timing=false return "Coming S∞n"..(rnd()<.5 and""or" "),1e99 end,
}setmetatable(levels,{__index=function(self,k)return self[k-1]end}) }setmetatable(levels,{__index=function(self,k)return self[k-1]end})
local level local level
local input,inputTime=0,0 local input,inputTime=0,0
local question,answer local question,answer
local function newQuestion(lv) local function newQuestion(lv)
return levels[lv]() return levels[lv]()
end end
local function reset()
timing=true
time=0
input=""
inputTime=0
level=1
question,answer=newQuestion(1)
end
local function check(val) local function check(val)
if val==answer then if val==answer then
level=level+1 level=level+1
@@ -142,10 +154,7 @@ end
local scene={} local scene={}
function scene.sceneInit() function scene.sceneInit()
input="" reset()
inputTime=0
level=1
question,answer=newQuestion(1)
BGM.play('truth') BGM.play('truth')
end end
@@ -173,14 +182,15 @@ function scene.keyDown(key,isRep)
elseif key=="backspace"then elseif key=="backspace"then
input="" input=""
inputTime=0 inputTime=0
elseif key=="s"then elseif key=="r"then
check(answer) reset()
elseif key=="escape"then elseif key=="escape"then
SCN.back() SCN.back()
end end
end end
function scene.update(dt) function scene.update(dt)
if timing then time=time+dt end
if inputTime>0 then if inputTime>0 then
inputTime=inputTime-dt inputTime=inputTime-dt
if inputTime<=0 then if inputTime<=0 then
@@ -189,8 +199,11 @@ function scene.update(dt)
end end
end end
function scene.draw() function scene.draw()
FONT.set(35)
gc.setColor(COLOR.Z) gc.setColor(COLOR.Z)
FONT.set(45)
gc.print(("%.3f"):format(time),1026,70)
FONT.set(35)
GC.mStr("["..level.."]",640,30) GC.mStr("["..level.."]",640,30)
FONT.set(100) FONT.set(100)
@@ -203,6 +216,7 @@ function scene.draw()
end end
scene.widgetList={ scene.widgetList={
WIDGET.newButton{name='reset',x=155,y=100,w=180,h=100,color='lG',font=40,code=pressKey"r"},
WIDGET.newKey{name='X',x=540,y=620,w=90,font=60,fText="X",code=pressKey"backspace"}, WIDGET.newKey{name='X',x=540,y=620,w=90,font=60,fText="X",code=pressKey"backspace"},
WIDGET.newKey{name='0',x=640,y=620,w=90,font=60,fText="0",code=pressKey"0"}, WIDGET.newKey{name='0',x=640,y=620,w=90,font=60,fText="0",code=pressKey"0"},
WIDGET.newKey{name='-',x=740,y=620,w=90,font=60,fText="-",code=pressKey"-"}, WIDGET.newKey{name='-',x=740,y=620,w=90,font=60,fText="-",code=pressKey"-"},

View File

@@ -3,8 +3,8 @@ local kb=love.keyboard
local ins,rem=table.insert,table.remove local ins,rem=table.insert,table.remove
local C=COLOR local C=COLOR
local inputBox=WIDGET.newInputBox{name='input',x=40,y=650,w=1200,h=50} local inputBox=WIDGET.newInputBox{name='input',x=40,y=650,w=1200,h=50,fType='mono'}
local outputBox=WIDGET.newTextBox{name='output',x=40,y=30,w=1200,h=610,font=25,lineH=25,fix=true} local outputBox=WIDGET.newTextBox{name='output',x=40,y=30,w=1200,h=610,font=25,fType='mono',lineH=25,fix=true}
local function log(str)outputBox:push(str)end local function log(str)outputBox:push(str)end
log{C.lP,"Techmino Console"} log{C.lP,"Techmino Console"}

View File

@@ -17,6 +17,7 @@ local sList={
wait={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, wait={0,1,2,3,4,5,6,7,8,10,15,20,30,60},
fall={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, fall={0,1,2,3,4,5,6,7,8,10,15,20,30,60},
hang={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, hang={0,1,2,3,4,5,6,7,8,10,15,20,30,60},
hurry={0,1,2,3,4,5,6,7,8,10,1e99},
eventSet=EVENTSETS, eventSet=EVENTSETS,
holdMode={'hold','swap'}, holdMode={'hold','swap'},
} }
@@ -63,11 +64,11 @@ function scene.keyDown(key,isRep)
end end
if key=="return2"or kb.isDown("lalt","lctrl","lshift")then if key=="return2"or kb.isDown("lalt","lctrl","lshift")then
if #FIELD[1]>0 then if #FIELD[1]>0 then
FILE.save(CUSTOMENV,'conf/customEnv') saveFile(CUSTOMENV,'conf/customEnv')
loadGame('custom_puzzle',true) loadGame('custom_puzzle',true)
end end
else else
FILE.save(CUSTOMENV,'conf/customEnv') saveFile(CUSTOMENV,'conf/customEnv')
loadGame('custom_clear',true) loadGame('custom_clear',true)
end end
elseif key=="f"then elseif key=="f"then
@@ -83,10 +84,10 @@ function scene.keyDown(key,isRep)
TABLE.clear(CUSTOMENV) TABLE.clear(CUSTOMENV)
TABLE.complete(require"parts.customEnv0",CUSTOMENV) TABLE.complete(require"parts.customEnv0",CUSTOMENV)
for _,W in next,scene.widgetList do W:reset()end for _,W in next,scene.widgetList do W:reset()end
FILE.save(DATA.copyMission(),'conf/customMissions') saveFile(DATA.copyMission(),'conf/customMissions')
FILE.save(DATA.copyBoards(),'conf/customBoards') saveFile(DATA.copyBoards(),'conf/customBoards')
FILE.save(DATA.copySequence(),'conf/customSequence') saveFile(DATA.copySequence(),'conf/customSequence')
FILE.save(CUSTOMENV,'conf/customEnv') saveFile(CUSTOMENV,'conf/customEnv')
sure=0 sure=0
SFX.play('finesseError',.7) SFX.play('finesseError',.7)
BG.set(CUSTOMENV.bg) BG.set(CUSTOMENV.bg)
@@ -122,7 +123,7 @@ function scene.keyDown(key,isRep)
do return end do return end
::THROW_fail::MES.new('error',text.dataCorrupted) ::THROW_fail::MES.new('error',text.dataCorrupted)
elseif key=="escape"then elseif key=="escape"then
FILE.save(CUSTOMENV,'conf/customEnv') saveFile(CUSTOMENV,'conf/customEnv')
SCN.back() SCN.back()
else else
WIDGET.keyPressed(key) WIDGET.keyPressed(key)
@@ -212,7 +213,8 @@ scene.widgetList={
WIDGET.newSelector{name='lock', x=730,y=410,w=260,color='O',list=sList.lock,disp=CUSval('lock'),code=CUSsto('lock')}, WIDGET.newSelector{name='lock', x=730,y=410,w=260,color='O',list=sList.lock,disp=CUSval('lock'),code=CUSsto('lock')},
WIDGET.newSelector{name='wait', x=730,y=520,w=260,color='G',list=sList.wait,disp=CUSval('wait'),code=CUSsto('wait')}, WIDGET.newSelector{name='wait', x=730,y=520,w=260,color='G',list=sList.wait,disp=CUSval('wait'),code=CUSsto('wait')},
WIDGET.newSelector{name='fall', x=730,y=600,w=260,color='G',list=sList.fall,disp=CUSval('fall'),code=CUSsto('fall')}, WIDGET.newSelector{name='fall', x=730,y=600,w=260,color='G',list=sList.fall,disp=CUSval('fall'),code=CUSsto('fall')},
WIDGET.newSelector{name='hang', x=730,y=680,w=260,color='G',list=sList.hang,disp=CUSval('hang'),code=CUSsto('hang')}, WIDGET.newSelector{name='hurry', x=730,y=680,w=260,color='G',list=sList.hurry,disp=CUSval('hurry'),code=CUSsto('hurry')},
WIDGET.newSelector{name='hang', x=730,y=760,w=260,color='G',list=sList.hang,disp=CUSval('hang'),code=CUSsto('hang')},
--Copy / Paste / Start --Copy / Paste / Start
WIDGET.newButton{name='copy', x=1070,y=300,w=310,h=70,color='lR',font=25,code=pressKey"cC"}, WIDGET.newButton{name='copy', x=1070,y=300,w=310,h=70,color='lR',font=25,code=pressKey"cC"},
@@ -222,19 +224,19 @@ scene.widgetList={
WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,font=60,fText=CHAR.icon.back,code=pressKey"escape"}, WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,font=60,fText=CHAR.icon.back,code=pressKey"escape"},
--Rule set --Rule set
WIDGET.newSelector{name='eventSet', x=1050,y=740,w=340,color='H',list=sList.eventSet,disp=CUSval('eventSet'),code=CUSsto('eventSet')}, WIDGET.newSelector{name='eventSet', x=1050,y=760,w=340,color='H',list=sList.eventSet,disp=CUSval('eventSet'),code=CUSsto('eventSet')},
--Special rules --Special rules
WIDGET.newSwitch{name='ospin', x=850, y=820 ,lim=210,disp=CUSval('ospin'), code=CUSrev('ospin')}, WIDGET.newSwitch{name='ospin', x=850, y=830, lim=210,disp=CUSval('ospin'), code=CUSrev('ospin')},
WIDGET.newSwitch{name='fineKill', x=850, y=880 ,lim=210,disp=CUSval('fineKill'), code=CUSrev('fineKill')}, WIDGET.newSwitch{name='fineKill', x=850, y=890, lim=210,disp=CUSval('fineKill'), code=CUSrev('fineKill')},
WIDGET.newSwitch{name='b2bKill', x=850, y=940 ,lim=210,disp=CUSval('b2bKill'), code=CUSrev('b2bKill')}, WIDGET.newSwitch{name='b2bKill', x=850, y=950, lim=210,disp=CUSval('b2bKill'), code=CUSrev('b2bKill')},
WIDGET.newSwitch{name='lockout', x=850, y=1000,lim=210,disp=CUSval('lockout'), code=CUSrev('lockout')}, WIDGET.newSwitch{name='lockout', x=850, y=1010,lim=210,disp=CUSval('lockout'), code=CUSrev('lockout')},
WIDGET.newSwitch{name='easyFresh', x=1170,y=820 ,lim=250,disp=CUSval('easyFresh'),code=CUSrev('easyFresh')}, WIDGET.newSwitch{name='easyFresh', x=1170,y=830, lim=250,disp=CUSval('easyFresh'),code=CUSrev('easyFresh')},
WIDGET.newSwitch{name='deepDrop', x=1170,y=880 ,lim=250,disp=CUSval('deepDrop'), code=CUSrev('deepDrop')}, WIDGET.newSwitch{name='deepDrop', x=1170,y=890, lim=250,disp=CUSval('deepDrop'), code=CUSrev('deepDrop')},
WIDGET.newSwitch{name='bone', x=1170,y=940 ,lim=250,disp=CUSval('bone'), code=CUSrev('bone')}, WIDGET.newSwitch{name='bone', x=1170,y=950, lim=250,disp=CUSval('bone'), code=CUSrev('bone')},
--Next & Hold --Next & Hold
WIDGET.newSelector{name='holdMode', x=310, y=890, w=300,color='lY',list=sList.holdMode,disp=CUSval('holdMode'),code=CUSsto('holdMode')}, WIDGET.newSelector{name='holdMode', x=310, y=890, w=300,color='lY',list=sList.holdMode,disp=CUSval('holdMode'),code=CUSsto('holdMode'),hideF=function()return CUSTOMENV.holdCount==0 end},
WIDGET.newSlider{name='nextCount', x=140, y=960, lim=130,w=180,unit=6,disp=CUSval('nextCount'),code=CUSsto('nextCount')}, WIDGET.newSlider{name='nextCount', x=140, y=960, lim=130,w=180,unit=6,disp=CUSval('nextCount'),code=CUSsto('nextCount')},
WIDGET.newSlider{name='holdCount', x=140, y=1030,lim=130,w=180,unit=6,disp=CUSval('holdCount'),code=CUSsto('holdCount')}, WIDGET.newSlider{name='holdCount', x=140, y=1030,lim=130,w=180,unit=6,disp=CUSval('holdCount'),code=CUSsto('holdCount')},
WIDGET.newSwitch{name='infHold', x=560, y=960, lim=200, disp=CUSval('infHold'),code=CUSrev('infHold'),hideF=function()return CUSTOMENV.holdCount==0 end}, WIDGET.newSwitch{name='infHold', x=560, y=960, lim=200, disp=CUSval('infHold'),code=CUSrev('infHold'),hideF=function()return CUSTOMENV.holdCount==0 end},

View File

@@ -127,7 +127,7 @@ function scene.sceneInit()
page=1 page=1
end end
function scene.sceneBack() function scene.sceneBack()
FILE.save(DATA.copyBoards(),'conf/customBoards') saveFile(DATA.copyBoards(),'conf/customBoards')
end end
function scene.mouseMove(x,y) function scene.mouseMove(x,y)

View File

@@ -16,7 +16,7 @@ function scene.sceneInit()
sure=0 sure=0
end end
function scene.sceneBack() function scene.sceneBack()
FILE.save(DATA.copyMission(),'conf/customMissions') saveFile(DATA.copyMission(),'conf/customMissions')
end end
local ENUM_MISSION=ENUM_MISSION local ENUM_MISSION=ENUM_MISSION

View File

@@ -16,7 +16,7 @@ function scene.sceneInit()
sure=0 sure=0
end end
function scene.sceneBack() function scene.sceneBack()
FILE.save(DATA.copySequence(),'conf/customSequence') saveFile(DATA.copySequence(),'conf/customSequence')
end end
local minoKey={ local minoKey={

View File

@@ -12,7 +12,7 @@ local dict--Dict list
local result--Result Lable local result--Result Lable
local lastTickInput local lastTickInput
local waiting--Searching animation timer local searchWait--Searching animation timer
local selected--Selected option local selected--Selected option
local scrollPos--Scroll down length local scrollPos--Scroll down length
@@ -53,7 +53,7 @@ local function _clearResult()
TABLE.cut(result) TABLE.cut(result)
selected=1 selected=1
scrollPos=0 scrollPos=0
waiting,lastSearch=0,false searchWait,lastSearch=0,false
scene.widgetList.copy.hide=false scene.widgetList.copy.hide=false
end end
local function _search() local function _search()
@@ -82,7 +82,7 @@ function scene.sceneInit()
inputBox:clear() inputBox:clear()
result={} result={}
waiting=0 searchWait=0
selected=1 selected=1
scrollPos=0 scrollPos=0
@@ -115,8 +115,9 @@ function scene.keyDown(key)
for _=1,12 do scene.keyDown("up")end for _=1,12 do scene.keyDown("up")end
elseif key=="right"or key=="pagedown"then elseif key=="right"or key=="pagedown"then
for _=1,12 do scene.keyDown("down")end for _=1,12 do scene.keyDown("down")end
elseif key=="link"then elseif key=="application"then
love.system.openURL(_getList()[selected].url) local url=_getList()[selected].url
if url then love.system.openURL(url)end
elseif key=="delete"then elseif key=="delete"then
if inputBox:hasText()then if inputBox:hasText()then
_clearResult() _clearResult()
@@ -152,13 +153,13 @@ function scene.update(dt)
if #input==0 then if #input==0 then
_clearResult() _clearResult()
else else
waiting=.8 searchWait=.8
end end
lastTickInput=input lastTickInput=input
end end
if waiting>0 then if searchWait>0 then
waiting=waiting-dt searchWait=searchWait-dt
if waiting<=0 then if searchWait<=0 then
if #input>0 and input~=lastSearch then if #input>0 and input~=lastSearch then
_search() _search()
end end
@@ -201,7 +202,7 @@ function scene.draw()
gc.rectangle('line',300,180,958,526,5) gc.rectangle('line',300,180,958,526,5)
gc.rectangle('line',20,180,280,526,5) gc.rectangle('line',20,180,280,526,5)
if waiting>0 then if searchWait>0 then
local r=TIME()*2 local r=TIME()*2
local R=int(r)%7+1 local R=int(r)%7+1
gc.setColor(1,1,1,1-abs(r%1*2-1)) gc.setColor(1,1,1,1-abs(r%1*2-1))
@@ -213,7 +214,7 @@ scene.widgetList={
WIDGET.newText{name='book', x=20,y=15,font=70,align='L',fText=CHAR.icon.zBook}, WIDGET.newText{name='book', x=20,y=15,font=70,align='L',fText=CHAR.icon.zBook},
WIDGET.newText{name='title', x=100,y=15,font=70,align='L'}, WIDGET.newText{name='title', x=100,y=15,font=70,align='L'},
inputBox, inputBox,
WIDGET.newKey{name='link', x=1120,y=655,w=80,font=55,fText=CHAR.icon.globe, code=pressKey"link",hideF=function()return not _getList()[selected].url end}, WIDGET.newKey{name='link', x=1120,y=655,w=80,font=55,fText=CHAR.icon.globe, code=pressKey"application",hideF=function()return not _getList()[selected].url end},
WIDGET.newKey{name='copy', x=1210,y=655,w=80,font=50,fText=CHAR.icon.copy, code=pressKey"cC"}, WIDGET.newKey{name='copy', x=1210,y=655,w=80,font=50,fText=CHAR.icon.copy, code=pressKey"cC"},
WIDGET.newKey{name='up', x=1120,y=475,w=80,font=50,fText=CHAR.key.up, code=pressKey"up",hide=not MOBILE}, WIDGET.newKey{name='up', x=1120,y=475,w=80,font=50,fText=CHAR.key.up, code=pressKey"up",hide=not MOBILE},
WIDGET.newKey{name='down', x=1120,y=565,w=80,font=50,fText=CHAR.key.down, code=pressKey"down",hide=not MOBILE}, WIDGET.newKey{name='down', x=1120,y=565,w=80,font=50,fText=CHAR.key.down, code=pressKey"down",hide=not MOBILE},

View File

@@ -9,9 +9,9 @@ local scene={}
function scene.sceneInit() function scene.sceneInit()
BGcolor=rnd()>.026 and{.3,.5,.9}or{.62,.3,.926} BGcolor=rnd()>.026 and{.3,.5,.9}or{.62,.3,.926}
stateInfo=SYSTEM.."-"..VERSION.string.." scene:"..ERRDATA[#ERRDATA].scene stateInfo=SYSTEM.."-"..VERSION.string.." scene:"..Z.errData[#Z.errData].scene
errorText=LOADED and text.errorMsg or"An error has occurred during loading.\nError info has been created, and you can send it to the author." errorText=LOADED and text.errorMsg or"An error has occurred during loading.\nError info has been created, and you can send it to the author."
errorShot,errorInfo=ERRDATA[#ERRDATA].shot,ERRDATA[#ERRDATA].mes errorShot,errorInfo=Z.errData[#Z.errData].shot,Z.errData[#Z.errData].mes
NET.wsclose_app() NET.wsclose_app()
NET.wsclose_user() NET.wsclose_user()
NET.wsclose_play() NET.wsclose_play()

View File

@@ -11,6 +11,14 @@ local t1,t2,animeType
local studioLogo--Studio logo text object local studioLogo--Studio logo text object
local logoColor1,logoColor2 local logoColor1,logoColor2
local titleTransform={
function(t)gc.translate(0,max(50-t,0)^2/25)end,
function(t)gc.translate(0,-max(50-t,0)^2/25)end,
function(t,i)local d=max(50-t,0)gc.translate(sin(TIME()*3+626*i)*d,cos(TIME()*3+626*i)*d)end,
function(t,i)local d=max(50-t,0)gc.translate(sin(TIME()*3+626*i)*d,-cos(TIME()*3+626*i)*d)end,
function(t)gc.setColor(1,1,1,min(t*.02,1)+rnd()*.2)end,
}
local loadingThread=coroutine.wrap(function() local loadingThread=coroutine.wrap(function()
DAILYLAUNCH=freshDate'q' DAILYLAUNCH=freshDate'q'
if DAILYLAUNCH then if DAILYLAUNCH then
@@ -27,7 +35,7 @@ local loadingThread=coroutine.wrap(function()
YIELD('loadSample')SFX.loadSample{name='lead',path='media/sample/lead',base='A3'}--A3~A5 YIELD('loadSample')SFX.loadSample{name='lead',path='media/sample/lead',base='A3'}--A3~A5
YIELD('loadSample')SFX.loadSample{name='bell',path='media/sample/bell',base='A4'}--A4~A6 YIELD('loadSample')SFX.loadSample{name='bell',path='media/sample/bell',base='A4'}--A4~A6
YIELD('loadVoice')VOC.load('media/vocal/'..SETTING.vocPack..'/') YIELD('loadVoice')VOC.load('media/vocal/'..SETTING.vocPack..'/')
YIELD('loadFont')for i=1,17 do getFont(15+5*i)end YIELD('loadFont')for i=1,17 do getFont(15+5*i)getFont(15+5*i,'mono')end
YIELD('loadModeIcon') YIELD('loadModeIcon')
local modeIcons={} local modeIcons={}
@@ -88,7 +96,7 @@ local loadingThread=coroutine.wrap(function()
YIELD('loadMode') YIELD('loadMode')
for _,M in next,MODES do for _,M in next,MODES do
M.records=FILE.load("record/"..M.name..".rec",'luaon')or M.score and{} M.records=loadFile("record/"..M.name..".rec",'-luaon -canSkip')or M.score and{}
M.icon=M.icon and(modeIcons[M.icon]or gc.newImage("media/image/modeicon/"..M.icon..".png")) M.icon=M.icon and(modeIcons[M.icon]or gc.newImage("media/image/modeicon/"..M.icon..".png"))
end end
@@ -113,7 +121,7 @@ function scene.sceneInit()
progress=0 progress=0
maxProgress=10 maxProgress=10
t1,t2=0,0--Timer t1,t2=0,0--Timer
animeType={}for i=1,8 do animeType[i]=rnd(5)end--Random animation type animeType={}for i=1,#SVG_TITLE_FILL do animeType[i]=rnd(#titleTransform)end--Random animation type
end end
function scene.sceneBack() function scene.sceneBack()
love.event.quit() love.event.quit()
@@ -147,13 +155,6 @@ function scene.update(dt)
end end
end end
local titleTransform={
function(t)gc.translate(0,max(50-t,0)^2/25)end,
function(t)gc.translate(0,-max(50-t,0)^2/25)end,
function(t,i)local d=max(50-t,0)gc.translate(sin(TIME()*3+626*i)*d,cos(TIME()*3+626*i)*d)end,
function(t,i)local d=max(50-t,0)gc.translate(sin(TIME()*3+626*i)*d,-cos(TIME()*3+626*i)*d)end,
function(t)gc.setColor(1,1,1,min(t*.02,1)+rnd()*.2)end,
}
local titleColor={COLOR.P,COLOR.F,COLOR.V,COLOR.A,COLOR.M,COLOR.N,COLOR.W,COLOR.Y} local titleColor={COLOR.P,COLOR.F,COLOR.V,COLOR.A,COLOR.M,COLOR.N,COLOR.W,COLOR.Y}
function scene.draw() function scene.draw()
gc.clear(.08,.08,.084) gc.clear(.08,.08,.084)
@@ -166,7 +167,8 @@ function scene.draw()
end end
gc.push('transform') gc.push('transform')
gc.translate(126,100) gc.translate(126,100)
for i=1,8 do for i=1,#SVG_TITLE_FILL do
local triangles=love.math.triangulate(SVG_TITLE_FILL[i])
local t=t1-i*15 local t=t1-i*15
if t>0 then if t>0 then
gc.push('transform') gc.push('transform')
@@ -176,9 +178,12 @@ function scene.draw()
gc.translate(0,math.abs(10-dt)-10) gc.translate(0,math.abs(10-dt)-10)
end end
gc.setColor(titleColor[i][1],titleColor[i][2],titleColor[i][3],min(t*.025,1)*.2) gc.setColor(titleColor[i][1],titleColor[i][2],titleColor[i][3],min(t*.025,1)*.2)
gc.polygon('fill',SVG_TITLE[i]) for j=1,#triangles do
gc.polygon('fill',triangles[j])
end
gc.setColor(1,1,1,min(t*.025,1)) gc.setColor(1,1,1,min(t*.025,1))
gc.polygon('line',SVG_TITLE[i]) gc.polygon('line',SVG_TITLE_LINE[i])
if i==8 then gc.polygon('line',SVG_TITLE_LINE[9])end
gc.pop() gc.pop()
end end
end end

View File

@@ -12,7 +12,7 @@ local function _login()
end end
NET.wsconn_user_pswd(email,password) NET.wsconn_user_pswd(email,password)
if savePW then if savePW then
FILE.save({email,password},'conf/account') saveFile({email,password},'conf/account')
else else
love.filesystem.remove('conf/account') love.filesystem.remove('conf/account')
end end
@@ -21,7 +21,7 @@ end
local scene={} local scene={}
function scene.sceneInit() function scene.sceneInit()
local data=FILE.load('conf/account') local data=loadFile('conf/account')
if data then if data then
savePW=true savePW=true
emailBox:setText(data[1]) emailBox:setText(data[1])

View File

@@ -162,7 +162,7 @@ function scene.update()
if kb.isDown("down","s")then dy=dy-10 F=true end if kb.isDown("down","s")then dy=dy-10 F=true end
if kb.isDown("left","a")then dx=dx+10 F=true end if kb.isDown("left","a")then dx=dx+10 F=true end
if kb.isDown("right","d")then dx=dx-10 F=true end if kb.isDown("right","d")then dx=dx-10 F=true end
local js1=joysticks[1] local js1=Z.js[1]
if js1 then if js1 then
local dir=js1:getAxis(1) local dir=js1:getAxis(1)
if dir~="c"then if dir~="c"then

View File

@@ -22,6 +22,7 @@ local author={
["race remix"]="柒栎流星", ["race remix"]="柒栎流星",
["sakura"]="ZUN & C₂₉H₂₅N₃O₅", ["sakura"]="ZUN & C₂₉H₂₅N₃O₅",
["1980s"]="C₂₉H₂₅N₃O₅", ["1980s"]="C₂₉H₂₅N₃O₅",
["malate"]="ZUN & C₂₉H₂₅N₃O₅",
} }
local scene={} local scene={}

View File

@@ -28,7 +28,7 @@ scene.widgetList={
NET.wsclose_user() NET.wsclose_user()
USER.uid=false USER.uid=false
USER.authToken=false USER.authToken=false
FILE.save(USER,'conf/user') saveFile(USER,'conf/user')
SCN.back() SCN.back()
end end
else else

View File

@@ -20,7 +20,10 @@ local sList={
lock={0,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99}, lock={0,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99},
wait={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, wait={0,1,2,3,4,5,6,7,8,10,15,20,30,60},
fall={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, fall={0,1,2,3,4,5,6,7,8,10,15,20,30,60},
hang={0,1,2,3,4,5,6,7,8,10,15,20,30,60},
hurry={0,1,2,3,4,5,6,7,8,10,1e99},
eventSet=EVENTSETS, eventSet=EVENTSETS,
holdMode={'hold','swap'},
} }
local scene={} local scene={}
@@ -87,6 +90,8 @@ scene.widgetList={
WIDGET.newSelector{name='lock', x=730,y=410,w=260,color='O',list=sList.lock,disp=ROOMval('lock'),code=ROOMsto('lock')}, WIDGET.newSelector{name='lock', x=730,y=410,w=260,color='O',list=sList.lock,disp=ROOMval('lock'),code=ROOMsto('lock')},
WIDGET.newSelector{name='wait', x=730,y=520,w=260,color='G',list=sList.wait,disp=ROOMval('wait'),code=ROOMsto('wait')}, WIDGET.newSelector{name='wait', x=730,y=520,w=260,color='G',list=sList.wait,disp=ROOMval('wait'),code=ROOMsto('wait')},
WIDGET.newSelector{name='fall', x=730,y=600,w=260,color='G',list=sList.fall,disp=ROOMval('fall'),code=ROOMsto('fall')}, WIDGET.newSelector{name='fall', x=730,y=600,w=260,color='G',list=sList.fall,disp=ROOMval('fall'),code=ROOMsto('fall')},
WIDGET.newSelector{name='hurry', x=730,y=680,w=260,color='G',list=sList.hurry,disp=ROOMval('hurry'),code=ROOMval('hurry')},
WIDGET.newSelector{name='hang', x=730,y=760,w=260,color='G',list=sList.hang,disp=ROOMval('hang'),code=ROOMval('hang')},
--Capacity & Create & Back --Capacity & Create & Back
WIDGET.newSelector{name='capacity', x=1070,y=330,w=310,color='lY',list={2,3,4,5,7,10,17,31,49,99},disp=ROOMval('capacity'),code=ROOMsto('capacity')}, WIDGET.newSelector{name='capacity', x=1070,y=330,w=310,color='lY',list={2,3,4,5,7,10,17,31,49,99},disp=ROOMval('capacity'),code=ROOMsto('capacity')},
@@ -94,18 +99,19 @@ scene.widgetList={
WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,font=60,fText=CHAR.icon.back,code=backScene}, WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,font=60,fText=CHAR.icon.back,code=backScene},
--Special rules --Special rules
WIDGET.newSwitch{name='ospin', x=850, y=760 ,lim=210,disp=ROOMval('ospin'), code=ROOMrev('ospin')}, WIDGET.newSwitch{name='ospin', x=850, y=850, lim=210,disp=ROOMval('ospin'), code=ROOMrev('ospin')},
WIDGET.newSwitch{name='fineKill', x=850, y=850 ,lim=210,disp=ROOMval('fineKill'), code=ROOMrev('fineKill')}, WIDGET.newSwitch{name='fineKill', x=850, y=910, lim=210,disp=ROOMval('fineKill'), code=ROOMrev('fineKill')},
WIDGET.newSwitch{name='b2bKill', x=850, y=940 ,lim=210,disp=ROOMval('b2bKill'), code=ROOMrev('b2bKill')}, WIDGET.newSwitch{name='b2bKill', x=850, y=970, lim=210,disp=ROOMval('b2bKill'), code=ROOMrev('b2bKill')},
WIDGET.newSwitch{name='lockout', x=850, y=1030,lim=210,disp=ROOMval('lockout'), code=ROOMval('lockout')}, WIDGET.newSwitch{name='lockout', x=850, y=1030,lim=210,disp=ROOMval('lockout'), code=ROOMrev('lockout')},
WIDGET.newSwitch{name='easyFresh', x=1170,y=760 ,lim=250,disp=ROOMval('easyFresh'),code=ROOMrev('easyFresh')}, WIDGET.newSwitch{name='easyFresh', x=1170,y=850, lim=250,disp=ROOMval('easyFresh'),code=ROOMrev('easyFresh')},
WIDGET.newSwitch{name='deepDrop', x=1170,y=850 ,lim=250,disp=ROOMval('deepDrop'), code=ROOMrev('deepDrop')}, WIDGET.newSwitch{name='deepDrop', x=1170,y=910, lim=250,disp=ROOMval('deepDrop'), code=ROOMrev('deepDrop')},
WIDGET.newSwitch{name='bone', x=1170,y=940 ,lim=250,disp=ROOMval('bone'), code=ROOMrev('bone')}, WIDGET.newSwitch{name='bone', x=1170,y=970, lim=250,disp=ROOMval('bone'), code=ROOMrev('bone')},
--Rule set --Rule set
WIDGET.newSelector{name='eventSet', x=310,y=880,w=360,color='H',list=sList.eventSet,disp=ROOMval('eventSet'),code=ROOMsto('eventSet')}, WIDGET.newSelector{name='eventSet', x=1050,y=760,w=340,color='H',list=sList.eventSet,disp=ROOMval('eventSet'),code=ROOMval('eventSet')},
--Next & Hold --Next & Hold
WIDGET.newSelector{name='holdMode', x=310, y=890, w=300,color='lY',list=sList.holdMode,disp=ROOMval('holdMode'),code=ROOMval('holdMode'),hideF=function()return CUSTOMENV.holdCount==0 end},
WIDGET.newSlider{name='nextCount', x=140, y=960, lim=130,w=200,unit=6,disp=ROOMval('nextCount'),code=ROOMsto('nextCount')}, WIDGET.newSlider{name='nextCount', x=140, y=960, lim=130,w=200,unit=6,disp=ROOMval('nextCount'),code=ROOMsto('nextCount')},
WIDGET.newSlider{name='holdCount', x=140, y=1030,lim=130,w=200,unit=6,disp=ROOMval('holdCount'),code=ROOMsto('holdCount')}, WIDGET.newSlider{name='holdCount', x=140, y=1030,lim=130,w=200,unit=6,disp=ROOMval('holdCount'),code=ROOMsto('holdCount')},
WIDGET.newSwitch{name='infHold', x=560, y=960, lim=200, disp=ROOMval('infHold'),code=ROOMrev('infHold'),hideF=function()return ROOMENV.holdCount==0 end}, WIDGET.newSwitch{name='infHold', x=560, y=960, lim=200, disp=ROOMval('infHold'),code=ROOMrev('infHold'),hideF=function()return ROOMENV.holdCount==0 end},

View File

@@ -90,7 +90,7 @@ function scene.keyDown(key)
local rep=listBox:getSel() local rep=listBox:getSel()
if rep then if rep then
if rep.available and rep.fileName then if rep.available and rep.fileName then
local repStr=FILE.load(rep.fileName,'string') local repStr=loadFile(rep.fileName,'-string')
if repStr then if repStr then
love.system.setClipboardText(love.data.encode('string','base64',repStr)) love.system.setClipboardText(love.data.encode('string','base64',repStr))
MES.new('info',text.exportSuccess) MES.new('info',text.exportSuccess)
@@ -108,7 +108,7 @@ function scene.keyDown(key)
local fileName=os.date("replay/%Y_%m_%d_%H%M%S_import.rep") local fileName=os.date("replay/%Y_%m_%d_%H%M%S_import.rep")
local rep=DATA.parseReplayData(fileName,fileData,false) local rep=DATA.parseReplayData(fileName,fileData,false)
if rep.available then if rep.available then
if FILE.save(fileData,fileName,'d')then if saveFile(fileData,fileName,'-d')then
table.insert(REPLAY,1,rep) table.insert(REPLAY,1,rep)
MES.new('info',text.importSuccess) MES.new('info',text.importSuccess)
end end

View File

@@ -71,7 +71,7 @@ scene.widgetList={
local D=_parseCB() local D=_parseCB()
if D then if D then
TABLE.update(D,VK_ORG) TABLE.update(D,VK_ORG)
FILE.save(VK_ORG,'conf/virtualkey') saveFile(VK_ORG,'conf/virtualkey')
MES.new('check',text.importSuccess) MES.new('check',text.importSuccess)
else else
MES.new('error',text.dataCorrupted) MES.new('error',text.dataCorrupted)

View File

@@ -31,24 +31,25 @@ function scene.draw()
end end
scene.widgetList={ scene.widgetList={
WIDGET.newText{name='title', x=640,y=15,font=80}, WIDGET.newText{name='title', x=640,y=15,font=80},
WIDGET.newButton{name='graphic', x=200, y=80, w=240,h=80,color='lC',font=35,code=swapScene('setting_video','swipeR')}, WIDGET.newButton{name='graphic', x=200, y=80, w=240,h=80,color='lC',font=35,code=swapScene('setting_video','swipeR')},
WIDGET.newButton{name='sound', x=1080, y=80, w=240,h=80,color='lC',font=35,code=swapScene('setting_sound','swipeL')}, WIDGET.newButton{name='sound', x=1080, y=80, w=240,h=80,color='lC',font=35,code=swapScene('setting_sound','swipeL')},
WIDGET.newButton{name='layout', x=250, y=540, w=200,h=70,font=35,code=goScene'setting_skin'}, WIDGET.newButton{name='layout', x=250, y=540, w=200,h=70,font=35,code=goScene'setting_skin'},
WIDGET.newButton{name='ctrl', x=290, y=220, w=320,h=80,font=35,code=goScene'setting_control'}, WIDGET.newButton{name='ctrl', x=290, y=220, w=320,h=80,font=35,code=goScene'setting_control'},
WIDGET.newButton{name='key', x=640, y=220, w=320,h=80,color=MOBILE and'dH',font=35,code=goScene'setting_key'}, WIDGET.newButton{name='key', x=640, y=220, w=320,h=80,color=MOBILE and'dH',font=35, code=goScene'setting_key'},
WIDGET.newButton{name='touch', x=990, y=220, w=320,h=80,color=not MOBILE and'dH',font=35,code=goScene'setting_touch'}, WIDGET.newButton{name='touch', x=990, y=220, w=320,h=80,color=not MOBILE and'dH',font=35, code=goScene'setting_touch',hideF=function()return not SETTING.VKSwitch end},
WIDGET.newSlider{name='reTime', x=330, y=320, w=300,lim=180,unit=10,disp=SETval('reTime'), code=SETsto('reTime'),show=function(S)return(.5+S.disp()*.25).."s"end}, WIDGET.newSwitch{name='showVK', x=1100, y=150, lim=400, disp=SETval('VKSwitch'), code=SETrev('VKSwitch')},
WIDGET.newSelector{name='RS', x=300, y=420, w=300,color='S', disp=SETval('RS'), code=SETsto('RS'),list={'TRS','SRS','SRS_plus','SRS_X','BiRS','ARS_Z','ASC','ASC_plus','C2','C2_sym','Classic','Classic_plus','None','None_plus'}}, WIDGET.newSlider{name='reTime', x=330, y=320, w=300,lim=180,unit=10,disp=SETval('reTime'), code=SETsto('reTime'),show=function(S)return(.5+S.disp()*.25).."s"end},
WIDGET.newSelector{name='menuPos', x=980, y=320, w=300,color='O', disp=SETval('menuPos'), code=SETsto('menuPos'),list={'left','middle','right'}}, WIDGET.newSelector{name='RS', x=300, y=420, w=300,color='S', disp=SETval('RS'), code=SETsto('RS'),list={'TRS','SRS','SRS_plus','SRS_X','BiRS','ARS_Z','ASC','ASC_plus','C2','C2_sym','Classic','Classic_plus','None','None_plus'}},
WIDGET.newSwitch{name='sysCursor' ,x=1060, y=390, lim=580, disp=SETval('sysCursor'),code=function()SETTING.sysCursor=not SETTING.sysCursor applyCursor()end}, WIDGET.newSelector{name='menuPos',x=980, y=320, w=300,color='O', disp=SETval('menuPos'), code=SETsto('menuPos'),list={'left','middle','right'}},
WIDGET.newSwitch{name='autoPause', x=1060, y=450, lim=580, disp=SETval('autoPause'),code=SETrev('autoPause')}, WIDGET.newSwitch{name='sysCursor',x=1060, y=390, lim=580, disp=SETval('sysCursor'),code=function()SETTING.sysCursor=not SETTING.sysCursor applyCursor()end},
WIDGET.newSwitch{name='autoSave', x=1060, y=500, lim=580, disp=SETval('autoSave'), code=SETrev('autoSave')}, WIDGET.newSwitch{name='autoPause',x=1060, y=450, lim=580, disp=SETval('autoPause'),code=SETrev('autoPause')},
WIDGET.newSwitch{name='autoLogin', x=960, y=580, lim=480, disp=SETval('autoLogin'),code=SETrev('autoLogin')}, WIDGET.newSwitch{name='autoSave', x=1060, y=500, lim=580, disp=SETval('autoSave'), code=SETrev('autoSave')},
WIDGET.newSwitch{name='simpMode', x=960, y=640, lim=480, disp=SETval('simpMode'), WIDGET.newSwitch{name='autoLogin',x=960, y=580, lim=480, disp=SETval('autoLogin'),code=SETrev('autoLogin')},
WIDGET.newSwitch{name='simpMode', x=960, y=640, lim=480, disp=SETval('simpMode'),
code=function() code=function()
SETTING.simpMode=not SETTING.simpMode SETTING.simpMode=not SETTING.simpMode
for i=1,#SCN.stack,2 do for i=1,#SCN.stack,2 do
@@ -58,7 +59,7 @@ scene.widgetList={
end end
end end
end}, end},
WIDGET.newButton{name='back', x=1140, y=640, w=170,h=80,font=60,fText=CHAR.icon.back,code=backScene}, WIDGET.newButton{name='back', x=1140, y=640, w=170,h=80,font=60,fText=CHAR.icon.back,code=backScene},
} }
return scene return scene

View File

@@ -23,7 +23,7 @@ function scene.sceneInit()
BG.set('none') BG.set('none')
end end
function scene.sceneBack() function scene.sceneBack()
FILE.save(KEY_MAP,'conf/key') saveFile(KEY_MAP,'conf/key')
end end
local forbbidenKeys={ local forbbidenKeys={

View File

@@ -62,6 +62,7 @@ local function _nextSkin(i)
SETTING.skin[i]=SETTING.skin[i]%16+1 SETTING.skin[i]=SETTING.skin[i]%16+1
end end
local function _nextDir(i) local function _nextDir(i)
trySettingWarn()
SETTING.face[i]=(SETTING.face[i]+1)%4 SETTING.face[i]=(SETTING.face[i]+1)%4
minoRot0[i]=minoRot0[i]+1.5707963 minoRot0[i]=minoRot0[i]+1.5707963
if not selEggMode and not GAME.playing then if not selEggMode and not GAME.playing then

View File

@@ -9,10 +9,10 @@ local snapUnit=1
local selected--Button selected local selected--Button selected
local function _save1() local function _save1()
FILE.save(VK_ORG,'conf/vkSave1') saveFile(VK_ORG,'conf/vkSave1')
end end
local function _load1() local function _load1()
local D=FILE.load('conf/vkSave1') local D=loadFile('conf/vkSave1')
if D then if D then
TABLE.update(D,VK_ORG) TABLE.update(D,VK_ORG)
else else
@@ -20,10 +20,10 @@ local function _load1()
end end
end end
local function _save2() local function _save2()
FILE.save(VK_ORG,'conf/vkSave2') saveFile(VK_ORG,'conf/vkSave2')
end end
local function _load2() local function _load2()
local D=FILE.load('conf/vkSave2') local D=loadFile('conf/vkSave2')
if D then if D then
TABLE.update(D,VK_ORG) TABLE.update(D,VK_ORG)
else else
@@ -37,7 +37,7 @@ function scene.sceneInit()
selected=false selected=false
end end
function scene.sceneBack() function scene.sceneBack()
FILE.save(VK_ORG,'conf/virtualkey') saveFile(VK_ORG,'conf/virtualkey')
end end
local function _onVK_org(x,y) local function _onVK_org(x,y)

View File

@@ -5,7 +5,7 @@ function scene.sceneInit()
end end
function scene.draw() function scene.draw()
if SETTING.VKSwitch and SETTING.VKTrack then if SETTING.VKTrack then
love.graphics.setColor(1,1,1) love.graphics.setColor(1,1,1)
setFont(30) setFont(30)
mStr(text.VKTchW,140+500*SETTING.VKTchW,800-WIDGET.scrollPos) mStr(text.VKTchW,140+500*SETTING.VKTchW,800-WIDGET.scrollPos)
@@ -15,9 +15,17 @@ function scene.draw()
end end
local function _VKAdisp(n)return function()return VK_ORG[n].ava end end local function _VKAdisp(n)return function()return VK_ORG[n].ava end end
local function _VKAcode(n)return function()VK_ORG[n].ava=not VK_ORG[n].ava end end local function _VKAcode(n)
local function _notShow()return not SETTING.VKSwitch end return n<10 and
local function _notTrack()return not(SETTING.VKSwitch and SETTING.VKTrack)end function()
VK_ORG[n].ava=not VK_ORG[n].ava
trySettingWarn()
end or
function()
VK_ORG[n].ava=not VK_ORG[n].ava
end
end
local function _notTrack()return not SETTING.VKTrack end
scene.widgetScrollHeight=340 scene.widgetScrollHeight=340
scene.widgetList={ scene.widgetList={
@@ -44,13 +52,12 @@ scene.widgetList={
WIDGET.newButton{name='norm', x=840, y=80, w=240,h=80, font=35,code=function()for i=1,20 do VK_ORG[i].ava=i<11 end end}, WIDGET.newButton{name='norm', x=840, y=80, w=240,h=80, font=35,code=function()for i=1,20 do VK_ORG[i].ava=i<11 end end},
WIDGET.newButton{name='pro', x=1120, y=80, w=240,h=80, font=35,code=function()for i=1,20 do VK_ORG[i].ava=true end end}, WIDGET.newButton{name='pro', x=1120, y=80, w=240,h=80, font=35,code=function()for i=1,20 do VK_ORG[i].ava=true end end},
WIDGET.newSwitch{name='hide', x=1150, y=200, lim=400, font=40,disp=SETval('VKSwitch'),code=SETrev('VKSwitch')}, WIDGET.newSwitch{name='icon', x=1150, y=240, lim=400, font=35,disp=SETval('VKIcon'),code=SETrev('VKIcon')},
WIDGET.newSwitch{name='icon', x=1150, y=300, lim=400, font=40,disp=SETval('VKIcon'),code=SETrev('VKIcon'),hideF=_notShow}, WIDGET.newSlider{name='sfx', x=830, y=320, lim=160,w=400, font=35,change=function()SFX.play('virtualKey',SETTING.VKSFX)end,disp=SETval('VKSFX'),code=SETsto('VKSFX')},
WIDGET.newSlider{name='sfx', x=830, y=380, lim=160,w=400, font=35,change=function()SFX.play('virtualKey',SETTING.VKSFX)end,disp=SETval('VKSFX'),code=SETsto('VKSFX'),hideF=_notShow}, WIDGET.newSlider{name='vib', x=830, y=390, lim=160,w=400,unit=6, font=35,change=function()if SETTING.vib>0 then VIB(SETTING.vib+SETTING.VKVIB)end end,disp=SETval('VKVIB'),code=SETsto('VKVIB')},
WIDGET.newSlider{name='vib', x=830, y=450, lim=160,w=400,unit=6, font=35,change=function()if SETTING.vib>0 then VIB(SETTING.vib+SETTING.VKVIB)end end,disp=SETval('VKVIB'),code=SETsto('VKVIB'),hideF=_notShow}, WIDGET.newSlider{name='alpha', x=830, y=460, lim=160,w=400, font=35,disp=SETval('VKAlpha'),code=SETsto('VKAlpha')},
WIDGET.newSlider{name='alpha', x=830, y=520, lim=160,w=400, font=40,disp=SETval('VKAlpha'),code=SETsto('VKAlpha'),hideF=_notShow},
WIDGET.newSwitch{name='track', x=360, y=720, lim=250, font=35,disp=SETval('VKTrack'),code=SETrev('VKTrack'),hideF=_notShow}, WIDGET.newSwitch{name='track', x=360, y=720, lim=250, font=35,disp=SETval('VKTrack'),code=SETrev('VKTrack')},
WIDGET.newSwitch{name='dodge', x=800, y=720, lim=250, font=35,disp=SETval('VKDodge'),code=SETrev('VKDodge'),hideF=_notTrack}, WIDGET.newSwitch{name='dodge', x=800, y=720, lim=250, font=35,disp=SETval('VKDodge'),code=SETrev('VKDodge'),hideF=_notTrack},
WIDGET.newSlider{name='tchW', x=140, y=860, w=1000, font=35,disp=SETval('VKTchW'),code=function(i)SETTING.VKTchW=i SETTING.VKCurW=math.max(SETTING.VKCurW,i)end,hideF=_notTrack}, WIDGET.newSlider{name='tchW', x=140, y=860, w=1000, font=35,disp=SETval('VKTchW'),code=function(i)SETTING.VKTchW=i SETTING.VKCurW=math.max(SETTING.VKCurW,i)end,hideF=_notTrack},
WIDGET.newSlider{name='curW', x=140, y=930, w=1000, font=35,disp=SETval('VKCurW'),code=function(i)SETTING.VKCurW=i SETTING.VKTchW=math.min(SETTING.VKTchW,i)end,hideF=_notTrack}, WIDGET.newSlider{name='curW', x=140, y=930, w=1000, font=35,disp=SETval('VKCurW'),code=function(i)SETTING.VKCurW=i SETTING.VKTchW=math.min(SETTING.VKTchW,i)end,hideF=_notTrack},

View File

@@ -69,38 +69,37 @@ end
gc.setDefaultFilter('linear','linear') gc.setDefaultFilter('linear','linear')
TEXTURE.title=NSC(1160,236)--Title image (Middle: 580,118) TEXTURE.title=NSC(1040,236)--Title image (Middle: 580,118)
do do
for i=1,8 do gc.setLineWidth(12)
local triangles=love.math.triangulate(SVG_TITLE[i]) gc.translate(10,10)
for i=1,#SVG_TITLE_FILL do
local triangles=love.math.triangulate(SVG_TITLE_FILL[i])
gc.translate(12*i,i==1 and 8 or 14)
gc.setLineWidth(16)
gc.setColor(COLOR.Z) gc.setColor(COLOR.Z)
gc.polygon('line',SVG_TITLE[i]) gc.polygon('line',SVG_TITLE_FILL[i])
gc.setColor(.2,.2,.2) gc.setColor(.2,.2,.2)
for j=1,#triangles do for j=1,#triangles do
gc.polygon('fill',triangles[j]) gc.polygon('fill',triangles[j])
end end
gc.translate(-12*i,i==1 and -8 or -14)
end end
gc.translate(-10,-10)
end end
TEXTURE.title_color=NSC(1160,236)--Title image (colored) TEXTURE.title_color=NSC(1040,236)--Title image (colored)
do do
local titleColor={COLOR.P,COLOR.F,COLOR.V,COLOR.A,COLOR.M,COLOR.N,COLOR.W,COLOR.Y} local titleColor={COLOR.P,COLOR.F,COLOR.V,COLOR.A,COLOR.M,COLOR.N,COLOR.W,COLOR.Y}
gc.translate(10,10)
for i=1,8 do for i=1,8 do
local triangles=love.math.triangulate(SVG_TITLE[i]) local triangles=love.math.triangulate(SVG_TITLE_FILL[i])
gc.translate(12*i,i==1 and 8 or 14) gc.setLineWidth(12)
gc.setLineWidth(16)
gc.setColor(COLOR.Z) gc.setColor(COLOR.Z)
gc.polygon('line',SVG_TITLE[i]) gc.polygon('line',SVG_TITLE_FILL[i])
gc.setLineWidth(4) gc.setLineWidth(4)
gc.setColor(COLOR.D) gc.setColor(COLOR.D)
@@ -109,14 +108,11 @@ do
end end
gc.setColor(.2+.8*titleColor[i][1],.2+.8*titleColor[i][2],.2+.8*titleColor[i][3],.3) gc.setColor(.2+.8*titleColor[i][1],.2+.8*titleColor[i][2],.2+.8*titleColor[i][3],.3)
gc.translate(-4,-4)
for j=1,#triangles do for j=1,#triangles do
gc.polygon('fill',triangles[j]) gc.polygon('fill',triangles[j])
end end
gc.translate(4,4)
gc.translate(-12*i,i==1 and -8 or -14)
end end
gc.translate(-10,-10)
end end
TEXTURE.multiple=GC.DO{15,15, TEXTURE.multiple=GC.DO{15,15,

View File

@@ -3,26 +3,42 @@ return[=[
Tetro-1010(2C2N, 重力); Tetra-link(桌游) Tetro-1010(2C2N, 重力); Tetra-link(桌游)
噗哟; 泡泡龙; 求合体; 坦克大战; 扫雷; 接水管; 记忆 噗哟; 泡泡龙; 求合体; 坦克大战; 扫雷; 接水管; 记忆
其他未来内容: 其他未来内容:
组队战; 实时统计数据可视化; 教学关; 从录像继续 实时统计数据可视化; 教学关脚本语言; 从录像继续
重做模式选择UI; 重做模组UI; 加速下落; spike相关统计数据 模式系统重做; 重做模组UI; 加速下落; spike相关统计数据
支持更多手柄; 场地格边缘线; 模式数据分析; 高级自定义序列 等级系统; 场地格边缘线; 模式数据分析; 高级自定义序列
等级系统; 成就系统; 手势操作; C2连击; 特殊控件(虚拟摇杆等) 成就系统; 手势操作; C2连击; 特殊控件(虚拟摇杆等)
方块位移/旋转动画; 更细节的DAS选项; 拓展主题系统 组队战; 方块位移/旋转动画; 更细节的DAS选项; 拓展主题系统
可调攻击系统; 更多消除方式; 可调场地宽度; 新联网游戏场景切换逻辑 更自由的攻击系统; 更多消除方式; 可调场地宽度; 新联网游戏场景切换逻辑
工程编译到字节码; task-Z(新AI); 自适应UI; 多方块 task-Z(新AI); 自适应UI; 多方块
0.17.0: 硬着陆 Hard Landing 0.17.0: 硬着陆 Hard Landing
新增: 新增:
新模式:大爆炸 新模式:清版竞速
新模式:策略堆叠(原设计来自Cambridge游戏, by NOT_A_ROBOT) 新模式:策略堆叠(原设计来自游戏Cambridge, by NOT_A_ROBOT)
添加lockout判负规则(默认关闭) 新BGM:malate(暂未使用)
新机制:出块延迟打断(ARE打断)(默认关闭) #471
添加锁定在外判负(lockout)规则(默认关闭)
全局默认使用5帧窒息延迟
支持摇杆和扳机(参数暂时不能调整)
改动: 改动:
TRS的S/Z添加四个踢墙防止在一些地方卡死 调整游戏大logo为正体字
软降n格的键也可以触发深降
ultra模式计时器改为秒表,重开的时候会重播bgm
出块/消行延迟逻辑修正,现在真的是0延迟,不再有一帧等待了(略微影响手感,更滑)
生成位置预览开启后hold的生成位置也可见 #453 生成位置预览开启后hold的生成位置也可见 #453
TRS的S/Z添加四个踢墙防止在一些地方卡死
优化pc训练模式体验,添加胜利条件,不再无尽 优化pc训练模式体验,添加胜利条件,不再无尽
堆积模式添加15帧的窒息延迟 #465 堆积模式添加15帧的窒息延迟 #465
修改部分不常用设置时会显示警告
小程序arm加入计时器和重置按钮
控制台使用等宽字体,更有味道(
代码: 代码:
bgm模块可限制最大加载数不容易达到上限导致没声 #447 BGM模块可限制最大加载数,不容易达到上限导致没声 #447
语音模块支持设置轻微随机音调偏移半径(游戏内固定使用1)
较大规模整理玩家相关代码,重构出块延迟/消行延迟/`当前块`逻辑
重构字体模块,支持多字体
再次封装FILE模块
扩展字符串扩展模块
修复: 修复:
机翻语言超级消除无行数显示 #462 机翻语言超级消除无行数显示 #462
竞速-效率左侧信息颜色问题 竞速-效率左侧信息颜色问题
@@ -109,7 +125,7 @@ return[=[
新语音包:miku(by vocaloidvictory) 新语音包:miku(by vocaloidvictory)
新BGM:Jazz nihilism(用于节日主题, by Trebor) 新BGM:Jazz nihilism(用于节日主题, by Trebor)
新BGM:Race remix(用于大师-ph, by 柒栎流星) 新BGM:Race remix(用于大师-ph, by 柒栎流星)
新BGM:Sakura(用于限时打分, by C₂₉H₂₅N₃O₅) 新BGM:Sakura(用于ultra, by C₂₉H₂₅N₃O₅)
新BGM:Null(用于节日主题) 新BGM:Null(用于节日主题)
新音效:单次消5/6行 新音效:单次消5/6行
新机制:swap(hold的另一种实现) 新机制:swap(hold的另一种实现)
@@ -1326,7 +1342,7 @@ return[=[
0.10.5: 特效更新 FX update 0.10.5: 特效更新 FX update
新内容: 新内容:
瞬移特效独立为瞬降和移动(旋转)特效,增加移动特效滑条,各特效范围均为0~5 瞬移特效独立为瞬降和移动(旋转)特效,增加移动特效滑条,各特效范围均为0~5
增加两个莫名其妙的背景(放在无尽和限时打分) 增加两个莫名其妙的背景(放在无尽和ultra)
把之前不小心弄丢的自制蓝屏报错界面捡回来了 把之前不小心弄丢的自制蓝屏报错界面捡回来了
改动: 改动:
雷达图OPM参数改为ADPM 雷达图OPM参数改为ADPM
@@ -1446,7 +1462,7 @@ return[=[
pc训练方块ghost浮空 pc训练方块ghost浮空
i平放顶层消1的奇怪行为 i平放顶层消1的奇怪行为
玩家掉出屏幕过程中绘制场地时剪裁不正确 玩家掉出屏幕过程中绘制场地时剪裁不正确
限时打分的时间条和hold重合 ultra的时间条和hold重合
0.9.2: Global Update 0.9.2: Global Update
new: new:

View File

@@ -1,7 +1,7 @@
return{ return{
["apkCode"]=405, ["apkCode"]=410,
["code"]=1700, ["code"]=1700,
["string"]="V0.17.0", ["string"]="V0.17.0",
["room"]="ver A-1", ["room"]="ver A-2",
["name"]="硬着陆 Hard Landing", ["name"]="硬着陆 Hard Landing",
} }