Merge branch 'wstest_3_28' into main
@@ -165,7 +165,7 @@ function love.touchpressed(id,x,y)
|
||||
if SCN.touchDown then SCN.touchDown(x,y)end
|
||||
if kb.hasTextInput()then kb.setTextInput(false)end
|
||||
end
|
||||
function love.touchmoved(id,x,y,dx,dy)
|
||||
function love.touchmoved(_,x,y,dx,dy)
|
||||
if SCN.swapping then return end
|
||||
x,y=xOy:inverseTransformPoint(x,y)
|
||||
if SCN.touchMove then SCN.touchMove(x,y,dx/SCR.k,dy/SCR.k)end
|
||||
@@ -205,7 +205,7 @@ local function noDevkeyPressed(key)
|
||||
LOG.print(string.format("System:%s[%s]\nluaVer:%s\njitVer:%s\njitVerNum:%s",SYSTEM,jit.arch,_VERSION,jit.version,jit.version_num))
|
||||
elseif key=="f3"then
|
||||
for _=1,8 do
|
||||
local P=PLAYERS.alive[rnd(#PLAYERS.alive)]
|
||||
local P=PLY_ALIVE[rnd(#PLY_ALIVE)]
|
||||
if P~=PLAYERS[1]then
|
||||
P.lastRecv=PLAYERS[1]
|
||||
P:lose()
|
||||
@@ -382,7 +382,7 @@ function love.errorhandler(msg)
|
||||
love.audio.stop()
|
||||
gc.reset()
|
||||
|
||||
if LOADED and #ERRDATA<5 then
|
||||
if LOADED and #ERRDATA<3 then
|
||||
BG.set("none")
|
||||
local scn=SCN and SCN.cur or"NULL"
|
||||
ERRDATA[#ERRDATA+1]={mes=err,scene=scn}
|
||||
@@ -444,13 +444,13 @@ function love.errorhandler(msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
local WSnames={"app","user","chat","play","stream"}
|
||||
local WSnames={"app","user","play","stream","chat"}
|
||||
local WScolor={
|
||||
{1,0,0,.26},
|
||||
{1,.7,0,.26},
|
||||
{0,.7,1,.26},
|
||||
{0,1,0,.26},
|
||||
{1,1,0,.26}
|
||||
{1,.5,.5,.7},
|
||||
{1,.8,.3,.7},
|
||||
{1,1,.4,.7},
|
||||
{.4,1,.7,.7},
|
||||
{.5,.8,1,.7},
|
||||
}
|
||||
local devColor={
|
||||
COLOR.white,
|
||||
@@ -511,7 +511,7 @@ function love.run()
|
||||
if SCN.swapping then SCN.swapUpdate()end--Scene swapping animation
|
||||
WIDGET.update()--Widgets animation
|
||||
LOG.update()
|
||||
WS.update()
|
||||
WS.update(dt)
|
||||
|
||||
--DRAW
|
||||
if not MINI()then
|
||||
@@ -587,22 +587,21 @@ function love.run()
|
||||
for i=1,5 do
|
||||
local status=WS.status(WSnames[i])
|
||||
gc_setColor(WScolor[i])
|
||||
gc_rectangle("fill",0,20*i,-20,-20)
|
||||
gc_rectangle("fill",0,20*i,-80,-20)
|
||||
if status=="dead"then
|
||||
gc_setColor(.8,.8,.8)
|
||||
gc_setColor(1,1,1)
|
||||
gc_draw(TEXTURE.ws_dead,-20,20*i-20)
|
||||
elseif status=="connecting"then
|
||||
gc_setColor(.8,.8,.8,.5+.3*sin(t*6.26))
|
||||
gc_setColor(1,1,1,.5+.3*sin(t*6.26))
|
||||
gc_draw(TEXTURE.ws_connecting,-20,20*i-20)
|
||||
elseif status=="running"then
|
||||
gc_setColor(.8,.8,.8)
|
||||
gc_setColor(1,1,1)
|
||||
gc_draw(TEXTURE.ws_running,-20,20*i-20)
|
||||
end
|
||||
local lastPongTime=WS.lastPongTime(WSnames[i])
|
||||
if lastPongTime<1 then
|
||||
gc_setColor(1,1,1,1-lastPongTime)
|
||||
gc_rectangle("fill",0,20*i,-20,-20)
|
||||
end
|
||||
local t1,t2,t3=WS.getTimers(WSnames[i])
|
||||
gc_setColor(1,1,1,t1)gc_rectangle("fill",-60,20*i,-20,-20)
|
||||
gc_setColor(0,1,0,t2)gc_rectangle("fill",-40,20*i,-20,-20)
|
||||
gc_setColor(1,0,0,t3)gc_rectangle("fill",-20,20*i,-20,-20)
|
||||
end
|
||||
gc_pop()
|
||||
|
||||
|
||||
@@ -137,7 +137,8 @@ function SCN.swapTo(tar,style)--Parallel scene swapping, cannot back
|
||||
SCN.swapping=true
|
||||
local S=SCN.stat
|
||||
S.tar,S.style=tar,style
|
||||
S.time,S.mid,S.draw=unpack(swap[style])
|
||||
local s=swap[style]
|
||||
S.time,S.mid,S.draw=s[1],s[2],s[3]
|
||||
end
|
||||
else
|
||||
LOG.print("No Scene: "..tar,"warn")
|
||||
@@ -152,6 +153,8 @@ function SCN.go(tar,style)--Normal scene swapping, can back
|
||||
end
|
||||
end
|
||||
function SCN.back()
|
||||
if SCN.swapping then return end
|
||||
|
||||
--Leave scene
|
||||
if SCN.sceneBack then SCN.sceneBack()end
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
local gc=love.graphics
|
||||
local setColor,setWidth=gc.setColor,gc.setLineWidth
|
||||
local sin,cos=math.sin,math.cos
|
||||
local max,min=math.max,math.min
|
||||
local rnd=math.random
|
||||
local rem=table.remove
|
||||
@@ -77,8 +78,13 @@ function FXdraw.tap(S)
|
||||
gc.circle("line",S.x,S.y,t*(2-t)*30)
|
||||
setColor(1,1,1,(1-t)*.5)
|
||||
gc.circle("fill",S.x,S.y,t*30)
|
||||
setColor(1,1,1,(1-t)*.2)
|
||||
gc.circle("fill",S.x,S.y,(t*(1-t)*2)*30)
|
||||
|
||||
setColor(1,1,1,1-t)
|
||||
for i=1,10 do
|
||||
local p=S.ptc[i]
|
||||
local T=t^.5
|
||||
gc.rectangle("fill",p[1]*(1-T)+p[3]*T-5,p[2]*(1-T)+p[4]*T-5,11,11)
|
||||
end
|
||||
end
|
||||
function FXdraw.ripple(S)
|
||||
local t=S.t
|
||||
@@ -142,13 +148,21 @@ function SYSFX.newAttack(rate,x1,y1,x2,y2,wid,r,g,b,a)
|
||||
}
|
||||
end
|
||||
function SYSFX.newTap(rate,x,y)
|
||||
fx[#fx+1]={
|
||||
local T=
|
||||
{
|
||||
update=FXupdate.tap,
|
||||
draw=FXdraw.tap,
|
||||
t=0,
|
||||
rate=rate,
|
||||
x=x,y=y,
|
||||
ptc={},
|
||||
}
|
||||
for i=1,10 do
|
||||
local d=40+50*rnd()
|
||||
local ang=rnd()*6.2832
|
||||
T.ptc[i]={x,y,x+d*cos(ang),y+d*sin(ang)}
|
||||
end
|
||||
fx[#fx+1]=T
|
||||
end
|
||||
function SYSFX.newRipple(rate,x,y,r)
|
||||
fx[#fx+1]={
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
local next,type=next,type
|
||||
local TABLE={}
|
||||
|
||||
--Copy [1~#] elements
|
||||
function TABLE.shift(org)
|
||||
local L={}
|
||||
for i=1,#org do
|
||||
@@ -11,6 +13,8 @@ function TABLE.shift(org)
|
||||
end
|
||||
return L
|
||||
end
|
||||
|
||||
--Copy all elements
|
||||
function TABLE.copy(org)
|
||||
local L={}
|
||||
for k,v in next,org do
|
||||
@@ -22,18 +26,22 @@ function TABLE.copy(org)
|
||||
end
|
||||
return L
|
||||
end
|
||||
function TABLE.add(G,base)--For all things in G if same type in base, push to base
|
||||
|
||||
--For all things in G if same type in base, push to base
|
||||
function TABLE.update(G,base)
|
||||
for k,v in next,G do
|
||||
if type(v)==type(base[k])then
|
||||
if type(v)=="table"then
|
||||
TABLE.add(v,base[k])
|
||||
TABLE.update(v,base[k])
|
||||
else
|
||||
base[k]=v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function TABLE.complete(G,base)--For all things in G if no val in base, push to base
|
||||
|
||||
--For all things in G if no val in base, push to base
|
||||
function TABLE.complete(G,base)
|
||||
for k,v in next,G do
|
||||
if base[k]==nil then
|
||||
base[k]=v
|
||||
@@ -42,6 +50,22 @@ function TABLE.complete(G,base)--For all things in G if no val in base, push to
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Remove positive integer index of table
|
||||
function TABLE.cut(G)
|
||||
for i=#G,1,-1 do
|
||||
G[i]=nil
|
||||
end
|
||||
end
|
||||
|
||||
--Clear table
|
||||
function TABLE.clear(G)
|
||||
for k in next,G do
|
||||
G[k]=nil
|
||||
end
|
||||
end
|
||||
|
||||
--Re-index string value of a table
|
||||
function TABLE.reIndex(org)
|
||||
for k,v in next,org do
|
||||
if type(v)=="string"then
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
local rem=table.remove
|
||||
local ct=coroutine
|
||||
local assert=assert
|
||||
local assert,resume,status=assert,coroutine.resume,coroutine.status
|
||||
local tasks={}
|
||||
|
||||
local TASK={}
|
||||
@@ -10,16 +9,17 @@ end
|
||||
function TASK.update()
|
||||
for i=#tasks,1,-1 do
|
||||
local T=tasks[i]
|
||||
assert(ct.resume(T.thread))
|
||||
if ct.status(T.thread)=="dead"then
|
||||
rem(tasks,i)
|
||||
if status(T.thread)=="dead"then
|
||||
rem(tasks,i)
|
||||
else
|
||||
assert(resume(T.thread))
|
||||
end
|
||||
end
|
||||
end
|
||||
function TASK.new(code,...)
|
||||
local thread=ct.create(code)
|
||||
ct.resume(thread,...)
|
||||
if ct.status(thread)~="dead"then
|
||||
local thread=coroutine.create(code)
|
||||
resume(thread,...)
|
||||
if status(thread)~="dead"then
|
||||
tasks[#tasks+1]={
|
||||
thread=thread,
|
||||
code=code,
|
||||
|
||||
@@ -27,6 +27,10 @@ function THEME.calculate(Y,M,D)
|
||||
})[Y-2000]or -26)-((M-1)*31+D))<6 and
|
||||
"sprfes"or
|
||||
|
||||
--April fool's day
|
||||
M=="04"and D=="01"and
|
||||
"fool"or
|
||||
|
||||
--Z day (Feb./Mar./Apr./May./June 26)
|
||||
math.abs(M-4)<=2 and D+0==26 and
|
||||
"zday"or
|
||||
@@ -53,6 +57,9 @@ function THEME.set(theme)
|
||||
elseif theme=="zday"then
|
||||
BG.setDefault("lanterns")
|
||||
BGM.setDefault("overzero")
|
||||
elseif theme=="fool"then
|
||||
BG.setDefault("blockrain")
|
||||
BGM.setDefault("how feeling")
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
@@ -4,51 +4,19 @@ local host="hdustea.3322.org"
|
||||
local port="10026"
|
||||
local path="/tech/socket/v1"
|
||||
|
||||
local debug=false
|
||||
|
||||
local wsThread=[[
|
||||
-- lua + love2d threading websocket client
|
||||
-- Original pure lua ver. by flaribbit and Particle_G and MrZ
|
||||
-- Original pure lua ver. by flaribbit and Particle_G
|
||||
-- Threading version by MrZ
|
||||
|
||||
local triggerCHN,sendCHN,readCHN=...
|
||||
local triggerCHN,sendCHN,readCHN,threadName=...
|
||||
|
||||
|
||||
|
||||
local byte,char=string.byte,string.char
|
||||
local band,bor,bxor=bit.band,bit.bor,bit.bxor
|
||||
local shl,shr=bit.lshift,bit.rshift
|
||||
|
||||
local SOCK=require"socket".tcp()
|
||||
local JSON=require"Zframework.json"
|
||||
|
||||
local mask_key={1,14,5,14}
|
||||
local function _send(opcode,message)
|
||||
--Message type
|
||||
SOCK:send(char(bor(0x80,opcode)))
|
||||
|
||||
if not message then
|
||||
SOCK:send(char(0x80,unpack(mask_key)))
|
||||
return 0
|
||||
end
|
||||
|
||||
--Length
|
||||
local length=#message
|
||||
if length>65535 then
|
||||
SOCK:send(char(bor(127,0x80),0,0,0,0,band(shr(length,24),0xff),band(shr(length,16),0xff),band(shr(length,8),0xff),band(length,0xff)))
|
||||
elseif length>125 then
|
||||
SOCK:send(char(bor(126,0x80),band(shr(length,8),0xff),band(length,0xff)))
|
||||
else
|
||||
SOCK:send(char(bor(length,0x80)))
|
||||
end
|
||||
SOCK:send(char(unpack(mask_key)))
|
||||
local msgbyte={byte(message,1,length)}
|
||||
for i=1,length do
|
||||
msgbyte[i]=bxor(msgbyte[i],mask_key[(i-1)%4+1])
|
||||
end
|
||||
return SOCK:send(char(unpack(msgbyte)))
|
||||
end
|
||||
|
||||
|
||||
|
||||
do--Connect
|
||||
local host=sendCHN:demand()
|
||||
local port=sendCHN:demand()
|
||||
@@ -57,48 +25,97 @@ do--Connect
|
||||
|
||||
SOCK:settimeout(2.6)
|
||||
local res,err=SOCK:connect(host,port)
|
||||
if res then
|
||||
--WebSocket handshake
|
||||
if not body then body=""end
|
||||
SOCK:send(
|
||||
"GET "..path.." HTTP/1.1\r\n"..
|
||||
"Host: "..host..":"..port.."\r\n"..
|
||||
"Connection: Upgrade\r\n"..
|
||||
"Upgrade: websocket\r\n"..
|
||||
"Content-Type: application/json\r\n"..
|
||||
"Content-Length: "..#body.."\r\n"..
|
||||
"Sec-WebSocket-Version: 13\r\n"..
|
||||
"Sec-WebSocket-Key: osT3F7mvlojIvf3/8uIsJQ==\r\n\r\n"..--secKey
|
||||
body
|
||||
)
|
||||
if err then readCHN:push(err)return end
|
||||
|
||||
--First line of HTTP
|
||||
local l=SOCK:receive("*l")
|
||||
local code,ctLen
|
||||
if l then
|
||||
code=l:find(" "); code=l:sub(code+1,code+3)
|
||||
repeat
|
||||
l=SOCK:receive("*l")
|
||||
if not ctLen and l:find"length"then
|
||||
ctLen=tonumber(l:match"%d+")
|
||||
end
|
||||
until l==""
|
||||
--WebSocket handshake
|
||||
if not body then body=""end
|
||||
SOCK:send(
|
||||
"GET "..path.." HTTP/1.1\r\n"..
|
||||
"Host: "..host..":"..port.."\r\n"..
|
||||
"Connection: Upgrade\r\n"..
|
||||
"Upgrade: websocket\r\n"..
|
||||
"Content-Type: application/json\r\n"..
|
||||
"Content-Length: "..#body.."\r\n"..
|
||||
"Sec-WebSocket-Version: 13\r\n"..
|
||||
"Sec-WebSocket-Key: osT3F7mvlojIvf3/8uIsJQ==\r\n\r\n"..--secKey
|
||||
body
|
||||
)
|
||||
|
||||
--First line of HTTP
|
||||
res,err=SOCK:receive("*l")
|
||||
if not res then readCHN:push(err)return end
|
||||
local code,ctLen
|
||||
code=res:find(" ")
|
||||
code=res:sub(code+1,code+3)
|
||||
|
||||
--Get body length from headers and remove headers
|
||||
repeat
|
||||
res,err=SOCK:receive("*l")
|
||||
if not res then readCHN:push(err)return end
|
||||
if not ctLen and res:find"length"then
|
||||
ctLen=tonumber(res:match"%d+")
|
||||
end
|
||||
until res==""
|
||||
|
||||
--Result
|
||||
if ctLen then
|
||||
if code=="101"then
|
||||
readCHN:push("success")
|
||||
else
|
||||
local reason=JSON.decode(SOCK:receive(ctLen))
|
||||
readCHN:push(code..":"..(reason and reason.message or"Server Error"))
|
||||
res,err=SOCK:receive(ctLen)
|
||||
if not res then readCHN:push(err)return end
|
||||
res=JSON.decode(res)
|
||||
readCHN:push((code or"XXX")..":"..(res and res.reason or"Server Error"))
|
||||
end
|
||||
else
|
||||
readCHN:push(err)
|
||||
end
|
||||
SOCK:settimeout(0)
|
||||
end
|
||||
|
||||
|
||||
|
||||
local byte=string.byte
|
||||
local band,shl=bit.band,bit.lshift
|
||||
|
||||
local _send do
|
||||
local char=string.char
|
||||
local bor,bxor=bit.bor,bit.bxor
|
||||
local shr=bit.rshift
|
||||
|
||||
local mask_key={1,14,5,14}
|
||||
local mask_str=char(unpack(mask_key))
|
||||
|
||||
function _send(opcode,message)
|
||||
--Message type
|
||||
SOCK:send(char(bor(0x80,opcode)))
|
||||
|
||||
if message then
|
||||
--Length
|
||||
local length=#message
|
||||
if length>65535 then
|
||||
SOCK:send(char(bor(127,0x80),0,0,0,0,band(shr(length,24),0xff),band(shr(length,16),0xff),band(shr(length,8),0xff),band(length,0xff)))
|
||||
elseif length>125 then
|
||||
SOCK:send(char(bor(126,0x80),band(shr(length,8),0xff),band(length,0xff)))
|
||||
else
|
||||
SOCK:send(char(bor(length,0x80)))
|
||||
end
|
||||
SOCK:send(mask_str)
|
||||
local msgbyte={byte(message,1,length)}
|
||||
for i=1,length do
|
||||
msgbyte[i]=bxor(msgbyte[i],mask_key[(i-1)%4+1])
|
||||
end
|
||||
return SOCK:send(char(unpack(msgbyte)))
|
||||
else
|
||||
SOCK:send("\128"..mask_str)
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
local length
|
||||
local lBuffer=""--Long multi-data buffer
|
||||
local UFF--Un-finished-frame mode
|
||||
local sBuffer=""--Short multi-frame buffer
|
||||
while true do--Running
|
||||
--Send
|
||||
triggerCHN:demand()
|
||||
while sendCHN:getCount()>=2 do
|
||||
local op=sendCHN:pop()
|
||||
@@ -106,39 +123,85 @@ while true do--Running
|
||||
_send(op,message)
|
||||
end
|
||||
|
||||
while true do--Read
|
||||
--Byte 0-1
|
||||
local res,err=SOCK:receive(2)
|
||||
if not res then break end
|
||||
|
||||
local op=band(byte(res,1),0x0f)
|
||||
|
||||
--Calculating data length
|
||||
local length=band(byte(res,2),0x7f)
|
||||
if length==126 then
|
||||
res=SOCK:receive(2)
|
||||
length=shl(byte(res,1),8)+byte(res,2)
|
||||
elseif length==127 then
|
||||
res=SOCK:receive(8)
|
||||
local b={byte(res,1,8)}
|
||||
length=shl(b[5],32)+shl(b[6],24)+shl(b[7],8)+b[8]
|
||||
end
|
||||
|
||||
--Receive data
|
||||
res=SOCK:receive(length)
|
||||
|
||||
--React
|
||||
readCHN:push(op)
|
||||
if op==8 then--close
|
||||
SOCK:close()
|
||||
if type(res)=="string"then
|
||||
local reason=JSON.decode(res)
|
||||
readCHN:push(reason and reason.message or"Server Error")
|
||||
else
|
||||
readCHN:push("Server Error")
|
||||
--Read
|
||||
while true do
|
||||
if UFF then--UNF process
|
||||
local s,e,p=SOCK:receive(length)
|
||||
if s then
|
||||
sBuffer=sBuffer..s
|
||||
UFF=false
|
||||
elseif p then
|
||||
sBuffer=sBuffer..p
|
||||
length=length-#p
|
||||
if length==0 then
|
||||
UFF=false
|
||||
end
|
||||
end
|
||||
else
|
||||
readCHN:push(res)
|
||||
--Byte 0-1
|
||||
local res,err=SOCK:receive(2)
|
||||
if err then break end
|
||||
|
||||
local op=band(byte(res,1),0x0f)
|
||||
local fin=band(byte(res,1),0x80)==0x80
|
||||
|
||||
--Calculating data length
|
||||
length=band(byte(res,2),0x7f)
|
||||
if length==126 then
|
||||
res=SOCK:receive(2)
|
||||
length=shl(byte(res,1),8)+byte(res,2)
|
||||
elseif length==127 then
|
||||
local b={byte(SOCK:receive(8),1,8)}
|
||||
length=shl(b[5],24)+shl(b[6],16)+shl(b[7],8)+b[8]
|
||||
end
|
||||
|
||||
if length>0 then
|
||||
--Receive data
|
||||
local s,_,p=SOCK:receive(length)
|
||||
if s then
|
||||
]]..(debug==1 and""or"--")..[[print(("%s[%d]:%s"):format(threadName,length,s))
|
||||
res=s
|
||||
elseif p then--UNF head
|
||||
]]..(debug==1 and""or"--")..[[print(("%s[%d/%d]:%s"):format(threadName,#p,length,p))
|
||||
UFF=true
|
||||
sBuffer=sBuffer..p
|
||||
length=length-#p
|
||||
break
|
||||
end
|
||||
else
|
||||
res=""
|
||||
end
|
||||
|
||||
--React
|
||||
if op==8 then--8=close
|
||||
readCHN:push(op)
|
||||
SOCK:close()
|
||||
if type(res)=="string"then
|
||||
res=JSON.decode(res)
|
||||
readCHN:push(res and res.reason or"WS Error")
|
||||
else
|
||||
readCHN:push("WS Error")
|
||||
end
|
||||
elseif op==0 then--0=continue
|
||||
lBuffer=lBuffer..res
|
||||
if fin then
|
||||
]]..(debug==2 and""or"--")..[[print("FIN=1 (c")
|
||||
readCHN:push(lBuffer)
|
||||
lBuffer=""
|
||||
else
|
||||
]]..(debug==2 and""or"--")..[[print("FIN=0 (c")
|
||||
end
|
||||
else
|
||||
readCHN:push(op)
|
||||
if fin then
|
||||
]]..(debug==2 and""or"--")..[[print("OP: "..op.."\tFIN=1")
|
||||
readCHN:push(res)
|
||||
else
|
||||
]]..(debug==2 and""or"--")..[[print("OP: "..op.."\tFIN=0")
|
||||
sBuffer=res
|
||||
]]..(debug==2 and""or"--")..[[print("START pack: "..res)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -146,10 +209,24 @@ end
|
||||
|
||||
local timer=love.timer.getTime
|
||||
local WS={}
|
||||
local wsList={}
|
||||
local wsList=setmetatable({},{
|
||||
__index=function(l,k)
|
||||
local ws={
|
||||
real=false,
|
||||
status="dead",
|
||||
lastPongTime=timer(),
|
||||
sendTimer=0,
|
||||
alertTimer=0,
|
||||
pongTimer=0,
|
||||
}
|
||||
l[k]=ws
|
||||
return ws
|
||||
end
|
||||
})
|
||||
|
||||
function WS.connect(name,subPath,body)
|
||||
local ws={
|
||||
real=true,
|
||||
thread=love.thread.newThread(wsThread),
|
||||
triggerCHN=love.thread.newChannel(),
|
||||
sendCHN=love.thread.newChannel(),
|
||||
@@ -158,9 +235,12 @@ function WS.connect(name,subPath,body)
|
||||
lastPongTime=timer(),
|
||||
pingInterval=26,
|
||||
status="connecting",--connecting, running, dead
|
||||
sendTimer=0,
|
||||
alertTimer=0,
|
||||
pongTimer=0,
|
||||
}
|
||||
wsList[name]=ws
|
||||
ws.thread:start(ws.triggerCHN,ws.sendCHN,ws.readCHN)
|
||||
ws.thread:start(ws.triggerCHN,ws.sendCHN,ws.readCHN,name)
|
||||
ws.sendCHN:push(host)
|
||||
ws.sendCHN:push(port)
|
||||
ws.sendCHN:push(path..subPath)
|
||||
@@ -168,11 +248,13 @@ function WS.connect(name,subPath,body)
|
||||
end
|
||||
|
||||
function WS.status(name)
|
||||
return wsList[name]and wsList[name].status or"dead"
|
||||
local ws=wsList[name]
|
||||
return ws.status or"dead"
|
||||
end
|
||||
|
||||
function WS.lastPongTime(name)
|
||||
return wsList[name]and timer()-wsList[name].lastPongTime or 999
|
||||
function WS.getTimers(name)
|
||||
local ws=wsList[name]
|
||||
return ws.pongTimer,ws.sendTimer,ws.alertTimer
|
||||
end
|
||||
|
||||
function WS.setPingInterval(name,time)
|
||||
@@ -180,6 +262,11 @@ function WS.setPingInterval(name,time)
|
||||
ws.pingInterval=math.max(time or 1,2.6)
|
||||
end
|
||||
|
||||
function WS.alert(name)
|
||||
local ws=wsList[name]
|
||||
ws.alertTimer=2
|
||||
end
|
||||
|
||||
local OPcode={
|
||||
continue=0,
|
||||
text=1,
|
||||
@@ -188,54 +275,76 @@ local OPcode={
|
||||
ping=9,
|
||||
pong=10,
|
||||
}
|
||||
local OPname={
|
||||
[0]="continue",
|
||||
[1]="text",
|
||||
[2]="binary",
|
||||
[8]="close",
|
||||
[9]="ping",
|
||||
[10]="pong",
|
||||
}
|
||||
function WS.send(name,message,op)
|
||||
local ws=wsList[name]
|
||||
ws.sendCHN:push(op and OPcode[op]or 2)--2=binary
|
||||
ws.sendCHN:push(message)
|
||||
ws.lastPingTime=timer()
|
||||
if ws.real then
|
||||
ws.sendCHN:push(op and OPcode[op]or 2)--2=binary
|
||||
ws.sendCHN:push(message)
|
||||
ws.lastPingTime=timer()
|
||||
ws.sendTimer=1
|
||||
end
|
||||
end
|
||||
|
||||
function WS.read(name)
|
||||
local ws=wsList[name]
|
||||
if ws.readCHN:getCount()>=2 then
|
||||
if ws.real and ws.readCHN:getCount()>=2 then
|
||||
local op=ws.readCHN:pop()
|
||||
local message=ws.readCHN:pop()
|
||||
if op==8 then ws.status="dead"end
|
||||
if op==8 then ws.status="dead"end--8=close
|
||||
ws.lastPongTime=timer()
|
||||
return message,op
|
||||
ws.pongTimer=1
|
||||
return message,OPname[op]or op
|
||||
end
|
||||
end
|
||||
|
||||
function WS.close(name)
|
||||
local ws=wsList[name]
|
||||
ws.sendCHN:push(8)--close
|
||||
ws.sendCHN:push("")
|
||||
ws.status="dead"
|
||||
if ws.real then
|
||||
ws.sendCHN:push(8)--close
|
||||
ws.sendCHN:push("")
|
||||
ws.status="dead"
|
||||
end
|
||||
end
|
||||
|
||||
function WS.update()
|
||||
function WS.update(dt)
|
||||
local time=timer()
|
||||
for name,ws in next,wsList do
|
||||
ws.triggerCHN:push(0)
|
||||
if ws.status=="connecting"then
|
||||
local mes=ws.readCHN:pop()
|
||||
if mes then
|
||||
if mes=="success"then
|
||||
ws.status="running"
|
||||
if ws.real then
|
||||
ws.triggerCHN:push(0)
|
||||
if ws.status=="connecting"then
|
||||
local mes=ws.readCHN:pop()
|
||||
if mes then
|
||||
if mes=="success"then
|
||||
ws.status="running"
|
||||
ws.lastPingTime=time
|
||||
ws.lastPongTime=time
|
||||
ws.pongTimer=1
|
||||
else
|
||||
ws.status="dead"
|
||||
LOG.print(text.wsFailed..": "..(mes=="timeout"and text.netTimeout or mes),"warn")
|
||||
end
|
||||
end
|
||||
elseif ws.status=="running"then
|
||||
if time-ws.lastPingTime>ws.pingInterval then
|
||||
ws.sendCHN:push(9)
|
||||
ws.sendCHN:push("")--ping
|
||||
ws.lastPingTime=time
|
||||
ws.lastPongTime=time
|
||||
else
|
||||
ws.status="dead"
|
||||
LOG.print(text.wsFailed.." "..mes,"warn")
|
||||
end
|
||||
if time-ws.lastPongTime>10+3*ws.pingInterval then
|
||||
WS.close(name)
|
||||
end
|
||||
end
|
||||
elseif time-ws.lastPingTime>ws.pingInterval then
|
||||
ws.sendCHN:push(9)
|
||||
ws.sendCHN:push("")--ping
|
||||
ws.lastPingTime=time
|
||||
end
|
||||
if time-ws.lastPongTime>10+3*ws.pingInterval then
|
||||
WS.close(name)
|
||||
if ws.sendTimer>0 then ws.sendTimer=ws.sendTimer-dt end
|
||||
if ws.pongTimer>0 then ws.pongTimer=ws.pongTimer-dt end
|
||||
if ws.alertTimer>0 then ws.alertTimer=ws.alertTimer-dt end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -141,7 +141,8 @@ end
|
||||
function button:draw()
|
||||
local x,y,w,h=self.x,self.y,self.w,self.h
|
||||
local ATV=self.ATV
|
||||
local r,g,b=unpack(self.color)
|
||||
local c=self.color
|
||||
local r,g,b=c[1],c[2],c[3]
|
||||
gc.setColor(.2+r*.8,.2+g*.8,.2+b*.8,.7)
|
||||
gc.rectangle("fill",x-ATV,y-ATV,w+2*ATV,h+2*ATV)
|
||||
if ATV>0 then
|
||||
@@ -233,7 +234,8 @@ end
|
||||
function key:draw()
|
||||
local x,y,w,h=self.x,self.y,self.w,self.h
|
||||
local ATV=self.ATV
|
||||
local r,g,b=unpack(self.color)
|
||||
local c=self.color
|
||||
local r,g,b=c[1],c[2],c[3]
|
||||
|
||||
gc.setColor(1,1,1,ATV*.125)
|
||||
gc.rectangle("fill",x,y,w,h)
|
||||
|
||||
4
conf.lua
@@ -1,5 +1,5 @@
|
||||
VERSION_CODE=1303
|
||||
VERSION_NAME="Alpha V0.13.3"
|
||||
VERSION_CODE=1400
|
||||
VERSION_NAME="Alpha V0.14.0"
|
||||
function love.conf(t)
|
||||
t.identity="Techmino"--Saving folder
|
||||
t.version="11.1"
|
||||
|
||||
32
main.lua
@@ -23,12 +23,7 @@ SAVEDIR=fs.getSaveDirectory()
|
||||
--Global Vars & Settings
|
||||
LOADED=false
|
||||
DAILYLAUNCH=false
|
||||
LOGIN=false
|
||||
EDITING=""
|
||||
NET={
|
||||
allow_online=false,
|
||||
try_enter_netmenu=false,
|
||||
}
|
||||
ERRDATA={}
|
||||
|
||||
--System setting
|
||||
@@ -81,6 +76,7 @@ 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"
|
||||
|
||||
@@ -113,14 +109,14 @@ IMG.init{
|
||||
pay1="mess/pay1.png",
|
||||
pay2="mess/pay2.png",
|
||||
|
||||
miyaCH="miya/ch.png",
|
||||
miyaF1="miya/f1.png",
|
||||
miyaF2="miya/f2.png",
|
||||
miyaF3="miya/f3.png",
|
||||
miyaF4="miya/f4.png",
|
||||
|
||||
electric="mess/electric.png",
|
||||
hbm="mess/hbm.png",
|
||||
nakiCH="characters/naki.png",
|
||||
miyaCH="characters/miya.png",
|
||||
miyaF1="characters/miya_f1.png",
|
||||
miyaF2="characters/miya_f2.png",
|
||||
miyaF3="characters/miya_f3.png",
|
||||
miyaF4="characters/miya_f4.png",
|
||||
electric="characters/electric.png",
|
||||
hbm="characters/hbm.png",
|
||||
|
||||
lanterns={
|
||||
"lanterns/1.png",
|
||||
@@ -259,14 +255,12 @@ do
|
||||
if type(STAT.version)~="number"then
|
||||
STAT.version=0
|
||||
end
|
||||
if STAT.version<1204 then
|
||||
if STAT.version<1300 then
|
||||
STAT.frame=math.floor(STAT.time*60)
|
||||
STAT.lastPlay="sprint_10l"
|
||||
RANKS.sprintFix=nil
|
||||
RANKS.sprintLock=nil
|
||||
needSave=true
|
||||
end
|
||||
if STAT.version<1300 then
|
||||
for _,name in next,fs.getDirectoryItems("replay")do
|
||||
fs.remove("replay/"..name)
|
||||
end
|
||||
@@ -274,13 +268,15 @@ do
|
||||
if STAT.version<1302 then
|
||||
if RANKS.pctrain_n then RANKS.pctrain_n=0 end
|
||||
if RANKS.pctrain_l then RANKS.pctrain_l=0 end
|
||||
fs.remove("conf/user")
|
||||
fs.remove("conf/settings")
|
||||
needSave=true
|
||||
autoRestart=true
|
||||
end
|
||||
if STAT.version<1303 then
|
||||
if STAT.version<1400 then
|
||||
fs.remove("conf/user")
|
||||
SETTING.appLock=false
|
||||
needSave=true
|
||||
autoRestart=true
|
||||
end
|
||||
|
||||
for _,v in next,VK_org do
|
||||
|
||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
media/image/characters/naki.png
Normal file
|
After Width: | Height: | Size: 121 KiB |
@@ -1,6 +1,6 @@
|
||||
local int,ceil,min,abs,rnd,modf=math.floor,math.ceil,math.min,math.abs,math.random,math.modf
|
||||
local ins,rem=table.insert,table.remove
|
||||
local resume,yield=coroutine.resume,coroutine.yield
|
||||
local yield=coroutine.yield
|
||||
-- controlname:
|
||||
-- 1~5:mL,mR,rR,rL,rF,
|
||||
-- 6~10:hD,sD,H,A,R,
|
||||
@@ -73,13 +73,13 @@ if type(_CC)=="table"then
|
||||
end
|
||||
CC.updateField(P)
|
||||
|
||||
while P.holdQueue[1]do rem(P.holdQueue)end
|
||||
TABLE.clear(P.holdQueue)
|
||||
P.holdTime=P.gameEnv.holdCount
|
||||
|
||||
P.cur=rem(P.nextQueue,1)
|
||||
P.curX,P.curY=blockPos[P.cur.id],int(P.gameEnv.fieldH+1-modf(P.cur.sc[1]))+ceil(P.fieldBeneath/30)
|
||||
|
||||
assert(resume(P.newNext))
|
||||
P.newNext()
|
||||
local id=CCblockID[P.nextQueue[P.AIdata.next].id]
|
||||
if id then
|
||||
CC.addNext(P.AI_bot,id)
|
||||
|
||||
56
parts/backgrounds/blockrain.lua
Normal file
@@ -0,0 +1,56 @@
|
||||
--Block rain
|
||||
local gc=love.graphics
|
||||
local rnd=math.random
|
||||
local ins,rem=table.insert,table.remove
|
||||
local back={}
|
||||
|
||||
local t
|
||||
local cell
|
||||
function back.init()
|
||||
t=0
|
||||
cell={}
|
||||
end
|
||||
function back.update()
|
||||
t=t+1
|
||||
if t%10==0 then
|
||||
ins(cell,{
|
||||
bid=rnd(29),
|
||||
x=SCR.w*rnd(),
|
||||
y=-25,
|
||||
a=rnd()*6.2832,
|
||||
vy=.5+rnd()*.4,
|
||||
vx=rnd()*.4-.2,
|
||||
va=rnd()*.04-.02,
|
||||
})
|
||||
end
|
||||
for i=#cell,1,-1 do
|
||||
local P=cell[i]
|
||||
P.y=P.y+P.vy
|
||||
if P.y>SCR.h+25 then
|
||||
rem(cell,i)
|
||||
else
|
||||
P.x=P.x+P.vx
|
||||
P.a=P.a+P.va
|
||||
P.vx=P.vx-.01+rnd()*.02
|
||||
end
|
||||
end
|
||||
end
|
||||
function back.draw()
|
||||
gc.clear(.15,.15,.15)
|
||||
gc.push("transform")
|
||||
gc.origin()
|
||||
local texture=TEXTURE.miniBlock
|
||||
local minoColor=minoColor
|
||||
for i=1,#cell do
|
||||
local C=cell[i]
|
||||
local tex=texture[C.bid]
|
||||
local c=minoColor[SETTING.skin[C.bid]]
|
||||
gc.setColor(c[1],c[2],c[3],.5)
|
||||
gc.draw(tex,C.x,C.y,C.a,10,10,tex:getWidth()/2,tex:getHeight()/2)
|
||||
end
|
||||
gc.pop()
|
||||
end
|
||||
function back.discard()
|
||||
cell=nil
|
||||
end
|
||||
return back
|
||||
@@ -271,10 +271,10 @@ end
|
||||
|
||||
--Royale mode
|
||||
function randomTarget(P)--Return a random opponent for P
|
||||
if #PLAYERS.alive>1 then
|
||||
if #PLY_ALIVE>1 then
|
||||
local R
|
||||
repeat
|
||||
R=PLAYERS.alive[rnd(#PLAYERS.alive)]
|
||||
R=PLY_ALIVE[rnd(#PLY_ALIVE)]
|
||||
until R~=P
|
||||
return R
|
||||
end
|
||||
@@ -282,28 +282,28 @@ end
|
||||
function freshMostDangerous()
|
||||
GAME.mostDangerous,GAME.secDangerous=false,false
|
||||
local m,m2=0,0
|
||||
for i=1,#PLAYERS.alive do
|
||||
local h=#PLAYERS.alive[i].field
|
||||
for i=1,#PLY_ALIVE do
|
||||
local h=#PLY_ALIVE[i].field
|
||||
if h>=m then
|
||||
GAME.mostDangerous,GAME.secDangerous=PLAYERS.alive[i],GAME.mostDangerous
|
||||
GAME.mostDangerous,GAME.secDangerous=PLY_ALIVE[i],GAME.mostDangerous
|
||||
m,m2=h,m
|
||||
elseif h>=m2 then
|
||||
GAME.secDangerous=PLAYERS.alive[i]
|
||||
GAME.secDangerous=PLY_ALIVE[i]
|
||||
m2=h
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,#PLAYERS.alive do
|
||||
if PLAYERS.alive[i].atkMode==3 then
|
||||
PLAYERS.alive[i]:freshTarget()
|
||||
for i=1,#PLY_ALIVE do
|
||||
if PLY_ALIVE[i].atkMode==3 then
|
||||
PLY_ALIVE[i]:freshTarget()
|
||||
end
|
||||
end
|
||||
end
|
||||
function freshMostBadge()
|
||||
GAME.mostBadge,GAME.secBadge=false,false
|
||||
local m,m2=0,0
|
||||
for i=1,#PLAYERS.alive do
|
||||
local P=PLAYERS.alive[i]
|
||||
for i=1,#PLY_ALIVE do
|
||||
local P=PLY_ALIVE[i]
|
||||
local b=P.badge
|
||||
if b>=m then
|
||||
GAME.mostBadge,GAME.secBadge=P,GAME.mostBadge
|
||||
@@ -314,44 +314,44 @@ function freshMostBadge()
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,#PLAYERS.alive do
|
||||
if PLAYERS.alive[i].atkMode==4 then
|
||||
PLAYERS.alive[i]:freshTarget()
|
||||
for i=1,#PLY_ALIVE do
|
||||
if PLY_ALIVE[i].atkMode==4 then
|
||||
PLY_ALIVE[i]:freshTarget()
|
||||
end
|
||||
end
|
||||
end
|
||||
function royaleLevelup()
|
||||
GAME.stage=GAME.stage+1
|
||||
local spd
|
||||
TEXT.show(text.royale_remain:gsub("$1",#PLAYERS.alive),640,200,40,"beat",.3)
|
||||
TEXT.show(text.royale_remain:gsub("$1",#PLY_ALIVE),640,200,40,"beat",.3)
|
||||
if GAME.stage==2 then
|
||||
spd=30
|
||||
elseif GAME.stage==3 then
|
||||
spd=15
|
||||
for _,P in next,PLAYERS.alive do
|
||||
for _,P in next,PLY_ALIVE do
|
||||
P.gameEnv.garbageSpeed=.6
|
||||
end
|
||||
if PLAYERS[1].alive then BGM.play("cruelty")end
|
||||
elseif GAME.stage==4 then
|
||||
spd=10
|
||||
for _,P in next,PLAYERS.alive do
|
||||
for _,P in next,PLY_ALIVE do
|
||||
P.gameEnv.pushSpeed=3
|
||||
end
|
||||
elseif GAME.stage==5 then
|
||||
spd=5
|
||||
for _,P in next,PLAYERS.alive do
|
||||
for _,P in next,PLY_ALIVE do
|
||||
P.gameEnv.garbageSpeed=1
|
||||
end
|
||||
elseif GAME.stage==6 then
|
||||
spd=3
|
||||
if PLAYERS[1].alive then BGM.play("final")end
|
||||
end
|
||||
for _,P in next,PLAYERS.alive do
|
||||
for _,P in next,PLY_ALIVE do
|
||||
P.gameEnv.drop=spd
|
||||
end
|
||||
if GAME.curMode.name:find("_u")then
|
||||
for i=1,#PLAYERS.alive do
|
||||
local P=PLAYERS.alive[i]
|
||||
for i=1,#PLY_ALIVE do
|
||||
local P=PLY_ALIVE[i]
|
||||
P.gameEnv.drop=int(P.gameEnv.drop*.3)
|
||||
if P.gameEnv.drop==0 then
|
||||
P.curY=P.ghoY
|
||||
@@ -537,9 +537,7 @@ function destroyPlayers()--Destroy all player objects, restore freerows and free
|
||||
end
|
||||
PLAYERS[i]=nil
|
||||
end
|
||||
for i=#PLAYERS.alive,1,-1 do
|
||||
PLAYERS.alive[i]=nil
|
||||
end
|
||||
TABLE.clear(PLY_ALIVE)
|
||||
collectgarbage()
|
||||
end
|
||||
function restoreVirtualkey()
|
||||
@@ -611,7 +609,7 @@ function loadGame(M,ifQuickPlay,ifNet)--Load a mode and go to game scene
|
||||
end
|
||||
end
|
||||
function initPlayerPosition(sudden)--Set initial position for every player
|
||||
local L=PLAYERS.alive
|
||||
local L=PLY_ALIVE
|
||||
if not sudden then
|
||||
for i=1,#L do
|
||||
L[i]:setPosition(640,#L<=5 and 360 or -62,0)
|
||||
@@ -715,7 +713,7 @@ do--function resetGameData(args)
|
||||
end
|
||||
return S
|
||||
end
|
||||
function resetGameData(args,playerData,seed)
|
||||
function resetGameData(args,seed)
|
||||
if not args then args=""end
|
||||
if PLAYERS[1]and not GAME.replaying and(GAME.frame>400 or GAME.result)then
|
||||
mergeStat(STAT,PLAYERS[1].stat)
|
||||
@@ -744,7 +742,7 @@ do--function resetGameData(args)
|
||||
end
|
||||
|
||||
destroyPlayers()
|
||||
GAME.curMode.load(playerData)
|
||||
GAME.curMode.load()
|
||||
initPlayerPosition(args:find("q"))
|
||||
restoreVirtualkey()
|
||||
if GAME.modeEnv.task then
|
||||
@@ -958,7 +956,7 @@ do--function saveRecording()
|
||||
os.date("%Y/%m/%d %A %H:%M:%S\n")..
|
||||
GAME.curModeName.."\n"..
|
||||
VERSION_NAME.."\n"..
|
||||
(USER.name or"Player")
|
||||
(USER.username or"Player")
|
||||
local fileBody=
|
||||
GAME.seed.."\n"..
|
||||
JSON.encode(GAME.setting).."\n"..
|
||||
@@ -982,25 +980,26 @@ end
|
||||
--Game draw
|
||||
do--function drawFWM()
|
||||
local m={
|
||||
"\230\184\184\230\136\143\228\189\156\232\128\133\58\77\114\90\95\50\54\10\228\187\187\228\189\149\232\167\134\233\162\145\47\231\155\180\230\146\173\228\184\141\229\190\151\229\135\186\231\142\176\230\173\164\230\176\180\229\141\176\10\228\187\187\228\189\149\232\189\172\232\191\176\229\163\176\230\152\142\230\151\160\230\149\136",
|
||||
"\230\184\184\230\136\143\228\189\156\232\128\133\58\77\114\90\95\50\54\10\228\187\187\228\189\149\232\167\134\233\162\145\47\231\155\180\230\146\173\228\184\141\229\190\151\229\135\186\231\142\176\230\173\164\230\176\180\229\141\176\10\228\187\187\228\189\149\232\189\172\232\191\176\229\163\176\230\152\142\230\151\160\230\149\136",
|
||||
"\230\184\184\230\136\143\228\189\156\232\128\133\58\77\114\90\95\50\54\10\228\187\187\228\189\149\232\167\134\233\162\145\47\231\155\180\230\146\173\228\184\141\229\190\151\229\135\186\231\142\176\230\173\164\230\176\180\229\141\176\10\228\187\187\228\189\149\232\189\172\232\191\176\229\163\176\230\152\142\230\151\160\230\149\136",
|
||||
"\65\117\116\104\111\114\58\32\77\114\90\95\50\54\n\82\101\99\111\114\100\105\110\103\115\32\99\111\110\116\97\105\110\105\110\103\32\116\104\105\115\n\119\97\116\101\114\109\97\114\107\32\97\114\101\32\117\110\97\117\116\104\111\114\105\122\101\100",
|
||||
"\67\114\195\169\97\116\101\117\114\32\100\117\32\106\101\117\58\32\77\114\90\95\50\54\10\69\110\114\101\103\105\115\116\114\101\109\101\110\116\32\110\111\110\32\97\117\116\111\114\105\115\195\169\10\99\111\110\116\101\110\97\110\116\32\99\101\32\102\105\108\105\103\114\97\110\101",
|
||||
"\65\117\116\111\114\58\32\77\114\90\95\50\54\10\71\114\97\98\97\99\105\195\179\110\32\110\111\32\97\117\116\111\114\105\122\97\100\97\32\113\117\101\10\99\111\110\116\105\101\110\101\32\101\115\116\97\32\109\97\114\99\97\32\100\101\32\97\103\117\97",
|
||||
"\65\117\116\111\114\32\100\111\32\106\111\103\111\58\32\77\114\90\95\50\54\10\71\114\97\118\97\195\167\195\181\101\115\32\99\111\110\116\101\110\100\111\32\101\115\116\97\32\77\97\114\99\97\10\100\101\32\195\161\103\117\97\32\110\195\163\111\32\115\195\163\111\32\97\117\116\111\114\105\122\97\100\97\115",
|
||||
"\65\117\116\104\111\114\58\32\77\114\90\95\50\54\10\82\101\99\111\114\100\105\110\103\115\32\99\111\110\116\97\105\110\105\110\103\32\116\104\105\115\10\119\97\116\101\114\109\97\114\107\32\97\114\101\32\117\110\97\117\116\104\111\114\105\122\101\100",
|
||||
string.char(230,184,184,230,136,143,228,189,156,232,128,133,58,77,114,90,95,50,54,10,228,187,187,228,189,149,232,167,134,233,162,145,47,231,155,180,230,146,173,228,184,141,229,190,151,229,135,186,231,142,176,230,173,164,230,176,180,229,141,176,10,228,187,187,228,189,149,232,189,172,232,191,176,229,163,176,230,152,142,230,151,160,230,149,136),
|
||||
string.char(230,184,184,230,136,143,228,189,156,232,128,133,58,77,114,90,95,50,54,10,228,187,187,228,189,149,232,167,134,233,162,145,47,231,155,180,230,146,173,228,184,141,229,190,151,229,135,186,231,142,176,230,173,164,230,176,180,229,141,176,10,228,187,187,228,189,149,232,189,172,232,191,176,229,163,176,230,152,142,230,151,160,230,149,136),
|
||||
string.char(230,184,184,230,136,143,228,189,156,232,128,133,58,77,114,90,95,50,54,10,228,187,187,228,189,149,232,167,134,233,162,145,47,231,155,180,230,146,173,228,184,141,229,190,151,229,135,186,231,142,176,230,173,164,230,176,180,229,141,176,10,228,187,187,228,189,149,232,189,172,232,191,176,229,163,176,230,152,142,230,151,160,230,149,136),
|
||||
string.char(65,117,116,104,111,114,58,32,77,114,90,95,50,54,10,82,101,99,111,114,100,105,110,103,115,32,99,111,110,116,97,105,110,105,110,103,32,116,104,105,115,10,119,97,116,101,114,109,97,114,107,32,97,114,101,32,117,110,97,117,116,104,111,114,105,122,101,100),
|
||||
string.char(67,114,195,169,97,116,101,117,114,32,100,117,32,106,101,117,58,32,77,114,90,95,50,54,10,69,110,114,101,103,105,115,116,114,101,109,101,110,116,32,110,111,110,32,97,117,116,111,114,105,115,195,169,10,99,111,110,116,101,110,97,110,116,32,99,101,32,102,105,108,105,103,114,97,110,101),
|
||||
string.char(65,117,116,111,114,58,32,77,114,90,95,50,54,10,71,114,97,98,97,99,105,195,179,110,32,110,111,32,97,117,116,111,114,105,122,97,100,97,32,113,117,101,10,99,111,110,116,105,101,110,101,32,101,115,116,97,32,109,97,114,99,97,32,100,101,32,97,103,117,97),
|
||||
string.char(65,117,116,111,114,32,100,111,32,106,111,103,111,58,32,77,114,90,95,50,54,10,71,114,97,118,97,195,167,195,181,101,115,32,99,111,110,116,101,110,100,111,32,101,115,116,97,32,77,97,114,99,97,10,100,101,32,195,161,103,117,97,32,110,195,163,111,32,115,195,163,111,32,97,117,116,111,114,105,122,97,100,97,115),
|
||||
string.char(65,117,116,104,111,114,58,32,77,114,90,95,50,54,10,82,101,99,111,114,100,105,110,103,115,32,99,111,110,116,97,105,110,105,110,103,32,116,104,105,115,10,119,97,116,101,114,109,97,114,107,32,97,114,101,32,117,110,97,117,116,104,111,114,105,122,101,100),
|
||||
}
|
||||
--你竟然找到了这里!那么在动手之前读读下面这些吧。
|
||||
--千万不要为了在网络公共场合发视 频或者直播需要而擅自删除这部分代码!
|
||||
--录制视 频上传到公共场合(包括但不限于任何视 频平台/论坛/几十个人以上的社区群等)很可能会对Techmino未来的发展有负面影响
|
||||
--【魔幻躲关键字搜索警告,看得懂就行】
|
||||
--千万不要为了在网络公共场合发视屏或者直播需要而擅自删除这部分代码!
|
||||
--录制视屏上传到公共场合(包括但不限于任何视屏平台/论坛/几十个人以上的社区群等)很可能会对Techmino未来的发展有负面影响
|
||||
--如果被TTC发现,TTC随时可以用DMCA从法律层面强迫停止开发,到时候谁都没得玩。这是真的,已经有几个方块这么死了…
|
||||
--水 印限制还可以减少低质量视 频泛滥,也能减轻过多不是真的感兴趣路人玩家入坑可能带来的压力
|
||||
--想发视 频的话请先向作者申请,描述录制的大致内容,同意了才可以去关闭水 印
|
||||
--氵印限制还可以减少低质量视屏泛滥,也能减轻过多不是真的感兴趣路人玩家入坑可能带来的压力
|
||||
--想发视屏的话请先向作者申请,描述录制的大致内容,同意了才可以去关闭氵印
|
||||
--等Techmino发展到一定程度之后会解除这个限制
|
||||
--最后,别把藏在这里的东西截图/复制出去哦~
|
||||
--感谢您对Techmino的支持!!!
|
||||
local setFont=setFont
|
||||
local setFont,TIME,mStr=setFont,TIME,mStr
|
||||
function drawFWM()
|
||||
local t=TIME()
|
||||
setFont(25)
|
||||
@@ -1051,221 +1050,12 @@ do--function pressKey(k)
|
||||
return cache[k]
|
||||
end
|
||||
end
|
||||
do--lnk_CUS/SETXXX(k)
|
||||
do--CUS/SETXXX(k)
|
||||
local c,s=CUSTOMENV,SETTING
|
||||
function lnk_CUSval(k)return function()return c[k] end end
|
||||
function lnk_SETval(k)return function()return s[k] end end
|
||||
function lnk_CUSrev(k)return function()c[k]=not c[k]end end
|
||||
function lnk_SETrev(k)return function()s[k]=not s[k]end end
|
||||
function lnk_CUSsto(k)return function(i)c[k]=i end end
|
||||
function lnk_SETsto(k)return function(i)s[k]=i end end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--Network funcs
|
||||
do
|
||||
--[[
|
||||
register:
|
||||
if response.message=="OK"then
|
||||
LOGIN=true
|
||||
USER.name=res.name
|
||||
USER.id=res.id
|
||||
USER.motto=res.motto
|
||||
USER.avatar=res.avatar
|
||||
FILE.save(USER,"conf/user","q")
|
||||
LOG.print(text.registerSuccessed..": "..res.message)
|
||||
else
|
||||
LOG.print(text.httpCode..response.code..": "..res.message,"warn")
|
||||
end
|
||||
|
||||
goChatRoom:
|
||||
if res.message=="OK"then
|
||||
SCN.go("net_chat")
|
||||
LOG.print(text.wsSuccessed,"warn")
|
||||
else
|
||||
LOG.print(text.wsFailed..": "..connErr,"warn")
|
||||
end
|
||||
|
||||
fetchRooms:
|
||||
if res.message=="OK"then
|
||||
rooms=res.room_list
|
||||
else
|
||||
LOG.print(text.httpCode..response.code..": "..res.message,"warn")
|
||||
end
|
||||
|
||||
createRoom:
|
||||
if res.message=="OK"then
|
||||
LOG.print(text.createRoomSuccessed)
|
||||
enterRoom(res.room.id)
|
||||
else
|
||||
LOG.print(text.httpCode..res.code..": "..res.message,"warn")
|
||||
end
|
||||
|
||||
enterRoom:
|
||||
if res.message=="OK"then
|
||||
loadGame("netBattle",true,true)
|
||||
LOG.print(text.wsSuccessed,"warn")
|
||||
else
|
||||
LOG.print(text.wsFailed..": "..connErr,"warn")
|
||||
end
|
||||
]]
|
||||
|
||||
function TICK_WS_app()
|
||||
local retryTime=5
|
||||
while true do
|
||||
YIELD()
|
||||
local status=WS.status("app")
|
||||
if status=="running"then
|
||||
local message,op=WS.read("app")
|
||||
if message then
|
||||
if op=="ping"then
|
||||
WS.send("app",message,"pong")
|
||||
elseif op=="close"then
|
||||
message=JSON.decode(message)
|
||||
if message then
|
||||
LOG.print(text.wsClose..message.message,"warn")
|
||||
end
|
||||
return
|
||||
else
|
||||
local res=JSON.decode(message)
|
||||
if VERSION_CODE>=res.lowest then
|
||||
NET.allow_online=true
|
||||
end
|
||||
if VERSION_CODE<res.newestCode then
|
||||
LOG.print(text.oldVersion:gsub("$1",res.newestName),180,COLOR.sky)
|
||||
end
|
||||
LOG.print(res.notice,300,COLOR.sky)
|
||||
end
|
||||
end
|
||||
elseif status=="dead"then
|
||||
retryTime=retryTime-1
|
||||
if retryTime==0 then return end
|
||||
for _=1,120 do YIELD()end
|
||||
WS.connect("app","/app")
|
||||
end
|
||||
end
|
||||
end
|
||||
function TICK_WS_user()
|
||||
while true do
|
||||
YIELD()
|
||||
local status=WS.status("user")
|
||||
if status=="running"then
|
||||
local message,op=WS.read("user")
|
||||
if message then
|
||||
if op=="ping"then
|
||||
WS.send("user",message,"pong")
|
||||
elseif op=="close"then
|
||||
message=JSON.decode(message)
|
||||
if message then
|
||||
LOG.print(text.wsClose..message.message,"warn")
|
||||
end
|
||||
return
|
||||
else
|
||||
local res=JSON.decode(message)
|
||||
if res.message=="Connected"then
|
||||
LOGIN=true
|
||||
if res.id then
|
||||
USER.id=res.id
|
||||
USER.authToken=res.authToken
|
||||
NET.try_enter_netmenu=true
|
||||
WS.send("user",JSON.encode{action=0})
|
||||
end
|
||||
FILE.save(USER,"conf/user","q")
|
||||
LOG.print(text.loginSuccessed)
|
||||
|
||||
--Get self infos
|
||||
WS.send("user",JSON.encode{
|
||||
action=1,
|
||||
data={
|
||||
id=USER.id,
|
||||
},
|
||||
})
|
||||
elseif res.action==0 then
|
||||
USER.accessToken=res.accessToken
|
||||
LOG.print(text.accessSuccessed)
|
||||
if NET.try_enter_netmenu then
|
||||
NET.try_enter_netmenu=false
|
||||
SCN.go("net_menu")
|
||||
end
|
||||
elseif res.action==1 then
|
||||
USER.name=res.username
|
||||
USER.motto=res.motto
|
||||
USER.avatar=res.avatar
|
||||
FILE.save(USER,"conf/user")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function TICK_WS_chat()
|
||||
while true do
|
||||
YIELD()
|
||||
local status=WS.status("chat")
|
||||
if status=="running"then
|
||||
local message,op=WS.read("chat")
|
||||
if message then
|
||||
if op=="ping"then
|
||||
WS.send("chat",message,"pong")
|
||||
elseif op=="close"then
|
||||
message=JSON.decode(message)
|
||||
if message then
|
||||
LOG.print(text.wsClose..message.message,"warn")
|
||||
end
|
||||
return
|
||||
else
|
||||
local res=JSON.decode(message)
|
||||
--TODO
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function TICK_WS_play()
|
||||
while true do
|
||||
YIELD()
|
||||
local status=WS.status("play")
|
||||
if status=="running"then
|
||||
local message,op=WS.read("play")
|
||||
if message then
|
||||
if op=="ping"then
|
||||
WS.send("play",message,"pong")
|
||||
elseif op=="close"then
|
||||
message=JSON.decode(message)
|
||||
if message then
|
||||
LOG.print(text.wsClose..message.message,"warn")
|
||||
end
|
||||
return
|
||||
else
|
||||
local res=JSON.decode(message)
|
||||
--TODO
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function TICK_WS_stream()
|
||||
while true do
|
||||
YIELD()
|
||||
local status=WS.status("stream")
|
||||
if status=="running"then
|
||||
local message,op=WS.read("stream")
|
||||
if message then
|
||||
if op=="ping"then
|
||||
WS.send("stream",message,"pong")
|
||||
elseif op=="close"then
|
||||
message=JSON.decode(message)
|
||||
if message then
|
||||
LOG.print(text.wsClose..message.message,"warn")
|
||||
end
|
||||
return
|
||||
else
|
||||
local res=JSON.decode(message)
|
||||
--TODO
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function CUSval(k)return function()return c[k]end end
|
||||
function SETval(k)return function()return s[k]end end
|
||||
function CUSrev(k)return function()c[k]=not c[k]end end
|
||||
function SETrev(k)return function()s[k]=not s[k]end end
|
||||
function CUSsto(k)return function(i)c[k]=i end end
|
||||
function SETsto(k)return function(i)s[k]=i end end
|
||||
end
|
||||
@@ -142,7 +142,9 @@ for i=1,#MODOPT do
|
||||
end
|
||||
|
||||
--Game tables
|
||||
PLAYERS={alive={}}--Players data
|
||||
PLAYERS={}--Players data
|
||||
PLY_ALIVE={}
|
||||
PLY_NET={}
|
||||
FIELD={}--Field(s) for custom game
|
||||
BAG={}--Sequence for custom game
|
||||
MISSION={}--Clearing mission for custom game
|
||||
@@ -220,17 +222,14 @@ GAME={--Global game data
|
||||
RANKS=FILE.load("conf/unlock")or{sprint_10l=0}--Ranks of modes
|
||||
USER=FILE.load("conf/user")or{--User infomation
|
||||
--Network infos
|
||||
name=false,
|
||||
id=false,
|
||||
email=false,
|
||||
motto=false,
|
||||
avatar=false,
|
||||
username=false,
|
||||
uid=false,
|
||||
authToken=false,
|
||||
accessToken=false,
|
||||
|
||||
--Local data
|
||||
xp=0,lv=1,
|
||||
}
|
||||
USERS=FILE.load("conf/users")or{}
|
||||
SETTING={--Settings
|
||||
--Tuning
|
||||
das=10,arr=2,dascut=0,
|
||||
@@ -300,7 +299,7 @@ SETTING={--Settings
|
||||
VKAlpha=.3,
|
||||
}
|
||||
local S=FILE.load("conf/settings")
|
||||
if S then TABLE.add(S,SETTING)end
|
||||
if S then TABLE.update(S,SETTING)end
|
||||
S=FILE.load("conf/data")
|
||||
if S then--Statistics
|
||||
STAT=S
|
||||
|
||||
@@ -75,7 +75,6 @@ return{
|
||||
needUpdate="Newer version required!",
|
||||
notFinished="Coming soon!",
|
||||
|
||||
httpCode="HTTP status code",
|
||||
jsonError="JSON error",
|
||||
|
||||
noUsername="Please specify a username.",
|
||||
@@ -90,10 +89,8 @@ return{
|
||||
accessFailed="Access Denied.",
|
||||
wsSuccessed="WebSocket: Connected.",
|
||||
wsFailed="WebSocket: Connection Failed.",
|
||||
wsDisconnected="WebSocket: Disconnected.",
|
||||
wsNoConn="WebSocket: Not Connected.",
|
||||
wsClose="WebSocket Closed: ",
|
||||
waitNetTask="Connecting. Please wait...",
|
||||
netTimeout="Network connection timeout",
|
||||
|
||||
createRoomTooFast="Hold on there! We can't handle this fast!",
|
||||
createRoomSuccessed="Room successfully created!",
|
||||
@@ -106,7 +103,6 @@ return{
|
||||
chatStart="------Beginning of log------",
|
||||
chatHistory="------New messages below------",
|
||||
|
||||
noRooms="Such emptiness much void, come back later?",
|
||||
roomsCreateFailed="Failed to create room.",
|
||||
roomsFetchFailed="Failed to fetch room list.",
|
||||
|
||||
@@ -252,7 +248,9 @@ return{
|
||||
chat="Chat",
|
||||
},
|
||||
net_rooms={
|
||||
fresh="Reresh",
|
||||
refreshing="Refreshing Rooms",
|
||||
noRoom="Such emptiness much void, come back later?",
|
||||
refresh="Refresh",
|
||||
new="New Room",
|
||||
join="Join",
|
||||
up="↑",
|
||||
|
||||
@@ -76,7 +76,6 @@ return{
|
||||
-- needUpdate="Newer version required!",
|
||||
-- notFinished="Coming soon!",
|
||||
|
||||
httpCode="Code de statut Http",
|
||||
jsonError="Erreur json",
|
||||
|
||||
noUsername="Entrez votre nom d'utilisateur",
|
||||
@@ -91,10 +90,8 @@ return{
|
||||
accessFailed="Autorisation échouée",
|
||||
wsSuccessed="WebSocket: connecté",
|
||||
wsFailed="WebSocket: connection échouée",
|
||||
wsDisconnected="WebSocket: déconnecté",
|
||||
wsNoConn="WebSocket: vous n'êtes pas connecté",
|
||||
wsError="Erreur WebSocket : ",
|
||||
waitNetTask="Connexion, veuillez patienter",
|
||||
-- wsClose="WebSocket Closed: ",
|
||||
-- netTimeout="Network connection timeout",
|
||||
|
||||
createRoomTooFast="Vous avez créé un salon trop rapidement !",
|
||||
createRoomSuccessed="Salon créé avec succès !",
|
||||
@@ -107,7 +104,6 @@ return{
|
||||
chatStart="--------Début des logs--------",
|
||||
chatHistory="-Nouveaux messages en dessous-",
|
||||
|
||||
noRooms="Aucun salon actuellement",
|
||||
roomsCreateFailed="Echec de la création du salon",
|
||||
roomsFetchFailed="Echec de la récupération des salons",
|
||||
|
||||
@@ -186,7 +182,7 @@ return{
|
||||
simple-love-lights [dylhunn]
|
||||
]],
|
||||
support="Aider le créateur",
|
||||
group="Groupe QQ officiel (si non piraté) : 913154753",
|
||||
group="Groupe QQ officiel : 913154753",
|
||||
WidgetText={
|
||||
main={
|
||||
-- offline="Solo",
|
||||
@@ -225,8 +221,9 @@ return{
|
||||
chat="Chat",
|
||||
},
|
||||
net_rooms={
|
||||
fresh="Fresh",
|
||||
new="Nouveau salon",
|
||||
-- refreshing="Refreshing Rooms",
|
||||
noRoom="Aucun salon actuellement",
|
||||
-- refresh="Refresh",
|
||||
join="Rejoindre",
|
||||
up="↑",
|
||||
down="↓",
|
||||
|
||||
@@ -75,7 +75,6 @@ return{
|
||||
-- needUpdate="Newer version required!",
|
||||
-- notFinished="Coming soon!",
|
||||
|
||||
-- httpCode="Http status code",
|
||||
jsonError="Json error",
|
||||
|
||||
noUsername="Insira seu nome de usuário",
|
||||
@@ -90,10 +89,8 @@ return{
|
||||
accessFailed="Falha na autorização",
|
||||
wsSuccessed="WebSocket: conectado",
|
||||
wsFailed="WebSocket: falha na conexão",
|
||||
wsDisconnected="WebSocket: desconectado",
|
||||
wsNoConn="WebSocket: você não está conectado",
|
||||
wsClose="WebSocket closed: ",
|
||||
waitNetTask="Conectando, aguarde",
|
||||
-- netTimeout="Network connection timeout",
|
||||
|
||||
-- createRoomTooFast="Create room too fast!",
|
||||
-- createRoomSuccessed="Room successfully created!",
|
||||
@@ -106,7 +103,6 @@ return{
|
||||
chatStart="------Começo do log------",
|
||||
chatHistory="------Novas mensagens abaixo------",
|
||||
|
||||
noRooms="Nenhuma sala agora",
|
||||
-- roomsCreateFailed="Failed to create room",
|
||||
roomsFetchFailed="Falha ao buscar salas",
|
||||
|
||||
@@ -252,7 +248,9 @@ return{
|
||||
chat="Chat",
|
||||
},
|
||||
net_rooms={
|
||||
fresh="Fresh",
|
||||
-- refreshing="Refreshing Rooms",
|
||||
noRoom="Nenhuma sala agora",
|
||||
-- refresh="Refresh",
|
||||
-- new="New room",
|
||||
-- join="Join",
|
||||
up="↑",
|
||||
|
||||
@@ -76,11 +76,9 @@ return{
|
||||
-- needUpdate="Newer version required!",
|
||||
-- notFinished="Coming soon!",
|
||||
|
||||
-- httpCode="Http status code",
|
||||
-- jsonError="Json error",
|
||||
|
||||
noUsername="Por favor ingresa un nombre de usuario",
|
||||
|
||||
-- wrongEmail="Wrong email address",
|
||||
noPassword="Por favor ingresa una contraseña",
|
||||
diffPassword="Las contraseñas no coinciden",
|
||||
@@ -92,10 +90,8 @@ return{
|
||||
-- accessFailed="Authorization failed",
|
||||
-- wsSuccessed="WebSocket: connected",
|
||||
-- wsFailed="WebSocket: connection failed",
|
||||
-- wsDisconnected="WebSocket: disconnected",
|
||||
-- wsNoConn="WebSocket: you are not connected",
|
||||
-- wsClose="WebSocket closed: ",
|
||||
-- waitNetTask="Connecting, please wait",
|
||||
-- netTimeout="Network connection timeout",
|
||||
|
||||
-- createRoomTooFast="Create room too fast!",
|
||||
-- createRoomSuccessed="Room successfully created!",
|
||||
@@ -108,7 +104,6 @@ return{
|
||||
-- chatStart="------Beginning of log------",
|
||||
-- chatHistory="------New messages below------",
|
||||
|
||||
-- noRooms="No Rooms Now",
|
||||
-- roomsCreateFailed="Failed to create room",
|
||||
-- roomsFetchFailed="Failed to fetch rooms",
|
||||
|
||||
@@ -188,7 +183,7 @@ return{
|
||||
simple-love-lights [dylhunn]
|
||||
]],
|
||||
support="Apoyen al Autor",
|
||||
group="Grupo Oficial de QQ (si no lo hackean) : 913154753",
|
||||
group="Grupo Oficial de QQ : 913154753",
|
||||
WidgetText={
|
||||
main={
|
||||
-- offline="Single",
|
||||
@@ -231,7 +226,9 @@ return{
|
||||
-- chat="Chat",
|
||||
},
|
||||
net_rooms={
|
||||
-- fresh="Fresh",
|
||||
-- refreshing="Refreshing Rooms",
|
||||
-- noRoom="No Rooms Now",
|
||||
-- refresh="Refresh",
|
||||
-- new="New room",
|
||||
-- join="Join",
|
||||
up="↑",
|
||||
|
||||
@@ -83,11 +83,12 @@ return{
|
||||
"□!!~~~,□□□□X",
|
||||
"□!!==*/*/*/*~",
|
||||
"",
|
||||
"bug reports/suggestions, sent to the author's testing group or email ~",
|
||||
"This is a free download available only through discord.gg/f9pUvkh",
|
||||
"The game downloaded from other sources may contain viruses,",
|
||||
"and only vibration & networking permissions are needed for mobile versions!",
|
||||
"The author is not responsible for any losses from modifying the game.",
|
||||
"Powered by LÖVE/love2d",
|
||||
"Any suggestions or bug reports are appreciated!",
|
||||
"Make sure to only obtain the game from official sources;",
|
||||
"We can't make sure you're safe if you got it elsewhere.",
|
||||
"The author is not responsible for any modified binaries.",
|
||||
"While the game is free, donations are appreciated."
|
||||
},
|
||||
WidgetText={
|
||||
main={
|
||||
|
||||
@@ -75,7 +75,6 @@ return{
|
||||
needUpdate="此功能需要更新游戏!",
|
||||
notFinished="暂未完成,敬请期待!",
|
||||
|
||||
httpCode="Http码",
|
||||
jsonError="json错误",
|
||||
|
||||
noUsername="请填写用户名",
|
||||
@@ -90,10 +89,8 @@ return{
|
||||
accessFailed="身份验证失败",
|
||||
wsSuccessed="WS连接成功",
|
||||
wsFailed="WS连接失败",
|
||||
wsDisconnected="WS连接断开",
|
||||
wsNoConn="WS未连接",
|
||||
wsClose="WS被断开: ",
|
||||
waitNetTask="正在连接,请稍候",
|
||||
netTimeout="网络连接超时",
|
||||
|
||||
createRoomTooFast="创建房间太快啦,等等吧",
|
||||
createRoomSuccessed="创建房间成功!",
|
||||
@@ -106,7 +103,6 @@ return{
|
||||
chatStart="------消息的开头------",
|
||||
chatHistory="------以上是历史消息------",
|
||||
|
||||
noRooms="一个房间都没有哎...",
|
||||
roomsCreateFailed="创建房间失败",
|
||||
roomsFetchFailed="拉取房间列表失败",
|
||||
|
||||
@@ -177,7 +173,7 @@ return{
|
||||
"",
|
||||
"使用LOVE2D引擎",
|
||||
"错误或者建议请附带截图发送到内测群或者作者邮箱~",
|
||||
"仅通过内测群1127702001进行免费下载/更新",
|
||||
"仅通过内测qq群/discord群进行免费下载/更新",
|
||||
"其他渠道获得游戏皆有被修改/加广告/植入病毒的风险,程序只申请了振动&联网权限!",
|
||||
"若由于被修改的本游戏产生的各种损失作者不负责(我怎么负责啊跟我有啥关系)",
|
||||
"请从正规途径获得最新版,游戏现为免费,不过有打赏当然感谢啦~",
|
||||
@@ -209,7 +205,7 @@ return{
|
||||
simple-love-lights [dylhunn]
|
||||
]],
|
||||
support="支持作者",
|
||||
group="官方QQ群(如果没有被暗改的话就是这个):913154753",
|
||||
group="官方QQ群:913154753",
|
||||
WidgetText={
|
||||
main={
|
||||
offline="单机游戏",
|
||||
@@ -252,7 +248,9 @@ return{
|
||||
chat="聊天室",
|
||||
},
|
||||
net_rooms={
|
||||
fresh="刷新",
|
||||
refreshing="刷新房间列表中",
|
||||
noRoom="一个房间都没有哎...",
|
||||
refresh="刷新",
|
||||
new="创建房间",
|
||||
join="加入",
|
||||
up="↑",
|
||||
|
||||
@@ -71,7 +71,7 @@ return{
|
||||
PLY.newAIPlayer(2,AIBUILDER("CC",2*AIlevel-1,math.floor(AIlevel*.5+1),true,20000+5000*AIlevel))
|
||||
end
|
||||
|
||||
for _,P in next,PLAYERS.alive do
|
||||
for _,P in next,PLY_ALIVE do
|
||||
setField(P,1)
|
||||
end
|
||||
end,
|
||||
|
||||
@@ -9,17 +9,15 @@ return{
|
||||
task=function(P)P.modeData.target=50 end,
|
||||
dropPiece=function(P)
|
||||
if P.stat.row>=P.modeData.target then
|
||||
local T=P.modeData.target
|
||||
if T==50 then
|
||||
if P.modeData.target==50 then
|
||||
P.gameEnv.drop=.25
|
||||
P.modeData.target=100
|
||||
SFX.play("reach")
|
||||
elseif T==100 then
|
||||
elseif P.modeData.target==100 then
|
||||
P:set20G(true)
|
||||
P.modeData.target=200
|
||||
SFX.play("reach")
|
||||
else
|
||||
P.stat.row=200
|
||||
P:win("finish")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,14 +8,15 @@ return{
|
||||
drop=60,wait=8,fall=20,
|
||||
task=function(P)P.modeData.target=10 end,
|
||||
dropPiece=function(P)
|
||||
local T=P.modeData.target
|
||||
if P.stat.row>=T then
|
||||
if T==200 then
|
||||
if P.stat.row<180 then
|
||||
P.stat.row=180
|
||||
end
|
||||
if P.stat.row>=P.modeData.target then
|
||||
if P.modeData.target==200 then
|
||||
P:win("finish")
|
||||
else
|
||||
T=T+10
|
||||
P.gameEnv.drop=dropSpeed[T/10]
|
||||
P.modeData.target=T
|
||||
P.gameEnv.drop=dropSpeed[P.modeData.target/10]
|
||||
P.modeData.target=P.modeData.target+10
|
||||
SFX.play("reach")
|
||||
end
|
||||
end
|
||||
@@ -31,7 +32,7 @@ return{
|
||||
mesDisp=function(P)
|
||||
setFont(45)
|
||||
mStr(P.stat.row,69,320)
|
||||
mStr(P.modeData.target+10,69,370)
|
||||
mStr(P.modeData.target,69,370)
|
||||
gc.rectangle("fill",25,375,90,4)
|
||||
end,
|
||||
score=function(P)return{math.min(P.stat.row,200),P.stat.time}end,
|
||||
|
||||
@@ -4,15 +4,16 @@ return{
|
||||
drop=30,
|
||||
freshLimit=15,
|
||||
noMod=true,
|
||||
bg="space",
|
||||
},
|
||||
load=function(playerData)
|
||||
load=function()
|
||||
PLY.newPlayer(1)
|
||||
local N=2
|
||||
for i=1,#playerData do
|
||||
if playerData[i].id==tostring(USER.id)then
|
||||
PLAYERS[1].subID=playerData[1].sid
|
||||
for i=1,#PLY_NET do
|
||||
if PLY_NET[i].uid==USER.uid then
|
||||
PLAYERS[1].subID=PLY_NET[1].sid
|
||||
else
|
||||
PLY.newRemotePlayer(N,false,playerData[i])
|
||||
PLY.newRemotePlayer(N,false,PLY_NET[i])
|
||||
N=N+1
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local function update_round(P)
|
||||
if #PLAYERS.alive>1 then
|
||||
if #PLY_ALIVE>1 then
|
||||
P.control=false
|
||||
local ID=P.id
|
||||
repeat
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local function update_round(P)
|
||||
if #PLAYERS.alive>1 then
|
||||
if #PLY_ALIVE>1 then
|
||||
P.control=false
|
||||
local ID=P.id
|
||||
repeat
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local function update_round(P)
|
||||
if #PLAYERS.alive>1 then
|
||||
if #PLY_ALIVE>1 then
|
||||
P.control=false
|
||||
local ID=P.id
|
||||
repeat
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local function update_round(P)
|
||||
if #PLAYERS.alive>1 then
|
||||
if #PLY_ALIVE>1 then
|
||||
P.control=false
|
||||
local ID=P.id
|
||||
repeat
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local function update_round(P)
|
||||
if #PLAYERS.alive>1 then
|
||||
if #PLY_ALIVE>1 then
|
||||
P.control=false
|
||||
local ID=P.id
|
||||
repeat
|
||||
|
||||
@@ -59,7 +59,7 @@ return{
|
||||
end,
|
||||
mesDisp=function(P)
|
||||
setFont(35)
|
||||
mStr(#PLAYERS.alive.."/49",69,175)
|
||||
mStr(#PLY_ALIVE.."/49",69,175)
|
||||
mStr(P.modeData.ko,80,215)
|
||||
gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222)
|
||||
setFont(20)
|
||||
|
||||
@@ -59,7 +59,7 @@ return{
|
||||
end,
|
||||
mesDisp=function(P)
|
||||
setFont(35)
|
||||
mStr(#PLAYERS.alive.."/49",69,175)
|
||||
mStr(#PLY_ALIVE.."/49",69,175)
|
||||
mStr(P.modeData.ko,80,215)
|
||||
gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222)
|
||||
setFont(20)
|
||||
|
||||
@@ -59,7 +59,7 @@ return{
|
||||
end,
|
||||
mesDisp=function(P)
|
||||
setFont(35)
|
||||
mStr(#PLAYERS.alive.."/49",69,175)
|
||||
mStr(#PLY_ALIVE.."/49",69,175)
|
||||
mStr(P.modeData.ko,80,215)
|
||||
gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222)
|
||||
setFont(20)
|
||||
|
||||
@@ -59,7 +59,7 @@ return{
|
||||
end,
|
||||
mesDisp=function(P)
|
||||
setFont(35)
|
||||
mStr(#PLAYERS.alive.."/99",69,175)
|
||||
mStr(#PLY_ALIVE.."/99",69,175)
|
||||
mStr(P.modeData.ko,80,215)
|
||||
gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222)
|
||||
setFont(20)
|
||||
|
||||
@@ -59,7 +59,7 @@ return{
|
||||
end,
|
||||
mesDisp=function(P)
|
||||
setFont(35)
|
||||
mStr(#PLAYERS.alive.."/99",69,175)
|
||||
mStr(#PLY_ALIVE.."/99",69,175)
|
||||
mStr(P.modeData.ko,80,215)
|
||||
gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222)
|
||||
setFont(20)
|
||||
|
||||
@@ -59,7 +59,7 @@ return{
|
||||
end,
|
||||
mesDisp=function(P)
|
||||
setFont(35)
|
||||
mStr(#PLAYERS.alive.."/99",69,175)
|
||||
mStr(#PLY_ALIVE.."/99",69,175)
|
||||
mStr(P.modeData.ko,80,215)
|
||||
gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222)
|
||||
setFont(20)
|
||||
|
||||
434
parts/net.lua
Normal file
@@ -0,0 +1,434 @@
|
||||
local data=love.data
|
||||
local ins,rem=table.insert,table.remove
|
||||
local NET={
|
||||
login=false,
|
||||
allow_online=false,
|
||||
roomList={},
|
||||
accessToken=false,
|
||||
rid=false,
|
||||
rsid=false,
|
||||
}
|
||||
|
||||
local mesType={
|
||||
Connect=true,
|
||||
Self=true,
|
||||
Broadcast=true,
|
||||
Private=true,
|
||||
Server=true,
|
||||
}
|
||||
|
||||
--Lock & Unlock submodule
|
||||
local locks={}
|
||||
local function _lock(name,T)
|
||||
if locks[name]and TIME()<locks[name]then
|
||||
return false
|
||||
else
|
||||
locks[name]=TIME()+(T or 1e99)
|
||||
return true
|
||||
end
|
||||
end
|
||||
local function _unlock(name)
|
||||
locks[name]=false
|
||||
end
|
||||
function NET.getLock(name)
|
||||
return locks[name]
|
||||
end
|
||||
|
||||
--Parse json message
|
||||
local function _parse(res)
|
||||
res=JSON.decode(res)
|
||||
if res then
|
||||
if mesType[res.type]then
|
||||
return res
|
||||
else
|
||||
LOG.print(
|
||||
"WS error:"..(
|
||||
res.type and(
|
||||
res.reason and res.type..": "..res.reason or
|
||||
res.type
|
||||
)or
|
||||
"[NO Message]"
|
||||
),
|
||||
"warning")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--wsEvent
|
||||
function NET.wsCloseMessage(message)
|
||||
local mes=JSON.decode(message)
|
||||
if mes then
|
||||
LOG.print(("%s [%s] %s"):format(text.wsClose,mes.type or"unknown type",mes.reason or""),"warn")
|
||||
else
|
||||
LOG.print(text.wsClose.."","warn")
|
||||
end
|
||||
end
|
||||
|
||||
--Account
|
||||
function NET.pong(wsName,message)
|
||||
WS.send(wsName,message,"pong")
|
||||
end
|
||||
function NET.getAccessToken()
|
||||
if _lock("accessToken")then
|
||||
WS.send("user",JSON.encode{action=0})
|
||||
end
|
||||
end
|
||||
function NET.getUserInfo(id,ifDetail)
|
||||
WS.send("user",JSON.encode{
|
||||
action=1,
|
||||
data={
|
||||
id=id or USER.uid,
|
||||
detailed=ifDetail or false,
|
||||
},
|
||||
})
|
||||
end
|
||||
function NET.storeUserInfo(res)
|
||||
local user=USERS[res.uid]
|
||||
if not user then
|
||||
user={}
|
||||
user.email=res.email
|
||||
user.name=res.username
|
||||
USERS[res.uid]=user
|
||||
else
|
||||
user.email=res.email
|
||||
user.name=res.username
|
||||
if not user.motto then user.motto=res.motto end
|
||||
if not user.avatar then user.avatar=res.avatar end
|
||||
end
|
||||
|
||||
--Get own name
|
||||
if res.uid==USER.uid then
|
||||
USER.username=res.username
|
||||
FILE.save(USER,"conf/user")
|
||||
end
|
||||
|
||||
-- FILE.save(USERS,"conf/users")
|
||||
end
|
||||
|
||||
--Room
|
||||
function NET.fetchRoom()
|
||||
if _lock("fetchRoom")then
|
||||
WS.send("play",JSON.encode{
|
||||
action=0,
|
||||
data={
|
||||
type=nil,
|
||||
begin=0,
|
||||
count=10,
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
function NET.createRoom()
|
||||
if _lock("enterRoom")then
|
||||
WS.send("play",JSON.encode{
|
||||
action=1,
|
||||
data={
|
||||
type="classic",
|
||||
name=(USER.username or"???").."'s room",
|
||||
password=nil,
|
||||
config=dumpBasicConfig(),
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
function NET.enterRoom(roomID,password)
|
||||
if _lock("enterRoom")then
|
||||
NET.rid=roomID
|
||||
WS.send("play",JSON.encode{
|
||||
action=2,
|
||||
data={
|
||||
rid=roomID,
|
||||
config=dumpBasicConfig(),
|
||||
password=password,
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
--Play
|
||||
function NET.wsConnectPlay()
|
||||
if _lock("connectPlay")then
|
||||
WS.connect("play","/play",JSON.encode{
|
||||
uid=USER.uid,
|
||||
accessToken=NET.accessToken,
|
||||
})
|
||||
end
|
||||
end
|
||||
function NET.signal_ready()
|
||||
if _lock("ready")then
|
||||
WS.send("play",'{"action":6,"data":{"ready":true}}')
|
||||
end
|
||||
end
|
||||
function NET.signal_quit()
|
||||
WS.send("play",'{"action":3}')
|
||||
end
|
||||
function NET.wsConnectStream()
|
||||
if _lock("connectStream")then
|
||||
WS.connect("stream","/stream",JSON.encode{
|
||||
uid=USER.uid,
|
||||
accessToken=NET.accessToken,
|
||||
rid=NET.rsid,
|
||||
})
|
||||
end
|
||||
end
|
||||
function NET.uploadRecStream(stream)
|
||||
WS.send("stream",'{"action":2,"data":{"stream":"'..data.encode("string","base64",stream)..'"}}')
|
||||
end
|
||||
function NET.signal_die()
|
||||
WS.send("stream",'{"action":3,"data":{"score":0,"survivalTime":0}}')
|
||||
end
|
||||
|
||||
--Chat
|
||||
function NET.sendChatMes(mes)
|
||||
WS.send("chat","T"..data.encode("string","base64",mes))
|
||||
end
|
||||
function NET.quitChat()
|
||||
WS.send("chat","Q")
|
||||
end
|
||||
|
||||
--WS tick funcs
|
||||
function NET.updateWS_app()
|
||||
local retryTime=5
|
||||
while true do
|
||||
YIELD()
|
||||
local status=WS.status("app")
|
||||
if status=="running"then
|
||||
local message,op=WS.read("app")
|
||||
if message then
|
||||
if op=="ping"then
|
||||
NET.pong("app",message)
|
||||
elseif op=="pong"then
|
||||
elseif op=="close"then
|
||||
NET.wsCloseMessage(message)
|
||||
return
|
||||
else
|
||||
local res=_parse(message)
|
||||
if res then
|
||||
if VERSION_CODE>=res.lowest then
|
||||
NET.allow_online=true
|
||||
end
|
||||
if VERSION_CODE<res.newestCode then
|
||||
LOG.print(text.oldVersion:gsub("$1",res.newestName),180,COLOR.sky)
|
||||
end
|
||||
LOG.print(res.notice,300,COLOR.sky)
|
||||
else
|
||||
WS.alert("app")
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif status=="dead"then
|
||||
retryTime=retryTime-1
|
||||
if retryTime==0 then return end
|
||||
for _=1,120 do YIELD()end
|
||||
WS.connect("app","/app")
|
||||
end
|
||||
end
|
||||
end
|
||||
function NET.updateWS_user()
|
||||
while true do
|
||||
YIELD()
|
||||
local status=WS.status("user")
|
||||
if status=="running"then
|
||||
local message,op=WS.read("user")
|
||||
if message then
|
||||
if op=="ping"then
|
||||
NET.pong("user",message)
|
||||
elseif op=="pong"then
|
||||
elseif op=="close"then
|
||||
NET.wsCloseMessage(message)
|
||||
return
|
||||
else
|
||||
local res=_parse(message)
|
||||
if res then
|
||||
if res.type=="Connect"then
|
||||
NET.login=true
|
||||
if res.uid then
|
||||
USER.uid=res.uid
|
||||
USER.authToken=res.authToken
|
||||
FILE.save(USER,"conf/user","q")
|
||||
SCN.back()
|
||||
end
|
||||
LOG.print(text.loginSuccessed)
|
||||
|
||||
--Get self infos
|
||||
NET.getUserInfo(USER.uid)
|
||||
elseif res.action==0 then--Get accessToken
|
||||
NET.accessToken=res.accessToken
|
||||
LOG.print(text.accessSuccessed)
|
||||
NET.wsConnectPlay()
|
||||
_unlock("accessToken")
|
||||
elseif res.action==1 then--Get userInfo
|
||||
NET.storeUserInfo(res)
|
||||
end
|
||||
else
|
||||
WS.alert("user")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function NET.updateWS_play()
|
||||
while true do
|
||||
YIELD()
|
||||
local status=WS.status("play")
|
||||
if status=="running"then
|
||||
local message,op=WS.read("play")
|
||||
if message then
|
||||
if op=="ping"then
|
||||
NET.pong("play",message)
|
||||
elseif op=="pong"then
|
||||
elseif op=="close"then
|
||||
NET.wsCloseMessage(message)
|
||||
return
|
||||
else
|
||||
local res=_parse(message)
|
||||
if res then
|
||||
if res.type=="Connect"then
|
||||
SCN.go("net_menu")
|
||||
_unlock("connectPlay")
|
||||
elseif res.action==0 then--Fetch rooms
|
||||
NET.roomList=res.roomList
|
||||
_unlock("fetchRoom")
|
||||
elseif res.action==1 then--Create room (not used)
|
||||
elseif res.action==2 then--Player join
|
||||
local d=res.data
|
||||
if res.type=="Self"then
|
||||
--Create room
|
||||
TABLE.clear(PLY_NET)
|
||||
ins(PLY_NET,{
|
||||
uid=USER.uid,
|
||||
username=USER.username,
|
||||
sid=d.sid,
|
||||
ready=d.ready,
|
||||
conf=dumpBasicConfig(),
|
||||
})
|
||||
if d.players then
|
||||
for _,p in next,d.players do
|
||||
ins(PLY_NET,{
|
||||
uid=p.uid,
|
||||
username=p.username,
|
||||
sid=p.sid,
|
||||
ready=p.ready,
|
||||
conf=p.config,
|
||||
})
|
||||
end
|
||||
end
|
||||
loadGame("netBattle",true,true)
|
||||
_unlock("enterRoom")
|
||||
else
|
||||
--Load other players
|
||||
ins(PLY_NET,{
|
||||
uid=d.uid,
|
||||
username=d.username,
|
||||
sid=d.sid,
|
||||
ready=d.ready,
|
||||
conf=d.config,
|
||||
})
|
||||
SCN.socketRead("Join",res.data)
|
||||
end
|
||||
elseif res.action==3 then--Player leave
|
||||
for i=1,#PLY_NET do
|
||||
if PLY_NET[i].uid==data.uid then
|
||||
rem(PLY_NET,i)
|
||||
break
|
||||
end
|
||||
end
|
||||
for i=1,#PLAYERS do
|
||||
if PLAYERS[i].userID==data.uid then
|
||||
rem(PLAYERS,i)
|
||||
break
|
||||
end
|
||||
end
|
||||
for i=1,#PLY_ALIVE do
|
||||
if PLY_ALIVE[i].userID==data.uid then
|
||||
rem(PLY_ALIVE,i)
|
||||
break
|
||||
end
|
||||
end
|
||||
SCN.socketRead("Leave",res.data)
|
||||
elseif res.action==4 then--Player talk
|
||||
SCN.socketRead("Talk",res.data)
|
||||
elseif res.action==5 then--Player change settings
|
||||
SCN.socketRead("Config",res.data)
|
||||
elseif res.action==6 then--Player ready
|
||||
SCN.socketRead("Ready",res.data)
|
||||
_unlock("ready")
|
||||
elseif res.action==7 then--All ready
|
||||
elseif res.action==8 then--Sure ready
|
||||
SCN.socketRead("Set",res.data)
|
||||
end
|
||||
else
|
||||
WS.alert("play")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function NET.updateWS_stream()
|
||||
while true do
|
||||
YIELD()
|
||||
local status=WS.status("stream")
|
||||
if status=="running"then
|
||||
local message,op=WS.read("stream")
|
||||
if message then
|
||||
if op=="ping"then
|
||||
NET.pong("stream",message)
|
||||
elseif op=="pong"then
|
||||
elseif op=="close"then
|
||||
NET.wsCloseMessage(message)
|
||||
return
|
||||
else
|
||||
local res=_parse(message)
|
||||
if res then
|
||||
if res.type=="Connect"then
|
||||
--?
|
||||
elseif res.action==0 then--Game start
|
||||
SCN.socketRead("Begin",res.data)
|
||||
elseif res.action==1 then--Game finished
|
||||
SCN.socketRead("Finish",res.data)
|
||||
elseif res.action==2 then--Player join
|
||||
--?
|
||||
elseif res.action==3 then--Player leave
|
||||
--?
|
||||
elseif res.action==4 then--Player died
|
||||
SCN.socketRead("Die",res.data)
|
||||
elseif res.action==5 then--Receive stream
|
||||
SCN.socketRead("Stream",res.data)
|
||||
end
|
||||
else
|
||||
WS.alert("stream")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function NET.updateWS_chat()
|
||||
while true do
|
||||
YIELD()
|
||||
local status=WS.status("chat")
|
||||
if status=="running"then
|
||||
local message,op=WS.read("chat")
|
||||
if message then
|
||||
if op=="ping"then
|
||||
NET.pong("chat",message)
|
||||
elseif op=="pong"then
|
||||
elseif op=="close"then
|
||||
NET.wsCloseMessage(message)
|
||||
return
|
||||
else
|
||||
local res=_parse(message)
|
||||
if res then
|
||||
--TODO
|
||||
else
|
||||
WS.alert("chat")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return NET
|
||||
@@ -75,7 +75,7 @@ end
|
||||
local function newEmptyPlayer(id,mini)
|
||||
local P={id=id}
|
||||
PLAYERS[id]=P
|
||||
PLAYERS.alive[id]=P
|
||||
PLY_ALIVE[id]=P
|
||||
|
||||
--Inherit functions of Player class
|
||||
for k,v in next,Player do P[k]=v end
|
||||
@@ -134,6 +134,9 @@ local function newEmptyPlayer(id,mini)
|
||||
P.atker,P.atking,P.lastRecv={}
|
||||
|
||||
--Network-related
|
||||
P.userName="_"
|
||||
P.userID=-1
|
||||
P.subID=-1
|
||||
P.ready=false
|
||||
|
||||
P.dropDelay,P.lockDelay=0,0
|
||||
@@ -178,7 +181,7 @@ local function newEmptyPlayer(id,mini)
|
||||
P.type="none"
|
||||
P.sound=false
|
||||
|
||||
-- P.newNext=false--Coroutine to get new next, loaded in applyGameEnv()
|
||||
-- P.newNext=false--Warped coroutine to get new next, loaded in applyGameEnv()
|
||||
|
||||
P.keyPressing={}for i=1,12 do P.keyPressing[i]=false end
|
||||
P.movDir,P.moving,P.downing=0,0,0--Last move key,DAS charging,downDAS charging
|
||||
@@ -312,8 +315,8 @@ local function applyGameEnv(P)--Finish gameEnv processing
|
||||
|
||||
if ENV.nextCount==0 then ENV.nextPos=false end
|
||||
|
||||
P.newNext=coroutine.create(getSeqGen(P))
|
||||
assert(coroutine.resume(P.newNext,P,P.gameEnv.seqData))
|
||||
P.newNext=coroutine.wrap(getSeqGen(P))
|
||||
P.newNext(P,P.gameEnv.seqData)
|
||||
|
||||
if P.mini then
|
||||
ENV.lockFX=false
|
||||
@@ -369,7 +372,7 @@ function PLY.newDemoPlayer(id)
|
||||
}
|
||||
P:popNext()
|
||||
end
|
||||
function PLY.newRemotePlayer(id,mini,playerData)
|
||||
function PLY.newRemotePlayer(id,mini,data)
|
||||
local P=newEmptyPlayer(id,mini)
|
||||
P.type="remote"
|
||||
P.update=PLY.update.remote_alive
|
||||
@@ -379,13 +382,13 @@ function PLY.newRemotePlayer(id,mini,playerData)
|
||||
P.stream={}
|
||||
P.streamProgress=1
|
||||
|
||||
playerData.p=P
|
||||
P.userName=playerData.name
|
||||
P.userID=playerData.id
|
||||
P.subID=playerData.sid
|
||||
P.ready=playerData.ready
|
||||
data.p=P
|
||||
P.userID=data.uid
|
||||
P.userName=data.username
|
||||
P.subID=data.sid
|
||||
P.ready=data.ready
|
||||
loadRemoteEnv(P,data.conf)
|
||||
|
||||
loadRemoteEnv(P,playerData.conf)
|
||||
applyGameEnv(P)
|
||||
end
|
||||
|
||||
@@ -405,6 +408,9 @@ function PLY.newPlayer(id,mini)
|
||||
P.type="human"
|
||||
P.sound=true
|
||||
|
||||
P.userID=USER.uid
|
||||
P.subID=-1
|
||||
|
||||
loadGameEnv(P)
|
||||
applyGameEnv(P)
|
||||
end
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
local max,min=math.max,math.min
|
||||
local int,abs,rnd=math.floor,math.abs,math.random
|
||||
local rem=table.remove
|
||||
local resume=coroutine.resume
|
||||
local status=coroutine.status
|
||||
local assert,resume,status=assert,coroutine.resume,coroutine.status
|
||||
|
||||
local function updateLine(P)--Attacks, line pushing, cam moving
|
||||
local bf=P.atkBuffer
|
||||
@@ -100,16 +99,13 @@ local function updateFXs(P,dt)
|
||||
TEXT.update(P.bonus)
|
||||
end
|
||||
end
|
||||
local updateTasks do--updateTasks(P)
|
||||
local assert=assert
|
||||
function updateTasks(P)
|
||||
local L=P.tasks
|
||||
for i=#L,1,-1 do
|
||||
local tr=L[i].thread
|
||||
assert(resume(tr))
|
||||
if status(tr)=="dead"then
|
||||
rem(L,i)
|
||||
end
|
||||
local function updateTasks(P)
|
||||
local L=P.tasks
|
||||
for i=#L,1,-1 do
|
||||
local tr=L[i].thread
|
||||
assert(resume(tr))
|
||||
if status(tr)=="dead"then
|
||||
rem(L,i)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -135,7 +131,7 @@ function update.alive(P,dt)
|
||||
end
|
||||
|
||||
if GAME.modeEnv.royaleMode then
|
||||
v=P.swappingAtkMode
|
||||
local v=P.swappingAtkMode
|
||||
if P.keyPressing[9]then
|
||||
P.swappingAtkMode=min(v+2,30)
|
||||
else
|
||||
@@ -150,8 +146,8 @@ function update.alive(P,dt)
|
||||
local C=P.AI_keys
|
||||
P.AI_delay=P.AI_delay-1
|
||||
if not C[1]then
|
||||
if status(P.AI_thread)=="suspended"then
|
||||
resume(P.AI_thread)
|
||||
if P.AI_thread and not pcall(P.AI_thread)then
|
||||
P.AI_thread=false
|
||||
end
|
||||
elseif P.AI_delay<=0 then
|
||||
P:pressKey(C[1])P:releaseKey(C[1])
|
||||
@@ -398,7 +394,7 @@ function update.remote_alive(P,dt)
|
||||
local amount=int(event/0x100)%0x100
|
||||
local time=int(event/0x10000)%0x10000
|
||||
local line=int(event/0x100000000)%0x10000
|
||||
local L=PLAYERS.alive
|
||||
local L=PLY_ALIVE
|
||||
for i=1,#L do
|
||||
if L[i].subID==sid then
|
||||
P:attack(L[i],amount,time,line,true)
|
||||
@@ -409,7 +405,7 @@ function update.remote_alive(P,dt)
|
||||
end
|
||||
end
|
||||
elseif event>0x1000000000000 then--Receiving lines
|
||||
local L=PLAYERS.alive
|
||||
local L=PLY_ALIVE
|
||||
local sid=tostring(event%0x100)
|
||||
for i=1,#L do
|
||||
if L[i].subID==sid then
|
||||
|
||||
@@ -52,6 +52,7 @@ local function reset()
|
||||
end end
|
||||
board[rnd(5)][rnd(5)]=2
|
||||
fallingTimer=false
|
||||
failPos=false
|
||||
end
|
||||
function scene.sceneInit()
|
||||
BG.set("rainbow2")
|
||||
@@ -76,7 +77,8 @@ local function merge()
|
||||
local connected={{cy,cx}}
|
||||
local count=1
|
||||
repeat
|
||||
local y,x=unpack(rem(connected))
|
||||
local c=rem(connected)
|
||||
local y,x=c[1],c[2]
|
||||
if board[y][x]~=0 then
|
||||
board[y][x]=0
|
||||
SYSFX.newShade(2,320+x*128-128,40+y*128-128,128,128)
|
||||
|
||||
@@ -149,14 +149,14 @@ scene.widgetList={
|
||||
WIDGET.newText{name="noMsn", x=610, y=550,align="L",color="grey",hide=function()return MISSION[1]end},
|
||||
|
||||
--Basic
|
||||
WIDGET.newSelector{name="drop", x=170, y=150,w=220,color="orange", list={0,.125,.25,.5,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99},disp=lnk_CUSval("drop"),code=lnk_CUSsto("drop")},
|
||||
WIDGET.newSelector{name="lock", x=170, y=230,w=220,color="red", list={0,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99}, disp=lnk_CUSval("lock"),code=lnk_CUSsto("lock")},
|
||||
WIDGET.newSelector{name="wait", x=410, y=150,w=220,color="green", list={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, disp=lnk_CUSval("wait"),code=lnk_CUSsto("wait")},
|
||||
WIDGET.newSelector{name="fall", x=410, y=230,w=220,color="yellow", list={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, disp=lnk_CUSval("fall"),code=lnk_CUSsto("fall")},
|
||||
WIDGET.newSelector{name="drop", x=170, y=150,w=220,color="orange", list={0,.125,.25,.5,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99},disp=CUSval("drop"),code=CUSsto("drop")},
|
||||
WIDGET.newSelector{name="lock", x=170, y=230,w=220,color="red", list={0,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99}, disp=CUSval("lock"),code=CUSsto("lock")},
|
||||
WIDGET.newSelector{name="wait", x=410, y=150,w=220,color="green", list={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, disp=CUSval("wait"),code=CUSsto("wait")},
|
||||
WIDGET.newSelector{name="fall", x=410, y=230,w=220,color="yellow", list={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, disp=CUSval("fall"),code=CUSsto("fall")},
|
||||
|
||||
--Else
|
||||
WIDGET.newSelector{name="bg", x=1070, y=150,w=250,color="yellow",list=BG.getList(),disp=lnk_CUSval("bg"), code=function(i)CUSTOMENV.bg=i BG.set(i)end},
|
||||
WIDGET.newSelector{name="bgm", x=1070, y=230,w=250,color="yellow", list=BGM.getList(), disp=lnk_CUSval("bgm"), code=function(i)CUSTOMENV.bgm=i BGM.play(i)end},
|
||||
WIDGET.newSelector{name="bg", x=1070, y=150,w=250,color="yellow",list=BG.getList(),disp=CUSval("bg"), code=function(i)CUSTOMENV.bg=i BG.set(i)end},
|
||||
WIDGET.newSelector{name="bgm", x=1070, y=230,w=250,color="yellow", list=BGM.getList(), disp=CUSval("bgm"), code=function(i)CUSTOMENV.bgm=i BGM.play(i)end},
|
||||
|
||||
--Copy/Paste/Start
|
||||
WIDGET.newButton{name="copy", x=1070, y=310,w=310,h=70,color="lRed", font=25,code=pressKey"cC"},
|
||||
|
||||
@@ -15,26 +15,26 @@ scene.widgetList={
|
||||
WIDGET.newText{name="subTitle", x=530,y=50,font=35,align="L",color="grey"},
|
||||
|
||||
--Control
|
||||
WIDGET.newSlider{name="nextCount", x=200, y=150, w=200,unit=6,disp=lnk_CUSval("nextCount"),code=lnk_CUSsto("nextCount")},
|
||||
WIDGET.newSlider{name="holdCount", x=200, y=240, w=200,unit=6,disp=lnk_CUSval("holdCount"),code=lnk_CUSsto("holdCount")},
|
||||
WIDGET.newSwitch{name="infHold", x=350, y=340, disp=lnk_CUSval("infHold"), code=lnk_CUSrev("infHold"),hide=function()return CUSTOMENV.holdCount==0 end},
|
||||
WIDGET.newSwitch{name="phyHold", x=350, y=430, disp=lnk_CUSval("phyHold"), code=lnk_CUSrev("phyHold"),hide=function()return CUSTOMENV.holdCount==0 end},
|
||||
WIDGET.newSlider{name="nextCount", x=200, y=150, w=200,unit=6,disp=CUSval("nextCount"),code=CUSsto("nextCount")},
|
||||
WIDGET.newSlider{name="holdCount", x=200, y=240, w=200,unit=6,disp=CUSval("holdCount"),code=CUSsto("holdCount")},
|
||||
WIDGET.newSwitch{name="infHold", x=350, y=340, disp=CUSval("infHold"), code=CUSrev("infHold"),hide=function()return CUSTOMENV.holdCount==0 end},
|
||||
WIDGET.newSwitch{name="phyHold", x=350, y=430, disp=CUSval("phyHold"), code=CUSrev("phyHold"),hide=function()return CUSTOMENV.holdCount==0 end},
|
||||
|
||||
--Rule
|
||||
WIDGET.newSelector{name="fieldH", x=270, y=520, w=260,color="sky", list=sList.fieldH, disp=lnk_CUSval("fieldH"),code=lnk_CUSsto("fieldH")},
|
||||
WIDGET.newSelector{name="visible", x=840, y=60, w=260,color="lBlue",list=sList.visible, disp=lnk_CUSval("visible"),code=lnk_CUSsto("visible")},
|
||||
WIDGET.newSelector{name="target", x=840, y=160, w=260,color="green",list=sList.target, disp=lnk_CUSval("target"),code=lnk_CUSsto("target")},
|
||||
WIDGET.newSelector{name="freshLimit",x=840, y=260, w=260,color="purple",list=sList.freshLimit, disp=lnk_CUSval("freshLimit"),code=lnk_CUSsto("freshLimit")},
|
||||
WIDGET.newSelector{name="opponent", x=1120, y=60, w=260,color="red", list=sList.opponent, disp=lnk_CUSval("opponent"),code=lnk_CUSsto("opponent")},
|
||||
WIDGET.newSelector{name="life", x=1120, y=160, w=260,color="red", list=sList.life, disp=lnk_CUSval("life"),code=lnk_CUSsto("life")},
|
||||
WIDGET.newSelector{name="pushSpeed",x=1120, y=260, w=260,color="red", list=sList.pushSpeed, disp=lnk_CUSval("pushSpeed"),code=lnk_CUSsto("pushSpeed")},
|
||||
WIDGET.newSelector{name="fieldH", x=270, y=520, w=260,color="sky", list=sList.fieldH, disp=CUSval("fieldH"),code=CUSsto("fieldH")},
|
||||
WIDGET.newSelector{name="visible", x=840, y=60, w=260,color="lBlue",list=sList.visible, disp=CUSval("visible"),code=CUSsto("visible")},
|
||||
WIDGET.newSelector{name="target", x=840, y=160, w=260,color="green",list=sList.target, disp=CUSval("target"),code=CUSsto("target")},
|
||||
WIDGET.newSelector{name="freshLimit",x=840, y=260, w=260,color="purple",list=sList.freshLimit, disp=CUSval("freshLimit"),code=CUSsto("freshLimit")},
|
||||
WIDGET.newSelector{name="opponent", x=1120, y=60, w=260,color="red", list=sList.opponent, disp=CUSval("opponent"),code=CUSsto("opponent")},
|
||||
WIDGET.newSelector{name="life", x=1120, y=160, w=260,color="red", list=sList.life, disp=CUSval("life"),code=CUSsto("life")},
|
||||
WIDGET.newSelector{name="pushSpeed",x=1120, y=260, w=260,color="red", list=sList.pushSpeed, disp=CUSval("pushSpeed"),code=CUSsto("pushSpeed")},
|
||||
|
||||
WIDGET.newSwitch{name="ospin", x=870, y=350, font=30,disp=lnk_CUSval("ospin"), code=lnk_CUSrev("ospin")},
|
||||
WIDGET.newSwitch{name="fineKill", x=870, y=530, font=20,disp=lnk_CUSval("fineKill"),code=lnk_CUSrev("fineKill")},
|
||||
WIDGET.newSwitch{name="b2bKill", x=870, y=620, font=20,disp=lnk_CUSval("b2bKill"), code=lnk_CUSrev("b2bKill")},
|
||||
WIDGET.newSwitch{name="easyFresh", x=1160, y=350, font=20,disp=lnk_CUSval("easyFresh"),code=lnk_CUSrev("easyFresh")},
|
||||
WIDGET.newSwitch{name="deepDrop", x=1160, y=440, font=30,disp=lnk_CUSval("deepDrop"),code=lnk_CUSrev("deepDrop")},
|
||||
WIDGET.newSwitch{name="bone", x=1160, y=530, disp=lnk_CUSval("bone"), code=lnk_CUSrev("bone")},
|
||||
WIDGET.newSwitch{name="ospin", x=870, y=350, font=30,disp=CUSval("ospin"), code=CUSrev("ospin")},
|
||||
WIDGET.newSwitch{name="fineKill", x=870, y=530, font=20,disp=CUSval("fineKill"),code=CUSrev("fineKill")},
|
||||
WIDGET.newSwitch{name="b2bKill", x=870, y=620, font=20,disp=CUSval("b2bKill"), code=CUSrev("b2bKill")},
|
||||
WIDGET.newSwitch{name="easyFresh", x=1160, y=350, font=20,disp=CUSval("easyFresh"),code=CUSrev("easyFresh")},
|
||||
WIDGET.newSwitch{name="deepDrop", x=1160, y=440, font=30,disp=CUSval("deepDrop"),code=CUSrev("deepDrop")},
|
||||
WIDGET.newSwitch{name="bone", x=1160, y=530, disp=CUSval("bone"), code=CUSrev("bone")},
|
||||
|
||||
WIDGET.newButton{name="back", x=1140, y=640, w=170,h=80, font=40,code=backScene},
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local gc,sys=love.graphics,love.system
|
||||
local ms,kb=love.mouse,love.keyboard
|
||||
local kb=love.keyboard
|
||||
|
||||
local max,min,int=math.max,math.min,math.floor
|
||||
local ins,rem=table.insert,table.remove
|
||||
@@ -9,7 +9,8 @@ local FIELD=FIELD
|
||||
local scene={}
|
||||
|
||||
local sure
|
||||
local pen--Pen type
|
||||
local penColor--Pen color
|
||||
local penMode--Pen mode (false=unavailable, else=mouse button)
|
||||
local penX,penY--Pen position
|
||||
local demo--If show x
|
||||
local page
|
||||
@@ -54,6 +55,7 @@ local minoPosCode={
|
||||
local SPmode
|
||||
local SPlist={}--Smart pen path list
|
||||
local function SPpath(x,y)
|
||||
if not penMode then return end
|
||||
for i=1,#SPlist do
|
||||
if x==SPlist[i][1]and y==SPlist[i][2]then
|
||||
return
|
||||
@@ -61,8 +63,7 @@ local function SPpath(x,y)
|
||||
end
|
||||
ins(SPlist,{x,y})
|
||||
if #SPlist==1 then
|
||||
local start=FIELD[page][y][x]
|
||||
SPmode=start==0 and 0 or 1
|
||||
SPmode=FIELD[page][y][x]==0 and 0 or 1
|
||||
end
|
||||
end
|
||||
local function SPdraw()
|
||||
@@ -98,99 +99,88 @@ local function SPdraw()
|
||||
end
|
||||
end
|
||||
SPlist={}
|
||||
SPmode=0
|
||||
end
|
||||
|
||||
function scene.sceneInit()
|
||||
sure=0
|
||||
pen=1
|
||||
penColor=1
|
||||
penMode=false
|
||||
penX,penY=1,1
|
||||
demo=false
|
||||
page=1
|
||||
love.keyboard.setKeyRepeat(false)
|
||||
end
|
||||
function scene.sceneBack()
|
||||
love.keyboard.setKeyRepeat(true)
|
||||
end
|
||||
|
||||
function scene.mouseMove(x,y)
|
||||
local sx,sy=int((x-200)/30)+1,20-int((y-60)/30)
|
||||
if sx<1 or sx>10 then sx=nil end
|
||||
if sy<1 or sy>20 then sy=nil end
|
||||
penX,penY=sx,sy
|
||||
if ms.isDown(1,2,3)then
|
||||
if sx and sy then
|
||||
if pen==-2 then
|
||||
if ms.isDown(1)then
|
||||
SPpath(sx,sy)
|
||||
else
|
||||
FIELD[page][sy][sx]=-1
|
||||
end
|
||||
if sx>=1 and sx<=10 and sy>=1 and sy<=20 then
|
||||
penX,penY=sx,sy
|
||||
if penMode then
|
||||
if penColor==-2 and penMode==1 then
|
||||
SPpath(sx,sy)
|
||||
else
|
||||
FIELD[page][sy][sx]=
|
||||
ms.isDown(1)and pen or
|
||||
ms.isDown(2)and -1
|
||||
or 0
|
||||
penMode==1 and penColor or
|
||||
penMode==2 and -1 or
|
||||
-- penMode==3 and 0
|
||||
0
|
||||
end
|
||||
end
|
||||
else
|
||||
penX,penY=nil
|
||||
end
|
||||
end
|
||||
function scene.mouseDown(x,y,k)
|
||||
if k==2 and pen==-2 then
|
||||
SPlist={}
|
||||
else
|
||||
scene.mouseMove(x,y)
|
||||
if not penMode then
|
||||
penMode=k
|
||||
elseif penMode~=k then
|
||||
penMode=false
|
||||
if penColor==-2 then
|
||||
SPlist={}
|
||||
end
|
||||
end
|
||||
end
|
||||
function scene.mouseUp()
|
||||
if pen==-2 then SPdraw()end
|
||||
end
|
||||
|
||||
function scene.wheelMoved(_,y)
|
||||
if y<0 then
|
||||
pen=pen+1
|
||||
if pen==25 then pen=1 end
|
||||
else
|
||||
pen=pen-1
|
||||
if pen==0 then pen=24 end
|
||||
end
|
||||
end
|
||||
function scene.touchDown(x,y)
|
||||
scene.mouseMove(x,y)
|
||||
end
|
||||
function scene.touchMove(x,y)
|
||||
local sx,sy=int((x-200)/30)+1,20-int((y-60)/30)
|
||||
if sx<1 or sx>10 then sx=nil end
|
||||
if sy<1 or sy>20 then sy=nil end
|
||||
penX,penY=sx,sy
|
||||
if sx and sy then
|
||||
if pen==-2 then
|
||||
SPpath(sx,sy)
|
||||
else
|
||||
FIELD[page][sy][sx]=pen
|
||||
function scene.mouseUp(_,_,k)
|
||||
if penMode==k then
|
||||
penMode=false
|
||||
if penColor==-2 then
|
||||
SPdraw()
|
||||
end
|
||||
end
|
||||
end
|
||||
scene.touchUp=scene.mouseUp
|
||||
|
||||
function scene.wheelMoved(_,y)
|
||||
if penColor>0 then
|
||||
penColor=(penColor+(y<0 and 1 or -1)-1)%24+1
|
||||
end
|
||||
end
|
||||
function scene.touchDown(x,y)scene.mouseDown(x,y,1)end
|
||||
function scene.touchMove(x,y)scene.mouseMove(x,y)end
|
||||
function scene.touchUp(x,y)scene.mouseUp(x,y,1)end
|
||||
|
||||
function scene.keyDown(key)
|
||||
local sx,sy=penX,penY
|
||||
if key=="up"or key=="down"or key=="left"or key=="right"then
|
||||
if not sx then sx=1 end
|
||||
if not sy then sy=1 end
|
||||
if key=="up"and sy<20 then sy=sy+1
|
||||
elseif key=="down"and sy>1 then sy=sy-1
|
||||
elseif key=="left"and sx>1 then sx=sx-1
|
||||
elseif key=="right"and sx<10 then sx=sx+1
|
||||
if not penX or not penY then penX,penY=1,1 end
|
||||
if key=="up"then
|
||||
if penY<20 then penY=penY+1 end
|
||||
elseif key=="down"then
|
||||
if penY>1 then penY=penY-1 end
|
||||
elseif key=="left"then
|
||||
if penX>1 then penX=penX-1 end
|
||||
elseif key=="right"then
|
||||
if penX<10 then penX=penX+1 end
|
||||
end
|
||||
if kb.isDown("space")then
|
||||
scene.keyDown("space")
|
||||
end
|
||||
elseif key=="space"then
|
||||
if sx and sy then
|
||||
if pen==-2 then
|
||||
SPpath(sx,sy)
|
||||
if penX and penY then
|
||||
penMode=1
|
||||
if penColor==-2 then
|
||||
SPpath(penX,penY)
|
||||
else
|
||||
FIELD[page][sy][sx]=pen
|
||||
FIELD[page][penY][penX]=penColor
|
||||
end
|
||||
end
|
||||
elseif key=="delete"then
|
||||
@@ -260,13 +250,15 @@ function scene.keyDown(key)
|
||||
elseif key=="escape"then
|
||||
SCN.back()
|
||||
else
|
||||
pen=penKey[key]or pen
|
||||
penColor=penKey[key]or penColor
|
||||
end
|
||||
penX,penY,pen=sx,sy,pen
|
||||
end
|
||||
function scene.keyUp(key)
|
||||
if key=="space"and pen==-2 then
|
||||
SPdraw()
|
||||
if key=="space"then
|
||||
if penColor==-2 then
|
||||
SPdraw()
|
||||
end
|
||||
penMode=false
|
||||
end
|
||||
end
|
||||
|
||||
@@ -303,20 +295,19 @@ function scene.draw()
|
||||
--Draw pen
|
||||
if penX and penY then
|
||||
local x,y=30*penX,600-30*penY
|
||||
if kb.isDown("space")or ms.isDown(1)then
|
||||
if penMode==1 or penMode==2 then
|
||||
gc.setLineWidth(5)
|
||||
gc.rectangle("line",x-30,y,30,30,4)
|
||||
elseif ms.isDown(3)then
|
||||
elseif penMode==3 then
|
||||
gc.setLineWidth(3)
|
||||
gc.line(x-15,y,x-30,y+15)
|
||||
gc.line(x,y,x-30,y+30)
|
||||
gc.line(x,y+15,x-15,y+30)
|
||||
else
|
||||
gc.setLineWidth(2)
|
||||
gc.rectangle("line",x-30,y,30,30,3)
|
||||
gc.setColor(1,1,1,.2)
|
||||
gc.rectangle("fill",x-30,y,30,30,3)
|
||||
end
|
||||
gc.setLineWidth(2)
|
||||
gc.rectangle("line",x-30,y,30,30,3)
|
||||
gc.setColor(1,1,1,.2)
|
||||
gc.rectangle("fill",x-30,y,30,30,3)
|
||||
end
|
||||
|
||||
--Draw smart pen path
|
||||
@@ -326,14 +317,15 @@ function scene.draw()
|
||||
if #SPlist<=5 then
|
||||
gc.setColor(COLOR.rainbow_light(TIME()*6.2))
|
||||
else
|
||||
gc.setColor(COLOR.grey)
|
||||
gc.setColor(.9,.9,.9,.7+.2*math.sin(TIME()*12.6))
|
||||
end
|
||||
for i=1,#SPlist do
|
||||
gc.rectangle("line",30*SPlist[i][1]-30+2,600-30*SPlist[i][2]+2,30-4,30-4,3)
|
||||
end
|
||||
elseif SPmode==1 then
|
||||
else
|
||||
gc.setColor(1,0,0)
|
||||
for i=1,#SPlist do
|
||||
gc.rectangle("line",30*SPlist[i][1]-30+2,600-30*SPlist[i][2]+2,30-4,30-4,3)
|
||||
gc.draw(cross,30*SPlist[i][1]-30+math.random(-1,1),600-30*SPlist[i][2]+math.random(-1,1))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -347,20 +339,38 @@ function scene.draw()
|
||||
gc.rectangle("fill",50,600,100,6)
|
||||
|
||||
--Draw pen color
|
||||
if pen>0 then
|
||||
gc.setLineWidth(13)
|
||||
gc.setColor(minoColor[pen])
|
||||
gc.rectangle("line",565,495,70,70)
|
||||
elseif pen==-1 then
|
||||
gc.setLineWidth(5)
|
||||
gc.setColor(.9,.9,.9)
|
||||
gc.line(575,505,625,555)
|
||||
gc.line(575,555,625,505)
|
||||
elseif pen==-2 then
|
||||
gc.setLineWidth(13)
|
||||
gc.setColor(COLOR.rainbow(TIME()*6.2))
|
||||
gc.rectangle("line",565,495,70,70)
|
||||
end
|
||||
gc.translate(560,475)
|
||||
--Right mouse button
|
||||
gc.setLineWidth(3)
|
||||
gc.setColor(1,1,1,.9)
|
||||
gc.line(52,5,75,35)
|
||||
gc.line(75,5,52,35)
|
||||
--Left mouse button
|
||||
if penColor>0 then
|
||||
gc.setColor(minoColor[penColor])
|
||||
gc.rectangle("fill",5,5,23,30)
|
||||
elseif penColor==-1 then
|
||||
gc.line(5,5,28,35)
|
||||
gc.line(28,5,5,35)
|
||||
elseif penColor==-2 then
|
||||
if SPmode==1 then
|
||||
gc.setColor(1,0,0)
|
||||
gc.line(5,5,28,35)
|
||||
gc.line(28,5,5,35)
|
||||
else
|
||||
gc.setLineWidth(13)
|
||||
gc.setColor(COLOR.rainbow(TIME()*12.6))
|
||||
gc.rectangle("fill",5,5,23,30)
|
||||
end
|
||||
end
|
||||
--Draw mouse
|
||||
gc.setLineWidth(2)
|
||||
gc.setColor(1,1,1)
|
||||
gc.rectangle("line",0,0,80,110,5)
|
||||
gc.line(0,40,80,40)
|
||||
gc.line(33,0,33,40)
|
||||
gc.line(47,0,47,40)
|
||||
gc.translate(-560,-475)
|
||||
|
||||
--Confirm reset
|
||||
if sure>0 then
|
||||
@@ -382,7 +392,7 @@ function scene.draw()
|
||||
end
|
||||
end
|
||||
|
||||
local function setPen(i)return function()pen=i end end
|
||||
local function setPen(i)return function()penColor=i end end
|
||||
scene.widgetList={
|
||||
WIDGET.newText{name="title", x=1020,y=5,font=70,align="R"},
|
||||
WIDGET.newText{name="subTitle", x=1030,y=50,font=35,align="L",color="grey"},
|
||||
|
||||
@@ -231,7 +231,7 @@ scene.widgetList={
|
||||
WIDGET.newKey{name="reset", x=1000, y=640, w=90, color="lYellow",font=50,code=pressKey"delete"},
|
||||
WIDGET.newButton{name="copy", x=1140, y=440, w=170,h=80, color="lRed", font=40,code=pressKey"cC",hide=function()return #MISSION==0 end},
|
||||
WIDGET.newButton{name="paste", x=1140, y=540, w=170,h=80, color="lBlue", font=40,code=pressKey"cV"},
|
||||
WIDGET.newSwitch{name="mission",x=1150, y=350, disp=lnk_CUSval("missionKill"),code=lnk_CUSrev("missionKill")},
|
||||
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},
|
||||
}
|
||||
|
||||
@@ -191,8 +191,8 @@ scene.widgetList={
|
||||
WIDGET.newSelector{name="sequence",
|
||||
x=1080,y=60,w=200,color="yellow",
|
||||
list={"bag","his4","c2","rnd","mess","reverb","loop","fixed"},
|
||||
disp=lnk_CUSval("sequence"),
|
||||
code=lnk_CUSsto("sequence")
|
||||
disp=CUSval("sequence"),
|
||||
code=CUSsto("sequence")
|
||||
},
|
||||
|
||||
WIDGET.newKey{name="Z", x=120,y=460,w=80,font=50,code=pressKey(1)},
|
||||
|
||||
@@ -36,7 +36,7 @@ function scene.sceneInit()
|
||||
end
|
||||
|
||||
local function clearResult()
|
||||
for _=1,#result do rem(result)end
|
||||
TABLE.clear(result)
|
||||
selected,scrollPos=1,0
|
||||
waiting,lastSearch=0,false
|
||||
end
|
||||
@@ -60,6 +60,9 @@ local function search()
|
||||
lastSearch=input
|
||||
end
|
||||
|
||||
function scene.wheelMoved(_,y)
|
||||
WHEELMOV(y)
|
||||
end
|
||||
function scene.keyDown(key)
|
||||
if key=="up"then
|
||||
if selected and selected>1 then
|
||||
@@ -75,6 +78,10 @@ function scene.keyDown(key)
|
||||
scrollPos=selected-15
|
||||
end
|
||||
end
|
||||
elseif key=="pageup"then
|
||||
for _=1,12 do scene.keyDown("up")end
|
||||
elseif key=="pagedown"then
|
||||
for _=1,12 do scene.keyDown("down")end
|
||||
elseif key=="link"then
|
||||
love.system.openURL(url)
|
||||
elseif key=="delete"then
|
||||
|
||||
@@ -36,7 +36,7 @@ local function upFloor()
|
||||
SFX.play("click",.3)
|
||||
end
|
||||
end
|
||||
local loadingThread=coroutine.create(function()
|
||||
local loadingThread=coroutine.wrap(function()
|
||||
for i=1,SFX.getCount()do
|
||||
SFX.loadOne()
|
||||
if i%3==0 then YIELD()end
|
||||
@@ -175,15 +175,15 @@ local loadingThread=coroutine.create(function()
|
||||
logoColor2={COLOR.rainbow_light(r)}
|
||||
end
|
||||
STAT.run=STAT.run+1
|
||||
LOADED=true
|
||||
|
||||
--Connect to server
|
||||
TASK.new(TICK_WS_app)
|
||||
TASK.new(TICK_WS_user)
|
||||
TASK.new(NET.updateWS_app)
|
||||
TASK.new(NET.updateWS_user)
|
||||
TASK.new(NET.updateWS_play)
|
||||
WS.connect("app","/app")
|
||||
if USER.authToken then
|
||||
WS.connect("user","/user",JSON.encode{
|
||||
id=USER.id,
|
||||
uid=USER.uid,
|
||||
authToken=USER.authToken,
|
||||
})
|
||||
end
|
||||
@@ -193,10 +193,10 @@ local loadingThread=coroutine.create(function()
|
||||
upFloor()
|
||||
end
|
||||
if progress==25 then
|
||||
loadingThread=false
|
||||
SFX.play("welcome_sfx")
|
||||
VOC.play("welcome_voc")
|
||||
THEME.fresh()
|
||||
LOADED=true
|
||||
return
|
||||
end
|
||||
YIELD()
|
||||
@@ -255,8 +255,8 @@ function scene.update(dt)
|
||||
if progress<25 then
|
||||
local p=progress
|
||||
repeat
|
||||
assert(coroutine.resume(loadingThread))
|
||||
until not loadingThread or skip<=0 or progress~=p
|
||||
loadingThread()
|
||||
until LOADED or skip<=0 or progress~=p
|
||||
if skip>0 then skip=skip-1 end
|
||||
else
|
||||
openTime=openTime+dt
|
||||
|
||||
@@ -6,7 +6,6 @@ local function login()
|
||||
elseif #password==0 then
|
||||
LOG.print(text.noPassword)return
|
||||
end
|
||||
USER.email=email
|
||||
WS.connect("user","/user",JSON.encode{
|
||||
email=email,
|
||||
password=password,
|
||||
|
||||
@@ -12,15 +12,13 @@ local widgetX0={
|
||||
1290,1290,1290,1290,
|
||||
}
|
||||
|
||||
local cmdEntryThread=coroutine.create(function()
|
||||
local cmdEntryThread=coroutine.wrap(function()
|
||||
while true do
|
||||
while true do
|
||||
if YIELD()~="c"then break end
|
||||
SFX.play("ren_6")
|
||||
if YIELD()~="m"then break end
|
||||
SFX.play("ren_9")
|
||||
if YIELD()~="d"then break end
|
||||
SFX.play("ren_11")
|
||||
if
|
||||
YIELD()=="c"and(SFX.play("ren_6")or 1)and
|
||||
YIELD()=="m"and(SFX.play("ren_9")or 1)and
|
||||
YIELD()=="d"and(SFX.play("ren_11")or 1)
|
||||
then
|
||||
SCN.go("app_cmd")
|
||||
end
|
||||
end
|
||||
@@ -30,7 +28,7 @@ function scene.sceneInit()
|
||||
scrollX=tipLength
|
||||
|
||||
BG.set()
|
||||
coroutine.resume(cmdEntryThread)
|
||||
cmdEntryThread()
|
||||
|
||||
--Set quick-play-button text
|
||||
scene.widgetList[2].text=text.WidgetText.main.qplay..": "..text.modes[STAT.lastPlay][1]
|
||||
@@ -43,15 +41,11 @@ function scene.sceneInit()
|
||||
GAME.seed=math.random(2e6)
|
||||
PLY.newDemoPlayer(1)
|
||||
PLAYERS[1]:setPosition(520,140,.8)
|
||||
love.keyboard.setKeyRepeat(false)
|
||||
end
|
||||
function scene.sceneBack()
|
||||
love.keyboard.setKeyRepeat(true)
|
||||
end
|
||||
|
||||
function scene.mouseDown(x,y)
|
||||
if x>=520 and x<=760 and y>=140 and y<=620 then
|
||||
coroutine.resume(cmdEntryThread,
|
||||
cmdEntryThread(
|
||||
x<520+80 and y>620-80 and"c"or
|
||||
x>760-80 and y>620-80 and"m"or
|
||||
x<520+80 and y<140+80 and"d"
|
||||
@@ -77,12 +71,12 @@ function scene.keyDown(key)
|
||||
end
|
||||
elseif key=="a"then
|
||||
if testButton(3)then
|
||||
if LOGIN then
|
||||
if NET.login then
|
||||
if not NET.allow_online then
|
||||
TEXT.show(text.needUpdate,640,450,60,"flicker")
|
||||
SFX.play("finesseError")
|
||||
else
|
||||
WS.send("user",JSON.encode{action=0})
|
||||
NET.getAccessToken()
|
||||
end
|
||||
else
|
||||
SCN.go("login")
|
||||
@@ -125,7 +119,7 @@ function scene.keyDown(key)
|
||||
SCN.back()
|
||||
end
|
||||
else
|
||||
coroutine.resume(cmdEntryThread,key)
|
||||
cmdEntryThread(key)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -183,9 +177,9 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="dict", x=2480,y=450,w=800,h=100, color="lGreen", 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="lOrange",font=35, code=pressKey"f2"},
|
||||
WIDGET.newButton{name="lang", x=1120,y=80,w=200,h=90, color="lY", font=40, code=pressKey"f3"},
|
||||
WIDGET.newButton{name="about", x=-110,y=670,w=600,h=70, color="lB", font=35,align="R",edge=30, code=pressKey"f1"},
|
||||
WIDGET.newButton{name="music", x=160,y=80,w=200,h=90, color="lOrange",font=35, code=pressKey"2"},
|
||||
WIDGET.newButton{name="lang", x=1120,y=80,w=200,h=90, color="lY", font=40, code=pressKey"0"},
|
||||
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},
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ scene.widgetList={
|
||||
WIDGET.newText{name="title", x=30, y=30,font=80,align="L"},
|
||||
WIDGET.newText{name="arrow", x=270, y=360,font=45,align="L"},
|
||||
WIDGET.newText{name="now", x=700, y=500,font=50,align="R",hide=function()return not BGM.nowPlay end},
|
||||
WIDGET.newSlider{name="bgm", x=760, y=80,w=400, font=35,disp=lnk_SETval("bgm"),code=function(v)SETTING.bgm=v BGM.freshVolume()end},
|
||||
WIDGET.newSlider{name="bgm", x=760, y=80,w=400, font=35,disp=SETval("bgm"),code=function(v)SETTING.bgm=v BGM.freshVolume()end},
|
||||
WIDGET.newButton{name="up", x=200, y=250,w=120, font=55,code=pressKey"up",hide=function()return selected==1 end},
|
||||
WIDGET.newButton{name="play", x=200, y=390,w=120, font=35,code=pressKey"space"},
|
||||
WIDGET.newButton{name="down", x=200, y=530,w=120, font=55,code=pressKey"down",hide=function()return selected==#bgmList end},
|
||||
|
||||
@@ -3,12 +3,12 @@ local data=love.data
|
||||
|
||||
local textBox=WIDGET.newTextBox{name="texts",x=40,y=50,w=1200,h=430}
|
||||
local remain--People in chat room
|
||||
local heartBeatTimer
|
||||
local escapeTimer=0
|
||||
|
||||
local function sendMessage()
|
||||
local W=WIDGET.active.input
|
||||
if #W.value>0 and WS.send("chat","T"..data.encode("string","base64",W.value))then
|
||||
if #W.value>0 then
|
||||
NET.sendChatMes(W.value)
|
||||
W.value=""
|
||||
end
|
||||
end
|
||||
@@ -16,7 +16,6 @@ end
|
||||
local scene={}
|
||||
|
||||
function scene.sceneInit()
|
||||
heartBeatTimer=0
|
||||
remain=false
|
||||
|
||||
local texts=textBox.texts
|
||||
@@ -30,8 +29,7 @@ function scene.sceneInit()
|
||||
BG.set("none")
|
||||
end
|
||||
function scene.sceneBack()
|
||||
WS.send("chat","Q")
|
||||
LOG.print(text.wsDisconnected,"warn")
|
||||
NET.quitChat()
|
||||
end
|
||||
|
||||
function scene.wheelMoved(_,y)
|
||||
@@ -80,13 +78,6 @@ function scene.socketRead(mes)
|
||||
end
|
||||
end
|
||||
|
||||
function scene.update(dt)
|
||||
heartBeatTimer=heartBeatTimer+dt
|
||||
if heartBeatTimer>42 then
|
||||
heartBeatTimer=0
|
||||
WS.send("chat","P")
|
||||
end
|
||||
end
|
||||
function scene.draw()
|
||||
setFont(25)
|
||||
gc.setColor(1,1,1)
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
local data=love.data
|
||||
local gc=love.graphics
|
||||
local tc=love.touch
|
||||
|
||||
local playerData
|
||||
local ins,rem=table.insert,table.remove
|
||||
local ins=table.insert
|
||||
|
||||
local SCR=SCR
|
||||
local VK=virtualkey
|
||||
@@ -13,14 +11,8 @@ local updateVirtualkey=updateVirtualkey
|
||||
|
||||
local hideChatBox
|
||||
local textBox=WIDGET.newTextBox{name="texts",x=340,y=80,w=600,h=550,hide=function()return hideChatBox end}
|
||||
local function switchChat()
|
||||
hideChatBox=not hideChatBox
|
||||
end
|
||||
|
||||
|
||||
local playerInitialized
|
||||
local playing
|
||||
local heartBeatTimer
|
||||
local lastUpstreamTime
|
||||
local upstreamProgress
|
||||
local lastBackTime=0
|
||||
@@ -30,23 +22,19 @@ local touchMoveLastFrame=false
|
||||
local scene={}
|
||||
|
||||
function scene.sceneBack()
|
||||
WS.send("play","Q")
|
||||
LOG.print(text.wsDisconnected,"warn")
|
||||
NET.signal_quit()
|
||||
love.keyboard.setKeyRepeat(true)
|
||||
end
|
||||
function scene.sceneInit()
|
||||
love.keyboard.setKeyRepeat(false)
|
||||
hideChatBox=true
|
||||
playerInitialized=false
|
||||
textBox:clear()
|
||||
|
||||
playerData={}
|
||||
resetGameData("n",playerData)
|
||||
resetGameData("n")
|
||||
noTouch=not SETTING.VKSwitch
|
||||
playing=false
|
||||
lastUpstreamTime=0
|
||||
upstreamProgress=1
|
||||
heartBeatTimer=0
|
||||
end
|
||||
|
||||
function scene.touchDown(x,y)
|
||||
@@ -96,7 +84,7 @@ function scene.keyDown(key)
|
||||
LOG.print(text.sureQuit,COLOR.orange)
|
||||
end
|
||||
elseif key=="\\"then
|
||||
switchChat()
|
||||
hideChatBox=not hideChatBox
|
||||
elseif playing then
|
||||
if noKey then return end
|
||||
local k=keyMap.keyboard[key]
|
||||
@@ -106,8 +94,8 @@ function scene.keyDown(key)
|
||||
VK[k].pressTime=10
|
||||
end
|
||||
elseif key=="space"then
|
||||
if not PLAYERS[1].ready then
|
||||
WS.send("play","R")
|
||||
if not NET.getLock("ready")then
|
||||
NET.signal_ready()
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -147,77 +135,85 @@ function scene.gamepadUp(key)
|
||||
end
|
||||
end
|
||||
|
||||
function scene.socketRead(mes)
|
||||
local cmd=mes:sub(1,1)
|
||||
local args=SPLITSTR(mes:sub(2),";")
|
||||
if cmd=="J"then
|
||||
if playerInitialized then
|
||||
local L=SPLITSTR(args[1],",")
|
||||
textBox:push{
|
||||
COLOR.lR,L[1],
|
||||
COLOR.dY,"#"..L[2].." ",
|
||||
COLOR.Y,text.joinRoom,
|
||||
}
|
||||
end
|
||||
for i=1,#args do
|
||||
local L=SPLITSTR(args[i],",")
|
||||
ins(playerData,{name=L[1],id=L[2],sid=L[3],conf=L[4],ready=L[5]=="1"})
|
||||
end
|
||||
playerInitialized=true
|
||||
function scene.socketRead(cmd,data)
|
||||
if cmd=="Join"then
|
||||
textBox:push{
|
||||
COLOR.lR,data.username,
|
||||
COLOR.dY,"#"..data.uid.." ",
|
||||
COLOR.Y,text.joinRoom,
|
||||
}
|
||||
SFX.play("click")
|
||||
if not playing then
|
||||
resetGameData("qn",playerData)
|
||||
resetGameData("qn")
|
||||
end
|
||||
elseif cmd=="L"then
|
||||
elseif cmd=="Leave"then
|
||||
textBox:push{
|
||||
COLOR.lR,args[1],
|
||||
COLOR.dY,"#"..args[2].." ",
|
||||
COLOR.lR,data.username,
|
||||
COLOR.dY,"#"..data.uid.." ",
|
||||
COLOR.Y,text.leaveRoom,
|
||||
}
|
||||
for i=1,#playerData do
|
||||
if playerData[i].id==args[2]then
|
||||
rem(playerData,i)
|
||||
break
|
||||
end
|
||||
if not playing then
|
||||
initPlayerPosition(true)
|
||||
end
|
||||
for i=1,#PLAYERS do
|
||||
if PLAYERS[i].userID==args[2]then
|
||||
rem(PLAYERS,i)
|
||||
break
|
||||
end
|
||||
end
|
||||
for i=1,#PLAYERS.alive do
|
||||
if PLAYERS.alive[i].userID==args[2]then
|
||||
rem(PLAYERS.alive,i)
|
||||
break
|
||||
end
|
||||
end
|
||||
initPlayerPosition(true)
|
||||
elseif cmd=="T"then
|
||||
local _,text=pcall(data.decode,"string","base64",args[3])
|
||||
if not _ then text=args[3]end
|
||||
elseif cmd=="Talk"then
|
||||
textBox:push{
|
||||
COLOR.W,args[1],
|
||||
COLOR.dY,"#"..args[2].." ",
|
||||
COLOR.sky,text
|
||||
COLOR.W,data.username,
|
||||
COLOR.dY,"#"..data.uid.." ",
|
||||
COLOR.sky,data.message or"[_]",
|
||||
}
|
||||
elseif cmd=="C"then
|
||||
if tostring(USER.id)~=args[2]then
|
||||
for i=1,#playerData do
|
||||
if playerData[i].id==args[2]then
|
||||
playerData[i].conf=args[4]
|
||||
playerData[i].p:setConf(args[4])
|
||||
elseif cmd=="Config"then
|
||||
if tostring(USER.uid)~=data.uid then
|
||||
for i=1,#PLY_NET do
|
||||
if PLY_NET[i].uid==data.uid then
|
||||
PLY_NET[i].conf=data.config
|
||||
PLY_NET[i].p:setConf(data.config)
|
||||
return
|
||||
end
|
||||
end
|
||||
resetGameData("qn",playerData)
|
||||
resetGameData("qn")
|
||||
end
|
||||
elseif cmd=="S"then
|
||||
if playing and args[1]~=PLAYERS[1].subID then
|
||||
elseif cmd=="Ready"then
|
||||
if data.uid==USER.uid then
|
||||
PLAYERS[1].ready=true
|
||||
SFX.play("reach",.6)
|
||||
else
|
||||
for i=1,#PLAYERS do
|
||||
if PLAYERS[i].userID==data.uid then
|
||||
PLAYERS[i].ready=true
|
||||
SFX.play("reach",.6)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif cmd=="Set"then
|
||||
NET.rsid=data.rid
|
||||
NET.wsConnectStream()
|
||||
TASK.new(NET.updateWS_stream)
|
||||
elseif cmd=="Begin"then
|
||||
if not playing then
|
||||
playing=true
|
||||
lastUpstreamTime=0
|
||||
upstreamProgress=1
|
||||
resetGameData("n",data.seed)
|
||||
else
|
||||
LOG.print("Redundant signal: B(begin)",30,COLOR.green)
|
||||
end
|
||||
elseif cmd=="Finish"then
|
||||
playing=false
|
||||
resetGameData("n")
|
||||
TEXT.show(text.champion:gsub("$1","SOMEBODY"),640,260,80,"zoomout",.26)
|
||||
elseif cmd=="Die"then
|
||||
LOG.print("One player failed",COLOR.sky)
|
||||
elseif cmd=="Stream"then
|
||||
if data.uid==USER.uid then
|
||||
LOG.print("SELF STREAM")
|
||||
return
|
||||
end
|
||||
if playing then
|
||||
for _,P in next,PLAYERS do
|
||||
if P.subID==args[1]then
|
||||
local _,stream=pcall(data.decode,"string","base64",args[2])
|
||||
if _ then
|
||||
if P.userID==data.uid then
|
||||
local res,stream=pcall(love.data.decode,"string","base64",data.stream)
|
||||
if res then
|
||||
pumpRecording(stream,P.stream)
|
||||
else
|
||||
LOG.print("Bad stream from "..P.userName.."#"..P.userID)
|
||||
@@ -225,35 +221,6 @@ function scene.socketRead(mes)
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif cmd=="R"then
|
||||
local L=PLAYERS.alive
|
||||
for i=1,#L do
|
||||
if L[i].subID==args[1]then
|
||||
L[i].ready=true
|
||||
SFX.play("reach",.6)
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif cmd=="B"then
|
||||
if not playing then
|
||||
playing=true
|
||||
lastUpstreamTime=0
|
||||
upstreamProgress=1
|
||||
resetGameData("n",playerData,tonumber(args[1]))
|
||||
else
|
||||
LOG.print("Redundant signal: B(begin)",30,COLOR.green)
|
||||
end
|
||||
elseif cmd=="F"then
|
||||
playing=false
|
||||
resetGameData("n",playerData)
|
||||
for i=1,#playerData do
|
||||
if playerData[i].sid==args[1]then
|
||||
TEXT.show(text.champion:gsub("$1",playerData[i].name.."#"..playerData[i].id),640,260,80,"zoomout",.26)
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
LOG.print("Illegal message: ["..mes.."]",30,COLOR.green)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -261,15 +228,8 @@ function scene.update(dt)
|
||||
local _
|
||||
local GAME=GAME
|
||||
|
||||
if WS.status("play")~="running"and not SCN.swapping then SCN.back()end
|
||||
if not playing then
|
||||
heartBeatTimer=heartBeatTimer+dt
|
||||
if heartBeatTimer>42 then
|
||||
heartBeatTimer=0
|
||||
WS.send("play","P")
|
||||
end
|
||||
return
|
||||
end
|
||||
if WS.status("play")~="running"then SCN.back()end
|
||||
if not playing then return end
|
||||
|
||||
touchMoveLastFrame=false
|
||||
updateVirtualkey()
|
||||
@@ -289,7 +249,7 @@ function scene.update(dt)
|
||||
local stream
|
||||
stream,upstreamProgress=dumpRecording(GAME.rep,upstreamProgress)
|
||||
if #stream>0 then
|
||||
WS.send("stream",data.encode("string","base64",stream))
|
||||
NET.uploadRecStream(stream)
|
||||
else
|
||||
ins(GAME.rep,GAME.frame)
|
||||
ins(GAME.rep,0)
|
||||
@@ -322,7 +282,7 @@ end
|
||||
scene.widgetList={
|
||||
textBox,
|
||||
WIDGET.newKey{name="ready",x=640,y=440,w=200,h=80,color="yellow",font=40,code=pressKey"space",hide=function()return playing or not hideChatBox or PLAYERS[1].ready end},
|
||||
WIDGET.newKey{name="hideChat",fText="...",x=380,y=35,w=60,font=35,code=switchChat},
|
||||
WIDGET.newKey{name="hideChat",fText="...",x=380,y=35,w=60,font=35,code=pressKey"\\"},
|
||||
WIDGET.newKey{name="quit",fText="X",x=900,y=35,w=60,font=40,code=pressKey"escape"},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
local scene={}
|
||||
|
||||
function scene.sceneInit()
|
||||
BG.set("matrix")
|
||||
BG.set("space")
|
||||
end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newButton{name="ffa", x=640, y=200,w=350,h=120,font=40,code=NULL},
|
||||
-- WIDGET.newButton{name="ffa", x=640, y=200,w=350,h=120,font=40,code=NULL},
|
||||
WIDGET.newButton{name="rooms", x=640, y=360,w=350,h=120,font=40,code=goScene"net_rooms"},
|
||||
WIDGET.newButton{name="chat", x=640, y=540,w=350,h=120,font=40,code=goScene"net_chat",hide=function()return WS.status("chat")~="running"end},
|
||||
-- WIDGET.newButton{name="chat", x=640, y=540,w=350,h=120,font=40,code=goScene"net_chat"},
|
||||
WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80,font=40,code=backScene},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +1,23 @@
|
||||
local gc=love.graphics
|
||||
local min=math.min
|
||||
|
||||
local rooms
|
||||
local NET=NET
|
||||
local scrollPos,selected
|
||||
local lastfreshTime
|
||||
local fetchTimer
|
||||
local lastCreateRoomTime=0
|
||||
|
||||
local function enterRoom(roomID)
|
||||
--[[TODO
|
||||
WS.connect("play","/play",JSON.encode{
|
||||
email=USER.email,
|
||||
token=USER.accessToken,
|
||||
id=roomID,
|
||||
conf=dumpBasicConfig(),
|
||||
-- password=password,
|
||||
})
|
||||
]]
|
||||
end
|
||||
local function fresh()
|
||||
lastfreshTime=TIME()
|
||||
rooms=nil
|
||||
--[[TODO
|
||||
WS.connect("play","/play",JSON.encode{
|
||||
email=USER.email,
|
||||
accessToken=USER.accessToken,
|
||||
})
|
||||
]]
|
||||
local function fetchRoom()
|
||||
fetchTimer=5
|
||||
NET.fetchRoom()
|
||||
end
|
||||
|
||||
local scene={}
|
||||
|
||||
function scene.sceneInit()
|
||||
BG.set("bg1")
|
||||
BG.set("space")
|
||||
scrollPos=0
|
||||
selected=1
|
||||
fresh()
|
||||
fetchRoom()
|
||||
end
|
||||
|
||||
function scene.wheelMoved(_,y)
|
||||
@@ -42,28 +25,21 @@ function scene.wheelMoved(_,y)
|
||||
end
|
||||
function scene.keyDown(k)
|
||||
if k=="r"then
|
||||
if TIME()-lastfreshTime>1 then
|
||||
fresh()
|
||||
if fetchTimer<=3.26 then
|
||||
fetchRoom()
|
||||
end
|
||||
elseif k=="n"then
|
||||
if TIME()-lastCreateRoomTime>26 then
|
||||
--[[TODO
|
||||
WS.send("room",JSON.encode{
|
||||
email=USER.email,
|
||||
accessToken=USER.accessToken,
|
||||
room_name=(USER.name or"???").."'s room",
|
||||
room_password=nil,
|
||||
})
|
||||
]]
|
||||
NET.createRoom()
|
||||
lastCreateRoomTime=TIME()
|
||||
else
|
||||
LOG.print(text.createRoomTooFast,"warn")
|
||||
end
|
||||
elseif k=="escape"then
|
||||
SCN.back()
|
||||
elseif rooms and #rooms>0 then
|
||||
elseif #NET.roomList>0 then
|
||||
if k=="down"then
|
||||
if selected<#rooms then
|
||||
if selected<#NET.roomList then
|
||||
selected=selected+1
|
||||
if selected>scrollPos+10 then
|
||||
scrollPos=scrollPos+1
|
||||
@@ -77,59 +53,63 @@ function scene.keyDown(k)
|
||||
end
|
||||
end
|
||||
elseif k=="return"then
|
||||
if rooms[selected].private then
|
||||
if NET.getLock("fetchRoom")then return end
|
||||
if NET.roomList[selected].private then
|
||||
LOG.print("Can't enter private room now")
|
||||
return
|
||||
end
|
||||
enterRoom(rooms[selected].id)
|
||||
NET.enterRoom(NET.roomList[selected].rid)--,password
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function scene.update()
|
||||
if TIME()-lastfreshTime>5 then
|
||||
fresh()
|
||||
function scene.update(dt)
|
||||
if not NET.getLock("fetchRoom")then
|
||||
fetchTimer=fetchTimer-dt
|
||||
if fetchTimer<=0 then
|
||||
fetchRoom()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function scene.draw()
|
||||
--Fetching timer
|
||||
gc.setColor(1,1,1,.26)
|
||||
gc.arc("fill","pie",240,620,60,-1.5708,-1.5708+1.2566*(TIME()-lastfreshTime))
|
||||
if rooms then
|
||||
gc.setColor(1,1,1)
|
||||
if #rooms>0 then
|
||||
gc.setLineWidth(2)
|
||||
gc.rectangle("line",55,110,1100,400)
|
||||
gc.setColor(1,1,1,.3)
|
||||
gc.rectangle("fill",55,40*(1+selected-scrollPos)+30,1100,40)
|
||||
setFont(35)
|
||||
for i=1,min(10,#rooms-scrollPos)do
|
||||
local R=rooms[scrollPos+i]
|
||||
if R.private then
|
||||
gc.setColor(1,1,1)
|
||||
gc.draw(IMG.lock,64,75+40*i)
|
||||
end
|
||||
gc.setColor(.9,.9,1)
|
||||
gc.print(scrollPos+i,100,66+40*i)
|
||||
gc.setColor(1,1,.7)
|
||||
gc.print(R.name,200,66+40*i)
|
||||
gc.arc("fill","pie",240,620,60,-1.5708,-1.5708-1.2566*fetchTimer)
|
||||
|
||||
--Room list
|
||||
gc.setColor(1,1,1)
|
||||
gc.setLineWidth(2)
|
||||
gc.rectangle("line",50,110,1180,400)
|
||||
if #NET.roomList>0 then
|
||||
gc.setColor(1,1,1,.3)
|
||||
gc.rectangle("fill",50,40*(1+selected-scrollPos)+30,1180,40)
|
||||
setFont(35)
|
||||
for i=1,min(10,#NET.roomList-scrollPos)do
|
||||
local R=NET.roomList[scrollPos+i]
|
||||
if R.private then
|
||||
gc.setColor(1,1,1)
|
||||
gc.printf(R.type,500,66+40*i,500,"right")
|
||||
gc.print(R.count.."/"..R.capacity,1050,66+40*i)
|
||||
gc.draw(IMG.lock,59,75+40*i)
|
||||
end
|
||||
else
|
||||
setFont(60)
|
||||
mStr(text.noRooms,640,315)
|
||||
gc.setColor(.9,.9,1)
|
||||
gc.print(scrollPos+i,95,66+40*i)
|
||||
gc.setColor(1,1,.7)
|
||||
gc.print(R.name,250,66+40*i)
|
||||
gc.setColor(1,1,1)
|
||||
gc.printf(R.type,550,66+40*i,500,"right")
|
||||
gc.print(R.count.."/"..R.capacity,1100,66+40*i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newKey{name="fresh", x=240,y=620,w=140,h=140,font=40,code=fresh,hide=function()return TIME()-lastfreshTime<1.26 end},
|
||||
WIDGET.newText{name="refreshing",x=640,y=260,font=65,hide=function()return not NET.getLock("fetchRoom")end},
|
||||
WIDGET.newText{name="noRoom", x=640,y=260,font=40,hide=function()return #NET.roomList>0 or NET.getLock("fetchRoom")end},
|
||||
WIDGET.newKey{name="refresh", x=240,y=620,w=140,h=140,font=40,code=fetchRoom, hide=function()return fetchTimer>3.26 end},
|
||||
WIDGET.newKey{name="new", x=440,y=620,w=140,h=140,font=25,code=pressKey"n"},
|
||||
WIDGET.newKey{name="join", x=640,y=620,w=140,h=140,font=40,code=pressKey"return",hide=function()return not rooms end},
|
||||
WIDGET.newKey{name="up", x=840,y=585,w=140,h=70,font=40,code=pressKey"up",hide=function()return not rooms end},
|
||||
WIDGET.newKey{name="down", x=840,y=655,w=140,h=70,font=40,code=pressKey"down",hide=function()return not rooms end},
|
||||
WIDGET.newKey{name="join", x=640,y=620,w=140,h=140,font=40,code=pressKey"return", hide=function()return #NET.roomList==0 end},
|
||||
WIDGET.newKey{name="up", x=840,y=585,w=140,h=70,font=40,code=pressKey"up", hide=function()return #NET.roomList==0 end},
|
||||
WIDGET.newKey{name="down", x=840,y=655,w=140,h=70,font=40,code=pressKey"down", hide=function()return #NET.roomList==0 end},
|
||||
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,font=40,code=backScene},
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="importUnlock", x=190,y=300,w=280,h=100,color="lBlue",font=25,code=function()
|
||||
local D=parseCB()
|
||||
if D then
|
||||
TABLE.add(D,RANKS)
|
||||
TABLE.update(D,RANKS)
|
||||
FILE.save(RANKS,"conf/unlock")
|
||||
LOG.print(text.importSuccess,"message")
|
||||
else
|
||||
@@ -59,7 +59,7 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="importData", x=490,y=300,w=280,h=100,color="lBlue",font=25,code=function()
|
||||
local D=parseCB()
|
||||
if D and D.version==STAT.version then
|
||||
TABLE.add(D,STAT)
|
||||
TABLE.update(D,STAT)
|
||||
FILE.save(STAT,"conf/data")
|
||||
LOG.print(text.importSuccess,"message")
|
||||
else
|
||||
@@ -69,7 +69,7 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="importSetting", x=790,y=300,w=280,h=100,color="lBlue",font=25,code=function()
|
||||
local D=parseCB()
|
||||
if D then
|
||||
TABLE.add(D,SETTING)
|
||||
TABLE.update(D,SETTING)
|
||||
FILE.save(SETTING,"conf/settings")
|
||||
LOG.print(text.importSuccess,"message")
|
||||
else
|
||||
@@ -79,7 +79,7 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="importVK", x=1090,y=300,w=280,h=100,color="lBlue",font=25,code=function()
|
||||
local D=parseCB()
|
||||
if D then
|
||||
TABLE.add(D,VK_org)
|
||||
TABLE.update(D,VK_org)
|
||||
FILE.save(VK_org,"conf/virtualkey")
|
||||
LOG.print(text.importSuccess,"message")
|
||||
else
|
||||
|
||||
@@ -81,14 +81,14 @@ scene.widgetList={
|
||||
WIDGET.newText{name="title", x=80, y=50,font=70,align="L"},
|
||||
WIDGET.newText{name="preview", x=520, y=540,font=40,align="R"},
|
||||
|
||||
WIDGET.newSlider{name="das", x=250, y=190,w=600,unit=20,disp=lnk_SETval("das"), show=sliderShow,code=lnk_SETsto("das")},
|
||||
WIDGET.newSlider{name="arr", x=250, y=260,w=525,unit=15,disp=lnk_SETval("arr"), show=sliderShow,code=lnk_SETsto("arr")},
|
||||
WIDGET.newSlider{name="sddas", x=250, y=330,w=350,unit=10,disp=lnk_SETval("sddas"),show=sliderShow,code=lnk_SETsto("sddas")},
|
||||
WIDGET.newSlider{name="sdarr", x=250, y=400,w=140,unit=4, disp=lnk_SETval("sdarr"),show=sliderShow,code=lnk_SETsto("sdarr")},
|
||||
WIDGET.newSlider{name="dascut", x=250, y=470,w=600,unit=20,disp=lnk_SETval("dascut"),show=sliderShow,code=lnk_SETsto("dascut")},
|
||||
WIDGET.newSwitch{name="ihs", x=1100, y=260, disp=lnk_SETval("ihs"), code=lnk_SETrev("ihs")},
|
||||
WIDGET.newSwitch{name="irs", x=1100, y=330, disp=lnk_SETval("irs"), code=lnk_SETrev("irs")},
|
||||
WIDGET.newSwitch{name="ims", x=1100, y=400, disp=lnk_SETval("ims"), code=lnk_SETrev("ims")},
|
||||
WIDGET.newSlider{name="das", x=250, y=190,w=600,unit=20,disp=SETval("das"), show=sliderShow,code=SETsto("das")},
|
||||
WIDGET.newSlider{name="arr", x=250, y=260,w=525,unit=15,disp=SETval("arr"), show=sliderShow,code=SETsto("arr")},
|
||||
WIDGET.newSlider{name="sddas", x=250, y=330,w=350,unit=10,disp=SETval("sddas"),show=sliderShow,code=SETsto("sddas")},
|
||||
WIDGET.newSlider{name="sdarr", x=250, y=400,w=140,unit=4, disp=SETval("sdarr"),show=sliderShow,code=SETsto("sdarr")},
|
||||
WIDGET.newSlider{name="dascut", x=250, y=470,w=600,unit=20,disp=SETval("dascut"),show=sliderShow,code=SETsto("dascut")},
|
||||
WIDGET.newSwitch{name="ihs", x=1100, y=260, disp=SETval("ihs"), code=SETrev("ihs")},
|
||||
WIDGET.newSwitch{name="irs", x=1100, y=330, disp=SETval("irs"), code=SETrev("irs")},
|
||||
WIDGET.newSwitch{name="ims", x=1100, y=400, disp=SETval("ims"), code=SETrev("ims")},
|
||||
WIDGET.newButton{name="reset", x=160, y=580,w=200,h=100,color="lRed",font=40,
|
||||
code=function()
|
||||
local _=SETTING
|
||||
|
||||
@@ -27,14 +27,14 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="ctrl", x=290, y=220, w=320,h=80, color="lYellow",font=35,code=goScene"setting_control"},
|
||||
WIDGET.newButton{name="key", x=640, y=220, w=320,h=80, color="lGreen", font=35,code=goScene"setting_key"},
|
||||
WIDGET.newButton{name="touch", x=990, y=220, w=320,h=80, color="lBlue", font=35,code=goScene"setting_touch"},
|
||||
WIDGET.newSlider{name="reTime", x=350, y=340, w=300,unit=10,disp=lnk_SETval("reTime"),code=lnk_SETsto("reTime"),show=function(S)return(.5+S.disp()*.25).."s"end},
|
||||
WIDGET.newSelector{name="RS", x=500, y=420, w=300,color="sea",list={"TRS","SRS","C2","C2sym","Classic","None"},disp=lnk_SETval("RS"),code=lnk_SETsto("RS")},
|
||||
WIDGET.newSlider{name="reTime", x=350, y=340, w=300,unit=10,disp=SETval("reTime"),code=SETsto("reTime"),show=function(S)return(.5+S.disp()*.25).."s"end},
|
||||
WIDGET.newSelector{name="RS", x=500, y=420, w=300,color="sea",list={"TRS","SRS","C2","C2sym","Classic","None"},disp=SETval("RS"),code=SETsto("RS")},
|
||||
WIDGET.newButton{name="layout", x=550, y=540, w=200,h=70, font=35,code=goScene"setting_skin"},
|
||||
WIDGET.newSwitch{name="autoPause", x=1060, y=310, font=20,disp=lnk_SETval("autoPause"),code=lnk_SETrev("autoPause")},
|
||||
WIDGET.newSwitch{name="swap", x=1060, y=370, font=20,disp=lnk_SETval("swap"), code=lnk_SETrev("swap")},
|
||||
WIDGET.newSwitch{name="fine", x=1060, y=430, font=20,disp=lnk_SETval("fine"), code=function()SETTING.fine=not SETTING.fine if SETTING.fine then SFX.play("finesseError",.6) end end},
|
||||
WIDGET.newSwitch{name="appLock", x=1060, y=490, font=20,disp=lnk_SETval("appLock"), code=lnk_SETrev("appLock")},
|
||||
WIDGET.newSwitch{name="simpMode", x=1060, y=550, font=25,disp=lnk_SETval("simpMode"),code=function()
|
||||
WIDGET.newSwitch{name="autoPause", x=1060, y=310, font=20,disp=SETval("autoPause"),code=SETrev("autoPause")},
|
||||
WIDGET.newSwitch{name="swap", x=1060, y=370, font=20,disp=SETval("swap"), code=SETrev("swap")},
|
||||
WIDGET.newSwitch{name="fine", x=1060, y=430, font=20,disp=SETval("fine"), code=function()SETTING.fine=not SETTING.fine if SETTING.fine then SFX.play("finesseError",.6) end end},
|
||||
WIDGET.newSwitch{name="appLock", x=1060, y=490, font=20,disp=SETval("appLock"), code=SETrev("appLock")},
|
||||
WIDGET.newSwitch{name="simpMode", x=1060, y=550, font=25,disp=SETval("simpMode"),code=function()
|
||||
SETTING.simpMode=not SETTING.simpMode
|
||||
for i=1,#SCN.stack,2 do
|
||||
if SCN.stack[i]=="main"or SCN.stack[i]=="main_simple"then
|
||||
|
||||
@@ -10,8 +10,7 @@ local jump--Animation timer(10 to 0)
|
||||
local cv=SETTING.cv
|
||||
|
||||
function scene.sceneInit()
|
||||
last=0
|
||||
jump=0
|
||||
last,jump=0,0
|
||||
cv=SETTING.cv
|
||||
BG.set()
|
||||
end
|
||||
@@ -34,24 +33,24 @@ function scene.touchDown(x,y)
|
||||
end
|
||||
|
||||
function scene.update()
|
||||
local t=jump
|
||||
if t>0 then
|
||||
jump=t-1
|
||||
end
|
||||
if jump>0 then jump=jump-1 end
|
||||
end
|
||||
|
||||
function scene.draw()
|
||||
gc.setColor(1,1,1)
|
||||
local t=TIME()
|
||||
local _=jump
|
||||
local x,y=800,340+10*sin(t*.5)+(_-10)*_*.3
|
||||
local x,y=800,340+10*sin(t*.5)+(jump-10)*jump*.3
|
||||
gc.translate(x,y)
|
||||
gc.draw(IMG.miyaCH,0,0)
|
||||
gc.setColor(1,1,1,.7)
|
||||
gc.draw(IMG.miyaF1,4,47+4*sin(t*.9))
|
||||
gc.draw(IMG.miyaF2,42,107+5*sin(t))
|
||||
gc.draw(IMG.miyaF3,93,126+3*sin(t*.7))
|
||||
gc.draw(IMG.miyaF4,129,98+3*sin(t*.7))
|
||||
if cv=="miya"then
|
||||
gc.draw(IMG.miyaCH)
|
||||
gc.setColor(1,1,1,.7)
|
||||
gc.draw(IMG.miyaF1,4,47+4*sin(t*.9))
|
||||
gc.draw(IMG.miyaF2,42,107+5*sin(t))
|
||||
gc.draw(IMG.miyaF3,93,126+3*sin(t*.7))
|
||||
gc.draw(IMG.miyaF4,129,98+3*sin(t*.5))
|
||||
elseif cv=="naki"then
|
||||
gc.draw(IMG.nakiCH)
|
||||
end
|
||||
gc.translate(-x,-y)
|
||||
end
|
||||
|
||||
@@ -61,13 +60,13 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="game", x=200, y=80,w=240,h=80,color="lCyan",font=35,code=swapScene"setting_game","swipeR"},
|
||||
WIDGET.newButton{name="graphic",x=1080, y=80,w=240,h=80,color="lCyan",font=35,code=swapScene"setting_video","swipeL"},
|
||||
|
||||
WIDGET.newSlider{name="sfx", x=180, y=200,w=400, font=35,change=function()SFX.play("blip_1")end, disp=lnk_SETval("sfx"),code=lnk_SETsto("sfx")},
|
||||
WIDGET.newSlider{name="spawn", x=180, y=300,w=400, font=30,change=function()SFX.fplay("spawn_"..math.random(7),SETTING.sfx_spawn)end,disp=lnk_SETval("sfx_spawn"),code=lnk_SETsto("sfx_spawn")},
|
||||
WIDGET.newSlider{name="warn", x=180, y=400,w=400, font=30,change=function()SFX.fplay("warning",SETTING.sfx_warn)end,disp=lnk_SETval("sfx_warn"),code=lnk_SETsto("sfx_warn")},
|
||||
WIDGET.newSlider{name="bgm", x=180, y=500,w=400, font=35, disp=lnk_SETval("bgm"),code=function(v)SETTING.bgm=v BGM.freshVolume()end},
|
||||
WIDGET.newSlider{name="stereo", x=180, y=600,w=400, font=35,change=function()SFX.play("move",1,-1)SFX.play("lock",1,1)end,disp=lnk_SETval("stereo"),code=lnk_SETsto("stereo"),hide=function()return SETTING.sx==0 end},
|
||||
WIDGET.newSlider{name="vib", x=750, y=200,w=400,unit=5, font=25,change=function()VIB(2)end, disp=lnk_SETval("vib"),code=lnk_SETsto("vib")},
|
||||
WIDGET.newSlider{name="voc", x=750, y=300,w=400, font=35,change=function()VOC.play("test")end, disp=lnk_SETval("voc"),code=lnk_SETsto("voc")},
|
||||
WIDGET.newSlider{name="sfx", x=180, y=200,w=400, font=35,change=function()SFX.play("blip_1")end, disp=SETval("sfx"),code=SETsto("sfx")},
|
||||
WIDGET.newSlider{name="spawn", x=180, y=300,w=400, font=30,change=function()SFX.fplay("spawn_"..math.random(7),SETTING.sfx_spawn)end,disp=SETval("sfx_spawn"),code=SETsto("sfx_spawn")},
|
||||
WIDGET.newSlider{name="warn", x=180, y=400,w=400, font=30,change=function()SFX.fplay("warning",SETTING.sfx_warn)end,disp=SETval("sfx_warn"),code=SETsto("sfx_warn")},
|
||||
WIDGET.newSlider{name="bgm", x=180, y=500,w=400, font=35, disp=SETval("bgm"),code=function(v)SETTING.bgm=v BGM.freshVolume()end},
|
||||
WIDGET.newSlider{name="stereo", x=180, y=600,w=400, font=35,change=function()SFX.play("move",1,-1)SFX.play("lock",1,1)end,disp=SETval("stereo"),code=SETsto("stereo"),hide=function()return SETTING.sx==0 end},
|
||||
WIDGET.newSlider{name="vib", x=750, y=200,w=400,unit=5, font=25,change=function()VIB(2)end, disp=SETval("vib"),code=SETsto("vib")},
|
||||
WIDGET.newSlider{name="voc", x=750, y=300,w=400, font=35,change=function()VOC.play("test")end, disp=SETval("voc"),code=SETsto("voc")},
|
||||
WIDGET.newSelector{name="cv", x=1100, y=380,w=200, list={"miya","naki"}, disp=function()return cv end,code=function(i)cv=i end},
|
||||
WIDGET.newButton{name="apply", x=1100, y=460,w=180,h=80, code=function()SETTING.cv=cv VOC.loadAll()end,hide=function()return SETTING.cv==cv end},
|
||||
WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80, font=40,code=backScene},
|
||||
|
||||
@@ -30,11 +30,11 @@ scene.widgetList={
|
||||
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=lnk_SETval("VKSwitch"),code=lnk_SETrev("VKSwitch")},
|
||||
WIDGET.newSwitch{name="track", x=1170, y=300, font=35,disp=lnk_SETval("VKTrack"),code=lnk_SETrev("VKTrack")},
|
||||
WIDGET.newSlider{name="sfx", x=800, y=380, w=180, font=35,change=function()SFX.play("virtualKey",SETTING.VKSFX)end,disp=lnk_SETval("VKSFX"),code=lnk_SETsto("VKSFX")},
|
||||
WIDGET.newSlider{name="vib", x=800, y=460, w=180,unit=2, font=35,change=function()VIB(SETTING.VKVIB)end,disp=lnk_SETval("VKVIB"),code=lnk_SETsto("VKVIB")},
|
||||
WIDGET.newSwitch{name="icon", x=850, y=300, font=40,disp=lnk_SETval("VKIcon"),code=lnk_SETrev("VKIcon")},
|
||||
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()
|
||||
SCN.go("setting_trackSetting")
|
||||
@@ -42,7 +42,7 @@ scene.widgetList={
|
||||
hide=function()
|
||||
return not SETTING.VKTrack
|
||||
end},
|
||||
WIDGET.newSlider{name="alpha", x=840, y=540, w=400,font=40,disp=lnk_SETval("VKAlpha"),code=lnk_SETsto("VKAlpha")},
|
||||
WIDGET.newSlider{name="alpha", x=840, y=540, w=400,font=40,disp=SETval("VKAlpha"),code=SETsto("VKAlpha")},
|
||||
WIDGET.newButton{name="back", x=1140, y=640, w=170,h=80,font=40,code=backScene},
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ function scene.draw()
|
||||
end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newSwitch{name="VKDodge",x=400, y=530, font=35,disp=lnk_SETval("VKDodge"),code=lnk_SETrev("VKDodge")},
|
||||
WIDGET.newSlider{name="VKTchW", x=140, y=320,w=1000, font=35,disp=lnk_SETval("VKTchW"),code=function(i)SETTING.VKTchW=i SETTING.VKCurW=math.max(SETTING.VKCurW,i)end},
|
||||
WIDGET.newSlider{name="VKCurW", x=140, y=390,w=1000, font=35,disp=lnk_SETval("VKCurW"),code=function(i)SETTING.VKCurW=i SETTING.VKTchW=math.min(SETTING.VKTchW,i)end},
|
||||
WIDGET.newSwitch{name="VKDodge",x=400, y=530, font=35,disp=SETval("VKDodge"),code=SETrev("VKDodge")},
|
||||
WIDGET.newSlider{name="VKTchW", x=140, y=320,w=1000, font=35,disp=SETval("VKTchW"),code=function(i)SETTING.VKTchW=i SETTING.VKCurW=math.max(SETTING.VKCurW,i)end},
|
||||
WIDGET.newSlider{name="VKCurW", x=140, y=390,w=1000, font=35,disp=SETval("VKCurW"),code=function(i)SETTING.VKCurW=i SETTING.VKTchW=math.min(SETTING.VKTchW,i)end},
|
||||
WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80,font=40,code=backScene},
|
||||
}
|
||||
|
||||
|
||||
@@ -13,22 +13,22 @@ scene.widgetList={
|
||||
WIDGET.newButton{name="sound", x=200, y=80,w=240,h=80,color="lCyan",font=35,code=swapScene"setting_sound","swipeR"},
|
||||
WIDGET.newButton{name="game", x=1080, y=80,w=240,h=80,color="lCyan",font=35,code=swapScene"setting_game","swipeL"},
|
||||
|
||||
WIDGET.newSwitch{name="block", x=340, y=150, disp=lnk_SETval("block"), code=lnk_SETrev("block")},
|
||||
WIDGET.newSwitch{name="smooth", x=340, y=210, disp=lnk_SETval("smooth"), code=lnk_SETrev("smooth")},
|
||||
WIDGET.newSwitch{name="upEdge", x=340, y=270, disp=lnk_SETval("upEdge"), code=lnk_SETrev("upEdge")},
|
||||
WIDGET.newSwitch{name="bagLine", x=340, y=330, disp=lnk_SETval("bagLine"), code=lnk_SETrev("bagLine")},
|
||||
WIDGET.newSwitch{name="block", x=340, y=150, disp=SETval("block"), code=SETrev("block")},
|
||||
WIDGET.newSwitch{name="smooth", x=340, y=210, disp=SETval("smooth"), code=SETrev("smooth")},
|
||||
WIDGET.newSwitch{name="upEdge", x=340, y=270, disp=SETval("upEdge"), code=SETrev("upEdge")},
|
||||
WIDGET.newSwitch{name="bagLine", x=340, y=330, disp=SETval("bagLine"), code=SETrev("bagLine")},
|
||||
|
||||
WIDGET.newSlider{name="ghost", x=630, y=180,w=200,unit=.6,disp=lnk_SETval("ghost"),show="percent",code=lnk_SETsto("ghost")},
|
||||
WIDGET.newSlider{name="grid", x=630, y=240,w=200,unit=.4,disp=lnk_SETval("grid"),show="percent", code=lnk_SETsto("grid")},
|
||||
WIDGET.newSlider{name="center", x=630, y=300,w=200,unit=1, disp=lnk_SETval("center"), code=lnk_SETsto("center")},
|
||||
WIDGET.newSlider{name="ghost", x=630, y=180,w=200,unit=.6,disp=SETval("ghost"),show="percent",code=SETsto("ghost")},
|
||||
WIDGET.newSlider{name="grid", x=630, y=240,w=200,unit=.4,disp=SETval("grid"),show="percent", code=SETsto("grid")},
|
||||
WIDGET.newSlider{name="center", x=630, y=300,w=200,unit=1, disp=SETval("center"), code=SETsto("center")},
|
||||
|
||||
WIDGET.newSlider{name="lockFX", x=350, y=375,w=373,unit=5, disp=lnk_SETval("lockFX"), code=lnk_SETsto("lockFX")},
|
||||
WIDGET.newSlider{name="dropFX", x=350, y=420,w=373,unit=5, disp=lnk_SETval("dropFX"), code=lnk_SETsto("dropFX")},
|
||||
WIDGET.newSlider{name="moveFX", x=350, y=465,w=373,unit=5, disp=lnk_SETval("moveFX"), code=lnk_SETsto("moveFX")},
|
||||
WIDGET.newSlider{name="clearFX", x=350, y=510,w=373,unit=5, disp=lnk_SETval("clearFX"), code=lnk_SETsto("clearFX")},
|
||||
WIDGET.newSlider{name="splashFX", x=350, y=555,w=373,unit=5, disp=lnk_SETval("splashFX"),code=lnk_SETsto("splashFX")},
|
||||
WIDGET.newSlider{name="shakeFX", x=350, y=600,w=373,unit=5, disp=lnk_SETval("shakeFX"), code=lnk_SETsto("shakeFX")},
|
||||
WIDGET.newSlider{name="atkFX", x=350, y=645,w=373,unit=5, disp=lnk_SETval("atkFX"), code=lnk_SETsto("atkFX")},
|
||||
WIDGET.newSlider{name="lockFX", x=350, y=375,w=373,unit=5, disp=SETval("lockFX"), code=SETsto("lockFX")},
|
||||
WIDGET.newSlider{name="dropFX", x=350, y=420,w=373,unit=5, disp=SETval("dropFX"), code=SETsto("dropFX")},
|
||||
WIDGET.newSlider{name="moveFX", x=350, y=465,w=373,unit=5, disp=SETval("moveFX"), code=SETsto("moveFX")},
|
||||
WIDGET.newSlider{name="clearFX", x=350, y=510,w=373,unit=5, disp=SETval("clearFX"), code=SETsto("clearFX")},
|
||||
WIDGET.newSlider{name="splashFX", x=350, y=555,w=373,unit=5, disp=SETval("splashFX"),code=SETsto("splashFX")},
|
||||
WIDGET.newSlider{name="shakeFX", x=350, y=600,w=373,unit=5, disp=SETval("shakeFX"), code=SETsto("shakeFX")},
|
||||
WIDGET.newSlider{name="atkFX", x=350, y=645,w=373,unit=5, disp=SETval("atkFX"), code=SETsto("atkFX")},
|
||||
WIDGET.newSlider{name="frame", x=350, y=690,w=373,unit=10,
|
||||
disp=function()
|
||||
return SETTING.frameMul>35 and SETTING.frameMul/10 or SETTING.frameMul/5-4
|
||||
@@ -37,20 +37,20 @@ scene.widgetList={
|
||||
SETTING.frameMul=i<5 and 5*i+20 or 10*i
|
||||
end},
|
||||
|
||||
WIDGET.newSwitch{name="text", x=1100, y=180,font=35,disp=lnk_SETval("text"), code=lnk_SETrev("text")},
|
||||
WIDGET.newSwitch{name="score", x=1100, y=240,font=35,disp=lnk_SETval("score"), code=lnk_SETrev("score")},
|
||||
WIDGET.newSwitch{name="warn", x=1100, y=300,font=35,disp=lnk_SETval("warn"), code=lnk_SETrev("warn")},
|
||||
WIDGET.newSwitch{name="highCam", x=1100, y=360,font=35,disp=lnk_SETval("highCam"),code=lnk_SETrev("highCam")},
|
||||
WIDGET.newSwitch{name="nextPos", x=1100, y=420,font=35,disp=lnk_SETval("nextPos"),code=lnk_SETrev("nextPos")},
|
||||
WIDGET.newSwitch{name="fullscreen",x=1100, y=480,disp=lnk_SETval("fullscreen"), code=switchFullscreen},
|
||||
WIDGET.newSwitch{name="bg", x=1100, y=540,font=35,disp=lnk_SETval("bg"),
|
||||
WIDGET.newSwitch{name="text", x=1100, y=180,font=35,disp=SETval("text"), code=SETrev("text")},
|
||||
WIDGET.newSwitch{name="score", x=1100, y=240,font=35,disp=SETval("score"), code=SETrev("score")},
|
||||
WIDGET.newSwitch{name="warn", x=1100, y=300,font=35,disp=SETval("warn"), code=SETrev("warn")},
|
||||
WIDGET.newSwitch{name="highCam", x=1100, y=360,font=35,disp=SETval("highCam"),code=SETrev("highCam")},
|
||||
WIDGET.newSwitch{name="nextPos", x=1100, y=420,font=35,disp=SETval("nextPos"),code=SETrev("nextPos")},
|
||||
WIDGET.newSwitch{name="fullscreen",x=1100, y=480,disp=SETval("fullscreen"), code=switchFullscreen},
|
||||
WIDGET.newSwitch{name="bg", x=1100, y=540,font=35,disp=SETval("bg"),
|
||||
code=function()
|
||||
BG.set("none")
|
||||
SETTING.bg=not SETTING.bg
|
||||
BG.set()
|
||||
end},
|
||||
WIDGET.newSwitch{name="power", x=990, y=610,font=35,disp=lnk_SETval("powerInfo"),code=lnk_SETrev("powerInfo")},
|
||||
WIDGET.newSwitch{name="clean", x=990, y=670,font=35,disp=lnk_SETval("cleanCanvas"),code=lnk_SETrev("cleanCanvas")},
|
||||
WIDGET.newSwitch{name="power", x=990, y=610,font=35,disp=SETval("powerInfo"),code=SETrev("powerInfo")},
|
||||
WIDGET.newSwitch{name="clean", x=990, y=670,font=35,disp=SETval("cleanCanvas"),code=SETrev("cleanCanvas")},
|
||||
WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80,font=40,code=backScene},
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newText{name="title", x=30, y=15,font=70,align="L"},
|
||||
WIDGET.newSlider{name="sfx", x=510, y=60,w=330,font=35,change=function()SFX.play("blip_1")end,disp=lnk_SETval("sfx"),code=lnk_SETsto("sfx")},
|
||||
WIDGET.newSlider{name="voc", x=510, y=120,w=330,font=35,change=function()VOC.play("test")end,disp=lnk_SETval("voc"),code=lnk_SETsto("voc")},
|
||||
WIDGET.newSlider{name="sfx", x=510, y=60,w=330,font=35,change=function()SFX.play("blip_1")end,disp=SETval("sfx"),code=SETsto("sfx")},
|
||||
WIDGET.newSlider{name="voc", x=510, y=120,w=330,font=35,change=function()VOC.play("test")end,disp=SETval("voc"),code=SETsto("voc")},
|
||||
|
||||
WIDGET.newKey{name="move", x=110, y=140,w=160,h=50,font=20,code=function()SFX.play("move")end},
|
||||
WIDGET.newKey{name="lock", x=110, y=205,w=160,h=50,font=20,code=function()SFX.play("lock")end},
|
||||
|
||||
@@ -144,14 +144,14 @@ end
|
||||
--WS icons
|
||||
setFont(20)
|
||||
TEXTURE.ws_dead=NSC(20,20)
|
||||
gc.setColor(1,.4,.3)
|
||||
gc.setColor(1,.3,.3)
|
||||
gc.print("X",3,-4)
|
||||
TEXTURE.ws_connecting=NSC(20,20)
|
||||
gc.setLineWidth(3)
|
||||
gc.setColor(1,1,1)
|
||||
gc.arc("line","open",11.5,10,6.26,1,5.28)
|
||||
TEXTURE.ws_running=NSC(20,20)
|
||||
gc.setColor(0,.9,0)
|
||||
gc.setColor(.5,1,0)
|
||||
gc.print("R",3,-4)
|
||||
|
||||
|
||||
|
||||
@@ -1,24 +1,70 @@
|
||||
return SPLITSTR([=[
|
||||
未来计划:
|
||||
新模式:
|
||||
无尽PC挑战; 简单极简练习; 任务生存; 对称; 跑酷; 教学; 术语问答; 无摩擦
|
||||
极简教程/考试; 连击练习; 自攻自受; 大爆炸; 音游模式; 拼方形; 养成玩法
|
||||
OSD; 强制Misdrop; 涂色模式(模仿喷喷, designed by teatube)
|
||||
其他:
|
||||
小游戏:
|
||||
速算(前缀后缀表达式,二八十六进制); 动态视力测试(记数字)
|
||||
Tetro-1010(四/五连块, 2C2N, 若干回合改变重力方向)
|
||||
求合体; 坦克大战; 扫雷; 接水管; 各种NS计算器小游戏移植
|
||||
多方块; XRS; 移动n格+硬降复合操作键; 更好的手柄支持; 手势操作
|
||||
区分各种消除(隔断/架空/混合/彩色/穿墙)
|
||||
更复杂的垃圾行(数量/等待时间/抵消倍率/洞数/连接/炸弹)
|
||||
可调场地宽度; DAS系统更细节的折返选项; 特殊控件(虚拟摇杆等)
|
||||
主菜单和选关UI重做; 适应任意屏幕尺寸的UI
|
||||
可更换的全局主题系统; 成就系统; 3D背景
|
||||
可选虚拟按键颜色; 工程编译到字节码; task-Z(新AI)
|
||||
录像回放菜单; 跳帧开关; 超60帧; 热更新
|
||||
未来模式:
|
||||
无尽PC挑战; 简单极简练习; 任务生存; 对称; 无摩擦; 连击练习; 拼方形
|
||||
极简教程/考试; 大爆炸; 音游模式; 跑酷; 术语问答; 养成玩法
|
||||
OSD; 强制Misdrop; 涂色模式(模仿喷喷, designed by teatube)
|
||||
未来大游戏:
|
||||
puyo; 花仙子方块; 2048; 泡泡龙
|
||||
未来Mod:
|
||||
修改颜色配置; 只显示场地边框线/顶线
|
||||
未来小游戏:
|
||||
Tetro-1010(四/五连块, 2C2N, 若干回合改变重力方向)
|
||||
Tetra-link; 速算(前缀后缀表达式,二八十六进制)
|
||||
连连看; 求合体; 坦克大战; 扫雷; 接水管
|
||||
其他未来内容:
|
||||
XRS; 移动n格+硬降复合操作键; 更好的手柄支持
|
||||
自适应UI; 重做模式选择UI和MOD的UI; 高级自定义序列
|
||||
区分各种消除(隔断/架空/混合/彩色/穿墙)
|
||||
更复杂的垃圾行(数量/等待时间/抵消倍率/洞数/连接/炸弹)
|
||||
可调场地宽度; 手势操作; 特殊控件(虚拟摇杆等); 切换高低镜头的按键
|
||||
DAS系统和Deepdrop系统更细节的选项; spike计数器; 攻击总缓冲显示
|
||||
成就系统; 更强的主题系统; 多方块; 3D背景
|
||||
可选虚拟按键颜色; 工程编译到字节码; task-Z(新AI)
|
||||
录像回放菜单; 跳帧开关; 教学关; 超60帧; 热更新
|
||||
|
||||
0.13.3: 科技飞跃
|
||||
0.14.0: 地平线 The Horizon
|
||||
新增:
|
||||
重新开放联网游戏测试
|
||||
主菜单UI更新,改变几个场景间的关系
|
||||
场地晃动加入旋转分量
|
||||
加入c2和mess序列模式,可以在自定义或mod中开启
|
||||
新模式:Backfire(四个难度)
|
||||
新背景:BlackHole(用于Backfire)
|
||||
新增BGM:echo(用于Backfire), hang out(用于两个小程序)
|
||||
调整自定义场地的ui,可以看到鼠标不同按键对应画笔颜色
|
||||
小程序DTW增加双押功能
|
||||
新增绘制优化设置(手机开启可能加速,花屏可能关闭解决)
|
||||
改动:
|
||||
错误处理机制大升级,更不容易闪退(CC爆炸除外)
|
||||
赞助名单移至staff场景并添加动画(已经在榜上的可以来定制颜色!)
|
||||
修改GM模式的名称和段位名以及修改连带内容,加高成绩上限,修复一个旧版本存档转换错误
|
||||
封面NOGAME改为启动时弹窗提示重启
|
||||
鼠标按下时光标显示会变化
|
||||
优化场地绘制交互,添加一个鼠标功能指示器
|
||||
微调生存模式下落速度
|
||||
修改时间字符串格式
|
||||
词典不再大小写敏感
|
||||
调整徽章图标
|
||||
添加naki立绘
|
||||
报错时会把traceback信息保存到日志文件便于debug
|
||||
cmd添加一些测试用命令和一些文件管理命令,可以用于自行修复存档
|
||||
cmd添加复制粘贴剪切和tab补全,不再需要切焦点
|
||||
ws状态展示样式升级,只在debug模式下显示
|
||||
代码:
|
||||
序列生成器改用协程实现
|
||||
THEME做成独立模块
|
||||
玩家属性modeData地位提升
|
||||
不再每次启动时强制删除存档目录内所有非文件夹内容
|
||||
绘制玩家场地用的scissor换成stencil(支持旋转和变形)
|
||||
优化/大规模整理代码,网络相关全面升级
|
||||
修复:
|
||||
物理hold可能会卡死和踢墙测试位置不正确
|
||||
词典中c2序列生成器的说明错误
|
||||
刚安装就用简洁模式玩会报错(修改成绩比较逻辑)
|
||||
报错提示的场景显示不正确
|
||||
智能画笔问题
|
||||
|
||||
0.13.3: 科技飞跃 Technological Advancements
|
||||
新增:
|
||||
地图UI升级,增加模式图标
|
||||
自定义场地新增智能画笔
|
||||
@@ -45,7 +91,7 @@ return SPLITSTR([=[
|
||||
一个老存档转换问题
|
||||
重开后虚拟按键失效
|
||||
|
||||
0.13.2+: 工作室搬迁
|
||||
0.13.2+: 工作室搬迁 Moving the Studio
|
||||
新增:
|
||||
全新加载动画与资源加载机制
|
||||
显示ai计算的下一块位置
|
||||
@@ -59,7 +105,7 @@ return SPLITSTR([=[
|
||||
修复:
|
||||
CC闪退(可能修复)
|
||||
|
||||
0.13.2: 节奏模式
|
||||
0.13.2: 节奏模式 Rhythm Mode
|
||||
新增:
|
||||
新增节奏模式(三个难度)
|
||||
加入deepDrop功能(暂时只在自定义开放)
|
||||
|
||||