Compare commits
241 Commits
pre0.17.0-
...
test-new-m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
707bcca368 | ||
|
|
f8f115de10 | ||
|
|
b07c4dc53a | ||
|
|
6eeddba773 | ||
|
|
0cfe4df468 | ||
|
|
eb5c3c3be5 | ||
|
|
a5b9206694 | ||
|
|
375e67bdc4 | ||
|
|
724a576aa3 | ||
|
|
ed47dcb90c | ||
|
|
64b08a5a4d | ||
|
|
baed0153a2 | ||
|
|
46d95b33e4 | ||
|
|
200d270fee | ||
|
|
a8628275a0 | ||
|
|
20a1d2bcc1 | ||
|
|
b887a1f096 | ||
|
|
9bf0e9f28d | ||
|
|
dfc724767b | ||
|
|
f0e66e9dc5 | ||
|
|
0932335f0b | ||
|
|
a9b39e396a | ||
|
|
2e0ceaae72 | ||
|
|
04f38d2eb6 | ||
|
|
fc1ed4dff6 | ||
|
|
f8935d3dd7 | ||
|
|
a86228677f | ||
|
|
79df9f7876 | ||
|
|
12ea2d76be | ||
|
|
485bd72241 | ||
|
|
7240275075 | ||
|
|
29ef9b8d15 | ||
|
|
97f4795d4e | ||
|
|
226e45b24d | ||
|
|
d6ab7e72b2 | ||
|
|
168f44b8b3 | ||
|
|
b73f646a4c | ||
|
|
36cefcc000 | ||
|
|
f901c25c87 | ||
|
|
6d8478b029 | ||
|
|
9bcb040019 | ||
|
|
d977087fc0 | ||
|
|
1a330771d7 | ||
|
|
9c8c9f2106 | ||
|
|
0498beecdf | ||
|
|
8e075adf8f | ||
|
|
60f2a0e647 | ||
|
|
b642f2b5c4 | ||
|
|
2b80f72c6b | ||
|
|
462720881a | ||
|
|
3dda0254a8 | ||
|
|
054a52a445 | ||
|
|
85242d808b | ||
|
|
57241677a9 | ||
|
|
6ccdee2a53 | ||
|
|
a3d2b7b7f3 | ||
|
|
b7b28b4ae3 | ||
|
|
30748200dd | ||
|
|
c9f8240234 | ||
|
|
5c7082e886 | ||
|
|
9a3c889a9d | ||
|
|
f41f58e13f | ||
|
|
e81f25c216 | ||
|
|
36fc681fbf | ||
|
|
87e5e29129 | ||
|
|
b432fdf90a | ||
|
|
6e78a3fedd | ||
|
|
24760801af | ||
|
|
f5e8e0f7a5 | ||
|
|
df089a2f04 | ||
|
|
6600713f4b | ||
|
|
96dad762b2 | ||
|
|
5470387685 | ||
|
|
fa64c868b9 | ||
|
|
2f4a416353 | ||
|
|
3dbafb042c | ||
|
|
97e7b019dd | ||
|
|
28103ad952 | ||
|
|
1826ca6f2f | ||
|
|
db490a6c6c | ||
|
|
421fdef4f9 | ||
|
|
d717ce842d | ||
|
|
f13c9792af | ||
|
|
41e7b8e0f4 | ||
|
|
4bd723a7ee | ||
|
|
66d5bd5490 | ||
|
|
351d0258b2 | ||
|
|
26fb9a7052 | ||
|
|
307fd637fa | ||
|
|
93fb716f89 | ||
|
|
7b41551e2d | ||
|
|
4806af5f7d | ||
|
|
85cb55cdd0 | ||
|
|
27a9697e47 | ||
|
|
7d230cc3b0 | ||
|
|
0db2fffad1 | ||
|
|
2a3296a0e8 | ||
|
|
941b875afa | ||
|
|
99155bb9cf | ||
|
|
0701dd2ad3 | ||
|
|
5570c19e1f | ||
|
|
a728c91476 | ||
|
|
6a43481067 | ||
|
|
29a049fe4e | ||
|
|
b5a9c8e1bb | ||
|
|
bb9a35c161 | ||
|
|
b25a345b42 | ||
|
|
b22b0e0194 | ||
|
|
55cf95f218 | ||
|
|
225ddbcfac | ||
|
|
9377090c7c | ||
|
|
ed002ec2e1 | ||
|
|
e33036d9ec | ||
|
|
ef03e7c009 | ||
|
|
aef4220ac0 | ||
|
|
46223e38cd | ||
|
|
4bafa4bffe | ||
|
|
2b3dd877dd | ||
|
|
0553e5c45e | ||
|
|
4d93374cf6 | ||
|
|
4e421bf9ba | ||
|
|
8b2a9d7c01 | ||
|
|
5a3244d345 | ||
|
|
f1b9d0c5e4 | ||
|
|
6493e0e623 | ||
|
|
e71ba17f9f | ||
|
|
e656363e20 | ||
|
|
0826a748ae | ||
|
|
a595fe99ef | ||
|
|
9dbc7942e3 | ||
|
|
845d8ae32e | ||
|
|
5c524e138c | ||
|
|
86d9265ff9 | ||
|
|
6994a5d6d3 | ||
|
|
e6213b00c1 | ||
|
|
43e2caa30e | ||
|
|
97ca245dfc | ||
|
|
36de1c0751 | ||
|
|
704341fd15 | ||
|
|
22b61bc9c3 | ||
|
|
f4cbbc0a2a | ||
|
|
dc99187b9d | ||
|
|
915598dec4 | ||
|
|
e7b4518d73 | ||
|
|
9603a78e87 | ||
|
|
bd90e051d4 | ||
|
|
26e66b313f | ||
|
|
c534bbd12a | ||
|
|
83b5e217e5 | ||
|
|
c0adf5bf0b | ||
|
|
4ff737a4ac | ||
|
|
5af0706c09 | ||
|
|
4ccee0f1de | ||
|
|
9b752d540e | ||
|
|
e860c7b7ec | ||
|
|
8a1fd9531f | ||
|
|
5fd6e0ee99 | ||
|
|
53b2b81fe0 | ||
|
|
6ccc811b46 | ||
|
|
962a61567a | ||
|
|
58f05e1cec | ||
|
|
6b426790c7 | ||
|
|
d4fc578673 | ||
|
|
51b567b8db | ||
|
|
07b47dee3f | ||
|
|
4431a906b9 | ||
|
|
2bb6852e3e | ||
|
|
1948ed3e16 | ||
|
|
81b5ccae30 | ||
|
|
5543ff0d29 | ||
|
|
cd567e9e98 | ||
|
|
5d86925a8a | ||
|
|
e3db564a4b | ||
|
|
a4293624ab | ||
|
|
367e2dc81a | ||
|
|
9ec33c6eef | ||
|
|
9c9b8d36f2 | ||
|
|
4fc6f335c7 | ||
|
|
d2f4123d08 | ||
|
|
b29d352a1b | ||
|
|
cd5a71cd12 | ||
|
|
cdd68e985d | ||
|
|
8cf4d4280c | ||
|
|
cd29bf8702 | ||
|
|
13d98be051 | ||
|
|
a350ff3182 | ||
|
|
e0360cc7eb | ||
|
|
4249a29b63 | ||
|
|
43b2a0a8c8 | ||
|
|
6d6584f99e | ||
|
|
077c651226 | ||
|
|
3fc872aa76 | ||
|
|
cb0b347a38 | ||
|
|
d08967c688 | ||
|
|
3666c0caa9 | ||
|
|
4ef179fccb | ||
|
|
861f9b3caa | ||
|
|
05292df456 | ||
|
|
9fed692223 | ||
|
|
b1c04c1fea | ||
|
|
bc9adc2cd3 | ||
|
|
cdf149afca | ||
|
|
73145b4e5e | ||
|
|
f8b9f30fd6 | ||
|
|
e6bc567b12 | ||
|
|
fe004a72f0 | ||
|
|
0433fd3d9d | ||
|
|
1c18060570 | ||
|
|
be54c0e641 | ||
|
|
0be2eb9107 | ||
|
|
4859faf1e7 | ||
|
|
c25d40c67d | ||
|
|
b6c37a5c9f | ||
|
|
f6b4c1b109 | ||
|
|
841faeede4 | ||
|
|
e61b9b23a0 | ||
|
|
72a826ef0a | ||
|
|
f070b8f295 | ||
|
|
1646b75520 | ||
|
|
241617e31a | ||
|
|
5de2893e07 | ||
|
|
030e894040 | ||
|
|
e7b9a4ba87 | ||
|
|
617bae67c6 | ||
|
|
64d2d08820 | ||
|
|
037b33c99a | ||
|
|
afa69ce9a4 | ||
|
|
3226c0c831 | ||
|
|
4e759cad4c | ||
|
|
291795928d | ||
|
|
a1315e7f7f | ||
|
|
657bc2b4e0 | ||
|
|
d8b12fc55d | ||
|
|
6d11367ea4 | ||
|
|
eb9e741b4f | ||
|
|
c47546d501 | ||
|
|
11aa178fc1 | ||
|
|
f3a88ef269 | ||
|
|
720dc2131f | ||
|
|
701ef17ae1 | ||
|
|
1a689a5f07 |
BIN
.github/build/macOS/backgroundImage.tiff
vendored
@@ -4,8 +4,9 @@ local BGs={
|
|||||||
}
|
}
|
||||||
local BGlist={'none'}
|
local BGlist={'none'}
|
||||||
local BG={
|
local BG={
|
||||||
cur='none',
|
|
||||||
default='none',
|
default='none',
|
||||||
|
locked=false,
|
||||||
|
cur='none',
|
||||||
init=false,
|
init=false,
|
||||||
resize=false,
|
resize=false,
|
||||||
update=NULL,
|
update=NULL,
|
||||||
@@ -14,6 +15,8 @@ local BG={
|
|||||||
discard=NULL,
|
discard=NULL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function BG.lock()BG.locked=true end
|
||||||
|
function BG.unlock()BG.locked=false end
|
||||||
function BG.add(name,bg)
|
function BG.add(name,bg)
|
||||||
BGs[name]=bg
|
BGs[name]=bg
|
||||||
BGlist[#BGlist+1]=name
|
BGlist[#BGlist+1]=name
|
||||||
@@ -21,6 +24,9 @@ end
|
|||||||
function BG.getList()
|
function BG.getList()
|
||||||
return BGlist
|
return BGlist
|
||||||
end
|
end
|
||||||
|
function BG.remList(name)
|
||||||
|
table.remove(BGlist,TABLE.find(BGlist,name))
|
||||||
|
end
|
||||||
function BG.send(...)
|
function BG.send(...)
|
||||||
if BG.event then
|
if BG.event then
|
||||||
BG.event(...)
|
BG.event(...)
|
||||||
@@ -29,20 +35,20 @@ end
|
|||||||
function BG.setDefault(bg)
|
function BG.setDefault(bg)
|
||||||
BG.default=bg
|
BG.default=bg
|
||||||
end
|
end
|
||||||
function BG.set(background)
|
function BG.set(name)
|
||||||
background=background or BG.default
|
name=name or BG.default
|
||||||
if not BGs[background]or not SETTING.bg then return end
|
if not BGs[name]or BG.locked then return end
|
||||||
if background~=BG.cur then
|
if name~=BG.cur then
|
||||||
BG.discard()
|
BG.discard()
|
||||||
BG.cur=background
|
BG.cur=name
|
||||||
background=BGs[background]
|
local bg=BGs[name]
|
||||||
|
|
||||||
BG.init= background.init or NULL
|
BG.init= bg.init or NULL
|
||||||
BG.resize= background.resize or NULL
|
BG.resize= bg.resize or NULL
|
||||||
BG.update= background.update or NULL
|
BG.update= bg.update or NULL
|
||||||
BG.draw= background.draw or NULL
|
BG.draw= bg.draw or NULL
|
||||||
BG.event= background.event or NULL
|
BG.event= bg.event or NULL
|
||||||
BG.discard=background.discard or NULL
|
BG.discard=bg.discard or NULL
|
||||||
BG.init()
|
BG.init()
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -1,44 +1,37 @@
|
|||||||
local lastLoaded={}
|
local lastLoaded={}
|
||||||
local maxLoadedCount=3
|
local maxLoadedCount=3
|
||||||
|
local nameList={}
|
||||||
local SourceObjList={}
|
local SourceObjList={}
|
||||||
local volume=1
|
local volume=1
|
||||||
|
|
||||||
local BGM={
|
local BGM={
|
||||||
default=false,
|
default=false,
|
||||||
getList=function()error("Cannot getList before initialize!")end,
|
|
||||||
getCount=function()return 0 end,
|
|
||||||
play=NULL,
|
|
||||||
stop=NULL,
|
|
||||||
onChange=NULL,
|
onChange=NULL,
|
||||||
--nowPlay=[str:playing ID]
|
--nowPlay=[str:playing ID]
|
||||||
--playing=[src:playing SRC]
|
--playing=[src:playing SRC]
|
||||||
--lastPlayed=[str:lastPlayed ID]
|
--lastPlayed=[str:lastPlayed ID]
|
||||||
}
|
}
|
||||||
local function task_fadeOut(src)
|
|
||||||
while true do
|
function BGM.getList()return nameList end
|
||||||
coroutine.yield()
|
function BGM.getCount()return #nameList end
|
||||||
local v=src:getVolume()-.025*volume
|
local function _addFile(name,path)
|
||||||
src:setVolume(v>0 and v or 0)
|
if not SourceObjList[name]then
|
||||||
if v<=0 then
|
table.insert(nameList,name)
|
||||||
src:pause()
|
SourceObjList[name]={path=path,source=false}
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function task_fadeIn(src)
|
function BGM.load(name,path)
|
||||||
while true do
|
if type(name)=='table'then
|
||||||
coroutine.yield()
|
for k,v in next,name do
|
||||||
local v=volume
|
_addFile(k,v)
|
||||||
v=math.min(v,src:getVolume()+.025*v)
|
|
||||||
src:setVolume(v)
|
|
||||||
if v>=volume then
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
_addFile(name,path)
|
||||||
end
|
end
|
||||||
|
table.sort(nameList)
|
||||||
|
LOG(BGM.getCount().." BGM files added")
|
||||||
end
|
end
|
||||||
local function check_curFadeOut(task,code,src)
|
|
||||||
return task.code==code and task.args[1]==src
|
|
||||||
end
|
|
||||||
local function _tryReleaseSources()
|
local function _tryReleaseSources()
|
||||||
local n=#lastLoaded
|
local n=#lastLoaded
|
||||||
while #lastLoaded>maxLoadedCount do
|
while #lastLoaded>maxLoadedCount do
|
||||||
@@ -75,85 +68,115 @@ function BGM.setVol(v)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function BGM.init(list)
|
|
||||||
BGM.init=nil
|
|
||||||
|
|
||||||
local simpList={}
|
local function task_fadeOut(src)
|
||||||
for _,v in next,list do
|
while true do
|
||||||
table.insert(simpList,v.name)
|
coroutine.yield()
|
||||||
SourceObjList[v.name]={path=v.path,source=false}
|
local v=src:getVolume()-.025*volume
|
||||||
end
|
src:setVolume(v>0 and v or 0)
|
||||||
table.sort(simpList)
|
if v<=0 then
|
||||||
function BGM.getList()return simpList end
|
src:pause()
|
||||||
local count=#simpList
|
return true
|
||||||
LOG(count.." BGM files added")
|
|
||||||
function BGM.getCount()return count end
|
|
||||||
|
|
||||||
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: "..SourceObjList[name],5)
|
|
||||||
end
|
|
||||||
elseif name then
|
|
||||||
LOG("No BGM: "..name,5)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function BGM.play(name)
|
end
|
||||||
name=name or BGM.default
|
local function task_fadeIn(src)
|
||||||
if not _tryLoad(name)then return end
|
while true do
|
||||||
if volume==0 then
|
coroutine.yield()
|
||||||
|
local v=volume
|
||||||
|
v=math.min(v,src:getVolume()+.025*v)
|
||||||
|
src:setVolume(v)
|
||||||
|
if v>=volume then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function check_curFadeOut(task,code,src)
|
||||||
|
return task.code==code and task.args[1]==src
|
||||||
|
end
|
||||||
|
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:setVolume(0)
|
||||||
|
table.insert(lastLoaded,1,name)
|
||||||
|
_tryReleaseSources()
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
LOG("No BGM: "..SourceObjList[name],5)
|
||||||
|
end
|
||||||
|
elseif name then
|
||||||
|
LOG("No BGM: "..name,5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function BGM.play(name,args)
|
||||||
|
name=name or BGM.default
|
||||||
|
args=args or""
|
||||||
|
if not _tryLoad(name)or args:sArg('-preLoad')then return end
|
||||||
|
if volume==0 then
|
||||||
|
BGM.nowPlay=name
|
||||||
|
BGM.playing=SourceObjList[name].source
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if name and SourceObjList[name].source then
|
||||||
|
if BGM.nowPlay~=name then
|
||||||
|
if BGM.nowPlay then
|
||||||
|
if not args:sArg('-sdout')then
|
||||||
|
TASK.new(task_fadeOut,BGM.playing)
|
||||||
|
else
|
||||||
|
BGM.playing:pause()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,SourceObjList[name].source)
|
||||||
|
TASK.removeTask_code(task_fadeIn)
|
||||||
|
|
||||||
BGM.nowPlay=name
|
BGM.nowPlay=name
|
||||||
BGM.playing=SourceObjList[name].source
|
BGM.playing=SourceObjList[name].source
|
||||||
return true
|
if not args:sArg('-sdin')then
|
||||||
end
|
BGM.playing:setVolume(0)
|
||||||
if name and SourceObjList[name].source then
|
TASK.new(task_fadeIn,BGM.playing)
|
||||||
if BGM.nowPlay~=name then
|
else
|
||||||
if BGM.nowPlay then
|
BGM.playing:setVolume(volume)
|
||||||
TASK.new(task_fadeOut,BGM.playing)
|
|
||||||
end
|
|
||||||
TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,SourceObjList[name].source)
|
|
||||||
TASK.removeTask_code(task_fadeIn)
|
|
||||||
|
|
||||||
TASK.new(task_fadeIn,SourceObjList[name].source)
|
|
||||||
BGM.nowPlay=name
|
|
||||||
BGM.playing=SourceObjList[name].source
|
|
||||||
BGM.lastPlayed=BGM.nowPlay
|
|
||||||
BGM.playing:seek(0)
|
|
||||||
BGM.playing:play()
|
BGM.playing:play()
|
||||||
BGM.onChange(name)
|
|
||||||
end
|
end
|
||||||
return true
|
SourceObjList[name].source:setLooping(not args:sArg('-noloop'))
|
||||||
end
|
BGM.lastPlayed=BGM.nowPlay
|
||||||
end
|
BGM.playing:seek(0)
|
||||||
function BGM.seek(t)
|
|
||||||
if BGM.playing then
|
|
||||||
BGM.playing:seek(t)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function BGM.continue()
|
|
||||||
if BGM.lastPlayed then
|
|
||||||
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()
|
BGM.playing:play()
|
||||||
|
BGM.onChange(name)
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
function BGM.stop()
|
end
|
||||||
|
function BGM.seek(t)
|
||||||
|
if BGM.playing then
|
||||||
|
BGM.playing:seek(t)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function BGM.isPlaying()
|
||||||
|
return BGM.playing and BGM.playing:isPlaying()
|
||||||
|
end
|
||||||
|
function BGM.continue()
|
||||||
|
if BGM.lastPlayed then
|
||||||
|
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.removeTask_code(task_fadeIn)
|
||||||
|
TASK.new(task_fadeIn,BGM.playing)
|
||||||
|
BGM.playing:play()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function BGM.stop(args)
|
||||||
|
args=args or""
|
||||||
|
TASK.removeTask_code(task_fadeIn)
|
||||||
|
if not args:sArg('-s')then
|
||||||
if BGM.nowPlay then
|
if BGM.nowPlay then
|
||||||
TASK.new(task_fadeOut,BGM.playing)
|
TASK.new(task_fadeOut,BGM.playing)
|
||||||
end
|
end
|
||||||
BGM.nowPlay,BGM.playing=nil
|
elseif BGM.playing then
|
||||||
|
BGM.playing:pause()
|
||||||
end
|
end
|
||||||
|
BGM.nowPlay,BGM.playing=nil
|
||||||
end
|
end
|
||||||
return BGM
|
return BGM
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
local abs=math.abs
|
local abs=math.abs
|
||||||
local function hsv(h,s,v,a)
|
local function hsv(h,s,v,a)--Color type, Color amount, Light
|
||||||
if s<=0 then return v,v,v,a end
|
if s<=0 then return v,v,v,a end
|
||||||
h=h*6
|
h=h*6
|
||||||
local c=v*s
|
local c=v*s
|
||||||
@@ -19,33 +19,33 @@ local COLOR={
|
|||||||
red= {hsv(0.00, 0.89, 0.91)},
|
red= {hsv(0.00, 0.89, 0.91)},
|
||||||
fire= {hsv(0.04, 0.93, 0.94)},
|
fire= {hsv(0.04, 0.93, 0.94)},
|
||||||
orange= {hsv(0.09, 0.99, 0.96)},
|
orange= {hsv(0.09, 0.99, 0.96)},
|
||||||
yellow= {hsv(0.16, 0.82, 0.90)},
|
yellow= {hsv(0.15, 0.82, 0.90)},
|
||||||
lime= {hsv(0.18, 0.89, 0.88)},
|
lime= {hsv(0.20, 0.89, 0.88)},
|
||||||
jade= {hsv(0.23, 1.00, 0.82)},
|
jade= {hsv(0.25, 1.00, 0.82)},
|
||||||
green= {hsv(0.33, 1.00, 0.81)},
|
green= {hsv(0.33, 1.00, 0.81)},
|
||||||
aqua= {hsv(0.48, 1.00, 0.74)},
|
aqua= {hsv(0.47, 1.00, 0.76)},
|
||||||
cyan= {hsv(0.53, 1.00, 0.88)},
|
cyan= {hsv(0.53, 1.00, 0.88)},
|
||||||
navy= {hsv(0.56, 1.00, 1.00)},
|
navy= {hsv(0.56, 1.00, 1.00)},
|
||||||
sea= {hsv(0.61, 1.00, 1.00)},
|
sea= {hsv(0.61, 1.00, 1.00)},
|
||||||
blue= {hsv(0.64, 1.00, 0.95)},
|
blue= {hsv(0.64, 1.00, 0.95)},
|
||||||
violet= {hsv(0.73, 1.00, 0.91)},
|
violet= {hsv(0.74, 1.00, 0.91)},
|
||||||
purple= {hsv(0.80, 1.00, 0.81)},
|
purple= {hsv(0.80, 1.00, 0.81)},
|
||||||
magenta= {hsv(0.86, 1.00, 0.78)},
|
magenta= {hsv(0.86, 1.00, 0.78)},
|
||||||
wine= {hsv(0.94, 0.96, 0.91)},
|
wine= {hsv(0.92, 0.98, 0.91)},
|
||||||
|
|
||||||
lRed= {hsv(0.00, 0.38, 0.93)},
|
lRed= {hsv(0.00, 0.38, 0.93)},
|
||||||
lFire= {hsv(0.04, 0.45, 0.91)},
|
lFire= {hsv(0.04, 0.45, 0.91)},
|
||||||
lOrange= {hsv(0.10, 0.53, 0.92)},
|
lOrange= {hsv(0.10, 0.53, 0.92)},
|
||||||
lYellow= {hsv(0.15, 0.61, 0.95)},
|
lYellow= {hsv(0.14, 0.61, 0.95)},
|
||||||
lLime= {hsv(0.19, 0.66, 0.92)},
|
lLime= {hsv(0.20, 0.66, 0.92)},
|
||||||
lJade= {hsv(0.24, 0.56, 0.90)},
|
lJade= {hsv(0.26, 0.56, 0.90)},
|
||||||
lGreen= {hsv(0.34, 0.49, 0.89)},
|
lGreen= {hsv(0.34, 0.49, 0.89)},
|
||||||
lAqua= {hsv(0.49, 0.59, 0.85)},
|
lAqua= {hsv(0.47, 0.59, 0.86)},
|
||||||
lCyan= {hsv(0.51, 0.77, 0.88)},
|
lCyan= {hsv(0.51, 0.77, 0.88)},
|
||||||
lNavy= {hsv(0.54, 0.80, 0.95)},
|
lNavy= {hsv(0.54, 0.80, 0.95)},
|
||||||
lSea= {hsv(0.56, 0.72, 0.97)},
|
lSea= {hsv(0.57, 0.72, 0.97)},
|
||||||
lBlue= {hsv(0.64, 0.44, 0.96)},
|
lBlue= {hsv(0.64, 0.44, 0.96)},
|
||||||
lViolet= {hsv(0.73, 0.47, 0.95)},
|
lViolet= {hsv(0.72, 0.47, 0.95)},
|
||||||
lPurple= {hsv(0.80, 0.62, 0.89)},
|
lPurple= {hsv(0.80, 0.62, 0.89)},
|
||||||
lMagenta= {hsv(0.86, 0.61, 0.89)},
|
lMagenta= {hsv(0.86, 0.61, 0.89)},
|
||||||
lWine= {hsv(0.93, 0.57, 0.92)},
|
lWine= {hsv(0.93, 0.57, 0.92)},
|
||||||
@@ -53,13 +53,13 @@ local COLOR={
|
|||||||
dRed= {hsv(0.00, 0.80, 0.48)},
|
dRed= {hsv(0.00, 0.80, 0.48)},
|
||||||
dFire= {hsv(0.04, 0.80, 0.34)},
|
dFire= {hsv(0.04, 0.80, 0.34)},
|
||||||
dOrange= {hsv(0.07, 0.80, 0.39)},
|
dOrange= {hsv(0.07, 0.80, 0.39)},
|
||||||
dYellow= {hsv(0.11, 0.80, 0.37)},
|
dYellow= {hsv(0.12, 0.80, 0.37)},
|
||||||
dLime= {hsv(0.17, 0.80, 0.26)},
|
dLime= {hsv(0.20, 0.80, 0.26)},
|
||||||
dJade= {hsv(0.31, 0.80, 0.27)},
|
dJade= {hsv(0.29, 0.80, 0.27)},
|
||||||
dGreen= {hsv(0.33, 0.80, 0.26)},
|
dGreen= {hsv(0.33, 0.80, 0.26)},
|
||||||
dAqua= {hsv(0.47, 0.80, 0.23)},
|
dAqua= {hsv(0.46, 0.80, 0.24)},
|
||||||
dCyan= {hsv(0.50, 0.80, 0.30)},
|
dCyan= {hsv(0.50, 0.80, 0.30)},
|
||||||
dNavy= {hsv(0.59, 0.80, 0.42)},
|
dNavy= {hsv(0.58, 0.80, 0.42)},
|
||||||
dSea= {hsv(0.64, 0.80, 0.40)},
|
dSea= {hsv(0.64, 0.80, 0.40)},
|
||||||
dBlue= {hsv(0.67, 0.80, 0.34)},
|
dBlue= {hsv(0.67, 0.80, 0.34)},
|
||||||
dViolet= {hsv(0.71, 0.80, 0.35)},
|
dViolet= {hsv(0.71, 0.80, 0.35)},
|
||||||
@@ -72,12 +72,17 @@ local COLOR={
|
|||||||
gray= {hsv(0.02, 0.05, 0.65)},
|
gray= {hsv(0.02, 0.05, 0.65)},
|
||||||
lGray= {hsv(0.02, 0.06, 0.86)},
|
lGray= {hsv(0.02, 0.06, 0.86)},
|
||||||
white= {hsv(0.01, 0.02, 0.99)},
|
white= {hsv(0.01, 0.02, 0.99)},
|
||||||
|
|
||||||
|
xGray= {hsv(0.00, 0.00, 0.35,.8)},
|
||||||
|
lxGray= {hsv(0.00, 0.00, 0.62,.8)},
|
||||||
|
dxGray= {hsv(0.00, 0.00, 0.16,.8)},
|
||||||
}
|
}
|
||||||
for k,v in next,{
|
for k,v in next,{
|
||||||
R='red', F='fire', O='orange', Y='yellow', L='lime', J='jade', G='green', A='aqua', C='cyan', N='navy', S='sea', B='blue', V='violet', P='purple', M='magenta', W='wine',
|
R='red', F='fire', O='orange', Y='yellow', L='lime', J='jade', G='green', A='aqua', C='cyan', N='navy', S='sea', B='blue', V='violet', P='purple', M='magenta', W='wine',
|
||||||
lR='lRed',lF='lFire',lO='lOrange',lY='lYellow',lL='lLime',lJ='lJade',lG='lGreen',lA='lAqua',lC='lCyan',lN='lNavy',lS='lSea',lB='lBlue',lV='lViolet',lP='lPurple',lM='lMagenta',lW='lWine',
|
lR='lRed',lF='lFire',lO='lOrange',lY='lYellow',lL='lLime',lJ='lJade',lG='lGreen',lA='lAqua',lC='lCyan',lN='lNavy',lS='lSea',lB='lBlue',lV='lViolet',lP='lPurple',lM='lMagenta',lW='lWine',
|
||||||
dR='dRed',dF='dFire',dO='dOrange',dY='dYellow',dL='dLime',dJ='dJade',dG='dGreen',dA='dAqua',dC='dCyan',dN='dNavy',dS='dSea',dB='dBlue',dV='dViolet',dP='dPurple',dM='dMagenta',dW='dWine',
|
dR='dRed',dF='dFire',dO='dOrange',dY='dYellow',dL='dLime',dJ='dJade',dG='dGreen',dA='dAqua',dC='dCyan',dN='dNavy',dS='dSea',dB='dBlue',dV='dViolet',dP='dPurple',dM='dMagenta',dW='dWine',
|
||||||
D='black',dH='dGray',H='gray',lH='lGray',Z='white',
|
D='black',dH='dGray',H='gray',lH='lGray',Z='white',
|
||||||
|
X='xGray',lX='lxGray',dX='dxGray',
|
||||||
--Remain letter: EIKQTUX
|
--Remain letter: EIKQTUX
|
||||||
}do
|
}do
|
||||||
COLOR[k]=COLOR[v]
|
COLOR[k]=COLOR[v]
|
||||||
|
|||||||
@@ -1,66 +1,76 @@
|
|||||||
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()
|
local mode=
|
||||||
if mode=='luaon'or not mode and s:sub(1,6)=="return{"then
|
STRING.sArg(args,'-luaon')and'luaon'or
|
||||||
s=loadstring(s)
|
STRING.sArg(args,'-lua')and'lua'or
|
||||||
if s then
|
STRING.sArg(args,'-json')and'json'or
|
||||||
setfenv(s,{})
|
STRING.sArg(args,'-string')and'string'or
|
||||||
return s()
|
s:sub(1,6)=='return{'and'luaon'or
|
||||||
end
|
(s:sub(1,1)=='['and s:sub(-1)==']'or s:sub(1,1)=='{'and s:sub(-1)=='}')and'json'or
|
||||||
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
|
'string'
|
||||||
local res=JSON.decode(s)
|
if mode=='luaon'then
|
||||||
if res then
|
local func,err_mes=loadstring(s)
|
||||||
return res
|
if func then
|
||||||
end
|
setfenv(func,{})
|
||||||
elseif mode=='string'or not mode then
|
local res=func()
|
||||||
return s
|
return assert(res,'decode error')
|
||||||
else
|
else
|
||||||
MES.new("No file loading mode called "..tostring(mode))
|
error('decode error: '..err_mes)
|
||||||
end
|
end
|
||||||
|
elseif mode=='lua'then
|
||||||
|
local func,err_mes=loadstring(s)
|
||||||
|
if func then
|
||||||
|
local res=func()
|
||||||
|
return assert(res,'run error')
|
||||||
|
else
|
||||||
|
error('compile error: '..err_mes)
|
||||||
|
end
|
||||||
|
elseif mode=='json'then
|
||||||
|
local res=JSON.decode(s)
|
||||||
|
if res then
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
error('decode error')
|
||||||
|
elseif mode=='string'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 STRING.sArg(args,'-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 STRING.sArg(args,'-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
|
||||||
|
|||||||
@@ -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),STRING.repD("Font file $1($2) not exist!",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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ local IMG={}
|
|||||||
function IMG.init(list)
|
function IMG.init(list)
|
||||||
IMG.init=nil
|
IMG.init=nil
|
||||||
|
|
||||||
local null=love.graphics.newCanvas(1,1)
|
|
||||||
setmetatable(IMG,{__index=function(self,name)
|
setmetatable(IMG,{__index=function(self,name)
|
||||||
if type(list[name])=='table'then
|
if type(list[name])=='table'then
|
||||||
self[name]={}
|
self[name]={}
|
||||||
@@ -13,7 +12,7 @@ function IMG.init(list)
|
|||||||
self[name]=love.graphics.newImage(list[name])
|
self[name]=love.graphics.newImage(list[name])
|
||||||
else
|
else
|
||||||
LOG("No IMG: "..name)
|
LOG("No IMG: "..name)
|
||||||
self[name]=null
|
self[name]=PAPER
|
||||||
end
|
end
|
||||||
return self[name]
|
return self[name]
|
||||||
end})
|
end})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
NONE={}function NULL()end
|
NONE={}function NULL()end PAPER=love.graphics.newCanvas(1,1)
|
||||||
EDITING=""
|
EDITING=""
|
||||||
LOADED=false
|
LOADED=false
|
||||||
|
|
||||||
@@ -37,7 +37,6 @@ REQUIRE= require'Zframework.require'
|
|||||||
TASK= require'Zframework.task'
|
TASK= require'Zframework.task'
|
||||||
WS= require'Zframework.websocket'
|
WS= require'Zframework.websocket'
|
||||||
LANG= require'Zframework.languages'
|
LANG= require'Zframework.languages'
|
||||||
THEME= require'Zframework.theme'
|
|
||||||
|
|
||||||
--Love-based modules (basic)
|
--Love-based modules (basic)
|
||||||
FILE= require'Zframework.file'
|
FILE= require'Zframework.file'
|
||||||
@@ -61,6 +60,7 @@ BGM= require'Zframework.bgm'
|
|||||||
VOC= require'Zframework.voice'
|
VOC= require'Zframework.voice'
|
||||||
|
|
||||||
local ms,kb=love.mouse,love.keyboard
|
local ms,kb=love.mouse,love.keyboard
|
||||||
|
local KBisDown=kb.isDown
|
||||||
|
|
||||||
local gc=love.graphics
|
local gc=love.graphics
|
||||||
local gc_push,gc_pop,gc_clear,gc_discard=gc.push,gc.pop,gc.clear,gc.discard
|
local gc_push,gc_pop,gc_clear,gc_discard=gc.push,gc.pop,gc.clear,gc.discard
|
||||||
@@ -72,11 +72,24 @@ local WIDGET,SCR,SCN=WIDGET,SCR,SCN
|
|||||||
local xOy=SCR.xOy
|
local xOy=SCR.xOy
|
||||||
local ITP=xOy.inverseTransformPoint
|
local ITP=xOy.inverseTransformPoint
|
||||||
|
|
||||||
local mx,my,mouseShow=-20,-20,false
|
local max,min=math.max,math.min
|
||||||
|
|
||||||
|
local devMode
|
||||||
|
local mx,my,mouseShow,cursorSpd=640,360,false,0
|
||||||
local jsState={}--map, joystickID->axisStates: {axisName->axisVal}
|
local jsState={}--map, joystickID->axisStates: {axisName->axisVal}
|
||||||
local errData={}--list, each error create {mes={errMes strings},scene=sceneNameStr}
|
local errData={}--list, each error create {mes={errMes strings},scene=sceneNameStr}
|
||||||
|
|
||||||
local devMode
|
local function drawCursor(_,x,y)
|
||||||
|
gc_setColor(1,1,1)
|
||||||
|
gc_setLineWidth(2)
|
||||||
|
gc_circle(ms.isDown(1)and'fill'or'line',x,y,6)
|
||||||
|
end
|
||||||
|
local showPowerInfo=true
|
||||||
|
local showClickFX=true
|
||||||
|
local discardCanvas=false
|
||||||
|
local frameMul=100
|
||||||
|
local sleepInterval=1/60
|
||||||
|
local onQuit=NULL
|
||||||
|
|
||||||
local batteryImg=GC.DO{31,20,
|
local batteryImg=GC.DO{31,20,
|
||||||
{'fRect',1,0,26,2},
|
{'fRect',1,0,26,2},
|
||||||
@@ -94,17 +107,16 @@ local function updatePowerInfo()
|
|||||||
gc_clear(0,0,0,.25)
|
gc_clear(0,0,0,.25)
|
||||||
if state~='unknown'then
|
if state~='unknown'then
|
||||||
gc_setLineWidth(4)
|
gc_setLineWidth(4)
|
||||||
local charging=state=='charging'
|
|
||||||
if state=='nobattery'then
|
if state=='nobattery'then
|
||||||
gc_setColor(1,1,1)
|
gc_setColor(1,1,1)
|
||||||
gc_setLineWidth(2)
|
gc_setLineWidth(2)
|
||||||
gc_line(74,SCR.safeX+5,100,22)
|
gc_line(74,5,100,22)
|
||||||
elseif pow then
|
elseif pow then
|
||||||
if charging then gc_setColor(0,1,0)
|
if state=='charging'then gc_setColor(0,1,0)
|
||||||
elseif pow>50 then gc_setColor(1,1,1)
|
elseif pow>50 then gc_setColor(1,1,1)
|
||||||
elseif pow>26 then gc_setColor(1,1,0)
|
elseif pow>26 then gc_setColor(1,1,0)
|
||||||
elseif pow==26 then gc_setColor(.5,0,1)
|
elseif pow==26 then gc_setColor(.5,0,1)
|
||||||
else gc_setColor(1,0,0)
|
else gc_setColor(1,0,0)
|
||||||
end
|
end
|
||||||
gc.rectangle('fill',76,6,pow*.22,14)
|
gc.rectangle('fill',76,6,pow*.22,14)
|
||||||
if pow<100 then
|
if pow<100 then
|
||||||
@@ -127,36 +139,81 @@ local function updatePowerInfo()
|
|||||||
end
|
end
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
local lastX,lastY=0,0--Last click pos
|
local lastX,lastY=0,0--Last click pos
|
||||||
|
local function _updateMousePos(x,y,dx,dy)
|
||||||
|
if SCN.swapping then return end
|
||||||
|
dx,dy=dx/SCR.k,dy/SCR.k
|
||||||
|
if SCN.mouseMove then SCN.mouseMove(x,y,dx,dy)end
|
||||||
|
if ms.isDown(1)then
|
||||||
|
WIDGET.drag(x,y,dx,dy)
|
||||||
|
else
|
||||||
|
WIDGET.cursorMove(x,y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function _triggerMouseDown(x,y,k)
|
||||||
|
if devMode==1 then
|
||||||
|
print(("(%d,%d)<-%d,%d ~~(%d,%d)<-%d,%d"):format(
|
||||||
|
x,y,
|
||||||
|
x-lastX,y-lastY,
|
||||||
|
math.floor(x/10)*10,math.floor(y/10)*10,
|
||||||
|
math.floor((x-lastX)/10)*10,math.floor((y-lastY)/10)*10
|
||||||
|
))
|
||||||
|
end
|
||||||
|
if SCN.swapping then return end
|
||||||
|
if SCN.mouseDown then SCN.mouseDown(x,y,k)end
|
||||||
|
WIDGET.press(x,y,k)
|
||||||
|
lastX,lastY=x,y
|
||||||
|
if showClickFX then SYSFX.newTap(3,x,y)end
|
||||||
|
end
|
||||||
|
local function mouse_update(dt)
|
||||||
|
if not KBisDown('lctrl','rctrl')and KBisDown('up','down','left','right')then
|
||||||
|
local dx,dy=0,0
|
||||||
|
if KBisDown('up')then dy=dy-cursorSpd end
|
||||||
|
if KBisDown('down')then dy=dy+cursorSpd end
|
||||||
|
if KBisDown('left')then dx=dx-cursorSpd end
|
||||||
|
if KBisDown('right')then dx=dx+cursorSpd end
|
||||||
|
mx=max(min(mx+dx,1280),0)
|
||||||
|
my=max(min(my+dy,720),0)
|
||||||
|
if my==0 or my==720 then
|
||||||
|
WIDGET.sel=false
|
||||||
|
WIDGET.drag(0,0,0,-dy)
|
||||||
|
end
|
||||||
|
_updateMousePos(mx,my,dx,dy)
|
||||||
|
cursorSpd=min(cursorSpd+dt*26,12.6)
|
||||||
|
else
|
||||||
|
cursorSpd=6
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function gp_update(js,dt)
|
||||||
|
local sx,sy=js._jsObj:getGamepadAxis('leftx'),js._jsObj:getGamepadAxis('lefty')
|
||||||
|
if math.abs(sx)>.1 or math.abs(sy)>.1 then
|
||||||
|
local dx,dy=0,0
|
||||||
|
if sy<-.1 then dy=dy+2*sy*cursorSpd end
|
||||||
|
if sy>.1 then dy=dy+2*sy*cursorSpd end
|
||||||
|
if sx<-.1 then dx=dx+2*sx*cursorSpd end
|
||||||
|
if sx>.1 then dx=dx+2*sx*cursorSpd end
|
||||||
|
mx=max(min(mx+dx,1280),0)
|
||||||
|
my=max(min(my+dy,720),0)
|
||||||
|
if my==0 or my==720 then
|
||||||
|
WIDGET.sel=false
|
||||||
|
WIDGET.drag(0,0,0,-dy)
|
||||||
|
end
|
||||||
|
_updateMousePos(mx,my,dx,dy)
|
||||||
|
cursorSpd=min(cursorSpd+dt*26,12.6)
|
||||||
|
else
|
||||||
|
cursorSpd=6
|
||||||
|
end
|
||||||
|
end
|
||||||
function love.mousepressed(x,y,k,touch)
|
function love.mousepressed(x,y,k,touch)
|
||||||
if touch then return end
|
if touch then return end
|
||||||
mouseShow=true
|
mouseShow=true
|
||||||
mx,my=ITP(xOy,x,y)
|
mx,my=ITP(xOy,x,y)
|
||||||
if devMode==1 then
|
_triggerMouseDown(mx,my,k)
|
||||||
print(("(%d,%d)<-%d,%d ~~(%d,%d)<-%d,%d"):format(
|
|
||||||
mx,my,
|
|
||||||
mx-lastX,my-lastY,
|
|
||||||
math.floor(mx/10)*10,math.floor(my/10)*10,
|
|
||||||
math.floor((mx-lastX)/10)*10,math.floor((my-lastY)/10)*10
|
|
||||||
))
|
|
||||||
end
|
|
||||||
if SCN.swapping then return end
|
|
||||||
if SCN.mouseDown then SCN.mouseDown(mx,my,k)end
|
|
||||||
WIDGET.press(mx,my,k)
|
|
||||||
lastX,lastY=mx,my
|
|
||||||
if SETTING.clickFX then SYSFX.newTap(3,mx,my)end
|
|
||||||
end
|
end
|
||||||
function love.mousemoved(x,y,dx,dy,touch)
|
function love.mousemoved(x,y,dx,dy,touch)
|
||||||
if touch then return end
|
if touch then return end
|
||||||
mouseShow=true
|
mouseShow=true
|
||||||
mx,my=ITP(xOy,x,y)
|
mx,my=ITP(xOy,x,y)
|
||||||
if SCN.swapping then return end
|
_updateMousePos(mx,my,dx,dy)
|
||||||
dx,dy=dx/SCR.k,dy/SCR.k
|
|
||||||
if SCN.mouseMove then SCN.mouseMove(mx,my,dx,dy)end
|
|
||||||
if ms.isDown(1)then
|
|
||||||
WIDGET.drag(mx,my,dx/SCR.k,dy/SCR.k)
|
|
||||||
else
|
|
||||||
WIDGET.cursorMove(mx,my)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
function love.mousereleased(x,y,k,touch)
|
function love.mousereleased(x,y,k,touch)
|
||||||
if touch or SCN.swapping then return end
|
if touch or SCN.swapping then return end
|
||||||
@@ -191,13 +248,13 @@ function love.touchpressed(id,x,y)
|
|||||||
x,y=ITP(xOy,x,y)
|
x,y=ITP(xOy,x,y)
|
||||||
lastX,lastY=x,y
|
lastX,lastY=x,y
|
||||||
WIDGET.cursorMove(x,y)
|
WIDGET.cursorMove(x,y)
|
||||||
if SCN.touchDown then SCN.touchDown(x,y)end
|
if SCN.touchDown then SCN.touchDown(x,y,id)end
|
||||||
if kb.hasTextInput()then kb.setTextInput(false)end
|
if kb.hasTextInput()then kb.setTextInput(false)end
|
||||||
end
|
end
|
||||||
function love.touchmoved(_,x,y,dx,dy)
|
function love.touchmoved(id,x,y,dx,dy)
|
||||||
if SCN.swapping then return end
|
if SCN.swapping then return end
|
||||||
x,y=ITP(xOy,x,y)
|
x,y=ITP(xOy,x,y)
|
||||||
if SCN.touchMove then SCN.touchMove(x,y,dx/SCR.k,dy/SCR.k)end
|
if SCN.touchMove then SCN.touchMove(x,y,dx/SCR.k,dy/SCR.k,id)end
|
||||||
WIDGET.drag(x,y,dx/SCR.k,dy/SCR.k)
|
WIDGET.drag(x,y,dx/SCR.k,dy/SCR.k)
|
||||||
end
|
end
|
||||||
function love.touchreleased(id,x,y)
|
function love.touchreleased(id,x,y)
|
||||||
@@ -210,40 +267,40 @@ function love.touchreleased(id,x,y)
|
|||||||
WIDGET.unFocus()
|
WIDGET.unFocus()
|
||||||
SCN.mainTouchID=false
|
SCN.mainTouchID=false
|
||||||
end
|
end
|
||||||
if SCN.touchUp then SCN.touchUp(x,y)end
|
if SCN.touchUp then SCN.touchUp(x,y,id)end
|
||||||
if(x-lastX)^2+(y-lastY)^2<62 then
|
if(x-lastX)^2+(y-lastY)^2<62 then
|
||||||
if SCN.touchClick then SCN.touchClick(x,y)end
|
if SCN.touchClick then SCN.touchClick(x,y)end
|
||||||
if SETTING.clickFX then SYSFX.newTap(3,x,y)end
|
if showClickFX then SYSFX.newTap(3,x,y)end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local fnKey={NULL,NULL,NULL,NULL,NULL,NULL,NULL}
|
local fnKey={NULL,NULL,NULL,NULL,NULL,NULL,NULL}
|
||||||
local function noDevkeyPressed(key)
|
local function noDevkeyPressed(key)
|
||||||
if key=="f1"then fnKey[1]()
|
if key=='f1'then fnKey[1]()
|
||||||
elseif key=="f2"then fnKey[2]()
|
elseif key=='f2'then fnKey[2]()
|
||||||
elseif key=="f3"then fnKey[3]()
|
elseif key=='f3'then fnKey[3]()
|
||||||
elseif key=="f4"then fnKey[4]()
|
elseif key=='f4'then fnKey[4]()
|
||||||
elseif key=="f5"then fnKey[5]()
|
elseif key=='f5'then fnKey[5]()
|
||||||
elseif key=="f6"then fnKey[6]()
|
elseif key=='f6'then fnKey[6]()
|
||||||
elseif key=="f7"then fnKey[7]()
|
elseif key=='f7'then fnKey[7]()
|
||||||
elseif key=="f8"then devMode=nil MES.new('info',"DEBUG OFF",.2)
|
elseif key=='f8'then devMode=nil MES.new('info',"DEBUG OFF",.2)
|
||||||
elseif key=="f9"then devMode=1 MES.new('info',"DEBUG 1")
|
elseif key=='f9'then devMode=1 MES.new('info',"DEBUG 1")
|
||||||
elseif key=="f10"then devMode=2 MES.new('info',"DEBUG 2")
|
elseif key=='f10'then devMode=2 MES.new('info',"DEBUG 2")
|
||||||
elseif key=="f11"then devMode=3 MES.new('info',"DEBUG 3")
|
elseif key=='f11'then devMode=3 MES.new('info',"DEBUG 3")
|
||||||
elseif key=="f12"then devMode=4 MES.new('info',"DEBUG 4")
|
elseif key=='f12'then devMode=4 MES.new('info',"DEBUG 4")
|
||||||
elseif devMode==2 then
|
elseif devMode==2 then
|
||||||
local W=WIDGET.sel
|
local W=WIDGET.sel
|
||||||
if W then
|
if W then
|
||||||
if key=="left"then W.x=W.x-10
|
if key=='left'then W.x=W.x-10
|
||||||
elseif key=="right"then W.x=W.x+10
|
elseif key=='right'then W.x=W.x+10
|
||||||
elseif key=="up"then W.y=W.y-10
|
elseif key=='up'then W.y=W.y-10
|
||||||
elseif key=="down"then W.y=W.y+10
|
elseif key=='down'then W.y=W.y+10
|
||||||
elseif key==","then W.w=W.w-10
|
elseif key==','then W.w=W.w-10
|
||||||
elseif key=="."then W.w=W.w+10
|
elseif key=='.'then W.w=W.w+10
|
||||||
elseif key=="/"then W.h=W.h-10
|
elseif key=='/'then W.h=W.h-10
|
||||||
elseif key=="'"then W.h=W.h+10
|
elseif key=='\''then W.h=W.h+10
|
||||||
elseif key=="["then W.font=W.font-5
|
elseif key=='['then W.font=W.font-5
|
||||||
elseif key=="]"then W.font=W.font+5
|
elseif key==']'then W.font=W.font+5
|
||||||
else return true
|
else return true
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -257,22 +314,34 @@ function love.keypressed(key,_,isRep)
|
|||||||
mouseShow=false
|
mouseShow=false
|
||||||
if devMode and not noDevkeyPressed(key)then
|
if devMode and not noDevkeyPressed(key)then
|
||||||
return
|
return
|
||||||
elseif key=="f8"then
|
elseif key=='f8'then
|
||||||
devMode=1
|
devMode=1
|
||||||
MES.new('info',"DEBUG ON",.2)
|
MES.new('info',"DEBUG ON",.2)
|
||||||
elseif key=="f11"then
|
elseif key=='f11'then
|
||||||
SETTING.fullscreen=not SETTING.fullscreen
|
SETTING.fullscreen=not SETTING.fullscreen
|
||||||
applyFullscreen()
|
applySettings()
|
||||||
saveSettings()
|
saveSettings()
|
||||||
elseif not SCN.swapping then
|
elseif not SCN.swapping then
|
||||||
if SCN.keyDown then
|
if EDITING==""and(not SCN.keyDown or SCN.keyDown(key,isRep))then
|
||||||
if EDITING==""then
|
local W=WIDGET.sel
|
||||||
SCN.keyDown(key,isRep)
|
if key=='escape'and not isRep then
|
||||||
|
SCN.back()
|
||||||
|
elseif key=='up'or key=='down'or key=='left'or key=='right'then
|
||||||
|
mouseShow=true
|
||||||
|
if KBisDown('lctrl','rctrl')then
|
||||||
|
if W and W.arrowKey then W:arrowKey(key)end
|
||||||
|
end
|
||||||
|
elseif key=='space'or key=='return'then
|
||||||
|
mouseShow=true
|
||||||
|
if not isRep then
|
||||||
|
if showClickFX then SYSFX.newTap(3,mx,my)end
|
||||||
|
_triggerMouseDown(mx,my,1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if W and W.keypress then
|
||||||
|
W:keypress(key)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
elseif key=="escape"and not isRep then
|
|
||||||
SCN.back()
|
|
||||||
else
|
|
||||||
WIDGET.keyPressed(key,isRep)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -308,35 +377,38 @@ local dPadToKey={
|
|||||||
back='escape',
|
back='escape',
|
||||||
}
|
}
|
||||||
function love.joystickadded(JS)
|
function love.joystickadded(JS)
|
||||||
jsState[JS:getID()]={
|
table.insert(jsState,{
|
||||||
_loveJSObj=JS,
|
_id=JS:getID(),
|
||||||
|
_jsObj=JS,
|
||||||
leftx=0,lefty=0,
|
leftx=0,lefty=0,
|
||||||
rightx=0,righty=0,
|
rightx=0,righty=0,
|
||||||
triggerleft=0,triggerright=0
|
triggerleft=0,triggerright=0
|
||||||
}
|
})
|
||||||
MES.new('info',"Joystick added")
|
MES.new('info',"Joystick added")
|
||||||
end
|
end
|
||||||
function love.joystickremoved(JS)
|
function love.joystickremoved(JS)
|
||||||
local js=jsState[JS:getID()]
|
for i=1,#jsState do
|
||||||
if js then
|
if jsState[i]._jsObj==JS then
|
||||||
for i=1,#gamePadKeys do
|
for j=1,#gamePadKeys do
|
||||||
if JS:isGamepadDown(gamePadKeys[i])then
|
if JS:isGamepadDown(gamePadKeys[j])then
|
||||||
love.gamepadreleased(JS,gamePadKeys[i])
|
love.gamepadreleased(JS,gamePadKeys[j])
|
||||||
|
end
|
||||||
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)
|
||||||
|
MES.new('info',"Joystick removed")
|
||||||
|
table.remove(jsState,i)
|
||||||
|
break
|
||||||
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
|
||||||
end
|
end
|
||||||
function love.gamepadaxis(JS,axis,val)
|
function love.gamepadaxis(JS,axis,val)
|
||||||
local js=jsState[JS:getID()]
|
if jsState[1]and JS==jsState[1]._jsObj then
|
||||||
if js then
|
local js=jsState[1]
|
||||||
if axis=='leftx'or axis=='lefty'or axis=='rightx'or axis=='righty'then
|
if axis=='leftx'or axis=='lefty'or axis=='rightx'or axis=='righty'then
|
||||||
local newVal=--range: [0,1]
|
local newVal=--range: [0,1]
|
||||||
val>.4 and 1 or
|
val>.4 and 1 or
|
||||||
@@ -356,7 +428,7 @@ function love.gamepadaxis(JS,axis,val)
|
|||||||
js[axis]=newVal
|
js[axis]=newVal
|
||||||
end
|
end
|
||||||
elseif axis=='triggerleft'or axis=='triggerright'then
|
elseif axis=='triggerleft'or axis=='triggerright'then
|
||||||
local newVal=val>-.3 and 1 or 0--range: [-1,1]
|
local newVal=val>.3 and 1 or 0--range: [0,1]
|
||||||
if newVal~=js[axis]then
|
if newVal~=js[axis]then
|
||||||
if newVal==1 then
|
if newVal==1 then
|
||||||
love.gamepadpressed(JS,jsAxisEventName[axis])
|
love.gamepadpressed(JS,jsAxisEventName[axis])
|
||||||
@@ -368,13 +440,36 @@ function love.gamepadaxis(JS,axis,val)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function love.gamepadpressed(_,i)
|
function love.gamepadpressed(_,key)
|
||||||
mouseShow=false
|
mouseShow=false
|
||||||
if SCN.swapping then return end
|
if not SCN.swapping then
|
||||||
if SCN.gamepadDown then SCN.gamepadDown(i)
|
local cursorCtrl
|
||||||
elseif SCN.keyDown then SCN.keyDown(dPadToKey[i]or i)
|
if SCN.gamepadDown then
|
||||||
elseif i=="back"then SCN.back()
|
cursorCtrl=SCN.gamepadDown(key)
|
||||||
else WIDGET.gamepadPressed(dPadToKey[i]or i)
|
elseif SCN.keyDown then
|
||||||
|
cursorCtrl=SCN.keyDown(dPadToKey[key]or key)
|
||||||
|
else
|
||||||
|
cursorCtrl=true
|
||||||
|
end
|
||||||
|
if cursorCtrl then
|
||||||
|
key=dPadToKey[key]or key
|
||||||
|
mouseShow=true
|
||||||
|
local W=WIDGET.sel
|
||||||
|
if key=='back'then
|
||||||
|
SCN.back()
|
||||||
|
elseif key=='up'or key=='down'or key=='left'or key=='right'then
|
||||||
|
mouseShow=true
|
||||||
|
if W and W.arrowKey then W:arrowKey(key)end
|
||||||
|
elseif key=='return'then
|
||||||
|
mouseShow=true
|
||||||
|
if showClickFX then SYSFX.newTap(3,mx,my)end
|
||||||
|
_triggerMouseDown(mx,my,1)
|
||||||
|
else
|
||||||
|
if W and W.keypress then
|
||||||
|
W:keypress(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function love.gamepadreleased(_,i)
|
function love.gamepadreleased(_,i)
|
||||||
@@ -396,14 +491,16 @@ function love.lowmemory()
|
|||||||
MES.new('check',"[auto GC] low MEM 设备内存过低")
|
MES.new('check',"[auto GC] low MEM 设备内存过低")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local onResize=NULL
|
||||||
function love.resize(w,h)
|
function love.resize(w,h)
|
||||||
|
if SCR.w==w and SCR.h==h then return end
|
||||||
SCR.resize(w,h)
|
SCR.resize(w,h)
|
||||||
if BG.resize then BG.resize(w,h)end
|
if BG.resize then BG.resize(w,h)end
|
||||||
if SCN.resize then SCN.resize(w,h)end
|
if SCN.resize then SCN.resize(w,h)end
|
||||||
WIDGET.resize(w,h)
|
WIDGET.resize(w,h)
|
||||||
FONT.reset()
|
FONT.reset()
|
||||||
|
onResize(w,h)
|
||||||
SHADER.warning:send('w',w*SCR.dpi)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local onFocus=NULL
|
local onFocus=NULL
|
||||||
@@ -514,7 +611,7 @@ local devColor={
|
|||||||
}
|
}
|
||||||
local WS=WS
|
local WS=WS
|
||||||
local WSnames={'app','user','play','stream','chat','manage'}
|
local WSnames={'app','user','play','stream','chat','manage'}
|
||||||
local wsBottomImage do
|
local wsImg={}do
|
||||||
local L={78,18,
|
local L={78,18,
|
||||||
{'clear',1,1,1,0},
|
{'clear',1,1,1,0},
|
||||||
{'setCL',1,1,1,.3},
|
{'setCL',1,1,1,.3},
|
||||||
@@ -524,31 +621,23 @@ local wsBottomImage do
|
|||||||
table.insert(L,{'setCL',1,1,1,i*.005})
|
table.insert(L,{'setCL',1,1,1,i*.005})
|
||||||
table.insert(L,{'fRect',i,0,1,18})
|
table.insert(L,{'fRect',i,0,1,18})
|
||||||
end
|
end
|
||||||
wsBottomImage=GC.DO(L)
|
wsImg.bottom=GC.DO(L)
|
||||||
|
wsImg.dead=GC.DO{20,20,
|
||||||
|
{'rawFT',20},
|
||||||
|
{'setCL',1,.3,.3},
|
||||||
|
{'mText',"X",11,-1},
|
||||||
|
}
|
||||||
|
wsImg.connecting=GC.DO{20,20,
|
||||||
|
{'rawFT',20},
|
||||||
|
{'setLW',3},
|
||||||
|
{'mText',"C",11,-1},
|
||||||
|
}
|
||||||
|
wsImg.running=GC.DO{20,20,
|
||||||
|
{'rawFT',20},
|
||||||
|
{'setCL',.5,1,0},
|
||||||
|
{'mText',"R",11,-1},
|
||||||
|
}
|
||||||
end
|
end
|
||||||
local ws_deadImg=GC.DO{20,20,
|
|
||||||
{'setFT',20},
|
|
||||||
{'setCL',1,.3,.3},
|
|
||||||
{'mText',"X",11,-1},
|
|
||||||
}
|
|
||||||
local ws_connectingImg=GC.DO{20,20,
|
|
||||||
{'setFT',20},
|
|
||||||
{'setLW',3},
|
|
||||||
{'mText',"C",11,-1},
|
|
||||||
}
|
|
||||||
local ws_runningImg=GC.DO{20,20,
|
|
||||||
{'setFT',20},
|
|
||||||
{'setCL',.5,1,0},
|
|
||||||
{'mText',"R",11,-1},
|
|
||||||
}
|
|
||||||
|
|
||||||
local function drawCursor(_,x,y)
|
|
||||||
gc_setColor(1,1,1)
|
|
||||||
gc_setLineWidth(2)
|
|
||||||
gc_circle(ms.isDown(1)and'fill'or'line',x,y,6)
|
|
||||||
end
|
|
||||||
local function showPowerInfo()return true end
|
|
||||||
local onQuit=NULL
|
|
||||||
|
|
||||||
function love.run()
|
function love.run()
|
||||||
local love=love
|
local love=love
|
||||||
@@ -560,12 +649,11 @@ function love.run()
|
|||||||
local TASK_update=TASK.update
|
local TASK_update=TASK.update
|
||||||
local SYSFX_update,SYSFX_draw=SYSFX.update,SYSFX.draw
|
local SYSFX_update,SYSFX_draw=SYSFX.update,SYSFX.draw
|
||||||
local WIDGET_update,WIDGET_draw=WIDGET.update,WIDGET.draw
|
local WIDGET_update,WIDGET_draw=WIDGET.update,WIDGET.draw
|
||||||
|
|
||||||
local STEP,WAIT=love.timer.step,love.timer.sleep
|
local STEP,WAIT=love.timer.step,love.timer.sleep
|
||||||
local FPS,MINI=love.timer.getFPS,love.window.isMinimized
|
local FPS,MINI=love.timer.getFPS,love.window.isMinimized
|
||||||
local PUMP,POLL=love.event.pump,love.event.poll
|
local PUMP,POLL=love.event.pump,love.event.poll
|
||||||
|
|
||||||
local timer,SETTING,VERSION=love.timer.getTime,SETTING,VERSION
|
local timer,VERSION=love.timer.getTime,VERSION
|
||||||
|
|
||||||
local frameTimeList={}
|
local frameTimeList={}
|
||||||
local lastFrame=timer()
|
local lastFrame=timer()
|
||||||
@@ -599,6 +687,8 @@ function love.run()
|
|||||||
|
|
||||||
--UPDATE
|
--UPDATE
|
||||||
STEP()
|
STEP()
|
||||||
|
if mouseShow then mouse_update(dt)end
|
||||||
|
if next(jsState)then gp_update(jsState[1],dt)end
|
||||||
VOC.update()
|
VOC.update()
|
||||||
BG.update(dt)
|
BG.update(dt)
|
||||||
TEXT_update(dt)
|
TEXT_update(dt)
|
||||||
@@ -612,11 +702,10 @@ function love.run()
|
|||||||
|
|
||||||
--DRAW
|
--DRAW
|
||||||
if not MINI()then
|
if not MINI()then
|
||||||
FCT=FCT+SETTING.frameMul
|
FCT=FCT+frameMul
|
||||||
if FCT>=100 then
|
if FCT>=100 then
|
||||||
FCT=FCT-100
|
FCT=FCT-100
|
||||||
|
|
||||||
local safeX=SCR.safeX
|
|
||||||
gc_replaceTransform(SCR.origin)
|
gc_replaceTransform(SCR.origin)
|
||||||
gc_setColor(1,1,1)
|
gc_setColor(1,1,1)
|
||||||
BG.draw()
|
BG.draw()
|
||||||
@@ -627,16 +716,14 @@ function love.run()
|
|||||||
TEXT_draw()
|
TEXT_draw()
|
||||||
|
|
||||||
--Draw cursor
|
--Draw cursor
|
||||||
if mouseShow then
|
if mouseShow then drawCursor(time,mx,my)end
|
||||||
drawCursor(time,mx,my)
|
|
||||||
end
|
|
||||||
gc_replaceTransform(SCR.xOy_ul)
|
|
||||||
MES_draw()
|
|
||||||
gc_replaceTransform(SCR.origin)
|
gc_replaceTransform(SCR.origin)
|
||||||
|
MES_draw()
|
||||||
|
|
||||||
--Draw power info.
|
--Draw power info.
|
||||||
if showPowerInfo()then
|
if showPowerInfo then
|
||||||
gc_setColor(1,1,1)
|
gc_setColor(1,1,1)
|
||||||
gc_draw(infoCanvas,safeX,0,0,SCR.k)
|
gc_draw(infoCanvas,SCR.safeX,0,0,SCR.k)
|
||||||
end
|
end
|
||||||
|
|
||||||
--Draw scene swapping animation
|
--Draw scene swapping animation
|
||||||
@@ -647,10 +734,12 @@ function love.run()
|
|||||||
end
|
end
|
||||||
gc_replaceTransform(SCR.xOy_d)
|
gc_replaceTransform(SCR.xOy_d)
|
||||||
--Draw Version string
|
--Draw Version string
|
||||||
gc_setColor(.8,.8,.8,.4)
|
gc_setColor(.9,.9,.9,.42)
|
||||||
FONT.set(20)
|
FONT.set(20)
|
||||||
mStr(VERSION.string,0,-30)
|
mStr(VERSION.string,0,-30)
|
||||||
gc_replaceTransform(SCR.xOy_dl)
|
gc_replaceTransform(SCR.xOy_dl)
|
||||||
|
local safeX=SCR.safeX/SCR.k
|
||||||
|
|
||||||
--Draw FPS
|
--Draw FPS
|
||||||
FONT.set(15)
|
FONT.set(15)
|
||||||
gc_setColor(1,1,1)
|
gc_setColor(1,1,1)
|
||||||
@@ -690,14 +779,14 @@ function love.run()
|
|||||||
for i=1,6 do
|
for i=1,6 do
|
||||||
local status=WS.status(WSnames[i])
|
local status=WS.status(WSnames[i])
|
||||||
gc_setColor(1,1,1)
|
gc_setColor(1,1,1)
|
||||||
gc.draw(wsBottomImage,-79,20*i-139)
|
gc.draw(wsImg.bottom,-79,20*i-139)
|
||||||
if status=='dead'then
|
if status=='dead'then
|
||||||
gc_draw(ws_deadImg,-20,20*i-140)
|
gc_draw(wsImg.dead,-20,20*i-140)
|
||||||
elseif status=='connecting'then
|
elseif status=='connecting'then
|
||||||
gc_setColor(1,1,1,.5+.3*math.sin(time*6.26))
|
gc_setColor(1,1,1,.5+.3*math.sin(time*6.26))
|
||||||
gc_draw(ws_connectingImg,-20,20*i-140)
|
gc_draw(wsImg.connecting,-20,20*i-140)
|
||||||
elseif status=='running'then
|
elseif status=='running'then
|
||||||
gc_draw(ws_runningImg,-20,20*i-140)
|
gc_draw(wsImg.running,-20,20*i-140)
|
||||||
end
|
end
|
||||||
local t1,t2,t3=WS.getTimers(WSnames[i])
|
local t1,t2,t3=WS.getTimers(WSnames[i])
|
||||||
gc_setColor(.9,.9,.9,t1)gc.rectangle('fill',-60,20*i-122,-16,-16)
|
gc_setColor(.9,.9,.9,t1)gc.rectangle('fill',-60,20*i-122,-16,-16)
|
||||||
@@ -708,13 +797,13 @@ function love.run()
|
|||||||
gc_present()
|
gc_present()
|
||||||
|
|
||||||
--SPEED UPUPUP!
|
--SPEED UPUPUP!
|
||||||
if SETTING.cleanCanvas then gc_discard()end
|
if discardCanvas then gc_discard()end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--Fresh power info.
|
--Fresh power info.
|
||||||
if time-lastFreshPow>2.6 then
|
if time-lastFreshPow>2.6 then
|
||||||
if showPowerInfo()then
|
if showPowerInfo then
|
||||||
updatePowerInfo()
|
updatePowerInfo()
|
||||||
lastFreshPow=time
|
lastFreshPow=time
|
||||||
end
|
end
|
||||||
@@ -732,31 +821,44 @@ function love.run()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--Keep 60fps
|
|
||||||
_=timer()-lastFrame
|
_=timer()-lastFrame
|
||||||
if _<.0162 then WAIT(.0162-_)end
|
if _<sleepInterval*.9626 then WAIT(sleepInterval*.9626-_)end
|
||||||
while timer()-lastFrame<1/60 do end
|
while timer()-lastFrame<sleepInterval do end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local Z={}
|
local Z={}
|
||||||
|
|
||||||
Z.js=jsState
|
function Z.getJsState()return jsState end
|
||||||
Z.errData=errData
|
function Z.getErr(i)
|
||||||
|
if i=='#'then
|
||||||
|
return errData[#errData]
|
||||||
|
elseif i then
|
||||||
|
return errData[i]
|
||||||
|
else
|
||||||
|
return errData
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function Z.setIfPowerInfo(func)showPowerInfo=func end
|
function Z.setPowerInfo(bool)showPowerInfo=bool end
|
||||||
|
function Z.setCleanCanvas(bool)discardCanvas=bool end
|
||||||
|
function Z.setFrameMul(n)frameMul=n end
|
||||||
|
function Z.setMaxFPS(fps)sleepInterval=1/fps end
|
||||||
|
function Z.setClickFX(bool)showClickFX=bool 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.
|
||||||
function Z.setCursor(func)drawCursor=func end
|
function Z.setCursor(func)drawCursor=func end
|
||||||
|
|
||||||
--Change F1~F7 events of devmode (F8 mode)
|
--Change F1~F7 events of devmode (F8 mode)
|
||||||
function Z.setOnFnKeys(list)
|
function Z.setOnFnKeys(list)
|
||||||
assert(type(list)=='table')
|
assert(type(list)=='table',"Z.setOnFnKeys(list): list must be a table.")
|
||||||
for i=1,7 do fnKey[i]=type(list[i])=='function'and list[i]or NULL end
|
for i=1,7 do fnKey[i]=type(list[i])=='function'and list[i]or NULL end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Z.setOnFocus(func)onFocus=type(func)=='function'and func or NULL end
|
function Z.setOnFocus(func)onFocus=assert(type(func)=='function'and func,"Z.setOnFocus(func): func must be a function")end
|
||||||
|
|
||||||
function Z.setOnQuit(func)onQuit=type(func)=='function'and func or NULL end
|
function Z.setOnResize(func)onResize=assert(type(func)=='function'and func,"Z.setOnResize(func): func must be a function")end
|
||||||
|
|
||||||
|
function Z.setOnQuit(func)onQuit=assert(type(func)=='function'and func,"Z.setOnQuit(func): func must be a function")end
|
||||||
|
|
||||||
return Z
|
return Z
|
||||||
|
|||||||
@@ -20,4 +20,18 @@ function MATH.coin(a,b)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function MATH.interval(v,low,high)
|
||||||
|
if v<=low then
|
||||||
|
return low
|
||||||
|
elseif v>=high then
|
||||||
|
return high
|
||||||
|
else
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function MATH.expApproach(a,b,k)
|
||||||
|
return b+(a-b)*2.718281828459045^-k
|
||||||
|
end
|
||||||
|
|
||||||
return MATH
|
return MATH
|
||||||
@@ -140,11 +140,11 @@ function profile.switch()
|
|||||||
switch=not switch
|
switch=not switch
|
||||||
if not switch then
|
if not switch then
|
||||||
profile.stop()
|
profile.stop()
|
||||||
love.system.setClipboardText(PROFILE.report())
|
love.system.setClipboardText(profile.report())
|
||||||
PROFILE.reset()
|
profile.reset()
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
PROFILE.start()
|
profile.start()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ local SCN={
|
|||||||
draw=false, --Swap draw func
|
draw=false, --Swap draw func
|
||||||
},
|
},
|
||||||
stack={},--Scene stack
|
stack={},--Scene stack
|
||||||
|
prev=false,
|
||||||
|
args={},--Arguments from previous scene
|
||||||
|
|
||||||
scenes=scenes,
|
scenes=scenes,
|
||||||
|
|
||||||
@@ -52,14 +54,15 @@ function SCN.swapUpdate(dt)
|
|||||||
S.time=S.time-dt
|
S.time=S.time-dt
|
||||||
if S.time<S.changeTime and S.time+dt>=S.changeTime then
|
if S.time<S.changeTime and S.time+dt>=S.changeTime then
|
||||||
--Scene swapped this frame
|
--Scene swapped this frame
|
||||||
SCN.init(S.tar,SCN.cur)
|
SCN.prev=SCN.cur
|
||||||
|
SCN.init(S.tar)
|
||||||
SCN.mainTouchID=nil
|
SCN.mainTouchID=nil
|
||||||
end
|
end
|
||||||
if S.time<0 then
|
if S.time<0 then
|
||||||
SCN.swapping=false
|
SCN.swapping=false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function SCN.init(s,org)
|
function SCN.init(s)
|
||||||
love.keyboard.setTextInput(false)
|
love.keyboard.setTextInput(false)
|
||||||
|
|
||||||
local S=scenes[s]
|
local S=scenes[s]
|
||||||
@@ -89,7 +92,7 @@ function SCN.init(s,org)
|
|||||||
SCN.update=S.update
|
SCN.update=S.update
|
||||||
SCN.draw=S.draw
|
SCN.draw=S.draw
|
||||||
if S.sceneInit then
|
if S.sceneInit then
|
||||||
S.sceneInit(org)
|
S.sceneInit()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function SCN.push(tar,style)
|
function SCN.push(tar,style)
|
||||||
@@ -165,11 +168,12 @@ local swap={
|
|||||||
end
|
end
|
||||||
},
|
},
|
||||||
}--Scene swapping animations
|
}--Scene swapping animations
|
||||||
function SCN.swapTo(tar,style)--Parallel scene swapping, cannot back
|
function SCN.swapTo(tar,style,...)--Parallel scene swapping, cannot back
|
||||||
if scenes[tar]then
|
if scenes[tar]then
|
||||||
if not SCN.swapping and tar~=SCN.cur then
|
if not SCN.swapping and tar~=SCN.cur then
|
||||||
style=style or'fade'
|
style=style or'fade'
|
||||||
SCN.swapping=true
|
SCN.swapping=true
|
||||||
|
SCN.args={...}
|
||||||
local S=SCN.stat
|
local S=SCN.stat
|
||||||
S.tar,S.style=tar,style
|
S.tar,S.style=tar,style
|
||||||
S.time=swap[style].duration
|
S.time=swap[style].duration
|
||||||
@@ -180,15 +184,15 @@ function SCN.swapTo(tar,style)--Parallel scene swapping, cannot back
|
|||||||
MES.new('warn',"No Scene: "..tar)
|
MES.new('warn',"No Scene: "..tar)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function SCN.go(tar,style)--Normal scene swapping, can back
|
function SCN.go(tar,style,...)--Normal scene swapping, can back
|
||||||
if scenes[tar]then
|
if scenes[tar]then
|
||||||
SCN.push()
|
SCN.push()
|
||||||
SCN.swapTo(tar,style)
|
SCN.swapTo(tar,style,...)
|
||||||
else
|
else
|
||||||
MES.new('warn',"No Scene: "..tar)
|
MES.new('warn',"No Scene: "..tar)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function SCN.back()
|
function SCN.back(...)
|
||||||
if SCN.swapping then return end
|
if SCN.swapping then return end
|
||||||
|
|
||||||
--Leave scene
|
--Leave scene
|
||||||
@@ -199,7 +203,7 @@ function SCN.back()
|
|||||||
--Poll&Back to previous Scene
|
--Poll&Back to previous Scene
|
||||||
local m=#SCN.stack
|
local m=#SCN.stack
|
||||||
if m>0 then
|
if m>0 then
|
||||||
SCN.swapTo(SCN.stack[m-1],SCN.stack[m])
|
SCN.swapTo(SCN.stack[m-1],SCN.stack[m],...)
|
||||||
SCN.stack[m],SCN.stack[m-1]=nil
|
SCN.stack[m],SCN.stack[m-1]=nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
local type,rem=type,table.remove
|
local type,rem=type,table.remove
|
||||||
local int,rnd=math.floor,math.random
|
local int,rnd=math.floor,math.random
|
||||||
|
local interval=MATH.interval
|
||||||
|
|
||||||
local sfxList={}
|
local sfxList={}
|
||||||
local packSetting={}
|
local packSetting={}
|
||||||
@@ -42,16 +43,28 @@ function SFX.init(list)
|
|||||||
end
|
end
|
||||||
function SFX.load(path)
|
function SFX.load(path)
|
||||||
local c=0
|
local c=0
|
||||||
|
local missing=0
|
||||||
for i=1,#sfxList do
|
for i=1,#sfxList do
|
||||||
local fullPath=path..sfxList[i]..'.ogg'
|
local fullPath=path..sfxList[i]..'.ogg'
|
||||||
if love.filesystem.getInfo(fullPath)then
|
if love.filesystem.getInfo(fullPath)then
|
||||||
|
if Sources[sfxList[i]]then
|
||||||
|
for j=1,#Sources[sfxList[i]]do
|
||||||
|
Sources[sfxList[i]][j]:release()
|
||||||
|
end
|
||||||
|
end
|
||||||
Sources[sfxList[i]]={love.audio.newSource(fullPath,'static')}
|
Sources[sfxList[i]]={love.audio.newSource(fullPath,'static')}
|
||||||
c=c+1
|
c=c+1
|
||||||
else
|
else
|
||||||
LOG("No SFX: "..sfxList[i]..'.ogg',.1)
|
LOG("No SFX: "..sfxList[i]..'.ogg',.1)
|
||||||
|
missing=missing+1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
LOG(c.."/"..#sfxList.." SFX files loaded")
|
LOG(c.."/"..#sfxList.." SFX files loaded")
|
||||||
|
LOG(missing.." SFX files missing")
|
||||||
|
if missing>0 then
|
||||||
|
MES.new('info',missing.." SFX files missing")
|
||||||
|
end
|
||||||
|
collectgarbage()
|
||||||
end
|
end
|
||||||
function SFX.loadSample(pack)
|
function SFX.loadSample(pack)
|
||||||
assert(type(pack)=='table',"Usage: SFX.loadsample([table])")
|
assert(type(pack)=='table',"Usage: SFX.loadsample([table])")
|
||||||
@@ -128,7 +141,7 @@ local function _play(name,vol,pos,pitch)
|
|||||||
S=S[n]--AU_SRC
|
S=S[n]--AU_SRC
|
||||||
if S:getChannelCount()==1 then
|
if S:getChannelCount()==1 then
|
||||||
if pos then
|
if pos then
|
||||||
pos=pos*stereo
|
pos=interval(pos,-1,1)*stereo
|
||||||
S:setPosition(pos,1-pos^2,0)
|
S:setPosition(pos,1-pos^2,0)
|
||||||
else
|
else
|
||||||
S:setPosition(0,0,0)
|
S:setPosition(0,0,0)
|
||||||
|
|||||||
@@ -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']='%',
|
||||||
@@ -153,6 +169,25 @@ function STRING.vcsDecrypt(text,key)
|
|||||||
end
|
end
|
||||||
return result..buffer
|
return result..buffer
|
||||||
end
|
end
|
||||||
|
function STRING.digezt(text)--Not powerful hash, just protect the original text
|
||||||
|
local out={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
|
||||||
|
local seed=26
|
||||||
|
for i=1,#text do
|
||||||
|
local c=byte(text,i)
|
||||||
|
seed=(seed+c)%26
|
||||||
|
c=c+seed
|
||||||
|
local pos=c*i%16
|
||||||
|
local step=(c+i)%4+1
|
||||||
|
local times=2+(c%6)
|
||||||
|
for _=1,times do
|
||||||
|
out[pos+1]=(out[pos+1]+c)%256
|
||||||
|
pos=(pos+step)%16
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local result=""
|
||||||
|
for i=1,16 do result=result..char(out[i])end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
function STRING.readLine(str)
|
function STRING.readLine(str)
|
||||||
local p=str:find("\n")
|
local p=str:find("\n")
|
||||||
@@ -162,6 +197,9 @@ function STRING.readLine(str)
|
|||||||
return str,""
|
return str,""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
function STRING.readChars(str,n)
|
||||||
|
return sub(str,1,n),sub(str,n+1)
|
||||||
|
end
|
||||||
|
|
||||||
function STRING.packBin(s)
|
function STRING.packBin(s)
|
||||||
return data.encode('string','base64',data.compress('string','zlib',s))
|
return data.encode('string','base64',data.compress('string','zlib',s))
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ return function(y,key1,key2)
|
|||||||
trigDist=min(trigDist,0)-(-y)^1.2
|
trigDist=min(trigDist,0)-(-y)^1.2
|
||||||
end
|
end
|
||||||
while trigDist>=1 do
|
while trigDist>=1 do
|
||||||
love.keypressed(key1 or"up")
|
love.keypressed(key1 or'up')
|
||||||
trigDist=trigDist-1
|
trigDist=trigDist-1
|
||||||
end
|
end
|
||||||
while trigDist<=-1 do
|
while trigDist<=-1 do
|
||||||
love.keypressed(key2 or"down")
|
love.keypressed(key2 or'down')
|
||||||
trigDist=trigDist+1
|
trigDist=trigDist+1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ local kb=love.keyboard
|
|||||||
local timer=love.timer.getTime
|
local timer=love.timer.getTime
|
||||||
|
|
||||||
local next=next
|
local next=next
|
||||||
local int,ceil,abs=math.floor,math.ceil,math.abs
|
local int,ceil=math.floor,math.ceil
|
||||||
local max,min=math.max,math.min
|
local max,min=math.max,math.min
|
||||||
local sub,ins,rem=string.sub,table.insert,table.remove
|
local sub,ins,rem=string.sub,table.insert,table.remove
|
||||||
local mDraw,mDraw_X,mDraw_Y=GC.draw,GC.simpX,GC.simpY
|
|
||||||
local xOy=SCR.xOy
|
local xOy=SCR.xOy
|
||||||
local FONT=FONT
|
local FONT=FONT
|
||||||
local mStr=GC.mStr
|
local mStr=GC.mStr
|
||||||
|
local approach=MATH.expApproach
|
||||||
|
|
||||||
local downArrowIcon=GC.DO{40,25,{'fPoly',0,0,20,25,40,0}}
|
local downArrowIcon=GC.DO{40,25,{'fPoly',0,0,20,25,40,0}}
|
||||||
local upArrowIcon=GC.DO{40,25,{'fPoly',0,25,20,0,40,25}}
|
local upArrowIcon=GC.DO{40,25,{'fPoly',0,25,20,0,40,25}}
|
||||||
@@ -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,
|
||||||
@@ -46,7 +46,12 @@ local function _rectangleStencil()
|
|||||||
gc.rectangle('fill',1,1,STW-2,STH-2)
|
gc.rectangle('fill',1,1,STW-2,STH-2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local onChange=NULL
|
||||||
|
|
||||||
local WIDGET={}
|
local WIDGET={}
|
||||||
|
|
||||||
|
function WIDGET.setOnChange(func)onChange=assert(type(func)=='function'and func,"WIDGET.setOnChange(func): func must be a function")end
|
||||||
|
|
||||||
local widgetMetatable={
|
local widgetMetatable={
|
||||||
__tostring=function(self)
|
__tostring=function(self)
|
||||||
return self:getInfo()
|
return self:getInfo()
|
||||||
@@ -73,24 +78,28 @@ function text:draw()
|
|||||||
if self.alpha>0 then
|
if self.alpha>0 then
|
||||||
local c=self.color
|
local c=self.color
|
||||||
gc_setColor(c[1],c[2],c[3],self.alpha)
|
gc_setColor(c[1],c[2],c[3],self.alpha)
|
||||||
|
local w=self.obj:getWidth()
|
||||||
|
local k=min(self.lim/self.obj:getWidth(),1)
|
||||||
if self.align=='M'then
|
if self.align=='M'then
|
||||||
mDraw_X(self.obj,self.x,self.y)
|
gc_draw(self.obj,self.x,self.y,nil,k,1,w*.5,0)
|
||||||
elseif self.align=='L'then
|
elseif self.align=='L'then
|
||||||
gc_draw(self.obj,self.x,self.y)
|
gc_draw(self.obj,self.x,self.y,nil,k,1)
|
||||||
elseif self.align=='R'then
|
elseif self.align=='R'then
|
||||||
gc_draw(self.obj,self.x-self.obj:getWidth(),self.y)
|
gc_draw(self.obj,self.x,self.y,nil,k,1,w,0)
|
||||||
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[,lim][,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,
|
||||||
y= D.y,
|
y= D.y,
|
||||||
|
lim= D.lim or 1e99,
|
||||||
|
|
||||||
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 +148,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
|
||||||
@@ -148,9 +157,9 @@ function button:isAbove(x,y)
|
|||||||
local ATV=self.ATV
|
local ATV=self.ATV
|
||||||
return
|
return
|
||||||
x>self.x-ATV and
|
x>self.x-ATV and
|
||||||
y>self.y-ATV and
|
y>self.y and
|
||||||
x<self.x+self.w+2*ATV and
|
x<self.x+self.w+2*ATV and
|
||||||
y<self.y+self.h+2*ATV
|
y<self.y+self.h
|
||||||
end
|
end
|
||||||
function button:getCenter()
|
function button:getCenter()
|
||||||
return self.x+self.w*.5,self.y+self.h*.5
|
return self.x+self.w*.5,self.y+self.h*.5
|
||||||
@@ -171,45 +180,49 @@ function button:draw()
|
|||||||
|
|
||||||
--Button
|
--Button
|
||||||
gc_setColor(.15+r*.7,.15+g*.7,.15+b*.7,.9)
|
gc_setColor(.15+r*.7,.15+g*.7,.15+b*.7,.9)
|
||||||
gc_rectangle('fill',x-ATV,y-ATV,w+2*ATV,h+2*ATV,3)
|
gc_rectangle('fill',x-ATV,y,w+2*ATV,h,4)
|
||||||
|
gc_setLineWidth(2)
|
||||||
|
gc_setColor(.3+r*.7,.3+g*.7,.3+b*.7)
|
||||||
|
gc_rectangle('line',x-ATV,y,w+2*ATV,h,5)
|
||||||
if ATV>0 then
|
if ATV>0 then
|
||||||
gc_setLineWidth(2)
|
|
||||||
gc_setColor(.97,.97,.97,ATV*.125)
|
gc_setColor(.97,.97,.97,ATV*.125)
|
||||||
gc_rectangle('line',x-ATV+2,y-ATV+2,w+2*ATV-4,h+2*ATV-4,3)
|
gc_rectangle('line',x-ATV,y,w+2*ATV,h,3)
|
||||||
end
|
end
|
||||||
|
|
||||||
--Drawable
|
--Drawable
|
||||||
local obj=self.obj
|
local obj=self.obj
|
||||||
local y0=y+h*.5-ATV*.5
|
local ox,oy=obj:getWidth()*.5,obj:getHeight()*.5
|
||||||
|
local y0=y+h*.5
|
||||||
gc_setColor(1,1,1,.2+ATV*.05)
|
gc_setColor(1,1,1,.2+ATV*.05)
|
||||||
if self.align=='M'then
|
if self.align=='M'then
|
||||||
local x0=x+w*.5
|
local x0=x+w*.5
|
||||||
mDraw(obj,x0-1,y0-1)
|
local kx=obj:type()=='Text'and min(w/ox/2,1)or 1
|
||||||
mDraw(obj,x0-1,y0+1)
|
gc_draw(obj,x0-1,y0-1,nil,kx,1,ox,oy)
|
||||||
mDraw(obj,x0+1,y0-1)
|
gc_draw(obj,x0-1,y0+1,nil,kx,1,ox,oy)
|
||||||
mDraw(obj,x0+1,y0+1)
|
gc_draw(obj,x0+1,y0-1,nil,kx,1,ox,oy)
|
||||||
|
gc_draw(obj,x0+1,y0+1,nil,kx,1,ox,oy)
|
||||||
gc_setColor(r*.55,g*.55,b*.55)
|
gc_setColor(r*.55,g*.55,b*.55)
|
||||||
mDraw(obj,x0,y0)
|
gc_draw(obj,x0,y0,nil,kx,1,ox,oy)
|
||||||
elseif self.align=='L'then
|
elseif self.align=='L'then
|
||||||
local edge=self.edge
|
local edge=self.edge
|
||||||
mDraw_Y(obj,x+edge-1,y0-1)
|
gc_draw(obj,x+edge-1,y0-1-oy)
|
||||||
mDraw_Y(obj,x+edge-1,y0+1)
|
gc_draw(obj,x+edge-1,y0+1-oy)
|
||||||
mDraw_Y(obj,x+edge+1,y0-1)
|
gc_draw(obj,x+edge+1,y0-1-oy)
|
||||||
mDraw_Y(obj,x+edge+1,y0+1)
|
gc_draw(obj,x+edge+1,y0+1-oy)
|
||||||
gc_setColor(r*.55,g*.55,b*.55)
|
gc_setColor(r*.55,g*.55,b*.55)
|
||||||
mDraw_Y(obj,x+edge,y0)
|
gc_draw(obj,x+edge,y0-oy)
|
||||||
elseif self.align=='R'then
|
elseif self.align=='R'then
|
||||||
local x0=x+w-self.edge-obj:getWidth()
|
local x0=x+w-self.edge-ox*2
|
||||||
mDraw_Y(obj,x0-1,y0-1)
|
gc_draw(obj,x0-1,y0-1-oy)
|
||||||
mDraw_Y(obj,x0-1,y0+1)
|
gc_draw(obj,x0-1,y0+1-oy)
|
||||||
mDraw_Y(obj,x0+1,y0-1)
|
gc_draw(obj,x0+1,y0-1-oy)
|
||||||
mDraw_Y(obj,x0+1,y0+1)
|
gc_draw(obj,x0+1,y0+1-oy)
|
||||||
gc_setColor(r*.55,g*.55,b*.55)
|
gc_setColor(r*.55,g*.55,b*.55)
|
||||||
mDraw_Y(obj,x0,y0)
|
gc_draw(obj,x0,y0-oy)
|
||||||
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)
|
||||||
@@ -217,15 +230,15 @@ function button:press(_,_,k)
|
|||||||
SYSFX.newRectRipple(
|
SYSFX.newRectRipple(
|
||||||
6,
|
6,
|
||||||
self.x-ATV,
|
self.x-ATV,
|
||||||
self.y-ATV-WIDGET.scrollPos,
|
self.y-WIDGET.scrollPos,
|
||||||
self.w+2*ATV,
|
self.w+2*ATV,
|
||||||
self.h+2*ATV
|
self.h
|
||||||
)
|
)
|
||||||
if self.sound then
|
if self.sound then
|
||||||
SFX.play('button')
|
SFX.play(self.sound)
|
||||||
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][,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,13 +259,21 @@ 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,
|
code= D.code or NULL,
|
||||||
code= D.code,
|
|
||||||
hideF=D.hideF,
|
hideF=D.hideF,
|
||||||
hide= D.hide,
|
hide= D.hide,
|
||||||
}
|
}
|
||||||
|
if D.sound==false then
|
||||||
|
_.sound=false
|
||||||
|
elseif type(D.sound)=='string'then
|
||||||
|
_.sound=D.sound
|
||||||
|
else
|
||||||
|
_.sound='button'
|
||||||
|
end
|
||||||
|
|
||||||
for k,v in next,button do _[k]=v end
|
for k,v in next,button do _[k]=v end
|
||||||
setmetatable(_,widgetMetatable)
|
setmetatable(_,widgetMetatable)
|
||||||
return _
|
return _
|
||||||
@@ -268,7 +289,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
|
||||||
@@ -298,48 +319,54 @@ function key:draw()
|
|||||||
local align=self.align
|
local align=self.align
|
||||||
local r,g,b=c[1],c[2],c[3]
|
local r,g,b=c[1],c[2],c[3]
|
||||||
|
|
||||||
--Frame
|
|
||||||
if not self.noFrame then
|
|
||||||
gc_setColor(.2+r*.8,.2+g*.8,.2+b*.8,.7)
|
|
||||||
gc_setLineWidth(2)
|
|
||||||
gc_rectangle('line',x,y,w,h,3)
|
|
||||||
end
|
|
||||||
|
|
||||||
--Fill
|
--Fill
|
||||||
if self.fShade then
|
if self.fShade then
|
||||||
gc_setColor(r,g,b,ATV*.25)
|
gc_setColor(r,g,b,ATV*.25)
|
||||||
if align=='M'then
|
if align=='M'then
|
||||||
mDraw(self.fShade,x+w*.5,y+h*.5)
|
gc_draw(self.fShade,x+w*.5-self.fShade:getWidth()*.5,y+h*.5-self.fShade:getHeight()*.5)
|
||||||
elseif align=='L'then
|
elseif align=='L'then
|
||||||
mDraw_Y(self.fShade,x+self.edge,y+h*.5)
|
gc_draw(self.fShade,x+self.edge,y+h*.5-self.fShade:getHeight()*.5)
|
||||||
elseif align=='R'then
|
elseif align=='R'then
|
||||||
mDraw_Y(self.fShade,x+w-self.edge-self.fShade:getWidth(),y+h*.5)
|
gc_draw(self.fShade,x+w-self.edge-self.fShade:getWidth(),y+h*.5-self.fShade:getHeight()*.5)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
--Background
|
||||||
|
gc_setColor(0,0,0,.3)
|
||||||
|
gc_rectangle('fill',x,y,w,h,4)
|
||||||
|
|
||||||
|
--Frame
|
||||||
|
gc_setColor(.2+r*.8,.2+g*.8,.2+b*.8,.7)
|
||||||
|
gc_setLineWidth(2)
|
||||||
|
gc_rectangle('line',x,y,w,h,3)
|
||||||
|
|
||||||
|
--Shade
|
||||||
gc_setColor(1,1,1,ATV*.05)
|
gc_setColor(1,1,1,ATV*.05)
|
||||||
gc_rectangle('fill',x,y,w,h,3)
|
gc_rectangle('fill',x,y,w,h,3)
|
||||||
end
|
end
|
||||||
|
|
||||||
--Drawable
|
--Drawable
|
||||||
|
local obj=self.obj
|
||||||
|
local ox,oy=obj:getWidth()*.5,obj:getHeight()*.5
|
||||||
gc_setColor(r,g,b)
|
gc_setColor(r,g,b)
|
||||||
if align=='M'then
|
if align=='M'then
|
||||||
mDraw(self.obj,x+w*.5,y+h*.5)
|
local kx=obj:type()=='Text'and min(w/ox/2,1)or 1
|
||||||
|
gc_draw(obj,x+w*.5,y+h*.5,nil,kx,1,ox,oy)
|
||||||
elseif align=='L'then
|
elseif align=='L'then
|
||||||
mDraw_Y(self.obj,x+self.edge,y+h*.5)
|
gc_draw(obj,x+self.edge,y-oy+h*.5)
|
||||||
elseif align=='R'then
|
elseif align=='R'then
|
||||||
mDraw_Y(self.obj,x+w-self.edge-self.obj:getWidth(),y+h*.5)
|
gc_draw(obj,x+w-self.edge-ox*2,y-oy+h*.5)
|
||||||
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)
|
||||||
if self.sound then
|
if self.sound then
|
||||||
SFX.play('key')
|
SFX.play(self.sound)
|
||||||
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][,color][,font=30][,fType][,sound][,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"_",
|
||||||
@@ -359,16 +386,22 @@ function WIDGET.newKey(D)--name,x,y,w[,h][,fText][,fShade][,noFrame][,color][,fo
|
|||||||
|
|
||||||
fText= D.fText,
|
fText= D.fText,
|
||||||
fShade= D.fShade,
|
fShade= D.fShade,
|
||||||
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,
|
||||||
sound= D.sound~=false,
|
fType= D.fType,
|
||||||
align= D.align or'M',
|
align= D.align or'M',
|
||||||
edge= D.edge or 0,
|
edge= D.edge or 0,
|
||||||
code= D.code,
|
code= D.code or NULL,
|
||||||
hideF= D.hideF,
|
hideF= D.hideF,
|
||||||
hide= D.hide,
|
hide= D.hide,
|
||||||
}
|
}
|
||||||
|
if D.sound==false then
|
||||||
|
_.sound=false
|
||||||
|
elseif type(D.sound)=='string'then
|
||||||
|
_.sound=D.sound
|
||||||
|
else
|
||||||
|
_.sound='key'
|
||||||
|
end
|
||||||
for k,v in next,key do _[k]=v end
|
for k,v in next,key do _[k]=v end
|
||||||
setmetatable(_,widgetMetatable)
|
setmetatable(_,widgetMetatable)
|
||||||
return _
|
return _
|
||||||
@@ -408,6 +441,10 @@ function switch:draw()
|
|||||||
local x,y=self.x,self.y
|
local x,y=self.x,self.y
|
||||||
local ATV=self.ATV
|
local ATV=self.ATV
|
||||||
|
|
||||||
|
--Background
|
||||||
|
gc_setColor(0,0,0,.3)
|
||||||
|
gc_rectangle('fill',x,y-25,50,50,4)
|
||||||
|
|
||||||
--Frame
|
--Frame
|
||||||
gc_setLineWidth(2)
|
gc_setLineWidth(2)
|
||||||
gc_setColor(1,1,1,.6+ATV*.1)
|
gc_setColor(1,1,1,.6+ATV*.1)
|
||||||
@@ -430,15 +467,15 @@ 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()
|
||||||
if self.sound then
|
if self.sound then
|
||||||
SFX.play('touch')
|
SFX.play(self.disp()and'check'or'uncheck')
|
||||||
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,9 +490,10 @@ 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 or NULL,
|
||||||
hideF=D.hideF,
|
hideF=D.hideF,
|
||||||
hide= D.hide,
|
hide= D.hide,
|
||||||
}
|
}
|
||||||
@@ -491,7 +529,7 @@ function slider:isAbove(x,y)
|
|||||||
return x>self.x-10 and x<self.x+self.w+10 and y>self.y-25 and y<self.y+25
|
return x>self.x-10 and x<self.x+self.w+10 and y>self.y-25 and y<self.y+25
|
||||||
end
|
end
|
||||||
function slider:getCenter()
|
function slider:getCenter()
|
||||||
return self.x+self.w*(self.pos/self.unit),self.y
|
return self.x+self.w*((self.pos-self.rangeL)/(self.rangeR-self.rangeL)),self.y
|
||||||
end
|
end
|
||||||
function slider:update(dt)
|
function slider:update(dt)
|
||||||
local ATV=self.ATV
|
local ATV=self.ATV
|
||||||
@@ -505,7 +543,7 @@ function slider:update(dt)
|
|||||||
if ATV>0 then self.ATV=max(ATV-dt*30,0)end
|
if ATV>0 then self.ATV=max(ATV-dt*30,0)end
|
||||||
end
|
end
|
||||||
if not self.hide then
|
if not self.hide then
|
||||||
self.pos=self.pos*.7+self.disp()*.3
|
self.pos=approach(self.pos,self.disp(),dt*26)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function slider:draw()
|
function slider:draw()
|
||||||
@@ -518,8 +556,8 @@ function slider:draw()
|
|||||||
--Units
|
--Units
|
||||||
if not self.smooth then
|
if not self.smooth then
|
||||||
gc_setLineWidth(2)
|
gc_setLineWidth(2)
|
||||||
for p=0,self.unit do
|
for p=self.rangeL,self.rangeR,self.unit do
|
||||||
local X=x+(x2-x)*p/self.unit
|
local X=x+(x2-x)*(p-self.rangeL)/(self.rangeR-self.rangeL)
|
||||||
gc_line(X,y+7,X,y-7)
|
gc_line(X,y+7,X,y-7)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -529,7 +567,7 @@ function slider:draw()
|
|||||||
gc_line(x,y,x2,y)
|
gc_line(x,y,x2,y)
|
||||||
|
|
||||||
--Block
|
--Block
|
||||||
local cx=x+(x2-x)*self.pos/self.unit
|
local cx=x+(x2-x)*(self.pos-self.rangeL)/(self.rangeR-self.rangeL)
|
||||||
local bx,by,bw,bh=cx-10-ATV*.5,y-16-ATV,20+ATV,32+2*ATV
|
local bx,by,bw,bh=cx-10-ATV*.5,y-16-ATV,20+ATV,32+2*ATV
|
||||||
gc_setColor(.8,.8,.8)
|
gc_setColor(.8,.8,.8)
|
||||||
gc_rectangle('fill',bx,by,bw,bh,3)
|
gc_rectangle('fill',bx,by,bw,bh,3)
|
||||||
@@ -564,13 +602,16 @@ end
|
|||||||
function slider:drag(x)
|
function slider:drag(x)
|
||||||
if not x then return end
|
if not x then return end
|
||||||
x=x-self.x
|
x=x-self.x
|
||||||
local p=self.disp()
|
local newPos=MATH.interval(x/self.w,0,1)
|
||||||
local P=x<0 and 0 or x>self.w and self.unit or x/self.w*self.unit
|
local newVal
|
||||||
if not self.smooth then
|
if not self.unit then
|
||||||
P=int(P+.5)
|
newVal=(1-newPos)*self.rangeL+newPos*self.rangeR
|
||||||
|
else
|
||||||
|
newVal=newPos*(self.rangeR-self.rangeL)
|
||||||
|
newVal=self.rangeL+newVal-newVal%self.unit
|
||||||
end
|
end
|
||||||
if p~=P then
|
if newVal~=self.disp()then
|
||||||
self.code(P)
|
self.code(newVal)
|
||||||
end
|
end
|
||||||
if self.change and timer()-self.lastTime>.5 then
|
if self.change and timer()-self.lastTime>.5 then
|
||||||
self.lastTime=timer()
|
self.lastTime=timer()
|
||||||
@@ -583,8 +624,8 @@ function slider:release(x)
|
|||||||
end
|
end
|
||||||
function slider:scroll(n)
|
function slider:scroll(n)
|
||||||
local p=self.disp()
|
local p=self.disp()
|
||||||
local u=self.smooth and .01 or 1
|
local u=self.unit or .01
|
||||||
local P=n==-1 and max(p-u,0)or min(p+u,self.unit)
|
local P=MATH.interval(p+u*n,self.rangeL,self.rangeR)
|
||||||
if p==P or not P then return end
|
if p==P or not P then return end
|
||||||
self.code(P)
|
self.code(P)
|
||||||
if self.change and timer()-self.lastTime>.18 then
|
if self.change and timer()-self.lastTime>.18 then
|
||||||
@@ -593,9 +634,15 @@ function slider:scroll(n)
|
|||||||
end
|
end
|
||||||
end
|
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][,axis][,smooth][,font=30][,fType][,change],disp[,show][,code],hide
|
||||||
|
if not D.axis then
|
||||||
|
D.axis={0,1,false}
|
||||||
|
D.smooth=true
|
||||||
|
elseif not D.axis[3]then
|
||||||
|
D.smooth=true
|
||||||
|
end
|
||||||
local _={
|
local _={
|
||||||
name= D.name or"_",
|
name= D.name or"_",
|
||||||
|
|
||||||
@@ -614,32 +661,30 @@ function WIDGET.newSlider(D)--name,x,y,w[,lim][,fText][,color][,unit][,smooth][,
|
|||||||
|
|
||||||
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,
|
||||||
unit= D.unit or 1,
|
rangeL=D.axis[1],
|
||||||
smooth=false,
|
rangeR=D.axis[2],
|
||||||
|
unit= D.axis[3],
|
||||||
|
smooth=D.smooth,
|
||||||
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 or NULL,
|
||||||
hideF= D.hideF,
|
hideF= D.hideF,
|
||||||
hide= D.hide,
|
hide= D.hide,
|
||||||
show= false,
|
show= false,
|
||||||
}
|
}
|
||||||
if D.smooth~=nil then
|
|
||||||
_.smooth=D.smooth
|
|
||||||
else
|
|
||||||
_.smooth=_.unit<=1
|
|
||||||
end
|
|
||||||
if D.show then
|
if D.show then
|
||||||
if type(D.show)=='function'then
|
if type(D.show)=='function'then
|
||||||
_.show=D.show
|
_.show=D.show
|
||||||
else
|
else
|
||||||
_.show=sliderShowFunc[D.show]
|
_.show=sliderShowFunc[D.show]
|
||||||
end
|
end
|
||||||
elseif D.show~=false then
|
elseif D.show~=false then--Use default if nil
|
||||||
if _.unit<=1 then
|
if _.unit and _.unit%1==0 then
|
||||||
_.show=sliderShowFunc.percent
|
|
||||||
else
|
|
||||||
_.show=sliderShowFunc.int
|
_.show=sliderShowFunc.int
|
||||||
|
else
|
||||||
|
_.show=sliderShowFunc.percent
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for k,v in next,slider do _[k]=v end
|
for k,v in next,slider do _[k]=v end
|
||||||
@@ -691,6 +736,10 @@ function selector:draw()
|
|||||||
local w=self.w
|
local w=self.w
|
||||||
local ATV=self.ATV
|
local ATV=self.ATV
|
||||||
|
|
||||||
|
--Background
|
||||||
|
gc_setColor(0,0,0,.3)
|
||||||
|
gc_rectangle('fill',x,y,w,60,4)
|
||||||
|
|
||||||
--Frame
|
--Frame
|
||||||
gc_setColor(1,1,1,.6+ATV*.1)
|
gc_setColor(1,1,1,.6+ATV*.1)
|
||||||
gc_setLineWidth(2)
|
gc_setLineWidth(2)
|
||||||
@@ -744,7 +793,7 @@ function selector:press(x)
|
|||||||
self.select=s
|
self.select=s
|
||||||
self.selText=self.list[s]
|
self.selText=self.list[s]
|
||||||
if self.sound then
|
if self.sound then
|
||||||
SFX.play('prerotate')
|
SFX.play('selector')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -764,14 +813,14 @@ function selector:scroll(n)
|
|||||||
self.select=s
|
self.select=s
|
||||||
self.selText=self.list[s]
|
self.selText=self.list[s]
|
||||||
if self.sound then
|
if self.sound then
|
||||||
SFX.play('prerotate')
|
SFX.play('selector')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function selector:arrowKey(k)
|
function selector: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.newSelector(D)--name,x,y,w[,fText][,color][,sound=true],list,disp,code,hide
|
function WIDGET.newSelector(D)--name,x,y,w[,fText][,color][,sound=true],list,disp[,code],hide
|
||||||
local _={
|
local _={
|
||||||
name= D.name or"_",
|
name= D.name or"_",
|
||||||
|
|
||||||
@@ -793,7 +842,7 @@ function WIDGET.newSelector(D)--name,x,y,w[,fText][,color][,sound=true],list,dis
|
|||||||
font= 30,
|
font= 30,
|
||||||
list= D.list,
|
list= D.list,
|
||||||
disp= D.disp,
|
disp= D.disp,
|
||||||
code= D.code,
|
code= D.code or NULL,
|
||||||
hideF=D.hideF,
|
hideF=D.hideF,
|
||||||
hide= D.hide,
|
hide= D.hide,
|
||||||
}
|
}
|
||||||
@@ -854,18 +903,24 @@ function inputBox:draw()
|
|||||||
local x,y,w,h=self.x,self.y,self.w,self.h
|
local x,y,w,h=self.x,self.y,self.w,self.h
|
||||||
local ATV=self.ATV
|
local ATV=self.ATV
|
||||||
|
|
||||||
gc_setColor(1,1,1,ATV*.08)
|
--Background
|
||||||
gc_rectangle('fill',x,y,w,h,3)
|
gc_setColor(0,0,0,.4)
|
||||||
|
gc_rectangle('fill',x,y,w,h,4)
|
||||||
|
|
||||||
|
--Highlight
|
||||||
|
gc_setColor(1,1,1,ATV*.08*(math.sin(TIME()*4.2)*.2+.8))
|
||||||
|
gc_rectangle('fill',x,y,w,h,4)
|
||||||
|
|
||||||
|
--Frame
|
||||||
gc_setColor(1,1,1)
|
gc_setColor(1,1,1)
|
||||||
gc_setLineWidth(3)
|
gc_setLineWidth(3)
|
||||||
gc_rectangle('line',x,y,w,h,3)
|
gc_rectangle('line',x,y,w,h,3)
|
||||||
|
|
||||||
--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)
|
gc_draw(self.obj,x-12-self.obj:getWidth(),y+h*.5-self.obj:getHeight()*.5)
|
||||||
end
|
end
|
||||||
if self.secret then
|
if self.secret then
|
||||||
y=y+h*.5-f*.2
|
y=y+h*.5-f*.2
|
||||||
@@ -892,21 +947,21 @@ end
|
|||||||
function inputBox:keypress(k)
|
function inputBox:keypress(k)
|
||||||
local t=self.value
|
local t=self.value
|
||||||
if #t>0 and EDITING==""then
|
if #t>0 and EDITING==""then
|
||||||
if k=="backspace"then
|
if k=='backspace'then
|
||||||
local p=#t
|
local p=#t
|
||||||
while t:byte(p)>=128 and t:byte(p)<192 do
|
while t:byte(p)>=128 and t:byte(p)<192 do
|
||||||
p=p-1
|
p=p-1
|
||||||
end
|
end
|
||||||
t=sub(t,1,p-1)
|
t=sub(t,1,p-1)
|
||||||
SFX.play('lock')
|
SFX.play('lock')
|
||||||
elseif k=="delete"then
|
elseif k=='delete'then
|
||||||
t=""
|
t=""
|
||||||
SFX.play('hold')
|
SFX.play('hold')
|
||||||
end
|
end
|
||||||
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 +977,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,
|
||||||
@@ -999,9 +1055,9 @@ function textBox:scroll(dir)
|
|||||||
self:drag(nil,nil,nil,-dir*self.lineH)
|
self:drag(nil,nil,nil,-dir*self.lineH)
|
||||||
end
|
end
|
||||||
function textBox:arrowKey(k)
|
function textBox:arrowKey(k)
|
||||||
if k=="up"then
|
if k=='up'then
|
||||||
self:scroll(-1)
|
self:scroll(-1)
|
||||||
elseif k=="down"then
|
elseif k=='down'then
|
||||||
self:scroll(-1)
|
self:scroll(-1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1013,8 +1069,8 @@ function textBox:draw()
|
|||||||
local lineH=self.lineH
|
local lineH=self.lineH
|
||||||
|
|
||||||
--Background
|
--Background
|
||||||
gc_setColor(0,0,0,.4)
|
gc_setColor(0,0,0,.3)
|
||||||
gc_rectangle('fill',x,y,w,h,3)
|
gc_rectangle('fill',x,y,w,h,4)
|
||||||
|
|
||||||
--Frame
|
--Frame
|
||||||
gc_setLineWidth(2)
|
gc_setLineWidth(2)
|
||||||
@@ -1022,7 +1078,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 +1110,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 +1132,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,
|
||||||
@@ -1153,7 +1210,7 @@ function listBox:press(x,y)
|
|||||||
if self.list[y]then
|
if self.list[y]then
|
||||||
if self.selected~=y then
|
if self.selected~=y then
|
||||||
self.selected=y
|
self.selected=y
|
||||||
SFX.play('click',.4)
|
SFX.play('selector',.8,0,12)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1176,6 +1233,14 @@ function listBox:arrowKey(dir)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
function listBox:select(i)
|
||||||
|
self.selected=i
|
||||||
|
if self.selected<int(self.scrollPos/self.lineH)+2 then
|
||||||
|
self:drag(nil,nil,nil,1e99)
|
||||||
|
elseif self.selected>int(self.scrollPos/self.lineH)+self.capacity-1 then
|
||||||
|
self:drag(nil,nil,nil,-1e99)
|
||||||
|
end
|
||||||
|
end
|
||||||
function listBox:draw()
|
function listBox:draw()
|
||||||
local x,y,w,h=self.x,self.y,self.w,self.h
|
local x,y,w,h=self.x,self.y,self.w,self.h
|
||||||
local list=self.list
|
local list=self.list
|
||||||
@@ -1186,6 +1251,10 @@ function listBox:draw()
|
|||||||
gc_push('transform')
|
gc_push('transform')
|
||||||
gc_translate(x,y)
|
gc_translate(x,y)
|
||||||
|
|
||||||
|
--Background
|
||||||
|
gc_setColor(0,0,0,.4)
|
||||||
|
gc_rectangle('fill',0,0,w,h,4)
|
||||||
|
|
||||||
--Frame
|
--Frame
|
||||||
gc_setColor(WIDGET.sel==self and COLOR.lN or COLOR.Z)
|
gc_setColor(WIDGET.sel==self and COLOR.lN or COLOR.Z)
|
||||||
gc_setLineWidth(2)
|
gc_setLineWidth(2)
|
||||||
@@ -1214,7 +1283,7 @@ end
|
|||||||
function listBox:getInfo()
|
function listBox:getInfo()
|
||||||
return("x=%d,y=%d,w=%d,h=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h)
|
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.newListBox(D)--name,x,y,w,h,lineH[,hideF][,hide][,drawF]
|
function WIDGET.newListBox(D)--name,x,y,w,h,lineH,drawF[,hideF][,hide]
|
||||||
local _={
|
local _={
|
||||||
name= D.name or"_",
|
name= D.name or"_",
|
||||||
|
|
||||||
@@ -1271,16 +1340,7 @@ function WIDGET.setWidgetList(list)
|
|||||||
for i=1,#list do
|
for i=1,#list do
|
||||||
list[i]:reset()
|
list[i]:reset()
|
||||||
end
|
end
|
||||||
if SCN.cur~='custom_field'then
|
onChange()
|
||||||
local colorList=THEME.getThemeColor()
|
|
||||||
if not colorList then return end
|
|
||||||
local rnd=math.random
|
|
||||||
for _,W in next,list do
|
|
||||||
if W.color and not W.fText then
|
|
||||||
W.color=colorList[rnd(#colorList)]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function WIDGET.setScrollHeight(height)
|
function WIDGET.setScrollHeight(height)
|
||||||
@@ -1373,59 +1433,6 @@ function WIDGET.release(x,y)
|
|||||||
W:release(x,y+WIDGET.scrollPos)
|
W:release(x,y+WIDGET.scrollPos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function WIDGET.keyPressed(k,isRep)
|
|
||||||
local W=WIDGET.sel
|
|
||||||
if k=="space"or k=="return"then
|
|
||||||
if not isRep then
|
|
||||||
WIDGET.press()
|
|
||||||
end
|
|
||||||
elseif k=="up"or k=="down"or k=="left"or k=="right"then
|
|
||||||
if kb.isDown("lshift","lalt","lctrl")then
|
|
||||||
--Control some widgets with arrowkeys when hold shift/ctrl/alt
|
|
||||||
if W and W.arrowKey then W:arrowKey(k)end
|
|
||||||
else
|
|
||||||
if not W then
|
|
||||||
for _,w in next,WIDGET.active do
|
|
||||||
if not w.hide and w.isAbove then
|
|
||||||
WIDGET.focus(w)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif W.getCenter then
|
|
||||||
local WX,WY=W:getCenter()
|
|
||||||
local dir=(k=="right"or k=="down")and 1 or -1
|
|
||||||
local tar
|
|
||||||
local minDist=1e99
|
|
||||||
local swap_xy=k=="up"or k=="down"
|
|
||||||
if swap_xy then WX,WY=WY,WX end--note that we do not swap them back later
|
|
||||||
for _,W1 in ipairs(WIDGET.active)do
|
|
||||||
if W~=W1 and W1.resCtr and not W1.hide then
|
|
||||||
local L=W1.resCtr
|
|
||||||
for j=1,#L,2 do
|
|
||||||
local x,y=L[j],L[j+1]
|
|
||||||
if swap_xy then x,y=y,x end--note that we do not swap them back later
|
|
||||||
local dist=(x-WX)*dir
|
|
||||||
if dist>10 then
|
|
||||||
dist=dist+abs(y-WY)*6.26
|
|
||||||
if dist<minDist then
|
|
||||||
minDist=dist
|
|
||||||
tar=W1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if tar then
|
|
||||||
WIDGET.focus(tar)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if W and W.keypress then
|
|
||||||
W:keypress(k)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function WIDGET.textinput(texts)
|
function WIDGET.textinput(texts)
|
||||||
local W=WIDGET.sel
|
local W=WIDGET.sel
|
||||||
if W and W.type=='inputBox'then
|
if W and W.type=='inputBox'then
|
||||||
@@ -1433,41 +1440,10 @@ function WIDGET.textinput(texts)
|
|||||||
WIDGET.sel.value=WIDGET.sel.value..texts
|
WIDGET.sel.value=WIDGET.sel.value..texts
|
||||||
SFX.play('touch')
|
SFX.play('touch')
|
||||||
else
|
else
|
||||||
SFX.play('finesseError',.3)
|
SFX.play('drop_cancel')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local keyMirror={
|
|
||||||
dpup="up",
|
|
||||||
dpdown="down",
|
|
||||||
dpleft="left",
|
|
||||||
dpright="right",
|
|
||||||
start="return",
|
|
||||||
back="escape",
|
|
||||||
}
|
|
||||||
function WIDGET.gamepadPressed(i)
|
|
||||||
if i=="start"then
|
|
||||||
WIDGET.press()
|
|
||||||
elseif i=="a"or i=="b"then
|
|
||||||
local W=WIDGET.sel
|
|
||||||
if W then
|
|
||||||
if W.type=='button'or W.type=='key'then
|
|
||||||
WIDGET.press()
|
|
||||||
elseif W.type=='slider'then
|
|
||||||
local p=W.disp()
|
|
||||||
local P=i=="left"and(p>0 and p-1)or p<W.unit and p+1
|
|
||||||
if p==P or not P then return end
|
|
||||||
W.code(P)
|
|
||||||
if W.change and timer()-W.lastTime>.18 then
|
|
||||||
W.lastTime=timer()
|
|
||||||
W.change()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif i=="dpup"or i=="dpdown"or i=="dpleft"or i=="dpright"then
|
|
||||||
WIDGET.keyPressed(keyMirror[i])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function WIDGET.update(dt)
|
function WIDGET.update(dt)
|
||||||
for _,W in next,WIDGET.active do
|
for _,W in next,WIDGET.active do
|
||||||
|
|||||||
148
main.lua
@@ -23,14 +23,14 @@ local fs=love.filesystem
|
|||||||
VERSION=require"version"
|
VERSION=require"version"
|
||||||
TIME=love.timer.getTime
|
TIME=love.timer.getTime
|
||||||
YIELD=coroutine.yield
|
YIELD=coroutine.yield
|
||||||
SYSTEM=love.system.getOS()
|
SYSTEM=love.system.getOS()if SYSTEM=='OS X'then SYSTEM='macOS'end
|
||||||
FNSF=SYSTEM:find'\79\83'--What does FNSF stand for? IDK so don't ask me lol
|
FNNS=SYSTEM:find'\79\83'--What does FNSF stand for? IDK so don't ask me lol
|
||||||
MOBILE=SYSTEM=='Android'or SYSTEM=='iOS'
|
MOBILE=SYSTEM=='Android'or SYSTEM=='iOS'
|
||||||
SAVEDIR=fs.getSaveDirectory()
|
SAVEDIR=fs.getSaveDirectory()
|
||||||
|
|
||||||
--Global Vars & Settings
|
--Global Vars & Settings
|
||||||
SFXPACKS={'chiptune'}
|
SFXPACKS={'chiptune'}
|
||||||
VOCPACKS={'miya','mono','xiaoya','miku'}
|
VOCPACKS={'miya',--[['mono',]]'xiaoya','miku'}
|
||||||
FIRSTLAUNCH=false
|
FIRSTLAUNCH=false
|
||||||
DAILYLAUNCH=false
|
DAILYLAUNCH=false
|
||||||
|
|
||||||
@@ -50,11 +50,30 @@ 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)
|
VOC.setDiversion(.62)
|
||||||
|
|
||||||
|
WIDGET.setOnChange(function()
|
||||||
|
if SCN.cur~='custom_field'then
|
||||||
|
local colorList=THEME.getThemeColor()
|
||||||
|
if not colorList then return end
|
||||||
|
local rnd=math.random
|
||||||
|
for _,W in next,SCN.scenes[SCN.cur].widgetList do
|
||||||
|
if W.color then
|
||||||
|
W.color=colorList[rnd(#colorList)]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
table.insert(_LOADTIMELIST_,("Load Zframework: %.3fs"):format(TIME()-_LOADTIME_))
|
table.insert(_LOADTIMELIST_,("Load Zframework: %.3fs"):format(TIME()-_LOADTIME_))
|
||||||
|
|
||||||
@@ -65,6 +84,9 @@ mStr=GC.mStr
|
|||||||
mText=GC.simpX
|
mText=GC.simpX
|
||||||
mDraw=GC.draw
|
mDraw=GC.draw
|
||||||
Snd=SFX.playSample
|
Snd=SFX.playSample
|
||||||
|
string.repD=STRING.repD
|
||||||
|
string.sArg=STRING.sArg
|
||||||
|
string.split=STRING.split
|
||||||
|
|
||||||
--Delete all naked files (from too old version)
|
--Delete all naked files (from too old version)
|
||||||
FILE.clear('')
|
FILE.clear('')
|
||||||
@@ -93,6 +115,7 @@ for _,v in next,fs.getDirectoryItems('parts/shaders')do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
THEME= require'parts.theme'
|
||||||
LINE= require'parts.line'
|
LINE= require'parts.line'
|
||||||
DATA= require'parts.data'
|
DATA= require'parts.data'
|
||||||
|
|
||||||
@@ -105,20 +128,17 @@ BOT= require'parts.bot'
|
|||||||
RSlist= require'parts.RSlist'DSCP=RSlist.TRS.centerPos
|
RSlist= require'parts.RSlist'DSCP=RSlist.TRS.centerPos
|
||||||
PLY= require'parts.player'
|
PLY= require'parts.player'
|
||||||
NETPLY= require'parts.netPlayer'
|
NETPLY= require'parts.netPlayer'
|
||||||
MODES= require'parts.modes'
|
MODETREE= require'parts.modeTree'
|
||||||
|
|
||||||
setmetatable(TEXTURE,{__index=function(self,k)
|
setmetatable(TEXTURE,{__index=function(self,k)
|
||||||
MES.new('warn',"No texture called: "..k)
|
MES.new('warn',"No texture called: "..k)
|
||||||
self[k]=love.graphics.newCanvas(1,1)
|
self[k]=PAPER
|
||||||
return self[k]
|
return self[k]
|
||||||
end})
|
end})
|
||||||
|
|
||||||
table.insert(_LOADTIMELIST_,("Load Parts: %.3fs"):format(TIME()-_LOADTIME_))
|
table.insert(_LOADTIMELIST_,("Load Parts: %.3fs"):format(TIME()-_LOADTIME_))
|
||||||
|
|
||||||
--Init Zframework
|
--Init Zframework
|
||||||
Z.setIfPowerInfo(function()
|
|
||||||
return SETTING.powerInfo and LOADED
|
|
||||||
end)
|
|
||||||
do--Z.setCursor
|
do--Z.setCursor
|
||||||
local normImg=GC.DO{16,16,
|
local normImg=GC.DO{16,16,
|
||||||
{'fCirc',8,8,4},
|
{'fCirc',8,8,4},
|
||||||
@@ -164,6 +184,9 @@ Z.setOnFnKeys({
|
|||||||
function()for k,v in next,_G do print(k,v)end end,
|
function()for k,v in next,_G do print(k,v)end end,
|
||||||
function()if love['_openConsole']then love['_openConsole']()end end,
|
function()if love['_openConsole']then love['_openConsole']()end end,
|
||||||
})
|
})
|
||||||
|
Z.setOnResize(function(w,_)
|
||||||
|
SHADER.warning:send('w',w*SCR.dpi)
|
||||||
|
end)
|
||||||
do--Z.setOnFocus
|
do--Z.setOnFocus
|
||||||
local function task_autoSoundOff()
|
local function task_autoSoundOff()
|
||||||
while true do
|
while true do
|
||||||
@@ -205,15 +228,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','-canSkip')or{},USER)
|
||||||
TABLE.cover (FILE.load('conf/unlock')or{},RANKS)
|
TABLE.cover (loadFile('conf/unlock','-canSkip')or{},RANKS)
|
||||||
TABLE.update(FILE.load('conf/settings')or{},SETTING)
|
TABLE.update(loadFile('conf/settings','-canSkip')or{},SETTING)
|
||||||
TABLE.coverR(FILE.load('conf/data')or{},STAT)
|
TABLE.coverR(loadFile('conf/data','-canSkip')or{},STAT)
|
||||||
TABLE.cover (FILE.load('conf/key')or{},KEY_MAP)
|
TABLE.cover (loadFile('conf/key','-canSkip')or{},KEY_MAP)
|
||||||
TABLE.cover (FILE.load('conf/virtualkey')or{},VK_ORG)
|
TABLE.cover (loadFile('conf/virtualkey','-json -canSkip')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 -canSkip')
|
||||||
if fieldData then
|
if fieldData then
|
||||||
fieldData=STRING.split(fieldData,"!")
|
fieldData=STRING.split(fieldData,"!")
|
||||||
for i=1,#fieldData do
|
for i=1,#fieldData do
|
||||||
@@ -222,15 +245,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 -canSkip')
|
||||||
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 -canSkip')
|
||||||
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','-canSkip')
|
||||||
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
|
||||||
@@ -248,14 +271,17 @@ IMG.init{
|
|||||||
speedLimit='media/image/mess/speedLimit.png',--Not used, for future C2-mode
|
speedLimit='media/image/mess/speedLimit.png',--Not used, for future C2-mode
|
||||||
pay1='media/image/mess/pay1.png',
|
pay1='media/image/mess/pay1.png',
|
||||||
pay2='media/image/mess/pay2.png',
|
pay2='media/image/mess/pay2.png',
|
||||||
|
drought='media/image/mess/drought.png',
|
||||||
|
|
||||||
miyaCH='media/image/characters/miya.png',
|
miyaCH1='media/image/characters/miya1.png',
|
||||||
miyaF1='media/image/characters/miya_f1.png',
|
miyaCH2='media/image/characters/miya2.png',
|
||||||
miyaF2='media/image/characters/miya_f2.png',
|
miyaCH3='media/image/characters/miya3.png',
|
||||||
miyaF3='media/image/characters/miya_f3.png',
|
miyaCH4='media/image/characters/miya4.png',
|
||||||
miyaF4='media/image/characters/miya_f4.png',
|
miyaHeart='media/image/characters/miya_heart.png',
|
||||||
|
miyaGlow='media/image/characters/miya_glow.png',
|
||||||
monoCH='media/image/characters/mono.png',
|
monoCH='media/image/characters/mono.png',
|
||||||
xiaoyaCH='media/image/characters/xiaoya.png',
|
xiaoyaCH='media/image/characters/xiaoya.png',
|
||||||
|
xiaoyaOmino='media/image/characters/xiaoya_Omino.png',
|
||||||
mikuCH='media/image/characters/miku.png',
|
mikuCH='media/image/characters/miku.png',
|
||||||
electric='media/image/characters/electric.png',
|
electric='media/image/characters/electric.png',
|
||||||
hbm='media/image/characters/hbm.png',
|
hbm='media/image/characters/hbm.png',
|
||||||
@@ -272,7 +298,7 @@ IMG.init{
|
|||||||
SKIN.load{
|
SKIN.load{
|
||||||
{name="crystal_scf",path='media/image/skin/crystal_scf.png'},
|
{name="crystal_scf",path='media/image/skin/crystal_scf.png'},
|
||||||
{name="matte_mrz",path='media/image/skin/matte_mrz.png'},
|
{name="matte_mrz",path='media/image/skin/matte_mrz.png'},
|
||||||
{name="shiny_cho",path='media/image/skin/shiny_cho.png'},
|
{name="shiny_chno",path='media/image/skin/shiny_chno.png'},
|
||||||
{name="contrast_mrz",path='media/image/skin/contrast_mrz.png'},
|
{name="contrast_mrz",path='media/image/skin/contrast_mrz.png'},
|
||||||
{name="polkadots_scf",path='media/image/skin/polkadots_scf.png'},
|
{name="polkadots_scf",path='media/image/skin/polkadots_scf.png'},
|
||||||
{name="toy_scf",path='media/image/skin/toy_scf.png'},
|
{name="toy_scf",path='media/image/skin/toy_scf.png'},
|
||||||
@@ -295,6 +321,7 @@ SKIN.load{
|
|||||||
{name="classic",path='media/image/skin/classic_unknown.png'},
|
{name="classic",path='media/image/skin/classic_unknown.png'},
|
||||||
{name="ball_shaw",path='media/image/skin/ball_shaw.png'},
|
{name="ball_shaw",path='media/image/skin/ball_shaw.png'},
|
||||||
{name="retro_notypey",path='media/image/skin/retro_notypey.png'},
|
{name="retro_notypey",path='media/image/skin/retro_notypey.png'},
|
||||||
|
{name="pixel_chno",path='media/image/skin/pixel_chno.png'},
|
||||||
{name="textbone_mrz",path='media/image/skin/textbone_mrz.png'},
|
{name="textbone_mrz",path='media/image/skin/textbone_mrz.png'},
|
||||||
{name="coloredbone_mrz",path='media/image/skin/coloredbone_mrz.png'},
|
{name="coloredbone_mrz",path='media/image/skin/coloredbone_mrz.png'},
|
||||||
{name="wtf",path='media/image/skin/wtf_mrz.png'},
|
{name="wtf",path='media/image/skin/wtf_mrz.png'},
|
||||||
@@ -310,11 +337,11 @@ SFX.init((function()--[Warning] Not loading files here, just get the list of sou
|
|||||||
end
|
end
|
||||||
return L
|
return L
|
||||||
end)())
|
end)())
|
||||||
BGM.init((function()
|
BGM.load((function()
|
||||||
local L={}
|
local L={}
|
||||||
for _,v in next,fs.getDirectoryItems('media/music')do
|
for _,v in next,fs.getDirectoryItems('media/music')do
|
||||||
if isSafeFile('media/music/'..v,"Dangerous file : %SAVE%/media/music/"..v)then
|
if isSafeFile('media/music/'..v,"Dangerous file : %SAVE%/media/music/"..v)then
|
||||||
table.insert(L,{name=v:sub(1,-5),path='media/music/'..v})
|
L[v:sub(1,-5)]='media/music/'..v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return L
|
return L
|
||||||
@@ -333,12 +360,13 @@ VOC.init{
|
|||||||
LANG.init('zh',
|
LANG.init('zh',
|
||||||
{
|
{
|
||||||
zh=require'parts.language.lang_zh',
|
zh=require'parts.language.lang_zh',
|
||||||
zh_full=require'parts.language.lang_zh_full',
|
|
||||||
zh_trad=require'parts.language.lang_zh_trad',
|
zh_trad=require'parts.language.lang_zh_trad',
|
||||||
|
zh_full=require'parts.language.lang_zh_full',
|
||||||
en=require'parts.language.lang_en',
|
en=require'parts.language.lang_en',
|
||||||
fr=require'parts.language.lang_fr',
|
fr=require'parts.language.lang_fr',
|
||||||
es=require'parts.language.lang_es',
|
es=require'parts.language.lang_es',
|
||||||
pt=require'parts.language.lang_pt',
|
pt=require'parts.language.lang_pt',
|
||||||
|
id=require'parts.language.lang_id',
|
||||||
zh_grass=require'parts.language.lang_zh_grass',
|
zh_grass=require'parts.language.lang_zh_grass',
|
||||||
zh_yygq=require'parts.language.lang_yygq',
|
zh_yygq=require'parts.language.lang_yygq',
|
||||||
symbol=require'parts.language.lang_symbol',
|
symbol=require'parts.language.lang_symbol',
|
||||||
@@ -373,6 +401,7 @@ for _,v in next,fs.getDirectoryItems('parts/backgrounds')do
|
|||||||
BG.add(name,require('parts.backgrounds.'..name))
|
BG.add(name,require('parts.backgrounds.'..name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
BG.remList('none')BG.remList('gray')BG.remList('custom')
|
||||||
--Load scene files from SOURCE ONLY
|
--Load scene files from SOURCE ONLY
|
||||||
for _,v in next,fs.getDirectoryItems('parts/scenes')do
|
for _,v in next,fs.getDirectoryItems('parts/scenes')do
|
||||||
if isSafeFile('parts/scenes/'..v)then
|
if isSafeFile('parts/scenes/'..v)then
|
||||||
@@ -381,24 +410,6 @@ for _,v in next,fs.getDirectoryItems('parts/scenes')do
|
|||||||
LANG.addScene(sceneName)
|
LANG.addScene(sceneName)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
--Load mode files
|
|
||||||
for i=1,#MODES do
|
|
||||||
local m=MODES[i]--Mode template
|
|
||||||
if isSafeFile('parts/modes/'..m.name)then
|
|
||||||
TABLE.complete(require('parts.modes.'..m.name),MODES[i])
|
|
||||||
MODES[m.name],MODES[i]=MODES[i]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for _,v in next,fs.getDirectoryItems('parts/modes')do
|
|
||||||
if isSafeFile('parts/modes/'..v)and not MODES[v:sub(1,-5)]then
|
|
||||||
local M={name=v:sub(1,-5)}
|
|
||||||
local modeData=require('parts.modes.'..M.name)
|
|
||||||
if modeData.env then
|
|
||||||
TABLE.complete(modeData,M)
|
|
||||||
MODES[M.name]=M
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(_LOADTIMELIST_,("Load Files: %.3fs"):format(TIME()-_LOADTIME_))
|
table.insert(_LOADTIMELIST_,("Load Files: %.3fs"):format(TIME()-_LOADTIME_))
|
||||||
|
|
||||||
@@ -407,7 +418,6 @@ do
|
|||||||
local needSave
|
local needSave
|
||||||
|
|
||||||
if not fs.getInfo('conf/data')then
|
if not fs.getInfo('conf/data')then
|
||||||
FIRSTLAUNCH=true
|
|
||||||
needSave=true
|
needSave=true
|
||||||
end
|
end
|
||||||
if type(STAT.version)~='number'then
|
if type(STAT.version)~='number'then
|
||||||
@@ -439,7 +449,6 @@ do
|
|||||||
if RANKS.tsd_u then
|
if RANKS.tsd_u then
|
||||||
RANKS.tsd_u=0
|
RANKS.tsd_u=0
|
||||||
end
|
end
|
||||||
needSave=true
|
|
||||||
end
|
end
|
||||||
if STAT.version==1601 then
|
if STAT.version==1601 then
|
||||||
RANKS.round_e=nil
|
RANKS.round_e=nil
|
||||||
@@ -453,6 +462,13 @@ do
|
|||||||
fs.remove('record/round_l.rec')
|
fs.remove('record/round_l.rec')
|
||||||
fs.remove('record/round_u.rec')
|
fs.remove('record/round_u.rec')
|
||||||
end
|
end
|
||||||
|
if STAT.version<1700 and SETTING.dascut<5 then
|
||||||
|
SETTING.dascut=SETTING.dascut+1
|
||||||
|
needSave=true
|
||||||
|
end
|
||||||
|
if SETTING.vocPack=='mono'then
|
||||||
|
SETTING.vocPack='miya'
|
||||||
|
end
|
||||||
if RANKS.stack_e then
|
if RANKS.stack_e then
|
||||||
RANKS.stack_e=nil
|
RANKS.stack_e=nil
|
||||||
RANKS.stack_h=nil
|
RANKS.stack_h=nil
|
||||||
@@ -477,6 +493,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
|
||||||
@@ -504,6 +524,9 @@ do
|
|||||||
if type(SETTING.skinSet)=='number'then SETTING.skinSet='crystal_scf'end
|
if type(SETTING.skinSet)=='number'then SETTING.skinSet='crystal_scf'end
|
||||||
if not TABLE.find({8,10,13,17,22,29,37,47,62,80,100},SETTING.frameMul)then SETTING.frameMul=100 end
|
if not TABLE.find({8,10,13,17,22,29,37,47,62,80,100},SETTING.frameMul)then SETTING.frameMul=100 end
|
||||||
if SETTING.cv then SETTING.vocPack,SETTING.cv=SETTING.cv end
|
if SETTING.cv then SETTING.vocPack,SETTING.cv=SETTING.cv end
|
||||||
|
if type(SETTING.bg)~='string'then SETTING.bg='on'end
|
||||||
|
if SETTING.skin[18]==10 then SETTING.skin[18]=4 end
|
||||||
|
if SETTING.reTime>3 or SETTING.reTime<.5 then SETTING.reTime=2 end
|
||||||
if RANKS.infinite then RANKS.infinite=0 end
|
if RANKS.infinite then RANKS.infinite=0 end
|
||||||
if RANKS.infinite_dig then RANKS.infinite_dig=0 end
|
if RANKS.infinite_dig then RANKS.infinite_dig=0 end
|
||||||
if not RANKS.sprint_10l then RANKS.sprint_10l=0 end
|
if not RANKS.sprint_10l then RANKS.sprint_10l=0 end
|
||||||
@@ -514,26 +537,8 @@ do
|
|||||||
if type(name)=='number'or type(rank)~='number'then
|
if type(name)=='number'or type(rank)~='number'then
|
||||||
RANKS[name]=nil
|
RANKS[name]=nil
|
||||||
needSave=true
|
needSave=true
|
||||||
else
|
|
||||||
local M=MODES[name]
|
|
||||||
if M and M.unlock and rank>0 then
|
|
||||||
for _,unlockName in next,M.unlock do
|
|
||||||
if not RANKS[unlockName]then
|
|
||||||
RANKS[unlockName]=0
|
|
||||||
needSave=true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not(M and M.x)then
|
|
||||||
RANKS[name]=nil
|
|
||||||
needSave=true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not MODES[STAT.lastPlay]then
|
|
||||||
STAT.lastPlay='sprint_10l'
|
|
||||||
needSave=true
|
|
||||||
end
|
|
||||||
|
|
||||||
if needSave then
|
if needSave then
|
||||||
saveStats()
|
saveStats()
|
||||||
@@ -543,7 +548,8 @@ do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--First start for phones
|
--First start
|
||||||
|
FIRSTLAUNCH=STAT.run==0
|
||||||
if FIRSTLAUNCH and MOBILE then
|
if FIRSTLAUNCH and MOBILE then
|
||||||
SETTING.VKSwitch=true
|
SETTING.VKSwitch=true
|
||||||
SETTING.powerInfo=true
|
SETTING.powerInfo=true
|
||||||
@@ -551,7 +557,7 @@ if FIRSTLAUNCH and MOBILE then
|
|||||||
end
|
end
|
||||||
|
|
||||||
--Apply system setting
|
--Apply system setting
|
||||||
applyAllSettings()
|
applySettings()
|
||||||
|
|
||||||
--Load replays
|
--Load replays
|
||||||
for _,fileName in next,fs.getDirectoryItems('replay')do
|
for _,fileName in next,fs.getDirectoryItems('replay')do
|
||||||
@@ -629,9 +635,9 @@ if TABLE.find(arg,'--test')then
|
|||||||
TASK.new(function()
|
TASK.new(function()
|
||||||
while true do
|
while true do
|
||||||
YIELD()
|
YIELD()
|
||||||
if Z.errData[1]then break end
|
if Z.getErr(1)then break end
|
||||||
end
|
end
|
||||||
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")
|
LOG("\27[91m\27[1mAutomatic Test Failed :(\27[0m\nThe error message is:\n"..table.concat(Z.getErr(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/effect/chiptune/back.ogg
Normal file
BIN
media/effect/chiptune/check.ogg
Normal file
BIN
media/effect/chiptune/selector.ogg
Normal file
BIN
media/effect/chiptune/uncheck.ogg
Normal file
|
Before Width: | Height: | Size: 74 KiB |
BIN
media/image/characters/miya1.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
media/image/characters/miya2.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
media/image/characters/miya3.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
media/image/characters/miya4.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
media/image/characters/miya_glow.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
media/image/characters/miya_heart.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
BIN
media/image/characters/xiaoya_Omino.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 552 B |
|
Before Width: | Height: | Size: 534 B |
|
Before Width: | Height: | Size: 603 B |
|
Before Width: | Height: | Size: 483 B |
|
Before Width: | Height: | Size: 324 B |
|
Before Width: | Height: | Size: 275 B |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 283 B |
|
Before Width: | Height: | Size: 489 B |
|
Before Width: | Height: | Size: 272 B |
|
Before Width: | Height: | Size: 338 B |
|
Before Width: | Height: | Size: 403 B |
|
Before Width: | Height: | Size: 434 B |
|
Before Width: | Height: | Size: 464 B |
|
Before Width: | Height: | Size: 347 B |
|
Before Width: | Height: | Size: 395 B |
|
Before Width: | Height: | Size: 457 B |
|
Before Width: | Height: | Size: 1.2 KiB |
BIN
media/image/skin/pixel_chno.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 41 KiB |
BIN
media/music/lounge.ogg
Normal file
BIN
media/music/malate.ogg
Normal file
@@ -97,12 +97,12 @@ do
|
|||||||
{131,2,2, 0, 0,0},{131,2,2,-1,-1,0},{131,2,2,-1, 0,0},--S
|
{131,2,2, 0, 0,0},{131,2,2,-1,-1,0},{131,2,2,-1, 0,0},--S
|
||||||
{131,1,2,-1, 0,0},{131,1,2, 0,-1,0},{131,1,2, 0, 0,0},--Z(misOrder)
|
{131,1,2,-1, 0,0},{131,1,2, 0,-1,0},{131,1,2, 0, 0,0},--Z(misOrder)
|
||||||
{313,2,2, 0, 0,0},{313,2,2,-1,-1,0},{313,2,2,-1, 0,0},--S(misOrder)
|
{313,2,2, 0, 0,0},{313,2,2,-1,-1,0},{313,2,2,-1, 0,0},--S(misOrder)
|
||||||
{331,3,2, 0,-1,0},--J(farDown)
|
{331,3,2, 0,-1,1},--J(farDown)
|
||||||
{113,4,2,-1,-1,0},--L(farDown)
|
{113,4,2,-1,-1,1},--L(farDown)
|
||||||
{113,3,2,-1,-1,0},{113,3,0, 0, 0,0},--J
|
{113,3,2,-1,-1,0},{113,3,0, 0, 0,0},--J
|
||||||
{331,4,2, 0,-1,0},{331,4,0,-1, 0,0},--L
|
{331,4,2, 0,-1,0},{331,4,0,-1, 0,0},--L
|
||||||
{222,7,2,-1, 0,2},{222,7,2,-2, 0,2},{222,7,2, 0, 0,2},--I
|
|
||||||
{222,7,0,-1, 1,1},{222,7,0,-2, 1,1},{222,7,0, 0, 1,1},--I(high)
|
{222,7,0,-1, 1,1},{222,7,0,-2, 1,1},{222,7,0, 0, 1,1},--I(high)
|
||||||
|
{222,7,2,-1, 0,2},{222,7,2,-2, 0,2},{222,7,2, 0, 0,2},--I(low)
|
||||||
{121,6,0, 1,-1,2},{112,6,0, 2,-1,2},{122,6,0, 1,-2,2},--O
|
{121,6,0, 1,-1,2},{112,6,0, 2,-1,2},{122,6,0, 1,-2,2},--O
|
||||||
{323,6,0,-1,-1,2},{332,6,0,-2,-1,2},{322,6,0,-1,-2,2},--O
|
{323,6,0,-1,-1,2},{332,6,0,-2,-1,2},{322,6,0,-1,-2,2},--O
|
||||||
}--{keys, ID, dir, dx, dy, freeLevel (0=immovable, 1=U/D-immovable, 2=free)}
|
}--{keys, ID, dir, dx, dy, freeLevel (0=immovable, 1=U/D-immovable, 2=free)}
|
||||||
@@ -204,6 +204,7 @@ do
|
|||||||
P.spinLast=2
|
P.spinLast=2
|
||||||
P.stat.rotate=P.stat.rotate+1
|
P.stat.rotate=P.stat.rotate+1
|
||||||
P:freshBlock('move')
|
P:freshBlock('move')
|
||||||
|
C.spinSeq=nil
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -304,8 +305,8 @@ do
|
|||||||
[10]={'+0+0','+0+1','+1+0','+0-2','+1-2'},
|
[10]={'+0+0','+0+1','+1+0','+0-2','+1-2'},
|
||||||
[03]={'+0+0','+0-1','+0+1','+0+2'},
|
[03]={'+0+0','+0-1','+0+1','+0+2'},
|
||||||
[30]={'+0+0','+0-1','+0+1','+0-2'},
|
[30]={'+0+0','+0-1','+0+1','+0-2'},
|
||||||
[12]={'+0+0','+0-1','+0+1'},
|
[12]={'+0+0','+0-1','+0+1','+0+2'},
|
||||||
[21]={'+0+0','+0-1','+0-2'},
|
[21]={'+0+0','+0-1','+0-2','+0-2'},
|
||||||
[32]={'+0+0','+1+0','-1+0'},
|
[32]={'+0+0','+1+0','-1+0'},
|
||||||
[23]={'+0+0','-1+0','+1+0'},
|
[23]={'+0+0','-1+0','+1+0'},
|
||||||
[02]={'+0+0','-1+1','+1-1'},
|
[02]={'+0+0','-1+1','+1-1'},
|
||||||
@@ -375,8 +376,8 @@ do
|
|||||||
},--R
|
},--R
|
||||||
false,--Y
|
false,--Y
|
||||||
{
|
{
|
||||||
[01]={'+0+0','-1+0','-1+1','+0+1','+1+0','-1+2','-2+0','+0-2'},
|
[01]={'+0+0','-1+0','-1+1','+0+1','+1+0','+1+1','-1+2','-2+0','+0-2'},
|
||||||
[10]={'+0+0','+1+0','-1+0','+0-1','+1-1','+1-2','+2+0','+0+2'},
|
[10]={'+0+0','+1+0','-1+0','+0-1','-1-1','+1-1','+1-2','+2+0','+0+2'},
|
||||||
[03]={'+0+0','-1+0','+1-1','+0-2','+0-3','+1+0','+1-2','+1-3','+0+1','-1+1'},
|
[03]={'+0+0','-1+0','+1-1','+0-2','+0-3','+1+0','+1-2','+1-3','+0+1','-1+1'},
|
||||||
[30]={'+0+0','-1+0','+1-1','+1-2','+1+0','+0-2','+1-3','-1+2','+0+3','-1+3'},
|
[30]={'+0+0','-1+0','+1-1','+1-2','+1+0','+0-2','+1-3','-1+2','+0+3','-1+3'},
|
||||||
[12]={'+0+0','-1+0','+1-1','-1-1','+1-2','+1+0','+0-2','+1-3','-1+2','+0+3','-1+3'},
|
[12]={'+0+0','-1+0','+1-1','-1-1','+1-2','+1+0','+0-2','+1-3','-1+2','+0+3','-1+3'},
|
||||||
@@ -761,6 +762,68 @@ do
|
|||||||
ARS_Z.kickTable[25]=upSet
|
ARS_Z.kickTable[25]=upSet
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local DRS_weak
|
||||||
|
do
|
||||||
|
local centerPos=TABLE.copy(defaultCenterPos)
|
||||||
|
centerPos[1]={[0]={1,1},{1,0},{1,1},{1,1}}--Z
|
||||||
|
centerPos[2]={[0]={1,1},{1,0},{1,1},{1,1}}--S
|
||||||
|
centerPos[3]={[0]={1,1},{1,0},{1,1},{1,1}}--L
|
||||||
|
centerPos[4]={[0]={1,1},{1,0},{1,1},{1,1}}--J
|
||||||
|
centerPos[5]={[0]={1,1},{1,0},{1,1},{1,1}}--T
|
||||||
|
centerPos[7]={[0]={.5,1.5},{1.5,-.5},{.5,1.5},{1.5,.5}}--I
|
||||||
|
centerPos[10]={[0]={1,1},{1,0},{1,1},{1,0}}--P
|
||||||
|
centerPos[11]={[0]={1,1},{1,1},{1,1},{1,1}}--Q
|
||||||
|
centerPos[15]={[0]={1,1},{1,0},{1,1},{1,1}}--U
|
||||||
|
centerPos[16]={[0]={1,1},{1,1},{1,1},{1,1}}--V
|
||||||
|
centerPos[19]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--J5
|
||||||
|
centerPos[20]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--L5
|
||||||
|
centerPos[21]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--R
|
||||||
|
centerPos[22]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--Y
|
||||||
|
centerPos[23]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--N
|
||||||
|
centerPos[24]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--H
|
||||||
|
centerPos[26]={[0]={0,1},{0,0},{0,1},{0,0}}--I3
|
||||||
|
centerPos[28]={[0]={0,1},{0,0},{0,1},{0,0}}--I2
|
||||||
|
|
||||||
|
local L={'+0+0','-1+0','+1+0','+0-1','-1-1','+1-1'}
|
||||||
|
local R={'+0+0','+1+0','-1+0','+0-1','+1-1','-1-1'}
|
||||||
|
|
||||||
|
local Z={
|
||||||
|
[01]=R,[10]=L,[03]=L,[30]=R,
|
||||||
|
[12]=R,[21]=L,[32]=L,[23]=R,
|
||||||
|
[02]=R,[20]=L,[13]=L,[31]=R,
|
||||||
|
}
|
||||||
|
local S=_reflect(Z)
|
||||||
|
|
||||||
|
DRS_weak={
|
||||||
|
centerTex=GC.DO{10,10,
|
||||||
|
{'setLW',2},
|
||||||
|
{'dRect',1,1,8,8},
|
||||||
|
{'fRect',3,3,4,4},
|
||||||
|
},
|
||||||
|
centerPos=centerPos,
|
||||||
|
kickTable={
|
||||||
|
Z,S,--Z,S
|
||||||
|
Z,S,--J,L
|
||||||
|
Z,--T
|
||||||
|
noKickSet,--O
|
||||||
|
Z,--I
|
||||||
|
|
||||||
|
Z,S,--Z5,S5
|
||||||
|
Z,S,--P,Q
|
||||||
|
Z,S,--F,E
|
||||||
|
Z,Z,Z,Z,--T5,U,V,W
|
||||||
|
noKickSet,--X
|
||||||
|
Z,S,--J5,L5
|
||||||
|
Z,S,--R,Y
|
||||||
|
Z,S,--N,H
|
||||||
|
Z,--I5
|
||||||
|
|
||||||
|
Z,Z,--I3,C
|
||||||
|
Z,Z,--I2,O1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
local ASC
|
local ASC
|
||||||
do
|
do
|
||||||
local L={'+0+0','+1+0','+0-1','+1-1','+0-2','+1-2','+2+0','+2-1','+2-2','-1+0','-1-1','+0+1','+1+1','+2+1','-1-2','-2+0','+0+2','+1+2','+2+2','-2-1','-2-2'}
|
local L={'+0+0','+1+0','+0-1','+1-1','+0-2','+1-2','+2+0','+2-1','+2-2','-1+0','-1-1','+0+1','+1+1','+2+1','-1-2','-2+0','+0+2','+1+2','+2+2','-2-1','-2-2'}
|
||||||
@@ -934,6 +997,7 @@ local RSlist={
|
|||||||
SRS_X=SRS_X,
|
SRS_X=SRS_X,
|
||||||
BiRS=BiRS,
|
BiRS=BiRS,
|
||||||
ARS_Z=ARS_Z,
|
ARS_Z=ARS_Z,
|
||||||
|
DRS_weak=DRS_weak,
|
||||||
ASC=ASC,
|
ASC=ASC,
|
||||||
ASC_plus=ASC_plus,
|
ASC_plus=ASC_plus,
|
||||||
C2=C2,
|
C2=C2,
|
||||||
|
|||||||
31
parts/backgrounds/custom.lua
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
--Secret custom background
|
||||||
|
local gc_clear,gc_setColor=love.graphics.clear,love.graphics.setColor
|
||||||
|
local back={}
|
||||||
|
|
||||||
|
local image=false
|
||||||
|
local alpha=.26
|
||||||
|
|
||||||
|
local mx,my,k
|
||||||
|
|
||||||
|
function back.init()
|
||||||
|
back.resize()
|
||||||
|
end
|
||||||
|
function back.resize()
|
||||||
|
mx,my=SCR.w*.5,SCR.h*.5
|
||||||
|
if image then
|
||||||
|
k=math.max(SCR.w/image:getWidth(),SCR.h/image:getHeight())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function back.draw()
|
||||||
|
gc_clear(.1,.1,.1)
|
||||||
|
if image then
|
||||||
|
gc_setColor(1,1,1,alpha)
|
||||||
|
mDraw(image,mx,my,nil,k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function back.event(a,img)
|
||||||
|
if a then alpha=a end
|
||||||
|
if img then image=img end
|
||||||
|
back.resize()
|
||||||
|
end
|
||||||
|
return back
|
||||||
11
parts/backgrounds/gray.lua
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
--Customizable grey background
|
||||||
|
local gc=love.graphics
|
||||||
|
local back={}
|
||||||
|
local brightness=.26
|
||||||
|
function back.draw()
|
||||||
|
gc.clear(brightness,brightness,brightness)
|
||||||
|
end
|
||||||
|
function back.event(b)
|
||||||
|
brightness=b
|
||||||
|
end
|
||||||
|
return back
|
||||||
@@ -22,12 +22,12 @@ function back.resize(w,h)
|
|||||||
S[i+4]=(rnd()-.5)*.01*s--Vy
|
S[i+4]=(rnd()-.5)*.01*s--Vy
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function back.update()
|
function back.update(dt)
|
||||||
local S=stars
|
local S=stars
|
||||||
--Star moving
|
--Star moving
|
||||||
for i=1,1260,5 do
|
for i=1,1260,5 do
|
||||||
S[i+1]=(S[i+1]+S[i+3])%W
|
S[i+1]=(S[i+1]+S[i+3]*dt*60)%W
|
||||||
S[i+2]=(S[i+2]+S[i+4])%H
|
S[i+2]=(S[i+2]+S[i+4]*dt*60)%H
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function back.draw()
|
function back.draw()
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ function bot_cc:revive()
|
|||||||
self.P:loadAI(self.data)
|
self.P:loadAI(self.data)
|
||||||
end
|
end
|
||||||
function bot_cc:pushNewNext(id)
|
function bot_cc:pushNewNext(id)
|
||||||
self.ccBot:addNext(rem(self.nexts,1))
|
self.ccBot:addNext(rem(self.bufferedNexts,1))
|
||||||
ins(self.nexts,id)
|
ins(self.bufferedNexts,id)
|
||||||
end
|
end
|
||||||
function bot_cc:thread()
|
function bot_cc:thread()
|
||||||
local P,keys=self.P,self.keys
|
local P,keys=self.P,self.keys
|
||||||
|
|||||||
@@ -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==0 then
|
if P.control and P.cur 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
|
||||||
@@ -85,7 +85,7 @@ function BOT.new(P,data)
|
|||||||
if data.type=="CC"then
|
if data.type=="CC"then
|
||||||
P:setRS('SRS')
|
P:setRS('SRS')
|
||||||
bot.keys={}
|
bot.keys={}
|
||||||
bot.nexts={}
|
bot.bufferedNexts={}
|
||||||
bot.delay=data.delay
|
bot.delay=data.delay
|
||||||
bot.delay0=data.delay
|
bot.delay0=data.delay
|
||||||
if P.gameEnv.holdCount>1 then
|
if P.gameEnv.holdCount>1 then
|
||||||
@@ -109,20 +109,25 @@ function BOT.new(P,data)
|
|||||||
return
|
return
|
||||||
self.ccBot[k]and function(_,...)self.ccBot[k](self.ccBot,...)end or
|
self.ccBot[k]and function(_,...)self.ccBot[k](self.ccBot,...)end or
|
||||||
cc_lua[k]and function(_,...)cc_lua[k](self,...)end or
|
cc_lua[k]and function(_,...)cc_lua[k](self,...)end or
|
||||||
baseBot[k]and baseBot[k]or
|
assert(baseBot[k],"No CC action called "..k)
|
||||||
error("No actions called "..k)
|
|
||||||
end})
|
end})
|
||||||
|
|
||||||
for i,B in next,P.nextQueue do
|
local pushed=0
|
||||||
if i<=data.next then
|
if P.cur then
|
||||||
|
bot:addNext(P.cur.id)
|
||||||
|
pushed=pushed+1
|
||||||
|
end
|
||||||
|
for _,B in next,P.nextQueue do
|
||||||
|
if pushed<=data.next then
|
||||||
bot:addNext(B.id)
|
bot:addNext(B.id)
|
||||||
|
pushed=pushed+1
|
||||||
else
|
else
|
||||||
ins(bot.nexts,B.id)
|
ins(bot.bufferedNexts,B.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
bot.runningThread=coroutine.wrap(cc_lua.thread)
|
bot.runningThread=coroutine.wrap(cc_lua.thread)
|
||||||
bot.runningThread(bot)
|
bot.runningThread(bot)
|
||||||
elseif data.type=="9S"or true then--9s or else
|
else--if data.type=="9S"then--9s or else
|
||||||
TABLE.cover(baseBot,bot)
|
TABLE.cover(baseBot,bot)
|
||||||
TABLE.cover(require"parts.bot.bot_9s",bot)
|
TABLE.cover(require"parts.bot.bot_9s",bot)
|
||||||
P:setRS('TRS')
|
P:setRS('TRS')
|
||||||
|
|||||||
18
parts/eventsets/bigWallGen.lua
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
return{
|
||||||
|
hook_drop=function(P)
|
||||||
|
if P.lastPiece.row>0 then
|
||||||
|
for _=1,#P.clearedRow do
|
||||||
|
local h=#P.field
|
||||||
|
P.field[h+1]=LINE.new(20)
|
||||||
|
P.visTime[h+1]=LINE.new(20)
|
||||||
|
for i=3,7 do P.field[h+1][i]=0 end
|
||||||
|
end
|
||||||
|
if P.combo>P.modeData.maxCombo then
|
||||||
|
P.modeData.maxCombo=P.combo
|
||||||
|
end
|
||||||
|
if P.stat.row>=200 then
|
||||||
|
P:win('finish')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
39
parts/eventsets/big_h.lua
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
return
|
||||||
|
{
|
||||||
|
drop=1,
|
||||||
|
wait=8,
|
||||||
|
fall=20,
|
||||||
|
fieldH=10,
|
||||||
|
mesDisp=function(P)
|
||||||
|
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||||
|
PLY.draw.drawTargetLine(P,200-P.stat.row)
|
||||||
|
end,
|
||||||
|
task=function(P)
|
||||||
|
local F=P.field
|
||||||
|
for i=1,24 do
|
||||||
|
F[i]=LINE.new(20)
|
||||||
|
P.visTime[i]=LINE.new(20)
|
||||||
|
for x=3,7 do F[i][x]=0 end
|
||||||
|
end
|
||||||
|
P.modeData.target=50
|
||||||
|
end,
|
||||||
|
hook_drop=function(P)
|
||||||
|
if P.stat.row>=P.modeData.target then
|
||||||
|
if P.modeData.target==50 then
|
||||||
|
P.gameEnv.drop=.5
|
||||||
|
P.modeData.target=100
|
||||||
|
SFX.play('reach')
|
||||||
|
elseif P.modeData.target==100 then
|
||||||
|
P.gameEnv.drop=.25
|
||||||
|
P.modeData.target=150
|
||||||
|
SFX.play('reach')
|
||||||
|
elseif P.modeData.target==150 then
|
||||||
|
P:set20G(true)
|
||||||
|
P.modeData.target=200
|
||||||
|
SFX.play('reach')
|
||||||
|
else
|
||||||
|
P:win('finish')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
33
parts/eventsets/big_n.lua
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
local dropSpeed={100,80,60,48,36,28,20,16,12,10,8,6,4,2,2,1,1,.5,.5}
|
||||||
|
|
||||||
|
return
|
||||||
|
{
|
||||||
|
drop=120,
|
||||||
|
wait=8,
|
||||||
|
fall=20,
|
||||||
|
fieldH=10,
|
||||||
|
mesDisp=function(P)
|
||||||
|
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||||
|
PLY.draw.drawTargetLine(P,200-P.stat.row)
|
||||||
|
end,
|
||||||
|
task=function(P)
|
||||||
|
local F=P.field
|
||||||
|
for i=1,24 do
|
||||||
|
F[i]=LINE.new(20)
|
||||||
|
P.visTime[i]=LINE.new(20)
|
||||||
|
for x=3,7 do F[i][x]=0 end
|
||||||
|
end
|
||||||
|
P.modeData.target=10
|
||||||
|
end,
|
||||||
|
hook_drop=function(P)
|
||||||
|
if P.stat.row>=P.modeData.target then
|
||||||
|
if P.modeData.target==200 then
|
||||||
|
P:win('finish')
|
||||||
|
else
|
||||||
|
P.gameEnv.drop=dropSpeed[P.modeData.target/10]
|
||||||
|
P.modeData.target=P.modeData.target+10
|
||||||
|
SFX.play('reach')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ return{
|
|||||||
end
|
end
|
||||||
setField(P,D.finished+1)
|
setField(P,D.finished+1)
|
||||||
SYSFX.newShade(1.4,P.absFieldX,P.absFieldY,300*P.size,610*P.size,.6,.8,.6)
|
SYSFX.newShade(1.4,P.absFieldX,P.absFieldY,300*P.size,610*P.size,.6,.8,.6)
|
||||||
SFX.play('blip_1')
|
SFX.play('warn_1')
|
||||||
else
|
else
|
||||||
P:win('finish')
|
P:win('finish')
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ return{
|
|||||||
end
|
end
|
||||||
setFont(50)
|
setFont(50)
|
||||||
mStr(P.modeData.drought,63,130)
|
mStr(P.modeData.drought,63,130)
|
||||||
mDraw(MODES.drought_l.icon,63,200,nil,.5)
|
mDraw(IMG.drought,63,200,nil,.5)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
task=function(P)
|
task=function(P)
|
||||||
@@ -41,15 +41,15 @@ return{
|
|||||||
if D.target==110 then
|
if D.target==110 then
|
||||||
P.gameEnv.drop,P.gameEnv.lock=5,5
|
P.gameEnv.drop,P.gameEnv.lock=5,5
|
||||||
P.gameEnv.sddas,P.gameEnv.sdarr=5,5
|
P.gameEnv.sddas,P.gameEnv.sdarr=5,5
|
||||||
SFX.play('blip_2',.7)
|
SFX.play('warn_2',.7)
|
||||||
elseif D.target==140 then
|
elseif D.target==140 then
|
||||||
P.gameEnv.drop,P.gameEnv.lock=4,4
|
P.gameEnv.drop,P.gameEnv.lock=4,4
|
||||||
P.gameEnv.sddas,P.gameEnv.sdarr=4,4
|
P.gameEnv.sddas,P.gameEnv.sdarr=4,4
|
||||||
SFX.play('blip_2',.7)
|
SFX.play('warn_2',.7)
|
||||||
elseif D.target==170 then
|
elseif D.target==170 then
|
||||||
P.gameEnv.drop,P.gameEnv.lock=3,3
|
P.gameEnv.drop,P.gameEnv.lock=3,3
|
||||||
P.gameEnv.sddas,P.gameEnv.sdarr=3,3
|
P.gameEnv.sddas,P.gameEnv.sdarr=3,3
|
||||||
SFX.play('blip_2',.7)
|
SFX.play('warn_2',.7)
|
||||||
elseif D.target==200 then
|
elseif D.target==200 then
|
||||||
P:win('finish')
|
P:win('finish')
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ return{
|
|||||||
end
|
end
|
||||||
setFont(50)
|
setFont(50)
|
||||||
mStr(P.modeData.drought,63,130)
|
mStr(P.modeData.drought,63,130)
|
||||||
mDraw(MODES.drought_l.icon,63,200,nil,.5)
|
mDraw(IMG.drought,63,200,nil,.5)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
task=function(P)
|
task=function(P)
|
||||||
@@ -36,11 +36,12 @@ return{
|
|||||||
end,
|
end,
|
||||||
hook_drop=function(P)
|
hook_drop=function(P)
|
||||||
local D=P.modeData
|
local D=P.modeData
|
||||||
|
D.drought=P.lastPiece.id==7 and 0 or D.drought+1
|
||||||
if P.stat.row>=D.target then
|
if P.stat.row>=D.target then
|
||||||
if D.target==110 then
|
if D.target==110 then
|
||||||
P.gameEnv.drop,P.gameEnv.lock=2,2
|
P.gameEnv.drop,P.gameEnv.lock=2,2
|
||||||
P.gameEnv.sddas,P.gameEnv.sdarr=2,2
|
P.gameEnv.sddas,P.gameEnv.sdarr=2,2
|
||||||
SFX.play('blip_1')
|
SFX.play('warn_1')
|
||||||
elseif D.target==200 then
|
elseif D.target==200 then
|
||||||
P:win('finish')
|
P:win('finish')
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ return{
|
|||||||
end
|
end
|
||||||
setFont(50)
|
setFont(50)
|
||||||
mStr(P.modeData.drought,63,130)
|
mStr(P.modeData.drought,63,130)
|
||||||
mDraw(MODES.drought_l.icon,63,200,nil,.5)
|
mDraw(IMG.drought,63,200,nil,.5)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
task=function(P)
|
task=function(P)
|
||||||
@@ -36,6 +36,7 @@ return{
|
|||||||
end,
|
end,
|
||||||
hook_drop=function(P)
|
hook_drop=function(P)
|
||||||
local D=P.modeData
|
local D=P.modeData
|
||||||
|
D.drought=P.lastPiece.id==7 and 0 or D.drought+1
|
||||||
if P.stat.row>=D.target then
|
if P.stat.row>=D.target then
|
||||||
if D.target==100 then
|
if D.target==100 then
|
||||||
P:win('finish')
|
P:win('finish')
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
local dropSpeed={50,40,30,24,18,14,10,8,6,5,4,3,2,1,1,.5,.5,.25,.25}
|
local dropSpeed={50,40,30,24,18,13,9,6,4,3,2,2,1,1,.5,.5,.5,.25,.25}
|
||||||
|
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ return{
|
|||||||
D.pt=D.pt+s
|
D.pt=D.pt+s
|
||||||
|
|
||||||
if D.pt%100==99 then
|
if D.pt%100==99 then
|
||||||
SFX.play('blip_1')
|
SFX.play('warn_1')
|
||||||
elseif D.pt>=D.target then--Level up!
|
elseif D.pt>=D.target then--Level up!
|
||||||
s=D.target/100--range from 1 to 9
|
s=D.target/100--range from 1 to 9
|
||||||
local E=P.gameEnv
|
local E=P.gameEnv
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
local death_lock={12,11,10,9,8, 7,7,7,7,6}
|
local death_lock={12,11,10,9,8, 8,8,7,7,6}
|
||||||
local death_wait={10,9, 8, 7,6, 6,6,5,5,4}
|
local death_wait={10,9, 8, 7,6, 7,6,6,5,5}
|
||||||
local death_fall={10,9, 8, 7,6, 6,5,5,4,4}
|
local death_fall={10,9, 8, 7,6, 7,6,5,5,5}
|
||||||
|
|
||||||
return{
|
return{
|
||||||
drop=0,
|
drop=0,
|
||||||
@@ -24,7 +24,7 @@ return{
|
|||||||
D.pt=D.pt+s
|
D.pt=D.pt+s
|
||||||
|
|
||||||
if D.pt%100==99 then
|
if D.pt%100==99 then
|
||||||
SFX.play('blip_1')
|
SFX.play('warn_1')
|
||||||
elseif D.pt>=D.target then--Level up!
|
elseif D.pt>=D.target then--Level up!
|
||||||
s=D.target/100
|
s=D.target/100
|
||||||
local E=P.gameEnv
|
local E=P.gameEnv
|
||||||
|
|||||||
80
parts/eventsets/master_instinct.lua
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
local inv_lock={60,50,45,40,37, 34,32,30,28,26}
|
||||||
|
local inv_wait={12,11,11,10,10, 10,10, 9, 9, 9}
|
||||||
|
local inv_fall={18,16,14,13,12, 12,11,11,10,10}
|
||||||
|
local inv_hide={20,17,14,11, 8, 5, 3, 2, 1, 0}
|
||||||
|
local hidetimer=0
|
||||||
|
local held=false
|
||||||
|
|
||||||
|
return{
|
||||||
|
drop=0,
|
||||||
|
lock=inv_lock[1],
|
||||||
|
wait=inv_wait[1],
|
||||||
|
fall=inv_fall[1],
|
||||||
|
ghost=false,
|
||||||
|
noTele=true,
|
||||||
|
das=10,arr=1,
|
||||||
|
mesDisp=function(P)
|
||||||
|
PLY.draw.drawProgress(P.modeData.pt,P.modeData.target)
|
||||||
|
end,
|
||||||
|
hook_drop=function(P)
|
||||||
|
local D=P.modeData
|
||||||
|
|
||||||
|
local c=#P.clearedRow
|
||||||
|
if c==0 and D.pt%100==99 then return end
|
||||||
|
local s=c<3 and c+1 or c==3 and 5 or 7
|
||||||
|
if P.combo>7 then s=s+2
|
||||||
|
elseif P.combo>3 then s=s+1
|
||||||
|
end
|
||||||
|
D.pt=D.pt+s
|
||||||
|
held=false
|
||||||
|
if D.pt<1000 then
|
||||||
|
hidetimer=0-inv_wait[(P.modeData.pt/100-(P.modeData.pt%100)/100)+1]
|
||||||
|
if c>0 then hidetimer=hidetimer-inv_fall[(P.modeData.pt/100-(P.modeData.pt%100)/100)+1]end
|
||||||
|
end
|
||||||
|
|
||||||
|
if D.pt%100==99 then
|
||||||
|
SFX.play('warn_1')
|
||||||
|
elseif D.pt>=D.target then--Level up!
|
||||||
|
s=D.target/100
|
||||||
|
local E=P.gameEnv
|
||||||
|
E.lock=inv_lock[s]
|
||||||
|
E.wait=inv_wait[s]
|
||||||
|
E.fall=inv_fall[s]
|
||||||
|
|
||||||
|
if s==2 then
|
||||||
|
E.das=8
|
||||||
|
elseif s==4 then
|
||||||
|
BG.set('rgb')
|
||||||
|
elseif s==5 then
|
||||||
|
E.das=7
|
||||||
|
elseif s==7 then
|
||||||
|
E.das=6
|
||||||
|
BGM.play('far')
|
||||||
|
elseif s==10 then
|
||||||
|
D.pt=1000
|
||||||
|
P:win('finish')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
D.target=D.target+100
|
||||||
|
P:stageComplete(s)
|
||||||
|
SFX.play('reach')
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
task=function(P)
|
||||||
|
P.modeData.pt=0
|
||||||
|
P.modeData.target=100
|
||||||
|
while true do
|
||||||
|
YIELD()
|
||||||
|
if P.holdTime==0 and P.waiting<=0 and not held then
|
||||||
|
hidetimer=0
|
||||||
|
held=true
|
||||||
|
end
|
||||||
|
hidetimer=hidetimer+1
|
||||||
|
if hidetimer>inv_hide[(P.modeData.pt/100-(P.modeData.pt%100)/100)+1]then
|
||||||
|
P.gameEnv.block=false
|
||||||
|
else
|
||||||
|
P.gameEnv.block=true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
@@ -24,7 +24,7 @@ return{
|
|||||||
D.pt=D.pt+s
|
D.pt=D.pt+s
|
||||||
|
|
||||||
if D.pt%100==99 then
|
if D.pt%100==99 then
|
||||||
SFX.play('blip_1')
|
SFX.play('warn_1')
|
||||||
elseif D.pt>=D.target then--Level up!
|
elseif D.pt>=D.target then--Level up!
|
||||||
s=D.target/100
|
s=D.target/100
|
||||||
local E=P.gameEnv
|
local E=P.gameEnv
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ return
|
|||||||
|
|
||||||
P.modeData.target=260
|
P.modeData.target=260
|
||||||
p=260
|
p=260
|
||||||
SFX.play('blip_2')
|
SFX.play('warn_2')
|
||||||
SFX.play('reach')
|
SFX.play('reach')
|
||||||
else
|
else
|
||||||
p=260
|
p=260
|
||||||
|
|||||||
@@ -5,15 +5,22 @@ local setFont=setFont
|
|||||||
local PLAYERS,PLY_ALIVE=PLAYERS,PLY_ALIVE
|
local PLAYERS,PLY_ALIVE=PLAYERS,PLY_ALIVE
|
||||||
|
|
||||||
return{
|
return{
|
||||||
|
layout='royale',
|
||||||
|
fkey1=function(P)
|
||||||
|
P:changeAtkMode(P.atkMode<3 and P.atkMode+2 or 5-P.atkMode)
|
||||||
|
P.swappingAtkMode=45
|
||||||
|
end,
|
||||||
mesDisp=function(P)
|
mesDisp=function(P)
|
||||||
setFont(35)
|
setFont(35)
|
||||||
mStr(#PLY_ALIVE.."/"..#PLAYERS,63,175)
|
mStr(#PLY_ALIVE.."/"..#PLAYERS,63,175)
|
||||||
mStr(P.modeData.ko,80,215)
|
mStr(P.modeData.ko,80,215)
|
||||||
gc_draw(TEXTOBJ.ko,60-TEXTOBJ.ko:getWidth(),222)
|
gc_draw(TEXTOBJ.ko,60-TEXTOBJ.ko:getWidth(),222)
|
||||||
|
|
||||||
setFont(20)
|
setFont(20)
|
||||||
gc_setColor(1,.5,0,.6)
|
gc_setColor(1,.5,0,.6)
|
||||||
gc_print(P.badge,103,227)
|
gc_print(P.badge,103,227)
|
||||||
gc_setColor(.97,.97,.97)
|
gc_setColor(.97,.97,.97)
|
||||||
|
|
||||||
setFont(25)
|
setFont(25)
|
||||||
mStr(text.powerUp[P.strength],63,290)
|
mStr(text.powerUp[P.strength],63,290)
|
||||||
gc_setColor(1,1,1)
|
gc_setColor(1,1,1)
|
||||||
|
|||||||
@@ -18,8 +18,15 @@ return
|
|||||||
if P.modeData.target==200 then
|
if P.modeData.target==200 then
|
||||||
P:win('finish')
|
P:win('finish')
|
||||||
else
|
else
|
||||||
if P.modeData.target==100 then
|
if P.modeData.target==40 then
|
||||||
|
BG.set('rainbow')
|
||||||
|
elseif P.modeData.target==80 then
|
||||||
|
BG.set('rainbow2')
|
||||||
|
elseif P.modeData.target==100 then
|
||||||
|
BG.set('glow')
|
||||||
P.modeData.lock=6
|
P.modeData.lock=6
|
||||||
|
elseif P.modeData.target==120 then
|
||||||
|
BG.set('lightning')
|
||||||
end
|
end
|
||||||
P.gameEnv.wait=waitSpeed[P.modeData.target/10]
|
P.gameEnv.wait=waitSpeed[P.modeData.target/10]
|
||||||
P.modeData.target=P.modeData.target+10
|
P.modeData.target=P.modeData.target+10
|
||||||
|
|||||||
38
parts/eventsets/strategy_e_plus.lua
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
local waitSpeed={60,59,58,57,56,55,54,52,50,48,46,44,42,40,38,36,34,32,30}
|
||||||
|
|
||||||
|
return
|
||||||
|
{
|
||||||
|
holdCount=0,
|
||||||
|
das=5,arr=1,
|
||||||
|
drop=0,lock=7,
|
||||||
|
wait=60,fall=0,
|
||||||
|
freshLimit=12,
|
||||||
|
mesDisp=function(P)
|
||||||
|
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||||
|
PLY.draw.drawTargetLine(P,200-P.stat.row)
|
||||||
|
end,
|
||||||
|
task=function(P)
|
||||||
|
P.modeData.target=10
|
||||||
|
end,
|
||||||
|
hook_drop=function(P)
|
||||||
|
if P.stat.row>=P.modeData.target then
|
||||||
|
if P.modeData.target==200 then
|
||||||
|
P:win('finish')
|
||||||
|
else
|
||||||
|
if P.modeData.target==40 then
|
||||||
|
BG.set('rainbow')
|
||||||
|
elseif P.modeData.target==80 then
|
||||||
|
BG.set('rainbow2')
|
||||||
|
elseif P.modeData.target==100 then
|
||||||
|
BG.set('glow')
|
||||||
|
P.modeData.lock=6
|
||||||
|
elseif P.modeData.target==120 then
|
||||||
|
BG.set('lightning')
|
||||||
|
end
|
||||||
|
P.gameEnv.wait=waitSpeed[P.modeData.target/10]
|
||||||
|
P.modeData.target=P.modeData.target+10
|
||||||
|
SFX.play('reach')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
@@ -18,8 +18,16 @@ return
|
|||||||
if P.modeData.target==200 then
|
if P.modeData.target==200 then
|
||||||
P:win('finish')
|
P:win('finish')
|
||||||
else
|
else
|
||||||
if P.modeData.target==100 then
|
if P.modeData.target==40 then
|
||||||
|
BG.set('rainbow')
|
||||||
|
elseif P.modeData.target==80 then
|
||||||
|
BG.set('rainbow2')
|
||||||
|
elseif P.modeData.target==100 then
|
||||||
|
BG.set('glow')
|
||||||
P.modeData.lock=5
|
P.modeData.lock=5
|
||||||
|
BGM.play('secret8th remix')
|
||||||
|
elseif P.modeData.target==120 then
|
||||||
|
BG.set('lightning')
|
||||||
end
|
end
|
||||||
P.gameEnv.wait=waitSpeed[P.modeData.target/10]
|
P.gameEnv.wait=waitSpeed[P.modeData.target/10]
|
||||||
P.modeData.target=P.modeData.target+10
|
P.modeData.target=P.modeData.target+10
|
||||||
|
|||||||
39
parts/eventsets/strategy_h_plus.lua
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
local waitSpeed={30,29,28,27,26,25,24,23,22,21,20,19,18,18,17,17,16,16,15}
|
||||||
|
|
||||||
|
return
|
||||||
|
{
|
||||||
|
holdCount=0,
|
||||||
|
das=4,arr=1,
|
||||||
|
drop=0,lock=6,
|
||||||
|
wait=30,fall=0,
|
||||||
|
freshLimit=12,
|
||||||
|
mesDisp=function(P)
|
||||||
|
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||||
|
PLY.draw.drawTargetLine(P,200-P.stat.row)
|
||||||
|
end,
|
||||||
|
task=function(P)
|
||||||
|
P.modeData.target=10
|
||||||
|
end,
|
||||||
|
hook_drop=function(P)
|
||||||
|
if P.stat.row>=P.modeData.target then
|
||||||
|
if P.modeData.target==200 then
|
||||||
|
P:win('finish')
|
||||||
|
else
|
||||||
|
if P.modeData.target==40 then
|
||||||
|
BG.set('rainbow')
|
||||||
|
elseif P.modeData.target==80 then
|
||||||
|
BG.set('rainbow2')
|
||||||
|
elseif P.modeData.target==100 then
|
||||||
|
BG.set('glow')
|
||||||
|
P.modeData.lock=5
|
||||||
|
BGM.play('secret8th remix')
|
||||||
|
elseif P.modeData.target==120 then
|
||||||
|
BG.set('lightning')
|
||||||
|
end
|
||||||
|
P.gameEnv.wait=waitSpeed[P.modeData.target/10]
|
||||||
|
P.modeData.target=P.modeData.target+10
|
||||||
|
SFX.play('reach')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
@@ -18,8 +18,16 @@ return
|
|||||||
if P.modeData.target==200 then
|
if P.modeData.target==200 then
|
||||||
P:win('finish')
|
P:win('finish')
|
||||||
else
|
else
|
||||||
if P.modeData.target==100 then
|
if P.modeData.target==40 then
|
||||||
|
BG.set('rainbow')
|
||||||
|
elseif P.modeData.target==80 then
|
||||||
|
BG.set('rainbow2')
|
||||||
|
elseif P.modeData.target==100 then
|
||||||
|
BG.set('glow')
|
||||||
P.modeData.lock=4
|
P.modeData.lock=4
|
||||||
|
BGM.play('secret7th remix')
|
||||||
|
elseif P.modeData.target==120 then
|
||||||
|
BG.set('lightning')
|
||||||
end
|
end
|
||||||
P.gameEnv.wait=waitSpeed[P.modeData.target/10]
|
P.gameEnv.wait=waitSpeed[P.modeData.target/10]
|
||||||
P.modeData.target=P.modeData.target+10
|
P.modeData.target=P.modeData.target+10
|
||||||
|
|||||||
39
parts/eventsets/strategy_u_plus.lua
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
local waitSpeed={15,15,14,14,13,13,12,12,11,11,10,10,9,9,8,8,7,7,7}
|
||||||
|
|
||||||
|
return
|
||||||
|
{
|
||||||
|
holdCount=0,
|
||||||
|
das=3,arr=1,
|
||||||
|
drop=0,lock=5,
|
||||||
|
wait=15,fall=0,
|
||||||
|
freshLimit=12,
|
||||||
|
mesDisp=function(P)
|
||||||
|
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||||
|
PLY.draw.drawTargetLine(P,200-P.stat.row)
|
||||||
|
end,
|
||||||
|
task=function(P)
|
||||||
|
P.modeData.target=10
|
||||||
|
end,
|
||||||
|
hook_drop=function(P)
|
||||||
|
if P.stat.row>=P.modeData.target then
|
||||||
|
if P.modeData.target==200 then
|
||||||
|
P:win('finish')
|
||||||
|
else
|
||||||
|
if P.modeData.target==40 then
|
||||||
|
BG.set('rainbow')
|
||||||
|
elseif P.modeData.target==80 then
|
||||||
|
BG.set('rainbow2')
|
||||||
|
elseif P.modeData.target==100 then
|
||||||
|
BG.set('glow')
|
||||||
|
P.modeData.lock=4
|
||||||
|
BGM.play('secret7th remix')
|
||||||
|
elseif P.modeData.target==120 then
|
||||||
|
BG.set('lightning')
|
||||||
|
end
|
||||||
|
P.gameEnv.wait=waitSpeed[P.modeData.target/10]
|
||||||
|
P.modeData.target=P.modeData.target+10
|
||||||
|
SFX.play('reach')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ local gc_draw,gc_rectangle,gc_line,gc_printf=gc.draw,gc.rectangle,gc.line,gc.pri
|
|||||||
|
|
||||||
local ins,rem=table.insert,table.remove
|
local ins,rem=table.insert,table.remove
|
||||||
local int,rnd=math.floor,math.random
|
local int,rnd=math.floor,math.random
|
||||||
|
local approach=MATH.expApproach
|
||||||
|
|
||||||
local SETTING,GAME,SCR=SETTING,GAME,SCR
|
local SETTING,GAME,SCR=SETTING,GAME,SCR
|
||||||
local PLAYERS=PLAYERS
|
local PLAYERS=PLAYERS
|
||||||
@@ -15,39 +16,102 @@ local playSFX=SFX.play
|
|||||||
|
|
||||||
|
|
||||||
--System
|
--System
|
||||||
|
do--function tryBack()
|
||||||
|
local sureTime=-1e99
|
||||||
|
function tryBack()
|
||||||
|
if TIME()-sureTime<1 then
|
||||||
|
sureTime=-1e99
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
sureTime=TIME()
|
||||||
|
MES.new('warn',text.sureQuit)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
do--function tryReset()
|
||||||
|
local sureTime=-1e99
|
||||||
|
function tryReset()
|
||||||
|
if TIME()-sureTime<1 then
|
||||||
|
sureTime=-1e99
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
sureTime=TIME()
|
||||||
|
MES.new('warn',text.sureReset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
do--function tryDelete()
|
||||||
|
local sureTime=-1e99
|
||||||
|
function tryDelete()
|
||||||
|
if TIME()-sureTime<1 then
|
||||||
|
sureTime=-1e99
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
sureTime=TIME()
|
||||||
|
MES.new('warn',text.sureDelete)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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 true
|
||||||
|
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
|
local path=love.filesystem.getRealDirectory(file)
|
||||||
|
if path and path~=SAVEDIR then
|
||||||
return true
|
return true
|
||||||
elseif mes then
|
elseif mes then
|
||||||
MES.new('warn',mes)
|
MES.new('warn',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()
|
do--function applySettings()
|
||||||
text=LANG.get(SETTING.locale)
|
|
||||||
WIDGET.setLang(text.WidgetText)
|
|
||||||
for k,v in next,TEXTOBJ do
|
|
||||||
if rawget(text,k)then
|
|
||||||
v:set(text[k])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function applyCursor()
|
|
||||||
love.mouse.setVisible(SETTING.sysCursor)
|
|
||||||
end
|
|
||||||
function applyFullscreen()
|
|
||||||
love.window.setFullscreen(SETTING.fullscreen)
|
|
||||||
love.resize(gc.getWidth(),gc.getHeight())
|
|
||||||
end
|
|
||||||
do--function applyBlockSatur,applyFieldSatur(mode)
|
|
||||||
local saturateValues={
|
local saturateValues={
|
||||||
normal={0,1},
|
normal={0,1},
|
||||||
soft={.2,.7},
|
soft={.2,.7},
|
||||||
@@ -55,29 +119,79 @@ do--function applyBlockSatur,applyFieldSatur(mode)
|
|||||||
light={.2,.8},
|
light={.2,.8},
|
||||||
color={-.2,1.2},
|
color={-.2,1.2},
|
||||||
}
|
}
|
||||||
function applyBlockSatur(mode)
|
function applySettings()
|
||||||
local m=saturateValues[mode]or saturateValues.normal
|
--Apply fullscreen
|
||||||
|
love.window.setFullscreen(SETTING.fullscreen)
|
||||||
|
love.resize(gc.getWidth(),gc.getHeight())
|
||||||
|
|
||||||
|
--Apply Zframework setting
|
||||||
|
Z.setClickFX(SETTING.clickFX)
|
||||||
|
Z.setFrameMul(SETTING.frameMul)
|
||||||
|
Z.setPowerInfo(SETTING.powerInfo)
|
||||||
|
Z.setCleanCanvas(SETTING.cleanCanvas)
|
||||||
|
|
||||||
|
--Apply VK shape
|
||||||
|
VK.setShape(SETTING.VKSkin)
|
||||||
|
|
||||||
|
--Apply sound
|
||||||
|
love.audio.setVolume(SETTING.mainVol)
|
||||||
|
BGM.setVol(SETTING.bgm)
|
||||||
|
SFX.setVol(SETTING.sfx)
|
||||||
|
VOC.setVol(SETTING.voc)
|
||||||
|
|
||||||
|
--Apply saturs
|
||||||
|
local m
|
||||||
|
m=saturateValues[SETTING.blockSatur]or saturateValues.normal
|
||||||
SHADER.blockSatur:send('b',m[1])
|
SHADER.blockSatur:send('b',m[1])
|
||||||
SHADER.blockSatur:send('k',m[2])
|
SHADER.blockSatur:send('k',m[2])
|
||||||
end
|
m=saturateValues[SETTING.fieldSatur]or saturateValues.normal
|
||||||
function applyFieldSatur(mode)
|
|
||||||
local m=saturateValues[mode]or saturateValues.normal
|
|
||||||
SHADER.fieldSatur:send('b',m[1])
|
SHADER.fieldSatur:send('b',m[1])
|
||||||
SHADER.fieldSatur:send('k',m[2])
|
SHADER.fieldSatur:send('k',m[2])
|
||||||
|
|
||||||
|
--Apply language
|
||||||
|
text=LANG.get(SETTING.locale)
|
||||||
|
WIDGET.setLang(text.WidgetText)
|
||||||
|
for k,v in next,TEXTOBJ do
|
||||||
|
if rawget(text,k)then
|
||||||
|
v:set(text[k])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--Apply cursor
|
||||||
|
love.mouse.setVisible(SETTING.sysCursor)
|
||||||
|
|
||||||
|
--Apply BG
|
||||||
|
if SETTING.bg=='on'then
|
||||||
|
BG.unlock()
|
||||||
|
BG.set()
|
||||||
|
elseif SETTING.bg=='off'then
|
||||||
|
BG.unlock()
|
||||||
|
BG.set('gray')
|
||||||
|
BG.send(SETTING.bgAlpha)
|
||||||
|
BG.lock()
|
||||||
|
elseif SETTING.bg=='custom'then
|
||||||
|
if love.filesystem.getInfo('conf/customBG')then
|
||||||
|
local res,image=pcall(gc.newImage,love.filesystem.newFile('conf/customBG'))
|
||||||
|
if res then
|
||||||
|
BG.unlock()
|
||||||
|
BG.set('custom')
|
||||||
|
gc.setDefaultFilter('linear','linear')
|
||||||
|
BG.send(SETTING.bgAlpha,image)
|
||||||
|
gc.setDefaultFilter('nearest','nearest')
|
||||||
|
BG.lock()
|
||||||
|
else
|
||||||
|
MES.new('error',text.customBGloadFailed)
|
||||||
|
end
|
||||||
|
else--Switch off when custom BG not found
|
||||||
|
SETTING.bg='off'
|
||||||
|
BG.unlock()
|
||||||
|
BG.set('gray')
|
||||||
|
BG.send(SETTING.bgAlpha)
|
||||||
|
BG.lock()
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function applyAllSettings()
|
|
||||||
love.window.setFullscreen(SETTING.fullscreen)
|
|
||||||
love.audio.setVolume(SETTING.mainVol)
|
|
||||||
VK.setShape(SETTING.VKSkin)
|
|
||||||
BGM.setVol(SETTING.bgm)
|
|
||||||
SFX.setVol(SETTING.sfx)
|
|
||||||
VOC.setVol(SETTING.voc)
|
|
||||||
applyBlockSatur(SETTING.blockSatur)
|
|
||||||
applyFieldSatur(SETTING.fieldSatur)
|
|
||||||
applyLanguage()
|
|
||||||
applyCursor()
|
|
||||||
end
|
|
||||||
|
|
||||||
--Royale mode
|
--Royale mode
|
||||||
function randomTarget(P)--Return a random opponent for P
|
function randomTarget(P)--Return a random opponent for P
|
||||||
@@ -145,17 +259,17 @@ function royaleLevelup()
|
|||||||
BGM.play('cruelty')
|
BGM.play('cruelty')
|
||||||
end
|
end
|
||||||
elseif GAME.stage==4 then
|
elseif GAME.stage==4 then
|
||||||
spd=10
|
spd=8
|
||||||
for _,P in next,PLY_ALIVE do
|
for _,P in next,PLY_ALIVE do
|
||||||
P.gameEnv.pushSpeed=3
|
P.gameEnv.pushSpeed=3
|
||||||
end
|
end
|
||||||
elseif GAME.stage==5 then
|
elseif GAME.stage==5 then
|
||||||
spd=5
|
spd=4
|
||||||
for _,P in next,PLY_ALIVE do
|
for _,P in next,PLY_ALIVE do
|
||||||
P.gameEnv.garbageSpeed=1
|
P.gameEnv.garbageSpeed=1
|
||||||
end
|
end
|
||||||
elseif GAME.stage==6 then
|
elseif GAME.stage==6 then
|
||||||
spd=3
|
spd=2
|
||||||
if PLAYERS[1].alive then
|
if PLAYERS[1].alive then
|
||||||
BGM.play('final')
|
BGM.play('final')
|
||||||
end
|
end
|
||||||
@@ -166,7 +280,7 @@ function royaleLevelup()
|
|||||||
if GAME.curMode.name:find("_u")then
|
if GAME.curMode.name:find("_u")then
|
||||||
for i=1,#PLY_ALIVE do
|
for i=1,#PLY_ALIVE do
|
||||||
local P=PLY_ALIVE[i]
|
local P=PLY_ALIVE[i]
|
||||||
P.gameEnv.drop=int(P.gameEnv.drop*.3)
|
P.gameEnv.drop=int(P.gameEnv.drop*.4)
|
||||||
if P.gameEnv.drop==0 then
|
if P.gameEnv.drop==0 then
|
||||||
P.curY=P.ghoY
|
P.curY=P.ghoY
|
||||||
P:set20G(true)
|
P:set20G(true)
|
||||||
@@ -263,16 +377,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()
|
||||||
@@ -384,12 +498,9 @@ end
|
|||||||
function loadGame(mode,ifQuickPlay,ifNet)--Load a mode and go to game scene
|
function loadGame(mode,ifQuickPlay,ifNet)--Load a mode and go to game scene
|
||||||
freshDate()
|
freshDate()
|
||||||
if legalGameTime()then
|
if legalGameTime()then
|
||||||
if not MODES[mode]and love.filesystem.getRealDirectory('parts/modes/'..mode)~=SAVEDIR then
|
if not MODES[mode].available then
|
||||||
MODES[mode]=require('parts.modes.'..mode)
|
MES.new('error',"Unavailable mode: "..mode)
|
||||||
MODES[mode].name=mode
|
return
|
||||||
end
|
|
||||||
if MODES[mode].score then
|
|
||||||
STAT.lastPlay=mode
|
|
||||||
end
|
end
|
||||||
GAME.playing=true
|
GAME.playing=true
|
||||||
GAME.init=true
|
GAME.init=true
|
||||||
@@ -430,29 +541,9 @@ function gameOver()--Save record
|
|||||||
GAME.rank=R
|
GAME.rank=R
|
||||||
end
|
end
|
||||||
if not GAME.replaying and M.score and scoreValid()then
|
if not GAME.replaying and M.score and scoreValid()then
|
||||||
if RANKS[M.name]then--Old rank exist
|
if not RANKS[M.name]or R>RANKS[M.name]then--Old rank exist
|
||||||
local needSave
|
RANKS[M.name]=R
|
||||||
if R>RANKS[M.name]then
|
saveProgress()
|
||||||
RANKS[M.name]=R
|
|
||||||
needSave=true
|
|
||||||
end
|
|
||||||
if R>0 then
|
|
||||||
if M.unlock then
|
|
||||||
for i=1,#M.unlock do
|
|
||||||
local m=M.unlock[i]
|
|
||||||
local n=MODES[m].name
|
|
||||||
if not RANKS[n]then
|
|
||||||
if MODES[m].x then
|
|
||||||
RANKS[n]=0
|
|
||||||
end
|
|
||||||
needSave=true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if needSave then
|
|
||||||
saveProgress()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
local D=M.score(P)
|
local D=M.score(P)
|
||||||
local L=M.records
|
local L=M.records
|
||||||
@@ -475,7 +566,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
|
||||||
@@ -664,7 +755,7 @@ do--function resetGameData(args)
|
|||||||
BGM.play(type(bgm)=='string'and bgm or type(bgm)=='table'and bgm[math.random(#bgm)])
|
BGM.play(type(bgm)=='string'and bgm or type(bgm)=='table'and bgm[math.random(#bgm)])
|
||||||
|
|
||||||
TEXT.clear()
|
TEXT.clear()
|
||||||
if GAME.modeEnv.royaleMode then
|
if GAME.modeEnv.eventSet=='royale'then
|
||||||
for i=1,#PLAYERS do
|
for i=1,#PLAYERS do
|
||||||
PLAYERS[i]:changeAtk(randomTarget(PLAYERS[i]))
|
PLAYERS[i]:changeAtk(randomTarget(PLAYERS[i]))
|
||||||
end
|
end
|
||||||
@@ -685,7 +776,7 @@ do--function resetGameData(args)
|
|||||||
end
|
end
|
||||||
do--function checkWarning()
|
do--function checkWarning()
|
||||||
local max=math.max
|
local max=math.max
|
||||||
function checkWarning()
|
function checkWarning(dt)
|
||||||
local P1=PLAYERS[1]
|
local P1=PLAYERS[1]
|
||||||
if P1.alive then
|
if P1.alive then
|
||||||
if P1.frameRun%26==0 then
|
if P1.frameRun%26==0 then
|
||||||
@@ -705,13 +796,13 @@ do--function checkWarning()
|
|||||||
end
|
end
|
||||||
local _=GAME.warnLVL
|
local _=GAME.warnLVL
|
||||||
if _<GAME.warnLVL0 then
|
if _<GAME.warnLVL0 then
|
||||||
_=_*.95+GAME.warnLVL0*.05
|
_=approach(_,GAME.warnLVL0,dt*6)
|
||||||
elseif _>0 then
|
elseif _>0 then
|
||||||
_=max(_-.026,0)
|
_=max(_-.026,0)
|
||||||
end
|
end
|
||||||
GAME.warnLVL=_
|
GAME.warnLVL=_
|
||||||
if GAME.warnLVL>1.126 and P1.frameRun%30==0 then
|
if GAME.warnLVL>1.126 and P1.frameRun%30==0 then
|
||||||
SFX.fplay('warning',SETTING.sfx_warn)
|
SFX.fplay('warn_beep',SETTING.sfx_warn)
|
||||||
end
|
end
|
||||||
elseif GAME.warnLVL>0 then
|
elseif GAME.warnLVL>0 then
|
||||||
GAME.warnLVL=max(GAME.warnLVL-.026,0)
|
GAME.warnLVL=max(GAME.warnLVL-.026,0)
|
||||||
@@ -749,7 +840,7 @@ do--function drawSelfProfile()
|
|||||||
|
|
||||||
--Draw avatar
|
--Draw avatar
|
||||||
gc_setLineWidth(2)
|
gc_setLineWidth(2)
|
||||||
gc_setColor(.3,.3,.3,.8)gc_rectangle('fill',0,0,-300,80)
|
gc_setColor(COLOR.X)gc_rectangle('fill',0,0,-300,80)
|
||||||
gc_setColor(1,1,1)gc_rectangle('line',-300,0,300,80,5)
|
gc_setColor(1,1,1)gc_rectangle('line',-300,0,300,80,5)
|
||||||
gc_rectangle('line',-73,7,66,66,2)
|
gc_rectangle('line',-73,7,66,66,2)
|
||||||
gc_draw(selfAvatar,-72,8,nil,.5)
|
gc_draw(selfAvatar,-72,8,nil,.5)
|
||||||
@@ -828,8 +919,11 @@ end
|
|||||||
do--CUS/SETXXX(k)
|
do--CUS/SETXXX(k)
|
||||||
local CUSTOMENV=CUSTOMENV
|
local CUSTOMENV=CUSTOMENV
|
||||||
local warnList={
|
local warnList={
|
||||||
'ims','RS','FTLock','frameMul','highCam',
|
'das','arr','dascut','dropcut','sddas','sdarr',
|
||||||
|
'ihs','irs','ims','RS',
|
||||||
|
'FTLock','frameMul','highCam',
|
||||||
'VKSwitch','VKIcon','VKTrack','VKDodge',
|
'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
|
||||||
|
|||||||
@@ -13,6 +13,13 @@ BLOCK_COLORS={
|
|||||||
COLOR.dH,COLOR.D,COLOR.lY,COLOR.H,COLOR.lH,COLOR.dV,COLOR.dR,COLOR.dG,
|
COLOR.dH,COLOR.D,COLOR.lY,COLOR.H,COLOR.lH,COLOR.dV,COLOR.dR,COLOR.dG,
|
||||||
}
|
}
|
||||||
RANK_CHARS={'B','A','S','U','X'}for i=1,#RANK_CHARS do RANK_CHARS[i]=CHAR.icon['rank'..RANK_CHARS[i]]end
|
RANK_CHARS={'B','A','S','U','X'}for i=1,#RANK_CHARS do RANK_CHARS[i]=CHAR.icon['rank'..RANK_CHARS[i]]end
|
||||||
|
RANK_BASE_COLORS={
|
||||||
|
{.1,.2,.3},
|
||||||
|
{.3,.42,.32},
|
||||||
|
{.45,.44,.15},
|
||||||
|
{.42,.25,.2},
|
||||||
|
{.42,.15,.4},
|
||||||
|
}
|
||||||
RANK_COLORS={
|
RANK_COLORS={
|
||||||
{.8,.86,.9},
|
{.8,.86,.9},
|
||||||
{.6,.9,.7},
|
{.6,.9,.7},
|
||||||
@@ -594,7 +601,7 @@ do--Userdata tables
|
|||||||
FTLock=true,
|
FTLock=true,
|
||||||
|
|
||||||
--System
|
--System
|
||||||
reTime=4,
|
reTime=2,
|
||||||
allowTAS=false,
|
allowTAS=false,
|
||||||
autoPause=true,
|
autoPause=true,
|
||||||
menuPos='middle',
|
menuPos='middle',
|
||||||
@@ -603,11 +610,13 @@ do--Userdata tables
|
|||||||
autoLogin=true,
|
autoLogin=true,
|
||||||
simpMode=false,
|
simpMode=false,
|
||||||
sysCursor=true,
|
sysCursor=true,
|
||||||
|
maxFPS=60,
|
||||||
|
frameMul=100,
|
||||||
locale='zh',
|
locale='zh',
|
||||||
skinSet='crystal_scf',
|
skinSet='crystal_scf',
|
||||||
skin={
|
skin={
|
||||||
1,7,11,3,14,4,9,
|
1,7,11,3,14,4,9,
|
||||||
1,7,2,6,10,2,13,5,9,15,10,11,3,12,2,16,8,4,
|
1,7,2,6,10,2,13,5,9,15,4,11,3,12,2,16,8,4,
|
||||||
10,13,2,8
|
10,13,2,8
|
||||||
},
|
},
|
||||||
face={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
face={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||||
@@ -625,7 +634,6 @@ do--Userdata tables
|
|||||||
splashFX=2,
|
splashFX=2,
|
||||||
shakeFX=2,
|
shakeFX=2,
|
||||||
atkFX=2,
|
atkFX=2,
|
||||||
frameMul=100,
|
|
||||||
cleanCanvas=false,
|
cleanCanvas=false,
|
||||||
blockSatur='normal',
|
blockSatur='normal',
|
||||||
fieldSatur='normal',
|
fieldSatur='normal',
|
||||||
@@ -637,7 +645,8 @@ do--Userdata tables
|
|||||||
highCam=true,
|
highCam=true,
|
||||||
nextPos=true,
|
nextPos=true,
|
||||||
fullscreen=true,
|
fullscreen=true,
|
||||||
bg=true,
|
bg='on',
|
||||||
|
bgAlpha=.26,
|
||||||
powerInfo=false,
|
powerInfo=false,
|
||||||
clickFX=true,
|
clickFX=true,
|
||||||
warn=true,
|
warn=true,
|
||||||
@@ -674,7 +683,7 @@ do--Userdata tables
|
|||||||
r=0,
|
r=0,
|
||||||
},
|
},
|
||||||
joystick={
|
joystick={
|
||||||
dpleft=1,dpright=2,a=3,b=4,y=5,
|
dpleft=1,dpright=2,b=3,a=4,y=5,
|
||||||
dpup=6,dpdown=7,rightshoulder=8,x=9,
|
dpup=6,dpdown=7,rightshoulder=8,x=9,
|
||||||
leftshoulder=0,
|
leftshoulder=0,
|
||||||
},
|
},
|
||||||
@@ -721,4 +730,45 @@ do--Userdata tables
|
|||||||
date=false,
|
date=false,
|
||||||
todayTime=0,
|
todayTime=0,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
do--Mode data tables
|
||||||
|
MODES=setmetatable({},{__index=function(self,name)
|
||||||
|
local M
|
||||||
|
if love.filesystem.getInfo('parts/modes/'..name..'.lua')and love.filesystem.getRealDirectory('parts/modes/'..name..'.lua')~=SAVEDIR then
|
||||||
|
M=require('parts.modes.'..name)
|
||||||
|
M.available=true
|
||||||
|
M.name=name
|
||||||
|
do--Check if need slowmark
|
||||||
|
for k in next,M.env do
|
||||||
|
if
|
||||||
|
k=='mindas'or k=='minarr'or
|
||||||
|
k=='das'or k=='arr'or
|
||||||
|
k=='minsdarr'
|
||||||
|
then
|
||||||
|
M.slowMark=true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if M.score then
|
||||||
|
M.records=loadFile("record/"..name..".rec",'-luaon -canSkip')or{}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
M={
|
||||||
|
available=false,
|
||||||
|
}
|
||||||
|
MES.new('error',"Failed to load mode file: "..name)
|
||||||
|
end
|
||||||
|
self[name]=M
|
||||||
|
return M
|
||||||
|
end})
|
||||||
|
MODEICON=setmetatable({},{__index=function(self,k)
|
||||||
|
if isSafeFile('media/image/modeicon/'..k..'.png')then
|
||||||
|
local img=love.graphics.newImage('media/image/modeicon/'..k..'.png')
|
||||||
|
self[k]=img
|
||||||
|
return img
|
||||||
|
else
|
||||||
|
return PAPER
|
||||||
|
end
|
||||||
|
end})
|
||||||
|
end
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
local HDsearch="https://harddrop.com/wiki?search="
|
local HDsearch="https://harddrop.com/wiki?search="
|
||||||
local HDwiki="\nVisit HD Wiki for more information"
|
local HDwiki="\nVisit Hard Drop Wiki for more information."
|
||||||
return{
|
return{
|
||||||
{"Translator Note 1",
|
{"Translator Note 1",
|
||||||
"",
|
"",
|
||||||
"help",
|
"help",
|
||||||
"This translation of the TetroDictionary is provided by me, User670 (Discord: User670#9501).\n\nThe translation may not completely reflect the contents of the original Chinese text.\n\nCorrected by C₂₉H₂₅N₃O₅ (Discord: C29H25N3O5#1606).\n\nTo view the list of contributors or make contributions, feel free to visit the GitHub page.",
|
"This translation of the TetroDictionary is maly provided by User670 (Discord: User670#9501).\n\nThe translation may not completely reflect the contents of the original Chinese text.\n\nTo view the list of contributors or make contributions, feel free to visit the GitHub page.",
|
||||||
"https://github.com/26F-Studio/Techmino/blob/main/parts/language/dict_en.lua",
|
"https://github.com/26F-Studio/Techmino/blob/main/parts/language/dict_en.lua",
|
||||||
},
|
},
|
||||||
{"Official Website",
|
{"Official Website",
|
||||||
"official website homepage",
|
"official website homepage mainpage",
|
||||||
"help",
|
"help",
|
||||||
"The official website of Techmino!\nYou can modify your profile on it",
|
"The official website of Techmino!\nYou can modify your profile on it",
|
||||||
"http://home.techmino.org",
|
"http://home.techmino.org",
|
||||||
},
|
},
|
||||||
{"To New Players",
|
{"To New Players",
|
||||||
"guide newbie noob",
|
"guide newbie noob readme",
|
||||||
"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 to read the translated article by User670.",
|
"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://github.com/user670/temp/blob/master/tips_to_those_new_to_top.md",
|
"https://github.com/user670/temp/blob/master/tips_to_those_new_to_top.md",
|
||||||
@@ -39,7 +39,7 @@ return{
|
|||||||
{"Four.lol",
|
{"Four.lol",
|
||||||
"four wiki",
|
"four wiki",
|
||||||
"help",
|
"help",
|
||||||
"An website containing collections of various openings with simple UI and very detailed consecutive PC analyses (Not recommended for new players as you may have to memorize many techniques).",
|
"An website containing collections of various openings with simple UI and very detailed consecutive PC analyses (Not recommended for new players, as you may have to memorize many techniques).",
|
||||||
"https://four.lol",
|
"https://four.lol",
|
||||||
},
|
},
|
||||||
{"Tetris Wiki Fandom",
|
{"Tetris Wiki Fandom",
|
||||||
@@ -59,7 +59,7 @@ return{
|
|||||||
{"Github Repository",
|
{"Github Repository",
|
||||||
"githubrepository sourcecode",
|
"githubrepository sourcecode",
|
||||||
"org",
|
"org",
|
||||||
"Techmino's Github repository. Stars are appreciated.",
|
"Techmino's official Github repository. Stars are appreciated.",
|
||||||
"https://github.com/26F-Studio/Techmino",
|
"https://github.com/26F-Studio/Techmino",
|
||||||
},
|
},
|
||||||
{"Communities",
|
{"Communities",
|
||||||
@@ -69,7 +69,7 @@ return{
|
|||||||
"https://discord.gg/harddrop"
|
"https://discord.gg/harddrop"
|
||||||
},
|
},
|
||||||
{"Mew",
|
{"Mew",
|
||||||
"mew tieba forum",
|
"mew tieba forum reddit",
|
||||||
"org",
|
"org",
|
||||||
"The Mew forum owned by Chinese Tetris Research Community, and was founded in the second half of 2021. Mew is a Chinese social media that can be thought of a combination of Discord and Reddit, with many channels in a big community. Users can chat in the channels or submit posts to the channel. Mew also has a function called \"Library\" which allows storing documentations systematically. The Tetris Mew forum is currently under construction and not too much contents are available (2/Nov/2021).",
|
"The Mew forum owned by Chinese Tetris Research Community, and was founded in the second half of 2021. Mew is a Chinese social media that can be thought of a combination of Discord and Reddit, with many channels in a big community. Users can chat in the channels or submit posts to the channel. Mew also has a function called \"Library\" which allows storing documentations systematically. The Tetris Mew forum is currently under construction and not too much contents are available (2/Nov/2021).",
|
||||||
"https://mew.fun/n/tetris",
|
"https://mew.fun/n/tetris",
|
||||||
@@ -80,217 +80,244 @@ return{
|
|||||||
"Google \"Tetris Online Poland\" for the Poland server.\nClick on the globe icon for information about the Tetris Online Study server.",
|
"Google \"Tetris Online Poland\" for the Poland server.\nClick on the globe icon for information about the Tetris Online Study server.",
|
||||||
"http://teatube.ltd/tos",
|
"http://teatube.ltd/tos",
|
||||||
},
|
},
|
||||||
{"P\97\116\114\101\111\110",
|
{"Support 1",
|
||||||
"p\97\116\114\101\111\110 support",
|
"support wechat vx alipay zfb",
|
||||||
"org",
|
"org",
|
||||||
"Techmino's P\97\116\114\101\111\110 Page",
|
FNNS and "This feature is restricted due to platform policy restrictions. You may discuss about this feature in our Discord server." or "To donate to Techmino via WeChat Pay or Alipay, type \"support\" in console.",
|
||||||
FNSF and"https://www.youtube.com/watch?v=DVl0IiUKX_g"or"https://www.p\97\116\114\101\111\110.com/techmino",
|
|
||||||
},
|
},
|
||||||
|
{"Support 2",
|
||||||
|
"support afdian",
|
||||||
|
"org",
|
||||||
|
FNNS and "This feature is restricted due to platform policy restrictions. You may discuss about this feature in our Discord server. The URL in this entry is a rickroll, by the way." or "To donate to Techmino via Aifadian, use the globe icon on the bottom right to open URL. Aifadian charges 6% transaction fee off your purchase.",
|
||||||
|
FNNS and"https://youtu.be/dQw4w9WgXcQ"or"https://afdian.net/@MrZ_26",
|
||||||
|
},
|
||||||
|
{"Support 3",
|
||||||
|
"support p\97\116\114\101\111\110",
|
||||||
|
"org",
|
||||||
|
FNNS and "This feature is restricted due to platform policy restrictions. You may discuss about this feature in our Discord server. The URL in this entry is a rickroll, by the way." or "To donate to Techmino via P\97\116\114\101\111\110, use the globe icon on the bottom right to open URL. P\97\116\114\101\111\110 charges 7.9% + 0.30 USD transaction fee off your purchase that is greater than 3 USD.",
|
||||||
|
FNNS and"https://youtu.be/dQw4w9WgXcQ"or"https://www.p\97\116\114\101\111\110.com/techmino",
|
||||||
|
},
|
||||||
|
|
||||||
--Games
|
--Games
|
||||||
{"TTT",
|
{"TTT",
|
||||||
"ttt tetris trainer tres bien",
|
"ttt tetris trainer tres bien",
|
||||||
"game",
|
"game",
|
||||||
"*Web-based, no mobile support | Single-player*\nTetris Trainer Tres-Bien. A hands-on tutorial of advanced techniques in modern Tetris.\nRecommended for players that can complete a 40-line Sprint with all Tetris line clears and no hold.\nCovered topics include T-Spin, finesse, SRS, and some battle setups.\nLink translated to Simplified Chinese; originally in Japanese.",
|
"Tetris Trainer Très-Bien. A hands-on tutorial of advanced techniques in modern Tetris.\nRecommended for players that can complete a 40-line Sprint with all Tetris line clears and no hold.\nCovered topics include T-Spin, finesse, SRS, and some battle setups.\nLink in Japanese.",
|
||||||
"http://teatube.ltd/ttt",
|
"http://taninkona.web.fc2.com/ttt/",
|
||||||
},
|
},
|
||||||
{"TTPC",
|
{"TTPC",
|
||||||
"ttpc tetris perfect clear challenge",
|
"ttpc tetris perfect clear challenge",
|
||||||
"game",
|
"game",
|
||||||
"*Web-based, no mobile support | Single-player*\nTetris Perfect Clear Challenge. The PC opener tutorial for SRS+7 Bag.\nRecommended for players that have completed TTT. You need to know SRS to play this.\nIncludes only the basic PC opener.\nLink translated to Simplified Chinese; originally in Japanese.",
|
"Tetris Perfect Clear Challenge. The PC opener tutorial for SRS and 7-Bag.\nRecommended for players that have completed TTT. You need to know SRS to play this.\nIncludes only the basic PC opener.\nLink translated to Simplified Chinese; originally in Japanese.",
|
||||||
"http://teatube.ltd/ttpc",
|
"http://teatube.ltd/ttpc",
|
||||||
},
|
},
|
||||||
{"NAZO",
|
{"NAZO",
|
||||||
"nazo",
|
"nazo",
|
||||||
"game",
|
"game",
|
||||||
"*Web-based, no mobile support | Single-player*\nAll sorts of SRS puzzles. Recommended for players that have completed TTT.\nHas T-Spin and all spin puzzles of all difficulties.\nLink translated to Simplified Chinese; originally in Japanese.",
|
"All sorts of SRS puzzles. Recommended for players that have completed TTT.\nHas T-Spin and all spin puzzles of all difficulties.\nLink translated to Simplified Chinese; originally in Japanese.",
|
||||||
"http://teatube.ltd/nazo",
|
"http://teatube.ltd/nazo",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{"Side Note 1",
|
||||||
|
"note nb NB DM notice",
|
||||||
|
"game",
|
||||||
|
"The following contents are some brief introductions about some official and fan-made Tetris games with high popularity. We make absolutely no guarantees that they would cover every Tetris game. Also, the author of this game has made some comments on some of these games. Notice that they are just personal opinions and cannot be used to judge the qualities of these games. To better differentiate between the facts and opinions, all the commentary contents are enclosed with square brackets and are separated from the main contents.",
|
||||||
|
},
|
||||||
{"King of Stackers",
|
{"King of Stackers",
|
||||||
"kos kingofstackers",
|
"kos kingofstackers",
|
||||||
"game",
|
"game",
|
||||||
"*Web-based | Multiplayer*\nTurn-based battle Tetris game.",
|
"Browser Game | Multiplayer | Mobile Support\nKoS for short. A turn-based battle Tetris game. In this game, the players can place seven tetrominoes in his or her turn, and garbage lines can enter the field only if the player places a block that does not clear a line. This game requires careful thinking and there are multiple modes with different attack mechanics.",
|
||||||
"https://kingofstackers.com/games.php",
|
"https://kingofstackers.com/games.php",
|
||||||
},
|
},
|
||||||
{"Tetr.js",
|
{"Tetr.js",
|
||||||
"tetrjs tetr.js",
|
"tetrjs tetr.js",
|
||||||
"game",
|
"game",
|
||||||
"*Web-based | Single-player*\nHas newbie-friendly custom modes (most common features). Only a few on-screen control schemes are available to mobile.\nLink to Farter's Dig Mod, which itself is a mod of another version. Also has another mod called Tetr.js Enhanced.",
|
"Browser Game | Singleplayer | Mobile Support\nA browser-based Tetris game. It has many professional tunings and many modes, but the visuals are simple and there are barely any animations; besides that, only a few on-screen control schemes are available to mobile.\nLink to Farter's Dig Mod, which itself is a mod of another version. Also has another mod called Tetr.js Enhanced (You can find the link on Tetris Wiki).",
|
||||||
"http://farter.cn/t",
|
"http://farter.cn/t",
|
||||||
},
|
},
|
||||||
{"Tetra Legends",
|
{"Tetra Legends",
|
||||||
"tl tetralegends",
|
"tl tetralegends",
|
||||||
"game",
|
"game",
|
||||||
"*Web-based, no mobile support | Single-player*\nFeature-rich game with fancy visuals, also visualized some data that are otherwise hidden in other games, although controls aren't exactly the most comfortable. Has a rhythm mode.\nIt can be slow to load the game for the first time.",
|
"Browser Game | Singleplayer | No Mobile Support\nOr TL for short. It has many single-player modes, two hidden rhythm modes, and visualizes many hidden mechanics with rich animations. The development of this game was halted for multiple reasons in December 2020.",
|
||||||
"https://tetralegends.app",
|
"https://tetralegends.app",
|
||||||
},
|
},
|
||||||
{"Ascension",
|
{"Ascension",
|
||||||
"asc ascension",
|
"asc ascension ASC",
|
||||||
"game",
|
"game",
|
||||||
"Or ASC for short. A cross-platform web-based Tetris game using its own rotation system called ASC. It may take a very long time when first loading this game. It also has many single-player modes (The \"Stack\" mode in Techmino was inspired by Ascension). Battle mode is currently in the testing phase (08/20/2021).",
|
"Browser Game | Singleplayer/Multiplayer\nOr ASC for short. It uses its own rotation system (also called ASC) and has many single-player modes. Battle modes are currently under beta testing (15/Dec/2021). The Stack mode in this game was also inspired by Ascension. ",
|
||||||
"https://asc.winternebs.com",
|
"https://asc.winternebs.com",
|
||||||
},
|
},
|
||||||
{"Jstris",
|
{"Jstris",
|
||||||
"js jstris",
|
"js jstris",
|
||||||
"game",
|
"game",
|
||||||
"*Web-based | Single-player and multiplayer*\nBasic web-based battle Tetris game.",
|
"Browser Game | Singleplayer/Multiplayer | Mobile Support\nOr JS for short. It has some single-player modes with multiple customizable parameters, Adjustable virtual keys layouts for mobile, but it doesn't have any animation. ",
|
||||||
"https://jstris.jezevec10.com",
|
"https://jstris.jezevec10.com",
|
||||||
},
|
},
|
||||||
{"TETR.IO",
|
{"TETR.IO",
|
||||||
"io tetrio tetr.io",
|
"io tetrio tetr.io",
|
||||||
"game",
|
"game",
|
||||||
"*Web-based, no mobile support | Single-player and multiplayer*\nFancy online battling Tetris game.",
|
"Browser Game | Singleplayer/Multiplayer\nOr IO for short. It has a ranking system and custom game with many adjustable parameters. Also, it provides desktop clients for improved performances and no ads.\n[It seems that Safari cannot open this game.]",
|
||||||
"https://tetr.io",
|
"https://tetr.io",
|
||||||
},
|
},
|
||||||
{"Nuketris",
|
{"Nuketris",
|
||||||
"nuketris",
|
"nuketris",
|
||||||
"game",
|
"game",
|
||||||
"*Web-based | Single-player and multiplayer*\nA block stacker game with 1-vs-1 ranked mode and a few single-player modes. A PC is recommended for playing this game.",
|
"*Browser Game | Singleplayer/Multiplayer\nA block stacker game with 1V1 ranked matches and basic single-player modes.",
|
||||||
"https://nuketris.herokuapp.com",
|
"https://nuketris.herokuapp.com",
|
||||||
},
|
},
|
||||||
{"WWC",
|
{"Worldwide Combos",
|
||||||
"wwc worldwidecombos",
|
"wwc worldwidecombos",
|
||||||
"game",
|
"game",
|
||||||
"*Web-based | Multiplayer*\nWorldwide Combos, a web-based worldwide 1-vs-1 battle Tetris game.",
|
"Browser Game | Singleplayer/Multiplayer\nOr WWC for short. It has worldwide 1V1 ranked matches, recorded battles (which means that your opponent doesn't have to be a real person), many different rulesets, and bomb-handicapped garbage lines.",
|
||||||
"https://worldwidecombos.com",
|
"https://worldwidecombos.com",
|
||||||
},
|
},
|
||||||
{"Tetris Friends",
|
{"Tetris Friends",
|
||||||
"tf tetrisfriends notrisfoes",
|
"tf tetrisfriends notrisfoes",
|
||||||
"game",
|
"game",
|
||||||
"*Web-based, no mobile support | Single-player and multiplayer*\nA now-defunct web-based Tetris game; used to be a decent battle game. An unofficial private server known as Notris Foes exists.\nBuilt using Flash, which might require workarounds to play or cannot run at all on your devices.",
|
"Browser Game | Singleplayer/Multiplayer\n or TF for short, a now-defunct official Tetris game. Used to be a popular game but now nobody plays it because the website was shut down. However an unofficial private server known as \"Notris Foes\" still exists and you will need to download desktop client for full experiences.",
|
||||||
},
|
},
|
||||||
{"tetris.com",
|
{"tetris.com",
|
||||||
"tetris online official",
|
"tetris online official",
|
||||||
"game",
|
"game",
|
||||||
"The Tetris game on tetris.com. It only has one mode – marathon, and you can control the game with your mouse.",
|
"Browser Game | Singleplayer\nThe Tetris game on tetris.com. It only has one mode — marathon, and you can control the game with your mouse.",
|
||||||
},
|
},
|
||||||
{"Tetris Gems",
|
{"Tetris Gems",
|
||||||
"tetris online official gem",
|
"tetris online official gem",
|
||||||
"game",
|
"game",
|
||||||
"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.",
|
"Browser Game | Singleplayer\nAnother 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 Mind Bender",
|
||||||
"tetris online official gem",
|
"tetris online official gem",
|
||||||
"game",
|
"game",
|
||||||
"Another Tetris game from tetris.com. It introduced \"Mind Bender\" minoes on the basis of marathon mode. Clearing a line with a Mind Bender mino will give you either a good or bad effect.",
|
"Browser Game | Singleplayer\nAnother Tetris game from tetris.com. It introduced \"Mind Bender\" minoes on the basis of marathon mode. Clearing a line with a Mind Bender mino will give you either a good or bad effect.",
|
||||||
|
},
|
||||||
|
|
||||||
|
{"Techmino",
|
||||||
|
"techmino",
|
||||||
|
"game",
|
||||||
|
"Cross-Platform | Singleplayer/Multiplayer\nOr Tech for short. A block stacker game developed using LÖVE. It has many single-player modes and many customizable parameters, and online multiplayer modes are gradually being developed.",
|
||||||
|
},
|
||||||
|
{"Falling Lightblocks",
|
||||||
|
"fl fallinglightblocks",
|
||||||
|
"game",
|
||||||
|
"Browser Game/iOS/Android | Singleplayer/Multiplayer\n A cross-platform Tetris game that can be played in portrait and landscape modes. It has fixed DAS and line clear ARE. Has some customizable controls on mobile. Most of the game modes are designed based on NES classic Tetris, but there are some modern-ish modes. Battles are half turn-based, half real-time, and garbage cannot be buffered or canceled.",
|
||||||
|
"https://golfgl.de/lightblocks/",
|
||||||
|
},
|
||||||
|
{"Cambridge",
|
||||||
|
"cambridge",
|
||||||
|
"game",
|
||||||
|
"Cross-Platform | Singleplayer\n A Tetris game developed using LÖVE and is dedicated to creating a robust, easily customizable platform for creating new, custom game modes. Originally made by Joe Zeng, but Milla took over the development on 08/Oct/2020 starting from V0.1.5.\n — Tetris Wiki",
|
||||||
|
},
|
||||||
|
{"Nanamino",
|
||||||
|
"nanamino",
|
||||||
|
"game",
|
||||||
|
"Windows/Android | Singleplayer\nA developing fan game which has a interesting original rotation system.",
|
||||||
},
|
},
|
||||||
|
|
||||||
{"TGM",
|
{"TGM",
|
||||||
"tgm tetrisgrandmaster tetristhegrandmaster",
|
"tgm tetrisgrandmaster tetristhegrandmaster",
|
||||||
"game",
|
"game",
|
||||||
"*Arcade | Single-player*\nTetris The Grand Master, an arcade Tetris series that can run on Microsoft Windows. Titles like S13 or GM come from this series.\n\nTGM3 is the most well-known game in this series.",
|
"Arcade | Singleplayer/Local Multiplayer\nTetris The Grand Master, an arcade Tetris series. Titles like S13 and GM come from this series.\n\nTGM3 is the most well-known game in this series.",
|
||||||
},
|
},
|
||||||
{"DTET",
|
{"DTET",
|
||||||
"dtet",
|
"dtet",
|
||||||
"game",
|
"game",
|
||||||
"*Windows | Single-player*\nA game based on TGM's Classic rule with 20G and a powerful rotation system. Decent controls, but has no customization other than control mappings. The game is a bit hard to find now and you might need to manually install required DLLs.",
|
"Windows | Singleplayer\nA game based on TGM's Classic rule with 20G and a powerful rotation system. Decent controls, but has no customization other than control mappings. The game is a bit hard to find now and you may need to manually install required DLLs.",
|
||||||
},
|
},
|
||||||
{"Heboris",
|
{"Heboris",
|
||||||
"hb heboris",
|
"hb heboris",
|
||||||
"game",
|
"game",
|
||||||
"*Windows*\nA game with Arcade-ish play style, simulates some modes of many Tetris games.",
|
"Windows | Singleplayer\nA game with Arcade-ish play style, capable of simulating many modes of other Tetris games.",
|
||||||
},
|
},
|
||||||
{"Texmaster",
|
{"Texmaster",
|
||||||
"txm texmaster",
|
"txm texmaster",
|
||||||
"game",
|
"game",
|
||||||
"*Windows | Single-player*\nA game with all modes from TGM which you can use to practice. Has better controls than actual TGM. The world rule is slightly different, however (eg, instant-lock soft drops, and slightly different kick tables)",
|
"Windows | Singleplayer\nA game with all modes from TGM which you can use to practice. The world rule is slightly different, however (e.g. instant-lock soft drops and slightly different kick tables).",
|
||||||
},
|
|
||||||
{"Cambridge",
|
|
||||||
"cambridge",
|
|
||||||
"game",
|
|
||||||
"*Windows, macOS, Linux | Single-player*\nA Lua-based game engine dedicated to creating a robust, easily customizable platform for creating new, custom game modes. It was originally made by Joe Zeng, and starting with version 0.1.5 on October 8, 2020, Milla took over development of the game.\n--Tetris Wiki",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{"Tetris99",
|
{"Tetris Effect",
|
||||||
|
"tec tetriseffectconnected",
|
||||||
|
"game",
|
||||||
|
"PS/Oculus Quest/Xbox/NS/Windows | Singleplayer/Multiplayer\nOr TE(C) for short. An official Tetris game with fancy graphics and soundtracks that react to your input. The basic version (without the word \"Connected\") only has singleplayer modes. The extended version, Tetris Effect Connected, features four online battle modes, Connected (VS), Zone Battle, Score Attack, and Classic Score Attack.",
|
||||||
|
},
|
||||||
|
{"Tetris 99",
|
||||||
"t99 tetris99",
|
"t99 tetris99",
|
||||||
"game",
|
"game",
|
||||||
"*Nintendo Switch | Multiplayer*\nA game famous for its 99-player battle royale mode and has many interesting strategies not present on traditional battle Tetris games. Also has limited single-player modes like Marathon and bot matches available as DLC.",
|
"Nintendo Switch | Singleplayer/Multiplayer\nA game famous for its 99-player battle royale mode and has many interesting strategies not present on traditional battle Tetris games. Also has limited single-player modes like Marathon and bot matches available as DLC.",
|
||||||
},
|
},
|
||||||
{"Puyo Puyo Tetris",
|
{"Puyo Puyo Tetris",
|
||||||
"ppt puyopuyotetris",
|
"ppt puyopuyotetris",
|
||||||
"game",
|
"game",
|
||||||
"*Multiple platforms | Single-player and multiplayer*\nA game that combines two games, Tetris and Puyo Puyo, and can battle between those two games. Has many modes for both single-player and online. The PC/Steam version has worse controls and horrible online experience, so it is not recommended.",
|
"PS/NS/Xbox/Windows | Singleplayer/multiplayer\nA game that combines two games, Tetris and Puyo Puyo, and can battle between those two games. Has many modes for both single-player and online\n\n[The Steam PC version has worse controls and horrible online experience.]",
|
||||||
},
|
},
|
||||||
{"Tetris Online",
|
{"Tetris Online",
|
||||||
"top tetrisonline",
|
"top tetrisonline",
|
||||||
"game",
|
"game",
|
||||||
"*Windows | Single-player and multiplayer*\nA now-defunct Japanese Tetris game with both online and single-player modes. Allows custom DAS/ARR but neither can be set to 0. Minor input delay. Private servers exist and is decent for new players to get started.",
|
"Windows | Singleplayer/Multiplayer*\nA now-defunct Japanese Tetris game with both online and single-player modes. Allows custom DAS/ARR but neither can be set to 0. Minor input delay. Private servers do exist and is decent for new players to get started.",
|
||||||
},
|
},
|
||||||
{"Tetris Effect",
|
{"Tetra Online",
|
||||||
"te tetriseffect",
|
"TO tetraonline",
|
||||||
"game",
|
"game",
|
||||||
"*PS4, Windows, Xbox | Single-player*\nFancy graphics and soundtrack that react to your actions. Not-so-good controls. You can have a go if you are into the visuals, but not exactly worth it if you are just trying to play some Tetris.",
|
"Windows/macOS/Linux | Singleplayer/Multiplayer\nTO for short. A Tetris game developed by Dr Ocelot and Mine. The delays are AREs are intentionally set to high values, and players who get used to Tetris games with no delays may not get used to this game.\nThe game was removed from Steam on 09/Dec/2020 due to a DMCA notice filed by TTC.\nHowever, an offline build can still be downloaded on GitHub.",
|
||||||
},
|
"https://github.com/Juan-Cartes/Tetra-Offline/releases/tag/1.0",
|
||||||
{"Techmino",
|
|
||||||
"techmino",
|
|
||||||
"game",
|
|
||||||
"*Windows, macOS, Android, Linux, iOS/iPadOS | Single-player and multiplayer*\nA game with many modes and loads of customization. Low input delay, decent controls.",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{"Cultris II",
|
{"Cultris II",
|
||||||
"c2 cultris2 cultrisii",
|
"c2 cultris2 cultrisii",
|
||||||
"game",
|
"game",
|
||||||
"*Windows, macOS, Linux | Single-player and multiplayer*\nA game focusing on speed. Has no hold and limited lockdown timer (like old school Tetris), but has customizable DAS/ARR. The main gimmick is its timer-based combos and emphasizes on speed, combo setups and digging.",
|
"Windows/OS X | Singleplayer/Multiplayer\nC2 for short. Designed based on classic Tetris, Cultris II supports customizable DAS and ARR. The battle mode is focused on time-based combos, which challenges players’ speed, n-wide setups, and downstacking skills.\n[The Mac version was not being maintained for a long time. Any macOS build newer than macOS Catalina cannot run this game at all.]",
|
||||||
},
|
},
|
||||||
{"Nullpomino",
|
{"Nullpomino",
|
||||||
"np nullpomino",
|
"np nullpomino",
|
||||||
"game",
|
"game",
|
||||||
"*Windows | Single-player and multiplayer*\nProfessional Tetris game with extreme room for customization. You can customize almost every aspect of the game. However, this is not a beginner-friendly game (you can get lost in the menus quite easily).",
|
"Windows/macOS/Linux | Singleplayer/Multiplayer\nOr NP for short. A high-customizable professional Tetris game. Nearly every parameter in the game can be adjusted.\n[But the UI was outdated, and this game requires full-keyboard controls. New players may have some problems getting used to it. Also, it seems that macOS Monterey cannot run this game.]",
|
||||||
},
|
|
||||||
{"Touhoumino",
|
|
||||||
"touhoumino",
|
|
||||||
"game",
|
|
||||||
"*Windows | Single-player*\nA Nullpomino mod with elements from Touhou Project. It is fun to play but difficult. Recommended for players with at least half-decent skills otherwise you don't even know how you die",
|
|
||||||
},
|
|
||||||
{"Nanamino",
|
|
||||||
"nanamino",
|
|
||||||
"game",
|
|
||||||
"*Windows, Android | Single-player*\nDeveloping game, has a interesting rotation system",
|
|
||||||
},
|
},
|
||||||
{"Misamino",
|
{"Misamino",
|
||||||
"misamino",
|
"misamino",
|
||||||
"game",
|
"game",
|
||||||
"*Windows | Single-player?*\nLocal 1-vs-1 game, mainly plays turn-based mode. You can write your own bot for it (though you need to learn its API if you do).\nMisamino is also the name of its built-in bot. Said bot is also the core for the Puyo Puyo Tetris bot, Zetris.",
|
"Windows | Single-player\nLocal 1V1 game, mainly plays turn-based mode. You can write your own bot for it (though you need to learn its API if you do).\nMisamino is also the name of its built-in bot.",
|
||||||
},
|
},
|
||||||
{"Tetris Journey",
|
{"Touhoumino",
|
||||||
"huanyouji tetrisjourney mobile phone",
|
"touhoumino",
|
||||||
"game",
|
"game",
|
||||||
"An official mobile Tetris game developed by Tencent (available only in China). It has level modes, battle modes, and some single-player modes. You can customize the sizes and positions of the virtual keys but you cannot adjust DAS or ARR.\n The battle mode lasts for 2 minutes and if both player did not top out, the one who sent more attacks wins."
|
"Windows | Singleplayer\nA fan-made Tetris game, basically Nullpomino with elements from Touhou Project. The \"Spellcards\" from Touhou was introduced in the game, and you can only get bonus scores if you can reach the target score within the given period of time.\n[Recommended for players with at least half-decent skills otherwise you don't even know how you die.]",
|
||||||
},
|
},
|
||||||
|
|
||||||
{"Tetris Blitz",
|
{"Tetris Blitz",
|
||||||
"blitz ea mobile phone",
|
"blitz ea mobile phone",
|
||||||
"game",
|
"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 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.",
|
"iOS/Android | Singleplayer\nA 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)",
|
||||||
"tetris ea galaxy universe cosmos mobile phone",
|
"tetris ea galaxy universe cosmos mobile phone",
|
||||||
"game",
|
"game",
|
||||||
"Another mobile Tetris game by EA. It has two control modes – Swipe and One-Touch. It also has a Galaxy Mode besides the Marathon Mode (with gravity mechanism), and the goal of this mode is to clear all Galaxy minoes before the sequence runs out.\n\nThis game is no longer available since April 2020."
|
"iOS/Android | Singleplayer/Multiplayer?\nAnother mobile Tetris game by EA. It has two control modes – Swipe and One-Touch. It also has a Galaxy Mode besides the Marathon Mode (with gravity mechanism), and the goal of this mode is to clear all Galaxy minoes before the sequence runs out.\n\nThis game is no longer available since April 2020."
|
||||||
},
|
},
|
||||||
{"Tetris (N3TWORK)",
|
{"Tetris (N3TWORK)",
|
||||||
"tetris n3twork mobile phone",
|
"tetris n3twork mobile phone",
|
||||||
"game",
|
"game",
|
||||||
"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.",
|
"iOS/Android | Singleplayer\nThe mobile Tetris game from N3TWORK Inc. It has a 3-minute ultra mode, a marathon mode and a 100-player Royale mode.\n[The UI is great but its controls are not so good.]",
|
||||||
},
|
},
|
||||||
{"Tetris Beat",
|
{"Tetris Beat",
|
||||||
"tetris beat n3twork rhythm",
|
"tetris beat n3twork rhythm",
|
||||||
"game",
|
"game",
|
||||||
"A mobile Tetris game from N3TWORK. It has a \"Beat\" mode besides the Marathon mode, but in this game you only have drop the blocks in rhythm with the BGM. The effects are very heavy and the controls are not so good."
|
"iOS | Singleplayer\nA mobile Tetris game from N3TWORK. It has a \"Beat\" mode besides the Marathon mode, but in this game you only have drop the blocks in rhythm with the BGM.\n[The effects are very heavy and the controls are not so good.]"
|
||||||
|
},
|
||||||
|
{"Tetris Journey",
|
||||||
|
"tetrisjourney mobile phone huanyouji",
|
||||||
|
"game",
|
||||||
|
"iOS/Android | Singleplayer\nAn official mobile Tetris game developed by Tencent (available exclusively in China). It has level modes, battle modes, and some single-player modes. You can customize the sizes and positions of the virtual keys but you cannot adjust DAS or ARR.\n The battle mode lasts for 2 minutes and if both player did not top out, the one who sent more attacks wins."
|
||||||
},
|
},
|
||||||
{"JJ Tetris",
|
{"JJ Tetris",
|
||||||
"jjtetris",
|
"jjtetris",
|
||||||
"game",
|
"game",
|
||||||
"*Android | Multiplayer*\n(JJ块)\nA casual game on JJ Card Games (JJ棋牌). Portrait screen, low input delay, smooth controls. Customizable DAS/ARR and toggle-able 20G soft drop, limited control scheme customization. No hold nor B2B, no garbage buffer nor cancelling. Every attack sends at most 4 lines, combos are more powerful, otherwise similar to modern Tetris.",
|
"Android | Multiplayer\n(JJ块)\nA casual game on JJ Card Games (JJ棋牌). Portrait screen, low input delay, smooth controls. Customizable DAS/ARR and toggle-able 20G soft drop, limited control scheme customization. No hold nor B2B, no garbage buffer nor cancelling. Every attack sends at most 4 lines, combos are more powerful, otherwise similar to modern Tetris.",
|
||||||
},
|
|
||||||
{"Falling lightblock",
|
|
||||||
"fl fallinglightblock",
|
|
||||||
"game",
|
|
||||||
"*Android, iOS, Web | Single-player and multiplayer*\nA game that supports many platforms. Has delays that cannot be adjusted. Can, to some extent, customize controls on mobile. Most of the modes are similar to classic Tetris, but modern-ish modes also exist. Battles are half-turn-based-half-real-time, and garbage cannot be buffered or cancelled.",
|
|
||||||
"https://golfgl.de/lightblocks/",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{"Huopin Tetris",
|
{"Huopin Tetris",
|
||||||
"huopin qq",
|
"huopin qq",
|
||||||
"game",
|
"game",
|
||||||
"*Windows | Multiplayer*\n(火拼俄罗斯)\n\nThe Tetris game on Tencent Game Center, 12-wide board, DAS/ARR the same as your typing, 1 next, no hold. Can only send garbage through Tetris (sends 3 lines) and Triple (sends 2 lines). Garbage is checker-board-shaped and is very difficult to dig through.",
|
"Windows | Multiplayer\n(火拼俄罗斯)\n\nThe Tetris game on Tencent Game Center, 12-wide board, DAS/ARR the same as your typing, 1 next, no hold. Can only send garbage through Tetris (sends 3 lines) and Triple (sends 2 lines). Garbage is checker-board-shaped and is nearly impossible to dig through.",
|
||||||
},
|
},
|
||||||
|
|
||||||
--Terms
|
--Terms
|
||||||
@@ -744,7 +771,7 @@ return{
|
|||||||
"For advanced players who want to play faster, the recommended values are DAS 4-6f (67-100ms), ARR 0f (0ms). (At 0ms ARR, pieces will instantly snap to the wall once you get past DAS.)\n\nThe ideal configuration strategy for advanced players is to minimize DAS while still being able to reliably control whether to tap or hold, and to set to ARR to 0 if possible, or as low as possible otherwise.",
|
"For advanced players who want to play faster, the recommended values are DAS 4-6f (67-100ms), ARR 0f (0ms). (At 0ms ARR, pieces will instantly snap to the wall once you get past DAS.)\n\nThe ideal configuration strategy for advanced players is to minimize DAS while still being able to reliably control whether to tap or hold, and to set to ARR to 0 if possible, or as low as possible otherwise.",
|
||||||
},
|
},
|
||||||
{"DAS cut",
|
{"DAS cut",
|
||||||
"dascut",
|
"dascut dcd",
|
||||||
"term",
|
"term",
|
||||||
"Techmino exclusive: in Techmino, the DAS timer can be cleared or discharged for a short time when the player starts to control a new piece. This can reduce the case where a piece instantly starts moving if spawned with a direction button held.\n\nOther games may have a similar feature but may function differently.",
|
"Techmino exclusive: in Techmino, the DAS timer can be cleared or discharged for a short time when the player starts to control a new piece. This can reduce the case where a piece instantly starts moving if spawned with a direction button held.\n\nOther games may have a similar feature but may function differently.",
|
||||||
},
|
},
|
||||||
@@ -788,6 +815,16 @@ return{
|
|||||||
"term",
|
"term",
|
||||||
"Vibrate your finger on the controller to achieve faster sideways movement speed than holding it.\nIt is most commonly used on classic Tetris where DAS is rather slow. In most cases, you do not need to hypertap in modern Tetris games, because their DAS is often fast enough.",
|
"Vibrate your finger on the controller to achieve faster sideways movement speed than holding it.\nIt is most commonly used on classic Tetris where DAS is rather slow. In most cases, you do not need to hypertap in modern Tetris games, because their DAS is often fast enough.",
|
||||||
},
|
},
|
||||||
|
{"Rolling",
|
||||||
|
"rolling",
|
||||||
|
"term",
|
||||||
|
"Another method of fast-tapping in high-gravity (around 1G) modes (with slow DAS/ARR setting).\nWhen you perform rolling, you fix the position of one hand and the controller, and then tap the back of the controller with fingers on your other hand repeatedly. This method allows even faster moving speeds than hypertapping (see \"Hypertapping\" for more)and requires much less effort.\nThis method was first discovered by Cheez-fish and he has once achieved a tapping speed of more than 20 Hz.",
|
||||||
|
},
|
||||||
|
{"Passthrough",
|
||||||
|
"passthrough pingthrough",
|
||||||
|
"term",
|
||||||
|
"",--TODO
|
||||||
|
},
|
||||||
{"Tetris OL attack",
|
{"Tetris OL attack",
|
||||||
"top tetrisonlineattack",
|
"top tetrisonlineattack",
|
||||||
"term",
|
"term",
|
||||||
@@ -854,12 +891,12 @@ return{
|
|||||||
"Any input device takes some time for the input to reach the game. This delay can range from a few milliseconds to a few dozen milliseconds.\nIf input delay is too long, the controls can feel uncomfortable.\nThis delay is often due to the performance of the hardware and software used, and often out of your control. Turn on performance mode (or turn off power saving mode) on your device, and turn on gaming mode on your monitor/TV (if you have one), may help reducing input delay.",
|
"Any input device takes some time for the input to reach the game. This delay can range from a few milliseconds to a few dozen milliseconds.\nIf input delay is too long, the controls can feel uncomfortable.\nThis delay is often due to the performance of the hardware and software used, and often out of your control. Turn on performance mode (or turn off power saving mode) on your device, and turn on gaming mode on your monitor/TV (if you have one), may help reducing input delay.",
|
||||||
},
|
},
|
||||||
{"Cold Clear",
|
{"Cold Clear",
|
||||||
"cc coldclear",
|
"cc coldclear ai bot",
|
||||||
"term",
|
"term",
|
||||||
"A Tetris bot. Originally built for Puyo Puyo Tetris, thus can be less powerful on Techmino.",
|
"A Tetris bot. Originally built for Puyo Puyo Tetris, thus can be less powerful on Techmino.",
|
||||||
},
|
},
|
||||||
{"ZZZbot",
|
{"ZZZbot",
|
||||||
"zzzbot",
|
"zzzbot ai bot",
|
||||||
"term",
|
"term",
|
||||||
"A Tetris bot. Built by the Chinese Tetris player 奏之章 (Zou Zhi Zhang) and has decent performance in many games",
|
"A Tetris bot. Built by the Chinese Tetris player 奏之章 (Zou Zhi Zhang) and has decent performance in many games",
|
||||||
},
|
},
|
||||||
@@ -1021,9 +1058,9 @@ return{
|
|||||||
|
|
||||||
--Savedata managing
|
--Savedata managing
|
||||||
{"Console",
|
{"Console",
|
||||||
"console cmd commamd minglinghang kongzhitai",
|
"console cmd commamd minglinghang kongzhitai terminal",
|
||||||
"command",
|
"command",
|
||||||
"Techmino has a console that enables debugging/advanced features.\nTo access the console, repeatedly tap the Techmino logo or press the C key on the keyboard on the main menu.\n\nCareless actions in the console may result in corrupting or losing saved data. Proceed at your own risk.",
|
"Techmino has a console that enables debugging/advanced features.\nTo access the console, repeatedly tap (or click) the Techmino logo or press the C key on the keyboard on the main menu.\n\nCareless actions in the console may result in corrupting or losing saved data. Proceed at your own risk.",
|
||||||
},
|
},
|
||||||
{"Reset setting",
|
{"Reset setting",
|
||||||
"reset setting",
|
"reset setting",
|
||||||
@@ -1127,7 +1164,7 @@ return{
|
|||||||
{"Jonas",
|
{"Jonas",
|
||||||
"jonas",
|
"jonas",
|
||||||
"name",
|
"name",
|
||||||
"One of the top players in Classic Tetris.\nFour-times-in-a-row champion of CTWC.\n\n(1981-2021)",
|
"(1981-2021) One of the top players in Classic Tetris.\nFour-times-in-a-row champion of CTWC.",
|
||||||
},
|
},
|
||||||
{"Joseph",
|
{"Joseph",
|
||||||
"joseph",
|
"joseph",
|
||||||
@@ -1167,10 +1204,10 @@ return{
|
|||||||
{"TetroDictionary",
|
{"TetroDictionary",
|
||||||
"zictionary tetrodictionary littlez",
|
"zictionary tetrodictionary littlez",
|
||||||
"name",
|
"name",
|
||||||
"(or Zictionary for short) The name of this dictionary!\nIt includes brief introductions on many common terms in Tetris.\nIt used to be a chatbot in our QQ group, which was used to answer new player's FAQs. The entries in the Tetrodictionary were also inherited from the database in the chatbot.",
|
"(or Zictionary for short) The name of this dictionary!\nIt includes brief introductions on many common terms in Tetris.\nIt used to be a chatbot in our QQ group, which was used to answer new player's FAQs. The entries in the Tetrodictionary were also inherited from the database in the chatbot.\nThe contents in the TetroDictionary was adapted from a variety of sources such as Tetris Wiki and Hard Drop Wiki.",
|
||||||
},
|
},
|
||||||
{"MrZ",
|
{"MrZ",
|
||||||
"mrz_26",
|
"mrz_26 t026 t626",
|
||||||
"name",
|
"name",
|
||||||
"Tetris Research community member, the author of Techmino.\nPersonal bests: Sprint 25.95 seconds, MPH Sprint 57 seconds, #8 on Jstris leaderboards, X rank on TETR.IO, cleared TGM3 (World rule, Shirase gold 1300).",
|
"Tetris Research community member, the author of Techmino.\nPersonal bests: Sprint 25.95 seconds, MPH Sprint 57 seconds, #8 on Jstris leaderboards, X rank on TETR.IO, cleared TGM3 (World rule, Shirase gold 1300).",
|
||||||
"https://space.bilibili.com/225238922",
|
"https://space.bilibili.com/225238922",
|
||||||
@@ -1179,7 +1216,7 @@ return{
|
|||||||
{"Circu1ation",
|
{"Circu1ation",
|
||||||
"circu1ation",
|
"circu1ation",
|
||||||
"name",
|
"name",
|
||||||
"One of the top players. First one to achieve sub-20 Sprint in China, X rank on TETR.IO.",
|
"One of the top players. First one to achieve sub-20 40L Sprint in China, X rank on TETR.IO.",
|
||||||
"https://space.bilibili.com/557547205",
|
"https://space.bilibili.com/557547205",
|
||||||
},
|
},
|
||||||
{"Farter",
|
{"Farter",
|
||||||
@@ -1260,7 +1297,7 @@ return{
|
|||||||
"https://space.bilibili.com/109356367",
|
"https://space.bilibili.com/109356367",
|
||||||
},
|
},
|
||||||
{"ZXC",
|
{"ZXC",
|
||||||
"zxc thtsod",
|
"zxc thtsod flag ctf",
|
||||||
"name",
|
"name",
|
||||||
"Also known as ThTsOd.\nTetris Research community member.\nA technical player.",
|
"Also known as ThTsOd.\nTetris Research community member.\nA technical player.",
|
||||||
"https://space.bilibili.com/4610502",
|
"https://space.bilibili.com/4610502",
|
||||||
@@ -1284,7 +1321,7 @@ return{
|
|||||||
"https://space.bilibili.com/471341780",
|
"https://space.bilibili.com/471341780",
|
||||||
},
|
},
|
||||||
{"思竣",
|
{"思竣",
|
||||||
"sijun",
|
"sijun acm oi",
|
||||||
"name",
|
"name",
|
||||||
"(Sī Jùn)\n\nTetris Research community member.\nLots of mental computation power.",
|
"(Sī Jùn)\n\nTetris Research community member.\nLots of mental computation power.",
|
||||||
"https://space.bilibili.com/403250559",
|
"https://space.bilibili.com/403250559",
|
||||||
|
|||||||