535 lines
9.6 KiB
Lua
535 lines
9.6 KiB
Lua
local tm,gc=love.timer,love.graphics
|
|
local kb,data=love.keyboard,love.data
|
|
local int,abs,rnd=math.floor,math.abs,math.random
|
|
local max,min=math.max,math.min
|
|
local sub,find=string.sub,string.find
|
|
local char,byte=string.char,string.byte
|
|
local ins,rem=table.insert,table.remove
|
|
|
|
local default_setting={
|
|
"das","arr",
|
|
"sddas","sdarr",
|
|
"ihs","irs","ims",
|
|
"maxNext",
|
|
"swap",
|
|
-- "face",
|
|
}
|
|
local function copyGameSetting()
|
|
local S={face={}}
|
|
for _,v in next,default_setting do
|
|
S[v]=setting[v]
|
|
end
|
|
for i=1,25 do
|
|
S.face[i]=setting.face[i]
|
|
end
|
|
return S
|
|
end
|
|
|
|
function destroyPlayers()
|
|
for i=#players,1,-1 do
|
|
local P=players[i]
|
|
if P.canvas then P.canvas:release()end
|
|
while P.field[1]do
|
|
freeRow.discard(rem(P.field))
|
|
freeRow.discard(rem(P.visTime))
|
|
end
|
|
if P.AI_mode=="CC"then
|
|
CC.free(P.bot_opt)
|
|
CC.free(P.bot_wei)
|
|
CC.destroy(P.AI_bot)
|
|
P.AI_mode=nil
|
|
end
|
|
players[i]=nil
|
|
end
|
|
for i=#players.alive,1,-1 do
|
|
players.alive[i]=nil
|
|
end
|
|
collectgarbage()
|
|
end
|
|
|
|
function restoreVirtualKey()
|
|
for i=1,#VK_org do
|
|
local B,O=virtualkey[i],VK_org[i]
|
|
B.ava=O.ava
|
|
B.x=O.x
|
|
B.y=O.y
|
|
B.r=O.r
|
|
B.isDown=false
|
|
B.pressTime=0
|
|
end
|
|
if not modeEnv.Fkey then
|
|
virtualkey[9].ava=false
|
|
end
|
|
end
|
|
|
|
function copyQuestArgs()
|
|
local ENV=customEnv
|
|
local str=""
|
|
str=str..(ENV.hold and"H"or"Z")
|
|
str=str..(ENV.ospin and"O"or"Z")
|
|
str=str..(ENV.missionKill and"M"or"Z")
|
|
str=str..ENV.sequence
|
|
return str
|
|
end
|
|
function pasteQuestArgs(str)
|
|
local ENV=customEnv
|
|
ENV.hold= byte(str,1)~=90
|
|
ENV.ospin= byte(str,2)~=90
|
|
ENV.missionKill= byte(str,3)~=90
|
|
ENV.sequence= sub(str,4)
|
|
end
|
|
|
|
--Encoding Functions
|
|
--Sep symbol: 33 (!)
|
|
--Safe char: 34~126
|
|
--[[
|
|
Count: 34~96
|
|
Block: 97~125
|
|
Encode: [A] or [AB] sequence, A = block ID, B = repeat times, no B means do not repeat.
|
|
Example: "abcdefg" is [SZJLTOI], "a^aDb)" is [Z*63,Z*37,S*10]
|
|
]]
|
|
function copySequence()
|
|
local preBag=preBag
|
|
local str=""
|
|
|
|
local count=1
|
|
for i=1,#preBag+1 do
|
|
if preBag[i+1]~=preBag[i]or count==64 then
|
|
str=str..char(96+preBag[i])
|
|
if count>1 then
|
|
str=str..char(32+count)
|
|
count=1
|
|
end
|
|
else
|
|
count=count+1
|
|
end
|
|
end
|
|
|
|
return str
|
|
end
|
|
function pasteSequence(str)
|
|
local _
|
|
|
|
local bag={}
|
|
local reg
|
|
for i=1,#str do
|
|
_=byte(str,i)
|
|
if not reg then
|
|
if _>=97 and _<=125 then
|
|
reg=_-96
|
|
else
|
|
return
|
|
end
|
|
else
|
|
if _>=97 and _<=125 then
|
|
ins(bag,reg)
|
|
reg=_-96
|
|
elseif _>=34 and _<=96 then
|
|
for i=1,_-32 do
|
|
ins(bag,reg)
|
|
end
|
|
reg=nil
|
|
end
|
|
end
|
|
end
|
|
if reg then
|
|
ins(bag,reg)
|
|
end
|
|
|
|
preBag=bag
|
|
sceneTemp.cur=#bag
|
|
return true
|
|
end
|
|
|
|
function copyBoard()
|
|
local str=""
|
|
local H=0
|
|
|
|
for y=20,1,-1 do
|
|
for x=1,10 do
|
|
if preField[y][x]~=0 then
|
|
H=y
|
|
goto topFound
|
|
end
|
|
end
|
|
end
|
|
::topFound::
|
|
|
|
--Encode field
|
|
for y=1,H do
|
|
local S=""
|
|
local L=preField[y]
|
|
for x=1,10 do
|
|
S=S..char(L[x]+1)
|
|
end
|
|
str=str..S
|
|
end
|
|
return data.encode("string","base64",data.compress("string","zlib",str))
|
|
end
|
|
function pasteBoard(str)
|
|
local _
|
|
|
|
--Decode
|
|
_,str=pcall(data.decode,"string","base64",str)
|
|
if not _ then return end
|
|
_,str=pcall(data.decompress,"string","zlib",str)
|
|
if not _ then return end
|
|
|
|
local fX,fY=1,1--*ptr for Field(r*10+(c-1))
|
|
local p=1
|
|
while true do
|
|
_=byte(str,p)--1byte
|
|
|
|
--Str end
|
|
if not _ then
|
|
if fX~=1 then
|
|
return
|
|
else
|
|
break
|
|
end
|
|
end
|
|
|
|
__=_%32-1--Block id
|
|
if __>17 then return end--Illegal blockid
|
|
_=int(_/32)--Mode id
|
|
|
|
preField[fY][fX]=__
|
|
if fX<10 then
|
|
fX=fX+1
|
|
else
|
|
fY=fY+1
|
|
if fY>20 then break end
|
|
fX=1
|
|
end
|
|
p=p+1
|
|
end
|
|
|
|
for y=fY,20 do
|
|
for x=1,10 do
|
|
preField[y][x]=0
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
--[[
|
|
Mission: 34~114
|
|
Count: 115~126
|
|
Encode: [A] or [AB] sequence, A = mission ID, B = repeat times, no B means do not repeat.
|
|
|
|
_1=01,_2=02,_3=03,_4=04,
|
|
A1=05,A2=06,A3=07,A4=08,
|
|
PC=09,
|
|
Z1=11,Z2=12,Z3=13,
|
|
S1=21,S2=22,S3=23,
|
|
J1=31,J2=32,J3=33,
|
|
L1=41,L2=42,L3=43,
|
|
T1=51,T2=52,T3=53,
|
|
O1=61,O2=62,O3=63,O4=64,
|
|
I1=71,I2=72,I3=73,I4=74,
|
|
]]
|
|
function copyMission()
|
|
local _
|
|
local preMission=preMission
|
|
local str=""
|
|
|
|
local count=1
|
|
for i=1,#preMission+1 do
|
|
if preMission[i+1]~=preMission[i]or count==13 then
|
|
_=33+preMission[i]
|
|
str=str..char(_)
|
|
if count>1 then
|
|
str=str..char(113+count)
|
|
count=1
|
|
end
|
|
else
|
|
count=count+1
|
|
end
|
|
end
|
|
|
|
return str
|
|
end
|
|
function pasteMission(str)
|
|
local _
|
|
local mission={}
|
|
local reg
|
|
for i=1,#str do
|
|
_=byte(str,i)
|
|
if not reg then
|
|
if _>=34 and _<=114 then
|
|
reg=_-33
|
|
else
|
|
return
|
|
end
|
|
else
|
|
if _>=34 and _<=114 then
|
|
if missionEnum[reg]then
|
|
ins(mission,reg)
|
|
reg=_-33
|
|
else
|
|
return
|
|
end
|
|
elseif _>=115 and _<=126 then
|
|
for i=1,_-113 do
|
|
ins(mission,reg)
|
|
end
|
|
reg=nil
|
|
end
|
|
end
|
|
end
|
|
if reg then
|
|
ins(mission,reg)
|
|
end
|
|
|
|
preMission=mission
|
|
sceneTemp.cur=#mission
|
|
return true
|
|
end
|
|
|
|
function mergeStat(stat,delta)
|
|
for k,v in next,delta do
|
|
if type(v)=="table"then
|
|
if type(stat[k])=="table"then
|
|
mergeStat(stat[k],v)
|
|
end
|
|
else
|
|
if stat[k]then
|
|
stat[k]=stat[k]+v
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function randomTarget(P)--Return a random opponent for P
|
|
if #players.alive>1 then
|
|
local R
|
|
repeat
|
|
R=players.alive[rnd(#players.alive)]
|
|
until R~=P
|
|
return R
|
|
end
|
|
end
|
|
function freshMostDangerous()
|
|
game.mostDangerous,game.secDangerous=nil
|
|
local m,m2=0,0
|
|
for i=1,#players.alive do
|
|
local h=#players.alive[i].field
|
|
if h>=m then
|
|
game.mostDangerous,game.secDangerous=players.alive[i],game.mostDangerous
|
|
m,m2=h,m
|
|
elseif h>=m2 then
|
|
game.secDangerous=players.alive[i]
|
|
m2=h
|
|
end
|
|
end
|
|
|
|
for i=1,#players.alive do
|
|
if players.alive[i].atkMode==3 then
|
|
players.alive[i]:freshTarget()
|
|
end
|
|
end
|
|
end
|
|
function freshMostBadge()
|
|
game.mostBadge,game.secBadge=nil
|
|
local m,m2=0,0
|
|
for i=1,#players.alive do
|
|
local P=players.alive[i]
|
|
local b=P.badge
|
|
if b>=m then
|
|
game.mostBadge,game.secBadge=P,game.mostBadge
|
|
m,m2=b,m
|
|
elseif b>=m2 then
|
|
game.secBadge=P
|
|
m2=b
|
|
end
|
|
end
|
|
|
|
for i=1,#players.alive do
|
|
if players.alive[i].atkMode==4 then
|
|
players.alive[i]:freshTarget()
|
|
end
|
|
end
|
|
end
|
|
function royaleLevelup()
|
|
game.stage=game.stage+1
|
|
local spd
|
|
TEXT.show(text.royale_remain(#players.alive),640,200,40,"beat",.3)
|
|
if game.stage==2 then
|
|
spd=30
|
|
elseif game.stage==3 then
|
|
spd=15
|
|
game.garbageSpeed=.6
|
|
if players[1].alive then BGM.play("cruelty")end
|
|
elseif game.stage==4 then
|
|
spd=10
|
|
local _=players.alive
|
|
for i=1,#_ do
|
|
_[i].gameEnv.pushSpeed=3
|
|
end
|
|
elseif game.stage==5 then
|
|
spd=5
|
|
game.garbageSpeed=1
|
|
elseif game.stage==6 then
|
|
spd=3
|
|
if players[1].alive then BGM.play("final")end
|
|
end
|
|
for i=1,#players.alive do
|
|
players.alive[i].gameEnv.drop=spd
|
|
end
|
|
if curMode.lv==3 then
|
|
for i=1,#players.alive do
|
|
local P=players.alive[i]
|
|
P.gameEnv.drop=int(P.gameEnv.drop*.3)
|
|
if P.gameEnv.drop==0 then
|
|
P.curY=P.imgY
|
|
P._20G=true
|
|
if P.AI_mode=="CC"then CC_switch20G(P)end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function pauseGame()
|
|
if not SCN.swapping then
|
|
restartCount=0--Avoid strange darkness
|
|
if not game.result then
|
|
game.pauseCount=game.pauseCount+1
|
|
end
|
|
if not game.replaying then
|
|
for i=1,#players do
|
|
local l=players[i].keyPressing
|
|
for j=1,#l do
|
|
if l[j]then
|
|
players[i]:releaseKey(j)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
SCN.swapTo("pause","none")
|
|
end
|
|
end
|
|
function resumeGame()
|
|
SCN.swapTo("play","none")
|
|
end
|
|
function loadGame(M,ifQuickPlay)
|
|
stat.lastPlay=M
|
|
curMode=Modes[M]
|
|
local lang=setting.lang
|
|
drawableText.modeName:set(text.modes[M][1])
|
|
drawableText.levelName:set(text.modes[M][2])
|
|
needResetGameData=true
|
|
SCN.swapTo("play",ifQuickPlay and"swipeD"or"fade_togame")
|
|
SFX.play("enter")
|
|
end
|
|
function resetGameData()
|
|
if players[1]and not game.replaying then
|
|
mergeStat(stat,players[1].stat)
|
|
end
|
|
|
|
game.frame=150-setting.reTime*15
|
|
game.result=false
|
|
game.pauseTime=0
|
|
game.pauseCount=0
|
|
game.garbageSpeed=1
|
|
game.warnLVL0=0
|
|
game.warnLVL=0
|
|
game.recording=true
|
|
game.replaying=false
|
|
game.setting=copyGameSetting()
|
|
game.rec={}
|
|
math.randomseed(tm.getTime())
|
|
game.seed=rnd(261046101471026)
|
|
|
|
destroyPlayers()
|
|
modeEnv=curMode.env
|
|
restoreVirtualKey()
|
|
curMode.load()
|
|
if modeEnv.task then
|
|
for i=1,#players do
|
|
players[i]:newTask(modeEnv.task)
|
|
end
|
|
end
|
|
BG.set(modeEnv.bg)
|
|
BGM.play(modeEnv.bgm)
|
|
|
|
TEXT.clear()
|
|
if modeEnv.royaleMode then
|
|
for i=1,#players do
|
|
players[i]:changeAtk(randomTarget(players[i]))
|
|
end
|
|
game.stage=nil
|
|
game.mostBadge=nil
|
|
game.secBadge=nil
|
|
game.mostDangerous=nil
|
|
game.secDangerous=nil
|
|
game.stage=1
|
|
game.garbageSpeed=.3
|
|
end
|
|
stat.game=stat.game+1
|
|
freeRow.reset(30*#players)
|
|
SFX.play("ready")
|
|
collectgarbage()
|
|
end
|
|
function resetPartGameData(replaying)
|
|
TASK.removeTask_code(TICK.autoPause)
|
|
if players[1]and not game.replaying then
|
|
mergeStat(stat,players[1].stat)
|
|
end
|
|
|
|
game.result=false
|
|
game.garbageSpeed=1
|
|
game.warnLVL0=0
|
|
game.warnLVL=0
|
|
if replaying then
|
|
game.frame=0
|
|
game.recording=false
|
|
game.replaying=1
|
|
else
|
|
game.frame=150-setting.reTime*15
|
|
game.pauseTime=0
|
|
game.pauseCount=0
|
|
game.recording=true
|
|
game.replaying=false
|
|
game.setting=copyGameSetting()
|
|
game.rec={}
|
|
math.randomseed(tm.getTime())
|
|
game.seed=rnd(1046101471,2662622626)
|
|
end
|
|
|
|
destroyPlayers()
|
|
modeEnv=curMode.env
|
|
restoreVirtualKey()
|
|
curMode.load()
|
|
if modeEnv.task then
|
|
for i=1,#players do
|
|
players[i]:newTask(modeEnv.task)
|
|
end
|
|
end
|
|
BG.set(modeEnv.bg)
|
|
BGM.play(modeEnv.bgm)
|
|
|
|
TEXT.clear()
|
|
if modeEnv.royaleMode then
|
|
for i=1,#players do
|
|
players[i]:changeAtk(randomTarget(players[i]))
|
|
end
|
|
game.stage=nil
|
|
game.mostBadge=nil
|
|
game.secBadge=nil
|
|
game.mostDangerous=nil
|
|
game.secDangerous=nil
|
|
game.stage=1
|
|
game.garbageSpeed=.3
|
|
end
|
|
collectgarbage()
|
|
end
|
|
function gameStart()
|
|
SFX.play("start")
|
|
for P=1,#players do
|
|
P=players[P]
|
|
P.control=true
|
|
P.timing=true
|
|
P:popNext()
|
|
end
|
|
end |