Compare commits

..

27 Commits

Author SHA1 Message Date
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
MrZ626
7f9c9248ce 版本推进 2021-11-19 17:36:12 +08:00
MrZ626
9c1db48804 整理代码 2021-11-19 17:35:53 +08:00
C₂₉H₂₅N₃O₅
0628830f0c 继续调词典(嗯) 2021-11-19 01:21:48 -06:00
C₂₉H₂₅N₃O₅
9436f2f5fb 微调词典 大改legals (#472) 2021-11-19 01:17:12 -06:00
MrZ626
c5e1b5617f 再调整词典两个词条 2021-11-19 14:21:42 +08:00
MrZ626
298c417aa3 更新部分词条(英文待翻译) 2021-11-19 02:40:46 +08:00
MrZ626
fc74831700 添加lockout判负规则(默认关闭) 2021-11-19 02:33:21 +08:00
MrZ626
d9db55de44 整理代码,修正一处多余代码忘了删 2021-11-19 02:16:34 +08:00
MrZ626
3fd205e8c2 bgm模块添加可调节的最大加载数限制,更不容易达到引擎加载音频数上限 close #447 2021-11-19 01:47:14 +08:00
MrZ626
5cb828fb92 修改策略堆叠模式的解锁路径 2021-11-19 00:59:16 +08:00
33 changed files with 374 additions and 223 deletions

View File

@@ -1,4 +1,6 @@
local Sources={}
local lastLoaded={}
local maxLoadedCount=3
local SourceObjList={}
local volume=1
local BGM={
@@ -37,15 +39,41 @@ end
local function check_curFadeOut(task,code,src)
return task.code==code and task.args[1]==src
end
local function _tryReleaseSources()
local n=#lastLoaded
while #lastLoaded>maxLoadedCount do
local name=lastLoaded[n]
if SourceObjList[name].source:isPlaying()then
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
function BGM.setDefault(bgm)
BGM.default=bgm
end
function BGM.setMaxSources(count)
maxLoadedCount=count
_tryReleaseSources()
end
function BGM.setChange(func)
BGM.onChange=func
end
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
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.init(list)
BGM.init=nil
@@ -53,7 +81,7 @@ function BGM.init(list)
local simpList={}
for _,v in next,list do
table.insert(simpList,v.name)
Sources[v.name]=v.path
SourceObjList[v.name]={path=v.path,source=false}
end
table.sort(simpList)
function BGM.getList()return simpList end
@@ -61,58 +89,43 @@ function BGM.init(list)
LOG(count.." BGM files added")
function BGM.getCount()return count end
local function _load(name)
if type(Sources[name])=='string'then
if love.filesystem.getInfo(Sources[name])then
Sources[name]=love.audio.newSource(Sources[name],'stream')
Sources[name]:setLooping(true)
Sources[name]:setVolume(0)
local function _tryLoad(name)
if SourceObjList[name]then
if SourceObjList[name].source then
return true
elseif love.filesystem.getInfo(SourceObjList[name].path)then
SourceObjList[name].source=love.audio.newSource(SourceObjList[name].path,'stream')
SourceObjList[name].source:setLooping(true)
SourceObjList[name].source:setVolume(0)
table.insert(lastLoaded,1,name)
_tryReleaseSources()
return true
else
LOG("No BGM: "..Sources[name],5)
LOG("No BGM: "..SourceObjList[name],5)
end
elseif Sources[name]then
return true
elseif name then
LOG("No BGM: "..name,5)
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.loadAll()--Not neccessary, unless you want avoid the lag when playing something for the first time
for name in next,Sources do
_load(name)
end
end
function BGM.play(name)
name=name or BGM.default
if not _load(name)then return end
if not _tryLoad(name)then return end
if volume==0 then
BGM.nowPlay=name
BGM.playing=Sources[name]
BGM.playing=SourceObjList[name].source
return true
end
if name and Sources[name]then
if name and SourceObjList[name].source then
if BGM.nowPlay~=name then
if BGM.nowPlay then
TASK.new(task_fadeOut,BGM.playing)
end
TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,Sources[name])
TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,SourceObjList[name].source)
TASK.removeTask_code(task_fadeIn)
TASK.new(task_fadeIn,Sources[name])
TASK.new(task_fadeIn,SourceObjList[name].source)
BGM.nowPlay=name
BGM.playing=Sources[name]
BGM.playing=SourceObjList[name].source
BGM.lastPlayed=BGM.nowPlay
BGM.playing:seek(0)
BGM.playing:play()
@@ -128,8 +141,8 @@ function BGM.init(list)
end
function BGM.continue()
if BGM.lastPlayed then
BGM.nowPlay,BGM.playing=BGM.lastPlayed,Sources[BGM.lastPlayed]
TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,Sources[BGM.nowPlay])
BGM.nowPlay,BGM.playing=BGM.lastPlayed,SourceObjList[BGM.lastPlayed].source
TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,SourceObjList[BGM.nowPlay].source)
TASK.removeTask_code(task_fadeIn)
TASK.new(task_fadeIn,BGM.playing)
BGM.playing:play()

View File

@@ -1,7 +1,6 @@
NONE={}function NULL()end
EDITING=""
LOADED=false
ERRDATA={}
--Pure lua modules (basic)
MATH= require'Zframework.mathExtend'
@@ -74,7 +73,8 @@ local xOy=SCR.xOy
local ITP=xOy.inverseTransformPoint
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
@@ -288,18 +288,75 @@ function love.textinput(texts)
WIDGET.textinput(texts)
end
--analog sticks: -1, 0, 1 for neg, neutral, pos
--triggers: 0 for released, 1 for pressed
local jsAxisEventName={
leftx={'leftstick_left','leftstick_right'},
lefty={'leftstick_up','leftstick_down'},
rightx={'rightstick_left','rightstick_right'},
righty={'rightstick_up','rightstick_down'},
triggerleft='triggerleft',
triggerright='triggerright'
}
function love.joystickadded(JS)
table.insert(joysticks,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 i=TABLE.find(joysticks,JS)
if i then
table.remove(joysticks,i)
local js=jsState[JS:getID()]
if js then
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
local keyMirror={
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>.5 and 1 or
val<-.5 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>0 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
local dPadToKey={
dpup='up',
dpdown='down',
dpleft='left',
@@ -311,39 +368,16 @@ function love.gamepadpressed(_,i)
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 SCN.keyDown then SCN.keyDown(dPadToKey[i]or i)
elseif i=="back"then SCN.back()
else WIDGET.gamepadPressed(keyMirror[i]or i)
else WIDGET.gamepadPressed(dPadToKey[i]or i)
end
end
function love.gamepadreleased(_,i)
if SCN.swapping then return end
if SCN.gamepadUp then SCN.gamepadUp(i)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)
if SCN.fileDropped then SCN.fileDropped(file)end
end
@@ -379,7 +413,7 @@ end
function love.errorhandler(msg)
if type(msg)~='string'then
msg="Unknown error"
elseif msg:find("Invaild UTF-8")and text then
elseif msg:find("Invalid UTF-8")and text then
msg=text.tryAnotherBuild
end
@@ -403,20 +437,20 @@ function love.errorhandler(msg)
love.audio.stop()
gc.reset()
if LOADED and #ERRDATA<3 then
if LOADED and #errData<3 then
BG.set('none')
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
love.filesystem.append('conf/error.log',
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"
)
--Get screencapture
gc.captureScreenshot(function(_)ERRDATA[#ERRDATA].shot=gc.newImage(_)end)
gc.captureScreenshot(function(_)errData[#errData].shot=gc.newImage(_)end)
gc.present()
--Create a new mainLoop thread to keep game alive
@@ -539,7 +573,7 @@ function love.run()
--Scene Launch
while #SCN.stack>0 do SCN.pop()end
SCN.push('quit','slowFade')
SCN.init(#ERRDATA==0 and'load'or'error')
SCN.init(#errData==0 and'load'or'error')
return function()
local _
@@ -703,6 +737,9 @@ end
local Z={}
Z.js=jsState
Z.errData=errData
function Z.setIfPowerInfo(func)showPowerInfo=func end
--[Warning] Color and line width is uncertain value, set it in the function.

View File

@@ -72,11 +72,11 @@ function SFX.getCount()
return #sfxList
end
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
end
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
end
@@ -112,7 +112,7 @@ function SFX.playSample(pack,...)--vol-1, sampSet1, vol-2, sampSet2
end
end
end
function SFX.play(name,vol,pos,pitch)
local function _play(name,vol,pos,pitch)
if volume==0 or vol==0 then return end
local S=Sources[name]--Source list
if not S then return end
@@ -134,33 +134,13 @@ function SFX.play(name,vol,pos,pitch)
S:setPosition(0,0,0)
end
end
S:setVolume(((vol or 1)*volume)^1.626)
S:setVolume(vol^1.626)
S:setPitch(pitch and 1.0594630943592953^pitch or 1)
S:play()
end
function SFX.fplay(name,vol,pos)
local S=Sources[name]--Source list
if not S then return end
local n=1
while S[n]:isPlaying()do
n=n+1
if not S[n]then
S[n]=S[1]:clone()
S[n]:seek(0)
break
end
end
S=S[n]--AU_SRC
if S:getChannelCount()==1 then
if pos then
pos=pos*stereo
S:setPosition(pos,1-pos^2,0)
else
S:setPosition(0,0,0)
end
end
S:setVolume(vol^1.626)
S:play()
SFX.fplay=_play--Play sounds without apply module's volume setting
function SFX.play(name,vol,pos,pitch)
_play(name,(vol or 1)*volume,pos,pitch)
end
function SFX.reset()
for _,L in next,Sources do

View File

@@ -1,4 +1,5 @@
local find=string.find
local rem=table.remove
local next,type=next,type
local TABLE={}
@@ -83,7 +84,7 @@ function TABLE.complete(new,old)
end
end
--Remove positive integer index of table
--Remove [1~#] of table
function TABLE.cut(G)
for i=1,#G do
G[i]=nil
@@ -97,16 +98,53 @@ function TABLE.clear(G)
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~#]
function TABLE.find(t,val)
for i=1,#t do if t[i]==val then return i end end
end
--Retuen next value of [1~#]
--Return next value of [1~#] (by value)
function TABLE.next(t,val)
for i=1,#t do if t[i]==val then return t[i%#t+1]end end
end
--------------------------
--Find value in whole table
function TABLE.search(t,val)
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
--------------------------
--Dump a simple lua table
do--function TABLE.dump(L,t)
local tabs={

View File

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

View File

@@ -1,26 +1,23 @@
**TECHMINO © 2019-2021 26F Studio. Some rights reserved.**
TECHMINO and "26F Studio" are trademarks of 26F Studio.
The TECHMINO game and source code are under a GNU Lesser General Public License Version 3.
TECHMINO © 2019-2021 26F Studio. Some rights reserved.
TECHMINO and "26F Studio" are trademarks of 26F Studio. The TECHMINO game and source code are under a GNU Lesser General Public License Version 3.
"Tetris" is the registered trademark of The Tetris Holding, LLC, licensed to The Tetris Company, Inc. TECHMINO is not a fan game of Tetris. TECHMINO and 26F Studio are not affiliated with Tetris Holding, LLC or The Tetris Company, Inc. in any way.
Powered by LÖVE, © 2006-2021 LÖVE Development Team.
Lua is free software distributed under the terms of the MIT license. Copyright © 1994-2021 by Lua.org, PUC-Rio.
Lua is free software distributed under the terms of the MIT license. Copyright © 1994~2021 by Lua.org, PUC-Rio.
SIMPLE LOVE LIGHTS is under a MIT License. Created by Dylan Hunn.
json.lua is copyrighted by rxi. © 2021 rxi.
IBM Plex is copyrighted by the International Business Machines Corporation. IBM and IBM Plex are trademarks of IBM Corp, registered in many jurisdictions worldwide. IBM Plex is licensed under the SIL Open Font License, Version 1.1.
The Apple logo, "Apple Inc.," iOS, iPadOS, macOS, iPhone, and Mac are registered trademarks of Apple Inc. in the United States of America and other countries or regions.
"Windows", the Windows logo, "Xbox", Xbox logo, and "Microsoft" are registered trademarks of Microsoft Corporation in the United States of America and other countries or regions.
Source Han Sans is copyrighted by Adobe Inc. Source Han Sans and Adobe are registered trademarks of Adobe Inc. in United States and other countries or regions. Source Han Sans is licensed under the SIL Open Font License.
IBM Plex is copyrighted by the International Business Machines Corporation. IBM and IBM Plex are trademarks of IBM Corp, registered in many jurisdictions worldwide. IBM Plex is licensed under the SIL Open Font License.
Source Han Sans is copyrighted by Adobe Inc. Source Han Sans and Adobe are registered trademarks of Adobe Inc. in United States and other countries or regions. Source Han Sans is licensed under the SIL Open Font License, Version 1.1.
JetBrains Mono is copyrighted by the JetBrains Mono Project authors. JetBrains Mono is a trademark of JetBrains s.r.o. JetBrains Mono is licensed under the SIL Open Font License, Version 1.1.
@@ -29,22 +26,26 @@ JetBrains Mono is copyrighted by the JetBrains Mono Project authors. JetBrains M
"PlayStation", "PS", "PlayStation Family Mark", "PS logo", "DualSense" and "Play Has No Limits" are registered trademarks or trademarks of Sony Interactive Entertainment Inc. "SONY" is a registered trademark of Sony Corporation. © 2021 Sony Interactive Entertainment LLC.
N3TWORK is a registered trademark of N3TWORK Inc. © 2021 N3TWORK Inc.
"Windows", the Windows logo, "Xbox", Xbox logo, and "Microsoft" are registered trademarks of Microsoft Corporation in the United States of America and other countries or regions.
The Apple logo, "Apple Inc.," iOS, iPadOS, macOS, iPhone, and Mac are registered trademarks of Apple Inc. in the United States of America and other countries or regions.
"EA" and "Electronic Arts" are registered trademarks of Electronic Arts Inc. © 2021 Electronic Arts Inc.
SEGA and the SEGA logo are registered trademarks of Sega Corporation. © 2021 Sega Corporation.
Oculus Quest is a registered trademark of Facebook Technologies, LLC. © Facebook, Inc.
Oculus Quest is a registered trademark of Facebook Technologies, LLC. © Meta Platforms, Inc.
"Nintendo" is a registered trademarks of Nintendo Co., Ltd. © 2021 Nintendo Co., Ltd.
N3TWORK is a registered trademark of N3TWORK Inc. © 2021 N3TWORK 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.
All other trademarks are the properties of their respective owners.
All other trademarks, logos, and copyrights are the properties of their respective owners.

View File

@@ -52,7 +52,9 @@ local _LOADTIME_=TIME()
Z=require'Zframework'
FONT.load('parts/fonts/proportional.ttf')
SCR.setSize(1280,720)--Initialize Screen size
BGM.setMaxSources(5)
BGM.setChange(function(name)MES.new('music',text.nowPlaying..name,5)end)
VOC.setDiversion(1)
table.insert(_LOADTIMELIST_,("Load Zframework: %.3fs"):format(TIME()-_LOADTIME_))
@@ -627,9 +629,9 @@ if TABLE.find(arg,'--test')then
TASK.new(function()
while true do
YIELD()
if ERRDATA[1]then break end
if Z.errData[1]then break 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)
love.event.quit(1)
end)

View File

@@ -13,13 +13,14 @@ return{
holdCount=1,
infHold=true,
phyHold=false,
hang=0,
hang=5,
--Visual
bone=false,
--Rule
sequence='bag',
lockout=false,
fieldH=20,
heightLimit=1e99,
bufferLimit=1e99,

View File

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

View File

@@ -167,7 +167,7 @@ return{
{"Tetris Gems",
"tetris online official gem",
"game",
"Another Tetris game from tetris.com. It has the gravity mechanism, and each game lasts for 2 minutes. There are three kinds of gem blocks with different abilities.",
"Another Tetris game from tetris.com. It has the gravity mechanism, and each game lasts for 1 minute. There are three kinds of gem blocks with different abilities.",
},
{"Tetris Mind Bender",
"tetris online official gem",
@@ -259,7 +259,7 @@ return{
{"Tetris Blitz",
"blitz ea mobile phone",
"game",
"A mobile Tetris game by Electronic Arts (EA). It has the gravity mechanism, and each game lasts for 2 minutes. A bunch of minoes fall down to the field at the beginning of the game, and you can enter the \"Frenzy\" mode by performing Tetris line clears continuously. There are many different power-ups available.\n\nThis game is no longer available since January 2020.",
"A mobile Tetris game by Electronic Arts (EA). It has the gravity mechanism, and each game lasts for 2 minutes. A bunch of minoes fall down to the field at the beginning of the game, and you can enter the \"Frenzy\" mode by performing line clears continuously. There are many different power-ups available. Also, this game has no top-out mechanism. When an incoming block overlaps with existing blocks in the field, the top lines will be cleared automatically. \n\nThis game is no longer available since April 2020.",
},
{"Tetris (EA)",
"tetris ea galaxy universe cosmos mobile phone",
@@ -269,7 +269,7 @@ return{
{"Tetris (N3TWORK)",
"tetris n3twork mobile phone",
"game",
"The latest mobile Tetris from N3TWORK Inc. It has a 3-minute ultra mode, a marathon mode and a Royale mode. The UI is great but its controls are not so good.",
"The latest mobile Tetris from N3TWORK Inc. It has a 3-minute ultra mode, a marathon mode and a 100-player Royale mode. The UI is great but its controls are not so good.",
},
{"Tetris Beat",
"tetris beat n3twork rhythm",
@@ -378,7 +378,7 @@ return{
{"Tetris",
"tetris",
"term",
"The name of the game (and its trademark). Also the name for clearing 4 lines at one time in official games.\nCoined from Tetra (greek for \"four\") and Tennis (favorite sport of the creator of Tetris).",--Thanks to Alexey Pajitnov!
"The name of the game (and its trademark). Also the name for clearing 4 lines at one time in official games.\nCoined from Tetra (greek for \"four\") and Tennis (favorite sport of the creator of Tetris). Also, the Tetris games developed by Nintendo and SEGA was licensed by TTC and these two companies do not have the copyright of Tetris.",--Thanks to Alexey Pajitnov!
},
{"All Clear",
"pc perfectclear ac allclear",
@@ -662,10 +662,10 @@ return{
"term",
"A way of stacking where you have a 6-block-wide stack on the left, and a 3-block-wide stack on the right.\nFor a skilled player, this method of stacking might reduce the keypresses needed for stacking, and is a popular Sprint stacking method. The reason why it works has to do with the fact that pieces spawn with a bias to the left.",
},
{"20G",
"20g",
{"Freestyle",
"freestyle ziyou",
"term",
"The fastest falling speed of modern Tetris. In 20G, pieces do not have a falling process and instantly appear on the bottom. This sometimes also limits a piece's sideways movements, as it is not always possible to make a piece climb over a bump or out of a well in 20G.",
"This term is usually used in 20TSDs. Freestyle means finishing 20 TSDs without using static stacking modes. Freestyle 20TSDs is more difficult than static tsacking modes such as LST, and the performance can represent the T-spin skills a player has in battles.",
},
{"Topping out",
"die death topout toppingout",
@@ -684,9 +684,14 @@ return{
"https://youtu.be/z4WtWISkrdU",
},
{"Falling speed",
"fallingspeed",
"fallingspeed gravity",
"term",
"Falling speed is often described in terms of G, i.e. how many lines it falls in one frame (often assuming 60 frames per second).\nG is a large unit. The speed of Lv 1 in a regular Marathon (one second per line) is 1/60 G, and 1G is about Lv 13 speed. G usually caps at 20G, for there are only 20 (visible) blocks in the matrix's height.",
"Falling speed is often described in terms of \"G\", i.e. how many lines the blocks fall in one frame (usually assuming 60 fps).\nG is a relatively large unit. The speed of Lv 1 in a regular Marathon (one second per line) is 1/60 G, and 1G is about Lv 13 speed. The highest speed of modern Tetris is 20G because the field height is 20 lines. In fact, the real meaning of 20G is \"Infinite falling speed\", and even when the field height is more than 20 lines, 20G modes force all the blocks to fall down to the bottom instantly. You can learn more about 20G at the \"20G\" entry.",
},
{"20G",
"20g gravity instant",
"term",
"The fastest falling speed of modern Tetris. In 20G modes, pieces appear instantly on the bottom of the field without the actual process of \"falling down\". This sometimes also limits a piece's sideways movements, as it is not always possible to make a piece climb over a bump or out of a well in 20G. You can learn more at the unit \"G\" at the \"falling speed\" entry. ",
},
{"Lockdown Delay",
"lockdelay lockdowndelay lockdowntimer",
@@ -829,7 +834,7 @@ return{
"The block skin used by the earliest version of Tetris.\nIn the early times, computers were all using Command Line Interface instead of Graphical User Interface, so at that time a single mino in the game of Tetris is represented using two enclosing square brackets [ ]. It looks kinds of like bones so it is sometimes called the bone blocks.\nIn Techmino, bone blocks are defined as \"A single, fancy block skin that all of the blocks use.\". Different block skins may have different types of bone block styles.",
},
{"Semi-invisible",
"half invisible",
"half invisible semi",
"term",
"Refers to a rule where the tetrominoes will become invisible after a period of time.\nThis time interval is not definite and it is acceptable to describe it as \"disappear after a few seconds\".",
},

View File

@@ -163,7 +163,7 @@ return{
{"Tetris Gems",
"宝石 tetris online official gems",
"game",
"tetris.com官网上的俄罗斯方块限时2分钟挖掘,有重力机制。\n有三种消除后可以获得不同功能的宝石方块。",
"tetris.com官网上的俄罗斯方块限时1分钟挖掘,有重力机制。\n有三种消除后可以获得不同功能的宝石方块。",
},
{"Tetris Mind Bender",
"技能 tetris online official mindbender",
@@ -248,7 +248,7 @@ return{
{"Tetris Blitz",
"闪电战 tetris blitz ea",
"game",
"简称闪电战EA代理的一款移动端方块有重力连锁机制限时2分钟游戏开始会掉下一堆小方块持续消会进入Frenzy模式场地下方会不断冒出垃圾行帮助玩家制造大连锁)。有非常多的道具\n\n已于2020年1月下架。",
"简称闪电战EA代理的一款移动端方块有重力连锁机制限时2分钟游戏开始会掉下一堆小方块持续消会进入Frenzy模式场地下方会不断冒出垃圾行帮助玩家制造大连锁如果多次落块没有消行会强制结束Frenzy。有非常多的道具。\n此外这款游戏似乎没有top-out机制。当新出现的方块与场地现有方块重叠时场地最上方的几行会被自动清除。\n\n已于2020年4月下架。",
},
{"Tetris (EA)",
"tetris ea",
@@ -258,7 +258,7 @@ return{
{"Tetris Beat",
"节奏 tetris beat n3twork",
"game",
"N3TWORK代理的一款移动端方块按钮、滑动和点击三种操控模式。除了马拉松模式外还有一个“节奏”模式,玩家根据音乐节奏落块可以得到额外分数奖励。特效比较花眼,操控手感不是很好。",
"N3TWORK代理的一款移动端方块马拉松、3分钟限时打分和Royale最多100人对战模式。UI比较好看但不支持自定义键位而且默认的按钮很小手感不好。",
},
{"Tetris (N3TWORK)",
"Tetris n3twork",
@@ -266,7 +266,7 @@ return{
"N3TWORK代理的一款移动端方块有马拉松、限时打分和Royale最多99人对战模式。UI比较好看但不支持自定义键位而且默认的按钮很小手感不好。"
},
{"Touhoumino",
"东方 车万 touhoumino chewan dongfang touhou th",
"东方 车万 偷猴 touhoumino chewan dongfang touhou th",
"game",
"玩家自制Windows平台方块东方主题其实就是一个Nullpomino的自带资源包的改版将东方Project元素结合到俄罗斯方块的游戏好玩但是难度较大适合有方块基础并且各项能力都较强的玩家游玩不然都不知道自己怎么死的",
},
@@ -578,7 +578,7 @@ return{
"term",
"交换功能Hold的另一种表现形式将手里的方块和Next槽中的第一个交换一般同样不能连续使用。",
},
{"Deepdrop",
{"深降",
"深降 deepdrop shenjiang",
"term",
"开启后当方块触底时,再次按下软降会让方块尝试向下穿墙寻找放得下的地方,如果有就会直接瞬移到那\n该功能更偏向用于技术研究对于ai来说有了它可以完全不用再考虑旋转系统形状能容得下的地方一定都能到达",
@@ -686,17 +686,12 @@ return{
{"Freestyle",
"freestyle ziyou",
"term",
"自由发挥的意思常用于freestyle TSDT2指不用固定的堆叠方式而是随机应变完成20TSD。比用LST或者垃圾分类完成的20 TSD的含金量高不少",
},
{"20G",
"高重力 20g",
"term",
"现代方块的最高下落速度,表观就是方块瞬间到底,不存在中间的下落过程,可能会让方块无法跨越壕沟/从山谷爬出。",
"自由发挥的意思常用于freestyle TSDT2指不用固定的堆叠方式而是随机应变完成20TSD。比用LST或者垃圾分类完成的20 TSD的难度要大,成绩也更能代表实战水平",
},
{"死亡判定",
"死亡判定 die death siwang",
"term",
"现代方块普遍使用的死亡判定:\n1. 新出现的方块和场地方块有重叠窒息Block Outc4w比s4w强的原因因为被打进18行都不会窒息\n2. 方块锁定时完全在场地的外面Lock Out\n3. 场地内现存方块总高度大于40。超高Top Out\n\n注:本游戏使用的死亡判定不包含上述的第二条和第三条。",
"现代方块普遍使用的死亡判定:\n1. 新出现的方块和场地方块有重叠窒息Block Outc4w比s4w强的原因因为被打进18行都不会窒息\n2. 方块锁定时完全在场地的外面Lock Out\n3. 场地内现存方块总高度大于40。超高Top Out\n\n注:本游戏使用的死亡判定默认不开启第二、三条。",
},
{"缓冲区",
"缓冲区 buffer zone huanchongqu",
@@ -712,7 +707,12 @@ return{
{"下落速度",
"下落速度 重力 drop speed zhongli gravity",
"term",
"一般用*G表示方块的下落速度意思是每一帧方块往下移动多少格一秒下落一格就是1/60G默认60fpsG是一个很大的单位20G即为上限因为场地就20格",
"一般用*G表示方块的下落速度意思是每一帧方块往下移动多少格一秒下落一格就是1/60G默认60fps可以看出G是一个很大的单位。因为场地就20格所以一般认为20G即为上限详见20G词条",
},
{"20G",
"高重力 20g",
"term",
"现代方块的最高下落速度,表观就是方块瞬间到底,不存在中间的下落过程,可能会让方块无法跨越壕沟/从山谷爬出。\n20G一般指的其实是“无限下落速度”就算场地不止20格“20G”也会让方块瞬间到底。\n本游戏和部分其他游戏推荐这么设计中20G的优先级比其他玩家操作都高即使是0arr的水平方向“瞬间移动”中途也会受到20G的影响。",
},
{"锁定延迟",
"锁定延迟 重力 lock delay suoyan zhongli gravity",

View File

@@ -303,6 +303,7 @@ return{
ospin="O-spin",
fineKill="100% Finesse",
b2bKill="No B2B break",
lockout="Fail when lock out",
easyFresh="Normal Lock Reset",
deepDrop="Deep Drop",
bone="Bone Blocks",
@@ -515,6 +516,7 @@ return{
ospin="O-Spin",
fineKill="100% Finesse",
b2bKill="No B2B break",
lockout="Fail when lock out",
easyFresh="Normal Lock Reset",
deepDrop="Deep Drop",
bone="Bone Blocks",

View File

@@ -269,6 +269,7 @@ return{
ospin="O-Spin",
fineKill="100% Finesse",
b2bKill="No Romper B2B ",
-- lockout="Fail when lock out",
easyFresh="Reinicio de Bloqueo Normal",
deepDrop="Deep Drop",
bone="Bone Block",
@@ -481,6 +482,7 @@ return{
ospin="O-Spin",
fineKill="100% Finesse",
b2bKill="No Romper B2B ",
-- lockout="Fail when lock out",
easyFresh="Reinicio de Bloqueo Normal",
deepDrop="Deep Drop",
bone="Bone Block",
@@ -609,6 +611,9 @@ return{
reset="Reiniciar",
invis="A ciegas",
},
app_arithmetic={
reset="Reiniciar",
},
savedata={
export="Exportar al portapapeles",
import="Importar de portapapeles",

View File

@@ -265,6 +265,7 @@ return{
ospin="O-spin",
fineKill="100% Finesse",
b2bKill="Sans perte de B2B",
-- lockout="Fail when lock out",
easyFresh="Réinit. de verrouillage normale",
-- deepDrop="Deep Drop",
bone="Crochets",
@@ -482,6 +483,7 @@ return{
ospin="O-spin",
fineKill="100% Finesse",
b2bKill="Sans perte de B2B",
-- lockout="Fail when lock out",
easyFresh="Réinit. de verrouillage normale",
-- deepDrop="Deep Drop",
bone="Crochets",
@@ -610,6 +612,9 @@ return{
reset="Réinitialiser",
invis="Aveugler",
},
app_arithmetic={
reset="Réinitialiser",
},
savedata={
-- export="Export to clipboard",
-- import="Import from clipboard",

View File

@@ -291,6 +291,7 @@ return{
ospin="O-Spin",
fineKill="100% Finesse",
b2bKill="Sem Quebrar B2B",
-- lockout="Fail when lock out",
easyFresh="Reset De Trava Normal",
-- deepDrop="Deep Drop",
bone="Bone Blocks",
@@ -504,6 +505,7 @@ return{
ospin="O-Spin",
fineKill="100% Finesse",
b2bKill="Sem Quebrar B2B",
-- lockout="Fail when lock out",
easyFresh="Reset De Trava Normal",
-- deepDrop="Deep Drop",
bone="Bone Blocks",
@@ -640,6 +642,9 @@ return{
reset="Resetar",
invis="Cego",
},
app_arithmetic={
reset="Resetar",
},
savedata={
-- export="Export to clipboard",
-- import="Import from clipboard",

View File

@@ -197,6 +197,7 @@ return{
ospin="O→Any",
fineKill="12 XX 21",
b2bKill="_1 XX",
lockout="X ↑_↓_↑",
easyFresh="↓_↓_↓_",
deepDrop="\\↓↓/",
bone="[]",
@@ -409,6 +410,7 @@ return{
ospin="O→Any",
fineKill="12 XX 21",
b2bKill="_1 XX",
lockout="X ↑_↓_↑",
easyFresh="↓_↓_↓_",
deepDrop="\\↓↓/",
bone="[]",

View File

@@ -303,6 +303,7 @@ return{
ospin="O-spin",
fineKill="强制极简",
b2bKill="强制B2B",
lockout="锁定在外时失败",
easyFresh="普通刷新锁延",
deepDrop="深降",
bone="骨块",
@@ -515,6 +516,7 @@ return{
ospin="O-spin",
fineKill="强制极简",
b2bKill="强制B2B",
lockout="锁定在外时失败",
easyFresh="普通刷新锁延",
deepDrop="深降",
bone="骨块",
@@ -654,6 +656,9 @@ return{
reset="重置",
invis="盲打",
},
app_arithmetic={
reset="重置",
},
savedata={
export="导出到剪切板",
import="从剪切板导入",
@@ -946,6 +951,24 @@ 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加入打击垫样式的音效室",
"使用固定堆叠方法达成20TSD难度很低",
"试试用跳舞毯打块",
"适度游戏益脑,沉迷游戏伤身,合理安排时间,享受健康生活",

View File

@@ -301,6 +301,7 @@ return{
ospin="O型自旋",
fineKill="100%精巧",
b2bKill="没有背靠背中断",
lockout="锁定时失败",
easyFresh="正常锁复位",
deepDrop="深滴",
bone="骨块",
@@ -412,7 +413,6 @@ return{
ihs="初始持有",
irs="初始旋转",
ims="初始运动",
reset="重置",
},
setting_key={
a1="向左移动",
@@ -514,6 +514,7 @@ return{
ospin="O型自旋",
fineKill="100%精巧",
b2bKill="没有背靠背中断",
lockout="锁定时失败",
easyFresh="正常锁复位",
deepDrop="深滴",
bone="骨块",
@@ -612,7 +613,6 @@ return{
revKB="逆转",
},
app_schulteG={
reset="重置",
rank="大小",
invis="英维斯",
disappear="隐藏",
@@ -624,30 +624,25 @@ return{
app_AtoZ={
level="水平仪",
keyboard="键盘",
reset="重置",
},
app_2048={
reset="重置",
invis="英维斯",
tapControl="抽头控制",
skip="跳转",
},
app_ten={
reset="重置",
next="下一个",
invis="英维斯",
fast="快速的",
},
app_dtw={
reset="重置",
color="颜色",
mode="模式",
bgm="血糖监测",
arcade="游乐中心",
},
app_link={
reset="重置",
invis="英维斯",
},
savedata={

View File

@@ -302,6 +302,7 @@ return{
ospin="O-spin",
fineKill="100% finesse",
b2bKill="強制B2B",
lockout="鎖定在外時失敗",
easyFresh="普通刷新鎖延",
deepDrop="深降",
bone="骨塊",
@@ -514,6 +515,7 @@ return{
ospin="O-spin",
fineKill="強制finesse",
b2bKill="強制B2B",
lockout="鎖定在外時失敗",
easyFresh="普通刷新鎖延",
deepDrop="深降",
bone="骨塊",
@@ -653,6 +655,9 @@ return{
reset="重設",
invis="盲打",
},
app_arithmetic={
reset="重設",
},
savedata={
export="導出到剪貼板",
import="從剪貼板導入",

View File

@@ -7,7 +7,7 @@ Gameplay:
Play until the end or achieve the level's goal to win.
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:
Satisfies "3 corner" rule +2 points
@@ -87,4 +87,4 @@ Custom mode:
empty cells can be in any state;
regular colored cells have to be made of the corresponding block;
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判定:
满足三角判定+2分

View File

@@ -18,7 +18,7 @@ return{
{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_h', x=0, y=-800, size=50,shape=1,icon="marathon", unlock={'master_n'}},
{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_n', x=-800, y=-1000, size=40,shape=1,icon="solo", unlock={'solo_h'}},
@@ -39,16 +39,16 @@ return{
{name='round_l', x=-1200, y=-800, size=40,shape=1,icon="round", unlock={'round_u'}},
{name='round_u', x=-1400, y=-800, size=40,shape=1,icon="round"},
{name='master_n', x=0, y=-1000, size=40,shape=1,icon="master", unlock={'master_h','strategy_e'}},
{name='master_h', x=0, y=-1200, size=40,shape=3,icon="master", unlock={'master_final','master_ex','master_ph','master_m'}},
{name='master_n', x=0, y=-1000, size=40,shape=1,icon="master", unlock={'master_h','strategy_h'}},
{name='master_h', x=0, y=-1200, size=40,shape=3,icon="master", unlock={'master_final','master_ex','master_ph','master_m','strategy_u'}},
{name='master_m', x=150, y=-1320, size=30,shape=3,icon="master"},
{name='master_final', x=0, y=-1600, size=40,shape=2,icon="master"},
{name='master_ph', x=-150, y=-1500, size=40,shape=2,icon="master"},
{name='master_ex', x=150, y=-1500, size=40,shape=2,icon="master_ex"},
{name='strategy_e', x=-150, y=-1100, size=40,shape=3,icon="master", unlock={'strategy_h'}},
{name='strategy_h', x=-250, y=-1200, size=35,shape=3,icon="master", unlock={'strategy_u'}},
{name='strategy_u', x=-350, y=-1300, size=30,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_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_n', x=150, y=-800, size=40,shape=1,icon="hidden", unlock={'blind_h'}},
@@ -57,9 +57,9 @@ return{
{name='blind_u', x=150, y=-1100, size=30,shape=3,icon="hidden", unlock={'blind_wtf'}},
{name='blind_wtf', x=150, y=-1200, size=25,shape=2,icon="hidden"},
{name='classic_e', x=-150, y=-850, size=40,shape=1,icon="classic", unlock={'classic_h'}},
{name='classic_h', x=-300, y=-950, size=35,shape=2,icon="classic", unlock={'classic_u'}},
{name='classic_u', x=-450, y=-1050, size=30,shape=2,icon="classic"},
{name='classic_e', x=-200, y=-850, size=40,shape=1,icon="classic", unlock={'classic_h'}},
{name='classic_h', x=-300, y=-950, size=35,shape=2,icon="classic", unlock={'classic_u'}},
{name='classic_u', x=-400, y=-1050, size=30,shape=2,icon="classic"},
{name='survivor_e', x=300, y=-600, size=40,shape=1,icon="survivor", unlock={'survivor_n'}},
{name='survivor_n', x=500, y=-600, size=40,shape=1,icon="survivor", unlock={'survivor_h','attacker_h','defender_n','dig_h'}},

View File

@@ -1,5 +1,6 @@
return{
{font=100,name="☆★白羽★☆"},
{font=100,name="[*浩]"},
{font=65,name="那没事了(T6300)"},
{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=25,name="八零哥"},
{font=25,name="蕴空之灵"},
@@ -121,4 +124,6 @@ return{
{font=25,name="小丘"},
{font=25,name="Techtris"},
{font=25,name="费尔特林"},
{font=25,name="零醇丘卡"},
{font=25,name="Hathtiz"},
}

View File

@@ -3,7 +3,7 @@ return{
dascut=0,dropcut=0,
sddas=2,sdarr=2,
ihs=true,irs=true,ims=true,
hang=0,FTLock=true,
hang=5,FTLock=true,
ghostType='gray',
block=true,ghost=.3,center=1,
@@ -31,6 +31,7 @@ return{
drop=60,lock=60,
wait=0,fall=0,
bone=false,
lockout=false,
fieldH=20,heightLimit=1e99,
nextCount=6,nextStartPos=1,
holdMode='hold',holdCount=1,

View File

@@ -203,7 +203,7 @@ end
--------------------------<Method>--------------------------
function Player:newTask(code,...)
local thread=coroutine.create(code)
resume(thread,self,...)
assert(resume(thread,self,...))
if status(thread)~='dead'then
ins(self.tasks,{
thread=thread,
@@ -387,16 +387,8 @@ function Player:garbageRise(color,amount,line)--Release n-lines garbage to field
#self.field>self.gameEnv.heightLimit
)
then
self:lock()
self:lose()
end
if #self.field>self.gameEnv.heightLimit then
self:_triggerEvent('hook_die')
if #self.field>self.gameEnv.heightLimit then
self:lose()
end
end
end
local invList={2,1,4,3,5,6,7}
@@ -1645,7 +1637,7 @@ do
end
end
--Prevent sudden death if hang>0
--Prevent sudden death if hang>0
if ENV.hang>ENV.wait and self.nextQueue[1]then
local B=self.nextQueue[1]
if self:ifoverlap(B.bk,int(6-#B.bk[1]*.5),int(ENV.fieldH+1-modf(B.RS.centerPos[B.id][B.dir][1]))+ceil(self.fieldBeneath/30))then
@@ -1661,7 +1653,7 @@ do
end
--Check height limit
if cc==0 and #self.field>ENV.heightLimit then
if cc==0 and(#self.field>ENV.heightLimit or ENV.lockout and CY>ENV.fieldH)then
finish='lose'
end

View File

@@ -3,6 +3,8 @@ local rnd=math.random
local int,ceil=math.floor,math.ceil
local char=string.char
local timing,time
local function b2(i)
if i==0 then return 0 end
local s=""
@@ -114,17 +116,27 @@ local levels={
local a=rnd(17,int(s/2))
return{COLOR.J,b16(a),COLOR.Z,"+",COLOR.J,b16(s-a)},s
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})
local level
local input,inputTime=0,0
local question,answer
local function newQuestion(lv)
return levels[lv]()
end
local function reset()
timing=true
time=0
input=""
inputTime=0
level=1
question,answer=newQuestion(1)
end
local function check(val)
if val==answer then
level=level+1
@@ -142,10 +154,7 @@ end
local scene={}
function scene.sceneInit()
input=""
inputTime=0
level=1
question,answer=newQuestion(1)
reset()
BGM.play('truth')
end
@@ -173,14 +182,15 @@ function scene.keyDown(key,isRep)
elseif key=="backspace"then
input=""
inputTime=0
elseif key=="s"then
check(answer)
elseif key=="r"then
reset()
elseif key=="escape"then
SCN.back()
end
end
function scene.update(dt)
if timing then time=time+dt end
if inputTime>0 then
inputTime=inputTime-dt
if inputTime<=0 then
@@ -189,8 +199,11 @@ function scene.update(dt)
end
end
function scene.draw()
FONT.set(35)
gc.setColor(COLOR.Z)
FONT.set(45)
gc.print(("%.3f"):format(time),1026,70)
FONT.set(35)
GC.mStr("["..level.."]",640,30)
FONT.set(100)
@@ -203,6 +216,7 @@ function scene.draw()
end
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='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"-"},

View File

@@ -181,7 +181,7 @@ function scene.draw()
gc.translate(0,WIDGET.scrollPos)
end
scene.widgetScrollHeight=400
scene.widgetScrollHeight=450
scene.widgetList={
WIDGET.newText{name='title', x=520,y=15,font=70,align='R'},
@@ -225,12 +225,13 @@ scene.widgetList={
WIDGET.newSelector{name='eventSet', x=1050,y=740,w=340,color='H',list=sList.eventSet,disp=CUSval('eventSet'),code=CUSsto('eventSet')},
--Special rules
WIDGET.newSwitch{name='ospin', x=850, y=810,lim=210,disp=CUSval('ospin'), code=CUSrev('ospin')},
WIDGET.newSwitch{name='fineKill', x=850, y=870,lim=210,disp=CUSval('fineKill'), code=CUSrev('fineKill')},
WIDGET.newSwitch{name='b2bKill', x=850, y=930,lim=210,disp=CUSval('b2bKill'), code=CUSrev('b2bKill')},
WIDGET.newSwitch{name='easyFresh', x=1170,y=810,lim=250,disp=CUSval('easyFresh'),code=CUSrev('easyFresh')},
WIDGET.newSwitch{name='deepDrop', x=1170,y=870,lim=250,disp=CUSval('deepDrop'), code=CUSrev('deepDrop')},
WIDGET.newSwitch{name='bone', x=1170,y=930,lim=250,disp=CUSval('bone'), code=CUSrev('bone')},
WIDGET.newSwitch{name='ospin', x=850, y=820 ,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='b2bKill', x=850, y=940 ,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='easyFresh', x=1170,y=820 ,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='bone', x=1170,y=940 ,lim=250,disp=CUSval('bone'), code=CUSrev('bone')},
--Next & Hold
WIDGET.newSelector{name='holdMode', x=310, y=890, w=300,color='lY',list=sList.holdMode,disp=CUSval('holdMode'),code=CUSsto('holdMode')},
@@ -240,8 +241,8 @@ scene.widgetList={
WIDGET.newSwitch{name='phyHold', x=560, y=1030,lim=200, disp=CUSval('phyHold'),code=CUSrev('phyHold'),hideF=function()return CUSTOMENV.holdCount==0 end},
--BG & BGM
WIDGET.newSelector{name='bg', x=840, y=1030,w=250,color='Y',list=BG.getList(),disp=CUSval('bg'),code=function(i)CUSTOMENV.bg=i BG.set(i)end},
WIDGET.newSelector{name='bgm', x=1120,y=1030,w=250,color='Y',list=BGM.getList(),disp=CUSval('bgm'),code=function(i)CUSTOMENV.bgm=i BGM.play(i)end},
WIDGET.newSelector{name='bg', x=840, y=1090,w=250,color='Y',list=BG.getList(),disp=CUSval('bg'),code=function(i)CUSTOMENV.bg=i BG.set(i)end},
WIDGET.newSelector{name='bgm', x=1120,y=1090,w=250,color='Y',list=BGM.getList(),disp=CUSval('bgm'),code=function(i)CUSTOMENV.bgm=i BGM.play(i)end},
}
return scene

View File

@@ -115,8 +115,9 @@ function scene.keyDown(key)
for _=1,12 do scene.keyDown("up")end
elseif key=="right"or key=="pagedown"then
for _=1,12 do scene.keyDown("down")end
elseif key=="link"then
love.system.openURL(_getList()[selected].url)
elseif key=="application"then
local url=_getList()[selected].url
if url then love.system.openURL(url)end
elseif key=="delete"then
if inputBox:hasText()then
_clearResult()
@@ -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='title', x=100,y=15,font=70,align='L'},
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='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},

View File

@@ -9,9 +9,9 @@ local scene={}
function scene.sceneInit()
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."
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_user()
NET.wsclose_play()

View File

@@ -162,7 +162,7 @@ function scene.update()
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("right","d")then dx=dx-10 F=true end
local js1=joysticks[1]
local js1=Z.js[1]
if js1 then
local dir=js1:getAxis(1)
if dir~="c"then

View File

@@ -94,12 +94,13 @@ scene.widgetList={
WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,font=60,fText=CHAR.icon.back,code=backScene},
--Special rules
WIDGET.newSwitch{name='ospin', x=850, y=750,lim=210,disp=ROOMval('ospin'), code=ROOMrev('ospin')},
WIDGET.newSwitch{name='fineKill', x=850, y=840,lim=210,disp=ROOMval('fineKill'), code=ROOMrev('fineKill')},
WIDGET.newSwitch{name='b2bKill', x=850, y=930,lim=210,disp=ROOMval('b2bKill'), code=ROOMrev('b2bKill')},
WIDGET.newSwitch{name='easyFresh', x=1170,y=750,lim=250,disp=ROOMval('easyFresh'),code=ROOMrev('easyFresh')},
WIDGET.newSwitch{name='deepDrop', x=1170,y=840,lim=250,disp=ROOMval('deepDrop'), code=ROOMrev('deepDrop')},
WIDGET.newSwitch{name='bone', x=1170,y=930,lim=250,disp=ROOMval('bone'), code=ROOMrev('bone')},
WIDGET.newSwitch{name='ospin', x=850, y=760 ,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='b2bKill', x=850, y=940 ,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='easyFresh', x=1170,y=760 ,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='bone', x=1170,y=940 ,lim=250,disp=ROOMval('bone'), code=ROOMrev('bone')},
--Rule set
WIDGET.newSelector{name='eventSet', x=310,y=880,w=360,color='H',list=sList.eventSet,disp=ROOMval('eventSet'),code=ROOMsto('eventSet')},

View File

@@ -14,12 +14,19 @@ return[=[
0.17.0: 硬着陆 Hard Landing
新增:
新模式:大爆炸
新模式:策略堆叠(原设计来自Cambridge游戏, by NOT_A_ROBOT)
新模式:策略堆叠(原设计来自游戏Cambridge, by NOT_A_ROBOT)
添加lockout判负规则(默认关闭)
全局默认使用5帧窒息延迟
尝试支持摇杆和扳机
改动:
TRS的S/Z添加四个踢墙防止在一些地方卡死
生成位置预览开启后hold的生成位置也可见 #453
优化pc训练模式体验,添加胜利条件,不再无尽
堆积模式添加15帧的窒息延迟 #465
小程序arm加入计时器和重置按钮
代码:
bgm模块可限制最大加载数不容易达到上限导致没声 #447
语音模块支持设置轻微随机音调偏移半径(游戏内固定使用1)
修复:
机翻语言超级消除无行数显示 #462
竞速-效率左侧信息颜色问题

View File

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