Files
Techmino/player.lua
2020-02-04 19:37:53 +08:00

2358 lines
60 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-------------------------<Head>-------------------------
local int,ceil,abs,rnd,max,min=math.floor,math.ceil,math.abs,math.random,math.max,math.min
local ins,rem=table.insert,table.remove
local gc=love.graphics
local Timer=love.timer.getTime
local format=string.format
local scr=scr--screen camera
-------------------------</Head>-------------------------
-------------------------<GameData>-------------------------
local gameEnv0={
das=10,arr=2,
sddas=2,sdarr=2,
quickR=true,swap=true,
ghost=true,center=true,
grid=false,swap=true,
_20G=false,bone=false,
drop=60,lock=60,
wait=0,fall=0,
next=6,hold=true,oncehold=true,
sequence="bag7",
block=true,
visible="show",--keepVisible=visile~="show"
Fkey=NULL,puzzle=false,ospin=true,
freshLimit=1e99,easyFresh=true,
fine=false,fineKill=false,
target=1e99,dropPiece="null",
bg="none",bgm="race"
}
local renATK={[0]=0,0,0,1,1,2,2,3,3,4,4}--3 else
local b2bPoint={50,100,180}
local b2bATK={3,5,8}
local clearSCR={80,200,400}
local spinSCR={--[blockName][row]
{200,750,1600},--Z
{200,750,1600},--S
{220,700,1600},--L
{220,700,1600},--J
{250,800,1500},--T
{300,1000,2200},--O
{300,1000,1800},--I
}--MUL:1.2,2.0
--Techrash:1K;MUL:1.3,1.8
--Mini*=.5
local visible_opt={show=1e99,time=300,fast=20,none=5}
local reAtk={0,0,1,1,1,2,2,3,3}
local reDef={0,1,1,2,3,3,4,4,5}
local blockName={"Z","S","L","J","T","O","I"}
local clearName={"single","double","triple"}
local spin_n={[0]="spin_0","spin_1","spin_2","spin_3"}
local clear_n={"clear_1","clear_2","clear_3","clear_4"}
local ren_n={}for i=1,11 do ren_n[i]="ren_"..i end
local blockPos={4,4,4,4,4,5,4}
local TMP1,TMP2,TMP3,TMP4={1,2},{2,1},{2,2},{1.5,1.5}----------save cache
local scs={
{[0]=TMP1,TMP2,TMP3,TMP3},
{[0]=TMP1,TMP2,TMP3,TMP3},
{[0]=TMP1,TMP2,TMP3,TMP3},
{[0]=TMP1,TMP2,TMP3,TMP3},
{[0]=TMP1,TMP2,TMP3,TMP3},
{[0]=TMP4,TMP4,TMP4,TMP4},
{[0]={0.5,2.5},{2.5,0.5},{1.5,2.5},{2.5,1.5}},
}
local CCblockID={4,3,5,6,1,2,0}
TMP1={0,0}
local TRS={
[1]={
[01]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2},{0,1} },
[10]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2}, {0,-1} },
[03]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-1}, {1,-2} },
[30]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2}, {0,-1}},
[12]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2} },
[21]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2} },
[32]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2} },
[23]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2} },
[02]={TMP1,{1,0}, {-1,0}, {0,-1}, {0,1} },
[20]={TMP1,{-1,0}, {1,0}, {0,1}, {0,-1} },
[13]={TMP1,{0,-1}, {0,1}, {-1,0}, {0,-2} },
[31]={TMP1,{0,1}, {0,-1}, {1,0}, {0,2} },
},--Z
[2]={
[01]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-1},{-1,-2} },
[10]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2}, {0,-1}},
[03]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2}, {0,1} },
[30]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2}, {0,-1} },
[12]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2} },
[21]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2} },
[32]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2} },
[23]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2} },
[02]={TMP1,{-1,0}, {1,0}, {0,-1}, {0,1} },
[20]={TMP1,{1,0}, {-1,0}, {0,1}, {0,-1} },
[13]={TMP1,{0,1}, {0,-1}, {-1,0}, {0,2} },
[31]={TMP1,{0,-1}, {0,1}, {1,0}, {0,-2} },
},--S
[3]={
[01]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2},{0,1}, {-1,-1} },
[10]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2}, {0,-1}, {1,1} },
[03]={TMP1,{1,0}, {1,1}, {0,-2}, {-1,1} },
[30]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2} },
[12]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2}, {1,1} },
[21]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2},{-1,-1} },
[32]={TMP1,{-1,0}, {-1,-1},{1,0}, {0,2}, {-1,2} },
[23]={TMP1,{1,0}, {1,1}, {-1,0}, {0,-2}, {1,-2} },
[02]={TMP1,{1,0}, {-1,0}, {0,-1}, {0,1} },
[20]={TMP1,{-1,0}, {1,0}, {0,1}, {0,-1} },
[13]={TMP1,{0,1}, {1,0}, {0,-1} },
[31]={TMP1,{0,-1}, {-1,0}, {0,1} },
},--L
[4]={
[01]={TMP1,{-1,0}, {-1,1}, {0,-2}, {1,1} },
[10]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2} },
[03]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2}, {0,1}, {1,-1} },
[30]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2}, {0,-1}, {-1,1} },
[12]={TMP1,{1,0}, {1,-1}, {-1,0}, {0,2}, {1,2} },
[21]={TMP1,{-1,0}, {-1,1}, {1,0}, {0,-2}, {-1,-2} },
[32]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2}, {-1,1} },
[23]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2}, {1,-1} },
[02]={TMP1,{-1,0}, {1,0}, {0,-1}, {0,1} },
[20]={TMP1,{1,0}, {-1,0}, {0,1}, {0,-1} },
[13]={TMP1,{0,-1}, {1,0}, {0,1} },
[31]={TMP1,{0,1}, {-1,0}, {0,-1} },
},--J
[5]={
[01]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2},{-1,-1} },
[10]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2}, {0,-1}, {1,1}},
[03]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2} },
[30]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2}, {0,-1} },
[12]={TMP1,{1,0}, {1,-1}, {0,-1}, {0,2}, {1,2}, {-1,-1}},
[21]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2},{1,1} },
[32]={TMP1,{-1,0}, {-1,-1},{0,-1}, {0,2}, {-1,2}, {1,-1}},
[23]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2}, {-1,1} },
[02]={TMP1,{-1,0}, {1,0}, {0,1} },
[20]={TMP1,{1,0}, {-1,0}, {0,-1} },
[13]={TMP1,{0,-1}, {0,1}, {1,0}, {0,-2}, {0,2}},
[31]={TMP1,{0,-1}, {0,1}, {-1,0}, {0,-2}, {0,2}},
},--T
[6]={},--O(special)
[7]={
[01]={TMP1,{0,1}, {1,0}, {-2,0}, {-2,-1},{1,2} },
[03]={TMP1,{0,1}, {-1,0}, {2,0}, {2,-1}, {-1,2} },
[10]={TMP1,{2,0}, {-1,0}, {-1,-2},{2,1}, {0,2} },
[30]={TMP1,{-2,0}, {1,0}, {1,-2}, {-2,1}, {0,2} },
[12]={TMP1,{-1,0}, {2,0}, {-1,2}, {2,-1} },
[32]={TMP1,{1,0}, {-2,0}, {1,-2}, {-2,-1} },
[21]={TMP1,{-2,0}, {1,0}, {1,-2}, {-2,1} },
[23]={TMP1,{2,0}, {-1,0}, {-1,-2},{2,1} },
[02]={TMP1,{-1,0}, {1,0}, {0,-1}, {0,1} },
[20]={TMP1,{1,0}, {-1,0}, {0,1}, {0,-1} },
[13]={TMP1,{0,-1}, {-1,0}, {1,0}, {0,1} },
[31]={TMP1,{1,0}, {-1,0}},
}
}
local AIRS={{
[01]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2} },
[10]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2} },
[03]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2} },
[30]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2} },
[12]={TMP1,{1,0}, {1,-1}, {0,2}, {1,2} },
[21]={TMP1,{-1,0}, {-1,1}, {0,-2}, {-1,-2} },
[32]={TMP1,{-1,0}, {-1,-1},{0,2}, {-1,2} },
[23]={TMP1,{1,0}, {1,1}, {0,-2}, {1,-2} },
}}for i=2,6 do AIRS[i]=AIRS[1]end
AIRS[7]={
[01]={TMP1,{-2,0}, {1,0}, {-2,-1},{1,2} },
[10]={TMP1,{2,0}, {-1,0}, {2,1}, {-1,-2} },
[12]={TMP1,{-1,0}, {2,0}, {-1,2}, {2,-1} },
[21]={TMP1,{1,0}, {-2,0}, {1,-2}, {-2,1} },
[23]={TMP1,{2,0}, {-1,0}, {2,1}, {-1,-2} },
[32]={TMP1,{-2,0}, {1,0}, {-2,-1},{1,2} },
[30]={TMP1,{1,0}, {-2,0}, {1,-2}, {-2,1} },
[03]={TMP1,{-1,0}, {2,0}, {-1,2}, {2,-1} },
}
local TMP1={
[1]={
{1,2,1,0,1,2,2,1},
{2,2,3,1,1,2,3,2,2},
},--Z
[3]={
{1,2,1,0,1,2,2,1},
{2,2,3,2,1,2,3,3,2},
{3,4,3,2,3,4,4,3},
{2,3,2,1,2,3,3,2,2},
},--L
[6]={
{1,2,2,1,0,1,2,2,1},
},--O
[7]={
{1,2,1,0,1,2,1},
{2,2,2,2,1,1,2,2,2,2},
},--I
}--SZI逆态视为顺态JLT算法相同
TMP1[2]=TMP1[1]
TMP1[4]=TMP1[3]
TMP1[5]=TMP1[3]
local finesseCtrlPar=TMP1
TMP1,TMP2,TMP3,TMP4=nil----------release
local CCblockID={4,3,5,6,1,2,0}
local freshMethod={
none=NULL,
bag7=function(P)
if #P.next<6 then
local bag={1,2,3,4,5,6,7}
::L::P:newNext(rem(bag,rnd(#bag)))
if bag[1]then goto L end
end
end,
his4=function(P)
if #P.next<6 then
local j,i=0
repeat
i,j=rnd(7),j+1
until i~=P.his[1]and i~=P.his[2]and i~=P.his[3]and i~=P.his[4]
P:newNext(i)
rem(P.his,1)P.his[4]=i
end
end,
rnd=function(P)
::L::local i=rnd(7)
if i==P.next[5]then goto L end
P:newNext(i)
end,--random
drought1=function(P)
if #P.next<6 then
local bag={1,2,3,4,5,6}
::L::P:newNext(rem(bag,rnd(#bag)))
if bag[1]then goto L end
end
end,
drought2=function(P)
if #P.next<6 then
local bag={1,1,1,1,2,2,2,2,6,6,6,6,3,3,4,4,5,7}
::L::P:newNext(rem(bag,rnd(#bag)))
if bag[1]then goto L end
end
end,
}
-------------------------</GameData>-------------------------
local frameColor={
[0]=color.white,
color.lightGreen,
color.lightBlue,
color.lightPurple,
color.lightOrange,
}
local attackColor={
{color.darkGrey,color.white},
{color.grey,color.white},
{color.lightPurple,color.white},
{color.lightRed,color.white},
{color.darkGreen,color.cyan},
}
local function drawPixel(y,x,id)
gc.draw(blockSkin[id],30*x-30,600-30*y)
end
local function drawDial(x,y,speed)
gc.setColor(1,1,1)
mStr(int(speed),x,y-18)
gc.draw(dialCircle,x,y,nil,nil,nil,32,32)
gc.setColor(1,1,1,.6)
gc.draw(dialNeedle,x,y,2.094+(speed<=175 and .02094*speed or 4.712-52.36/(speed-125)),nil,nil,5,4)
end
local mesDisp={
--Default:font=35,white
sprint=function(P)
setFont(60)
local r=max(P.gameEnv.target-P.stat.row,0)
mStr(r,-82,265)
if r<21 and r>0 then
gc.setLineWidth(4)
gc.setColor(1,r>10 and 0 or rnd(),.5)
gc.line(0,600-30*r,300,600-30*r)
end
end,
marathon=function(P)
setFont(50)
mStr(P.stat.row,-82,320)
mStr(P.gameEnv.target,-82,370)
gc.rectangle("fill",-125,375,90,4)
end,
master=function(P)
setFont(50)
mStr(P.modeData.point,-82,320)
mStr((P.modeData.event+1)*100,-82,370)
gc.rectangle("fill",-125,375,90,4)
end,
classic=function(P)
setFont(80)
local r=P.gameEnv.target*.1
mStr(r<11 and 18 or r<22 and r+8 or r==22 and"00"or r==23 and"0a"or format("%x",r*10-220),-82,210)
mDraw(drawableText.speedLV,-82,290)
setFont(50)
mStr(P.stat.row,-82,320)
mStr(P.gameEnv.target,-82,370)
gc.rectangle("fill",-125,375,90,4)
end,
zen=function(P)
setFont(75)
mStr(max(200-P.stat.row,0),-82,280)
end,
infinite=function(P)
setFont(50)
mStr(P.stat.atk,-82,310)
mStr(format("%.2f",P.stat.atk/P.stat.row),-82,420)
mDraw(drawableText.atk,-82,363)
mDraw(drawableText.eff,-82,475)
end,
tsd=function(P)
setFont(80)
mStr(P.modeData.event,-82,330)
mDraw(drawableText.tsd,-82,407)
end,
blind=function(P)
mDraw(drawableText.line,-82,300)
mDraw(drawableText.techrash,-82,420)
if curMode.lv==6 then
mDraw(drawableText.grade,-82,170)
setFont(60)
mStr(P.modeData.event,-82,110)
end
setFont(80)
mStr(P.stat.row,-82,220)
mStr(P.stat.clear_4,-82,340)
end,
dig=function(P)
setFont(70)
mStr(P.modeData.event,-82,310)
mDraw(drawableText.wave,-82,375)
end,
survivor=function(P)
setFont(70)
mStr(P.modeData.event,-82,310)
mDraw(drawableText.wave,-82,375)
end,
defender=function(P)
setFont(60)
mStr(P.modeData.point,-82,315)
mDraw(drawableText.rpm,-82,375)
end,
attacker=function(P)
setFont(60)
mStr(P.modeData.point,-82,315)
mDraw(drawableText.rpm,-82,375)
end,
tech=function(P)
setFont(50)
mStr(P.stat.atk,-82,310)
mStr(format("%.2f",P.stat.atk/P.stat.row),-82,420)
mDraw(drawableText.atk,-82,363)
mDraw(drawableText.eff,-82,475)
end,
c4wtrain=function(P)
setFont(50)
mStr(max(100-P.stat.row,0),-82,220)
mStr(P.combo,-82,310)
mStr(P.modeData.point,-82,400)
mDraw(drawableText.combo,-82,358)
mDraw(drawableText.mxcmb,-82,450)
end,
pctrain=function(P)
setFont(80)
mStr(P.stat.pc,-82,330)
mDraw(drawableText.pc,-82,412)
end,
pcchallenge=function(P)
setFont(50)
mStr(max(100-P.stat.row,0),-82,250)
setFont(80)
mStr(P.stat.pc,-82,350)
mDraw(drawableText.pc,-82,432)
gc.setColor(.5,.5,.5)
if frame>179 then
local y=72*(7-(P.stat.piece+(P.hd.id>0 and 2 or 1))%7)-36
gc.line(320,y,442,y)
end
end,
techmino49=function(P)
setFont(40)
mStr(#players.alive.."/49",-82,175)
mStr(P.ko,-70,215)
gc.draw(drawableText.ko,-127,225)
setFont(25)
gc.setColor(1,.5,0,.6)
gc.print(P.badge,-47,227)
gc.setColor(1,1,1)
setFont(30)
gc.print(up0to4[P.strength],-132,290)
for i=1,P.strength do
gc.draw(badgeIcon,16*i-138,260)
end
end,
techmino99=function(P)
setFont(40)
mStr(#players.alive.."/99",-82,175)
mStr(P.ko,-70,215)
gc.draw(drawableText.ko,-127,225)
setFont(25)
gc.setColor(1,.5,0,.6)
gc.print(P.badge,-47,227)
gc.setColor(1,1,1)
setFont(30)
gc.print(up0to4[P.strength],-132,290)
for i=1,P.strength do
gc.draw(badgeIcon,16*i-138,260)
end
end,
drought=function(P)
setFont(75)
mStr(max(100-P.stat.row,0),-82,280)
end,
custom=function(P)
if P.gameEnv.puzzle or P.gameEnv.target>1e10 then
setFont(60)
mStr(P.stat.row,-82,225)
mDraw(drawableText.line,-82,290)
else
setFont(60)
mStr(max(P.gameEnv.target-P.stat.row,0),-82,240)
end
if P.gameEnv.puzzle and P.modeData.event==0 then
gc.setLineWidth(3)
for y=1,preField.h do for x=1,10 do
local B=preField[y][x]
if B>7 then
gc.setColor(blockColor[B])
gc.rectangle("line",30*x-23,607-30*y,16,16)
elseif B>0 then
local c=blockColor[B]
gc.setColor(c[1],c[2],c[3],.6)
gc.rectangle("line",30*x-25,605-30*y,20,20)
gc.rectangle("line",30*x-20,610-30*y,10,10)
elseif B==-1 then
gc.setColor(1,1,1,.4)
gc.line(30*x-25,605-30*y,30*x-5,625-30*y)
gc.line(30*x-25,625-30*y,30*x-5,605-30*y)
end
end end
end
end
}
--------------Used in draw player↑
player={}local player=player
function newDemoPlayer(id,x,y,size)
local P={id=id}players[id]=P
P.invincible=true
for k,v in next,player do P[k]=v end
players.alive[#players.alive+1]=P
P.x,P.y,P.size=x,y,size
P.fieldOffX,P.fieldOffY=0,0
P.small,P.keyRec=false,false
P.centerX,P.centerY=P.x+300*P.size,P.y+670*P.size
P.absFieldX=P.x+150*P.size
P.absFieldY=P.y+60*P.size
P.alive=true
P.control=true
P.timing=false
P.stat={
time=0,score=0,
key=0,extraPiece=0,extraRate=0,
rotate=0,hold=0,piece=0,row=0,
atk=0,send=0,recv=0,pend=0,
clear_1=0,clear_2=0,clear_3=0,clear_4=0,
spin_0=0,spin_1=0,spin_2=0,spin_3=0,
pc=0,b2b=0,b3b=0,
}
P.modeData={point=0,event=0}
P.keyTime={}for i=1,10 do P.keyTime[i]=-1e5 end P.keySpeed=0
P.dropTime={}for i=1,10 do P.dropTime[i]=-1e5 end P.dropSpeed=0
P.atker={}
P.strength=0
P.field,P.visTime={},{}
P.atkBuffer={sum=0}
P.gameEnv={
das=5,arr=2,
sddas=2,sdarr=2,
_20G=false,bone=false,
drop=1e99,lock=1e99,
wait=10,fall=20,
next=6,hold=true,oncehold=true,
sequence="bag7",
block=true,
visible="show",
Fkey=NULL,puzzle=false,ospin=true,
freshLimit=1e99,easyFresh=true,
target=1e99,dropPiece="null",
}
P.cur={bk={{}},id=0,color=0,name=0}
P.sc,P.dir,P.r,P.c={0,0},0,0,0
P.curX,P.curY,P.y_img=0,0,0
P.hd={bk={{}},id=0,color=0,name=0}
P.holded=false
P.next={}
P.dropDelay,P.lockDelay=1e99,1e99
P.freshTime=0
P.spinLast,P.lastClear=false,nil
P.spinSeq=0
P.ctrlCount=0
local bag1={1,2,3,4,5,6,7}
for _=1,7 do
P:newNext(rem(bag1,rnd(#bag1)))
end
P.freshNext=freshMethod.bag7
if P.gameEnv.sequence==1 then P.bag={}--Bag7
elseif P.gameEnv.sequence==2 then P.his={}for i=1,4 do P.his[i]=P.next.id[i+3]end--History4
elseif P.gameEnv.sequence==3 then--Pure random
end
P.human=false
P.AI_mode="CC"
P.AI_stage=1
P.AI_needFresh=false
P.AI_keys={}
P.AI_delay,P.AI_delay0=3,3
P.AIdata={next=5,hold=true,_20G=false,bag7=true,node=80000}
if not BOT then P.AI_mode="9S"end
if P.AI_mode=="CC"then
P.RS=AIRS
local opt,wei=BOT.getConf()
BOT.setHold(opt,P.AIdata.hold)
BOT.set20G(opt,P.AIdata._20G)
BOT.setBag(opt,P.AIdata.bag7)
BOT.setNode(opt,P.AIdata.node)
P.AI_bot=BOT.new(opt,wei)
BOT.free(opt)BOT.free(wei)
local CCBID={4,3,5,6,1,2,0}
for i=1,5 do
BOT.addNext(P.AI_bot,CCBID[P.next[i].id])
end
elseif P.AI_mode=="9S"then
P.RS=TRS
end
P.showTime=1e99
P.keepVisible=true
P.keyPressing={}for i=1,12 do P.keyPressing[i]=false end
P.moving,P.downing=0,0
P.waiting,P.falling=-1,-1
P.clearing,P.cleared={},{}
P.combo,P.b2b=0,0
P.fieldBeneath=0
P.shade={}
P.score1,P.b2b1=0,0
P.bonus={}--texts
P:resetblock()
PTC.dust[1]=PTC.dust0:clone()
end
function newPlayer(id,x,y,size,AIdata)
players[id]={id=id}
local P=players[id]
for k,v in next,player do P[k]=v end--Class function
players.alive[#players.alive+1]=P
P.x,P.y,P.size=x,y,size or 1
P.fieldOffX,P.fieldOffY=0,0--for Shake fx
P.small=P.size<.1--if draw in small mode
P.keyRec=not P.small--if calculate keySpeed
if P.small then
P.centerX,P.centerY=P.x+300*P.size,P.y+600*P.size
P.canvas=love.graphics.newCanvas(60,120)
P.frameWait=rnd(30,120)
else
P.centerX,P.centerY=P.x+300*P.size,P.y+670*P.size
P.absFieldX=P.x+150*P.size
P.absFieldY=P.y+60*P.size
end
P.alive=true
P.control=false
P.timing=false
P.stat={
time=0,score=0,
key=0,extraPiece=0,extraRate=0,
rotate=0,hold=0,piece=0,row=0,
atk=0,send=0,recv=0,pend=0,
clear_1=0,clear_2=0,clear_3=0,clear_4=0,
spin_0=0,spin_1=0,spin_2=0,spin_3=0,
pc=0,b2b=0,b3b=0,
}--Current gamestat
P.modeData={point=0,event=0}--data use by mode
P.keyTime={}for i=1,10 do P.keyTime[i]=-1e5 end P.keySpeed=0
P.dropTime={}for i=1,10 do P.dropTime[i]=-1e5 end P.dropSpeed=0
P.field,P.visTime={},{}
P.atkBuffer={sum=0}
P.ko,P.badge,P.strength=0,0,0
P.atkMode,P.swappingAtkMode=1,20
P.atker,P.atking,P.lastRecv={}
--Royale-related
P.gameEnv={}--Current game setting environment
for k,v in next,gameEnv0 do
if modeEnv[k]~=nil then
P.gameEnv[k]=modeEnv[k]
elseif setting[k]~=nil then
P.gameEnv[k]=setting[k]
else
P.gameEnv[k]=v
end
end--reset current game settings
P.cur={bk={{}},id=0,color=0,name=0}
P.sc,P.dir,P.r,P.c={0,0},0,0,0
P.curX,P.curY,P.y_img=0,0,0
P.hd={bk={{}},id=0,color=0,name=0}
P.holded=false
P.next={}
P.dropDelay,P.lockDelay=P.gameEnv.drop,P.gameEnv.lock
P.freshTime=0
P.spinLast,P.lastClear=false,nil
P.spinSeq=0--for Ospin,each digit mean a spin
P.ctrlCount=0--key press time,for finesse check
P.his={rnd(7),rnd(7),rnd(7),rnd(7)}
local s=P.gameEnv.sequence
if s=="bag7"or s=="his4"then
local bag1={1,2,3,4,5,6,7}
for _=1,7 do
P:newNext(rem(bag1,rnd(#bag1)))
end
elseif s=="rnd"then
for _=1,6 do
local r=rnd(7)
P:newNext(r)
end
elseif s=="drought1"then
local bag1={1,2,3,4,5,6}
for _=1,6 do
P:newNext(rem(bag1,rnd(#bag1)))
end
elseif s=="drought2"then
local bag1={1,2,3,4,6,6}
for _=1,6 do
P:newNext(rem(bag1,rnd(#bag1)))
end
end
P.freshNext=freshMethod[P.gameEnv.sequence]
if P.gameEnv.sequence==1 then P.bag={}--Bag7
elseif P.gameEnv.sequence==2 then P.his={}for i=1,4 do P.his[i]=P.next.id[i+3]end--History4
elseif P.gameEnv.sequence==3 then--Pure random
end
if AIdata then
P.human=false
P.AI_mode=AIdata.type
P.AI_stage=1
P.AI_needFresh=false
P.AI_keys={}
P.AI_delay=min(int(P.gameEnv.drop*.8),2*AIdata.delta)
P.AI_delay0=AIdata.delta
P.AIdata={
next=AIdata.next,
hold=AIdata.hold,
_20G=P.gameEnv._20G,
bag7=AIdata.bag7=="bag7",
node=AIdata.node,
}
if not BOT then P.AI_mode="9S"end
if P.AI_mode=="CC"then
P.RS=AIRS
local opt,wei=BOT.getConf()
BOT.setHold(opt,P.AIdata.hold)
BOT.set20G(opt,P.AIdata._20G)
BOT.setBag(opt,P.AIdata.bag7)
BOT.setNode(opt,P.AIdata.node)
P.AI_bot=BOT.new(opt,wei)
BOT.free(opt)BOT.free(wei)
for i=1,AIdata.next do
BOT.addNext(P.AI_bot,CCblockID[P.next[i].id])
end
elseif P.AI_mode=="9S"then
P.RS=TRS
P.AI_keys={}
end
else
P.human=true
P.RS=TRS
players.human=players.human+1
end
P.showTime=visible_opt[P.gameEnv.visible]
P.keepVisible=P.gameEnv.visible=="show"
P.keyPressing={}for i=1,12 do P.keyPressing[i]=false end
P.moving,P.downing=0,0
P.waiting,P.falling=-1,-1
P.clearing,P.cleared={},{}
P.combo,P.b2b=0,0
P.fieldBeneath=0
P.shade={}
P.score1,P.b2b1=0,0
P.bonus={}--texts
P.endCounter=0--used after gameover
P.counter=0--many usage
P.result=nil--string:win/lose
end
function player.update(P,dt)
if P.timing then P.stat.time=P.stat.time+dt end
if P.alive then
if P.keyRec then
local v=0
for i=2,10 do v=v+i*(i-1)*7.2/(frame-P.keyTime[i])end P.keySpeed=P.keySpeed*.99+v*.1
v=0
for i=2,10 do v=v+i*(i-1)*7.2/(frame-P.dropTime[i])end P.dropSpeed=P.dropSpeed*.99+v*.1
--Update speeds
if modeEnv.royaleMode then
if P.keyPressing[9]then
P.swappingAtkMode=min(P.swappingAtkMode+2,30)
else
P.swappingAtkMode=P.swappingAtkMode+((#P.field>15 and P.swappingAtkMode>4 or P.swappingAtkMode>8)and -1 or 1)
end
end
end
if not P.human and P.control and P.waiting==-1 then
local C=P.AI_keys
P.AI_delay=P.AI_delay-1
if not C[1]then
P.AI_stage=AI_think[P.AI_mode][P.AI_stage](P,C)
elseif P.AI_delay<=0 then
P:pressKey(C[1])P:releaseKey(C[1])
local k=#C for i=1,k do C[i]=C[i+1]end--table.remove(C,1)
P.AI_delay=P.AI_delay0*2
end
end
if not P.keepVisible then
for j=1,#P.field do for i=1,10 do
if P.visTime[j][i]>0 then P.visTime[j][i]=P.visTime[j][i]-1 end
end end
end--Fresh visible time
if P.moving<0 then
if P.keyPressing[1]then
if -P.moving<=P.gameEnv.das then
P.moving=P.moving-1
elseif P.waiting==-1 then
local x=P.curX
if P.gameEnv.arr>0 then
P.act.moveLeft(P,true)
else
P.act.insLeft(P,true)
end
if x~=P.curX then P.moving=P.moving+P.gameEnv.arr-1 end
end
else
P.moving=0
end
elseif P.moving>0 then
if P.keyPressing[2]then
if P.moving<=P.gameEnv.das then
P.moving=P.moving+1
elseif P.waiting==-1 then
local x=P.curX
if P.gameEnv.arr>0 then
P.act.moveRight(P,true)
else
P.act.insRight(P,true)
end
if x~=P.curX then P.moving=P.moving-P.gameEnv.arr+1 end
end
else
P.moving=0
end
end
if P.keyPressing[7]and not P.keyPressing[9]then
local d=abs(P.downing)-P.gameEnv.sddas
P.downing=P.downing+1
if d>1 then
if P.gameEnv.sdarr>0 then
if d%P.gameEnv.sdarr==0 then
P.act.down1(P)
end
else
P.act.insDown(P)
end
end
else
P.downing=0
end
if P.falling>=0 then
P.falling=P.falling-1
if P.falling>=0 then
goto stop
else
local L=#P.clearing
if P.human and P.gameEnv.fall>0 and #P.field+L>P.clearing[L]then SFX("fall")end
P.clearing,P.cleared={},{}
end
end
if not P.control then goto stop end
if P.waiting>=0 then
P.waiting=P.waiting-1
if P.waiting==-1 then P:resetblock()end
goto stop
end
if P.curY~=P.y_img then
if P.dropDelay>=0 then
P.dropDelay=P.dropDelay-1
if P.dropDelay>0 then goto stop end
end
P.curY=P.curY-1
P.spinLast=false
if P.y_img~=P.curY then
P.dropDelay=P.gameEnv.drop
elseif P.AI_mode=="CC"then
P.AI_needFresh=true
if not P.AIdata._20G and P.gameEnv.drop<P.AI_delay0*.5 then
CC_switch20G(P)
end
end
if P.freshTime<=P.gameEnv.freshLimit then
P.lockDelay=P.gameEnv.lock
end
else
P.lockDelay=P.lockDelay-1
if P.lockDelay>=0 then goto stop end
P:drop()
if P.AI_mode=="CC"then
P.AI_needFresh=true
end
end
::stop::
if P.b2b1==P.b2b then
elseif P.b2b1<P.b2b then
P.b2b1=min(P.b2b1*.98+P.b2b*.02+.4,P.b2b)
else
P.b2b1=max(P.b2b1*.95+P.b2b*.05-.6,P.b2b)
end
--Alive
else
if not P.small then
P.keySpeed=P.keySpeed*.96+P.stat.key/P.stat.time*60*.04
P.dropSpeed=P.dropSpeed*.96+P.stat.piece/P.stat.time*60*.04
--Final average speeds
if modeEnv.royaleMode then
P.swappingAtkMode=min(P.swappingAtkMode+2,30)
end
end
if P.falling>=0 then
P.falling=P.falling-1
if P.falling>=0 then
goto stop
else
local L=#P.clearing
if P.human and P.gameEnv.fall>0 and #P.field+L>P.clearing[L]then SFX("fall")end
P.clearing,P.cleared={},{}
end
end::stop::
if P.endCounter<40 then
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
end end--Make field visible
end
if P.b2b1>0 then P.b2b1=max(0,P.b2b1*.92-1)end
--Dead
end
if P.stat.score>P.score1 then
if P.stat.score-P.score1<10 then
P.score1=P.score1+1
else
P.score1=int(min(P.score1*.9+P.stat.score*.1+1))
end
end
for i=#P.shade,1,-1 do
local S=P.shade[i]
S[1]=S[1]-1+setting.dropFX*.25
if S[1]<=0 then
rem(P.shade,i)
end
end
if P.fieldOffY>0 then
P.fieldOffY=P.fieldOffY-(P.fieldOffY>3 and 2 or 1)
end
if P.fieldOffX~=0 then
P.fieldOffX=P.fieldOffX-(P.fieldOffX>0 and 1 or -1)
end
for i=#P.bonus,1,-1 do
local b=P.bonus[i]
if b.inf then
if b.t<30 then
b.t=b.t+.5
end
else
b.t=b.t+b.speed
if b.t>=60 then rem(P.bonus,i)end
end
end
for i=#P.atkBuffer,1,-1 do
local A=P.atkBuffer[i]
A.time=A.time+1
if not A.sent then
if A.countdown>0 then
A.countdown=max(A.countdown-garbageSpeed,0)
end
else
if A.time>20 then
rem(P.atkBuffer,i)
end
end
end
if P.fieldBeneath>0 then P.fieldBeneath=max(P.fieldBeneath-pushSpeed,0)end
if not P.small then
PTC.dust[P.id]:update(dt)
end
end
function player.draw(P)
if P.small then
P.frameWait=P.frameWait-1
if P.frameWait==0 then
P.frameWait=8
gc.setCanvas(P.canvas)
gc.clear(0,0,0,.4)
gc.push("transform")
gc.origin()
gc.setColor(1,1,1,P.result and max(20-P.endCounter,0)*.05 or 1)
local F=P.field
for j=1,#F do
for i=1,10 do if F[j][i]>0 then
gc.draw(blockSkinmini[F[j][i]],6*i-6,120-6*j)
end end
end--Field
if P.alive then
gc.setLineWidth(2)
gc.setColor(frameColor[P.strength])gc.rectangle("line",1,1,58,118)
end--Draw boarder
if modeEnv.royaleMode then
gc.setColor(1,1,1)
for i=1,P.strength do
gc.draw(badgeIcon,12*i-7,4,nil,.5)
end
end
if P.result then
gc.setColor(1,1,1,min(P.endCounter,60)*.01)
setFont(22)mStr(P.result,32,47)
setFont(20)mStr(P.rank,30,82)
end
gc.pop()
gc.setCanvas()
--draw content
end
gc.setColor(1,1,1)
gc.draw(P.canvas,P.x,P.y,nil,P.size*10)
if P.killMark then
gc.setLineWidth(3)
gc.setColor(1,0,0,min(P.endCounter,25)*.04)
gc.circle("line",P.centerX,P.centerY,(840-20*min(P.endCounter,30))*P.size)
end
--draw Canvas
else
gc.push("transform")
gc.translate(P.x,P.y)gc.scale(P.size)
--Camera
gc.setColor(0,0,0,.6)gc.rectangle("fill",0,0,600,690)
gc.setLineWidth(7)gc.setColor(frameColor[P.strength])gc.rectangle("line",0,0,600,690,3)
--Frame
gc.translate(150+P.fieldOffX,70+P.fieldOffY)
if P.gameEnv.grid then
gc.setLineWidth(1)
gc.setColor(1,1,1,.2)
for x=1,9 do gc.line(30*x,-10,30*x,600)end
for y=0,19 do
y=30*(y-int(P.fieldBeneath/30))+P.fieldBeneath
gc.line(0,y,300,y)
end
end--Grid
gc.translate(0,P.fieldBeneath)
gc.setScissor(scr.x+P.absFieldX*scr.k,scr.y+P.absFieldY*scr.k,300*P.size*scr.k,610*P.size*scr.k)
if P.falling==-1 then
for j=int(P.fieldBeneath/30+1),#P.field do
for i=1,10 do
if P.field[j][i]>0 then
gc.setColor(1,1,1,min(P.visTime[j][i]*.05,1))
drawPixel(j,i,P.field[j][i])
end
end
end
else--field block only
local dy,stepY=0,setting.smo and(P.falling/(P.gameEnv.fall+1))^2.5*30 or 30
local A=P.falling/P.gameEnv.fall
local h,H=1,#P.field
for j=int(P.fieldBeneath/30+1),H do
while j==P.clearing[h]do
h=h+1
dy=dy+stepY
gc.translate(0,-stepY)
gc.setColor(1,1,1,A)
gc.rectangle("fill",0,630-30*j,300,stepY)
end
for i=1,10 do
if P.field[j][i]>0 then
gc.setColor(1,1,1,min(P.visTime[j][i]*.05,1))
drawPixel(j,i,P.field[j][i])
end
end
end
gc.translate(0,dy)
end--Field with falling animation
for i=1,#P.shade do
local S=P.shade[i]
gc.setColor(1,1,1,S[1]*.12)
for x=S[3],S[5]do
for y=S[6],S[4]do
drawPixel(y,x,S[2])
end
end
end--shade FX
if P.waiting==-1 then
if P.gameEnv.ghost then
gc.setColor(1,1,1,.3)
for i=1,P.r do for j=1,P.c do
if P.cur.bk[i][j]then
drawPixel(i+P.y_img-1,j+P.curX-1,P.cur.color)
end
end end
end--Ghost
-- local dy=setting.smo and(P.y_img~=P.curY and or 1)^4*30 or 0
local dy
if setting.smo then
if P.y_img~=P.curY then
dy=(min(P.dropDelay,1e99)/P.gameEnv.drop-1)*30
else
dy=0
end
--[[
if P.y_img~=P.curY then
dy=(min(P.dropDelay,8e98)/P.gameEnv.drop)^4*30
else
dy=(min(P.lockDelay,8e98)/P.gameEnv.lock)^(P.gameEnv._20G and 3 or 7)*30
end
]]
else
dy=0
end
gc.translate(0,-dy)
local trans=P.lockDelay/P.gameEnv.lock
if P.gameEnv.block then
gc.setColor(1,1,1,trans)
for i=1,P.r do for j=1,P.c do
if P.cur.bk[i][j]then
gc.rectangle("fill",30*(j+P.curX-1)-33,597-30*(i+P.curY-1),36,36)
end
end end--BlockShade(lockdelay indicator)
gc.setColor(1,1,1)
for i=1,P.r do for j=1,P.c do
if P.cur.bk[i][j]then
drawPixel(i+P.curY-1,j+P.curX-1,P.cur.color)
end
end end--Block
end
if P.gameEnv.center then
gc.setColor(1,1,1,trans)
local x=30*(P.curX+P.sc[2]-1)-15
gc.draw(spinCenter,x,600-30*(P.curY+P.sc[1]-1)+15,nil,nil,nil,4,4)
gc.translate(0,dy)
gc.setColor(1,1,1,.5)
gc.draw(spinCenter,x,600-30*(P.y_img+P.sc[1]-1)+15,nil,nil,nil,4,4)
goto E
end--Rotate center
gc.translate(0,dy)
end
::E::
gc.setScissor()--In-playField things
gc.setColor(1,1,1)
gc.draw(PTC.dust[P.id])
gc.translate(0,-P.fieldBeneath)
gc.setBlendMode("replace","alphamultiply")--SPEED UPUP(?)
gc.setLineWidth(2)
gc.rectangle("line",-1,-11,302,612)--Draw boarder
gc.rectangle("line",301,0,15,601)--Draw atkBuffer boarder
local h=0
for i=1,#P.atkBuffer do
local A=P.atkBuffer[i]
local bar=A.amount*30
if h+bar>600 then bar=600-h end
if not A.sent then
if A.time<20 then
bar=bar*(20*A.time)^.5*.05
--Appear
end
if A.countdown>0 then
gc.setColor(attackColor[A.lv][1])
gc.rectangle("fill",303,599-h,11,-bar+3)
gc.setColor(attackColor[A.lv][2])
gc.rectangle("fill",303,599-h+(-bar+3),11,-(-bar+3)*(1-A.countdown/A.cd0))
--Timing
else
local t=math.sin((Timer()-i)*30)*.5+.5
local c1,c2=attackColor[A.lv][1],attackColor[A.lv][2]
gc.setColor(c1[1]*t+c2[1]*(1-t),c1[2]*t+c2[2]*(1-t),c1[3]*t+c2[3]*(1-t))
gc.rectangle("fill",303,599-h,11,-bar+3)
--Warning
end
else
gc.setColor(attackColor[A.lv][1])
bar=bar*(20-A.time)*.05
gc.rectangle("fill",303,599-h,11,-bar+2)
--Disappear
end
h=h+bar
end--Buffer line
local a,b=P.b2b,P.b2b1 if a>b then a,b=b,a end
gc.setColor(.8,1,.2)
gc.rectangle("fill",-14,599,11,-b*.5)
gc.setColor(P.b2b<40 and color.white or P.b2b<=1e3 and color.lightRed or color.lightBlue)
gc.rectangle("fill",-14,599,11,-a*.5)
gc.setColor(1,1,1)
if Timer()%.5<.3 then
gc.rectangle("fill",-15,b<40 and 578.5 or 98.5,13,3)
end
gc.rectangle("line",-16,-3,15,604)--Draw b2b bar boarder
--B2B indictator
gc.translate(-P.fieldOffX,-P.fieldOffY)
gc.setBlendMode("alpha")
if P.gameEnv.hold then
mDraw(drawableText.hold,-82,-10)
if P.holded then gc.setColor(.6,.5,.5)end
local B=P.hd.bk
for i=1,#B do for j=1,#B[1]do
if B[i][j]then
drawPixel(i+17.5-#B*.5,j-2.7-#B[1]*.5,P.hd.color)
end
end end
end--Hold
gc.setColor(1,1,1)
mDraw(drawableText.next,381,-10)
local N=1
::L::
if N<=P.gameEnv.next and P.next[N]then
local b,c=P.next[N].bk,P.next[N].color
for i=1,#b do for j=1,#b[1] do
if b[i][j]then
drawPixel(i+20-2.4*N-#b*.5,j+12.7-#b[1]*.5,c)
end
end end
N=N+1
goto L
end
--Next
gc.setColor(.8,.8,.8)
gc.draw(drawableText.modeName,-135,-65)
gc.draw(drawableText.levelName,437-drawableText.levelName:getWidth(),-65)
gc.setColor(1,1,1)
if frame<180 then
local count=179-frame
gc.push("transform")
gc.translate(155,220)
setFont(100)
if count%60>45 then gc.scale(1+(count%60-45)^2*.01,1)end
mStr(int(count/60+1),0,0)
gc.pop()
end--Draw starting counter
for i=1,#P.bonus do
P.bonus[i]:draw(min((30-abs(P.bonus[i].t-30))*.05,1)*(not P.bonus[i].inf and #P.field>(9-P.bonus[i].dy*.0333)and .7 or 1))
end--Effects
setFont(30)
gc.setColor(1,1,1)
mStr(format("%.2f",P.stat.time),-82,518)--Time
mStr(P.score1,-82,560)--Score
gc.draw(drawableText.bpm,390,490)
gc.draw(drawableText.kpm,350,583)
setFont(30)
drawDial(360,520,P.dropSpeed)
drawDial(405,575,P.keySpeed)
--Speed dials
gc.setColor(1,1,1)
if mesDisp[curMode.id]then mesDisp[curMode.id](P)end--Other messages
if modeEnv.royaleMode then
if P.atkMode then
gc.setColor(1,.8,0,P.swappingAtkMode*.02)
gc.rectangle("fill",RCPB[2*P.atkMode-1],RCPB[2*P.atkMode],90,35,8,4)
end
gc.setColor(1,1,1,P.swappingAtkMode*.025)
gc.draw(royaleCtrlPad)
end
gc.pop()
end
end
function player.demoDraw(P)
gc.push("transform")
gc.translate(P.x,P.y)gc.scale(P.size)gc.translate(P.fieldOffX,P.fieldOffY)
--Camera
gc.setColor(.1,.1,.1,.8)gc.rectangle("fill",0,0,300,600)
gc.setLineWidth(2)gc.setColor(1,1,1)gc.rectangle("line",-1,-1,302,602)
--Frame
if P.falling==-1 then
for j=int(P.fieldBeneath/30+1),#P.field do
for i=1,10 do
if P.field[j][i]>0 then
gc.setColor(1,1,1,min(P.visTime[j][i]*.05,1))
drawPixel(j,i,P.field[j][i])
end
end
end
else--field block only
local dy,stepY=0,setting.smo and(P.falling/(P.gameEnv.fall+1))^2.5*30 or 30
local A=P.falling/P.gameEnv.fall
local h,H=1,#P.field
for j=int(P.fieldBeneath/30+1),H do
while j==P.clearing[h]do
h=h+1
dy=dy+stepY
gc.translate(0,-stepY)
gc.setColor(1,1,1,A)
gc.rectangle("fill",0,630-30*j,300,stepY)
end
for i=1,10 do
if P.field[j][i]>0 then
gc.setColor(1,1,1,min(P.visTime[j][i]*.05,1))
drawPixel(j,i,P.field[j][i])
end
end
end
gc.translate(0,dy)
end--Field with falling animation
for i=1,#P.shade do
local S=P.shade[i]
gc.setColor(1,1,1,S[1]*.12)
for x=S[3],S[5]do
for y=S[6],S[4]do
drawPixel(y,x,S[2])
end
end
end--shade FX
if P.waiting==-1 then
gc.setColor(1,1,1,.3)
for i=1,P.r do for j=1,P.c do
if P.cur.bk[i][j]then
drawPixel(i+P.y_img-1,j+P.curX-1,P.cur.color)
end
end end
--Ghost draw
gc.setColor(1,1,1)
for i=1,P.r do for j=1,P.c do
if P.cur.bk[i][j]then
drawPixel(i+P.curY-1,j+P.curX-1,P.cur.color)
end
end end--Block
end
gc.setColor(1,1,1,.3)
local N=miniBlock[P.hd.id]
if N then
gc.draw(N,15,30,nil,16,nil,0,N:getHeight()*.5)
end
local N=1
::L::
if N<=P.gameEnv.next and P.next[N]then
local p=miniBlock[P.next[N].id]
gc.draw(p,285,40*N-10,nil,16,nil,p:getWidth(),p:getHeight()*.5)
N=N+1
goto L
end
--Next
gc.setColor(1,1,1)
gc.draw(PTC.dust[P.id])
gc.translate(-P.fieldOffX,-P.fieldOffY)
for i=1,#P.bonus do
P.bonus[i]:draw(min((30-abs(P.bonus[i].t-30))*.05,1)*(not P.bonus[i].inf and #P.field>(9-P.bonus[i].dy*.0333)and .7 or 1))
end--Effects
gc.pop()
end
-------------------------<FX>-------------------------
function player:showText(text,type,font,dy,spd,inf)
if not self.small then
self.bonus[#self.bonus+1]={t=0,text=text,draw=textFX[type],font=font,dy=dy or 0,speed=spd or 1,inf=inf}
end
end
function player:createShade(x1,y1,x2,y2)--x1<x2,y1>y2
if self.gameEnv.block and y1>=y2 then
self.shade[#self.shade+1]={5,self.cur.color,x1,y1,x2,y2}
end
end
function player:createBeam(R,send,time,target,color,clear,spin,mini,combo)
local x1,y1,x2,y2
if self.small then x1,y1=self.centerX,self.centerY
else x1,y1=self.x+(30*(self.curX+self.sc[2]-1)-30+15+150)*self.size,self.y+(600-30*(self.curY+self.sc[1]-1)+15+70)*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 radius,corner
local a,r,g,b=1,unpack(blockColor[color])
if clear>10 then
radius=10+3*send+100/(target+4)
local t=clear%10
if t==1 then
corner=3
r=.3+r*.4
g=.3+g*.4
b=.3+b*.4
elseif t==2 then
corner=5
r=.5+r*.5
g=.5+g*.5
b=.5+b*.5
elseif t<6 then
corner=6
r=.6+r*.4
g=.6+g*.4
b=.6+b*.4
else
r=.8+r*.2
g=.8+g*.2
b=.8+b*.2
corner=20
end
else
if combo>3 then
radius=min(15+combo,30)
corner=3
else
radius=30
corner=4
end
r=1-r*.3
g=1-g*.3
b=1-b*.3
end
if modeEnv.royaleMode and not(self.human or R.human)then
radius=radius*.4
a=.35
end
FX_attack[#FX_attack+1]={
x=x1,y=y1,--current pos
x1=x1,y1=y1,--start pos
x2=x2,y2=y2,--end pos
rad=radius*(setting.atkFX+2)*.2,
corner=corner,
type=type==1 and"fill"or"line",
r=r,g=g,b=b,a=a*(setting.atkFX+1)*.25,
t=0,
drag={},--Afterimage coordinate list
}
end
-------------------------</FX>-------------------------
-------------------------<Method>-------------------------
local function ifoverlap(P,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
for i=1,#bk do
if P.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
end
end
end
end
local function ckfull(P,i)
for j=1,10 do if P.field[i][j]<=0 then return end end
return true
end
local function checkrow(P,start,height)--(cy,r)
local c=0
local h=start
for i=1,height do
if ckfull(P,h)then
ins(P.clearing,h)
ins(P.cleared,h+c)
removeRow(P.field,h)
removeRow(P.visTime,h)
c=c+1
if not P.small then
local S=PTC.dust[P.id]
for _=1,100 do
S:setPosition(rnd(300),630-30*(h+c)+rnd(30))
S:emit(2)
end
end
else
h=h+1
end
end
h=#P.field
for i=c,1,-1 do
if P.clearing[i]>h then
P.clearing[i]=nil
end
end
return c
end
local function solid(P,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][x]>0
end
local function getBlockDirection(P)
return(P.curX+P.sc[2]-6.5)*.15
end
function player:fineError(rate)
self.stat.extraPiece=self.stat.extraPiece+1
self.stat.extraRate=self.stat.extraRate+rate
if self.human then
if self.gameEnv.fineKill then
SFX("error_long")
Event.lose(self)
elseif setting.fine then
SFX("error")
end
elseif self.gameEnv.fineKill then
Event.lose(self)
end
end
function player:garbageSend(R,send,time,...)
if setting.atkFX>0 then
self:createBeam(R,send,time,...)
end
R.lastRecv=self
if R.atkBuffer.sum<20 then
local B=R.atkBuffer
if B.sum+send>20 then send=20-B.sum end--no more then 20
local m,k=#B,1
while k<=m and time>B[k].countdown do k=k+1 end
for i=m,k,-1 do
B[i+1]=B[i]
end
B[k]={
pos=rnd(10),
amount=send,
countdown=time,
cd0=time,
time=0,
sent=false,
lv=min(int(send^.69),5),
}--Sorted insert(by time)
B.sum=B.sum+send
R.stat.recv=R.stat.recv+send
if R.human then
SFX(send<4 and "blip_1"or"blip_2",min(send+1,5)*.1)
end
end
end
function player:garbageRelease()
local n,flag=1
::L::
local A=self.atkBuffer[n]
if A and A.countdown<=0 and not A.sent then
self:garbageRise(8+A.lv,A.amount,A.pos)
self.atkBuffer.sum=self.atkBuffer.sum-A.amount
A.sent,A.time=true,0
self.stat.pend=self.stat.pend+A.amount
n=n+1
flag=true
else
goto E
end
goto L
::E::
if flag and self.AI_mode=="CC"then CC_updateField(self)end
end
function player:garbageRise(color,amount,pos)
local t=self.showTime*2
for _=1,amount do
ins(self.field,1,getNewRow(color))
ins(self.visTime,1,getNewRow(t))
self.field[1][pos]=0
end
self.fieldBeneath=self.fieldBeneath+amount*30
self.curY=self.curY+amount
self:freshgho()
for i=1,#self.clearing do
self.clearing[i]=self.clearing[i]+amount
end
for i=1,#self.shade do
local S=self.shade[i]
S[4],S[6]=S[4]+amount,S[6]+amount
end
if #self.field>40 then Event.lose(self)end
end
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 self.atkMode==2 then
self:changeAtk(self~=mostBadge and mostBadge or secBadge or randomTarget(self))
elseif self.atkMode==3 then
self:changeAtk(self~=mostDangerous and mostDangerous or 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(m)
if self.atkMode==m then return end
self.atkMode=m
if m==1 then
self:changeAtk(randomTarget(self))
elseif m==2 then
self:freshTarget()
elseif m==3 then
self:freshTarget()
elseif m==4 then
self:changeAtk()
end
::L::
end
function player:changeAtk(R)
-- if not self.human then R=players[1]end--Delete first "--" to enable 1vALL mode
if self.atking then
local K=self.atking.atker
for i=1,#K do
if K[i]==self then
rem(K,i)
goto L
end
end
end
::L::
if R then
self.atking=R
R.atker[#R.atker+1]=self
else
self.atking=nil
end
end
function player:freshgho()
self.y_img=min(#self.field+1,self.curY)
if self.gameEnv._20G or self.keyPressing[7]and self.gameEnv.sdarr==0 then
while not ifoverlap(self,self.cur.bk,self.curX,self.y_img-1)do
self.y_img=self.y_img-1
self.spinLast=false
end
if self.curY>self.y_img then
if not self.small then
if setting.dropFX>0 then
self:createShade(self.curX,self.curY+1,self.curX+self.c-1,self.y_img+self.r-1)
end
if setting.shakeFX>0 then
self.fieldOffY=2*setting.shakeFX+1
end
end
self.curY=self.y_img
end
else
while not ifoverlap(self,self.cur.bk,self.curX,self.y_img-1)do
self.y_img=self.y_img-1
end
end
end
function player:freshLockDelay()
if self.lockDelay<self.gameEnv.lock then
self.dropDelay=self.gameEnv.drop
self.freshTime=self.freshTime+1
if self.freshTime<=self.gameEnv.freshLimit then
self.lockDelay=self.gameEnv.lock
end
end
end
function player:lock()
for i=1,self.r do
local y=self.curY+i-1
if not self.field[y]then self.field[y],self.visTime[y]=getNewRow(0),getNewRow(0)end
for j=1,self.c do
if self.cur.bk[i][j]then
self.field[y][self.curX+j-1]=self.cur.color
self.visTime[y][self.curX+j-1]=self.showTime
end
end
end
end
function player:spin(d,ifpre)
local idir=(self.dir+d)%4
--<Ospin>
if self.cur.id==6 then
if self.gameEnv.easyFresh then
self:freshLockDelay()
end
if self.gameEnv.ospin then
if self.curY==self.y_img then
self.spinSeq=self.spinSeq%100*10+d
local x,y=self.curX,self.curY
local id
if self.spinSeq==313 then--Z
if solid(self,x-1,y)and solid(self,x+2,y)then
if solid(self,x-1,y+2)and not solid(self,x-1,y+1)then--嵌
self.curX=x-1
self.dir=2
id=1
elseif not solid(self,x+1,y-1)and not solid(self,x+2,y-1)then--压
self.curY=y-1
self.dir=2
id=1
end
end
elseif self.spinSeq==131 then--S
if solid(self,x-1,y)and solid(self,x+2,y)then
if solid(self,x+2,y+2)and not solid(self,x+2,y+1)then--嵌
self.dir=2
id=2
elseif not solid(self,x,y-1)and not solid(self,x-1,y-1)then--压
self.curY=y-1
self.curX=x-1
self.dir=2
id=2
end
end
elseif self.spinSeq==331 then--L
if solid(self,x-1,y+1)and solid(self,x+2,y+1)then
if solid(self,x+2,y)and not solid(self,x-1,y)then--钩
self.curX=x-1
self.dir=0
id=3
elseif not solid(self,x,y-1)and not solid(self,x+2,y)then--扣
self.curY=y-1
self.dir=2
id=3
end
end
elseif self.spinSeq==113 then--J
if solid(self,x+2,y+1)and solid(self,x-2,y+1)then
if solid(self,x-2,y)and not solid(self,x+2,y)then--钩
self.dir=0
id=4
elseif not solid(self,x+1,y-1)and not solid(self,x-1,y)then--扣
self.curX=x-1
self.curY=y-1
self.dir=2
id=4
end
end
elseif self.spinSeq==111 then--T-R
if solid(self,x+2,y+1)and solid(self,x-1,y+1)and solid(self,x+2,y)and not solid(self,x-1,y)then
if solid(self,x,y-1)then--钩
self.curX=x-1
self.dir=0
id=5
else--转
self.curY=y-1
self.dir=1
id=5
end
end
elseif self.spinSeq==333 then--T-L
if solid(self,x-1,y+1)and solid(self,x-1,y)and solid(self,x+2,y+1)and not solid(self,x+2,y)then
if solid(self,x+1,y-1)then--钩
self.dir=0
id=5
else--转
self.curY=y-1
self.dir=3
id=5
end
end
elseif self.spinSeq==222 then--I
if solid(self,x+2,y+1)and solid(self,x-1,y+1)then
if not solid(self,x-1,y)then
if not solid(self,x+2,y)then
self.curX=x-1
self.dir=2
id=7
elseif not solid(self,x-2,y)then
self.curX=x-2
self.dir=2
id=7
end
elseif not solid(self,x+2,y)and not solid(self,x+3,y)then
self.dir=2
id=7
end
end
end
if id then--Transform successed
local C=self.cur
C.id=id
C.bk=blocks[id][self.dir]
self.r,self.c=#C.bk,#C.bk[1]
self.sc=scs[id][self.dir]
self.spinLast=2
self.stat.rotate=self.stat.rotate+1
self:freshgho()
SFX("rotatekick",nil,getBlockDirection(self))
return
end
else
self.spinSeq=0
end
end
if self.human then
SFX(ifpre and"prerotate"or"rotate",nil,getBlockDirection(self))
end
return
end
--</Ospin>
local icb=blocks[self.cur.id][idir]
local isc=scs[self.cur.id][idir]
local ir,ic=#icb,#icb[1]
local ix,iy=self.curX+self.sc[2]-isc[2],self.curY+self.sc[1]-isc[1]
local t--succssful test
local iki=self.RS[self.cur.id][self.dir*10+idir]
for i=1,self.freshTime<=1.2*self.gameEnv.freshLimit and #iki or 1 do
if not ifoverlap(self,icb,ix+iki[i][1],iy+iki[i][2])then
ix,iy=ix+iki[i][1],iy+iki[i][2]
t=i
goto spin
end
end
do return end
::spin::
if not self.small and setting.dropFX>0 then
self:createShade(self.curX,self.curY+self.r-1,self.curX+self.c-1,self.curY)
end
local y0=self.curY
self.curX,self.curY,self.dir=ix,iy,idir
self.sc,self.cur.bk=scs[self.cur.id][idir],icb
self.r,self.c=ir,ic
self.spinLast=t==2 and 0 or 1
if not ifpre then self:freshgho()end
if self.gameEnv.easyFresh or y0>self.curY then self:freshLockDelay()end
if self.human then
SFX(ifpre and"prerotate"or ifoverlap(self,self.cur.bk,self.curX,self.curY+1)and ifoverlap(self,self.cur.bk,self.curX-1,self.curY)and ifoverlap(self,self.cur.bk,self.curX+1,self.curY)and"rotatekick"or"rotate",nil,getBlockDirection(self))
end
self.stat.rotate=self.stat.rotate+1
end
function player:hold(ifpre)
if not self.holded and self.waiting==-1 and self.gameEnv.hold then
--Finesse check
local H,B=self.hd,self.cur
if H and H.id==B.id and H.name==B.name then
self:fineError(1.5)
elseif self.ctrlCount>1 then
self:fineError(2)
end
self.holded=self.gameEnv.oncehold
self.spinLast=false
self.ctrlCount=0
self.spinSeq=0
self.cur,self.hd=self.hd,self.cur
self.hd.bk=blocks[self.hd.id][0]
if self.cur.id==0 then
self.cur=rem(self.next,1)
self:freshNext()
if self.AI_mode=="CC"then BOT.addNext(self.AI_bot,CCblockID[self.next[self.AIdata.next].id])end
end
self.sc,self.dir=scs[self.cur.id][0],0
self.r,self.c=#self.cur.bk,#self.cur.bk[1]
self.curX,self.curY=blockPos[self.cur.id],21+ceil(self.fieldBeneath/30)-self.r+min(int(#self.field*.2),2)
if abs(self.moving)>self.gameEnv.das and not ifoverlap(self,self.cur.bk,self.curX+(self.moving>0 and 1 or -1),self.curY)then
self.curX=self.curX+(self.moving>0 and 1 or -1)
end
--IMS
self:freshgho()
self.dropDelay,self.lockDelay,self.freshTime=self.gameEnv.drop,self.gameEnv.lock,max(self.freshTime-5,0)
if ifoverlap(self,self.cur.bk,self.curX,self.curY)then self:lock()Event.lose(self)end
if self.human then
SFX(ifpre and"prehold"or"hold")
end
self.stat.hold=self.stat.hold+1
end
end
function player:newNext(n)
self.next[#self.next+1]={bk=blocks[n][0],id=n,color=self.gameEnv.bone and 8 or n,name=n}
end
function player:resetblock()
self.holded=false
self.spinLast=false
self.spinSeq=0
self.ctrlCount=0
self.cur=rem(self.next,1)
self:freshNext()
if self.AI_mode=="CC"then BOT.addNext(self.AI_bot,CCblockID[self.next[self.AIdata.next].id])end
self.sc,self.dir=scs[self.cur.id][0],0--spin center/direction
self.r,self.c=#self.cur.bk,#self.cur.bk[1]--row/column
self.curX,self.curY=blockPos[self.cur.id],21+ceil(self.fieldBeneath/30)+min(int(#self.field*.15)-self.r,0)--初始高度7格+1,14格+2(非I)
self.dropDelay,self.lockDelay,self.freshTime=self.gameEnv.drop,self.gameEnv.lock,0
if self.keyPressing[8]then self:hold(true)end
if self.keyPressing[3]then self:spin(1,true)end
if self.keyPressing[4]then self:spin(3,true)end
if self.keyPressing[5]then self:spin(2,true)end
if abs(self.moving)>self.gameEnv.das and not ifoverlap(self,self.cur.bk,self.curX+(self.moving>0 and 1 or -1),self.curY)then
self.curX=self.curX+(self.moving>0 and 1 or -1)
end
--Initial SYSs
if ifoverlap(self,self.cur.bk,self.curX,self.curY)then self:lock()Event.lose(self)end
self:freshgho()
if self.keyPressing[6]then self.act.hardDrop(self)self.keyPressing[6]=false end
end
function player:drop()--Place piece
self.dropTime[11]=ins(self.dropTime,1,frame)--update speed dial
self.waiting=self.gameEnv.wait
local dospin=0
if self.spinLast then
if self.cur.id<6 then
local x,y=self.curX+self.sc[2]-1,self.curY+self.sc[1]-1
local c=0
if solid(self,x-1,y+1)then c=c+1 end
if solid(self,x+1,y+1)then c=c+1 end
if c==0 then goto NTC end
if solid(self,x-1,y-1)then c=c+1 end
if solid(self,x+1,y-1)then c=c+1 end
if c>2 then dospin=dospin+1 end
end--Three point
::NTC::
if self.cur.id~=6 and ifoverlap(self,self.cur.bk,self.curX-1,self.curY)and ifoverlap(self,self.cur.bk,self.curX+1,self.curY)and ifoverlap(self,self.cur.bk,self.curX,self.curY+1)then
dospin=dospin+2
end--Immobile
end
self:lock()
local CHN=getFreeVoiceChannel()
local cc,send,exblock=checkrow(self,self.curY,self.r),0,0--Currect clear&send&sendTime
if self.clearing[1]then self.falling=self.gameEnv.fall end
local cscore,sendTime=0,0
local mini
if self.spinLast then
if cc>0 then
if dospin>0 then
dospin=dospin+self.spinLast
if dospin<2 then
mini=self.cur.id<6 and cc<3 and cc<self.r
end
else
dospin=false
end
elseif cc==0 then
if dospin==0 then
dospin=false
end
end
else
dospin=false
end
--极简检测
if self.curY>18 then goto 通过测试 end--高处易误判
do
local y0=self.curY
local x,c=self.curX,self.c
local B=self.cur.bk
for x=1,c do
local y
for i=#B,1,-1 do
if B[i][x]then y=i;goto 继续 end
end
goto 操作判断法
::继续::
if y then
x=self.curX+x-1
for y=y0+y,#self.field do
if solid(self,x,y)then goto 通过测试 end
end
end
end--遮挡暂时都算最简
::操作判断法::
if dospin then self.ctrlCount=self.ctrlCount-2 end--对无遮挡spin宽松两步
local id=self.cur.id
local dir=self.dir+1
if id<3 or id==7 then
if dir>2 then
dir=dir-2
end
end--SZI的逆态视为顺态
local R,I=self.ctrlCount,finesseCtrlPar[id][dir][self.curX]--Real key/Ideal key
local d=R-I
if d<=0 then
goto 通过测试
end
if I==0 then I=1 end
local rate=R/I
if rate>2.5 then rate=2.5 end
self:fineError(rate)
end
::通过测试::
if cc>0 then
self.combo=self.combo+1
if cc==4 then
cscore=1000
if self.b2b>1000 then
self:showText(text.techrashB3B,"fly",80,-30)
send=6
sendTime=100
exblock=exblock+1
cscore=cscore*1.8
self.stat.b3b=self.stat.b3b+1
if self.human then
VOICE("b3b",CHN)
end
elseif self.b2b>=50 then
self:showText(text.techrashB2B,"drive",80,-30)
sendTime=80
send=5
cscore=cscore*1.3
self.stat.b2b=self.stat.b2b+1
if self.human then
VOICE("b2b",CHN)
end
else
self:showText(text.techrash,"stretch",80,-30)
sendTime=60
send=4
end
self.b2b=self.b2b+120
self.lastClear=74
self.stat.clear_4=self.stat.clear_4+1
if self.human then
VOICE("tts",CHN)
end
elseif cc>0 then
local clearKey=clear_n
if dospin then
cscore=spinSCR[self.cur.name][cc]
if self.b2b>1000 then
self:showText(text.b3b..text.spin[self.cur.name]..text.clear[cc],"spin",40,-30)
send=b2bATK[cc]+1
exblock=exblock+1
cscore=cscore*2
self.stat.b3b=self.stat.b3b+1
if self.human then
VOICE("b3b",CHN)
end
elseif self.b2b>=50 then
self:showText(text.b2b..text.spin[self.cur.name]..text.clear[cc],"spin",40,-30)
send=b2bATK[cc]
cscore=cscore*1.2
self.stat.b2b=self.stat.b2b+1
if self.human then
VOICE("b2b",CHN)
end
else
self:showText(text.spin[self.cur.name]..text.clear[cc],"spin",50,-30)
send=2*cc
end
sendTime=20+send*20
if mini then
self:showText(text.mini,"appear",40,-80)
send=ceil(send*.5)
sendTime=sendTime+60
cscore=cscore*.5
self.b2b=self.b2b+b2bPoint[cc]*.5
if self.human then
VOICE("mini",CHN)
end
else
self.b2b=self.b2b+b2bPoint[cc]
end
self.lastClear=self.cur.id*10+cc
clearKey=spin_n
if self.human then
SFX(spin_n[cc])
VOICE(blockName[self.cur.name],CHN)
VOICE("spin_",CHN)
end
elseif #self.field>0 then
self.b2b=max(self.b2b-250,0)
self:showText(text.clear[cc],"appear",32+cc*3,-30,(8-cc)*.3)
send=cc-1
sendTime=20+send*20
cscore=cscore+clearSCR[cc]
self.lastClear=cc
end
self.stat[clearKey[cc]]=self.stat[clearKey[cc]]+1
if self.human then
VOICE(clearName[cc],CHN)
end
end
send=send+(renATK[self.combo]or 3)
if #self.field==0 then
self:showText(text.PC,"flicker",70,-80)
send=min(send,3)+min(6+self.stat.pc,10)
exblock=exblock+2
sendTime=sendTime+60
if self.stat.row>4 then
self.b2b=1200
cscore=cscore+500*min(6+self.stat.pc,10)
else
cscore=cscore+500
end
self.stat.pc=self.stat.pc+1
self.lastClear=self.cur.id*10+5
if self.human then
SFX("perfectclear")
VOICE("pc",CHN)
end
end
if self.combo>2 then
self:showText(text.cmb[min(self.combo,20)],self.combo<10 and"appear"or"flicker",20+min(self.combo,25)*3,60)
cscore=cscore+min(20*self.combo,300)*cc
end
sendTime=sendTime+25*self.combo
if self.human then
SFX(clear_n[cc])
SFX(ren_n[min(self.combo,11)])
if self.combo>14 then SFX("ren_mega",(self.combo-10)*.1)end
VIB(cc+1)
end
if self.b2b>1200 then self.b2b=1200 end
if modeEnv.royaleMode then
local i=min(#self.atker,9)
if i>1 then
send=send+reAtk[i]
exblock=exblock+reDef[i]
end
end--Counter attack
if send>0 then
self.stat.atk=self.stat.atk+send
--ATK statistics
if exblock then exblock=int(exblock*(1+self.strength*.25))end
send=send*(1+self.strength*.25)
if mini then send=send*.8 end
send=int(send)
--Badge Buff
if send==0 then goto L end
self:showText(send,"zoomout",40,70)
if exblock==0 then goto L end
self:showText(exblock,"zoomout",20,115)
::L::
send=send+exblock
local k=0
::R::
if self.atkBuffer.sum>0 and send>0 then
::F::
k=k+1
local A=self.atkBuffer[k]
if not A then goto E end
if A.sent then goto F end
if send>=A.amount then
send=send-A.amount
self.atkBuffer.sum=self.atkBuffer.sum-A.amount
A.sent,A.time=true,0
if send>0 then goto R end
else
A.amount=A.amount-send
self.atkBuffer.sum=self.atkBuffer.sum-send
send=0
end
end
::E::
send=send-exblock
if send>0 then
local T
if modeEnv.royaleMode then
if self.atkMode==4 then
local M=#self.atker
if M>0 then
for i=1,M do
self:garbageSend(self.atker[i],send,sendTime,M,self.cur.color,self.lastClear,dospin,mini,self.combo)
end
else
T=randomTarget(self)
end
else
self:freshTarget()
T=self.atking
end
elseif #players.alive>1 then
T=randomTarget(self)
end
if T then
self:garbageSend(T,send,sendTime,1,self.cur.color,self.lastClear,dospin,mini,self.combo)
end
self.stat.send=self.stat.send+send
if self.human and send>3 then SFX("emit",min(send,8)*.1)end
end
end
else
self.combo=0
if dospin then
self:showText(text.spin[self.cur.name],"appear",50,-30)
self.b2b=self.b2b+20
self.stat.spin_0=self.stat.spin_0+1
if self.human then
SFX("spin_0")
VOICE(blockName[self.cur.name],CHN)
VOICE("spin",CHN)
end
cscore=cscore+30
end
cscore=cscore+10
if self.b2b>1000 then
self.b2b=max(self.b2b-40,1000)
end
self:garbageRelease()
end
self.stat.score=self.stat.score+cscore
self.stat.piece,self.stat.row=self.stat.piece+1,self.stat.row+cc
Event[self.gameEnv.dropPiece](self)
if self.human then SFX("lock",nil,getBlockDirection(self))end
end
function player:pressKey(i)
self.keyPressing[i]=true
if self.id==1 then
virtualkeyDown[i]=true
virtualkeyPressTime[i]=10
end
if self.alive then
self.act[actName[i]](self)
self.keyTime[11]=ins(self.keyTime,1,frame)
self.stat.key=self.stat.key+1
end
--ins(rec,{i,frame})
end
function player:releaseKey(i)
self.keyPressing[i]=false
if self.id==1 then virtualkeyDown[i]=false end
-- if recording then ins(rec,{-i,frame})end
end
-------------------------</Methods>-------------------------
-------------------------<Controls>-------------------------
player.act={}
function player.act.moveLeft(P,auto)
if not auto then
P.ctrlCount=P.ctrlCount+1
end
if P.keyPressing[9]then
if P.gameEnv.swap then
P:changeAtkMode(1)
end
elseif P.control and P.waiting==-1 then
if not ifoverlap(P,P.cur.bk,P.curX-1,P.curY)then
P.curX=P.curX-1
local y0=P.curY
P:freshgho()
if P.gameEnv.easyFresh or y0~=P.curY then P:freshLockDelay()end
if P.human and P.curY==P.y_img then SFX("move")end
P.spinLast=false
if not auto then
P.moving=-1
end
else
P.moving=-P.gameEnv.das-1
end
else
P.moving=-1
end
end
function player.act.moveRight(P,auto)
if not auto then
P.ctrlCount=P.ctrlCount+1
end
if P.keyPressing[9]then
if P.gameEnv.swap then
P:changeAtkMode(2)
end
elseif P.control and P.waiting==-1 then
if not ifoverlap(P,P.cur.bk,P.curX+1,P.curY)then
P.curX=P.curX+1
local y0=P.curY
P:freshgho()
if P.gameEnv.easyFresh or y0~=P.curY then P:freshLockDelay()end
if P.human and P.curY==P.y_img then SFX("move")end
P.spinLast=false
if not auto then
P.moving=1
end
else
P.moving=P.gameEnv.das+1
end
else
P.moving=1
end
end
function player.act.rotRight(P)
if P.control and P.waiting==-1 then
P.ctrlCount=P.ctrlCount+1
P:spin(1)
P.keyPressing[3]=false
end
end
function player.act.rotLeft(P)
if P.control and P.waiting==-1 then
P.ctrlCount=P.ctrlCount+1
P:spin(3)
P.keyPressing[4]=false
end
end
function player.act.rotFlip(P)
if P.control and P.waiting==-1 then
P.ctrlCount=P.ctrlCount+2
P:spin(2)
P.keyPressing[5]=false
end
end
function player.act.hardDrop(P)
if P.keyPressing[9]then
if P.gameEnv.swap then
P:changeAtkMode(3)
end
P.keyPressing[6]=false
elseif P.control and P.waiting==-1 then
if P.curY~=P.y_img then
if not P.small then
if setting.dropFX>0 then
P:createShade(P.curX,P.curY+1,P.curX+P.c-1,P.y_img+P.r-1)
end
if setting.shakeFX>0 then
P.fieldOffY=2*setting.shakeFX+1
end
end
P.curY=P.y_img
P.spinLast=false
if P.human then
SFX("drop",nil,getBlockDirection(P))
VIB(1)
end
end
P.lockDelay=-1
P:drop()------------------------------------BUG:drop==number?
P.keyPressing[6]=false
end
end
function player.act.softDrop(P)
if P.keyPressing[9]then
if P.gameEnv.swap then
P:changeAtkMode(4)
end
else
P.downing=1
if P.control and P.waiting==-1 then
if P.curY~=P.y_img then
P.curY=P.curY-1
P.spinLast=false
end
end
end
end
function player.act.hold(P)
if P.control and P.waiting==-1 then
P:hold()
end
end
function player.act.func(P)
P.gameEnv.Fkey(P)
end
function player.act.restart(P)
if P.gameEnv.quickR or frame<180 then
clearTask("play")
resetPartGameData()
end
end
function player.act.insLeft(P,auto)
local x0,y0=P.curX,P.curY
while not ifoverlap(P,P.cur.bk,P.curX-1,P.curY)do
P.curX=P.curX-1
if not P.small and setting.dropFX>0 then
P:createShade(P.curX+1,P.curY+P.r-1,P.curX+1,P.curY)
end
P:freshgho()
end
if x0~=P.curX then
if P.human and setting.shakeFX>0 then
P.fieldOffX=-2*setting.shakeFX
end
if P.gameEnv.easyFresh or y0~=P.curY then P:freshLockDelay()end
end
if auto then
if P.ctrlCount==0 then P.ctrlCount=1 end
else
P.ctrlCount=P.ctrlCount+1
end
end
function player.act.insRight(P,auto)
local x0,y0=P.curX,P.curY
while not ifoverlap(P,P.cur.bk,P.curX+1,P.curY)do
P.curX=P.curX+1
if not P.small and setting.dropFX>0 then
P:createShade(P.curX+P.c-1,P.curY+P.r-1,P.curX+P.c-1,P.curY)
end
P:freshgho()
end
if x0~=P.curX then
if P.human and setting.shakeFX>0 then
P.fieldOffX=2*setting.shakeFX
end
if P.gameEnv.easyFresh or y0~=P.curY then P:freshLockDelay()end
end
if auto then
if P.ctrlCount==0 then P.ctrlCount=1 end
else
P.ctrlCount=P.ctrlCount+1
end
end
function player.act.insDown(P)
if P.curY~=P.y_img then
if not P.small then
if setting.dropFX>0 then
P:createShade(P.curX,P.curY+1,P.curX+P.c-1,P.y_img+P.r-1)
end
if setting.shakeFX>0 then
P.fieldOffY=2*setting.shakeFX
end
end
P.curY,P.lockDelay,P.spinLast=P.y_img,P.gameEnv.lock,false
end
end
function player.act.down1(P)
if P.curY~=P.y_img then
P.curY=P.curY-1
P.spinLast=false
end
end
function player.act.down4(P)
for _=1,4 do
if P.curY~=P.y_img then
P.curY=P.curY-1
P.spinLast=false
else
break
end
end
end
function player.act.down10(P)
for _=1,10 do
if P.curY~=P.y_img then
P.curY=P.curY-1
P.spinLast=false
else
break
end
end
end
function player.act.dropLeft(P)
P.act.insLeft(P)
P.act.hardDrop(P)
end
function player.act.dropRight(P)
P.act.insRight(P)
P.act.hardDrop(P)
end
function player.act.addLeft(P)
P.act.insLeft(P)
P.act.insDown(P)
P.act.insRight(P)
P.act.hardDrop(P)
end
function player.act.addRight(P)
P.act.insRight(P)
P.act.insDown(P)
P.act.insLeft(P)
P.act.hardDrop(P)
end
-------------------------</Controls>-------------------------