Merge branch 'main' into main
This commit is contained in:
@@ -4,6 +4,7 @@ local cmds={
|
||||
trans="translate",
|
||||
scale="scale",
|
||||
rotat="rotate",
|
||||
clear="clear",
|
||||
|
||||
setCL="setColor",
|
||||
setCM="setColorMask",
|
||||
|
||||
@@ -14,7 +14,6 @@ ADRAW=require"Zframework.aDraw"
|
||||
mDraw=ADRAW.draw
|
||||
|
||||
JSON=require"Zframework.json"
|
||||
|
||||
TABLE=require"Zframework.tableExtend"
|
||||
STRING=require"Zframework.stringExtend"
|
||||
|
||||
@@ -103,7 +102,7 @@ function love.mousepressed(x,y,k,touch)
|
||||
mouseShow=true
|
||||
mx,my=xOy:inverseTransformPoint(x,y)
|
||||
if devMode==1 then
|
||||
DBP(("(%d,%d)<-%d,%d ~~(%d,%d)<-%d,%d"):format(
|
||||
print(("(%d,%d)<-%d,%d ~~(%d,%d)<-%d,%d"):format(
|
||||
mx,my,
|
||||
mx-lastX,my-lastY,
|
||||
int(mx/10)*10,int(my/10)*10,
|
||||
@@ -208,8 +207,8 @@ local function noDevkeyPressed(key)
|
||||
end
|
||||
end
|
||||
elseif key=="f4"then if not kb.isDown("lalt","ralt")then LOG.copy()end
|
||||
elseif key=="f5"then if WIDGET.sel then DBP(WIDGET.sel)end
|
||||
elseif key=="f6"then for k,v in next,_G do DBP(k,v)end
|
||||
elseif key=="f5"then if WIDGET.sel then print(WIDGET.sel)end
|
||||
elseif key=="f6"then for k,v in next,_G do print(k,v)end
|
||||
elseif key=="f7"then if love._openConsole then love._openConsole()end
|
||||
elseif key=="f8"then devMode=nil LOG.print("DEBUG OFF",COLOR.Y)
|
||||
elseif key=="f9"then devMode=1 LOG.print("DEBUG 1",COLOR.Y)
|
||||
@@ -372,7 +371,7 @@ function love.errorhandler(msg)
|
||||
c=3
|
||||
end
|
||||
end
|
||||
DBP(table.concat(err,"\n",1,c-2))
|
||||
print(table.concat(err,"\n",1,c-2))
|
||||
|
||||
--Reset something
|
||||
love.audio.stop()
|
||||
|
||||
@@ -9,29 +9,34 @@ return function(name,libName)
|
||||
elseif SYSTEM=="Android"then
|
||||
local fs=love.filesystem
|
||||
local platform={"arm64-v8a","armeabi-v7a"}
|
||||
local libFunc
|
||||
for i=1,#platform do
|
||||
local soFile,size=fs.read("data","libAndroid/"..platform[i].."/"..libName.Android)
|
||||
if soFile then
|
||||
local success,message=fs.write(libName.Android,soFile,size)
|
||||
if success then
|
||||
libFunc,message=package.loadlib(table.concat({SAVEDIR,libName.Android},"/"),libName.libFunc)
|
||||
if libFunc then
|
||||
LOG.print(name.." lib loaded","warn",COLOR.G)
|
||||
break
|
||||
|
||||
local libFunc=package.loadlib(SAVEDIR.."/lib/"..libName.Android,libName.libFunc)
|
||||
if libFunc then
|
||||
LOG.print(name.." lib loaded","warn",COLOR.G)
|
||||
else
|
||||
for i=1,#platform do
|
||||
local soFile=fs.read("data","libAndroid/"..platform[i].."/"..libName.Android)
|
||||
if soFile then
|
||||
local success,message=fs.write("lib/"..libName.Android,soFile)
|
||||
if success then
|
||||
libFunc,message=package.loadlib(SAVEDIR.."/lib/"..libName.Android,libName.libFunc)
|
||||
if libFunc then
|
||||
LOG.print(name.." lib loaded","warn",COLOR.G)
|
||||
break
|
||||
else
|
||||
LOG.print("Cannot load "..name..": "..message,"warn",COLOR.R)
|
||||
end
|
||||
else
|
||||
LOG.print("Cannot load "..name..": "..message,"warn",COLOR.R)
|
||||
LOG.print("Write "..name.."-"..platform[i].." to saving failed: "..message,"warn",COLOR.R)
|
||||
end
|
||||
else
|
||||
LOG.print("Write "..name.."-"..platform[i].." to saving failed: "..message,"warn",COLOR.R)
|
||||
LOG.print("Read "..name.."-"..platform[i].." failed","warn",COLOR.R)
|
||||
end
|
||||
else
|
||||
LOG.print("Read "..name.."-"..platform[i].." failed","warn",COLOR.R)
|
||||
end
|
||||
end
|
||||
if not libFunc then
|
||||
LOG.print("Cannot load "..name,"warn",COLOR.R)
|
||||
return
|
||||
if not libFunc then
|
||||
LOG.print("Cannot load "..name,"warn",COLOR.R)
|
||||
return
|
||||
end
|
||||
end
|
||||
return libFunc()
|
||||
else
|
||||
|
||||
@@ -6,7 +6,7 @@ local host="game.techmino.org"
|
||||
local port="10026"
|
||||
local path="/tech/socket/v1"
|
||||
|
||||
local debug=false
|
||||
local debug=""--S:send, R:receive, M=mark
|
||||
|
||||
local wsThread=[[
|
||||
-- lua + love2d threading websocket client
|
||||
@@ -87,6 +87,7 @@ local _send do
|
||||
local mask_str=char(unpack(mask_key))
|
||||
|
||||
function _send(op,message)
|
||||
]]..(debug:find"S"and""or"--")..[[print((">> %s[%d]:%s"):format(threadName,#message,message))
|
||||
--Message type
|
||||
SOCK:send(char(bor(0x80,op)))
|
||||
|
||||
@@ -153,7 +154,7 @@ while true do--Running
|
||||
if s then
|
||||
res=s
|
||||
elseif p then--UNF head
|
||||
]]..(debug==1 and""or"--")..[[print(("%s[%d/%d]:%s"):format(threadName,#p,length,p))
|
||||
]]..(debug:find"R"and""or"--")..[[print(("<< %s[%d/%d]:%s"):format(threadName,#p,length,#p<50 and p or p:sub(1,50)))
|
||||
UFF=true
|
||||
sBuffer=sBuffer..p
|
||||
length=length-#p
|
||||
@@ -165,11 +166,11 @@ while true do--Running
|
||||
else
|
||||
local s,e,p=SOCK:receive(length)
|
||||
if s then
|
||||
]]..(debug==1 and""or"--")..[[print(("%s<%d>:%s"):format(threadName,length,s))
|
||||
]]..(debug:find"R"and""or"--")..[[print(("<< %s(%d):%s"):format(threadName,length,#s<50 and s or s:sub(1,50)))
|
||||
sBuffer=sBuffer..s
|
||||
length=length-#s
|
||||
elseif p then
|
||||
]]..(debug==1 and""or"--")..[[print(("%s<%d>:%s"):format(threadName,length,p))
|
||||
]]..(debug:find"R"and""or"--")..[[print(("<< %s(%d):%s"):format(threadName,length,#p<50 and p or p:sub(1,50)))
|
||||
sBuffer=sBuffer..p
|
||||
length=length-#p
|
||||
end
|
||||
@@ -180,7 +181,7 @@ while true do--Running
|
||||
break
|
||||
end
|
||||
end
|
||||
]]..(debug==1 and""or"--")..[[print(("%s<[%d]>:%s"):format(threadName,#res,res))
|
||||
]]..(debug:find"R"and""or"--")..[[print(("<< %s[(%d)]:%s"):format(threadName,#res,#res<800 and res or res:sub(1,150).."\n...\n"..res:sub(-150)))
|
||||
|
||||
--React
|
||||
if op==8 then--8=close
|
||||
@@ -195,21 +196,21 @@ while true do--Running
|
||||
elseif op==0 then--0=continue
|
||||
lBuffer=lBuffer..res
|
||||
if fin then
|
||||
]]..(debug==2 and""or"--")..[[print("FIN=1 (c")
|
||||
]]..(debug:find"M"and""or"--")..[[print("FIN=1 (c")
|
||||
readCHN:push(lBuffer)
|
||||
lBuffer=""
|
||||
else
|
||||
]]..(debug==2 and""or"--")..[[print("FIN=0 (c")
|
||||
]]..(debug:find"M"and""or"--")..[[print("FIN=0 (c")
|
||||
end
|
||||
else
|
||||
readCHN:push(op)
|
||||
if fin then
|
||||
]]..(debug==2 and""or"--")..[[print("OP: "..op.."\tFIN=1")
|
||||
]]..(debug:find"M"and""or"--")..[[print("OP: "..op.."\tFIN=1")
|
||||
readCHN:push(res)
|
||||
else
|
||||
]]..(debug==2 and""or"--")..[[print("OP: "..op.."\tFIN=0")
|
||||
]]..(debug:find"M"and""or"--")..[[print("OP: "..op.."\tFIN=0")
|
||||
sBuffer=res
|
||||
]]..(debug==2 and""or"--")..[[print("START pack: "..res)
|
||||
]]..(debug:find"M"and""or"--")..[[print("START pack: "..res)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,10 +9,12 @@ local COLOR=COLOR
|
||||
local setFont,mStr=setFont,mStr
|
||||
local mDraw_X,mDraw_Y=ADRAW.simpX,ADRAW.simpY
|
||||
|
||||
local allowNoText={
|
||||
image=true,
|
||||
inputBox=true,
|
||||
textBox=true,
|
||||
local mustHaveText={
|
||||
text=true,
|
||||
button=true,
|
||||
key=true,
|
||||
switch=true,
|
||||
selector=true,
|
||||
}
|
||||
|
||||
local WIDGET={}
|
||||
@@ -40,13 +42,12 @@ function text:draw()
|
||||
if self.alpha>0 then
|
||||
local c=self.color
|
||||
gc.setColor(c[1],c[2],c[3],self.alpha)
|
||||
local obj=self.obj
|
||||
if self.align=="M"then
|
||||
mDraw_X(obj,self.x,self.y)
|
||||
mDraw_X(self.obj,self.x,self.y)
|
||||
elseif self.align=="L"then
|
||||
gc.draw(obj,self.x,self.y)
|
||||
gc.draw(self.obj,self.x,self.y)
|
||||
elseif self.align=="R"then
|
||||
gc.draw(obj,self.x-obj:getWidth(),self.y)
|
||||
gc.draw(self.obj,self.x-self.obj:getWidth(),self.y)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -270,7 +271,7 @@ function key:draw()
|
||||
elseif self.align=="L"then
|
||||
mDraw_Y(self.obj,x+self.edge,y+h*.5)
|
||||
elseif self.align=="R"then
|
||||
mDraw_Y(self.obj,self.x-self.edge-self.obj:getWidth(),y+h*.5)
|
||||
mDraw_Y(self.obj,x+w-self.edge-self.obj:getWidth(),y+h*.5)
|
||||
end
|
||||
end
|
||||
function key:getInfo()
|
||||
@@ -356,9 +357,8 @@ function switch:draw()
|
||||
gc.rectangle("line",x,y,50,50)
|
||||
|
||||
--Drawable
|
||||
local obj=self.obj
|
||||
gc.setColor(self.color)
|
||||
mDraw_Y(obj,x-12-ATV-obj:getWidth(),y+25)
|
||||
mDraw_Y(self.obj,x-12-ATV-self.obj:getWidth(),y+25)
|
||||
end
|
||||
function switch:getInfo()
|
||||
return format("x=%d,y=%d,font=%d",self.x,self.y,self.font)
|
||||
@@ -478,9 +478,10 @@ function slider:draw()
|
||||
end
|
||||
|
||||
--Drawable
|
||||
local obj=self.obj
|
||||
gc.setColor(self.color)
|
||||
mDraw_Y(obj,x-12-ATV-obj:getWidth(),y)
|
||||
if self.obj then
|
||||
gc.setColor(self.color)
|
||||
mDraw_Y(self.obj,x-12-ATV-self.obj:getWidth(),y)
|
||||
end
|
||||
end
|
||||
function slider:getInfo()
|
||||
return format("x=%d,y=%d,w=%d",self.x,self.y,self.w)
|
||||
@@ -757,9 +758,8 @@ function inputBox:draw()
|
||||
|
||||
--Drawable
|
||||
setFont(self.font)
|
||||
local obj=self.obj
|
||||
if obj then
|
||||
mDraw_Y(obj,x-12-obj:getWidth(),y+h*.5)
|
||||
if self.obj then
|
||||
mDraw_Y(self.obj,x-12-self.obj:getWidth(),y+h*.5)
|
||||
end
|
||||
if self.secret then
|
||||
for i=1,#self.value do
|
||||
@@ -909,7 +909,7 @@ function textBox:draw()
|
||||
|
||||
--Frame
|
||||
gc.setLineWidth(4)
|
||||
gc.setColor(COLOR[WIDGET.sel==self and"Y"or"W"])
|
||||
gc.setColor(COLOR[WIDGET.sel==self and"Y"or"Z"])
|
||||
gc.rectangle("line",x,y,w,h)
|
||||
|
||||
--Slider
|
||||
@@ -1016,7 +1016,7 @@ function WIDGET.setLang(widgetText)
|
||||
if L.widgetList then
|
||||
for _,W in next,L.widgetList do
|
||||
local t=W.fText or widgetText[S][W.name]
|
||||
if not t and not allowNoText[W.type]then
|
||||
if not t and mustHaveText[W.type]then
|
||||
t=W.name or"##"
|
||||
W.color=COLOR.dV
|
||||
end
|
||||
|
||||
58
main.lua
58
main.lua
@@ -13,7 +13,7 @@
|
||||
goto REM love=require"love"::REM::--Just tell IDE to load love-api, no actual usage
|
||||
local fs=love.filesystem
|
||||
NONE={}function NULL()end
|
||||
DBP=print--Use this in permanent code
|
||||
DBP=print--Use this in temporary code, easy to find and remove
|
||||
TIME=love.timer.getTime
|
||||
YIELD=coroutine.yield
|
||||
SYSTEM=love.system.getOS()
|
||||
@@ -34,14 +34,16 @@ love.keyboard.setTextInput(false)
|
||||
love.mouse.setVisible(false)
|
||||
|
||||
--Delete all files from too old version
|
||||
for _,name in next,fs.getDirectoryItems("")do
|
||||
if fs.getRealDirectory(name)==SAVEDIR and fs.getInfo(name).type~="directory"then
|
||||
fs.remove(name)
|
||||
function CLEAR(root)
|
||||
for _,name in next,fs.getDirectoryItems(root or"")do
|
||||
if fs.getRealDirectory(name)==SAVEDIR and fs.getInfo(name).type~="directory"then
|
||||
fs.remove(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end CLEAR()
|
||||
|
||||
--Create directories
|
||||
for _,v in next,{"conf","record","replay","cache"}do
|
||||
for _,v in next,{"conf","record","replay","cache","lib"}do
|
||||
local info=fs.getInfo(v)
|
||||
if not info then
|
||||
fs.createDirectory(v)
|
||||
@@ -53,24 +55,28 @@ end
|
||||
|
||||
--Load modules
|
||||
require"Zframework"
|
||||
SCR.setSize(1280,720)--Initialize Screen size
|
||||
|
||||
require"parts.list"
|
||||
require"parts.globalTables"
|
||||
require"parts.gametoolfunc"
|
||||
SCR.setSize(1280,720)--Initialize Screen size
|
||||
FIELD[1]=newBoard()--Initialize field[1]
|
||||
|
||||
NET= require"parts.net"
|
||||
AIBUILDER= require"parts.AITemplate"
|
||||
FREEROW= require"parts.freeRow"
|
||||
USERS= require"parts.users"
|
||||
DATA= require"parts.data"
|
||||
|
||||
USERS= require"parts.users"
|
||||
TEXTURE= require"parts.texture"
|
||||
SKIN= require"parts.skin"
|
||||
NET= require"parts.net"
|
||||
VK= require"parts.virtualKey"
|
||||
PLY= require"parts.player"
|
||||
AIFUNC= require"parts.ai"
|
||||
AIBUILDER= require"parts.AITemplate"
|
||||
MODES= require"parts.modes"
|
||||
|
||||
--Initialize field[1]
|
||||
FIELD[1]=DATA.newBoard()
|
||||
|
||||
--First start for phones
|
||||
if not fs.getInfo("conf/settings")and MOBILE then
|
||||
SETTING.VKSwitch=true
|
||||
@@ -234,11 +240,9 @@ do
|
||||
local needSave
|
||||
local autoRestart
|
||||
|
||||
if STAT.extraRate then
|
||||
STAT.finesseRate=5*(STAT.piece-STAT.extraRate)
|
||||
end
|
||||
if type(STAT.version)~="number"then
|
||||
STAT.version=0
|
||||
needSave=true
|
||||
end
|
||||
if STAT.version<1300 then
|
||||
STAT.frame=math.floor(STAT.time*60)
|
||||
@@ -264,6 +268,10 @@ do
|
||||
needSave=true
|
||||
autoRestart=true
|
||||
end
|
||||
if STAT.version<1405 then
|
||||
fs.remove("conf/user")
|
||||
autoRestart=true
|
||||
end
|
||||
|
||||
for _,v in next,VK_org do
|
||||
if not v.color then
|
||||
@@ -273,6 +281,14 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
if STAT.version~=VERSION.code then
|
||||
newVersionLaunch=true
|
||||
STAT.version=VERSION.code
|
||||
CLEAR("lib")
|
||||
needSave=true
|
||||
autoRestart=true
|
||||
end
|
||||
|
||||
if RANKS.GM then RANKS.GM=0 end
|
||||
if RANKS.infinite then RANKS.infinite=6 end
|
||||
if RANKS.infinite_dig then RANKS.infinite_dig=6 end
|
||||
@@ -303,17 +319,15 @@ do
|
||||
needSave=true
|
||||
end
|
||||
|
||||
if STAT.version~=VERSION.code then
|
||||
newVersionLaunch=true
|
||||
STAT.version=VERSION.code
|
||||
FILE.save(STAT,"conf/data","q")
|
||||
end
|
||||
|
||||
if needSave then
|
||||
FILE.save(RANKS,"conf/unlock","q")
|
||||
FILE.save(SETTING,"conf/settings","q")
|
||||
FILE.save(RANKS,"conf/unlock","q")
|
||||
FILE.save(STAT,"conf/data","q")
|
||||
end
|
||||
if autoRestart then
|
||||
love.event.quit("restart")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Var leak check
|
||||
-- setmetatable(_G,{__newindex=function(self,k,v)print('>>'..k,tostring(v))rawset(self,k,v)end})
|
||||
394
parts/data.lua
Normal file
394
parts/data.lua
Normal file
@@ -0,0 +1,394 @@
|
||||
local data=love.data
|
||||
|
||||
local int=math.floor
|
||||
local char,byte=string.char,string.byte
|
||||
local ins=table.insert
|
||||
|
||||
local DATA={}
|
||||
--Sep symbol: 33 (!)
|
||||
--Safe char: 34~126
|
||||
--[[
|
||||
Count: 34~96
|
||||
Block: 97~125
|
||||
Encode: A[B] sequence, A = block ID, B = repeat times, no B means do not repeat.
|
||||
Example: "abcdefg" is [SZJLTOI], "a^aDb)" is [Z*63,Z*37,S*10]
|
||||
]]
|
||||
function DATA.copySequence()
|
||||
local BAG=BAG
|
||||
local str=""
|
||||
|
||||
local count=1
|
||||
for i=1,#BAG+1 do
|
||||
if BAG[i+1]~=BAG[i]or count==64 then
|
||||
str=str..char(96+BAG[i])
|
||||
if count>1 then
|
||||
str=str..char(32+count)
|
||||
count=1
|
||||
end
|
||||
else
|
||||
count=count+1
|
||||
end
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
function DATA.pasteSequence(str)
|
||||
local b
|
||||
|
||||
local bag={}
|
||||
local reg
|
||||
for i=1,#str do
|
||||
b=byte(str,i)
|
||||
if not reg then
|
||||
if b>=97 and b<=125 then
|
||||
reg=b-96
|
||||
else
|
||||
return
|
||||
end
|
||||
else
|
||||
if b>=97 and b<=125 then
|
||||
ins(bag,reg)
|
||||
reg=b-96
|
||||
elseif b>=34 and b<=96 then
|
||||
for _=1,b-32 do
|
||||
ins(bag,reg)
|
||||
end
|
||||
reg=false
|
||||
end
|
||||
end
|
||||
end
|
||||
if reg then
|
||||
ins(bag,reg)
|
||||
end
|
||||
|
||||
BAG=bag
|
||||
return true
|
||||
end
|
||||
|
||||
function DATA.newBoard(f)--Generate a new board
|
||||
if f then
|
||||
return TABLE.shift(f)
|
||||
else
|
||||
local F={}
|
||||
for i=1,20 do F[i]={0,0,0,0,0,0,0,0,0,0}end
|
||||
return F
|
||||
end
|
||||
end
|
||||
function DATA.copyBoard(page)--Copy the [page] board
|
||||
local F=FIELD[page or 1]
|
||||
local str=""
|
||||
local H=0
|
||||
|
||||
for y=20,1,-1 do
|
||||
for x=1,10 do
|
||||
if F[y][x]~=0 then
|
||||
H=y
|
||||
goto BREAK_topFound
|
||||
end
|
||||
end
|
||||
end
|
||||
::BREAK_topFound::
|
||||
|
||||
--Encode field
|
||||
for y=1,H do
|
||||
local S=""
|
||||
local L=F[y]
|
||||
for x=1,10 do
|
||||
S=S..char(L[x]+1)
|
||||
end
|
||||
str=str..S
|
||||
end
|
||||
return data.encode("string","base64",data.compress("string","zlib",str))
|
||||
end
|
||||
function DATA.copyBoards()
|
||||
local out={}
|
||||
for i=1,#FIELD do
|
||||
out[i]=DATA.copyBoard(i)
|
||||
end
|
||||
return table.concat(out,"!")
|
||||
end
|
||||
function DATA.pasteBoard(str,page)--Paste [str] data to [page] board
|
||||
if not page then page=1 end
|
||||
if not FIELD[page]then FIELD[page]=DATA.newBoard()end
|
||||
local F=FIELD[page]
|
||||
local _,__
|
||||
|
||||
--Decode
|
||||
_,str=pcall(data.decode,"string","base64",str)
|
||||
if not _ then return end
|
||||
_,str=pcall(data.decompress,"string","zlib",str)
|
||||
if not _ then return end
|
||||
|
||||
local fX,fY=1,1--*ptr for Field(r*10+(c-1))
|
||||
local p=1
|
||||
while true do
|
||||
_=byte(str,p)--1byte
|
||||
|
||||
--Str end
|
||||
if not _ then
|
||||
if fX~=1 then
|
||||
return
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
__=_%32-1--Block id
|
||||
if __>26 then return end--Illegal blockid
|
||||
_=int(_/32)--Mode id
|
||||
|
||||
F[fY][fX]=__
|
||||
if fX<10 then
|
||||
fX=fX+1
|
||||
else
|
||||
fY=fY+1
|
||||
if fY>20 then break end
|
||||
fX=1
|
||||
end
|
||||
p=p+1
|
||||
end
|
||||
|
||||
for y=fY,20 do
|
||||
for x=1,10 do
|
||||
F[y][x]=0
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--[[
|
||||
Mission: 34~114
|
||||
Count: 115~126
|
||||
Encode: [A] or [AB] sequence, A = mission ID, B = repeat times, no B means do not repeat.
|
||||
|
||||
_1=01,_2=02,_3=03,_4=04,
|
||||
A1=05,A2=06,A3=07,A4=08,
|
||||
PC=09,
|
||||
Z1=11,Z2=12,Z3=13,
|
||||
S1=21,S2=22,S3=23,
|
||||
J1=31,J2=32,J3=33,
|
||||
L1=41,L2=42,L3=43,
|
||||
T1=51,T2=52,T3=53,
|
||||
O1=61,O2=62,O3=63,O4=64,
|
||||
I1=71,I2=72,I3=73,I4=74,
|
||||
]]
|
||||
function DATA.copyMission()
|
||||
local _
|
||||
local MISSION=MISSION
|
||||
local str=""
|
||||
|
||||
local count=1
|
||||
for i=1,#MISSION+1 do
|
||||
if MISSION[i+1]~=MISSION[i]or count==13 then
|
||||
_=33+MISSION[i]
|
||||
str=str..char(_)
|
||||
if count>1 then
|
||||
str=str..char(113+count)
|
||||
count=1
|
||||
end
|
||||
else
|
||||
count=count+1
|
||||
end
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
function DATA.pasteMission(str)
|
||||
local b
|
||||
local mission={}
|
||||
local reg
|
||||
for i=1,#str do
|
||||
b=byte(str,i)
|
||||
if not reg then
|
||||
if b>=34 and b<=114 then
|
||||
reg=b-33
|
||||
else
|
||||
return
|
||||
end
|
||||
else
|
||||
if b>=34 and b<=114 then
|
||||
if missionEnum[reg]then
|
||||
ins(mission,reg)
|
||||
reg=b-33
|
||||
else
|
||||
return
|
||||
end
|
||||
elseif b>=115 and b<=126 then
|
||||
for _=1,b-113 do
|
||||
ins(mission,reg)
|
||||
end
|
||||
reg=false
|
||||
end
|
||||
end
|
||||
end
|
||||
if reg then
|
||||
ins(mission,reg)
|
||||
end
|
||||
|
||||
MISSION=mission
|
||||
return true
|
||||
end
|
||||
|
||||
function DATA.copyQuestArgs()
|
||||
local ENV=CUSTOMENV
|
||||
local str=""..
|
||||
ENV.holdCount..
|
||||
(ENV.ospin and"O"or"Z")..
|
||||
(ENV.missionKill and"M"or"Z")..
|
||||
ENV.sequence
|
||||
return str
|
||||
end
|
||||
do--function DATA.pasteQuestArgs(str)
|
||||
local sub=string.sub
|
||||
function pasteQuestArgs(str)
|
||||
if #str<4 then return end
|
||||
local ENV=CUSTOMENV
|
||||
ENV.holdCount= byte(str,1)-48
|
||||
ENV.ospin= byte(str,2)~=90
|
||||
ENV.missionKill= byte(str,3)~=90
|
||||
ENV.sequence= sub(str,4)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Table data format:
|
||||
{frame,event, frame,event, ...}
|
||||
|
||||
Byte data format: (1 byte each period)
|
||||
dt, event, dt, event, ...
|
||||
all data range from 0 to 127
|
||||
large value will be encoded as 1xxxxxxx(high)-1xxxxxxx-...-0xxxxxxx(low)
|
||||
|
||||
Example (decoded):
|
||||
6,1, 20,-1, 0,2, 26,-2, 872,4, ...
|
||||
This means:
|
||||
Press key1 at 6f
|
||||
Release key1 at 26f (6+20)
|
||||
Press key2 at the same time (26+0)
|
||||
Release key 2 after 26 frame (26+26)
|
||||
Press key 4 after 872 frame (52+872)
|
||||
...
|
||||
]]
|
||||
function DATA.dumpRecording(list,ptr)
|
||||
local out=""
|
||||
local buffer,buffer2=""
|
||||
if not ptr then ptr=1 end
|
||||
local prevFrm=list[ptr-2]or 0
|
||||
while list[ptr]do
|
||||
--Flush buffer
|
||||
if #buffer>10 then
|
||||
out=out..buffer
|
||||
buffer=""
|
||||
end
|
||||
|
||||
--Encode time
|
||||
local t=list[ptr]-prevFrm
|
||||
prevFrm=list[ptr]
|
||||
if t>=128 then
|
||||
buffer2=char(t%128)
|
||||
t=int(t/128)
|
||||
while t>=128 do
|
||||
buffer2=char(128+t%128)..buffer2
|
||||
t=int(t/128)
|
||||
end
|
||||
buffer=buffer..char(128+t)..buffer2
|
||||
else
|
||||
buffer=buffer..char(t)
|
||||
end
|
||||
|
||||
--Encode event
|
||||
t=list[ptr+1]
|
||||
if t>=128 then
|
||||
buffer2=char(t%128)
|
||||
t=int(t/128)
|
||||
while t>=128 do
|
||||
buffer2=char(128+t%128)..buffer2
|
||||
t=int(t/128)
|
||||
end
|
||||
buffer=buffer..char(128+t)..buffer2
|
||||
else
|
||||
buffer=buffer..char(t)
|
||||
end
|
||||
|
||||
--Step
|
||||
ptr=ptr+2
|
||||
end
|
||||
return out..buffer,ptr
|
||||
end
|
||||
function DATA.pumpRecording(str,L)
|
||||
local len=#str
|
||||
local p=1
|
||||
|
||||
local curFrm=L[#L-1]or 0
|
||||
local code
|
||||
while p<=len do
|
||||
--Read delta time
|
||||
code=0
|
||||
local b=byte(str,p)
|
||||
while b>=128 do
|
||||
code=code*128+b-128
|
||||
p=p+1
|
||||
b=byte(str,p)
|
||||
end
|
||||
curFrm=curFrm+code*128+b
|
||||
L[#L+1]=curFrm
|
||||
p=p+1
|
||||
|
||||
local event=0
|
||||
b=byte(str,p)
|
||||
while b>=128 do
|
||||
event=event*128+b-128
|
||||
p=p+1
|
||||
b=byte(str,p)
|
||||
end
|
||||
L[#L+1]=event*128+b
|
||||
p=p+1
|
||||
end
|
||||
end
|
||||
do--function DATA.saveRecording()
|
||||
local noRecList={"custom","solo","round","techmino"}
|
||||
local function getModList()
|
||||
local res={}
|
||||
for _,v in next,GAME.mod do
|
||||
if v.sel>0 then
|
||||
ins(res,{v.no,v.sel})
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
function DATA.saveRecording()
|
||||
--Filtering modes that cannot be saved
|
||||
for _,v in next,noRecList do
|
||||
if GAME.curModeName:find(v)then
|
||||
LOG.print("Cannot save recording of this mode now!",COLOR.N)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
--Write file
|
||||
local fileName="replay/"..os.date("%Y_%m_%d_%a_%H%M%S.rep")
|
||||
if not love.filesystem.getInfo(fileName)then
|
||||
local fileHead=
|
||||
os.date("%Y/%m/%d %A %H:%M:%S\n")..
|
||||
GAME.curModeName.."\n"..
|
||||
VERSION.string.."\n"..
|
||||
"Local Player"
|
||||
local fileBody=
|
||||
GAME.seed.."\n"..
|
||||
JSON.encode(GAME.setting).."\n"..
|
||||
JSON.encode(getModList()).."\n"..
|
||||
DATA.dumpRecording(GAME.rep)
|
||||
|
||||
love.filesystem.write(fileName,fileHead.."\n"..data.compress("string","zlib",fileBody))
|
||||
ins(REPLAY,fileName)
|
||||
FILE.save(REPLAY,"conf/replay")
|
||||
return true
|
||||
else
|
||||
LOG.print("Save failed: File already exists")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return DATA
|
||||
@@ -1,12 +1,7 @@
|
||||
local data=love.data
|
||||
|
||||
local gc=love.graphics
|
||||
local gc_setColor,gc_setLineWidth,gc_setShader=gc.setColor,gc.setLineWidth,gc.setShader
|
||||
local gc_push,gc_pop,gc_origin,gc_translate=gc.push,gc.pop,gc.origin,gc.translate
|
||||
local gc_draw,gc_rectangle,gc_circle=gc.draw,gc.rectangle,gc.circle
|
||||
local int,rnd=math.floor,math.random
|
||||
local char,byte=string.char,string.byte
|
||||
local ins,rem=table.insert,table.remove
|
||||
local gc_draw,gc_printf,gc_line,gc_rectangle=gc.draw,gc.printf,gc.line,gc.rectangle
|
||||
|
||||
|
||||
|
||||
@@ -19,258 +14,9 @@ end
|
||||
|
||||
|
||||
|
||||
--Encoding Functions
|
||||
--Sep symbol: 33 (!)
|
||||
--Safe char: 34~126
|
||||
--[[
|
||||
Count: 34~96
|
||||
Block: 97~125
|
||||
Encode: A[B] sequence, A = block ID, B = repeat times, no B means do not repeat.
|
||||
Example: "abcdefg" is [SZJLTOI], "a^aDb)" is [Z*63,Z*37,S*10]
|
||||
]]
|
||||
function copySequence()
|
||||
local BAG=BAG
|
||||
local str=""
|
||||
|
||||
local count=1
|
||||
for i=1,#BAG+1 do
|
||||
if BAG[i+1]~=BAG[i]or count==64 then
|
||||
str=str..char(96+BAG[i])
|
||||
if count>1 then
|
||||
str=str..char(32+count)
|
||||
count=1
|
||||
end
|
||||
else
|
||||
count=count+1
|
||||
end
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
function pasteSequence(str)
|
||||
local b
|
||||
|
||||
local bag={}
|
||||
local reg
|
||||
for i=1,#str do
|
||||
b=byte(str,i)
|
||||
if not reg then
|
||||
if b>=97 and b<=125 then
|
||||
reg=b-96
|
||||
else
|
||||
return
|
||||
end
|
||||
else
|
||||
if b>=97 and b<=125 then
|
||||
ins(bag,reg)
|
||||
reg=b-96
|
||||
elseif b>=34 and b<=96 then
|
||||
for _=1,b-32 do
|
||||
ins(bag,reg)
|
||||
end
|
||||
reg=false
|
||||
end
|
||||
end
|
||||
end
|
||||
if reg then
|
||||
ins(bag,reg)
|
||||
end
|
||||
|
||||
BAG=bag
|
||||
return true
|
||||
end
|
||||
|
||||
function newBoard(f)--Generate a new board
|
||||
if f then
|
||||
return TABLE.shift(f)
|
||||
else
|
||||
local F={}
|
||||
for i=1,20 do F[i]={0,0,0,0,0,0,0,0,0,0}end
|
||||
return F
|
||||
end
|
||||
end
|
||||
function copyBoard(page)--Copy the [page] board
|
||||
local F=FIELD[page or 1]
|
||||
local str=""
|
||||
local H=0
|
||||
|
||||
for y=20,1,-1 do
|
||||
for x=1,10 do
|
||||
if F[y][x]~=0 then
|
||||
H=y
|
||||
goto BREAK_topFound
|
||||
end
|
||||
end
|
||||
end
|
||||
::BREAK_topFound::
|
||||
|
||||
--Encode field
|
||||
for y=1,H do
|
||||
local S=""
|
||||
local L=F[y]
|
||||
for x=1,10 do
|
||||
S=S..char(L[x]+1)
|
||||
end
|
||||
str=str..S
|
||||
end
|
||||
return data.encode("string","base64",data.compress("string","zlib",str))
|
||||
end
|
||||
function copyBoards()
|
||||
local out={}
|
||||
for i=1,#FIELD do
|
||||
out[i]=copyBoard(i)
|
||||
end
|
||||
return table.concat(out,"!")
|
||||
end
|
||||
function pasteBoard(str,page)--Paste [str] data to [page] board
|
||||
if not page then page=1 end
|
||||
if not FIELD[page]then FIELD[page]=newBoard()end
|
||||
local F=FIELD[page]
|
||||
local _,__
|
||||
|
||||
--Decode
|
||||
_,str=pcall(data.decode,"string","base64",str)
|
||||
if not _ then return end
|
||||
_,str=pcall(data.decompress,"string","zlib",str)
|
||||
if not _ then return end
|
||||
|
||||
local fX,fY=1,1--*ptr for Field(r*10+(c-1))
|
||||
local p=1
|
||||
while true do
|
||||
_=byte(str,p)--1byte
|
||||
|
||||
--Str end
|
||||
if not _ then
|
||||
if fX~=1 then
|
||||
return
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
__=_%32-1--Block id
|
||||
if __>26 then return end--Illegal blockid
|
||||
_=int(_/32)--Mode id
|
||||
|
||||
F[fY][fX]=__
|
||||
if fX<10 then
|
||||
fX=fX+1
|
||||
else
|
||||
fY=fY+1
|
||||
if fY>20 then break end
|
||||
fX=1
|
||||
end
|
||||
p=p+1
|
||||
end
|
||||
|
||||
for y=fY,20 do
|
||||
for x=1,10 do
|
||||
F[y][x]=0
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--[[
|
||||
Mission: 34~114
|
||||
Count: 115~126
|
||||
Encode: [A] or [AB] sequence, A = mission ID, B = repeat times, no B means do not repeat.
|
||||
|
||||
_1=01,_2=02,_3=03,_4=04,
|
||||
A1=05,A2=06,A3=07,A4=08,
|
||||
PC=09,
|
||||
Z1=11,Z2=12,Z3=13,
|
||||
S1=21,S2=22,S3=23,
|
||||
J1=31,J2=32,J3=33,
|
||||
L1=41,L2=42,L3=43,
|
||||
T1=51,T2=52,T3=53,
|
||||
O1=61,O2=62,O3=63,O4=64,
|
||||
I1=71,I2=72,I3=73,I4=74,
|
||||
]]
|
||||
function copyMission()
|
||||
local _
|
||||
local MISSION=MISSION
|
||||
local str=""
|
||||
|
||||
local count=1
|
||||
for i=1,#MISSION+1 do
|
||||
if MISSION[i+1]~=MISSION[i]or count==13 then
|
||||
_=33+MISSION[i]
|
||||
str=str..char(_)
|
||||
if count>1 then
|
||||
str=str..char(113+count)
|
||||
count=1
|
||||
end
|
||||
else
|
||||
count=count+1
|
||||
end
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
function pasteMission(str)
|
||||
local b
|
||||
local mission={}
|
||||
local reg
|
||||
for i=1,#str do
|
||||
b=byte(str,i)
|
||||
if not reg then
|
||||
if b>=34 and b<=114 then
|
||||
reg=b-33
|
||||
else
|
||||
return
|
||||
end
|
||||
else
|
||||
if b>=34 and b<=114 then
|
||||
if missionEnum[reg]then
|
||||
ins(mission,reg)
|
||||
reg=b-33
|
||||
else
|
||||
return
|
||||
end
|
||||
elseif b>=115 and b<=126 then
|
||||
for _=1,b-113 do
|
||||
ins(mission,reg)
|
||||
end
|
||||
reg=false
|
||||
end
|
||||
end
|
||||
end
|
||||
if reg then
|
||||
ins(mission,reg)
|
||||
end
|
||||
|
||||
MISSION=mission
|
||||
return true
|
||||
end
|
||||
|
||||
function copyQuestArgs()
|
||||
local ENV=CUSTOMENV
|
||||
local str=""..
|
||||
ENV.holdCount..
|
||||
(ENV.ospin and"O"or"Z")..
|
||||
(ENV.missionKill and"M"or"Z")..
|
||||
ENV.sequence
|
||||
return str
|
||||
end
|
||||
do--function pasteQuestArgs(str)
|
||||
local sub=string.sub
|
||||
function pasteQuestArgs(str)
|
||||
if #str<4 then return end
|
||||
local ENV=CUSTOMENV
|
||||
ENV.holdCount= byte(str,1)-48
|
||||
ENV.ospin= byte(str,2)~=90
|
||||
ENV.missionKill= byte(str,3)~=90
|
||||
ENV.sequence= sub(str,4)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--Royale mode
|
||||
function randomTarget(P)--Return a random opponent for P
|
||||
local rnd=math.random
|
||||
if #PLY_ALIVE>1 then
|
||||
local R
|
||||
repeat
|
||||
@@ -350,6 +96,7 @@ function royaleLevelup()
|
||||
P.gameEnv.drop=spd
|
||||
end
|
||||
if GAME.curMode.name:find("_u")then
|
||||
local int=math.floor
|
||||
for i=1,#PLY_ALIVE do
|
||||
local P=PLY_ALIVE[i]
|
||||
P.gameEnv.drop=int(P.gameEnv.drop*.3)
|
||||
@@ -363,108 +110,6 @@ end
|
||||
|
||||
|
||||
|
||||
--Virtualkey
|
||||
local VK=virtualkey
|
||||
function drawVirtualkeys()
|
||||
if SETTING.VKSwitch then
|
||||
local a=SETTING.VKAlpha
|
||||
local _
|
||||
if SETTING.VKIcon then
|
||||
local icons=TEXTURE.VKIcon
|
||||
for i=1,#VK do
|
||||
if VK[i].ava then
|
||||
local B=VK[i]
|
||||
gc_setColor(1,1,1,a)
|
||||
gc_setLineWidth(B.r*.07)
|
||||
gc_circle("line",B.x,B.y,B.r,10)--Button outline
|
||||
_=VK[i].pressTime
|
||||
gc_setColor(B.color[1],B.color[2],B.color[3],a)
|
||||
gc_draw(icons[i],B.x,B.y,nil,B.r*.026+_*.08,nil,18,18)--Icon
|
||||
if _>0 then
|
||||
gc_setColor(1,1,1,a*_*.08)
|
||||
gc_circle("fill",B.x,B.y,B.r*.94,10)--Glow when press
|
||||
gc_circle("line",B.x,B.y,B.r*(1.4-_*.04),10)--Ripple
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
for i=1,#VK do
|
||||
if VK[i].ava then
|
||||
local B=VK[i]
|
||||
gc_setColor(1,1,1,a)
|
||||
gc_setLineWidth(B.r*.07)
|
||||
gc_circle("line",B.x,B.y,B.r,10)
|
||||
_=VK[i].pressTime
|
||||
if _>0 then
|
||||
gc_setColor(1,1,1,a*_*.08)
|
||||
gc_circle("fill",B.x,B.y,B.r*.94,10)
|
||||
gc_circle("line",B.x,B.y,B.r*(1.4-_*.04),10)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function onVirtualkey(x,y)
|
||||
local dist,nearest=1e10
|
||||
for K=1,#VK do
|
||||
local B=VK[K]
|
||||
if B.ava then
|
||||
local d1=(x-B.x)^2+(y-B.y)^2
|
||||
if d1<B.r^2 then
|
||||
if d1<dist then
|
||||
nearest,dist=K,d1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return nearest
|
||||
end
|
||||
function pressVirtualkey(t,x,y)
|
||||
local SETTING=SETTING
|
||||
local B=VK[t]
|
||||
B.isDown=true
|
||||
B.pressTime=10
|
||||
|
||||
if x then
|
||||
if SETTING.VKTrack then
|
||||
--Auto follow
|
||||
local O=VK_org[t]
|
||||
local _FW,_CW=SETTING.VKTchW,1-SETTING.VKCurW
|
||||
local _OW=1-_FW-_CW
|
||||
--(finger+current+origin)
|
||||
B.x=x*_FW+B.x*_CW+O.x*_OW
|
||||
B.y=y*_FW+B.y*_CW+O.y*_OW
|
||||
|
||||
--Button collision (not accurate)
|
||||
if SETTING.VKDodge then
|
||||
for i=1,#VK do
|
||||
local b=VK[i]
|
||||
local d=B.r+b.r-((B.x-b.x)^2+(B.y-b.y)^2)^.5--Hit depth(Neg means distance)
|
||||
if d>0 then
|
||||
b.x=b.x+(b.x-B.x)*d*b.r*2.6e-5
|
||||
b.y=b.y+(b.y-B.y)*d*b.r*2.6e-5
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
SFX.play("virtualKey",SETTING.VKSFX)
|
||||
VIB(SETTING.VKVIB)
|
||||
end
|
||||
end
|
||||
function updateVirtualkey()
|
||||
if SETTING.VKSwitch then
|
||||
for i=1,#VK do
|
||||
local _=VK[i]
|
||||
if _.pressTime>0 then
|
||||
_.pressTime=_.pressTime-1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--Game
|
||||
function generateLine(hole)
|
||||
return 1023-2^(hole-1)
|
||||
@@ -522,6 +167,7 @@ function scoreValid()--Check if any unranked mods are activated
|
||||
return true
|
||||
end
|
||||
function destroyPlayers()--Destroy all player objects, restore freerows and free CCs
|
||||
local rem=table.remove
|
||||
for i=#PLAYERS,1,-1 do
|
||||
local P=PLAYERS[i]
|
||||
if P.canvas then P.canvas:release()end
|
||||
@@ -540,23 +186,6 @@ function destroyPlayers()--Destroy all player objects, restore freerows and free
|
||||
TABLE.clear(PLY_ALIVE)
|
||||
collectgarbage()
|
||||
end
|
||||
function restoreVirtualkey()
|
||||
for i=1,#VK_org do
|
||||
local B,O=virtualkey[i],VK_org[i]
|
||||
B.ava=O.ava
|
||||
B.x=O.x
|
||||
B.y=O.y
|
||||
B.r=O.r
|
||||
B.color=O.color
|
||||
B.isDown=false
|
||||
B.pressTime=0
|
||||
end
|
||||
for k,v in next,PLAYERS[1].keyAvailable do
|
||||
if not v then
|
||||
virtualkey[k].ava=false
|
||||
end
|
||||
end
|
||||
end
|
||||
function pauseGame()
|
||||
if not SCN.swapping then
|
||||
if not GAME.replaying then
|
||||
@@ -735,7 +364,7 @@ do--function resetGameData(args)
|
||||
GAME.replaying=1
|
||||
else
|
||||
GAME.frameStart=args:find("n")and 0 or 150-SETTING.reTime*15
|
||||
GAME.seed=seed or rnd(1046101471,2662622626)
|
||||
GAME.seed=seed or math.random(1046101471,2662622626)
|
||||
GAME.pauseTime=0
|
||||
GAME.pauseCount=0
|
||||
GAME.saved=false
|
||||
@@ -750,7 +379,7 @@ do--function resetGameData(args)
|
||||
destroyPlayers()
|
||||
GAME.curMode.load()
|
||||
initPlayerPosition(args:find("q"))
|
||||
restoreVirtualkey()
|
||||
VK.restore()
|
||||
if GAME.modeEnv.task then
|
||||
for i=1,#PLAYERS do
|
||||
PLAYERS[i]:newTask(GAME.modeEnv.task)
|
||||
@@ -758,7 +387,7 @@ do--function resetGameData(args)
|
||||
end
|
||||
BG.set(GAME.modeEnv.bg)
|
||||
local bgm=GAME.modeEnv.bgm
|
||||
BGM.play(type(bgm)=="string"and bgm or type(bgm)=="table"and bgm[rnd(#bgm)])
|
||||
BGM.play(type(bgm)=="string"and bgm or type(bgm)=="table"and bgm[math.random(#bgm)])
|
||||
|
||||
TEXT.clear()
|
||||
if GAME.modeEnv.royaleMode then
|
||||
@@ -816,146 +445,6 @@ do--function checkWarning()
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Table data format:
|
||||
{frame,event, frame,event, ...}
|
||||
|
||||
Byte data format: (1 byte each period)
|
||||
dt, event, dt, event, ...
|
||||
all data range from 0 to 127
|
||||
large value will be encoded as 1xxxxxxx(high)-1xxxxxxx-...-0xxxxxxx(low)
|
||||
|
||||
Example (decoded):
|
||||
6,1, 20,-1, 0,2, 26,-2, 872,4, ...
|
||||
This means:
|
||||
Press key1 at 6f
|
||||
Release key1 at 26f (6+20)
|
||||
Press key2 at the same time (26+0)
|
||||
Release key 2 after 26 frame (26+26)
|
||||
Press key 4 after 872 frame (52+872)
|
||||
...
|
||||
]]
|
||||
function dumpRecording(list,ptr)
|
||||
local out=""
|
||||
local buffer,buffer2=""
|
||||
if not ptr then ptr=1 end
|
||||
local prevFrm=list[ptr-2]or 0
|
||||
while list[ptr]do
|
||||
--Flush buffer
|
||||
if #buffer>10 then
|
||||
out=out..buffer
|
||||
buffer=""
|
||||
end
|
||||
|
||||
--Encode time
|
||||
local t=list[ptr]-prevFrm
|
||||
prevFrm=list[ptr]
|
||||
if t>=128 then
|
||||
buffer2=char(t%128)
|
||||
t=int(t/128)
|
||||
while t>=128 do
|
||||
buffer2=char(128+t%128)..buffer2
|
||||
t=int(t/128)
|
||||
end
|
||||
buffer=buffer..char(128+t)..buffer2
|
||||
else
|
||||
buffer=buffer..char(t)
|
||||
end
|
||||
|
||||
--Encode event
|
||||
t=list[ptr+1]
|
||||
if t>=128 then
|
||||
buffer2=char(t%128)
|
||||
t=int(t/128)
|
||||
while t>=128 do
|
||||
buffer2=char(128+t%128)..buffer2
|
||||
t=int(t/128)
|
||||
end
|
||||
buffer=buffer..char(128+t)..buffer2
|
||||
else
|
||||
buffer=buffer..char(t)
|
||||
end
|
||||
|
||||
--Step
|
||||
ptr=ptr+2
|
||||
end
|
||||
return out..buffer,ptr
|
||||
end
|
||||
function pumpRecording(str,L)
|
||||
local len=#str
|
||||
local p=1
|
||||
|
||||
local curFrm=L[#L-1]or 0
|
||||
local code
|
||||
while p<=len do
|
||||
--Read delta time
|
||||
code=0
|
||||
local b=byte(str,p)
|
||||
while b>=128 do
|
||||
code=code*128+b-128
|
||||
p=p+1
|
||||
b=byte(str,p)
|
||||
end
|
||||
curFrm=curFrm+code*128+b
|
||||
L[#L+1]=curFrm
|
||||
p=p+1
|
||||
|
||||
local event=0
|
||||
b=byte(str,p)
|
||||
while b>=128 do
|
||||
event=event*128+b-128
|
||||
p=p+1
|
||||
b=byte(str,p)
|
||||
end
|
||||
L[#L+1]=event*128+b
|
||||
p=p+1
|
||||
end
|
||||
end
|
||||
do--function saveRecording()
|
||||
local noRecList={"custom","solo","round","techmino"}
|
||||
local function getModList()
|
||||
local res={}
|
||||
for _,v in next,GAME.mod do
|
||||
if v.sel>0 then
|
||||
ins(res,{v.no,v.sel})
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
function saveRecording()
|
||||
--Filtering modes that cannot be saved
|
||||
for _,v in next,noRecList do
|
||||
if GAME.curModeName:find(v)then
|
||||
LOG.print("Cannot save recording of this mode now!",COLOR.N)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
--File contents
|
||||
local fileName="replay/"..os.date("%Y_%m_%d_%a_%H%M%S.rep")
|
||||
local fileHead=
|
||||
os.date("%Y/%m/%d %A %H:%M:%S\n")..
|
||||
GAME.curModeName.."\n"..
|
||||
VERSION.string.."\n"..
|
||||
"Local Player"
|
||||
local fileBody=
|
||||
GAME.seed.."\n"..
|
||||
JSON.encode(GAME.setting).."\n"..
|
||||
JSON.encode(getModList()).."\n"..
|
||||
dumpRecording(GAME.rep)
|
||||
|
||||
--Write file
|
||||
if not love.filesystem.getInfo(fileName)then
|
||||
love.filesystem.write(fileName,fileHead.."\n"..data.compress("string","zlib",fileBody))
|
||||
ins(REPLAY,fileName)
|
||||
FILE.save(REPLAY,"conf/replay")
|
||||
return true
|
||||
else
|
||||
LOG.print("Save failed: File already exists")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--Game draw
|
||||
@@ -989,21 +478,28 @@ do--function drawFWM()
|
||||
mStr(m[_G["\83\69\84\84\73\78\71"]["\108\97\110\103"]or m[1]],240,60+26*sin(t))
|
||||
end
|
||||
end
|
||||
do--function drawSelfProfile()
|
||||
function drawSelfProfile()
|
||||
local selfAvatar=USERS.getAvatar(USER.uid)
|
||||
gc_push("transform")
|
||||
gc_translate(1280,0)
|
||||
function drawSelfProfile()
|
||||
local selfAvatar=USERS.getAvatar(USER.uid)
|
||||
gc_push("transform")
|
||||
gc_translate(1280,0)
|
||||
|
||||
--Draw avatar
|
||||
gc_setLineWidth(2)
|
||||
gc_setColor(.3,.3,.3,.8)gc_rectangle("fill",-260,0,260,80)
|
||||
gc_setColor(1,1,1)gc_rectangle("line",-260,0,260,80)
|
||||
gc_rectangle("line",-73,7,66,66,2)
|
||||
gc_draw(selfAvatar,-72,8,nil,.5)
|
||||
--Draw avatar
|
||||
gc_setLineWidth(2)
|
||||
gc_setColor(.3,.3,.3,.8)gc_rectangle("fill",-260,0,260,80)
|
||||
gc_setColor(1,1,1)gc_rectangle("line",-260,0,260,80)
|
||||
gc_rectangle("line",-73,7,66,66,2)
|
||||
gc_draw(selfAvatar,-72,8,nil,.5)
|
||||
|
||||
gc_pop()
|
||||
end
|
||||
--Draw username
|
||||
setFont(30)
|
||||
gc_printf(USERS.getUsername(USER.uid),-342,5,260,"right")
|
||||
|
||||
--Draw lv. & xp.
|
||||
gc_draw(TEXTURE.lvIcon[USER.lv],-255,50)
|
||||
gc_line(-230,55,-80,55,-80,70,-230,70)
|
||||
gc_rectangle("fill",-230,55,150*USER.xp/USER.lv/USER.lv,15)
|
||||
|
||||
gc_pop()
|
||||
end
|
||||
function drawWarning()
|
||||
if SETTING.warn and GAME.warnLVL>0 then
|
||||
|
||||
@@ -178,6 +178,10 @@ GAME={--Global game data
|
||||
mostDangerous=false,--Most dangerous player
|
||||
secDangerous=false, --Second dangerous player
|
||||
}
|
||||
ROYALEDATA={
|
||||
powerUp=false,
|
||||
stage=false,
|
||||
}
|
||||
|
||||
--Userdata tables
|
||||
RANKS=FILE.load("conf/unlock")or{sprint_10l=0}--Ranks of modes
|
||||
@@ -355,5 +359,4 @@ VK_org=FILE.load("conf/virtualkey")or{--Virtualkey layout, refresh all VKs' posi
|
||||
{ava=false, x=900, y=50, r=80,color=COLOR.lA},--addToLeft
|
||||
{ava=false, x=1000, y=50, r=80,color=COLOR.lA},--addToRight
|
||||
}
|
||||
virtualkey={}for i=1,#VK_org do virtualkey[i]={}end--In-game virtualkey layout
|
||||
REPLAY=FILE.load("conf/replay")or{}
|
||||
@@ -511,6 +511,11 @@ return{
|
||||
"term",
|
||||
"\"Doing scientific research\" is a term sometimes used in the Chinese community, referring to researching/practicing techniques in a low-falling-speed, single player environment.",
|
||||
},
|
||||
{"Handling",
|
||||
"feel handling",
|
||||
"term",
|
||||
"Several main factors that affecting the hand feel:\n(1) Input delay is affected by device configuration or device condition. Restart / change device.\n(2) Program stability, program design (or implementation) is not good, cause lagging too much. May be alleviated by lowering the effect setting.\n(3) Designed on purpose. Adapt it.\n(4) Improper parameter setting. Change the settings.\n(5) Improper play posture. It's not convenient to use force. Change your posture.\n(6) Not used to the operation after changing the key position or changing the device. Get used to it or change the settings.\n(7) Muscle fatigue, response and coordination ability decreased. Get some sleep or do some sports, and come back later (maybe a few days).",
|
||||
},
|
||||
{"DAS & ARR",
|
||||
"das arr delayedautoshift autorepeatrate",
|
||||
"term",
|
||||
|
||||
@@ -61,43 +61,43 @@ return{
|
||||
{"King of Stackers",
|
||||
"回合制 kos kingofstackers",
|
||||
"game",
|
||||
"King of Stackers\n网页版回合制对战方块点击即玩(可能很卡),主要规则为:以7块为一个回合,双方轮流在自己场地中放置方块,任何的攻击只在对方回合放一块不消行后生效,策略性很强。有不同的伤害表设置。",
|
||||
"简称KOS,King of Stackers\n网页版回合制对战方块点击即玩(可能很卡),主要规则为:以7块为一个回合,双方轮流在自己场地中放置方块,任何的攻击只在对方回合放一块不消行后生效,策略性很强。有不同的伤害表设置。",
|
||||
"https://kingofstackers.com/games.php",
|
||||
},
|
||||
{"Tetr.js",
|
||||
"网页 手机 tetrjs",
|
||||
"game",
|
||||
"全平台网页版单机方块点击即玩,有对新人比较友好的全自定义(大多数常用功能),手机只能选几个默认按键组,不能自由摆放。别的都很好",
|
||||
"简称屁块,全平台网页版单机方块点击即玩,有对新人比较友好的全自定义(大多数常用功能),手机只能选几个默认按键组,不能自由摆放。别的都很好",
|
||||
"http://farter.cn/t",
|
||||
},
|
||||
{"Tetra Legends",
|
||||
"网页 tl tetralegends",
|
||||
"game",
|
||||
"全平台网页版单机方块点击即玩(推荐使用电脑,移动设备需要外接键盘)(第一次加载可能很慢),除了手感不够舒适以外功能比较强大,动效很好看,还把很多别的游戏里不可见的机制可视化了,游戏体验很好。\n\n注:包含节奏模式!\n\n2020年12月,基本确定由于各种原因不再继续开发",
|
||||
"简称TL,全平台网页版单机方块点击即玩(推荐使用电脑,移动设备需要外接键盘)(第一次加载可能很慢),除了手感不够舒适以外功能比较强大,动效很好看,还把很多别的游戏里不可见的机制可视化了,游戏体验很好。\n\n注:包含节奏模式!\n\n2020年12月,基本确定由于各种原因不再继续开发",
|
||||
"https://tetralegends.app",
|
||||
},
|
||||
{"Jstris",
|
||||
"网页 手机 js jstris",
|
||||
"game",
|
||||
"全平台网页对战方块点击即玩(服务器在国外可能很卡)。有常用的科研向单机模式和自定义各种参数的功能,但没有很多强制速度向的挑战项目。都是纯色素材导致画面效果不怎么好。移动端的键位设置并不舒适。",
|
||||
"简称JS,全平台网页对战方块点击即玩(服务器在国外可能很卡)。有常用的科研向单机模式和自定义各种参数的功能,但没有很多强制速度向的挑战项目。都是纯色素材导致画面效果不怎么好。移动端的键位设置并不舒适。",
|
||||
"https://jstris.jezevec10.com",
|
||||
},
|
||||
{"TETR.IO",
|
||||
"网页 io tetrio",
|
||||
"game",
|
||||
"炫酷在线对战方块点击即玩(推荐使用电脑,移动设备需要外接键盘)(服务器在国外,可能超级慢甚至打不开)有很科学的排位系统,自定义功能非常全面,同时也提供电脑客户端下载(可以去除广告)。缺点是单机模式非常非常少。",
|
||||
"简称IO,炫酷在线对战方块点击即玩(推荐使用电脑,移动设备需要外接键盘)(服务器在国外,可能超级慢甚至打不开)有很科学的排位系统,自定义功能非常全面,同时也提供电脑客户端下载(可以去除广告)。缺点是单机模式非常非常少。",
|
||||
"https://tetr.io",
|
||||
},
|
||||
{"World Wide Combo",
|
||||
"网页 wwc worldwidecombo",
|
||||
"game",
|
||||
"网页全世界匹配制1对1方块点击即玩(服务器在国外可能很卡)",
|
||||
"简称WWC,网页全世界匹配制1对1方块点击即玩(服务器在国外可能很卡)",
|
||||
"https://worldwidecombos.com",
|
||||
},
|
||||
{"Tetris Friends",
|
||||
"网页 tf tetrisfriends",
|
||||
"game",
|
||||
"一个已经关服了的网页版方块,曾经是一个不错的对战平台\n现在有人架了私服(怀旧服?)",
|
||||
"简称TF,一个已经关服了的网页版方块,曾经是一个不错的对战平台\n现在有人架了私服(怀旧服?)",
|
||||
"https://notrisfoes.com",
|
||||
},
|
||||
|
||||
@@ -121,49 +121,49 @@ return{
|
||||
{"Texmaster",
|
||||
"txm texmaster",
|
||||
"game",
|
||||
"一个win平台方块,包含TGM的所有模式,可以用来练习TGM,手感比真版较好,不足的是world规则不完全一样(如软降到底无锁延,踢墙表有细节不同等)",
|
||||
"简称Tex,一个win平台方块,包含TGM的所有模式,可以用来练习TGM,手感比真版较好,不足的是world规则不完全一样(如软降到底无锁延,踢墙表有细节不同等)",
|
||||
},
|
||||
|
||||
--游戏(PC/主机)
|
||||
{"Tetris99",
|
||||
"吃鸡 t99 tetris99",
|
||||
"game",
|
||||
"ns端方块,主玩99人混战的吃鸡模式,战术比重比较大,胜率不只由玩家在平时1v1时的水平决定。也有一些常用单机模式如马拉松等",
|
||||
"简称T99,ns端方块,主玩99人混战的吃鸡模式,战术比重比较大,胜率不只由玩家在平时1v1时的水平决定。也有一些常用单机模式如马拉松等",
|
||||
},
|
||||
{"Puyopuyo Tetris",
|
||||
"ppt puyopuyotetris",
|
||||
"game",
|
||||
"多平台方块(steamPC版手感,网络等都不太好,不建议购买),将tetris和puyopuyo两个下落消除游戏放到一个游戏里,二者可以对战,联机单机模式都很多,很有趣",
|
||||
"简称PPT,多平台方块(steamPC版手感,网络等都不太好,不建议购买),将tetris和puyopuyo两个下落消除游戏放到一个游戏里,二者可以对战,联机单机模式都很多,很有趣",
|
||||
},
|
||||
{"Tetris Online",
|
||||
"top tetris online study",
|
||||
"game",
|
||||
"一个win平台方块,主要用来6人内对战/单挑/刷每日40L榜/挖掘模式/打机器人。支持自定义das/arr但都不能到0,有一点输入延迟但问题不大,是新人入块圈不错的选择。\n\n现在还开着的服务器有:\n\tTO-P(波兰服,服务器在波兰,可能会卡顿)\n\tTO-S(研究服,研究群群友自己开的服,很稳定,需要进群注册)\n\tTO-X(千雪服,VUP星月千雪于20年9月开的服,还处于实验阶段)",
|
||||
"简称TO[服务器名首字母],一个win平台方块,主要用来6人内对战/单挑/刷每日40L榜/挖掘模式/打机器人。支持自定义das/arr但都不能到0,有一点输入延迟但问题不大,是新人入块圈不错的选择。\n\n现在还开着的服务器有:\n\tTO-P(波兰服,服务器在波兰,可能会卡顿)\n\tTO-S(研究服,研究群群友自己开的服,很稳定,需要进群注册)\n\tTO-X(千雪服,VUP星月千雪于20年9月开的服,还处于实验阶段)",
|
||||
},
|
||||
{"Tetra Online",
|
||||
"to tetraonline",
|
||||
"game",
|
||||
"PC方块打开Steam免费下载即玩(现在已经没了),开发团队只有Dr.Ocelot和Mine两个人(都没有很多开发经验),UI部分模仿PPT,手感故意设计为较慢,平时玩无延迟方块的玩家会很不习惯,音乐不错,攻击特效好看。2020年12月9日收到来自TTC的DCMA警告信于是被迫停止开发,在一段时间后关服并下架。",
|
||||
"简称TO,PC方块打开Steam免费下载即玩(现在已经没了),开发团队只有Dr.Ocelot和Mine两个人(都没有很多开发经验),UI部分模仿PPT,手感故意设计为较慢,平时玩无延迟方块的玩家会很不习惯,音乐不错,攻击特效好看。2020年12月9日收到来自TTC的DCMA警告信于是被迫停止开发,在一段时间后关服并下架。",
|
||||
},
|
||||
{"Tetris Effect",
|
||||
"tec tetriseffectconnect",
|
||||
"game",
|
||||
"一个win/ps4/xbox平台方块,特效方块游戏,只有单机模式,手感不算太好,想看特效的可以一试,只是去玩方块的不是很建议\n有一个拓展版本Tetris Effect: Connected增加了联网对战,包含普通对战,zone对战,经典对战和boss战四个模式",
|
||||
"简称TE(C),一个win/ps4/xbox平台方块,特效方块游戏,只有单机模式,手感不算太好,想看特效的可以一试,只是去玩方块的不是很建议\n有一个拓展版本Tetris Effect: Connected增加了联网对战,包含普通对战,zone对战,经典对战和boss战四个模式",
|
||||
},
|
||||
{"Techmino",
|
||||
"techmino tieke",
|
||||
"game",
|
||||
"一个win/android/linux/macOS方块,单机模式和各种设置都很齐全,联机正在逐渐开发中,输入延迟很小,手感很好",
|
||||
"简称Tech,一个win/android/linux/macOS方块,单机模式和各种设置都很齐全,联机正在逐渐开发中,输入延迟很小,手感很好",
|
||||
},
|
||||
{"Cultris II",
|
||||
"c2 cultris2 cultrisii",
|
||||
"game",
|
||||
"一个win/linux/macOS平台方块,基于经典规则,但支持自定义das/arr,主玩对战,打法是基于时间的连击,考验玩家速度/wide打法/挖掘",
|
||||
"简称C2,一个win/linux/macOS平台方块,设计基于经典规则出发,但支持自定义das/arr,对战的主要玩法是基于时间的连击,考验玩家速度/wide打法/挖掘",
|
||||
},
|
||||
{"Nullpomino",
|
||||
"np nullpomino",
|
||||
"game",
|
||||
"一个win平台方块,整个游戏自定义程度极高,几乎任何参数都可以自己设置,是一个专业级方块,不太适合新人上手,连菜单都不太好搞清楚",
|
||||
"简称NP,一个win平台方块,整个游戏自定义程度极高,几乎任何参数都可以自己设置,是一个专业级方块,不太适合新人上手,连菜单都不太好搞清楚",
|
||||
},
|
||||
{"Touhoumino",
|
||||
"touhoumino chewan dongfang",
|
||||
@@ -520,6 +520,11 @@ return{
|
||||
"term",
|
||||
"常用语,指在低重力的单人模式里减速研究怎么做各种Tspin,本游戏中拓展了含义,用于称呼几乎需要全程spin的游戏模式。",
|
||||
},
|
||||
{"手感",
|
||||
"手感 feel shougan",
|
||||
"term",
|
||||
"决定手感的几个主要因素:\n(1)输入延迟受设备配置或者设备状况影响。可以重启/换设备解决\n(2)程序运行稳定性程序设计(或者实现)得不好,时不时会卡一下。把设置画面效果拉低可能可以缓解\n(3)游戏设计故意的。自己适应\n(4)参数设置设置不当。去改设置\n(5)游玩姿势姿势不当。不便用力,换个姿势\n(6)换键位或者换设备后不适应,操作不习惯。多习惯习惯,改改设置\n(7)肌肉疲劳反应和协调能力下降。睡一觉或者做点体育运动,过段时间(也可能要几天)再来玩",
|
||||
},
|
||||
{"DAS & ARR",
|
||||
"灵敏度 das arr",
|
||||
"term",
|
||||
@@ -568,7 +573,7 @@ return{
|
||||
{"C2序列",
|
||||
"c2序列 seq",
|
||||
"term",
|
||||
"七个块初始权重0\n全体除以2再加0~1的随机数,选数字最大的块出,然后将其权重除以3.5,循环",
|
||||
"七个块初始权重0\n全体除以2再加0~1的随机数,选数字最大的块出,然后将其权重除以3.5,循环",--Reversed by zxc
|
||||
},
|
||||
{"C2踢墙",
|
||||
"c2踢墙 kick",
|
||||
|
||||
@@ -220,7 +220,6 @@ return{
|
||||
about="About",
|
||||
dict="Zictionary",
|
||||
manual="Manual",
|
||||
quit="Exit",
|
||||
},
|
||||
main_simple={
|
||||
sprint="Sprint",
|
||||
@@ -858,23 +857,23 @@ return{
|
||||
{C.C,"Also try Phigros!"},
|
||||
{C.C,"Also try Rubic's cube!"},
|
||||
{C.C,"Also try Terraria!"},
|
||||
{C.C,"Also try VVVVVV!"},
|
||||
{C.fire,"Also try Cultris II!"},
|
||||
{C.fire,"Also try Jstris"},
|
||||
{C.fire,"Also try NullpoMino!"},
|
||||
{C.fire,"Also try TETR.IO!"},
|
||||
{C.fire,"Also try Tetr.js!"},
|
||||
{C.fire,"Also try Tetra Legends!"},
|
||||
{C.purple,"T-spin!"},
|
||||
{C.C,"Also try VVVVVVV!"},
|
||||
{C.F,"Also try Cultris II!"},
|
||||
{C.F,"Also try Jstris"},
|
||||
{C.F,"Also try NullpoMino!"},
|
||||
{C.F,"Also try TETR.IO!"},
|
||||
{C.F,"Also try Tetr.js!"},
|
||||
{C.F,"Also try Tetra Legends!"},
|
||||
{C.H,"REGRET!!"},
|
||||
{C.lR,"Z ",C.lG,"S ",C.lS,"J ",C.lO,"L ",C.lP,"T ",C.lY,"O ",C.lC,"I"},
|
||||
{C.lY,"COOL!!"},
|
||||
{C.N,"Lua",C.Z," No.1"},
|
||||
{C.P,"T-spin!"},
|
||||
{C.R,"\"DMCA abusing\""},
|
||||
{C.R,"\"Intellectual property law\""},
|
||||
{C.R,"DT",C.Z," Cannon=",C.purple,"TS",C.R,"D",C.Z,"+",C.purple,"TS",C.R,"T",C.Z," Cannon"},
|
||||
{C.R,"LrL ",C.G,"RlR ",C.B,"LLr ",C.orange,"RRl ",C.purple,"RRR ",C.purple,"LLL ",C.C,"FFF ",C.Y,"RfR ",C.Y,"RRf ",C.Y,"rFF"},
|
||||
{C.navy,"Lua",C.Z," No.1"},
|
||||
{C.Z,"What is an ",c.lC,"X-Spin"?},
|
||||
{C.R,"DT",C.Z," Cannon=",C.P,"TS",C.R,"D",C.Z,"+",C.P,"TS",C.R,"T",C.Z," Cannon"},
|
||||
{C.R,"LrL ",C.G,"RlR ",C.B,"LLr ",C.O,"RRl ",C.P,"RRR ",C.P,"LLL ",C.C,"FFF ",C.Y,"RfR ",C.Y,"RRf ",C.Y,"rFF"},
|
||||
{C.Y,"O-Spin Triple!"},
|
||||
{C.Z,"What is an ",c.lC,"X-Spin"?},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +197,6 @@ return{
|
||||
-- about="About",
|
||||
dict="Zictionary",
|
||||
manual="Manuel",
|
||||
quit="Quitter",
|
||||
},
|
||||
mode={
|
||||
mod="Mods (F1)",
|
||||
|
||||
@@ -221,7 +221,6 @@ return{
|
||||
-- about="About",
|
||||
dict="Zictionary",
|
||||
manual="Manual",
|
||||
quit="Saída",
|
||||
},
|
||||
main_simple={
|
||||
sprint="Sprint",
|
||||
|
||||
@@ -198,7 +198,6 @@ return{
|
||||
about="Acerca del Juego",
|
||||
dict="Zictionary",
|
||||
manual="Manual",
|
||||
quit="Salir",
|
||||
},
|
||||
main_simple={
|
||||
sprint="Sprint",
|
||||
|
||||
@@ -102,7 +102,6 @@ return{
|
||||
about="?",
|
||||
dict="z",
|
||||
manual="???",
|
||||
quit="X",
|
||||
},
|
||||
mode={
|
||||
mod="?!?!?!(F1)",
|
||||
|
||||
@@ -220,7 +220,6 @@ return{
|
||||
about="关于",
|
||||
dict="小Z词典",
|
||||
manual="说明书",
|
||||
quit="退出",
|
||||
},
|
||||
main_simple={
|
||||
sprint="40行",
|
||||
@@ -799,6 +798,7 @@ return{
|
||||
"把手机调到特殊的日期也许会发生什么",
|
||||
"报时机器人:新的一天开始了",
|
||||
"背景影响游玩?可以去设置关闭",
|
||||
"本游戏不是产品,是作品(至少目前是…)",
|
||||
"本游戏的一部分内容是国际合作的!",
|
||||
"本游戏的B2B是气槽机制,和传统的开关机制不一样哦",
|
||||
"本游戏可不是休闲游戏。",
|
||||
@@ -808,6 +808,8 @@ return{
|
||||
"别问游戏名怎么取的,问就是随便想的",
|
||||
"不同人打40行最合适的方式不一样,s1w/63/散消/s2w...",
|
||||
"不同游戏(甚至不同模式)中不同战术的能力都不一样,并没有绝对的强弱之分",
|
||||
"不要悲伤,不要心急",
|
||||
"不知道有多少人玩游戏的时候会关心游戏是谁做的",
|
||||
"部分手机系统开启震动会导致严重卡顿",
|
||||
"彩色消除即将到来!",
|
||||
"草(日本语)",
|
||||
@@ -817,6 +819,7 @@ return{
|
||||
"凑数tip什么时候能站起来!",
|
||||
"打好块跟学习一样没有捷径,多练。",
|
||||
"大概还是有人会看tip的",
|
||||
"大陆的方块社区起步晚,所以世界级高手很少…下一个会是你吗?",
|
||||
"大满贯10连击消四全清!",
|
||||
"戴上耳机以获得最佳体验",
|
||||
"单手也能玩!",
|
||||
@@ -910,12 +913,14 @@ return{
|
||||
"适度游戏益脑,沉迷游戏伤身,合理安排时间,享受健康生活",
|
||||
"手机玩也可以外接键盘哦",
|
||||
"术语不认识?去帮助-词典里查查吧",
|
||||
"水平是随着时间一点点提升的,不是几天几星期就能玩好的哦",
|
||||
"四连块总共7种",
|
||||
"虽然极简连击和极简率计算看着很怪,但是很科学!",
|
||||
"提前旋转等功能可以用来救命",
|
||||
"天哪,我竟然是一条凑数tip",
|
||||
"挖掘能力在对战里非常非常非常重要!!!!",
|
||||
"玩到一半弹出消息框?快去设置禁止弹窗",
|
||||
"玩得开心的话游戏作者也会很开心哦",
|
||||
"为了保护玩家们的健康,本游戏有一个临时的简易防沉迷系统!(不过估计你也触发不了/笑)",
|
||||
"为什么关卡那么少!因为前一模式成绩连D都没达到,再加把劲吧~",
|
||||
"我曾经在极度愤怒的时候15秒消了40行",
|
||||
@@ -946,7 +951,6 @@ return{
|
||||
"这个菜单可以用纯键盘控制",
|
||||
"这里的极简判定不松不严,放心软降,小心hold!",
|
||||
"震惊,我只是一条凑数tip吗",
|
||||
"中国的方块起步晚,所以世界级高手很少…下一个会是你吗?",
|
||||
"众所周知俄罗斯方块是经典编程练手游戏(?",
|
||||
"注意到方块\"旋转\"的时候到底发生了些什么吗?",
|
||||
"自定义场地可以画图实现逐页演示",
|
||||
@@ -973,6 +977,7 @@ return{
|
||||
"e^(pi*i/4)=(1+i)/√2",
|
||||
"Farter:\"成天被夸赞'好玩'的\"",
|
||||
"Farter:\"可以形成方块圈子小中心话题,同作者一起衍生一些概念与梗的\"",
|
||||
"Farter:\"论方块的软工意义(就算这么小个范围内,各种取舍蒙混翻车现象都总会以很易懂的方式出现(\"",
|
||||
"Farter:\"民间微创新\"",
|
||||
"Farter:\"民间音le与图案\"",
|
||||
"Farter:\"民间游戏设计\"",
|
||||
@@ -982,27 +987,29 @@ return{
|
||||
"Farter:\"是民间UI动效艺术作品\"",
|
||||
"Farter:\"是一滩散乱的代码组成的蜜汁结构\"",
|
||||
"Farter:\"它是现在的techmino已发布版本\"",
|
||||
"Farter:\"论方块的软工意义(就算这么小个范围内,各种取舍蒙混翻车现象都总会以很易懂的方式出现(\"",
|
||||
"fin neo iso 是满足tspin条件的特殊t2的名字",
|
||||
"git commit",
|
||||
"hello world",
|
||||
"if a==true",
|
||||
"l-=-1",
|
||||
"Let-The-Bass-Kick!",
|
||||
"pps-0.01",
|
||||
"shutdown -h now",
|
||||
"sin(α+β)=SαCβ+SβCα",
|
||||
"sin²α-cos²β=-C(α+β)C(α-β)",
|
||||
"sin²α-sin²β=S(α+β)S(α-β)",
|
||||
"sin2α=2SαCα",
|
||||
"Staff名单里飘过的是赞助榜单,喜欢本游戏的话可以给Z酱打赞助哦",
|
||||
"Staff名单里飘过的是赞助榜单,喜欢本游戏的话可以给我们打赞助支持开发哦~",
|
||||
"SΔABC=√(h(h-a)(h-b)(h-c)), h=(a+b+c)/2",
|
||||
"Tech生日不太清楚,那就定在2019.6.26吧",
|
||||
"Tech也有节日主题了哦",
|
||||
"Techmino = Technique + tetromino",
|
||||
"Techmino n.铁壳米诺(游戏名)",
|
||||
"Techmino console了解一下",
|
||||
"Techmino安卓下载",
|
||||
"Techmino好玩!",
|
||||
"Techmino 好玩!",
|
||||
"Techmino 濂界帺锛",
|
||||
"Techmino console了解一下",
|
||||
"Techmino n.铁壳米诺(游戏名)",
|
||||
"Techmino安卓下载",
|
||||
"Techmino好玩!",
|
||||
"Techmino有一个Nspire-CX版本!",
|
||||
"Techmino在哪里下载",
|
||||
"Techminohaowan",
|
||||
@@ -1014,7 +1021,7 @@ return{
|
||||
"Z块等身抱枕来一个(x",
|
||||
{C.A,"AQUA"},
|
||||
{C.B,"BLUE"},
|
||||
{C.C,"<PURE ",C.purple,"MEMORY>"},
|
||||
{C.C,"<PURE ",C.P,"MEMORY>"},
|
||||
{C.C,"15puzzle好玩!"},
|
||||
{C.C,"魔方好玩!"},
|
||||
{C.C,"扫雷好玩!"},
|
||||
@@ -1047,7 +1054,8 @@ return{
|
||||
{C.H,"感谢Phigros提供部分tip模板("},
|
||||
{C.H,"暂定段位:9"},
|
||||
{C.H,"REGRET!!"},
|
||||
{C.jade,"JADE"},
|
||||
{C.J,"JADE"},
|
||||
{C.L,"LIME"},
|
||||
{C.lC,"26连T2来一个?"},
|
||||
{C.lC,"Xspin",C.Z,"是啥"},
|
||||
{C.lH,"腱鞘炎警告"},
|
||||
@@ -1057,7 +1065,6 @@ return{
|
||||
{C.lH,"你有一个好"},
|
||||
{C.lH,"STSD必死"},
|
||||
{C.lH,"Techmino没有抽卡没有氪金,太良心了"},
|
||||
{C.L,"LIME"},
|
||||
{C.lP,"Naki",C.Z," 可爱!"},
|
||||
{C.lR,"Z ",C.lG,"S ",C.lS,"J ",C.lO,"L ",C.lP,"T ",C.lY,"O ",C.lC,"I"},
|
||||
{C.lS,"茶娘",C.Z," 可爱!"},
|
||||
@@ -1077,9 +1084,9 @@ return{
|
||||
{C.R,"请在有一定游戏基础之后再学Tspin!不然副作用非常大!"},
|
||||
{C.R,"新人请千万记住,打好基础,不要太早学那些花里胡哨的。"},
|
||||
{C.R,"长时间游戏状态会越来越差!玩久了记得放松一下~"},
|
||||
{C.R,"DD",C.Z,"炮=",C.purple,"TS",C.R,"D",C.Z,"+",C.purple,"TS",C.R,"D",C.Z,"炮"},
|
||||
{C.R,"DT",C.Z,"炮=",C.purple,"TS",C.R,"D",C.Z,"+",C.purple,"TS",C.R,"T",C.Z,"炮"},
|
||||
{C.R,"LrL ",C.G,"RlR ",C.B,"LLr ",C.orange,"RRl ",C.purple,"RRR LLL ",C.C,"FFF ",C.Y,"RfR RRf rFF"},
|
||||
{C.R,"DD",C.Z,"炮=",C.P,"TS",C.R,"D",C.Z,"+",C.P,"TS",C.R,"D",C.Z,"炮"},
|
||||
{C.R,"DT",C.Z,"炮=",C.P,"TS",C.R,"D",C.Z,"+",C.P,"TS",C.R,"T",C.Z,"炮"},
|
||||
{C.R,"LrL ",C.G,"RlR ",C.B,"LLr ",C.O,"RRl ",C.P,"RRR LLL ",C.C,"FFF ",C.Y,"RfR RRf rFF"},
|
||||
{C.R,"RED"},
|
||||
{C.S,"SEA"},
|
||||
{C.V,"VIOLET"},
|
||||
|
||||
@@ -28,10 +28,8 @@ return{
|
||||
bg="rainbow",bgm="sugar fairy",
|
||||
},
|
||||
load=function()
|
||||
royaleData={
|
||||
powerUp={2,5,10,20},
|
||||
stage={30,20,15,10,5},
|
||||
}
|
||||
ROYALEDATA.powerUp={2,5,10,20}
|
||||
ROYALEDATA.stage={30,20,15,10,5}
|
||||
PLY.newPlayer(1)
|
||||
local L={}for i=1,49 do L[i]=true end
|
||||
local t=CC and 2 or 0
|
||||
|
||||
@@ -28,10 +28,8 @@ return{
|
||||
bg="rainbow",bgm="rockblock",
|
||||
},
|
||||
load=function()
|
||||
royaleData={
|
||||
powerUp={2,5,10,20},
|
||||
stage={30,20,15,10,5},
|
||||
}
|
||||
ROYALEDATA.powerUp={2,5,10,20}
|
||||
ROYALEDATA.stage={30,20,15,10,5}
|
||||
PLY.newPlayer(1)
|
||||
local L={}for i=1,49 do L[i]=true end
|
||||
local t=CC and 4 or 0
|
||||
|
||||
@@ -28,10 +28,8 @@ return{
|
||||
bg="rainbow",bgm="magicblock",
|
||||
},
|
||||
load=function()
|
||||
royaleData={
|
||||
powerUp={2,5,10,20},
|
||||
stage={30,20,15,10,5},
|
||||
}
|
||||
ROYALEDATA.powerUp={2,5,10,20}
|
||||
ROYALEDATA.stage={30,20,15,10,5}
|
||||
PLY.newPlayer(1)
|
||||
local L={}for i=1,49 do L[i]=true end
|
||||
local t=CC and 6 or 0
|
||||
|
||||
@@ -28,10 +28,8 @@ return{
|
||||
bg="rainbow",bgm="sugar fairy",
|
||||
},
|
||||
load=function()
|
||||
royaleData={
|
||||
powerUp={2,6,14,30},
|
||||
stage={75,50,35,20,10},
|
||||
}
|
||||
ROYALEDATA.powerUp={2,6,14,30}
|
||||
ROYALEDATA.stage={75,50,35,20,10}
|
||||
PLY.newPlayer(1)
|
||||
local L={}for i=1,100 do L[i]=true end
|
||||
local t=CC and 4 or 0
|
||||
|
||||
@@ -28,10 +28,8 @@ return{
|
||||
bg="rainbow",bgm="rockblock",
|
||||
},
|
||||
load=function()
|
||||
royaleData={
|
||||
powerUp={2,6,14,30},
|
||||
stage={75,50,35,20,10},
|
||||
}
|
||||
ROYALEDATA.powerUp={2,6,14,30}
|
||||
ROYALEDATA.stage={75,50,35,20,10}
|
||||
PLY.newPlayer(1)
|
||||
local L={}for i=1,100 do L[i]=true end
|
||||
local t=CC and 4 or 0
|
||||
|
||||
@@ -28,10 +28,8 @@ return{
|
||||
bg="rainbow",bgm="magicblock",
|
||||
},
|
||||
load=function()
|
||||
royaleData={
|
||||
powerUp={2,6,14,30},
|
||||
stage={75,50,35,20,10},
|
||||
}
|
||||
ROYALEDATA.powerUp={2,6,14,30}
|
||||
ROYALEDATA.stage={75,50,35,20,10}
|
||||
PLY.newPlayer(1)
|
||||
local L={}for i=1,100 do L[i]=true end
|
||||
local t=CC and 4 or 0
|
||||
|
||||
@@ -141,7 +141,7 @@ function NET.getUserInfo(uid)
|
||||
WS.send("user",JSON.encode{
|
||||
action=1,
|
||||
data={
|
||||
id=uid,
|
||||
uid=uid,
|
||||
hash=hash,
|
||||
},
|
||||
})
|
||||
@@ -249,8 +249,14 @@ function NET.updateWS_app()
|
||||
elseif res.action==1 then--Get notice
|
||||
--?
|
||||
elseif res.action==2 then--Register
|
||||
LOG.print(res.data.message,300,COLOR.N)
|
||||
if SCN.cur=="register"then SCN.back()end
|
||||
if res.type=="Self"or res.type=="Server"then
|
||||
LOG.print(res.data.message,300,COLOR.N)
|
||||
if SCN.cur=="register"then
|
||||
SCN.back()
|
||||
end
|
||||
else
|
||||
LOG.print(res.reason or"Registration failed",300,COLOR.N)
|
||||
end
|
||||
NET.unlock("register")
|
||||
end
|
||||
else
|
||||
|
||||
@@ -213,15 +213,15 @@ local function loadGameEnv(P)--Load gameEnv
|
||||
for k,v in next,gameEnv0 do
|
||||
if GAME.modeEnv[k]~=nil then
|
||||
v=GAME.modeEnv[k] --Mode setting
|
||||
-- DBP("mode-"..k..":"..tostring(v))
|
||||
-- print("mode-"..k..":"..tostring(v))
|
||||
elseif GAME.setting[k]~=nil then
|
||||
v=GAME.setting[k] --Game setting
|
||||
-- DBP("game-"..k..":"..tostring(v))
|
||||
-- print("game-"..k..":"..tostring(v))
|
||||
elseif SETTING[k]~=nil then
|
||||
v=SETTING[k] --Global setting
|
||||
-- DBP("global-"..k..":"..tostring(v))
|
||||
-- print("global-"..k..":"..tostring(v))
|
||||
-- else
|
||||
-- DBP("default-"..k..":"..tostring(v))
|
||||
-- print("default-"..k..":"..tostring(v))
|
||||
end
|
||||
if type(v)~="table"then--Default setting
|
||||
ENV[k]=v
|
||||
|
||||
@@ -172,7 +172,7 @@ function Player:switchKey(id,on)
|
||||
self:releaseKey(id)
|
||||
end
|
||||
if self.type=="human"then
|
||||
virtualkey[id].ava=on
|
||||
VK.switchKey(id,on)
|
||||
end
|
||||
end
|
||||
function Player:set20G(if20g)
|
||||
@@ -1798,7 +1798,7 @@ function Player:lose(force)
|
||||
end
|
||||
A.modeData.ko,A.badge=A.modeData.ko+1,A.badge+self.badge+1
|
||||
for j=A.strength+1,4 do
|
||||
if A.badge>=royaleData.powerUp[j]then
|
||||
if A.badge>=ROYALEDATA.powerUp[j]then
|
||||
A.strength=j
|
||||
A.frameColor=A.strength
|
||||
end
|
||||
@@ -1814,7 +1814,7 @@ function Player:lose(force)
|
||||
|
||||
freshMostBadge()
|
||||
freshMostDangerous()
|
||||
if #PLY_ALIVE==royaleData.stage[GAME.stage]then
|
||||
if #PLY_ALIVE==ROYALEDATA.stage[GAME.stage]then
|
||||
royaleLevelup()
|
||||
end
|
||||
self:showTextF(self.modeData.place,0,120,60,"appear",.26,.9)
|
||||
|
||||
@@ -7,8 +7,8 @@ function scene.sceneInit()
|
||||
end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newText{name="title", x=80, y=50,font=70,align="L"},
|
||||
WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80,font=40,code=backScene},
|
||||
WIDGET.newText{name="title",x=80,y=50,font=70,align="L"},
|
||||
WIDGET.newButton{name="back",x=1140,y=640,w=170,h=80,font=40,code=backScene},
|
||||
}
|
||||
|
||||
return scene
|
||||
@@ -481,18 +481,18 @@ end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newButton{name="reset", x=155,y=100,w=180,h=100,color="lG",font=40,code=pressKey"r"},
|
||||
WIDGET.newSwitch{name="blind", x=240,y=300,w=60, font=40,disp=function()return blind end, code=pressKey"q",hide=function()return state==1 end},
|
||||
WIDGET.newSwitch{name="tapControl", x=240,y=370,w=60, font=40,disp=function()return tapControl end, code=pressKey"w",hide=function()return state==1 end},
|
||||
WIDGET.newSwitch{name="blind", x=240,y=300,w=60,font=40,disp=function()return blind end,code=pressKey"q",hide=function()return state==1 end},
|
||||
WIDGET.newSwitch{name="tapControl", x=240,y=370,w=60,font=40,disp=function()return tapControl end,code=pressKey"w",hide=function()return state==1 end},
|
||||
|
||||
WIDGET.newKey{name="up", x=155,y=460,w=100,fText="↑",font=50,color="Y",code=pressKey"up",hide=function()return tapControl end},
|
||||
WIDGET.newKey{name="down", x=155,y=660,w=100,fText="↓",font=50,color="Y",code=pressKey"down",hide=function()return tapControl end},
|
||||
WIDGET.newKey{name="left", x=55,y=560,w=100,fText="←",font=50,color="Y",code=pressKey"left",hide=function()return tapControl end},
|
||||
WIDGET.newKey{name="right", x=255,y=560,w=100,fText="→",font=50,color="Y",code=pressKey"right",hide=function()return tapControl end},
|
||||
WIDGET.newKey{name="skip", x=155,y=400,w=100,font=20,color="Y",code=pressKey"space",hide=function()return state~=1 or not skipper.cd or skipper.cd>0 end},
|
||||
WIDGET.newKey{name="record1", x=1100,y=390,w=220,h=50,fText="",color="H",code=pressKey"1",hide=function()return state==2 end},
|
||||
WIDGET.newKey{name="record2", x=1100,y=450,w=220,h=50,fText="",color="H",code=pressKey"2",hide=function()return state==2 end},
|
||||
WIDGET.newKey{name="replay1", x=1245,y=390,w=50,fText="!",color="G",code=pressKey"c1",hide=function()return state==2 or #repeater.seq[1]==0 end},
|
||||
WIDGET.newKey{name="replay2", x=1245,y=450,w=50,fText="!",color="G",code=pressKey"c2",hide=function()return state==2 or #repeater.seq[2]==0 end},
|
||||
WIDGET.newKey{name="skip", x=155,y=400,w=100,font=20, color="Y",code=pressKey"space",hide=function()return state~=1 or not skipper.cd or skipper.cd>0 end},
|
||||
WIDGET.newKey{name="record1", x=1100,y=390,w=220,h=50,fText="", color="H",code=pressKey"1",hide=function()return state==2 end},
|
||||
WIDGET.newKey{name="record2", x=1100,y=450,w=220,h=50,fText="", color="H",code=pressKey"2",hide=function()return state==2 end},
|
||||
WIDGET.newKey{name="replay1", x=1245,y=390,w=50,fText="!", color="G",code=pressKey"c1",hide=function()return state==2 or #repeater.seq[1]==0 end},
|
||||
WIDGET.newKey{name="replay2", x=1245,y=450,w=50,fText="!", color="G",code=pressKey"c2",hide=function()return state==2 or #repeater.seq[2]==0 end},
|
||||
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,font=40,code=backScene},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,8 @@ local gc=love.graphics
|
||||
local int,rnd,abs,sin,cos=math.floor,math.random,math.abs,math.sin,math.cos
|
||||
|
||||
local pow,ang
|
||||
local state,timer
|
||||
local score,combo
|
||||
local x,y
|
||||
local vx,vy
|
||||
local ex,ey
|
||||
local state,timer,score,combo
|
||||
local x,y,vx,vy,ex,ey
|
||||
|
||||
local scene={}
|
||||
function scene.sceneInit()
|
||||
@@ -81,17 +78,17 @@ function scene.update()
|
||||
end
|
||||
|
||||
local scoreColor={
|
||||
"white",--0
|
||||
"aqua",--20
|
||||
"navy",--40
|
||||
"blue",--60
|
||||
"purple",--80
|
||||
"wine",--100
|
||||
"red","fire","orange","yellow","lAqua",--200
|
||||
"lNavy","lBlue","lPurple","lWine","lRed",--300
|
||||
"lFire","lOrange","lYellow","dAqua","dNavy",--400
|
||||
"dBlue","dPurple","dWine","dRed","dFire",--500
|
||||
"dYellow","lH","H","dH",--before 600, black after
|
||||
"Z",--0
|
||||
"A",--20
|
||||
"N",--40
|
||||
"B",--60
|
||||
"P",--80
|
||||
"W",--100
|
||||
"R","F","O","Y","lA",--200
|
||||
"lN","lB","lP","lW","lR",--300
|
||||
"lF","lO","lY","dA","dN",--400
|
||||
"dB","dP","dW","dR","dF",--500
|
||||
"dY","lH","H","dH",--before 600, black after
|
||||
}
|
||||
function scene.draw()
|
||||
--Spawn area
|
||||
@@ -116,7 +113,7 @@ function scene.draw()
|
||||
gc.setColor(1,1,.6)
|
||||
gc.print("x"..combo,300,80)
|
||||
end
|
||||
gc.setColor(COLOR[scoreColor[int(score/20)+1]or"black"])
|
||||
gc.setColor(COLOR[scoreColor[int(score/20)+1]or"D"])
|
||||
gc.print(score,300,30)
|
||||
|
||||
--Cannon ball
|
||||
|
||||
@@ -697,6 +697,12 @@ function scene.keyDown(k)
|
||||
end
|
||||
elseif combKey[k]and kb.isDown("lctrl","rctrl")then
|
||||
combKey[k]()
|
||||
elseif k=="escape"then
|
||||
if WIDGET.sel~=inputBox then
|
||||
WIDGET.sel=inputBox
|
||||
else
|
||||
SCN.back()
|
||||
end
|
||||
else
|
||||
if WIDGET.sel~=inputBox then WIDGET.sel=inputBox end
|
||||
WIDGET.keyPressed(k)
|
||||
|
||||
@@ -14,6 +14,7 @@ local blind,disappear
|
||||
local startTime,time
|
||||
local state,progress
|
||||
local tapFX,mistake
|
||||
|
||||
function scene.sceneInit()
|
||||
BG.set("space")
|
||||
BGM.play("way")
|
||||
|
||||
@@ -73,8 +73,8 @@ function scene.draw()
|
||||
end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newKey{name="tap", x=640,y=540,w=626,h=260,fText="TAP",color="Z",font=100,code=pressKey"button"},
|
||||
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,font=40,code=backScene},
|
||||
WIDGET.newKey{name="tap",x=640,y=540,w=626,h=260,fText="TAP",color="Z",font=100,code=pressKey"button"},
|
||||
WIDGET.newButton{name="back",x=1140,y=640,w=170,h=80,font=40,code=backScene},
|
||||
}
|
||||
|
||||
return scene
|
||||
@@ -64,11 +64,11 @@ function scene.keyDown(key)
|
||||
elseif key=="a"then
|
||||
SCN.go("custom_advance","swipeD")
|
||||
elseif key=="c"and kb.isDown("lctrl","rctrl")or key=="cC"then
|
||||
local str="Techmino Quest:"..copyQuestArgs().."!"
|
||||
if #BAG>0 then str=str..copySequence()end
|
||||
local str="Techmino Quest:"..DATA.copyQuestArgs().."!"
|
||||
if #BAG>0 then str=str..DATA.copySequence()end
|
||||
str=str.."!"
|
||||
if #MISSION>0 then str=str..copyMission()end
|
||||
sys.setClipboardText(str.."!"..copyBoards().."!")
|
||||
if #MISSION>0 then str=str..DATA.copyMission()end
|
||||
sys.setClipboardText(str.."!"..DATA.copyBoards().."!")
|
||||
LOG.print(text.exportSuccess,COLOR.G)
|
||||
elseif key=="v"and kb.isDown("lctrl","rctrl")or key=="cV"then
|
||||
local str=sys.getClipboardText()
|
||||
@@ -76,13 +76,13 @@ function scene.keyDown(key)
|
||||
if #args<4 then goto THROW_fail end
|
||||
if not(
|
||||
pasteQuestArgs(args[1])and
|
||||
pasteSequence(args[2])and
|
||||
pasteMission(args[3])
|
||||
DATA.pasteSequence(args[2])and
|
||||
DATA.pasteMission(args[3])
|
||||
)then goto THROW_fail end
|
||||
repeat table.remove(FIELD)until #FIELD==0
|
||||
FIELD[1]=newBoard()
|
||||
FIELD[1]=DATA.newBoard()
|
||||
for i=4,#args do
|
||||
if not pasteBoard(args[i],i-3)and i<#args then goto THROW_fail end
|
||||
if not DATA.pasteBoard(args[i],i-3)and i<#args then goto THROW_fail end
|
||||
end
|
||||
freshMiniFieldVisible()
|
||||
LOG.print(text.importSuccess,COLOR.G)
|
||||
@@ -165,7 +165,7 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="copy", x=1070, y=310,w=310,h=70,color="lR",font=25,code=pressKey"cC"},
|
||||
WIDGET.newButton{name="paste", x=1070, y=390,w=310,h=70,color="lB",font=25,code=pressKey"cV"},
|
||||
WIDGET.newButton{name="clear", x=1070, y=470,w=310,h=70,color="lY",font=35,code=pressKey"return"},
|
||||
WIDGET.newButton{name="puzzle",x=1070, y=550,w=310,h=70,color="lM",font=35,code=pressKey"return2",hide=function()return not initField end},
|
||||
WIDGET.newButton{name="puzzle", x=1070, y=550,w=310,h=70,color="lM",font=35,code=pressKey"return2",hide=function()return not initField end},
|
||||
|
||||
--More
|
||||
WIDGET.newKey{name="advance", x=730, y=190,w=220,h=90,color="R",font=35,code=goScene"custom_advance"},
|
||||
|
||||
@@ -212,7 +212,7 @@ function scene.keyDown(key)
|
||||
SFX.play("fall",.8)
|
||||
end
|
||||
elseif key=="n"then
|
||||
ins(FIELD,page+1,newBoard(FIELD[page]))
|
||||
ins(FIELD,page+1,DATA.newBoard(FIELD[page]))
|
||||
page=page+1
|
||||
SFX.play("blip_1",.8)
|
||||
SYSFX.newShade(3,200,60,300,600,.5,1,.5)
|
||||
@@ -220,19 +220,19 @@ function scene.keyDown(key)
|
||||
rem(FIELD,page)
|
||||
page=max(page-1,1)
|
||||
if not FIELD[1]then
|
||||
ins(FIELD,newBoard())
|
||||
ins(FIELD,DATA.newBoard())
|
||||
end
|
||||
SYSFX.newShade(3,200,60,300,600,1,.5,.5)
|
||||
SFX.play("clear_4",.8)
|
||||
SFX.play("fall",.8)
|
||||
elseif key=="c"and kb.isDown("lctrl","rctrl")or key=="cC"then
|
||||
sys.setClipboardText("Techmino Field:"..copyBoard(page))
|
||||
sys.setClipboardText("Techmino Field:"..DATA.copyBoard(page))
|
||||
LOG.print(text.exportSuccess,COLOR.G)
|
||||
elseif key=="v"and kb.isDown("lctrl","rctrl")or key=="cV"then
|
||||
local str=sys.getClipboardText()
|
||||
local p=string.find(str,":")--ptr*
|
||||
if p then str=sub(str,p+1)end
|
||||
if pasteBoard(str,page)then
|
||||
if DATA.pasteBoard(str,page)then
|
||||
LOG.print(text.importSuccess,COLOR.G)
|
||||
else
|
||||
LOG.print(text.dataCorrupted,COLOR.R)
|
||||
@@ -445,16 +445,16 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="b16", x=1140, y=210,w=75,fText="",color="W",code=setPen(16)},--B16
|
||||
|
||||
WIDGET.newButton{name="b17", x=580, y=290,w=75,fText="[ ]",color="dH", code=setPen(17)},--BONE
|
||||
WIDGET.newButton{name="b18", x=660, y=290,w=75,fText="N", color="D", code=setPen(18)},--HIDE
|
||||
WIDGET.newButton{name="b19", x=740, y=290,w=75,fText="B", color="lY", code=setPen(19)},--BOMB
|
||||
WIDGET.newButton{name="b18", x=660, y=290,w=75,fText="N", color="D", code=setPen(18)},--HIDE
|
||||
WIDGET.newButton{name="b19", x=740, y=290,w=75,fText="B", color="lY", code=setPen(19)},--BOMB
|
||||
WIDGET.newButton{name="b20", x=820, y=290,w=75,fText="_", color="H", code=setPen(20)},--GB1
|
||||
WIDGET.newButton{name="b21", x=900, y=290,w=75,fText="_", color="lH", code=setPen(21)},--GB2
|
||||
WIDGET.newButton{name="b22", x=980, y=290,w=75,fText="_", color="dV", code=setPen(22)},--GB3
|
||||
WIDGET.newButton{name="b23", x=1060, y=290,w=75,fText="_", color="dR", code=setPen(23)},--GB4
|
||||
WIDGET.newButton{name="b24", x=1140, y=290,w=75,fText="_", color="dG", code=setPen(24)},--GB5
|
||||
WIDGET.newButton{name="b22", x=980, y=290,w=75,fText="_", color="dV", code=setPen(22)},--GB3
|
||||
WIDGET.newButton{name="b23", x=1060, y=290,w=75,fText="_", color="dR", code=setPen(23)},--GB4
|
||||
WIDGET.newButton{name="b24", x=1140, y=290,w=75,fText="_", color="dG", code=setPen(24)},--GB5
|
||||
|
||||
WIDGET.newButton{name="any", x=600, y=400,w=120,color="lH", font=40,code=setPen(0)},
|
||||
WIDGET.newButton{name="space", x=730, y=400,w=120,color="H", font=65,code=setPen(-1)},
|
||||
WIDGET.newButton{name="any", x=600, y=400,w=120,color="lH", font=40,code=setPen(0)},
|
||||
WIDGET.newButton{name="space", x=730, y=400,w=120,color="H", font=65,code=setPen(-1)},
|
||||
WIDGET.newButton{name="smartPen", x=860, y=400,w=120,color="lG", font=30,code=setPen(-2)},
|
||||
WIDGET.newButton{name="pushLine", x=990, y=400,w=120,h=120,color="lY",font=20,code=pressKey"k"},
|
||||
WIDGET.newButton{name="delLine", x=1120, y=400,w=120,h=120,color="lY",font=20,code=pressKey"l"},
|
||||
|
||||
@@ -72,14 +72,14 @@ function scene.keyDown(key)
|
||||
end
|
||||
elseif key=="c"and kb.isDown("lctrl","rctrl")or key=="cC"then
|
||||
if #MISSION>0 then
|
||||
sys.setClipboardText("Techmino Target:"..copyMission())
|
||||
sys.setClipboardText("Techmino Target:"..DATA.copyMission())
|
||||
LOG.print(text.exportSuccess,COLOR.G)
|
||||
end
|
||||
elseif key=="v"and kb.isDown("lctrl","rctrl")or key=="cV"then
|
||||
local str=sys.getClipboardText()
|
||||
local p=string.find(str,":")--ptr*
|
||||
if p then str=sub(str,p+1)end
|
||||
if pasteMission(str)then
|
||||
if DATA.pasteMission(str)then
|
||||
LOG.print(text.importSuccess,COLOR.G)
|
||||
cur=#MISSION
|
||||
else
|
||||
@@ -187,51 +187,51 @@ scene.widgetList={
|
||||
WIDGET.newText{name="title", x=520,y=5,font=70,align="R"},
|
||||
WIDGET.newText{name="subTitle", x=530,y=50,font=35,align="L",color="H"},
|
||||
|
||||
WIDGET.newKey{name="_1", x=800, y=540, w=90, font=50,code=pressKey(01)},
|
||||
WIDGET.newKey{name="_2", x=900, y=540, w=90, font=50,code=pressKey(02)},
|
||||
WIDGET.newKey{name="_3", x=800, y=640, w=90, font=50,code=pressKey(03)},
|
||||
WIDGET.newKey{name="_4", x=900, y=640, w=90, font=50,code=pressKey(04)},
|
||||
WIDGET.newKey{name="any1", x=100, y=640, w=90, code=pressKey(05)},
|
||||
WIDGET.newKey{name="any2", x=200, y=640, w=90, code=pressKey(06)},
|
||||
WIDGET.newKey{name="any3", x=300, y=640, w=90, code=pressKey(07)},
|
||||
WIDGET.newKey{name="any4", x=400, y=640, w=90, code=pressKey(08)},
|
||||
WIDGET.newKey{name="PC", x=500, y=640, w=90, font=50,code=pressKey(09)},
|
||||
WIDGET.newKey{name="_1", x=800,y=540,w=90,font=50,code=pressKey(01)},
|
||||
WIDGET.newKey{name="_2", x=900,y=540,w=90,font=50,code=pressKey(02)},
|
||||
WIDGET.newKey{name="_3", x=800,y=640,w=90,font=50,code=pressKey(03)},
|
||||
WIDGET.newKey{name="_4", x=900,y=640,w=90,font=50,code=pressKey(04)},
|
||||
WIDGET.newKey{name="any1", x=100,y=640,w=90, code=pressKey(05)},
|
||||
WIDGET.newKey{name="any2", x=200,y=640,w=90, code=pressKey(06)},
|
||||
WIDGET.newKey{name="any3", x=300,y=640,w=90, code=pressKey(07)},
|
||||
WIDGET.newKey{name="any4", x=400,y=640,w=90, code=pressKey(08)},
|
||||
WIDGET.newKey{name="PC", x=500,y=640,w=90,font=50,code=pressKey(09)},
|
||||
|
||||
WIDGET.newKey{name="Z1", x=100, y=340, w=90, font=50,code=pressKey(11)},
|
||||
WIDGET.newKey{name="S1", x=200, y=340, w=90, font=50,code=pressKey(21)},
|
||||
WIDGET.newKey{name="J1", x=300, y=340, w=90, font=50,code=pressKey(31)},
|
||||
WIDGET.newKey{name="L1", x=400, y=340, w=90, font=50,code=pressKey(41)},
|
||||
WIDGET.newKey{name="T1", x=500, y=340, w=90, font=50,code=pressKey(51)},
|
||||
WIDGET.newKey{name="O1", x=600, y=340, w=90, font=50,code=pressKey(61)},
|
||||
WIDGET.newKey{name="I1", x=700, y=340, w=90, font=50,code=pressKey(71)},
|
||||
WIDGET.newKey{name="Z1", x=100,y=340,w=90,font=50,code=pressKey(11)},
|
||||
WIDGET.newKey{name="S1", x=200,y=340,w=90,font=50,code=pressKey(21)},
|
||||
WIDGET.newKey{name="J1", x=300,y=340,w=90,font=50,code=pressKey(31)},
|
||||
WIDGET.newKey{name="L1", x=400,y=340,w=90,font=50,code=pressKey(41)},
|
||||
WIDGET.newKey{name="T1", x=500,y=340,w=90,font=50,code=pressKey(51)},
|
||||
WIDGET.newKey{name="O1", x=600,y=340,w=90,font=50,code=pressKey(61)},
|
||||
WIDGET.newKey{name="I1", x=700,y=340,w=90,font=50,code=pressKey(71)},
|
||||
|
||||
WIDGET.newKey{name="Z2", x=100, y=440, w=90, font=50,code=pressKey(12)},
|
||||
WIDGET.newKey{name="S2", x=200, y=440, w=90, font=50,code=pressKey(22)},
|
||||
WIDGET.newKey{name="J2", x=300, y=440, w=90, font=50,code=pressKey(32)},
|
||||
WIDGET.newKey{name="L2", x=400, y=440, w=90, font=50,code=pressKey(42)},
|
||||
WIDGET.newKey{name="T2", x=500, y=440, w=90, font=50,code=pressKey(52)},
|
||||
WIDGET.newKey{name="O2", x=600, y=440, w=90, font=50,code=pressKey(62)},
|
||||
WIDGET.newKey{name="I2", x=700, y=440, w=90, font=50,code=pressKey(72)},
|
||||
WIDGET.newKey{name="Z2", x=100,y=440,w=90,font=50,code=pressKey(12)},
|
||||
WIDGET.newKey{name="S2", x=200,y=440,w=90,font=50,code=pressKey(22)},
|
||||
WIDGET.newKey{name="J2", x=300,y=440,w=90,font=50,code=pressKey(32)},
|
||||
WIDGET.newKey{name="L2", x=400,y=440,w=90,font=50,code=pressKey(42)},
|
||||
WIDGET.newKey{name="T2", x=500,y=440,w=90,font=50,code=pressKey(52)},
|
||||
WIDGET.newKey{name="O2", x=600,y=440,w=90,font=50,code=pressKey(62)},
|
||||
WIDGET.newKey{name="I2", x=700,y=440,w=90,font=50,code=pressKey(72)},
|
||||
|
||||
WIDGET.newKey{name="Z3", x=100, y=540, w=90, font=50,code=pressKey(13)},
|
||||
WIDGET.newKey{name="S3", x=200, y=540, w=90, font=50,code=pressKey(23)},
|
||||
WIDGET.newKey{name="J3", x=300, y=540, w=90, font=50,code=pressKey(33)},
|
||||
WIDGET.newKey{name="L3", x=400, y=540, w=90, font=50,code=pressKey(43)},
|
||||
WIDGET.newKey{name="T3", x=500, y=540, w=90, font=50,code=pressKey(53)},
|
||||
WIDGET.newKey{name="O3", x=600, y=540, w=90, font=50,code=pressKey(63)},
|
||||
WIDGET.newKey{name="I3", x=700, y=540, w=90, font=50,code=pressKey(73)},
|
||||
WIDGET.newKey{name="Z3", x=100,y=540,w=90,font=50,code=pressKey(13)},
|
||||
WIDGET.newKey{name="S3", x=200,y=540,w=90,font=50,code=pressKey(23)},
|
||||
WIDGET.newKey{name="J3", x=300,y=540,w=90,font=50,code=pressKey(33)},
|
||||
WIDGET.newKey{name="L3", x=400,y=540,w=90,font=50,code=pressKey(43)},
|
||||
WIDGET.newKey{name="T3", x=500,y=540,w=90,font=50,code=pressKey(53)},
|
||||
WIDGET.newKey{name="O3", x=600,y=540,w=90,font=50,code=pressKey(63)},
|
||||
WIDGET.newKey{name="I3", x=700,y=540,w=90,font=50,code=pressKey(73)},
|
||||
|
||||
WIDGET.newKey{name="O4", x=600, y=640, w=90, font=50,code=pressKey(64)},
|
||||
WIDGET.newKey{name="I4", x=700, y=640, w=90, font=50,code=pressKey(74)},
|
||||
WIDGET.newKey{name="O4", x=600,y=640,w=90,font=50,code=pressKey(64)},
|
||||
WIDGET.newKey{name="I4", x=700,y=640,w=90,font=50,code=pressKey(74)},
|
||||
|
||||
WIDGET.newKey{name="left", x=800, y=440, w=90, color="lG",font=55,code=pressKey"left"},
|
||||
WIDGET.newKey{name="right", x=900, y=440, w=90, color="lG",font=55,code=pressKey"right"},
|
||||
WIDGET.newKey{name="ten", x=1000, y=440, w=90, color="lG",font=40,code=pressKey"ten"},
|
||||
WIDGET.newKey{name="backsp", x=1000, y=540, w=90, color="lY",font=50,code=pressKey"backspace"},
|
||||
WIDGET.newKey{name="reset", x=1000, y=640, w=90, color="lY",font=50,code=pressKey"delete"},
|
||||
WIDGET.newButton{name="copy", x=1140, y=440, w=170,h=80, color="lR",font=40,code=pressKey"cC",hide=function()return #MISSION==0 end},
|
||||
WIDGET.newButton{name="paste", x=1140, y=540, w=170,h=80, color="lB",font=40,code=pressKey"cV"},
|
||||
WIDGET.newSwitch{name="mission",x=1150, y=350, disp=CUSval("missionKill"),code=CUSrev("missionKill")},
|
||||
WIDGET.newKey{name="left", x=800, y=440,w=90, color="lG",font=55,code=pressKey"left"},
|
||||
WIDGET.newKey{name="right", x=900, y=440,w=90, color="lG",font=55,code=pressKey"right"},
|
||||
WIDGET.newKey{name="ten", x=1000, y=440,w=90, color="lG",font=40,code=pressKey"ten"},
|
||||
WIDGET.newKey{name="backsp", x=1000, y=540,w=90, color="lY",font=50,code=pressKey"backspace"},
|
||||
WIDGET.newKey{name="reset", x=1000, y=640,w=90, color="lY",font=50,code=pressKey"delete"},
|
||||
WIDGET.newButton{name="copy", x=1140, y=440,w=170,h=80, color="lR",font=40,code=pressKey"cC",hide=function()return #MISSION==0 end},
|
||||
WIDGET.newButton{name="paste", x=1140, y=540,w=170,h=80, color="lB",font=40,code=pressKey"cV"},
|
||||
WIDGET.newSwitch{name="mission",x=1150, y=350,disp=CUSval("missionKill"),code=CUSrev("missionKill")},
|
||||
|
||||
WIDGET.newButton{name="back", x=1140, y=640, w=170,h=80, font=40,code=backScene},
|
||||
}
|
||||
|
||||
@@ -87,14 +87,14 @@ function scene.keyDown(key)
|
||||
end
|
||||
elseif key=="c"and kb.isDown("lctrl","rctrl")or key=="cC"then
|
||||
if #BAG>0 then
|
||||
sys.setClipboardText("Techmino SEQ:"..copySequence())
|
||||
sys.setClipboardText("Techmino SEQ:"..DATA.copySequence())
|
||||
LOG.print(text.exportSuccess,COLOR.G)
|
||||
end
|
||||
elseif key=="v"and kb.isDown("lctrl","rctrl")or key=="cV"then
|
||||
local str=sys.getClipboardText()
|
||||
local p=string.find(str,":")--ptr*
|
||||
if p then str=sub(str,p+1)end
|
||||
if pasteSequence(str)then
|
||||
if DATA.pasteSequence(str)then
|
||||
LOG.print(text.importSuccess,COLOR.G)
|
||||
cur=#BAG
|
||||
else
|
||||
@@ -185,11 +185,10 @@ function scene.draw()
|
||||
end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newText{name="title", x=520,y=5,font=70,align="R"},
|
||||
WIDGET.newText{name="title",x=520,y=5,font=70,align="R"},
|
||||
WIDGET.newText{name="subTitle",x=530,y=50,font=35,align="L",color="H"},
|
||||
|
||||
WIDGET.newSelector{name="sequence",
|
||||
x=1080,y=60,w=200,color="Y",
|
||||
WIDGET.newSelector{name="sequence",x=1080,y=60,w=200,color="Y",
|
||||
list={"bag","his4","c2","rnd","mess","reverb","loop","fixed"},
|
||||
disp=CUSval("sequence"),
|
||||
code=CUSsto("sequence")
|
||||
|
||||
@@ -5,10 +5,7 @@ local tc=love.touch
|
||||
local sin=math.sin
|
||||
|
||||
local SCR=SCR
|
||||
local VK=virtualkey
|
||||
local onVirtualkey=onVirtualkey
|
||||
local pressVirtualkey=pressVirtualkey
|
||||
local updateVirtualkey=updateVirtualkey
|
||||
local VK=VK
|
||||
|
||||
local noTouch,noKey=false,false
|
||||
local touchMoveLastFrame=false
|
||||
@@ -34,16 +31,16 @@ end
|
||||
function scene.touchDown(x,y)
|
||||
if noTouch then return end
|
||||
|
||||
local t=onVirtualkey(x,y)
|
||||
local t=VK.on(x,y)
|
||||
if t then
|
||||
PLAYERS[1]:pressKey(t)
|
||||
pressVirtualkey(t,x,y)
|
||||
VK.touch(t,x,y)
|
||||
end
|
||||
end
|
||||
function scene.touchUp(x,y)
|
||||
if noTouch then return end
|
||||
|
||||
local t=onVirtualkey(x,y)
|
||||
local t=VK.on(x,y)
|
||||
if t then
|
||||
PLAYERS[1]:releaseKey(t)
|
||||
end
|
||||
@@ -56,8 +53,9 @@ function scene.touchMove()
|
||||
for i=#L,1,-1 do
|
||||
L[2*i-1],L[2*i]=SCR.xOy:inverseTransformPoint(tc.getPosition(L[i]))
|
||||
end
|
||||
for n=1,#VK do
|
||||
local B=VK[n]
|
||||
local keys=VK.keys
|
||||
for n=1,#keys do
|
||||
local B=keys[n]
|
||||
if B.ava then
|
||||
for i=1,#L,2 do
|
||||
if(L[i]-B.x)^2+(L[i+1]-B.y)^2<=B.r^2 then
|
||||
@@ -75,8 +73,9 @@ function scene.keyDown(key)
|
||||
if k>0 then
|
||||
if noKey then return end
|
||||
PLAYERS[1]:pressKey(k)
|
||||
VK[k].isDown=true
|
||||
VK[k].pressTime=10
|
||||
local vk=VK.keys[k]
|
||||
vk.isDown=true
|
||||
vk.pressTime=10
|
||||
else
|
||||
restart()
|
||||
end
|
||||
@@ -90,7 +89,7 @@ function scene.keyUp(key)
|
||||
if k then
|
||||
if k>0 then
|
||||
PLAYERS[1]:releaseKey(k)
|
||||
VK[k].isDown=false
|
||||
VK.release(k)
|
||||
end
|
||||
elseif key=="back"then
|
||||
pauseGame()
|
||||
@@ -102,8 +101,7 @@ function scene.gamepadDown(key)
|
||||
if k then
|
||||
if k>0 then
|
||||
PLAYERS[1]:pressKey(k)
|
||||
VK[k].isDown=true
|
||||
VK[k].pressTime=10
|
||||
VK.press(k)
|
||||
else
|
||||
restart()
|
||||
end
|
||||
@@ -117,7 +115,7 @@ function scene.gamepadUp(key)
|
||||
if k then
|
||||
if k>0 then
|
||||
PLAYERS[1]:releaseKey(k)
|
||||
VK[k].isDown=false
|
||||
VK.release(k)
|
||||
end
|
||||
elseif key=="back"then
|
||||
pauseGame()
|
||||
@@ -138,10 +136,10 @@ function scene.update(dt)
|
||||
if key==0 then--Just wait
|
||||
elseif key<=32 then--Press key
|
||||
P1:pressKey(key)
|
||||
pressVirtualkey(key)
|
||||
VK.press(key)
|
||||
elseif key<=64 then--Release key
|
||||
P1:releaseKey(key-32)
|
||||
VK[key-32].isDown=false
|
||||
VK.release(key-32)
|
||||
end
|
||||
_=_+2
|
||||
end
|
||||
@@ -149,7 +147,7 @@ function scene.update(dt)
|
||||
end
|
||||
|
||||
touchMoveLastFrame=false
|
||||
updateVirtualkey()
|
||||
VK.update()
|
||||
|
||||
--Update players
|
||||
for p=1,#PLAYERS do PLAYERS[p]:update(dt)end
|
||||
@@ -183,7 +181,7 @@ function scene.draw()
|
||||
end
|
||||
|
||||
--Virtual keys
|
||||
drawVirtualkeys()
|
||||
VK.draw()
|
||||
|
||||
--Attacking & Being attacked
|
||||
if GAME.modeEnv.royaleMode then
|
||||
|
||||
@@ -22,6 +22,8 @@ function scene.mouseDown(_,_,k)
|
||||
else
|
||||
SCN.go(SETTING.simpMode and"main_simple"or"main")
|
||||
end
|
||||
else
|
||||
SCN.swapTo("quit","slowFade")
|
||||
end
|
||||
end
|
||||
function scene.touchDown()
|
||||
@@ -30,7 +32,7 @@ end
|
||||
function scene.keyDown(key)
|
||||
if key=="escape"then
|
||||
VOC.play("bye")
|
||||
SCN.back()
|
||||
SCN.swapTo("quit","slowFade")
|
||||
else
|
||||
scene.mouseDown()
|
||||
end
|
||||
|
||||
@@ -32,7 +32,6 @@ function scene.sceneInit()
|
||||
|
||||
--Set quick-play-button text
|
||||
scene.widgetList[2]:setObject(text.WidgetText.main.qplay..": "..text.modes[STAT.lastPlay][1])
|
||||
quickSure=false
|
||||
|
||||
--Create demo player
|
||||
destroyPlayers()
|
||||
@@ -184,8 +183,8 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="dict", x=2480,y=450,w=800,h=100, color="lG",font=40,align="L",edge=30,code=pressKey"l"},
|
||||
WIDGET.newButton{name="manual", x=2480,y=570,w=800,h=100, color="lC",font=40,align="L",edge=30,code=pressKey","},
|
||||
|
||||
WIDGET.newButton{name="music", x=160,y=80,w=200,h=90, color="lO",font=35,code=pressKey"2"},
|
||||
WIDGET.newButton{name="lang", x=960,y=80,w=90,h=90, color="lY",font=40,code=pressKey"0",fText=DOGC{64,64,
|
||||
WIDGET.newButton{name="music", x=130,y=80,w=200,h=90, color="lO",font=35,code=pressKey"2"},
|
||||
WIDGET.newButton{name="lang", x=300,y=80,w=90,h=90, color="lN",font=40,code=pressKey"0",fText=DOGC{64,64,
|
||||
{"setLW",4},
|
||||
{"dCirc",32,32,30},
|
||||
{"dLine",2,31,62,31},
|
||||
@@ -194,7 +193,7 @@ scene.widgetList={
|
||||
{"doArc",53,31,40,2.3,3.9},
|
||||
}},
|
||||
WIDGET.newButton{name="about", x=-110,y=670,w=600,h=70, color="lB",font=35,align="R",edge=30,code=pressKey"x"},
|
||||
WIDGET.newButton{name="quit", x=1390,y=670,w=600,h=70, color="lR",font=40,align="L",edge=30,code=function()VOC.play("bye")SCN.swapTo("quit","slowFade")end},
|
||||
WIDGET.newButton{name="back", x=1390,y=670,w=600,h=70, color="lR",font=40,align="L",edge=30,code=backScene},
|
||||
}
|
||||
|
||||
return scene
|
||||
@@ -4,10 +4,7 @@ local tc=love.touch
|
||||
local ins=table.insert
|
||||
|
||||
local SCR=SCR
|
||||
local VK=virtualkey
|
||||
local onVirtualkey=onVirtualkey
|
||||
local pressVirtualkey=pressVirtualkey
|
||||
local updateVirtualkey=updateVirtualkey
|
||||
local VK=VK
|
||||
|
||||
local textBox=WIDGET.newTextBox{name="texts",x=340,y=80,w=600,h=550,hide=false}
|
||||
|
||||
@@ -38,16 +35,16 @@ scene.mouseDown=NULL
|
||||
function scene.touchDown(x,y)
|
||||
if noTouch or not playing then return end
|
||||
|
||||
local t=onVirtualkey(x,y)
|
||||
local t=VK.on(x,y)
|
||||
if t then
|
||||
PLAYERS[1]:pressKey(t)
|
||||
pressVirtualkey(t,x,y)
|
||||
VK.touch(t,x,y)
|
||||
end
|
||||
end
|
||||
function scene.touchUp(x,y)
|
||||
if noTouch or not playing then return end
|
||||
|
||||
local t=onVirtualkey(x,y)
|
||||
local t=VK.on(x,y)
|
||||
if t then
|
||||
PLAYERS[1]:releaseKey(t)
|
||||
end
|
||||
@@ -60,8 +57,9 @@ function scene.touchMove()
|
||||
for i=#L,1,-1 do
|
||||
L[2*i-1],L[2*i]=SCR.xOy:inverseTransformPoint(tc.getPosition(L[i]))
|
||||
end
|
||||
for n=1,#VK do
|
||||
local B=VK[n]
|
||||
local keys=VK.keys
|
||||
for n=1,#keys do
|
||||
local B=keys[n]
|
||||
if B.ava then
|
||||
for i=1,#L,2 do
|
||||
if(L[i]-B.x)^2+(L[i+1]-B.y)^2<=B.r^2 then
|
||||
@@ -88,8 +86,9 @@ function scene.keyDown(key)
|
||||
local k=keyMap.keyboard[key]
|
||||
if k and k>0 then
|
||||
PLAYERS[1]:pressKey(k)
|
||||
VK[k].isDown=true
|
||||
VK[k].pressTime=10
|
||||
local vk=VK.keys[k]
|
||||
vk.isDown=true
|
||||
vk.pressTime=10
|
||||
end
|
||||
elseif key=="space"then
|
||||
NET.signal_ready(not PLY_NET[1].ready)
|
||||
@@ -100,7 +99,7 @@ function scene.keyUp(key)
|
||||
local k=keyMap.keyboard[key]
|
||||
if k and k>0 then
|
||||
PLAYERS[1]:releaseKey(k)
|
||||
VK[k].isDown=false
|
||||
VK.release(k)
|
||||
end
|
||||
end
|
||||
function scene.gamepadDown(key)
|
||||
@@ -116,8 +115,7 @@ function scene.gamepadDown(key)
|
||||
local k=keyMap.joystick[key]
|
||||
if k and k>0 then
|
||||
PLAYERS[1]:pressKey(k)
|
||||
VK[k].isDown=true
|
||||
VK[k].pressTime=10
|
||||
VK.press(k)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -126,7 +124,7 @@ function scene.gamepadUp(key)
|
||||
local k=keyMap.joystick[key]
|
||||
if k and k>0 then
|
||||
PLAYERS[1]:releaseKey(k)
|
||||
VK[k].isDown=false
|
||||
VK.release(k)
|
||||
return
|
||||
end
|
||||
end
|
||||
@@ -185,7 +183,7 @@ function scene.socketRead(cmd,d)
|
||||
if P.uid==d.uid then
|
||||
local res,stream=pcall(love.data.decode,"string","base64",d.stream)
|
||||
if res then
|
||||
pumpRecording(stream,P.stream)
|
||||
DATA.pumpRecording(stream,P.stream)
|
||||
else
|
||||
LOG.print("Bad stream from "..P.username.."#"..P.uid)
|
||||
end
|
||||
@@ -203,7 +201,7 @@ function scene.update(dt)
|
||||
local GAME=GAME
|
||||
|
||||
touchMoveLastFrame=false
|
||||
updateVirtualkey()
|
||||
VK.update()
|
||||
|
||||
--Update players
|
||||
for p=1,#PLAYERS do PLAYERS[p]:update(dt)end
|
||||
@@ -214,7 +212,7 @@ function scene.update(dt)
|
||||
--Upload stream
|
||||
if P1.frameRun-lastUpstreamTime>8 then
|
||||
local stream
|
||||
stream,upstreamProgress=dumpRecording(GAME.rep,upstreamProgress)
|
||||
stream,upstreamProgress=DATA.dumpRecording(GAME.rep,upstreamProgress)
|
||||
if #stream>0 then
|
||||
NET.uploadRecStream(stream)
|
||||
else
|
||||
@@ -235,7 +233,7 @@ function scene.draw()
|
||||
end
|
||||
|
||||
--Virtual keys
|
||||
drawVirtualkeys()
|
||||
VK.draw()
|
||||
|
||||
--Warning
|
||||
drawWarning()
|
||||
@@ -248,14 +246,17 @@ function scene.draw()
|
||||
gc.setLineWidth(3)
|
||||
gc.rectangle("line",40,67+50*i,800,42)
|
||||
|
||||
--Username
|
||||
gc.setColor(1,1,1)
|
||||
setFont(40)
|
||||
gc.print(p.username,200,60+50*i)
|
||||
|
||||
--UID
|
||||
setFont(40)
|
||||
gc.setColor(.5,.5,.5)
|
||||
gc.print("#"..p.uid,50,60+50*i)
|
||||
|
||||
--Avatar
|
||||
gc.setColor(1,1,1)
|
||||
gc.draw(USERS.getAvatar(p.uid),200,68+50*i,nil,.3125)
|
||||
|
||||
--Username
|
||||
gc.print(p.username,240,60+50*i)
|
||||
end
|
||||
|
||||
--Profile
|
||||
|
||||
@@ -25,6 +25,7 @@ scene.widgetList={
|
||||
NET.wsclose_play()
|
||||
NET.wsclose_user()
|
||||
USER.uid=false
|
||||
USER.username=false
|
||||
USER.authToken=false
|
||||
FILE.save(USER,"conf/user","q")
|
||||
SCN.back()
|
||||
@@ -34,7 +35,7 @@ scene.widgetList={
|
||||
lastLogoutTime=TIME()
|
||||
end
|
||||
end},
|
||||
WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80, font=40,code=backScene},
|
||||
WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80,font=40,code=backScene},
|
||||
}
|
||||
|
||||
return scene
|
||||
@@ -143,8 +143,10 @@ function scene.keyDown(key)
|
||||
SCN.swapTo("game","none")
|
||||
end
|
||||
elseif key=="o"then
|
||||
if(GAME.result or GAME.replaying)and #PLAYERS==1 and not GAME.saved and saveRecording()then
|
||||
GAME.saved=true
|
||||
if(GAME.result or GAME.replaying)and #PLAYERS==1 and not GAME.saved then
|
||||
if DATA.saveRecording()then
|
||||
GAME.saved=true
|
||||
end
|
||||
end
|
||||
else
|
||||
WIDGET.keyPressed(key)
|
||||
|
||||
@@ -51,8 +51,7 @@ end
|
||||
function scene.touchUp()
|
||||
if selected then
|
||||
local B=VK_org[selected]
|
||||
local k=snapUnit
|
||||
B.x,B.y=int(B.x/k+.5)*k,int(B.y/k+.5)*k
|
||||
B.x,B.y=int(B.x/snapUnit+.5)*snapUnit,int(B.y/snapUnit+.5)*snapUnit
|
||||
end
|
||||
end
|
||||
function scene.touchMove(_,_,dx,dy)
|
||||
@@ -62,41 +61,19 @@ function scene.touchMove(_,_,dx,dy)
|
||||
end
|
||||
end
|
||||
|
||||
local function virtualkeyPreview()
|
||||
if SETTING.VKSwitch then
|
||||
for i=1,#VK_org do
|
||||
local B=VK_org[i]
|
||||
if B.ava then
|
||||
gc.setColor(1,1,1,SETTING.VKAlpha)
|
||||
gc.setLineWidth(B.r*.07)
|
||||
gc.circle("line",B.x,B.y,B.r,10)
|
||||
if selected==i and TIME()%.26<.13 then
|
||||
gc.setColor(1,1,1,SETTING.VKAlpha*.62)
|
||||
gc.circle("fill",B.x,B.y,B.r,10)
|
||||
end
|
||||
if SETTING.VKIcon then
|
||||
local c=B.color
|
||||
gc.setColor(c[1],c[2],c[3],SETTING.VKAlpha)
|
||||
gc.draw(TEXTURE.VKIcon[i],B.x,B.y,nil,B.r*.025,nil,18,18)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function scene.draw()
|
||||
gc.setColor(1,1,1)
|
||||
gc.setLineWidth(7)gc.rectangle("line",340,15,600,690)
|
||||
gc.setLineWidth(3)gc.rectangle("line",490,85,300,600)
|
||||
virtualkeyPreview()
|
||||
local d=snapUnit
|
||||
if d>=10 then
|
||||
VK.preview(selected)
|
||||
if snapUnit>=10 then
|
||||
gc.setLineWidth(3)
|
||||
gc.setColor(1,1,1,sin(TIME()*4)*.1+.1)
|
||||
for i=1,1280/d-1 do
|
||||
gc.line(d*i,0,d*i,720)
|
||||
for i=1,1280/snapUnit-1 do
|
||||
gc.line(snapUnit*i,0,snapUnit*i,720)
|
||||
end
|
||||
for i=1,720/d-1 do
|
||||
gc.line(0,d*i,1280,d*i)
|
||||
for i=1,720/snapUnit-1 do
|
||||
gc.line(0,snapUnit*i,1280,snapUnit*i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -28,12 +28,12 @@ scene.widgetList={
|
||||
WIDGET.newSwitch{name="b18", x=580, y=500, font=35,disp=VKAdisp(18),code=VKAcode(18)},
|
||||
WIDGET.newSwitch{name="b19", x=580, y=560, font=35,disp=VKAdisp(19),code=VKAcode(19)},
|
||||
WIDGET.newSwitch{name="b20", x=580, y=620, font=35,disp=VKAdisp(20),code=VKAcode(20)},
|
||||
WIDGET.newButton{name="norm", x=840, y=100, w=240,h=80, font=35,code=function()for i=1,20 do VK_org[i].ava=i<11 end end},
|
||||
WIDGET.newButton{name="pro", x=1120, y=100, w=240,h=80, font=35,code=function()for i=1,20 do VK_org[i].ava=true end end},
|
||||
WIDGET.newSwitch{name="hide", x=1170, y=200, font=40,disp=SETval("VKSwitch"),code=SETrev("VKSwitch")},
|
||||
WIDGET.newSwitch{name="track", x=1170, y=300, font=35,disp=SETval("VKTrack"),code=SETrev("VKTrack")},
|
||||
WIDGET.newSlider{name="sfx", x=800, y=380, w=180, font=35,change=function()SFX.play("virtualKey",SETTING.VKSFX)end,disp=SETval("VKSFX"),code=SETsto("VKSFX")},
|
||||
WIDGET.newSlider{name="vib", x=800, y=460, w=180,unit=2, font=35,change=function()VIB(SETTING.VKVIB)end,disp=SETval("VKVIB"),code=SETsto("VKVIB")},
|
||||
WIDGET.newButton{name="norm", x=840, y=100, w=240,h=80, font=35,code=function()for i=1,20 do VK_org[i].ava=i<11 end end},
|
||||
WIDGET.newButton{name="pro", x=1120, y=100, w=240,h=80, font=35,code=function()for i=1,20 do VK_org[i].ava=true end end},
|
||||
WIDGET.newSwitch{name="hide", x=1170, y=200, font=40,disp=SETval("VKSwitch"),code=SETrev("VKSwitch")},
|
||||
WIDGET.newSwitch{name="track", x=1170, y=300, font=35,disp=SETval("VKTrack"),code=SETrev("VKTrack")},
|
||||
WIDGET.newSlider{name="sfx", x=800, y=380, w=180, font=35,change=function()SFX.play("virtualKey",SETTING.VKSFX)end,disp=SETval("VKSFX"),code=SETsto("VKSFX")},
|
||||
WIDGET.newSlider{name="vib", x=800, y=460, w=180,unit=2,font=35,change=function()VIB(SETTING.VKVIB)end,disp=SETval("VKVIB"),code=SETsto("VKVIB")},
|
||||
WIDGET.newSwitch{name="icon", x=850, y=300, font=40,disp=SETval("VKIcon"),code=SETrev("VKIcon")},
|
||||
WIDGET.newButton{name="tkset", x=1120, y=420, w=240,h=80,
|
||||
code=function()
|
||||
|
||||
@@ -13,10 +13,10 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="sound", x=200, y=80,w=240,h=80,color="lC",font=35,code=swapScene"setting_sound","swipeR"},
|
||||
WIDGET.newButton{name="game", x=1080, y=80,w=240,h=80,color="lC",font=35,code=swapScene"setting_game","swipeL"},
|
||||
|
||||
WIDGET.newSwitch{name="block", x=290, y=165, disp=SETval("block"), code=SETrev("block")},
|
||||
WIDGET.newSwitch{name="smooth", x=290, y=215, disp=SETval("smooth"), code=SETrev("smooth")},
|
||||
WIDGET.newSwitch{name="upEdge", x=290, y=265, disp=SETval("upEdge"), code=SETrev("upEdge")},
|
||||
WIDGET.newSwitch{name="bagLine", x=290, y=315, disp=SETval("bagLine"), code=SETrev("bagLine")},
|
||||
WIDGET.newSwitch{name="block", x=290, y=165,disp=SETval("block"),code=SETrev("block")},
|
||||
WIDGET.newSwitch{name="smooth", x=290, y=215,disp=SETval("smooth"),code=SETrev("smooth")},
|
||||
WIDGET.newSwitch{name="upEdge", x=290, y=265,disp=SETval("upEdge"),code=SETrev("upEdge")},
|
||||
WIDGET.newSwitch{name="bagLine", x=290, y=315,disp=SETval("bagLine"),code=SETrev("bagLine")},
|
||||
|
||||
WIDGET.newSlider{name="ghost", x=600, y=180,w=200,unit=.6,disp=SETval("ghost"),show="percent",code=SETsto("ghost")},
|
||||
WIDGET.newSlider{name="grid", x=600, y=240,w=200,unit=.4,disp=SETval("grid"),show="percent", code=SETsto("grid")},
|
||||
@@ -37,14 +37,14 @@ scene.widgetList={
|
||||
SETTING.frameMul=i<5 and 5*i+20 or 10*i
|
||||
end},
|
||||
|
||||
WIDGET.newSwitch{name="text", x=1140, y=160,font=35,disp=SETval("text"), code=SETrev("text")},
|
||||
WIDGET.newSwitch{name="score", x=1140, y=210,font=35,disp=SETval("score"), code=SETrev("score")},
|
||||
WIDGET.newSwitch{name="warn", x=1140, y=260,font=35,disp=SETval("warn"), code=SETrev("warn")},
|
||||
WIDGET.newSwitch{name="highCam", x=1140, y=310,font=35,disp=SETval("highCam"),code=SETrev("highCam")},
|
||||
WIDGET.newSwitch{name="nextPos", x=1140, y=360,font=35,disp=SETval("nextPos"),code=SETrev("nextPos")},
|
||||
WIDGET.newSwitch{name="fullscreen", x=1140, y=410,disp=SETval("fullscreen"), code=switchFullscreen},
|
||||
WIDGET.newSwitch{name="power", x=1140, y=460,font=35,disp=SETval("powerInfo"),code=SETrev("powerInfo")},
|
||||
WIDGET.newSwitch{name="clickFX", x=1140, y=510,font=35,disp=SETval("clickFX"),code=SETrev("clickFX")},
|
||||
WIDGET.newSwitch{name="text", x=1140, y=160,font=35,disp=SETval("text"), code=SETrev("text")},
|
||||
WIDGET.newSwitch{name="score", x=1140, y=210,font=35,disp=SETval("score"), code=SETrev("score")},
|
||||
WIDGET.newSwitch{name="warn", x=1140, y=260,font=35,disp=SETval("warn"), code=SETrev("warn")},
|
||||
WIDGET.newSwitch{name="highCam", x=1140, y=310,font=35,disp=SETval("highCam"), code=SETrev("highCam")},
|
||||
WIDGET.newSwitch{name="nextPos", x=1140, y=360,font=35,disp=SETval("nextPos"), code=SETrev("nextPos")},
|
||||
WIDGET.newSwitch{name="fullscreen", x=1140, y=410,disp=SETval("fullscreen"), code=switchFullscreen},
|
||||
WIDGET.newSwitch{name="power", x=1140, y=460,font=35,disp=SETval("powerInfo"), code=SETrev("powerInfo")},
|
||||
WIDGET.newSwitch{name="clickFX", x=1140, y=510,font=35,disp=SETval("clickFX"), code=SETrev("clickFX")},
|
||||
WIDGET.newSwitch{name="bg", x=1140, y=560,font=35,disp=SETval("bg"),
|
||||
code=function()
|
||||
BG.set("none")
|
||||
|
||||
@@ -34,6 +34,7 @@ function SKIN.init(list)
|
||||
I=gc.newImage("media/image/skin/"..list[1]..".png")
|
||||
LOG.print("No skin file: "..list[i],"warn")
|
||||
end
|
||||
gc.setDefaultFilter("linear","linear")
|
||||
for y=0,2 do
|
||||
for x=1,8 do
|
||||
SKIN.lib[i][8*y+x]=C(30,30)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
local gc=love.graphics
|
||||
local ins=table.insert
|
||||
|
||||
local function NSC(x,y)--New & Set Canvas
|
||||
local _=gc.newCanvas(x,y)
|
||||
gc.setCanvas(_)
|
||||
@@ -84,6 +86,21 @@ gc.setColor(1,1,1)
|
||||
gc.circle("line",8,8,7)
|
||||
gc.circle("fill",8,8,3)
|
||||
|
||||
TEXTURE.lvIcon=setmetatable({},{__index=function(self,lv)
|
||||
local img={25,25}
|
||||
|
||||
ins(img,{"clear",0,0,0})
|
||||
ins(img,{"setLW",4})
|
||||
ins(img,{"setCL",COLOR.lN})
|
||||
ins(img,{"dRect",2,2,21,21})
|
||||
--TODO: draw with lv
|
||||
|
||||
img=DOGC(img)
|
||||
rawset(self,lv,img)
|
||||
return img
|
||||
end})
|
||||
|
||||
|
||||
|
||||
gc.setDefaultFilter("linear","linear")
|
||||
|
||||
|
||||
@@ -33,14 +33,13 @@ return STRING.split([=[
|
||||
改动:
|
||||
微调TRS中PQT5J5L5的踢墙表
|
||||
加强消四,增加b2b点数(100→150)
|
||||
增强hpc攻击力(2→4)
|
||||
修改pc和hpc对b2b点数的影响
|
||||
增强hpc攻击力(2→4),修改pc和hpc对b2b点数的影响
|
||||
自定义游戏设置会自动保存,默认设置为无重力科研
|
||||
调低竞速模式部分评价要求,科研模式通关条件改为100攻击(原200)
|
||||
调整master-ph命数奖励
|
||||
对战背景改为主题默认背景
|
||||
主菜单语言按钮改为地球图标
|
||||
修改硬降音效
|
||||
主菜单语言按钮改为地球图标,移到左上角
|
||||
词典修改部分词条,调整词条顺序(意见来自群友 库德里尔)
|
||||
移除词典中两个不必要的个人词条
|
||||
词典支持左右键翻页,添加触屏可用的翻页按钮
|
||||
@@ -52,6 +51,7 @@ return STRING.split([=[
|
||||
新增users模块用来管理网络用户缓存信息
|
||||
play场景改名game
|
||||
重构GAME.frame相关内容
|
||||
大规模整理代码
|
||||
修复:
|
||||
登录界面邮箱格式判定错误
|
||||
调整主菜单点击联网游戏按钮代码的逻辑
|
||||
|
||||
@@ -12,26 +12,26 @@ local function loadAvatar(path)
|
||||
return canvas
|
||||
end
|
||||
|
||||
local texture_noImage=DOGC{120,120,
|
||||
{"setCL",0,0,0},
|
||||
{"fRect",0,0,120,120},
|
||||
local emptyUser={
|
||||
username="Player",
|
||||
motto="",
|
||||
hash="",
|
||||
new=true,
|
||||
}
|
||||
local texture_noImage=DOGC{128,128,
|
||||
{"setCL",.1,.1,.1},
|
||||
{"fRect",0,0,128,128},
|
||||
{"setCL",1,1,1},
|
||||
{"setLW",6},
|
||||
{"dLine",9,9,110,110},
|
||||
{"dLine",9,110,110,9},
|
||||
{"dLine",9,9,118,118},
|
||||
{"dLine",9,118,118,9},
|
||||
}
|
||||
|
||||
local db_img={}
|
||||
local db=setmetatable({},{__index=function(self,k)
|
||||
if not k then return emptyUser end
|
||||
local file="cache/user"..k..".dat"
|
||||
local d=
|
||||
fs.getInfo(file)and JSON.decode(fs.read(file))or
|
||||
{
|
||||
username="[X]",
|
||||
motto="Techmino haowan",
|
||||
hash="",
|
||||
new=false,
|
||||
}
|
||||
local d=fs.getInfo(file)and JSON.decode(fs.read(file))or TABLE.copy(emptyUser)
|
||||
rawset(self,k,d)
|
||||
if type(d.hash)=="string"and #d.hash>0 and fs.getInfo("cache/"..d.hash)then
|
||||
db_img[k]=loadAvatar("cache/"..d.hash)
|
||||
@@ -54,7 +54,6 @@ function USERS.updateUserData(data)
|
||||
fs.write("cache/"..data.hash,love.data.decode("string","base64",data.avatar:sub(data.avatar:find","+1)))
|
||||
db_img[uid]=loadAvatar("cache/"..data.hash)
|
||||
db[uid].hash=type(data.hash)=="string"and #data.hash>0 and data.hash
|
||||
db[uid].new=true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
174
parts/virtualKey.lua
Normal file
174
parts/virtualKey.lua
Normal file
@@ -0,0 +1,174 @@
|
||||
local SETTING=SETTING
|
||||
|
||||
local keys={}
|
||||
for i=1,#VK_org do keys[i]={}end--In-game virtualkey layout
|
||||
|
||||
local VK={}
|
||||
|
||||
VK.keys=keys
|
||||
|
||||
function VK.on(x,y)
|
||||
local dist,nearest=1e10
|
||||
for K=1,#keys do
|
||||
local B=keys[K]
|
||||
if B.ava then
|
||||
local d1=(x-B.x)^2+(y-B.y)^2
|
||||
if d1<B.r^2 then
|
||||
if d1<dist then
|
||||
nearest,dist=K,d1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return nearest
|
||||
end
|
||||
|
||||
function VK.touch(id,x,y)
|
||||
local B=keys[id]
|
||||
B.isDown=true
|
||||
B.pressTime=10
|
||||
|
||||
if SETTING.VKTrack then
|
||||
--Auto follow
|
||||
local O=VK_org[id]
|
||||
local _FW,_CW=SETTING.VKTchW,1-SETTING.VKCurW
|
||||
local _OW=1-_FW-_CW
|
||||
--(finger+current+origin)
|
||||
B.x=x*_FW+B.x*_CW+O.x*_OW
|
||||
B.y=y*_FW+B.y*_CW+O.y*_OW
|
||||
|
||||
--Button collision (not accurate)
|
||||
if SETTING.VKDodge then
|
||||
for i=1,#keys do
|
||||
local b=keys[i]
|
||||
local d=B.r+b.r-((B.x-b.x)^2+(B.y-b.y)^2)^.5--Hit depth(Neg means distance)
|
||||
if d>0 then
|
||||
b.x=b.x+(b.x-B.x)*d*b.r*2.6e-5
|
||||
b.y=b.y+(b.y-B.y)*d*b.r*2.6e-5
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
SFX.play("virtualKey",SETTING.VKSFX)
|
||||
VIB(SETTING.VKVIB)
|
||||
end
|
||||
|
||||
function VK.press(id)
|
||||
keys[id].isDown=true
|
||||
keys[id].pressTime=10
|
||||
end
|
||||
|
||||
function VK.release(id)
|
||||
keys[id].isDown=false
|
||||
end
|
||||
|
||||
function VK.switchKey(id,on)
|
||||
keys[id].ava=on
|
||||
end
|
||||
|
||||
function VK.restore()
|
||||
for i=1,#VK_org do
|
||||
local B,O=keys[i],VK_org[i]
|
||||
B.ava=O.ava
|
||||
B.x=O.x
|
||||
B.y=O.y
|
||||
B.r=O.r
|
||||
B.color=O.color
|
||||
B.isDown=false
|
||||
B.pressTime=0
|
||||
end
|
||||
for k,v in next,PLAYERS[1].keyAvailable do
|
||||
if not v then
|
||||
keys[k].ava=false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function VK.update()
|
||||
if SETTING.VKSwitch then
|
||||
for i=1,#keys do
|
||||
local _=keys[i]
|
||||
if _.pressTime>0 then
|
||||
_.pressTime=_.pressTime-1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local gc=love.graphics
|
||||
local gc_circle,gc_draw,gc_setColor,gc_setLineWidth=gc.circle,gc.draw,gc.setColor,gc.setLineWidth
|
||||
function VK.draw()
|
||||
if SETTING.VKSwitch then
|
||||
local a=SETTING.VKAlpha
|
||||
local _
|
||||
if SETTING.VKIcon then
|
||||
local icons=TEXTURE.VKIcon
|
||||
for i=1,#keys do
|
||||
if keys[i].ava then
|
||||
local B=keys[i]
|
||||
|
||||
--Button outline
|
||||
gc_setColor(1,1,1,a)
|
||||
gc_setLineWidth(B.r*.07)
|
||||
gc_circle("line",B.x,B.y,B.r,10)
|
||||
|
||||
--Icon
|
||||
_=keys[i].pressTime
|
||||
local c=B.color
|
||||
gc_setColor(c[1],c[2],c[3],a)
|
||||
gc_draw(icons[i],B.x,B.y,nil,B.r*.026+_*.08,nil,18,18)
|
||||
|
||||
--Ripple
|
||||
if _>0 then
|
||||
gc_setColor(1,1,1,a*_*.08)
|
||||
gc_circle("line",B.x,B.y,B.r*(1.4-_*.04),10)
|
||||
end
|
||||
|
||||
--Glow when press
|
||||
if B.isDown then
|
||||
gc_setColor(1,1,1,a*.4)
|
||||
gc_circle("fill",B.x,B.y,B.r*.94,10)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
for i=1,#keys do
|
||||
if keys[i].ava then
|
||||
local B=keys[i]
|
||||
gc_setColor(1,1,1,a)
|
||||
gc_setLineWidth(B.r*.07)
|
||||
gc_circle("line",B.x,B.y,B.r,10)
|
||||
_=keys[i].pressTime
|
||||
if _>0 then
|
||||
gc_setColor(1,1,1,a*_*.08)
|
||||
gc_circle("fill",B.x,B.y,B.r*.94,10)
|
||||
gc_circle("line",B.x,B.y,B.r*(1.4-_*.04),10)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function VK.preview(selected)
|
||||
if SETTING.VKSwitch then
|
||||
for i=1,#VK_org do
|
||||
local B=VK_org[i]
|
||||
if B.ava then
|
||||
gc_setColor(1,1,1,SETTING.VKAlpha)
|
||||
gc_setLineWidth(B.r*.07)
|
||||
gc_circle("line",B.x,B.y,B.r,10)
|
||||
if selected==i and TIME()%.26<.13 then
|
||||
gc_setColor(1,1,1,SETTING.VKAlpha*.62)
|
||||
gc_circle("fill",B.x,B.y,B.r,10)
|
||||
end
|
||||
if SETTING.VKIcon then
|
||||
local c=B.color
|
||||
gc_setColor(c[1],c[2],c[3],SETTING.VKAlpha)
|
||||
gc_draw(TEXTURE.VKIcon[i],B.x,B.y,nil,B.r*.025,nil,18,18)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return VK
|
||||
Reference in New Issue
Block a user