diff --git a/parts/AITemplate.lua b/parts/AITemplate.lua index 9d8960fe..80331f40 100644 --- a/parts/AITemplate.lua +++ b/parts/AITemplate.lua @@ -1,4 +1,3 @@ -local int=math.floor local AISpeed={60,50,45,35,25,15,9,6,4,3} return function(type,speedLV,next,hold,node) if type=="CC"then @@ -12,7 +11,7 @@ return function(type,speedLV,next,hold,node) elseif type=="9S"then return{ type="9S", - delta=int(AISpeed[speedLV]*.5), + delta=math.floor(AISpeed[speedLV]*.5), } end end \ No newline at end of file diff --git a/parts/player.lua b/parts/player.lua index cc9f880c..bde5d197 100644 --- a/parts/player.lua +++ b/parts/player.lua @@ -1027,6 +1027,274 @@ local function Pdraw_demo(P) end ---------------------------------------------------- +---------------------------------------------------- +local function pressKey(P,i) + P.keyPressing[i]=true + P.act[i](P) + if P.control then + if P.keyRec then + ins(P.keyTime,1,game.frame) + P.keyTime[11]=nil + end + P.stat.key=P.stat.key+1 + end +end +local function releaseKey(P,i) + P.keyPressing[i]=false +end +local function pressKey_Rec(P,i) + if game.recording then + ins(game.rec,game.frame) + ins(game.rec,i) + end + P.keyPressing[i]=true + P.act[i](P) + if P.control then + if P.keyRec then + ins(P.keyTime,1,game.frame) + P.keyTime[11]=nil + end + P.stat.key=P.stat.key+1 + end +end +local function releaseKey_Rec(P,i) + if game.recording then + ins(game.rec,game.frame) + ins(game.rec,-i) + end + P.keyPressing[i]=false +end +local function without(L,e) + for i=1,#L do + if L[i]==e then return end + end + return true +end +local function getNewStatTable() + local T={ + time=0,score=0, + key=0,rotate=0,hold=0, + extraPiece=0,extraRate=0, + piece=0,row=0,dig=0, + atk=0,digatk=0, + send=0,recv=0,pend=0,off=0, + clear={},clears={},spin={},spins={}, + pc=0,hpc=0,b2b=0,b3b=0, + } + for i=1,25 do + T.clear[i]={0,0,0,0,0} + T.spin[i]={0,0,0,0,0} + T.clears[i]=0 + T.spins[i]=0 + end + return T +end +local function newEmptyPlayer(id,x,y,size) + local P={id=id} + players[id]=P + players.alive[id]=P + + --Inherit functions of player class + for k,v in next,player do P[k]=v end + if P.id==1 and game.recording then + P.pressKey=pressKey_Rec + P.releaseKey=releaseKey_Rec + else + P.pressKey=pressKey + P.releaseKey=releaseKey + end + P.update=Pupdate_alive + + P.fieldOff={x=0,y=0,vx=0,vy=0}--For shake FX + P.x,P.y,P.size=x,y,size or 1 + P.frameColor=frameColor[0] + + P.small=P.size<.1--If draw in small mode + 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) + P.draw=Pdraw_small + else + P.keyRec=true--If calculate keySpeed + P.centerX,P.centerY=P.x+300*P.size,P.y+370*P.size + P.absFieldX=P.x+150*P.size + P.absFieldY=P.y+60*P.size + P.draw=Pdraw_norm + P.bonus={}--Text objects + end + P.randGen=mt.newRandomGenerator(game.seed) + + P.small=false + P.alive=true + P.control=false + P.timing=false + P.stat=getNewStatTable() + + P.modeData={point=0,event=0,counter=0}--Data use by mode + P.keyTime={}P.keySpeed=0 + P.dropTime={}P.dropSpeed=0 + for i=1,10 do P.keyTime[i]=-1e5 end + for i=1,10 do P.dropTime[i]=-1e5 end + + P.field,P.visTime={},{} + P.atkBuffer={sum=0} + + --Royale-related + P.badge,P.strength=0,0 + P.atkMode,P.swappingAtkMode=1,20 + P.atker,P.atking,P.lastRecv={} + + P.dropDelay,P.lockDelay=0,0 + P.color={} + P.showTime=nil + P.keepVisible=true + + --P.cur={bk=matrix[2], id=shapeID, color=colorID, name=nameID} + --P.sc,P.dir={0,0},0--SpinCenterCoord, direction + --P.r,P.c=0,0--row, col + --P.hd={...},same as P.cur + -- P.curX,P.curY,P.imgY,P.minY=0,0,0,0--x,y,ghostY + P.holded=false + P.next={} + + 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.pieceCount=0--Count pieces from next, for drawing bagline + + P.human=false + P.RS=kickList.TRS + + -- P.newNext=nil--Call prepareSequence()to get a function to get new next + + P.keyPressing={}for i=1,12 do P.keyPressing[i]=false end + P.movDir,P.moving,P.downing=0,0,0--Last move key,DAS charging,downDAS charging + P.waiting,P.falling=-1,-1 + P.clearingRow,P.clearedRow={},{}--Clearing animation height,cleared row mark + P.combo,P.b2b=0,0 + P.garbageBeneath=0 + P.fieldBeneath=0 + + P.score1,P.b2b1=0,0 + P.dropFX,P.moveFX,P.lockFX,P.clearFX={},{},{},{} + P.tasks={}--Tasks + P.bonus={}--Texts + + P.endCounter=0--Used after gameover + P.result=nil--String:"WIN"/"K.O." + + return P +end +local function loadGameEnv(P)--Load gameEnv + P.gameEnv={}--Current game setting environment + local ENV=P.gameEnv + local E + --Load game settings + for k,v in next,gameEnv0 do + if modeEnv[k]~=nil then + v=modeEnv[k] --Mode setting + -- DBP("mode-"..k..":"..tostring(v)) + elseif game.setting[k]~=nil then + v=game.setting[k] --Game setting + -- DBP("game-"..k..":"..tostring(v)) + elseif setting[k]~=nil then + v=setting[k] --Global setting + -- DBP("global-"..k..":"..tostring(v)) + -- else + -- DBP("default-"..k..":"..tostring(v)) + end + ENV[k]=v --Default setting + end +end +local function applyGameEnv(P)--Finish gameEnv processing + local ENV=P.gameEnv + + P.dropDelay=ENV.drop + P.lockDelay=ENV.lock + + P.color={} + for _=1,7 do + P.color[_]=SKIN.libColor[ENV.skin[_]] + end + + P.keepVisible=ENV.visible=="show" + P.showTime= + ENV.visible=="show"and 1e99 or + ENV.visible=="time"and 300 or + ENV.visible=="fast"and 20 or + ENV.visible=="none"and 0 + + P.life=ENV.life + + ENV.das=max(ENV.das,ENV.mindas) + ENV.arr=max(ENV.arr,ENV.minarr) + ENV.sdarr=max(ENV.sdarr,ENV.minsdarr) + ENV.next=min(ENV.next,setting.maxNext) + + if ENV.sequence~="bag"and ENV.sequence~="loop"then + ENV.bagLine=false + else + ENV.bagLen=#ENV.bag + end + + if ENV.lockFX==0 then ENV.lockFX=nil end + if ENV.dropFX==0 then ENV.dropFX=nil end + if ENV.moveFX==0 then ENV.moveFX=nil end + if ENV.clearFX==0 then ENV.clearFX=nil end + if ENV.shakeFX==0 then ENV.shakeFX=nil end + if ENV.ghost==0 then ENV.ghost=nil end + if ENV.center==0 then ENV.center=nil end +end +local function prepareSequence(P)--Call freshPrepare and set newNext + local ENV=P.gameEnv + if type(ENV.sequence)=="string"then + freshPrepare[ENV.sequence](P) + P.newNext=freshMethod[ENV.sequence] + else + assert(type(ENV.sequence)=="function"and type(ENV.freshMethod)=="function","wrong sequence generator code") + ENV.sequence(P) + P.newNext=ENV.freshMethod + end +end +local function loadAI(P,AIdata)--Load AI params + local ENV=P.gameEnv + P.AI_mode=AIdata.type + P.AI_stage=1 + P.AI_keys={} + P.AI_delay=AIdata.delay or min(int(ENV.drop*.8),2*AIdata.delta) + P.AI_delay0=AIdata.delta + P.AIdata={ + type=AIdata.type, + delay=AIdata.delay, + delta=AIdata.delta, + + next=AIdata.next, + hold=AIdata.hold, + _20G=ENV._20G, + bag=AIdata.bag, + node=AIdata.node, + } + if not BOT then P.AI_mode="9S"end + if P.AI_mode=="CC"then + P.RS=kickList.AIRS + local opt,wei=BOT.getConf() + BOT.setHold(opt,P.AIdata.hold) + BOT.set20G(opt,P.AIdata._20G) + BOT.setBag(opt,P.AIdata.bag=="bag") + 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=kickList.TRS + end +end +---------------------------------------------------- + ---------------------------------------------------- function player.showText(P,text,dx,dy,font,style,spd,stop) if P.gameEnv.text then @@ -1036,12 +1304,6 @@ 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)) end -local function without(L,e) - for i=1,#L do - if L[i]==e then return end - end - return true -end function player.createLockFX(P) local BK=P.cur.bk local t=12-P.gameEnv.lockFX*2 @@ -1166,25 +1428,6 @@ function player.RND(P,a,b) return R:random(a,b) end -local function getNewStatTable() - local T={ - time=0,score=0, - key=0,rotate=0,hold=0, - extraPiece=0,extraRate=0, - piece=0,row=0,dig=0, - atk=0,digatk=0, - send=0,recv=0,pend=0,off=0, - clear={},clears={},spin={},spins={}, - pc=0,hpc=0,b2b=0,b3b=0, - } - for i=1,25 do - T.clear[i]={0,0,0,0,0} - T.spin[i]={0,0,0,0,0} - T.clears[i]=0 - T.spins[i]=0 - end - return T -end function player.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 @@ -2108,46 +2351,6 @@ function player.drop(P)--Place piece end ---------------------------------------------------- ----------------------------------------------------- -local AM={} -function AM.pressKey(P,i) - P.keyPressing[i]=true - P.act[i](P) - if P.control then - if P.keyRec then - ins(P.keyTime,1,game.frame) - P.keyTime[11]=nil - end - P.stat.key=P.stat.key+1 - end -end -function AM.releaseKey(P,i) - P.keyPressing[i]=false -end -function AM.pressKey_Rec(P,i) - if game.recording then - ins(game.rec,game.frame) - ins(game.rec,i) - end - P.keyPressing[i]=true - P.act[i](P) - if P.control then - if P.keyRec then - ins(P.keyTime,1,game.frame) - P.keyTime[11]=nil - end - P.stat.key=P.stat.key+1 - end -end -function AM.releaseKey_Rec(P,i) - if game.recording then - ins(game.rec,game.frame) - ins(game.rec,-i) - end - P.keyPressing[i]=false -end ----------------------------------------------------- - ---------------------------------------------------- local function gameOver()--Save record if game.replaying then return end @@ -2253,10 +2456,13 @@ function player.lose(P) end if P.AI_mode=="CC"then - CC_updateField(P) + P.hd=nil + loadAI(P,P.AIdata) + P:popNext() end P.life=P.life-1 + P.fieldBeneath=0 P.b2b=0 for i=1,#P.atkBuffer do local A=P.atkBuffer[i] @@ -2272,7 +2478,7 @@ function player.lose(P) end sysFX.newShade(.5,1,1,1,P.x+150*P.size,P.y+60*P.size,300*P.size,610*P.size) sysFX.newRectRipple(.3,P.x+150*P.size,P.y+60*P.size,300*P.size,610*P.size) - sysFX.newRipple(.3,P.x+(300+25+25*P.life+12)*P.size,P.y+(595+12)*P.size,20) + sysFX.newRipple(.3,P.x+(450+25+25*P.life+12)*P.size,P.y+(665+12)*P.size,20) --300+25*i,595 SFX.play("clear_3") SFX.play("emit") @@ -2626,207 +2832,6 @@ end ---------------------------------------------------- ---------------------------------------------------- -local function newEmptyPlayer(id,x,y,size) - local P={id=id} - players[id]=P - players.alive[id]=P - - --Inherit functions of player class - for k,v in next,player do P[k]=v end - if P.id==1 and game.recording then - P.pressKey=AM.pressKey_Rec - P.releaseKey=AM.releaseKey_Rec - else - P.pressKey=AM.pressKey - P.releaseKey=AM.releaseKey - end - P.update=Pupdate_alive - - P.fieldOff={x=0,y=0,vx=0,vy=0}--For shake FX - P.x,P.y,P.size=x,y,size or 1 - P.frameColor=frameColor[0] - - P.small=P.size<.1--If draw in small mode - 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) - P.draw=Pdraw_small - else - P.keyRec=true--If calculate keySpeed - P.centerX,P.centerY=P.x+300*P.size,P.y+370*P.size - P.absFieldX=P.x+150*P.size - P.absFieldY=P.y+60*P.size - P.draw=Pdraw_norm - P.bonus={}--Text objects - end - P.randGen=mt.newRandomGenerator(game.seed) - - P.small=false - P.alive=true - P.control=false - P.timing=false - P.stat=getNewStatTable() - - P.modeData={point=0,event=0,counter=0}--Data use by mode - P.keyTime={}P.keySpeed=0 - P.dropTime={}P.dropSpeed=0 - for i=1,10 do P.keyTime[i]=-1e5 end - for i=1,10 do P.dropTime[i]=-1e5 end - - P.field,P.visTime={},{} - P.atkBuffer={sum=0} - - --Royale-related - P.badge,P.strength=0,0 - P.atkMode,P.swappingAtkMode=1,20 - P.atker,P.atking,P.lastRecv={} - - P.dropDelay,P.lockDelay=0,0 - P.color={} - P.showTime=nil - P.keepVisible=true - - --P.cur={bk=matrix[2], id=shapeID, color=colorID, name=nameID} - --P.sc,P.dir={0,0},0--SpinCenterCoord, direction - --P.r,P.c=0,0--row, col - --P.hd={...},same as P.cur - -- P.curX,P.curY,P.imgY,P.minY=0,0,0,0--x,y,ghostY - P.holded=false - P.next={} - - 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.pieceCount=0--Count pieces from next, for drawing bagline - - P.human=false - P.RS=kickList.TRS - - -- P.newNext=nil--Call prepareSequence()to get a function to get new next - - P.keyPressing={}for i=1,12 do P.keyPressing[i]=false end - P.movDir,P.moving,P.downing=0,0,0--Last move key,DAS charging,downDAS charging - P.waiting,P.falling=-1,-1 - P.clearingRow,P.clearedRow={},{}--Clearing animation height,cleared row mark - P.combo,P.b2b=0,0 - P.garbageBeneath=0 - P.fieldBeneath=0 - - P.score1,P.b2b1=0,0 - P.dropFX,P.moveFX,P.lockFX,P.clearFX={},{},{},{} - P.tasks={}--Tasks - P.bonus={}--Texts - - P.endCounter=0--Used after gameover - P.result=nil--String:"WIN"/"K.O." - - return P -end -local function loadGameEnv(P)--Load gameEnv - P.gameEnv={}--Current game setting environment - local ENV=P.gameEnv - local E - --Load game settings - for k,v in next,gameEnv0 do - if modeEnv[k]~=nil then - v=modeEnv[k] --Mode setting - -- DBP("mode-"..k..":"..tostring(v)) - elseif game.setting[k]~=nil then - v=game.setting[k] --Game setting - -- DBP("game-"..k..":"..tostring(v)) - elseif setting[k]~=nil then - v=setting[k] --Global setting - -- DBP("global-"..k..":"..tostring(v)) - -- else - -- DBP("default-"..k..":"..tostring(v)) - end - ENV[k]=v --Default setting - end -end -local function applyGameEnv(P)--Finish gameEnv processing - local ENV=P.gameEnv - - P.dropDelay=ENV.drop - P.lockDelay=ENV.lock - - P.color={} - for _=1,7 do - P.color[_]=SKIN.libColor[ENV.skin[_]] - end - - P.keepVisible=ENV.visible=="show" - P.showTime= - ENV.visible=="show"and 1e99 or - ENV.visible=="time"and 300 or - ENV.visible=="fast"and 20 or - ENV.visible=="none"and 0 - - P.life=ENV.life - - ENV.das=max(ENV.das,ENV.mindas) - ENV.arr=max(ENV.arr,ENV.minarr) - ENV.sdarr=max(ENV.sdarr,ENV.minsdarr) - ENV.next=min(ENV.next,setting.maxNext) - - if ENV.sequence~="bag"and ENV.sequence~="loop"then - ENV.bagLine=false - else - ENV.bagLen=#ENV.bag - end - - if ENV.lockFX==0 then ENV.lockFX=nil end - if ENV.dropFX==0 then ENV.dropFX=nil end - if ENV.moveFX==0 then ENV.moveFX=nil end - if ENV.clearFX==0 then ENV.clearFX=nil end - if ENV.shakeFX==0 then ENV.shakeFX=nil end - if ENV.ghost==0 then ENV.ghost=nil end - if ENV.center==0 then ENV.center=nil end -end -local function prepareSequence(P)--Call freshPrepare and set newNext - local ENV=P.gameEnv - if type(ENV.sequence)=="string"then - freshPrepare[ENV.sequence](P) - P.newNext=freshMethod[ENV.sequence] - else - assert(type(ENV.sequence)=="function"and type(ENV.freshMethod)=="function","wrong sequence generator code") - ENV.sequence(P) - P.newNext=ENV.freshMethod - end -end -local function loadAI(P,AIdata)--Load AI params - local ENV=P.gameEnv - P.AI_mode=AIdata.type - P.AI_stage=1 - P.AI_keys={} - P.AI_delay=AIdata.delay or min(int(ENV.drop*.8),2*AIdata.delta) - P.AI_delay0=AIdata.delta - P.AIdata={ - next=AIdata.next, - hold=AIdata.hold, - _20G=ENV._20G, - bag=AIdata.bag=="bag", - node=AIdata.node, - } - if not BOT then P.AI_mode="9S"end - if P.AI_mode=="CC"then - P.RS=kickList.AIRS - local opt,wei=BOT.getConf() - BOT.setHold(opt,P.AIdata.hold) - BOT.set20G(opt,P.AIdata._20G) - BOT.setBag(opt,P.AIdata.bag) - 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=kickList.TRS - end -end - function PLY.newDemoPlayer(id,x,y,size) local P=newEmptyPlayer(id,x,y,size)