diff --git a/Zframework/init.lua b/Zframework/init.lua index e89ff481..e66c0fd7 100644 --- a/Zframework/init.lua +++ b/Zframework/init.lua @@ -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() diff --git a/Zframework/scene.lua b/Zframework/scene.lua index 8a2bb951..022f8886 100644 --- a/Zframework/scene.lua +++ b/Zframework/scene.lua @@ -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 diff --git a/Zframework/sysFX.lua b/Zframework/sysFX.lua index e0d458b0..3f2204bb 100644 --- a/Zframework/sysFX.lua +++ b/Zframework/sysFX.lua @@ -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]={ diff --git a/Zframework/tableExtend.lua b/Zframework/tableExtend.lua index 120241fd..fea18fea 100644 --- a/Zframework/tableExtend.lua +++ b/Zframework/tableExtend.lua @@ -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 diff --git a/Zframework/task.lua b/Zframework/task.lua index f2685c7c..a7a7c976 100644 --- a/Zframework/task.lua +++ b/Zframework/task.lua @@ -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, diff --git a/Zframework/theme.lua b/Zframework/theme.lua index 4de2df1e..c79c85c5 100644 --- a/Zframework/theme.lua +++ b/Zframework/theme.lua @@ -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 diff --git a/Zframework/websocket.lua b/Zframework/websocket.lua index 8ac28640..13988ffb 100644 --- a/Zframework/websocket.lua +++ b/Zframework/websocket.lua @@ -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 diff --git a/Zframework/widget.lua b/Zframework/widget.lua index da7fb784..2a8e379f 100644 --- a/Zframework/widget.lua +++ b/Zframework/widget.lua @@ -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) diff --git a/conf.lua b/conf.lua index abcb88f0..df78d08c 100644 --- a/conf.lua +++ b/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" diff --git a/main.lua b/main.lua index 1f74bb39..f34549a9 100644 --- a/main.lua +++ b/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 diff --git a/media/image/mess/electric.png b/media/image/characters/electric.png similarity index 100% rename from media/image/mess/electric.png rename to media/image/characters/electric.png diff --git a/media/image/mess/hbm.png b/media/image/characters/hbm.png similarity index 100% rename from media/image/mess/hbm.png rename to media/image/characters/hbm.png diff --git a/media/image/miya/ch.png b/media/image/characters/miya.png similarity index 100% rename from media/image/miya/ch.png rename to media/image/characters/miya.png diff --git a/media/image/miya/f1.png b/media/image/characters/miya_f1.png similarity index 100% rename from media/image/miya/f1.png rename to media/image/characters/miya_f1.png diff --git a/media/image/miya/f2.png b/media/image/characters/miya_f2.png similarity index 100% rename from media/image/miya/f2.png rename to media/image/characters/miya_f2.png diff --git a/media/image/miya/f3.png b/media/image/characters/miya_f3.png similarity index 100% rename from media/image/miya/f3.png rename to media/image/characters/miya_f3.png diff --git a/media/image/miya/f4.png b/media/image/characters/miya_f4.png similarity index 100% rename from media/image/miya/f4.png rename to media/image/characters/miya_f4.png diff --git a/media/image/characters/naki.png b/media/image/characters/naki.png new file mode 100644 index 00000000..05c71f3b Binary files /dev/null and b/media/image/characters/naki.png differ diff --git a/parts/ai.lua b/parts/ai.lua index ae6506e0..6f2c0d93 100644 --- a/parts/ai.lua +++ b/parts/ai.lua @@ -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) diff --git a/parts/backgrounds/blockrain.lua b/parts/backgrounds/blockrain.lua new file mode 100644 index 00000000..1cb9cbb3 --- /dev/null +++ b/parts/backgrounds/blockrain.lua @@ -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 \ No newline at end of file diff --git a/parts/gametoolfunc.lua b/parts/gametoolfunc.lua index 814ac235..1d6440d0 100644 --- a/parts/gametoolfunc.lua +++ b/parts/gametoolfunc.lua @@ -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=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 diff --git a/parts/modes/marathon_n.lua b/parts/modes/marathon_n.lua index 41f41367..ea691ac5 100644 --- a/parts/modes/marathon_n.lua +++ b/parts/modes/marathon_n.lua @@ -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, diff --git a/parts/modes/netBattle.lua b/parts/modes/netBattle.lua index aaadc2e8..41925c8b 100644 --- a/parts/modes/netBattle.lua +++ b/parts/modes/netBattle.lua @@ -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 diff --git a/parts/modes/round_e.lua b/parts/modes/round_e.lua index 2b3ef740..d565c152 100644 --- a/parts/modes/round_e.lua +++ b/parts/modes/round_e.lua @@ -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 diff --git a/parts/modes/round_h.lua b/parts/modes/round_h.lua index 54d17ae3..3ccce225 100644 --- a/parts/modes/round_h.lua +++ b/parts/modes/round_h.lua @@ -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 diff --git a/parts/modes/round_l.lua b/parts/modes/round_l.lua index a9ab94d7..69a21cd4 100644 --- a/parts/modes/round_l.lua +++ b/parts/modes/round_l.lua @@ -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 diff --git a/parts/modes/round_n.lua b/parts/modes/round_n.lua index b790fa84..6619e14e 100644 --- a/parts/modes/round_n.lua +++ b/parts/modes/round_n.lua @@ -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 diff --git a/parts/modes/round_u.lua b/parts/modes/round_u.lua index d8675c26..15ddef4d 100644 --- a/parts/modes/round_u.lua +++ b/parts/modes/round_u.lua @@ -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 diff --git a/parts/modes/techmino49_e.lua b/parts/modes/techmino49_e.lua index e1083665..05caf981 100644 --- a/parts/modes/techmino49_e.lua +++ b/parts/modes/techmino49_e.lua @@ -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) diff --git a/parts/modes/techmino49_h.lua b/parts/modes/techmino49_h.lua index 9643673f..8f2efa53 100644 --- a/parts/modes/techmino49_h.lua +++ b/parts/modes/techmino49_h.lua @@ -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) diff --git a/parts/modes/techmino49_u.lua b/parts/modes/techmino49_u.lua index d10655b9..fdc11d4a 100644 --- a/parts/modes/techmino49_u.lua +++ b/parts/modes/techmino49_u.lua @@ -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) diff --git a/parts/modes/techmino99_e.lua b/parts/modes/techmino99_e.lua index c35700ac..9ef69fe9 100644 --- a/parts/modes/techmino99_e.lua +++ b/parts/modes/techmino99_e.lua @@ -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) diff --git a/parts/modes/techmino99_h.lua b/parts/modes/techmino99_h.lua index 713030b3..6479e695 100644 --- a/parts/modes/techmino99_h.lua +++ b/parts/modes/techmino99_h.lua @@ -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) diff --git a/parts/modes/techmino99_u.lua b/parts/modes/techmino99_u.lua index 3ca05a56..a6440694 100644 --- a/parts/modes/techmino99_u.lua +++ b/parts/modes/techmino99_u.lua @@ -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) diff --git a/parts/net.lua b/parts/net.lua new file mode 100644 index 00000000..0a35a405 --- /dev/null +++ b/parts/net.lua @@ -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()=res.lowest then + NET.allow_online=true + end + if VERSION_CODE-------------------------- -function Player.showText(P,text,dx,dy,font,style,spd,stop) - if P.gameEnv.text then - ins(P.bonus,TEXT.getText(text,150+dx,300+dy,font*P.size,style,spd,stop)) +function Player:showText(text,dx,dy,font,style,spd,stop) + if self.gameEnv.text then + ins(self.bonus,TEXT.getText(text,150+dx,300+dy,font*self.size,style,spd,stop)) end end -function Player.showTextF(P,text,dx,dy,font,style,spd,stop) - ins(P.bonus,TEXT.getText(text,150+dx,300+dy,font*P.size,style,spd,stop)) +function Player:showTextF(text,dx,dy,font,style,spd,stop) + ins(self.bonus,TEXT.getText(text,150+dx,300+dy,font*self.size,style,spd,stop)) end -function Player.createLockFX(P) - local CB=P.cur.bk - local t=12-P.gameEnv.lockFX*2 +function Player:createLockFX() + local CB=self.cur.bk + local t=12-self.gameEnv.lockFX*2 for i=1,#CB do - local y=P.curY+i-1 - local L=P.clearedRow + local y=self.curY+i-1 + local L=self.clearedRow for j=1,#L do if L[j]==y then goto CONTINUE_skip end end y=-30*y for j=1,#CB[1]do if CB[i][j]then - ins(P.lockFX,{30*(P.curX+j-2),y,0,t}) + ins(self.lockFX,{30*(self.curX+j-2),y,0,t}) end end ::CONTINUE_skip:: end end -function Player.createDropFX(P,x,y,w,h) - ins(P.dropFX,{x,y,w,h,0,13-2*P.gameEnv.dropFX}) +function Player:createDropFX(x,y,w,h) + ins(self.dropFX,{x,y,w,h,0,13-2*self.gameEnv.dropFX}) end -function Player.createMoveFX(P,dir) - local T=10-1.5*P.gameEnv.moveFX - local C=P.cur.color - local CB=P.cur.bk - local x=P.curX-1 - local y=P.gameEnv.smooth and P.curY+P.dropDelay/P.gameEnv.drop-2 or P.curY-1 +function Player:createMoveFX(dir) + local T=10-1.5*self.gameEnv.moveFX + local C=self.cur.color + local CB=self.cur.bk + local x=self.curX-1 + local y=self.gameEnv.smooth and self.curY+self.dropDelay/self.gameEnv.drop-2 or self.curY-1 if dir=="left"then for i=1,#CB do for j=#CB[1],1,-1 do - if P.cur.bk[i][j]then - ins(P.moveFX,{C,x+j,y+i,0,T}) + if self.cur.bk[i][j]then + ins(self.moveFX,{C,x+j,y+i,0,T}) break end end end elseif dir=="right"then for i=1,#CB do for j=1,#CB[1]do - if P.cur.bk[i][j]then - ins(P.moveFX,{C,x+j,y+i,0,T}) + if self.cur.bk[i][j]then + ins(self.moveFX,{C,x+j,y+i,0,T}) break end end end elseif dir=="down"then for j=1,#CB[1]do for i=#CB,1,-1 do - if P.cur.bk[i][j]then - ins(P.moveFX,{C,x+j,y+i,0,T}) + if self.cur.bk[i][j]then + ins(self.moveFX,{C,x+j,y+i,0,T}) break end end end else for i=1,#CB do for j=1,#CB[1]do - if P.cur.bk[i][j]then - ins(P.moveFX,{C,x+j,y+i,0,T}) + if self.cur.bk[i][j]then + ins(self.moveFX,{C,x+j,y+i,0,T}) end end end end end -function Player.createSplashFX(P,h) - local L=P.field[h] - local size=P.size - local y=P.fieldY+size*(P.fieldOff.y+P.fieldBeneath+P.fieldUp+615) +function Player:createSplashFX(h) + local L=self.field[h] + local size=self.size + local y=self.fieldY+size*(self.fieldOff.y+self.fieldBeneath+self.fieldUp+615) for x=1,10 do local c=L[x] if c>0 then SYSFX.newCell( - 2.5-P.gameEnv.splashFX*.4, + 2.5-self.gameEnv.splashFX*.4, SKIN.curText[c], size, - P.fieldX+(30*x-15)*size,y-30*h*size, + self.fieldX+(30*x-15)*size,y-30*h*size, rnd()*5-2.5,rnd()*-1, 0,.6 ) end end end -function Player.createClearingFX(P,y,spd) - ins(P.clearFX,{y,0,spd}) +function Player:createClearingFX(y,spd) + ins(self.clearFX,{y,0,spd}) end -function Player.createBeam(P,R,send,color) +function Player:createBeam(R,send,color) local x1,y1,x2,y2 - if P.mini then x1,y1=P.centerX,P.centerY - else x1,y1=P.x+(30*(P.curX+P.cur.sc[2])-30+15+150)*P.size,P.y+(600-30*(P.curY+P.cur.sc[1])+15)*P.size + if self.mini then x1,y1=self.centerX,self.centerY + else x1,y1=self.x+(30*(self.curX+self.cur.sc[2])-30+15+150)*self.size,self.y+(600-30*(self.curY+self.cur.sc[1])+15)*self.size end if R.small then x2,y2=R.centerX,R.centerY else x2,y2=R.x+308*R.size,R.y+450*R.size end - local r,g,b=unpack(minoColor[color]) - r,g,b=r*2,g*2,b*2 + local c=minoColor[color] + local r,g,b=c[1]*2,c[2]*2,c[3]*2 - local a=GAME.modeEnv.royaleMode and not(P.type=="human"or R.type=="human")and .2 or 1 + local a=GAME.modeEnv.royaleMode and not(self.type=="human"or R.type=="human")and .2 or 1 SYSFX.newAttack(1-SETTING.atkFX*.1,x1,y1,x2,y2,int(send^.7*(4+SETTING.atkFX)),r,g,b,a*(SETTING.atkFX+2)*.0626) end ---------------------------------------------------- ---------------------------------------------------- -function Player.RND(P,a,b) - local R=P.randGen +function Player:RND(a,b) + local R=self.randGen return R:random(a,b) end -function Player.newTask(P,code,...) +function Player:newTask(code,...) local thread=coroutine.create(code) - coroutine.resume(thread,P,...) - if coroutine.status(thread)~="dead"then - P.tasks[#P.tasks+1]={ + resume(thread,self,...) + if status(thread)~="dead"then + self.tasks[#self.tasks+1]={ thread=thread, code=code, args={...}, @@ -132,164 +131,164 @@ function Player.newTask(P,code,...) end end -function Player.setPosition(P,x,y,size) +function Player:setPosition(x,y,size) size=size or 1 - P.x,P.y,P.size=x,y,size - if P.mini or P.demo then - P.fieldX,P.fieldY=x,y - P.centerX,P.centerY=x+300*size,y+600*size + self.x,self.y,self.size=x,y,size + if self.mini or self.demo then + self.fieldX,self.fieldY=x,y + self.centerX,self.centerY=x+300*size,y+600*size else - P.fieldX,P.fieldY=x+150*size,y - P.centerX,P.centerY=x+300*size,y+370*size - P.absFieldX,P.absFieldY=x+150*size,y-10*size + self.fieldX,self.fieldY=x+150*size,y + self.centerX,self.centerY=x+300*size,y+370*size + self.absFieldX,self.absFieldY=x+150*size,y-10*size end end -local function task_movePosition(P,x,y,size) - local x1,y1,size1=P.x,P.y,P.size +local function task_movePosition(self,x,y,size) + local x1,y1,size1=self.x,self.y,self.size while true do yield() if (x1-x)^2+(y1-y)^2<1 then - P:setPosition(x,y,size) + self:setPosition(x,y,size) return true else x1=x1+(x-x1)*.126 y1=y1+(y-y1)*.126 size1=size1+(size-size1)*.126 - P:setPosition(x1,y1,size1) + self:setPosition(x1,y1,size1) end end end local function checkPlayer(obj,Ptar) return obj.args[1]==Ptar end -function Player.movePosition(P,x,y,size) - TASK.removeTask_iterate(checkPlayer,P) - TASK.new(task_movePosition,P,x,y,size or P.size) +function Player:movePosition(x,y,size) + TASK.removeTask_iterate(checkPlayer,self) + TASK.new(task_movePosition,self,x,y,size or self.size) end -function Player.switchKey(P,id,on) - P.keyAvailable[id]=on +function Player:switchKey(id,on) + self.keyAvailable[id]=on if not on then - P:releaseKey(id) + self:releaseKey(id) end - if P.type=="human"then + if self.type=="human"then virtualkey[id].ava=on end end -function Player.set20G(P,if20g) - P._20G=if20g - P:switchKey(7,not if20g) - if if20g and P.AI_mode=="CC"then CC.switch20G(P)end +function Player:set20G(if20g) + self._20G=if20g + self:switchKey(7,not if20g) + if if20g and self.AI_mode=="CC"then CC.switch20G(self)end end -function Player.setHold(P,count)--Set hold count (false/true as 0/1) +function Player:setHold(count)--Set hold count (false/true as 0/1) if not count then count=0 elseif count==true then count=1 end - P.gameEnv.holdCount=count - P.holdTime=count - while P.holdQueue[count+1]do rem(P.holdQueue)end + self.gameEnv.holdCount=count + self.holdTime=count + while self.holdQueue[count+1]do rem(self.holdQueue)end end -function Player.setNext(P,next,hidden)--Set next count (use hidden=true if set env.nextStartPos>1) - P.gameEnv.nextCount=next +function Player:setNext(next,hidden)--Set next count (use hidden=true if set env.nextStartPos>1) + self.gameEnv.nextCount=next if next==0 then - P.drawNext=NULL + self.drawNext=NULL elseif not hidden then - P.drawNext=PLY.draw.drawNext_norm + self.drawNext=PLY.draw.drawNext_norm else - P.drawNext=PLY.draw.drawNext_hidden + self.drawNext=PLY.draw.drawNext_hidden end end -function Player.setInvisible(P,time)--Time in frames +function Player:setInvisible(time)--Time in frames if time<0 then - P.keepVisible=true - P.showTime=1e99 + self.keepVisible=true + self.showTime=1e99 else - P.keepVisible=false - P.showTime=time + self.keepVisible=false + self.showTime=time end end -function Player.setRS(P,RSname) - P.RS=kickList[RSname] +function Player:setRS(RSname) + self.RS=kickList[RSname] end -function Player.setConf(P,confStr) +function Player:setConf(confStr) local _,conf=pcall(love.data.decode,"string","base64",confStr) if _ then for k,v in next,conf do if not GAME.modeEnv[k]then - P.gameEnv[k]=v + self.gameEnv[k]=v end end else - LOG.print("Bad conf from "..P.userName.."#"..P.userID) + LOG.print("Bad conf from "..self.userName.."#"..self.userID) end end -function Player.getHolePos(P)--Get a good garbage-line hole position - if P.garbageBeneath==0 then - return generateLine(P:RND(10)) +function Player:getHolePos()--Get a good garbage-line hole position + if self.garbageBeneath==0 then + return generateLine(self:RND(10)) else - local p=P:RND(10) - if P.field[1][p]<=0 then - return generateLine(P:RND(10)) + local p=self:RND(10) + if self.field[1][p]<=0 then + return generateLine(self:RND(10)) end return generateLine(p) end end -function Player.garbageRelease(P)--Check garbage buffer and try to release them +function Player:garbageRelease()--Check garbage buffer and try to release them local n,flag=1 while true do - local A=P.atkBuffer[n] + local A=self.atkBuffer[n] if A and A.countdown<=0 and not A.sent then - P:garbageRise(19+A.lv,A.amount,A.line) - P.atkBuffer.sum=P.atkBuffer.sum-A.amount + self:garbageRise(19+A.lv,A.amount,A.line) + self.atkBuffer.sum=self.atkBuffer.sum-A.amount A.sent,A.time=true,0 - P.stat.pend=P.stat.pend+A.amount + self.stat.pend=self.stat.pend+A.amount n=n+1 flag=true else break end end - if flag and P.AI_mode=="CC"and P.AI_bot then CC.updateField(P)end + if flag and self.AI_mode=="CC"and self.AI_bot then CC.updateField(self)end end -function Player.garbageRise(P,color,amount,line)--Release n-lines garbage to field +function Player:garbageRise(color,amount,line)--Release n-lines garbage to field local _ - local t=P.showTime*2 + local t=self.showTime*2 for _=1,amount do - ins(P.field,1,FREEROW.get(0,true)) - ins(P.visTime,1,FREEROW.get(t)) + ins(self.field,1,FREEROW.get(0,true)) + ins(self.visTime,1,FREEROW.get(t)) for i=1,10 do - P.field[1][i]=bit.rshift(line,i-1)%2==1 and color or 0 + self.field[1][i]=bit.rshift(line,i-1)%2==1 and color or 0 end end - P.fieldBeneath=P.fieldBeneath+amount*30 - if P.cur then - P.curY=P.curY+amount - P.ghoY=P.ghoY+amount + self.fieldBeneath=self.fieldBeneath+amount*30 + if self.cur then + self.curY=self.curY+amount + self.ghoY=self.ghoY+amount end - P.garbageBeneath=P.garbageBeneath+amount - for i=1,#P.clearingRow do - P.clearingRow[i]=P.clearingRow[i]+amount + self.garbageBeneath=self.garbageBeneath+amount + for i=1,#self.clearingRow do + self.clearingRow[i]=self.clearingRow[i]+amount end - P:freshBlock("push") - for i=1,#P.lockFX do - _=P.lockFX[i] + self:freshBlock("push") + for i=1,#self.lockFX do + _=self.lockFX[i] _[2]=_[2]-30*amount--Shift 30px per line cleared end - for i=1,#P.dropFX do - _=P.dropFX[i] + for i=1,#self.dropFX do + _=self.dropFX[i] _[3],_[5]=_[3]+amount,_[5]+amount end - if #P.field>42 then P:lose()end + if #self.field>42 then self:lose()end end local invList={2,1,4,3,5,6,7} -function Player.pushLineList(P,L,mir)--Push some lines to field +function Player:pushLineList(L,mir)--Push some lines to field local l=#L - local S=P.gameEnv.skin + local S=self.gameEnv.skin for i=1,l do local r=FREEROW.get(0) if not mir then @@ -301,44 +300,44 @@ function Player.pushLineList(P,L,mir)--Push some lines to field r[j]=S[invList[L[i][11-j]]]or 0 end end - ins(P.field,1,r) - ins(P.visTime,1,FREEROW.get(20)) + ins(self.field,1,r) + ins(self.visTime,1,FREEROW.get(20)) end - P.fieldBeneath=P.fieldBeneath+30*l - P.curY=P.curY+l - P.ghoY=P.ghoY+l - P:freshBlock("push") + self.fieldBeneath=self.fieldBeneath+30*l + self.curY=self.curY+l + self.ghoY=self.ghoY+l + self:freshBlock("push") end -function Player.pushNextList(P,L,mir)--Push some nexts to nextQueue +function Player:pushNextList(L,mir)--Push some nexts to nextQueue for i=1,#L do - P:getNext(mir and invList[L[i]]or L[i]) + self:getNext(mir and invList[L[i]]or L[i]) end end -function Player.getCenterX(P) - return P.curX+P.cur.sc[2]-5.5 +function Player:getCenterX() + return self.curX+self.cur.sc[2]-5.5 end -function Player.solid(P,x,y) +function Player:solid(x,y) if x<1 or x>10 or y<1 then return true end - if y>#P.field then return false end - return P.field[y] + if y>#self.field then return false end + return self.field[y] [x]>0--to catch bug (nil[*]) end -function Player.ifoverlap(P,bk,x,y) +function Player:ifoverlap(bk,x,y) local C=#bk[1] if x<1 or x+C>11 or y<1 then return true end - if y>#P.field then return end + if y>#self.field then return end for i=1,#bk do - if P.field[y+i-1]then + if self.field[y+i-1]then for j=1,C do - if bk[i][j]and P.field[y+i-1][x+j-1]>0 then return true end + if bk[i][j]and self.field[y+i-1][x+j-1]>0 then return true end end end end end -function Player.attack(P,R,send,time,line,fromStream) +function Player:attack(R,send,time,line,fromStream) if GAME.net then - if P.type=="human"then--Local player attack others + if self.type=="human"then--Local player attack others ins(GAME.rep,GAME.frame) ins(GAME.rep, R.subID+ @@ -351,21 +350,21 @@ function Player.attack(P,R,send,time,line,fromStream) if fromStream and R.type=="human"then--Local player receiving lines ins(GAME.rep,GAME.frame) ins(GAME.rep, - P.subID+ + self.subID+ send*0x100+ time*0x10000+ line*0x100000000+ 0x1000000000000 ) - R:receive(P,send,time,line) + R:receive(self,send,time,line) end else - R:receive(P,send,time,line) + R:receive(self,send,time,line) end end -function Player.receive(P,A,send,time,line) - P.lastRecv=A - local B=P.atkBuffer +function Player:receive(A,send,time,line) + self.lastRecv=A + local B=self.atkBuffer if B.sum<26 then if send>26-B.sum then send=26-B.sum end local m,k=#B,1 @@ -383,91 +382,91 @@ function Player.receive(P,A,send,time,line) lv=min(int(send^.69),5), }--Sorted insert(by time) B.sum=B.sum+send - P.stat.recv=P.stat.recv+send - if P.sound then + self.stat.recv=self.stat.recv+send + if self.sound then SFX.play(send<4 and"blip_1"or"blip_2",min(send+1,5)*.1) end end end -function Player.freshTarget(P) - if P.atkMode==1 then - if not P.atking or not P.atking.alive or rnd()<.1 then - P:changeAtk(randomTarget(P)) +function Player:freshTarget() + if self.atkMode==1 then + if not self.atking or not self.atking.alive or rnd()<.1 then + self:changeAtk(randomTarget(self)) end - elseif P.atkMode==2 then - P:changeAtk(P~=GAME.mostBadge and GAME.mostBadge or GAME.secBadge or randomTarget(P)) - elseif P.atkMode==3 then - P:changeAtk(P~=GAME.mostDangerous and GAME.mostDangerous or GAME.secDangerous or randomTarget(P)) - elseif P.atkMode==4 then - for i=1,#P.atker do - if not P.atker[i].alive then - rem(P.atker,i) + elseif self.atkMode==2 then + self:changeAtk(self~=GAME.mostBadge and GAME.mostBadge or GAME.secBadge or randomTarget(self)) + elseif self.atkMode==3 then + self:changeAtk(self~=GAME.mostDangerous and GAME.mostDangerous or GAME.secDangerous or randomTarget(self)) + elseif self.atkMode==4 then + for i=1,#self.atker do + if not self.atker[i].alive then + rem(self.atker,i) return end end end end -function Player.changeAtkMode(P,m) - if P.atkMode==m then return end - P.atkMode=m +function Player:changeAtkMode(m) + if self.atkMode==m then return end + self.atkMode=m if m==1 then - P:changeAtk(randomTarget(P)) + self:changeAtk(randomTarget(self)) elseif m==2 or m==3 then - P:freshTarget() + self:freshTarget() elseif m==4 then - P:changeAtk() + self:changeAtk() end end -function Player.changeAtk(P,R) - -- if P.type~="human"then R=PLAYERS[1]end--1vALL mode? - if P.atking then - local K=P.atking.atker +function Player:changeAtk(R) + -- if self.type~="human"then R=PLAYERS[1]end--1vALL mode? + if self.atking then + local K=self.atking.atker for i=1,#K do - if K[i]==P then + if K[i]==self then rem(K,i) break end end end if R then - P.atking=R - ins(R.atker,P) + self.atking=R + ins(R.atker,self) else - P.atking=false + self.atking=false end end -function Player.freshBlock(P,mode)--string mode: push/move/fresh/newBlock - local ENV=P.gameEnv +function Player:freshBlock(mode)--string mode: push/move/fresh/newBlock + local ENV=self.gameEnv --Fresh ghost - if(mode=="move"or mode=="newBlock"or mode=="push")and P.cur then - local CB=P.cur.bk - P.ghoY=min(#P.field+1,P.curY) - if P._20G or ENV.sdarr==0 and P.keyPressing[7]and P.downing>ENV.sddas then - local _=P.ghoY + if(mode=="move"or mode=="newBlock"or mode=="push")and self.cur then + local CB=self.cur.bk + self.ghoY=min(#self.field+1,self.curY) + if self._20G or ENV.sdarr==0 and self.keyPressing[7]and self.downing>ENV.sddas then + local _=self.ghoY --Move ghost to bottom - while not P:ifoverlap(CB,P.curX,P.ghoY-1)do - P.ghoY=P.ghoY-1 + while not self:ifoverlap(CB,self.curX,self.ghoY-1)do + self.ghoY=self.ghoY-1 end --Cancel spinLast - if _~=P.ghoY then - P.spinLast=false + if _~=self.ghoY then + self.spinLast=false end --Create FX if dropped - if P.curY>P.ghoY then - if ENV.dropFX and ENV.block and P.curY-P.ghoY-#CB>-1 then - P:createDropFX(P.curX,P.curY-1,#CB[1],P.curY-P.ghoY-#CB+1) + if self.curY>self.ghoY then + if ENV.dropFX and ENV.block and self.curY-self.ghoY-#CB>-1 then + self:createDropFX(self.curX,self.curY-1,#CB[1],self.curY-self.ghoY-#CB+1) end if ENV.shakeFX then - P.fieldOff.vy=ENV.shakeFX*.5 + self.fieldOff.vy=ENV.shakeFX*.5 end - P.curY=P.ghoY + self.curY=self.ghoY end else - while not P:ifoverlap(CB,P.curX,P.ghoY-1)do - P.ghoY=P.ghoY-1 + while not self:ifoverlap(CB,self.curX,self.ghoY-1)do + self.ghoY=self.ghoY-1 end end end @@ -476,43 +475,43 @@ function Player.freshBlock(P,mode)--string mode: push/move/fresh/newBlock if mode=="move"or mode=="newBlock"or mode=="fresh"then local d0,l0=ENV.drop,ENV.lock if ENV.easyFresh then - if P.lockDelay0 then + if self.lockDelay0 then if mode~="newBlock"then - P.freshTime=P.freshTime-1 + self.freshTime=self.freshTime-1 end - P.lockDelay=l0 - P.dropDelay=d0 + self.lockDelay=l0 + self.dropDelay=d0 end - if P.curY+P.cur.sc[1]0 then - P.freshTime=P.freshTime-1 - P.dropDelay=d0 - P.lockDelay=l0 + if self.curY+self.cur.sc[1]0 then + self.freshTime=self.freshTime-1 + self.dropDelay=d0 + self.lockDelay=l0 end end end end end -function Player.lock(P) - local dest=P.AI_dest +function Player:lock() + local dest=self.AI_dest local has_dest=dest~=nil - local CB=P.cur.bk + local CB=self.cur.bk for i=1,#CB do - local y=P.curY+i-1 - if not P.field[y]then P.field[y],P.visTime[y]=FREEROW.get(0),FREEROW.get(0)end + local y=self.curY+i-1 + if not self.field[y]then self.field[y],self.visTime[y]=FREEROW.get(0),FREEROW.get(0)end for j=1,#CB[1]do if CB[i][j]then - P.field[y][P.curX+j-1]=P.cur.color - P.visTime[y][P.curX+j-1]=P.showTime + self.field[y][self.curX+j-1]=self.cur.color + self.visTime[y][self.curX+j-1]=self.showTime if dest then - local x=P.curX+j-1 + local x=self.curX+j-1 for k=1,#dest,2 do if x==dest[k]+1 and y==dest[k+1]+1 then rem(dest,k)rem(dest,k) @@ -525,142 +524,142 @@ function Player.lock(P) end end end - if has_dest and not dest and P.AI_mode=="CC"and P.AI_bot then - CC.updateField(P) + if has_dest and not dest and self.AI_mode=="CC"and self.AI_bot then + CC.updateField(self) end end local spawnSFX_name={}for i=1,7 do spawnSFX_name[i]="spawn_"..i end -function Player.resetBlock(P)--Reset Block's position and execute I*S - local B=P.cur.bk - P.curX=int(6-#B[1]*.5) - local y=int(P.gameEnv.fieldH+1-modf(P.cur.sc[1]))+ceil(P.fieldBeneath/30) - P.curY=y - P.minY=y+P.cur.sc[1] +function Player:resetBlock()--Reset Block's position and execute I*S + local B=self.cur.bk + self.curX=int(6-#B[1]*.5) + local y=int(self.gameEnv.fieldH+1-modf(self.cur.sc[1]))+ceil(self.fieldBeneath/30) + self.curY=y + self.minY=y+self.cur.sc[1] - local _=P.keyPressing + local _=self.keyPressing --IMS - if P.gameEnv.ims and(_[1]and P.movDir==-1 or _[2]and P.movDir==1)and P.moving>=P.gameEnv.das then - local x=P.curX+P.movDir - if not P:ifoverlap(B,x,y)then - P.curX=x + if self.gameEnv.ims and(_[1]and self.movDir==-1 or _[2]and self.movDir==1)and self.moving>=self.gameEnv.das then + local x=self.curX+self.movDir + if not self:ifoverlap(B,x,y)then + self.curX=x end end --IRS - if P.gameEnv.irs then + if self.gameEnv.irs then if _[5]then - P:spin(2,true) + self:spin(2,true) else if _[3]then if _[4]then - P:spin(2,true) + self:spin(2,true) else - P:spin(1,true) + self:spin(1,true) end elseif _[4]then - P:spin(3,true) + self:spin(3,true) end end end --DAS cut - if P.gameEnv.dascut>0 then - P.moving=P.moving-(P.moving>0 and 1 or -1)*P.gameEnv.dascut + if self.gameEnv.dascut>0 then + self.moving=self.moving-(self.moving>0 and 1 or -1)*self.gameEnv.dascut end --Spawn SFX - if P.sound and P.cur.id<8 then - SFX.fplay(spawnSFX_name[P.cur.id],SETTING.sfx_spawn) + if self.sound and self.cur.id<8 then + SFX.fplay(spawnSFX_name[self.cur.id],SETTING.sfx_spawn) end end -function Player.spin(P,d,ifpre) - local kickData=P.RS[P.cur.id] +function Player:spin(d,ifpre) + local kickData=self.RS[self.cur.id] if type(kickData)=="table"then - local idir=(P.cur.dir+d)%4 - kickData=kickData[P.cur.dir*10+idir] + local idir=(self.cur.dir+d)%4 + kickData=kickData[self.cur.dir*10+idir] if not kickData then - P:freshBlock("move") - SFX.play(ifpre and"prerotate"or"rotate",nil,P:getCenterX()*.15) + self:freshBlock("move") + SFX.play(ifpre and"prerotate"or"rotate",nil,self:getCenterX()*.15) return end - local icb=BLOCKS[P.cur.id][idir] - local isc=SCS[P.cur.id][idir] - local ix,iy=P.curX+P.cur.sc[2]-isc[2],P.curY+P.cur.sc[1]-isc[1] + local icb=BLOCKS[self.cur.id][idir] + local isc=SCS[self.cur.id][idir] + local ix,iy=self.curX+self.cur.sc[2]-isc[2],self.curY+self.cur.sc[1]-isc[1] for test=1,#kickData do local x,y=ix+kickData[test][1],iy+kickData[test][2] - if not P:ifoverlap(icb,x,y)and(P.freshTime>=0 or kickData[test][2]<0)then + if not self:ifoverlap(icb,x,y)and(self.freshTime>=0 or kickData[test][2]<0)then ix,iy=x,y - if P.gameEnv.moveFX and P.gameEnv.block then - P:createMoveFX() + if self.gameEnv.moveFX and self.gameEnv.block then + self:createMoveFX() end - P.curX,P.curY,P.cur.dir=ix,iy,idir - P.cur.sc,P.cur.bk=isc,icb - P.spinLast=test==2 and 0 or 1 + self.curX,self.curY,self.cur.dir=ix,iy,idir + self.cur.sc,self.cur.bk=isc,icb + self.spinLast=test==2 and 0 or 1 - local t=P.freshTime + local t=self.freshTime if not ifpre then - P:freshBlock("move") + self:freshBlock("move") end - if kickData[test][2]>0 and P.freshTime~=t and P.curY~=P.imgY then - P.freshTime=P.freshTime-1 + if kickData[test][2]>0 and self.freshTime~=t and self.curY~=self.imgY then + self.freshTime=self.freshTime-1 end - if P.sound then + if self.sound then local sfx if ifpre then sfx="prerotate" - elseif P:ifoverlap(icb,ix,iy+1)and P:ifoverlap(icb,ix-1,iy)and P:ifoverlap(icb,ix+1,iy)then + elseif self:ifoverlap(icb,ix,iy+1)and self:ifoverlap(icb,ix-1,iy)and self:ifoverlap(icb,ix+1,iy)then sfx="rotatekick" - if P.gameEnv.shakeFX then + if self.gameEnv.shakeFX then if d==1 or d==3 then - P.fieldOff.va=P.fieldOff.va+(2-d)*P.gameEnv.shakeFX*6e-3 + self.fieldOff.va=self.fieldOff.va+(2-d)*self.gameEnv.shakeFX*6e-3 else - P.fieldOff.va=P.fieldOff.va+P:getCenterX()*P.gameEnv.shakeFX*3e-3 + self.fieldOff.va=self.fieldOff.va+self:getCenterX()*self.gameEnv.shakeFX*3e-3 end end else sfx="rotate" end - SFX.play(sfx,nil,P:getCenterX()*.15) + SFX.play(sfx,nil,self:getCenterX()*.15) end - P.stat.rotate=P.stat.rotate+1 + self.stat.rotate=self.stat.rotate+1 return end end elseif kickData then - kickData(P,d) + kickData(self,d) else - P:freshBlock("move") - SFX.play(ifpre and"prerotate"or"rotate",nil,P:getCenterX()*.15) + self:freshBlock("move") + SFX.play(ifpre and"prerotate"or"rotate",nil,self:getCenterX()*.15) end end local phyHoldKickX={ [true]={0,-1,1},--X==?.0 tests [false]={-.5,.5},--X==?.5 tests } -function Player.hold(P,ifpre) - local ENV=P.gameEnv - if P.holdTime>0 and(ifpre or P.waiting==-1)then - if #P.holdQueue0 and(ifpre or self.waiting==-1)then + if #self.holdQueue ::BREAK_success:: - P.spinLast=false - P.spinSeq=0 - local hb=P:getBlock(C.id) + self.spinLast=false + self.spinSeq=0 + local hb=self:getBlock(C.id) hb.name=C.name hb.color=C.color - ins(P.holdQueue,hb) - P.cur=rem(P.holdQueue,1) - P.curX,P.curY=x,y + ins(self.holdQueue,hb) + self.cur=rem(self.holdQueue,1) + self.curX,self.curY=x,y else--Normal hold - P.spinLast=false - P.spinSeq=0 + self.spinLast=false + self.spinSeq=0 if C then - local hb=P:getBlock(C.id) + local hb=self:getBlock(C.id) hb.color=C.color hb.name=C.name - ins(P.holdQueue,hb) + ins(self.holdQueue,hb) end - P.cur=rem(P.holdQueue,1) + self.cur=rem(self.holdQueue,1) - P:resetBlock() + self:resetBlock() end - P:freshBlock("move") - P.dropDelay=ENV.drop - P.lockDelay=ENV.lock - if P:ifoverlap(P.cur.bk,P.curX,P.curY)then - P:lock() - P:lose() + self:freshBlock("move") + self.dropDelay=ENV.drop + self.lockDelay=ENV.lock + if self:ifoverlap(self.cur.bk,self.curX,self.curY)then + self:lock() + self:lose() end end - P.freshTime=int(min(P.freshTime+ENV.freshLimit*.25,ENV.freshLimit*((P.holdTime+1)/ENV.holdCount))) + self.freshTime=int(min(self.freshTime+ENV.freshLimit*.25,ENV.freshLimit*((self.holdTime+1)/ENV.holdCount))) if not ENV.infHold then - P.holdTime=P.holdTime-1 + self.holdTime=self.holdTime-1 end - if P.sound then + if self.sound then SFX.play(ifpre and"prehold"or"hold") end - if P.AI_mode=="CC"then - local next=P.nextQueue[P.AIdata.nextCount] + if self.AI_mode=="CC"then + local next=self.nextQueue[self.AIdata.nextCount] if next then - CC.addNext(P.AI_bot,next.id) + CC.addNext(self.AI_bot,next.id) end end - P.stat.hold=P.stat.hold+1 + self.stat.hold=self.stat.hold+1 end end -function Player.getBlock(P,n)--Get a block(id=n) object - local E=P.gameEnv +function Player:getBlock(n)--Get a block(id=n) object + local E=self.gameEnv local dir=E.face[n] return{ id=n, @@ -743,10 +742,10 @@ function Player.getBlock(P,n)--Get a block(id=n) object color=E.bone and 17 or E.skin[n], } end -function Player.getNext(P,n)--Push a block(id=n) to nextQueue - local E=P.gameEnv +function Player:getNext(n)--Push a block(id=n) to nextQueue + local E=self.gameEnv local dir=E.face[n] - ins(P.nextQueue,{ + ins(self.nextQueue,{ id=n, bk=BLOCKS[n][dir], sc=SCS[n][dir], @@ -755,60 +754,60 @@ function Player.getNext(P,n)--Push a block(id=n) to nextQueue color=E.bone and 17 or E.skin[n], }) end -function Player.popNext(P,ifhold)--Pop nextQueue to hand +function Player:popNext(ifhold)--Pop nextQueue to hand if not ifhold then - P.holdTime=min(P.holdTime+1,P.gameEnv.holdCount) + self.holdTime=min(self.holdTime+1,self.gameEnv.holdCount) end - P.spinLast=false - P.spinSeq=0 - P.ctrlCount=0 + self.spinLast=false + self.spinSeq=0 + self.ctrlCount=0 - P.cur=rem(P.nextQueue,1) - assert(resume(P.newNext)) - if P.cur then - P.pieceCount=P.pieceCount+1 - if P.AI_mode=="CC"then - local next=P.nextQueue[P.AIdata.next] + self.cur=rem(self.nextQueue,1) + self.newNext() + if self.cur then + self.pieceCount=self.pieceCount+1 + if self.AI_mode=="CC"then + local next=self.nextQueue[self.AIdata.next] if next then - CC.addNext(P.AI_bot,next.id) + CC.addNext(self.AI_bot,next.id) end end - local _=P.keyPressing + local _=self.keyPressing --IHS - if not ifhold and _[8]and P.gameEnv.ihs then - P:hold(true) + if not ifhold and _[8]and self.gameEnv.ihs then + self:hold(true) _[8]=false else - P:resetBlock() + self:resetBlock() end - P.dropDelay=P.gameEnv.drop - P.lockDelay=P.gameEnv.lock - P.freshTime=P.gameEnv.freshLimit + self.dropDelay=self.gameEnv.drop + self.lockDelay=self.gameEnv.lock + self.freshTime=self.gameEnv.freshLimit - if P.cur then - if P:ifoverlap(P.cur.bk,P.curX,P.curY)then - P:lock() - P:lose() + if self.cur then + if self:ifoverlap(self.cur.bk,self.curX,self.curY)then + self:lock() + self:lose() end - P:freshBlock("newBlock") + self:freshBlock("newBlock") end --IHdS if _[6]and not ifhold then - P.act_hardDrop(P) + self.act_hardDrop(self) _[6]=false end else - P:hold() + self:hold() end end -function Player.cancel(P,N)--Cancel Garbage +function Player:cancel(N)--Cancel Garbage local off=0--Lines offseted - local bf=P.atkBuffer + local bf=self.atkBuffer for i=1,#bf do if bf.sum==0 or N==0 then break end local A=bf[i] @@ -826,7 +825,7 @@ function Player.cancel(P,N)--Cancel Garbage end return off end -do--Player.drop(P)--Place piece +do--Player.drop(self)--Place piece local clearSCR={80,200,400}--Techrash:1K; B2Bmul:1.3/1.8 local spinSCR={ {200,750,1300,2000},--Z @@ -879,7 +878,7 @@ do--Player.drop(P)--Place piece 1,2 },--Z5 8,--S5 - 3,--P + 3,--self 3,--Q { {1,2,1,0,1,2,2,1}, @@ -950,17 +949,17 @@ do--Player.drop(P)--Place piece end end - function Player.drop(P) + function Player:drop() local _ local CHN=VOC.getFreeChannel() - P.dropTime[11]=ins(P.dropTime,1,GAME.frame)--Update speed dial - local ENV=P.gameEnv - local STAT=P.stat - local piece=P.lastPiece + self.dropTime[11]=ins(self.dropTime,1,GAME.frame)--Update speed dial + local ENV=self.gameEnv + local STAT=self.stat + local piece=self.lastPiece local finish - local cmb=P.combo - local C,CB,CX,CY=P.cur,P.cur.bk,P.curX,P.curY + local cmb=self.combo + local C,CB,CX,CY=self.cur,self.cur.bk,self.curX,self.curY local clear--If clear with no line fall local cc,gbcc=0,0--Row/garbage-row cleared,full-part local atk,exblock=0,0--Attack & extra defense @@ -969,44 +968,44 @@ do--Player.drop(P)--Place piece local dospin,mini=0 piece.id,piece.name=C.id,C.name - P.waiting=ENV.wait + self.waiting=ENV.wait --Tri-corner spin check - if P.spinLast then + if self.spinLast then if C.id<6 then - local x,y=CX+P.cur.sc[2],CY+P.cur.sc[1] + local x,y=CX+self.cur.sc[2],CY+self.cur.sc[1] local c=0 - if P:solid(x-1,y+1)then c=c+1 end - if P:solid(x+1,y+1)then c=c+1 end + if self:solid(x-1,y+1)then c=c+1 end + if self:solid(x+1,y+1)then c=c+1 end if c~=0 then - if P:solid(x-1,y-1)then c=c+1 end - if P:solid(x+1,y-1)then c=c+1 end + if self:solid(x-1,y-1)then c=c+1 end + if self:solid(x+1,y-1)then c=c+1 end if c>2 then dospin=dospin+2 end end end end --Immovable spin check - if P:ifoverlap(CB,CX,CY+1)and P:ifoverlap(CB,CX-1,CY)and P:ifoverlap(CB,CX+1,CY)then + if self:ifoverlap(CB,CX,CY+1)and self:ifoverlap(CB,CX-1,CY)and self:ifoverlap(CB,CX+1,CY)then dospin=dospin+2 end --Lock block to field - P:lock() + self:lock() --Clear list of cleared-rows - if P.clearedRow[1]then P.clearedRow={}end + if self.clearedRow[1]then self.clearedRow={}end --Check line clear for i=1,#CB do local h=CY+i-2 --Bomb trigger - if h>0 and P.field[h]and P.clearedRow[cc]~=h then + if h>0 and self.field[h]and self.clearedRow[cc]~=h then for x=1,#CB[1]do - if CB[i][x]and P.field[h][CX+x-1]==19 then + if CB[i][x]and self.field[h][CX+x-1]==19 then cc=cc+1 - P.clearingRow[cc]=h-cc+1 - P.clearedRow[cc]=h + self.clearingRow[cc]=h-cc+1 + self.clearedRow[cc]=h break end end @@ -1015,13 +1014,13 @@ do--Player.drop(P)--Place piece h=h+1 --Row filled for x=1,10 do - if P.field[h][x]<=0 then + if self.field[h][x]<=0 then goto CONTINUE_notFull end end cc=cc+1 - P.clearingRow[cc]=h-cc+1 - P.clearedRow[cc]=h + self.clearingRow[cc]=h-cc+1 + self.clearedRow[cc]=h ::CONTINUE_notFull:: end @@ -1029,10 +1028,10 @@ do--Player.drop(P)--Place piece if cc>0 and ENV.clearFX then local t=7-ENV.clearFX*1 for i=1,cc do - local y=P.clearedRow[i] - P:createClearingFX(y,t) + local y=self.clearedRow[i] + self:createClearingFX(y,t) if ENV.splashFX then - P:createSplashFX(y) + self:createSplashFX(y) end end end @@ -1040,12 +1039,12 @@ do--Player.drop(P)--Place piece --Create locking FX if ENV.lockFX then if cc==0 then - P:createLockFX() + self:createLockFX() else - _=#P.lockFX + _=#self.lockFX if _>0 then for _=1,_ do - rem(P.lockFX) + rem(self.lockFX) end end end @@ -1054,7 +1053,7 @@ do--Player.drop(P)--Place piece --Final spin check if dospin>0 then if cc>0 then - dospin=dospin+(P.spinLast or 0) + dospin=dospin+(self.spinLast or 0) if dospin<3 then mini=C.id<6 and cc<#CB end @@ -1077,8 +1076,8 @@ do--Player.drop(P)--Place piece local testX=CX+x-1--Optimize --Test the whole column of field to find roof - for testY=CY+y,#P.field do - if P:solid(testX,testY)then + for testY=CY+y,#self.field do + if self:solid(testX,testY)then finesse=true goto BERAK_roofFound end @@ -1090,24 +1089,24 @@ do--Player.drop(P)--Place piece --Remove rows need to be cleared if cc>0 then for i=cc,1,-1 do - _=P.clearedRow[i] - if P.field[_].garbage then - P.garbageBeneath=P.garbageBeneath-1 + _=self.clearedRow[i] + if self.field[_].garbage then + self.garbageBeneath=self.garbageBeneath-1 gbcc=gbcc+1 end - FREEROW.discard(rem(P.field,_)) - FREEROW.discard(rem(P.visTime,_)) + FREEROW.discard(rem(self.field,_)) + FREEROW.discard(rem(self.visTime,_)) end end --Cancel no-sense clearing FX - _=#P.clearingRow - while _>0 and P.clearingRow[_]>#P.field do - P.clearingRow[_]=nil + _=#self.clearingRow + while _>0 and self.clearingRow[_]>#self.field do + self.clearingRow[_]=nil _=_-1 end - if P.clearingRow[1]then - P.falling=ENV.fall + if self.clearingRow[1]then + self.falling=ENV.fall elseif cc>=#C.bk then clear=true end @@ -1115,9 +1114,9 @@ do--Player.drop(P)--Place piece --Finesse check (control) local finePts if not finesse then - if dospin then P.ctrlCount=P.ctrlCount-2 end--Allow 2 more step for roof-less spin + if dospin then self.ctrlCount=self.ctrlCount-2 end--Allow 2 more step for roof-less spin local id=C.id - local d=P.ctrlCount-finesseList[id][P.cur.dir+1][CX] + local d=self.ctrlCount-finesseList[id][self.cur.dir+1][CX] finePts=d<=0 and 5 or max(3-d,0) else finePts=5 @@ -1130,25 +1129,25 @@ do--Player.drop(P)--Place piece if ENV.fineKill then finish=true end - if P.sound then + if self.sound then if ENV.fineKill then SFX.play("finesseError_long",.6) elseif ENV.fine then SFX.play("finesseError",.8) else - SFX.play("lock",nil,P:getCenterX()*.15) + SFX.play("lock",nil,self:getCenterX()*.15) end end - elseif P.sound then - SFX.play("lock",nil,P:getCenterX()*.15) + elseif self.sound then + SFX.play("lock",nil,self:getCenterX()*.15) end if finePts<=1 then - P.finesseCombo=0 + self.finesseCombo=0 else - P.finesseCombo=P.finesseCombo+1 - if P.finesseCombo>2 then - P.finesseComboTime=12 + self.finesseCombo=self.finesseCombo+1 + if self.finesseCombo>2 then + self.finesseComboTime=12 end end @@ -1159,88 +1158,88 @@ do--Player.drop(P)--Place piece cmb=cmb+1 if dospin then cscore=(spinSCR[C.name]or spinSCR[8])[cc] - if P.b2b>800 then - P:showText(text.b3b..text.block[C.name]..text.spin.." "..text.clear[cc],0,-30,35,"stretch") + if self.b2b>800 then + self:showText(text.b3b..text.block[C.name]..text.spin.." "..text.clear[cc],0,-30,35,"stretch") atk=b2bATK[cc]+cc*.5 exblock=exblock+1 cscore=cscore*2 STAT.b3b=STAT.b3b+1 - if P.sound then + if self.sound then VOC.play("b3b",CHN) end - elseif P.b2b>=50 then - P:showText(text.b2b..text.block[C.name]..text.spin.." "..text.clear[cc],0,-30,35,"spin") + elseif self.b2b>=50 then + self:showText(text.b2b..text.block[C.name]..text.spin.." "..text.clear[cc],0,-30,35,"spin") atk=b2bATK[cc] cscore=cscore*1.2 STAT.b2b=STAT.b2b+1 - if P.sound then + if self.sound then VOC.play("b2b",CHN) end else - P:showText(text.block[C.name]..text.spin.." "..text.clear[cc],0,-30,45,"spin") + self:showText(text.block[C.name]..text.spin.." "..text.clear[cc],0,-30,45,"spin") atk=2*cc end sendTime=20+atk*20 if mini then - P:showText(text.mini,0,-80,35,"appear") + self:showText(text.mini,0,-80,35,"appear") atk=atk*.25 sendTime=sendTime+60 cscore=cscore*.5 - P.b2b=P.b2b+b2bPoint[cc]*.5 - if P.sound then + self.b2b=self.b2b+b2bPoint[cc]*.5 + if self.sound then VOC.play("mini",CHN) end else - P.b2b=P.b2b+b2bPoint[cc] + self.b2b=self.b2b+b2bPoint[cc] end piece.mini=mini piece.special=true - if P.sound then + if self.sound then SFX.play(spinSFX[cc]or"spin_3") VOC.play(spinVoice[C.name],CHN) end elseif cc>=4 then cscore=cc==4 and 1000 or cc==5 and 1500 or 2000 - if P.b2b>800 then - P:showText(text.b3b..text.clear[cc],0,-30,50,"fly") + if self.b2b>800 then + self:showText(text.b3b..text.clear[cc],0,-30,50,"fly") atk=4*cc-10 sendTime=100 exblock=exblock+1 cscore=cscore*1.8 STAT.b3b=STAT.b3b+1 - if P.sound then + if self.sound then VOC.play("b3b",CHN) end - elseif P.b2b>=50 then - P:showText(text.b2b..text.clear[cc],0,-30,50,"drive") + elseif self.b2b>=50 then + self:showText(text.b2b..text.clear[cc],0,-30,50,"drive") sendTime=80 atk=3*cc-7 cscore=cscore*1.3 STAT.b2b=STAT.b2b+1 - if P.sound then + if self.sound then VOC.play("b2b",CHN) end else - P:showText(text.clear[cc],0,-30,70,"stretch") + self:showText(text.clear[cc],0,-30,70,"stretch") sendTime=60 atk=2*cc-4 end - P.b2b=P.b2b+cc*100-300 + self.b2b=self.b2b+cc*100-300 piece.special=true else piece.special=false end - if P.sound then + if self.sound then VOC.play(clearVoice[cc],CHN) end --Normal clear,reduce B2B point if not piece.special then - P.b2b=max(P.b2b-250,0) - if P.b2b<50 and ENV.b2bKill then + self.b2b=max(self.b2b-250,0) + if self.b2b<50 and ENV.b2bKill then finish=true end - P:showText(text.clear[cc],0,-30,35,"appear",(8-cc)*.3) + self:showText(text.clear[cc],0,-30,35,"appear",(8-cc)*.3) atk=cc-.5 sendTime=20+int(atk*20) cscore=cscore+clearSCR[cc] @@ -1253,37 +1252,37 @@ do--Player.drop(P)--Place piece if cmb>=3 then atk=atk+1 end - P:showText(text.cmb[min(cmb,21)],0,25,15+min(cmb,15)*5,cmb<10 and"appear"or"flicker") + self:showText(text.cmb[min(cmb,21)],0,25,15+min(cmb,15)*5,cmb<10 and"appear"or"flicker") cscore=cscore+min(50*cmb,500)*(2*cc-1) end --PC/HPC - if clear and #P.field==0 then - P:showText(text.PC,0,-80,50,"flicker") + if clear and #self.field==0 then + self:showText(text.PC,0,-80,50,"flicker") atk=max(atk,min(8+STAT.pc*2,16)) exblock=exblock+2 sendTime=sendTime+120 if STAT.row+cc>4 then - P.b2b=1000 + self.b2b=1000 cscore=cscore+300*min(6+STAT.pc,10) else cscore=cscore+626 end STAT.pc=STAT.pc+1 - if P.sound then + if self.sound then SFX.play("clear") VOC.play("perfect_clear",CHN) end piece.pc=true piece.special=true - elseif clear and(cc>1 or #P.field==P.garbageBeneath)then - P:showText(text.HPC,0,-80,50,"fly") + elseif clear and(cc>1 or #self.field==self.garbageBeneath)then + self:showText(text.HPC,0,-80,50,"fly") atk=atk+2 exblock=exblock+2 sendTime=sendTime+60 cscore=cscore+626 STAT.hpc=STAT.hpc+1 - if P.sound then + if self.sound then SFX.play("clear") VOC.play("half_clear",CHN) end @@ -1291,11 +1290,11 @@ do--Player.drop(P)--Place piece piece.special=true end - if P.b2b>1000 then P.b2b=1000 end + if self.b2b>1000 then self.b2b=1000 end --Bonus atk/def when focused if GAME.modeEnv.royaleMode then - local i=min(#P.atker,9) + local i=min(#self.atker,9) if i>1 then atk=atk+reAtk[i] exblock=exblock+reDef[i] @@ -1303,52 +1302,52 @@ do--Player.drop(P)--Place piece end --Send Lines - atk=int(atk*(1+P.strength*.25))--Badge Buff + atk=int(atk*(1+self.strength*.25))--Badge Buff send=atk if exblock>0 then - exblock=int(exblock*(1+P.strength*.25))--Badge Buff - P:showText("+"..exblock,0,53,20,"fly") - off=off+P:cancel(exblock) + exblock=int(exblock*(1+self.strength*.25))--Badge Buff + self:showText("+"..exblock,0,53,20,"fly") + off=off+self:cancel(exblock) end if send>=1 then - P:showText(send,0,80,35,"zoomout") - _=P:cancel(send) + self:showText(send,0,80,35,"zoomout") + _=self:cancel(send) send=send-_ off=off+_ if send>0 then local T if GAME.modeEnv.royaleMode then - if P.atkMode==4 then - local M=#P.atker + if self.atkMode==4 then + local M=#self.atker if M>0 then for i=1,M do - P:attack(P.atker[i],send,sendTime,generateLine(P:RND(10))) + self:attack(self.atker[i],send,sendTime,generateLine(self:RND(10))) if SETTING.atkFX>0 then - P:createBeam(P.atker[i],send,C.color) + self:createBeam(self.atker[i],send,C.color) end end else - T=randomTarget(P) + T=randomTarget(self) end else - T=P.atking - P:freshTarget() + T=self.atking + self:freshTarget() end - elseif #PLAYERS.alive>1 then - T=randomTarget(P) + elseif #PLY_ALIVE>1 then + T=randomTarget(self) end if T then - P:attack(T,send,sendTime,generateLine(P:RND(10))) + self:attack(T,send,sendTime,generateLine(self:RND(10))) if SETTING.atkFX>0 then - P:createBeam(T,send,C.color) + self:createBeam(T,send,C.color) end end end - if P.sound and send>3 then SFX.play("emit",min(send,7)*.1)end + if self.sound and send>3 then SFX.play("emit",min(send,7)*.1)end end --SFX & Vibrate - if P.sound then + if self.sound then SFX.play(clearSFX[cc]or"clear_4") SFX.play(renSFX[min(cmb,11)]) if cmb>14 then SFX.play("ren_mega",(cmb-10)*.1)end @@ -1359,25 +1358,25 @@ do--Player.drop(P)--Place piece --Spin bonus if dospin then - P:showText(text.block[C.name]..text.spin,0,-30,45,"appear") - P.b2b=P.b2b+20 - if P.sound then + self:showText(text.block[C.name]..text.spin,0,-30,45,"appear") + self.b2b=self.b2b+20 + if self.sound then SFX.play("spin_0") VOC.play(spinVoice[C.name],CHN) end cscore=30 end - if P.b2b>800 then - P.b2b=max(P.b2b-40,800) + if self.b2b>800 then + self.b2b=max(self.b2b-40,800) end - P:garbageRelease() + self:garbageRelease() end - P.combo=cmb + self.combo=cmb --DropSpeed bonus - if P._20G then + if self._20G then cscore=cscore*2 elseif ENV.drop<1 then cscore=cscore*1.5 @@ -1386,13 +1385,13 @@ do--Player.drop(P)--Place piece end --Speed bonus - if P.dropSpeed>60 then - cscore=cscore*(.9+P.dropSpeed/600) + if self.dropSpeed>60 then + cscore=cscore*(.9+self.dropSpeed/600) end cscore=int(cscore) if ENV.score then - P:showText(cscore,(P.curX+P.cur.sc[2]-5.5)*30,(10-P.curY-P.cur.sc[1])*30+P.fieldBeneath+P.fieldUp,40-600/(cscore+20),"score",2) + self:showText(cscore,(self.curX+self.cur.sc[2]-5.5)*30,(10-self.curY-self.cur.sc[1])*30+self.fieldBeneath+self.fieldUp,40-600/(cscore+20),"score",2) end piece.row,piece.dig=cc,gbcc @@ -1401,8 +1400,8 @@ do--Player.drop(P)--Place piece piece.off,piece.send=off,send --Check clearing task - if cc>0 and P.curMission then - local t=ENV.mission[P.curMission] + if cc>0 and self.curMission then + local t=ENV.mission[self.curMission] local success if t<5 then if piece.row==t and not piece.spin then @@ -1422,14 +1421,14 @@ do--Player.drop(P)--Place piece end end if success then - P.curMission=P.curMission+1 + self.curMission=self.curMission+1 SFX.play("reach") - if P.curMission>#ENV.mission then - P.curMission=false + if self.curMission>#ENV.mission then + self.curMission=false if not finish then finish="finish"end end elseif ENV.missionKill then - P:showText(text.missionFailed,0,140,40,"flicker",.5) + self:showText(text.missionFailed,0,140,40,"flicker",.5) SFX.play("finesseError_long",.6) finish=true end @@ -1439,8 +1438,8 @@ do--Player.drop(P)--Place piece STAT.score=STAT.score+cscore STAT.piece=STAT.piece+1 STAT.row=STAT.row+cc - STAT.maxFinesseCombo=max(STAT.maxFinesseCombo,P.finesseCombo) - STAT.maxCombo=max(STAT.maxCombo,P.combo) + STAT.maxFinesseCombo=max(STAT.maxFinesseCombo,self.finesseCombo) + STAT.maxCombo=max(STAT.maxCombo,self.combo) if atk>0 then STAT.atk=STAT.atk+atk if send>0 then @@ -1466,55 +1465,55 @@ do--Player.drop(P)--Place piece end if finish then - if finish==true then P:lose()end - _=ENV.dropPiece if _ then _(P)end - if finish then P:win(finish)end + if finish==true then self:lose()end + _=ENV.dropPiece if _ then _(self)end + if finish then self:win(finish)end else - _=ENV.dropPiece if _ then _(P)end + _=ENV.dropPiece if _ then _(self)end end end end -function Player.loadAI(P,data)--Load AI params +function Player:loadAI(data)--Load AI params if not CC then data.type="9S" data.delta=int(data.delta*.3) end - P.AI_mode=data.type - P.AI_keys={} - P.AI_delay=min(int(P.gameEnv.drop*.8),data.delta*rnd()*4) - P.AI_delay0=data.delta - P.AIdata={ + self.AI_mode=data.type + self.AI_keys={} + self.AI_delay=min(int(self.gameEnv.drop*.8),data.delta*rnd()*4) + self.AI_delay0=data.delta + self.AIdata={ type=data.type, delay=data.delay, delta=data.delta, next=data.next, hold=data.hold, - _20G=P._20G, + _20G=self._20G, bag=data.bag, node=data.node, } - if P.AI_mode=="CC"then - P:setRS("SRS") + if self.AI_mode=="CC"then + self:setRS("SRS") local opt,wei=CC.getConf() CC.fastWeights(wei) - CC.setHold(opt,P.AIdata.hold) - CC.set20G(opt,P.AIdata._20G) - CC.setBag(opt,P.AIdata.bag=="bag") - CC.setNode(opt,P.AIdata.node) - P.AI_bot=CC.new(opt,wei) + CC.setHold(opt,self.AIdata.hold) + CC.set20G(opt,self.AIdata._20G) + CC.setBag(opt,self.AIdata.bag=="bag") + CC.setNode(opt,self.AIdata.node) + self.AI_bot=CC.new(opt,wei) CC.free(opt)CC.free(wei) - for i=1,P.AIdata.next do - CC.addNext(P.AI_bot,P.nextQueue[i].id) + for i=1,self.AIdata.next do + CC.addNext(self.AI_bot,self.nextQueue[i].id) end - if P.gameEnv.holdCount and P.gameEnv.holdCount>1 then - P:setHold(1) + if self.gameEnv.holdCount and self.gameEnv.holdCount>1 then + self:setHold(1) end else - P:setRS("TRS") + self:setRS("TRS") end - P.AI_thread=coroutine.create(AIFUNC[data.type]) - coroutine.resume(P.AI_thread,P,P.AI_keys) + self.AI_thread=coroutine.wrap(AIFUNC[data.type]) + self.AI_thread(self,self.AI_keys) end ---------------------------------------------------- @@ -1547,49 +1546,49 @@ local function tick_throwBadge(ifAI,sender,time) if time<=0 then return end end end -local function tick_finish(P) +local function tick_finish(self) while true do yield() - P.endCounter=P.endCounter+1 - if P.endCounter<40 then + self.endCounter=self.endCounter+1 + if self.endCounter<40 then --Make field visible - for j=1,#P.field do for i=1,10 do - if P.visTime[j][i]<20 then P.visTime[j][i]=P.visTime[j][i]+.5 end + for j=1,#self.field do for i=1,10 do + if self.visTime[j][i]<20 then self.visTime[j][i]=self.visTime[j][i]+.5 end end end - elseif P.endCounter==60 then + elseif self.endCounter==60 then return end end end -local function tick_lose(P) +local function tick_lose(self) while true do yield() - P.endCounter=P.endCounter+1 - if P.endCounter<40 then + self.endCounter=self.endCounter+1 + if self.endCounter<40 then --Make field visible - for j=1,#P.field do for i=1,10 do - if P.visTime[j][i]<20 then P.visTime[j][i]=P.visTime[j][i]+.5 end + for j=1,#self.field do for i=1,10 do + if self.visTime[j][i]<20 then self.visTime[j][i]=self.visTime[j][i]+.5 end end end - elseif P.endCounter>80 then - for i=1,#P.field do + elseif self.endCounter>80 then + for i=1,#self.field do for j=1,10 do - if P.visTime[i][j]>0 then - P.visTime[i][j]=P.visTime[i][j]-1 + if self.visTime[i][j]>0 then + self.visTime[i][j]=self.visTime[i][j]-1 end end end - if P.endCounter==120 then - for _=#P.field,1,-1 do - FREEROW.discard(P.field[_]) - FREEROW.discard(P.visTime[_]) - P.field[_],P.visTime[_]=nil + if self.endCounter==120 then + for _=#self.field,1,-1 do + FREEROW.discard(self.field[_]) + FREEROW.discard(self.visTime[_]) + self.field[_],self.visTime[_]=nil end return end end if not GAME.modeEnv.royaleMode and #PLAYERS>1 then - P.y=P.y+P.endCounter*.26 - P.absFieldY=P.absFieldY+P.endCounter*.26 + self.y=self.y+self.endCounter*.26 + self.absFieldY=self.absFieldY+self.endCounter*.26 end end end @@ -1667,33 +1666,33 @@ local function gameOver()--Save record end end -function Player.die(P)--Called both when win/lose! - P.alive=false - P.timing=false - P.control=false - P.update=PLY.update.dead - P.waiting=1e99 - P.b2b=0 - P.tasks={} - for i=1,#P.atkBuffer do - P.atkBuffer[i].sent=true - P.atkBuffer[i].time=0 +function Player:die()--Called both when win/lose! + self.alive=false + self.timing=false + self.control=false + self.update=PLY.update.dead + self.waiting=1e99 + self.b2b=0 + self.tasks={} + for i=1,#self.atkBuffer do + self.atkBuffer[i].sent=true + self.atkBuffer[i].time=0 end - for i=1,#P.field do + for i=1,#self.field do for j=1,10 do - P.visTime[i][j]=min(P.visTime[i][j],20) + self.visTime[i][j]=min(self.visTime[i][j],20) end end end -function Player.win(P,result) - if P.result then return end - P:die() - P.result="WIN" +function Player:win(result) + if self.result then return end + self:die() + self.result="WIN" if GAME.modeEnv.royaleMode then - P.modeData.place=1 - P:changeAtk() + self.modeData.place=1 + self:changeAtk() end - if P.type=="human"then + if self.type=="human"then GAME.result=result or"win" SFX.play("win") VOC.play("win") @@ -1702,394 +1701,390 @@ function Player.win(P,result) end end if GAME.curMode.id=="custom_puzzle"then - P:showTextF(text.win,0,0,90,"beat",.4) + self:showTextF(text.win,0,0,90,"beat",.4) else - P:showTextF(text.win,0,0,90,"beat",.5,.2) + self:showTextF(text.win,0,0,90,"beat",.5,.2) end - if P.type=="human"then + if self.type=="human"then gameOver() TASK.new(tick_autoPause) end - P:newTask(tick_finish) + self:newTask(tick_finish) end -function Player.lose(P,force) - if P.result then return end - if P.life>0 and not force then - P.waiting=62 - local h=#P.field +function Player:lose(force) + if self.result then return end + if self.life>0 and not force then + self.waiting=62 + local h=#self.field for _=h,1,-1 do - FREEROW.discard(P.field[_]) - FREEROW.discard(P.visTime[_]) - P.field[_],P.visTime[_]=nil + FREEROW.discard(self.field[_]) + FREEROW.discard(self.visTime[_]) + self.field[_],self.visTime[_]=nil end - P.garbageBeneath=0 + self.garbageBeneath=0 - if P.AI_mode=="CC"then - CC.destroy(P.AI_bot) - while P.holdQueue[1]do rem(P.holdQueue)end - P:loadAI(P.AIdata) + if self.AI_mode=="CC"then + CC.destroy(self.AI_bot) + TABLE.clear(self.holdQueue) + self:loadAI(self.AIdata) end - P.life=P.life-1 - P.fieldBeneath=0 - P.b2b=0 - for i=1,#P.atkBuffer do - local A=P.atkBuffer[i] + self.life=self.life-1 + self.fieldBeneath=0 + self.b2b=0 + for i=1,#self.atkBuffer do + local A=self.atkBuffer[i] if not A.sent then A.sent=true A.time=0 end end - P.atkBuffer.sum=0 + self.atkBuffer.sum=0 for i=1,h do - P:createClearingFX(i,1.5) + self:createClearingFX(i,1.5) end - SYSFX.newShade(1.4,P.fieldX,P.fieldY,300*P.size,610*P.size) - SYSFX.newRectRipple(2,P.fieldX,P.fieldY,300*P.size,610*P.size) - SYSFX.newRipple(2,P.x+(475+25*(P.life<3 and P.life or 0)+12)*P.size,P.y+(665+12)*P.size,20) + SYSFX.newShade(1.4,self.fieldX,self.fieldY,300*self.size,610*self.size) + SYSFX.newRectRipple(2,self.fieldX,self.fieldY,300*self.size,610*self.size) + SYSFX.newRipple(2,self.x+(475+25*(self.life<3 and self.life or 0)+12)*self.size,self.y+(665+12)*self.size,20) SFX.play("clear_3") SFX.play("emit") return end - P:die() - for i=1,#PLAYERS.alive do - if PLAYERS.alive[i]==P then - rem(PLAYERS.alive,i) + self:die() + for i=1,#PLY_ALIVE do + if PLY_ALIVE[i]==self then + rem(PLY_ALIVE,i) break end end - P.result="K.O." + self.result="K.O." if GAME.modeEnv.royaleMode then - P:changeAtk() - P.modeData.place=#PLAYERS.alive+1 - P.strength=0 - if P.lastRecv then - local A,i=P,0 + self:changeAtk() + self.modeData.place=#PLY_ALIVE+1 + self.strength=0 + if self.lastRecv then + local A,i=self,0 repeat A,i=A.lastRecv,i+1 - until not A or A.alive or A==P or i==3 + until not A or A.alive or A==self or i==3 if A and A.alive then - if P.id==1 or A.id==1 then - P.killMark=A.id==1 + if self.id==1 or A.id==1 then + self.killMark=A.id==1 end - A.modeData.ko,A.badge=A.modeData.ko+1,A.badge+P.badge+1 + A.modeData.ko,A.badge=A.modeData.ko+1,A.badge+self.badge+1 for j=A.strength+1,4 do if A.badge>=royaleData.powerUp[j]then A.strength=j A.frameColor=A.strength end end - P.lastRecv=A - if P.id==1 or A.id==1 then - TASK.new(tick_throwBadge,not A.type=="human",P,max(3,P.badge)*4) + self.lastRecv=A + if self.id==1 or A.id==1 then + TASK.new(tick_throwBadge,not A.type=="human",self,max(3,self.badge)*4) end end else - P.badge=-1 + self.badge=-1 end freshMostBadge() freshMostDangerous() - if #PLAYERS.alive==royaleData.stage[GAME.stage]then + if #PLY_ALIVE==royaleData.stage[GAME.stage]then royaleLevelup() end - P:showTextF(P.modeData.place,0,120,60,"appear",.26,.9) + self:showTextF(self.modeData.place,0,120,60,"appear",.26,.9) end - P.gameEnv.keepVisible=P.gameEnv.visible~="show" - P:showTextF(text.gameover,0,0,60,"appear",.26,.9) - if P.type=="human"then + self.gameEnv.keepVisible=self.gameEnv.visible~="show" + self:showTextF(text.gameover,0,0,60,"appear",.26,.9) + if self.type=="human"then GAME.result="gameover" SFX.play("fail") VOC.play("lose") if GAME.modeEnv.royaleMode then - if P.modeData.place==2 then - BGM.play("hay what kind of feeling") - else - BGM.play("end") - end + BGM.play("end") end gameOver() - P:newTask(#PLAYERS>1 and tick_lose or tick_finish) + self:newTask(#PLAYERS>1 and tick_lose or tick_finish) if GAME.net then - WS.send("play","D") + NET.signal_die() else TASK.new(tick_autoPause) end else - P:newTask(tick_lose) + self:newTask(tick_lose) end - if #PLAYERS.alive==1 then - PLAYERS.alive[1]:win() + if #PLY_ALIVE==1 then + PLY_ALIVE[1]:win() end end --------------------------<\Events>-------------------------- ---------------------------------------------------- -function Player.act_moveLeft(P,auto) +function Player:act_moveLeft(auto) if not auto then - P.ctrlCount=P.ctrlCount+1 + self.ctrlCount=self.ctrlCount+1 end - P.movDir=-1 - if P.keyPressing[9]then - if P.gameEnv.swap then - P:changeAtkMode(1) - P.keyPressing[1]=false + self.movDir=-1 + if self.keyPressing[9]then + if self.gameEnv.swap then + self:changeAtkMode(1) + self.keyPressing[1]=false end - elseif P.control and P.waiting==-1 then - if P.cur and not P:ifoverlap(P.cur.bk,P.curX-1,P.curY)then - if P.gameEnv.moveFX and P.gameEnv.block then - P:createMoveFX("left") + elseif self.control and self.waiting==-1 then + if self.cur and not self:ifoverlap(self.cur.bk,self.curX-1,self.curY)then + if self.gameEnv.moveFX and self.gameEnv.block then + self:createMoveFX("left") end - P.curX=P.curX-1 - P:freshBlock("move") - if P.sound and P.curY==P.ghoY then SFX.play("move")end - if not auto then P.moving=0 end - P.spinLast=false + self.curX=self.curX-1 + self:freshBlock("move") + if self.sound and self.curY==self.ghoY then SFX.play("move")end + if not auto then self.moving=0 end + self.spinLast=false else - P.moving=P.gameEnv.das + self.moving=self.gameEnv.das end else - P.moving=0 + self.moving=0 end end -function Player.act_moveRight(P,auto) +function Player:act_moveRight(auto) if not auto then - P.ctrlCount=P.ctrlCount+1 + self.ctrlCount=self.ctrlCount+1 end - P.movDir=1 - if P.keyPressing[9]then - if P.gameEnv.swap then - P:changeAtkMode(2) - P.keyPressing[2]=false + self.movDir=1 + if self.keyPressing[9]then + if self.gameEnv.swap then + self:changeAtkMode(2) + self.keyPressing[2]=false end - elseif P.control and P.waiting==-1 then - if P.cur and not P:ifoverlap(P.cur.bk,P.curX+1,P.curY)then - if P.gameEnv.moveFX and P.gameEnv.block then - P:createMoveFX("right") + elseif self.control and self.waiting==-1 then + if self.cur and not self:ifoverlap(self.cur.bk,self.curX+1,self.curY)then + if self.gameEnv.moveFX and self.gameEnv.block then + self:createMoveFX("right") end - P.curX=P.curX+1 - P:freshBlock("move") - if P.sound and P.curY==P.ghoY then SFX.play("move")end - if not auto then P.moving=0 end - P.spinLast=false + self.curX=self.curX+1 + self:freshBlock("move") + if self.sound and self.curY==self.ghoY then SFX.play("move")end + if not auto then self.moving=0 end + self.spinLast=false else - P.moving=P.gameEnv.das + self.moving=self.gameEnv.das end else - P.moving=0 + self.moving=0 end end -function Player.act_rotRight(P) - if P.control and P.waiting==-1 and P.cur then - P.ctrlCount=P.ctrlCount+1 - P:spin(1) - P.keyPressing[3]=false +function Player:act_rotRight() + if self.control and self.waiting==-1 and self.cur then + self.ctrlCount=self.ctrlCount+1 + self:spin(1) + self.keyPressing[3]=false end end -function Player.act_rotLeft(P) - if P.control and P.waiting==-1 and P.cur then - P.ctrlCount=P.ctrlCount+1 - P:spin(3) - P.keyPressing[4]=false +function Player:act_rotLeft() + if self.control and self.waiting==-1 and self.cur then + self.ctrlCount=self.ctrlCount+1 + self:spin(3) + self.keyPressing[4]=false end end -function Player.act_rot180(P) - if P.control and P.waiting==-1 and P.cur then - P.ctrlCount=P.ctrlCount+2 - P:spin(2) - P.keyPressing[5]=false +function Player:act_rot180() + if self.control and self.waiting==-1 and self.cur then + self.ctrlCount=self.ctrlCount+2 + self:spin(2) + self.keyPressing[5]=false end end -function Player.act_hardDrop(P) - if P.keyPressing[9]then - if P.gameEnv.swap then - P:changeAtkMode(3) +function Player:act_hardDrop() + if self.keyPressing[9]then + if self.gameEnv.swap then + self:changeAtkMode(3) end - P.keyPressing[6]=false - elseif P.control and P.waiting==-1 and P.cur then - if P.curY>P.ghoY then - local CB=P.cur.bk - if P.gameEnv.dropFX and P.gameEnv.block and P.curY-P.ghoY-#CB>-1 then - P:createDropFX(P.curX,P.curY-1,#CB[1],P.curY-P.ghoY-#CB+1) + self.keyPressing[6]=false + elseif self.control and self.waiting==-1 and self.cur then + if self.curY>self.ghoY then + local CB=self.cur.bk + if self.gameEnv.dropFX and self.gameEnv.block and self.curY-self.ghoY-#CB>-1 then + self:createDropFX(self.curX,self.curY-1,#CB[1],self.curY-self.ghoY-#CB+1) end - P.curY=P.ghoY - P.spinLast=false - if P.sound then - SFX.play("drop",nil,P:getCenterX()*.15) + self.curY=self.ghoY + self.spinLast=false + if self.sound then + SFX.play("drop",nil,self:getCenterX()*.15) VIB(1) end end - if P.gameEnv.shakeFX then - P.fieldOff.vy=P.gameEnv.shakeFX*.6 - P.fieldOff.va=P.fieldOff.va+P:getCenterX()*P.gameEnv.shakeFX*6e-4 + if self.gameEnv.shakeFX then + self.fieldOff.vy=self.gameEnv.shakeFX*.6 + self.fieldOff.va=self.fieldOff.va+self:getCenterX()*self.gameEnv.shakeFX*6e-4 end - P.lockDelay=-1 - P:drop() - P.keyPressing[6]=false + self.lockDelay=-1 + self:drop() + self.keyPressing[6]=false end end -function Player.act_softDrop(P) - local ENV=P.gameEnv - if P.keyPressing[9]then +function Player:act_softDrop() + local ENV=self.gameEnv + if self.keyPressing[9]then if ENV.swap then - P:changeAtkMode(4) + self:changeAtkMode(4) end else - P.downing=1 - if P.control and P.waiting==-1 and P.cur then - if P.curY>P.ghoY then - P.curY=P.curY-1 - P:freshBlock("fresh") - P.spinLast=false + self.downing=1 + if self.control and self.waiting==-1 and self.cur then + if self.curY>self.ghoY then + self.curY=self.curY-1 + self:freshBlock("fresh") + self.spinLast=false elseif ENV.deepDrop then - local CB=P.cur.bk - local y=P.curY-1 - while P:ifoverlap(CB,P.curX,y)and y>0 do + local CB=self.cur.bk + local y=self.curY-1 + while self:ifoverlap(CB,self.curX,y)and y>0 do y=y-1 end if y>0 then - if ENV.dropFX and ENV.block and P.curY-y-#CB>-1 then - P:createDropFX(P.curX,P.curY-1,#CB[1],P.curY-y-#CB+1) + if ENV.dropFX and ENV.block and self.curY-y-#CB>-1 then + self:createDropFX(self.curX,self.curY-1,#CB[1],self.curY-y-#CB+1) end - P.curY=y - P:freshBlock("move") + self.curY=y + self:freshBlock("move") SFX.play("swipe") end end end end end -function Player.act_hold(P) - if P.control and P.waiting==-1 then - P:hold() +function Player:act_hold() + if self.control and self.waiting==-1 then + self:hold() end end -function Player.act_func1(P) - P.gameEnv.fkey1(P) +function Player:act_func1() + self.gameEnv.fkey1(self) end -function Player.act_func2(P) - P.gameEnv.fkey2(P) +function Player:act_func2() + self.gameEnv.fkey2(self) end -function Player.act_insLeft(P,auto) - if not P.cur then return end - local x0=P.curX - while not P:ifoverlap(P.cur.bk,P.curX-1,P.curY)do - if P.gameEnv.moveFX and P.gameEnv.block then - P:createMoveFX("left") +function Player:act_insLeft(auto) + if not self.cur then return end + local x0=self.curX + while not self:ifoverlap(self.cur.bk,self.curX-1,self.curY)do + if self.gameEnv.moveFX and self.gameEnv.block then + self:createMoveFX("left") end - P.curX=P.curX-1 - P:freshBlock("move") + self.curX=self.curX-1 + self:freshBlock("move") end - if P.curX~=x0 then - P.spinLast=false + if self.curX~=x0 then + self.spinLast=false end - if P.gameEnv.shakeFX then - P.fieldOff.vx=-P.gameEnv.shakeFX*.5 + if self.gameEnv.shakeFX then + self.fieldOff.vx=-self.gameEnv.shakeFX*.5 end if auto then - if P.ctrlCount==0 then P.ctrlCount=1 end + if self.ctrlCount==0 then self.ctrlCount=1 end else - P.ctrlCount=P.ctrlCount+1 + self.ctrlCount=self.ctrlCount+1 end end -function Player.act_insRight(P,auto) - if not P.cur then return end - local x0=P.curX - while not P:ifoverlap(P.cur.bk,P.curX+1,P.curY)do - if P.gameEnv.moveFX and P.gameEnv.block then - P:createMoveFX("right") +function Player:act_insRight(auto) + if not self.cur then return end + local x0=self.curX + while not self:ifoverlap(self.cur.bk,self.curX+1,self.curY)do + if self.gameEnv.moveFX and self.gameEnv.block then + self:createMoveFX("right") end - P.curX=P.curX+1 - P:freshBlock("move") + self.curX=self.curX+1 + self:freshBlock("move") end - if P.curX~=x0 then - P.spinLast=false + if self.curX~=x0 then + self.spinLast=false end - if P.gameEnv.shakeFX then - P.fieldOff.vx=P.gameEnv.shakeFX*.5 + if self.gameEnv.shakeFX then + self.fieldOff.vx=self.gameEnv.shakeFX*.5 end if auto then - if P.ctrlCount==0 then P.ctrlCount=1 end + if self.ctrlCount==0 then self.ctrlCount=1 end else - P.ctrlCount=P.ctrlCount+1 + self.ctrlCount=self.ctrlCount+1 end end -function Player.act_insDown(P) - if P.cur and P.curY>P.ghoY then - local ENV=P.gameEnv - local CB=P.cur.bk - if ENV.dropFX and ENV.block and P.curY-P.ghoY-#CB>-1 then - P:createDropFX(P.curX,P.curY-1,#CB[1],P.curY-P.ghoY-#CB+1) +function Player:act_insDown() + if self.cur and self.curY>self.ghoY then + local ENV=self.gameEnv + local CB=self.cur.bk + if ENV.dropFX and ENV.block and self.curY-self.ghoY-#CB>-1 then + self:createDropFX(self.curX,self.curY-1,#CB[1],self.curY-self.ghoY-#CB+1) end if ENV.shakeFX then - P.fieldOff.vy=ENV.shakeFX*.5 + self.fieldOff.vy=ENV.shakeFX*.5 end - P.curY=P.ghoY - P.lockDelay=ENV.lock - P.spinLast=false - P:freshBlock("fresh") + self.curY=self.ghoY + self.lockDelay=ENV.lock + self.spinLast=false + self:freshBlock("fresh") end end -function Player.act_down1(P) - if P.cur and P.curY>P.ghoY then - if P.gameEnv.moveFX and P.gameEnv.block then - P:createMoveFX("down") +function Player:act_down1() + if self.cur and self.curY>self.ghoY then + if self.gameEnv.moveFX and self.gameEnv.block then + self:createMoveFX("down") end - P.curY=P.curY-1 - P:freshBlock("fresh") - P.spinLast=false + self.curY=self.curY-1 + self:freshBlock("fresh") + self.spinLast=false end end -function Player.act_down4(P) - if P.cur and P.curY>P.ghoY then - local y=max(P.curY-4,P.ghoY) - local CB=P.cur.bk - if P.gameEnv.dropFX and P.gameEnv.block and P.curY-y-#CB>-1 then - P:createDropFX(P.curX,P.curY-1,#CB[1],P.curY-y-#CB+1) +function Player:act_down4() + if self.cur and self.curY>self.ghoY then + local y=max(self.curY-4,self.ghoY) + local CB=self.cur.bk + if self.gameEnv.dropFX and self.gameEnv.block and self.curY-y-#CB>-1 then + self:createDropFX(self.curX,self.curY-1,#CB[1],self.curY-y-#CB+1) end - P.curY=y - P:freshBlock("fresh") - P.spinLast=false + self.curY=y + self:freshBlock("fresh") + self.spinLast=false end end -function Player.act_down10(P) - if P.cur and P.curY>P.ghoY then - local y=max(P.curY-10,P.ghoY) - local CB=P.cur.bk - if P.gameEnv.dropFX and P.gameEnv.block and P.curY-y-#CB>-1 then - P:createDropFX(P.curX,P.curY-1,#CB[1],P.curY-y-#CB+1) +function Player:act_down10() + if self.cur and self.curY>self.ghoY then + local y=max(self.curY-10,self.ghoY) + local CB=self.cur.bk + if self.gameEnv.dropFX and self.gameEnv.block and self.curY-y-#CB>-1 then + self:createDropFX(self.curX,self.curY-1,#CB[1],self.curY-y-#CB+1) end - P.curY=y - P:freshBlock("fresh") - P.spinLast=false + self.curY=y + self:freshBlock("fresh") + self.spinLast=false end end -function Player.act_dropLeft(P) - if not P.cur then return end - P:act_insLeft() - P:act_hardDrop() +function Player:act_dropLeft() + if not self.cur then return end + self:act_insLeft() + self:act_hardDrop() end -function Player.act_dropRight(P) - if not P.cur then return end - P:act_insRight() - P:act_hardDrop() +function Player:act_dropRight() + if not self.cur then return end + self:act_insRight() + self:act_hardDrop() end -function Player.act_zangiLeft(P) - if not P.cur then return end - P:act_insLeft() - P:act_insDown() - P:act_insRight() - P:act_hardDrop() +function Player:act_zangiLeft() + if not self.cur then return end + self:act_insLeft() + self:act_insDown() + self:act_insRight() + self:act_hardDrop() end -function Player.act_zangiRight(P) - if not P.cur then return end - P:act_insRight() - P:act_insDown() - P:act_insLeft() - P:act_hardDrop() +function Player:act_zangiRight() + if not self.cur then return end + self:act_insRight() + self:act_insDown() + self:act_insLeft() + self:act_hardDrop() end Player.actList={ Player.act_moveLeft, --1 diff --git a/parts/player/update.lua b/parts/player/update.lua index 9b99af5d..2e7048fc 100644 --- a/parts/player/update.lua +++ b/parts/player/update.lua @@ -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 diff --git a/parts/scenes/app_ten.lua b/parts/scenes/app_ten.lua index c4c47881..e176f909 100644 --- a/parts/scenes/app_ten.lua +++ b/parts/scenes/app_ten.lua @@ -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) diff --git a/parts/scenes/customGame.lua b/parts/scenes/customGame.lua index 998bf10a..d3988082 100644 --- a/parts/scenes/customGame.lua +++ b/parts/scenes/customGame.lua @@ -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"}, diff --git a/parts/scenes/custom_advance.lua b/parts/scenes/custom_advance.lua index 4ef4beba..b7176219 100644 --- a/parts/scenes/custom_advance.lua +++ b/parts/scenes/custom_advance.lua @@ -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}, } diff --git a/parts/scenes/custom_field.lua b/parts/scenes/custom_field.lua index 4a059bcc..968c5f85 100644 --- a/parts/scenes/custom_field.lua +++ b/parts/scenes/custom_field.lua @@ -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"}, diff --git a/parts/scenes/custom_mission.lua b/parts/scenes/custom_mission.lua index c9855c4b..b5688b98 100644 --- a/parts/scenes/custom_mission.lua +++ b/parts/scenes/custom_mission.lua @@ -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}, } diff --git a/parts/scenes/custom_sequence.lua b/parts/scenes/custom_sequence.lua index ca999163..17deb1b6 100644 --- a/parts/scenes/custom_sequence.lua +++ b/parts/scenes/custom_sequence.lua @@ -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)}, diff --git a/parts/scenes/dict.lua b/parts/scenes/dict.lua index 2d8b088f..5f394ad6 100644 --- a/parts/scenes/dict.lua +++ b/parts/scenes/dict.lua @@ -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 diff --git a/parts/scenes/load.lua b/parts/scenes/load.lua index 94e5634e..9685dfa1 100644 --- a/parts/scenes/load.lua +++ b/parts/scenes/load.lua @@ -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 diff --git a/parts/scenes/login.lua b/parts/scenes/login.lua index 4885f58b..d6517847 100644 --- a/parts/scenes/login.lua +++ b/parts/scenes/login.lua @@ -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, diff --git a/parts/scenes/main.lua b/parts/scenes/main.lua index 6ea1db7a..08b66486 100644 --- a/parts/scenes/main.lua +++ b/parts/scenes/main.lua @@ -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}, } diff --git a/parts/scenes/music.lua b/parts/scenes/music.lua index 796a88fa..0289e344 100644 --- a/parts/scenes/music.lua +++ b/parts/scenes/music.lua @@ -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}, diff --git a/parts/scenes/net_chat.lua b/parts/scenes/net_chat.lua index 9c2242e2..f3d45d45 100644 --- a/parts/scenes/net_chat.lua +++ b/parts/scenes/net_chat.lua @@ -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) diff --git a/parts/scenes/net_game.lua b/parts/scenes/net_game.lua index f1d46441..52bbcd61 100644 --- a/parts/scenes/net_game.lua +++ b/parts/scenes/net_game.lua @@ -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"}, } diff --git a/parts/scenes/net_menu.lua b/parts/scenes/net_menu.lua index 8f1597fb..4246cec5 100644 --- a/parts/scenes/net_menu.lua +++ b/parts/scenes/net_menu.lua @@ -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}, } diff --git a/parts/scenes/net_rooms.lua b/parts/scenes/net_rooms.lua index 2d7e86a7..09577710 100644 --- a/parts/scenes/net_rooms.lua +++ b/parts/scenes/net_rooms.lua @@ -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}, } diff --git a/parts/scenes/savedata.lua b/parts/scenes/savedata.lua index e5b8eacb..8050e8aa 100644 --- a/parts/scenes/savedata.lua +++ b/parts/scenes/savedata.lua @@ -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 diff --git a/parts/scenes/setting_control.lua b/parts/scenes/setting_control.lua index 8ebb151a..4bb3f3a0 100644 --- a/parts/scenes/setting_control.lua +++ b/parts/scenes/setting_control.lua @@ -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 diff --git a/parts/scenes/setting_game.lua b/parts/scenes/setting_game.lua index 05a25023..2c0347af 100644 --- a/parts/scenes/setting_game.lua +++ b/parts/scenes/setting_game.lua @@ -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 diff --git a/parts/scenes/setting_sound.lua b/parts/scenes/setting_sound.lua index effea2a4..390a28c7 100644 --- a/parts/scenes/setting_sound.lua +++ b/parts/scenes/setting_sound.lua @@ -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}, diff --git a/parts/scenes/setting_touchSwitch.lua b/parts/scenes/setting_touchSwitch.lua index af5a6079..b8ec6bfb 100644 --- a/parts/scenes/setting_touchSwitch.lua +++ b/parts/scenes/setting_touchSwitch.lua @@ -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}, } diff --git a/parts/scenes/setting_trackSetting.lua b/parts/scenes/setting_trackSetting.lua index 85531473..f507c92b 100644 --- a/parts/scenes/setting_trackSetting.lua +++ b/parts/scenes/setting_trackSetting.lua @@ -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}, } diff --git a/parts/scenes/setting_video.lua b/parts/scenes/setting_video.lua index d63c3e8f..9311435e 100644 --- a/parts/scenes/setting_video.lua +++ b/parts/scenes/setting_video.lua @@ -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}, } diff --git a/parts/scenes/sound.lua b/parts/scenes/sound.lua index 3b8765ee..666a5e97 100644 --- a/parts/scenes/sound.lua +++ b/parts/scenes/sound.lua @@ -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}, diff --git a/parts/texture.lua b/parts/texture.lua index 4a2cb28f..f8631006 100644 --- a/parts/texture.lua +++ b/parts/texture.lua @@ -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) diff --git a/parts/updateLog.lua b/parts/updateLog.lua index 281659a7..2ba70aef 100644 --- a/parts/updateLog.lua +++ b/parts/updateLog.lua @@ -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功能(暂时只在自定义开放)