This commit is contained in:
MrZ_26
2020-02-22 00:47:35 +08:00
parent 527352ce15
commit 57857ceb67
49 changed files with 909 additions and 856 deletions

18
parts/AITemplate.lua Normal file
View File

@@ -0,0 +1,18 @@
local int=math.floor
local AISpeed={60,50,45,35,25,15,9,6,4,2}
return function(type,speedLV,next,hold,node)
if type=="CC"then
return{
type="CC",
next=next,
hold=hold,
delta=AISpeed[speedLV],
node=node,
}
elseif type=="9S"then
return{
type="9S",
delta=int(AISpeed[speedLV]*.5),
}
end
end

88
parts/bgm.lua Normal file
View File

@@ -0,0 +1,88 @@
local rem=table.remove
local BGM={}
BGM.nowPlay=nil
BGM.playing=nil--last loaded source
BGM.playingID=nil--last loaded ID
BGM.list={
"blank",
"way",
"race",
"newera",
"push",
"reason",
"infinite",
"cruelty",
"final",
"secret7th",
"secret8th",
"rockblock",
"8-bit happiness",
"shining terminal",
"oxygen",
"distortion",
"end",
}
function BGM.loadOne(_)
_,BGM.list[_]=BGM.list[_]
BGM.list[_]=love.audio.newSource("/BGM/".._..".ogg","stream")
BGM.list[_]:setLooping(true)
BGM.list[_]:setVolume(0)
end
function BGM.loadAll()
for i=1,#BGM.list do
BGM.loadOne(i)
end
end
function BGM.play(s)
if setting.bgm==0 or not s then return end
if BGM.nowPlay~=s then
if BGM.nowPlay then newTask(Event_task.bgmFadeOut,nil,BGM.nowPlay)end
for i=#Task,1,-1 do
local T=Task[i]
if T.code==Event_task.bgmFadeIn then
T.code=Event_task.bgmFadeOut
elseif T.code==Event_task.bgmFadeOut and T.data==s then
rem(Task,i)
end
end
if s then
BGM.playingID=s
end
BGM.nowPlay=s
newTask(Event_task.bgmFadeIn,nil,s)
BGM.playing=BGM.list[s]
BGM.playing:play()
end
end
function BGM.freshVolume()
if BGM.playing then
local v=setting.bgm*.1
if v>0 then
BGM.playing:setVolume(v)
if not BGM.nowPlay then
BGM.playing:play()
BGM.nowPlay=BGM.playingID
end
else
BGM.playing:pause()
BGM.playing:setVolume(0)
BGM.nowPlay=nil
end
end
end
function BGM.stop()
if BGM.nowPlay then
for i=1,#Task do
local T=Task[i]
if T.code==Event_task.bgmFadeIn and T.data==BGM.nowPlay then
T.code=Event_task.bgmFadeOut
goto L
end
end
BGM.list[BGM.nowPlay]:stop()
::L::
BGM.nowPlay=nil
end
end
return BGM

172
parts/event.lua Normal file
View File

@@ -0,0 +1,172 @@
local int,max,min=math.floor,math.max,math.min
local ins,rem=table.insert,table.remove
local function gameOver()
saveStat()
local M=curMode
if M.pauseLimit and(pauseCount==1 and pauseTime>2.6 or pauseTime>6.26)then
TEXT(text.invalidGame,640,260,80,"flicker",.5)
return
end
local R=M.getRank
if R then
local P=players[1]
R=R(P)--new rank
if R then
local r=modeRanks[M.id]--old rank
if R>r then
modeRanks[M.id]=R
if r==0 then
for i=1,#M.unlock do
local m=M.unlock[i]
modeRanks[m]=modes[m].score and 0 or 6
end
end
saveUnlock()
end
local D=M.score(P)
local L=M.records
local p=#L--排名数-1
if p>0 then
::L::
if M.comp(D,L[p])then--是否靠前
p=p-1
if p>0 then
goto L
end
end
end
if p<10 then
if p==0 then
P:showText(text.newRecord,0,-100,100,"beat",.5)
end
D.date=os.date("%Y/%m/%d %H:%M")
ins(L,p+1,D)
if L[11]then L[11]=nil end
saveRecord(M.saveFileName,L)
end
end
end
end--Save record
local function die(P)--Same thing when win/lose,not really die!
P.alive=false
P.control=false
P.timing=false
P.waiting=1e99
P.b2b=0
clearTask(P)
for i=1,#P.atkBuffer do
P.atkBuffer[i].sent=true
P.atkBuffer[i].time=0
end
for i=1,#P.field do
for j=1,10 do
P.visTime[i][j]=min(P.visTime[i][j],20)
end
end
end
Event={}
function Event.reach_winCheck(P)
if P.stat.row>=P.gameEnv.target then
Event.win(P,"finish")
end
end
function Event.win(P,result)
die(P)
P.result="WIN"
if modeEnv.royaleMode then
P.modeData.event=1
P:changeAtk()
end
if P.human then
gameResult=result or"win"
SFX.play("win")
VOICE("win")
if modeEnv.royaleMode then
BGM.play("8-bit happiness")
end
end
newTask(Event_task.finish,P)
if curMode.id=="custom_puzzle"then
P:showText(text.win,0,0,90,"beat",.4)
else
P:showText(text.win,0,0,90,"beat",.5,.2)
end
if P.human then
gameOver()
end
end
function Event.lose(P)
if P.invincible then
while P.field[1]do
removeRow(P.field)
removeRow(P.visTime)
end
if P.AI_mode=="CC"then
P.AI_needFresh=true
end
return
end
die(P)
for i=1,#players.alive do
if players.alive[i]==P then
rem(players.alive,i)
break
end
end
P.result="K.O."
if modeEnv.royaleMode then
P:changeAtk()
P.modeData.event=#players.alive+1
P:showText(P.modeData.event,0,-120,60,"appear",1,12)
P.strength=0
if P.lastRecv then
local A,i=P,0
repeat
A,i=A.lastRecv,i+1
until not A or A.alive or A==P or i==3
if A and A.alive then
if P.id==1 or A.id==1 then
P.killMark=A.id==1
end
A.modeData.point,A.badge=A.modeData.point+1,A.badge+P.badge+1
for i=A.strength+1,4 do
if A.badge>=royaleData.powerUp[i]then
A.strength=i
end
end
P.lastRecv=A
if P.id==1 or A.id==1 then
newTask(Event_task.throwBadge,A,{P,max(3,P.badge)*4})
end
freshMostBadge()
end
else
P.badge=-1
end
freshMostDangerous()
for i=1,#players.alive do
if players.alive[i].atking==P then
players.alive[i]:freshTarget()
end
end
if #players.alive==royaleData.stage[gameStage]then
royaleLevelup()
end
end
P.gameEnv.keepVisible=P.gameEnv.visible~="show"
P:showText(text.lose,0,0,90,"appear",.5,.2)
if P.human then
gameResult="lose"
SFX.play("fail")
VOICE("lose")
if modeEnv.royaleMode then BGM.play("end")end
end
if #players.alive==1 then
Event.win(players.alive[1])
end
if #players==1 or(P.human and not players[2].human)then
gameOver()
end
newTask(#players>1 and Event_task.lose or Event_task.finish,P)
end
return Event

93
parts/modes.lua Normal file
View File

@@ -0,0 +1,93 @@
modes={
{"sprint_10", id=1, x=0, y=0, size=35,shape=1,icon="timer", unlock={2,3}},
{"sprint_20", id=2, x=-300, y=0, size=45,shape=1,icon="timer", unlock={73,74,75}},
{"sprint_40", id=3, x=0, y=-400, size=55,shape=1,icon="timer", unlock={4,9}},
{"sprint_100", id=4, x=-200, y=-400, size=45,shape=1,icon="timer", unlock={5,7}},
{"sprint_400", id=5, x=-400, y=-400, size=35,shape=1,icon="timer", unlock={6}},
{"sprint_1000", id=6, x=-600, y=-400, size=35,shape=1,icon="timer", unlock={}},
{"drought_normal", id=7, x=-400, y=-200, size=35,shape=1,icon="noI", unlock={8}},
{"drought_lunatic", id=8, x=-600, y=-200, size=35,shape=1,icon="mess", unlock={}},
{"marathon_normal", id=9, x=0, y=-600, size=55,shape=1,icon="flag", unlock={10,11,22,31,36,37,48,67,71,72}},
{"marathon_hard", id=10, x=0, y=-800, size=45,shape=1,icon="flag", unlock={27}},
{"solo_1", id=11, x=-300, y=-1000, size=35,shape=1,icon="solo", unlock={12}},
{"solo_2", id=12, x=-500, y=-1000, size=35,shape=1,icon="solo", unlock={13}},
{"solo_3", id=13, x=-700, y=-1000, size=35,shape=1,icon="solo", unlock={14,16}},
{"solo_4", id=14, x=-900, y=-1000, size=35,shape=1,icon="solo", unlock={15}},
{"solo_5", id=15, x=-1100, y=-1000, size=35,shape=1,icon="solo", unlock={}},
{"techmino49_easy", id=16, x=-900, y=-1200, size=35,shape=1,icon="", unlock={17,19}},
{"techmino49_hard", id=17, x=-900, y=-1400, size=35,shape=1,icon="", unlock={18}},
{"techmino49_ultimate", id=18, x=-900, y=-1600, size=35,shape=1,icon="", unlock={}},
{"techmino99_easy", id=19, x=-1100, y=-1400, size=35,shape=1,icon="", unlock={20}},
{"techmino99_hard", id=20, x=-1100, y=-1600, size=35,shape=1,icon="", unlock={21}},
{"techmino99_ultimate", id=21, x=-1100, y=-1800, size=35,shape=1,icon="", unlock={}},
{"round_1", id=22, x=-300, y=-800, size=35,shape=1,icon="round", unlock={23}},
{"round_2", id=23, x=-500, y=-800, size=35,shape=1,icon="round", unlock={24}},
{"round_3", id=24, x=-700, y=-800, size=35,shape=1,icon="round", unlock={25}},
{"round_4", id=25, x=-900, y=-800, size=35,shape=1,icon="round", unlock={26}},
{"round_5", id=26, x=-1100, y=-800, size=35,shape=1,icon="round", unlock={}},
{"master_beginner", id=27, x=0, y=-1000, size=35,shape=1,icon="", unlock={28}},
{"master_adavnce", id=28, x=0, y=-1200, size=35,shape=1,icon="", unlock={29,30}},
{"master_final", id=29, x=0, y=-1400, size=35,shape=1,icon="", unlock={}},
{"GM", id=30, x=150, y=-1500, size=35,shape=1,icon="", unlock={}},
{"blind_easy", id=31, x=150, y=-700, size=35,shape=1,icon="", unlock={32}},
{"blind_normal", id=32, x=150, y=-800, size=35,shape=1,icon="", unlock={33}},
{"blind_hard", id=33, x=150, y=-900, size=35,shape=1,icon="", unlock={34}},
{"blind_lunatic", id=34, x=150, y=-1000, size=35,shape=1,icon="", unlock={35}},
{"blind_ultimate", id=35, x=150, y=-1100, size=35,shape=1,icon="", unlock={}},
{"classic_fast", id=36, x=-300, y=-1200, size=35,shape=2,icon="classic", unlock={}},
{"survivor_easy", id=37, x=300, y=-600, size=35,shape=1,icon="", unlock={38}},
{"survivor_normal", id=38, x=500, y=-600, size=35,shape=1,icon="", unlock={39,42,44,46}},
{"survivor_hard", id=39, x=700, y=-600, size=35,shape=1,icon="", unlock={40}},
{"survivor_lunatic", id=40, x=900, y=-600, size=35,shape=1,icon="", unlock={41}},
{"survivor_ultimate", id=41, x=1100, y=-600, size=35,shape=1,icon="", unlock={}},
{"attacker_hard", id=42, x=300, y=-800, size=35,shape=1,icon="", unlock={43}},
{"attacker_ultimate", id=43, x=300, y=-1000, size=35,shape=1,icon="", unlock={}},
{"defender_normal", id=44, x=500, y=-800, size=35,shape=1,icon="", unlock={45}},
{"defender_lunatic", id=45, x=500, y=-1000, size=35,shape=1,icon="", unlock={}},
{"dig_hard", id=46, x=700, y=-800, size=35,shape=1,icon="", unlock={47}},
{"dig_ultimate", id=47, x=700, y=-1000, size=35,shape=1,icon="", unlock={}},
{"bigbang", id=48, x=400, y=-400, size=55,shape=1,icon="", unlock={49,51,56}},
{"c4wtrain_normal", id=49, x=700, y=-400, size=35,shape=1,icon="", unlock={50}},
{"c4wtrain_lunatic", id=50, x=900, y=-400, size=35,shape=1,icon="", unlock={}},
{"pctrain_normal", id=51, x=700, y=-200, size=35,shape=1,icon="", unlock={52,53}},
{"pctrain_lunatic", id=52, x=900, y=-200, size=35,shape=1,icon="", unlock={}},
{"pcchallenge_normal", id=53, x=800, y=-100, size=35,shape=1,icon="", unlock={54}},
{"pcchallenge_hard", id=54, x=1000, y=-100, size=35,shape=1,icon="", unlock={55}},
{"pcchallenge_lunatic", id=55, x=1200, y=-100, size=35,shape=1,icon="", unlock={}},
{"tech_normal", id=56, x=400, y=-100, size=35,shape=1,icon="", unlock={57,58}},
{"tech_normal+", id=57, x=650, y=150, size=35,shape=1,icon="", unlock={64}},
{"tech_hard", id=58, x=400, y=50, size=35,shape=1,icon="", unlock={59,60}},
{"tech_hard+", id=59, x=250, y=50, size=35,shape=1,icon="", unlock={}},
{"tech_lunatic", id=60, x=400, y=200, size=35,shape=1,icon="", unlock={61,62}},
{"tech_lunatic+", id=61, x=250, y=200, size=35,shape=1,icon="", unlock={}},
{"tech_ultimate", id=62, x=400, y=350, size=35,shape=1,icon="", unlock={63}},
{"tech_ultimate+", id=63, x=250, y=350, size=35,shape=1,icon="", unlock={}},
{"tsd_easy", id=64, x=800, y=200, size=35,shape=1,icon="", unlock={65}},
{"tsd_hard", id=65, x=1000, y=200, size=35,shape=1,icon="", unlock={66}},
{"tsd_ultimate", id=66, x=1200, y=200, size=35,shape=1,icon="", unlock={}},
{"zen", id=67, x=-900, y=-600, size=35,shape=1,icon="zen", unlock={68,69,70}},
{"ultra", id=68, x=-1100, y=-400, size=35,shape=1,icon="", unlock={}},
{"infinite", id=69, x=-900, y=-400, size=35,shape=1,icon="", unlock={}},
{"infinite_dig", id=70, x=-1100, y=-600, size=35,shape=1,icon="", unlock={}},
{"custom_clear", id=71, x=200, y=-350, size=45,shape=3,icon="custom", unlock={}},
{"custom_puzzle", id=72, x=200, y=-200, size=45,shape=3,icon="puzzle", unlock={}},
{"hotseat_2P", id=73, x=-300, y=200, size=45,shape=3,icon="", unlock={}},
{"hotseat_3P", id=74, x=-450, y=200, size=45,shape=3,icon="", unlock={}},
{"hotseat_4P", id=75, x=-600, y=200, size=45,shape=3,icon="", unlock={}},
}
modeRanks={}
for i=1,#modes do
modeRanks[i]=false
assert(i==modes[i].id,"ModeID error:"..i)
end
modeRanks[1]=0

67
parts/sfx.lua Normal file
View File

@@ -0,0 +1,67 @@
local rem=table.remove
local SFX={}
SFX.list={
"welcome",
"click","enter",
"finesseError","finesseError_long",
--Stereo sfxs(cannot set position)
"button","swipe",
"ready","start","win","fail","collect",
"move","rotate","rotatekick","hold",
"prerotate","prehold",
"lock","drop","fall",
"reach",
"ren_1","ren_2","ren_3","ren_4","ren_5","ren_6","ren_7","ren_8","ren_9","ren_10","ren_11","ren_mega",
"clear_1","clear_2","clear_3","clear_4",
"spin_0","spin_1","spin_2","spin_3",
"emit","blip_1","blip_2",
"perfectclear",
"error",
--Mono sfxs
}
function SFX.loadOne(_)
_,SFX.list[_]=SFX.list[_]
SFX.list[_]={love.audio.newSource("/SFX/".._..".ogg","static")}
end
function SFX.loadAll()
for i=1,#SFX.list do
SFX.loadOne(i)
end
end
function SFX.play(s,v,pos)
if setting.sfx==0 then return end
local S=SFX.list[s]--source list
local n=1
while S[n]:isPlaying()do
n=n+1
if not S[n]then
S[n]=S[n-1]:clone()
S[n]:seek(0)
break
end
end
S=S[n]--AU_SRC
if S:getChannelCount()==1 then
if pos then
pos=pos*setting.stereo*.1
S:setPosition(pos,1-pos^2,0)
else
S:setPosition(0,0,0)
end
end
S:setVolume((v or 1)*setting.sfx*.1)
S:play()
end
function SFX.reset()
for _,L in next,sfx do
for i=#v,2,-1 do
if not L[i]:isPlaying()then
rem(L,i)
end
end
end
end
return SFX

View File

@@ -7,12 +7,12 @@ local planet={}
local function newPlanet()
local a=rnd()*3.142
local r=(H+W)*(rnd()*2+1)*.06
local r=(H+W)*(2+rnd())*.05
planet.r=r
planet.x=W*.5+cos(a)*(R+r)
planet.y=H*.5+sin(a)*(R+r)
planet.vx=-cos(a+rnd()-.5)*.126
planet.vy=-sin(a+rnd()-.5)*.126
planet.vx=-cos(a+rnd()-.5)*.0626
planet.vy=-sin(a+rnd()-.5)*.0626
planet.R=.7+rnd()*.2
planet.G=.7+rnd()*.1
end

92
parts/task.lua Normal file
View File

@@ -0,0 +1,92 @@
local min=math.min
local mini=love.window.isMinimized
local task={}
function task.pauseGame()
if not mini()then
pauseTimer=pauseTimer+1
end
return pauseTimer==50
end
function task.resumeGame()
pauseTimer=pauseTimer-1
if pauseTimer==0 then
scene.swapTo("play","none")
return true
end
end
function task.finish(P)
if scene.cur~="play"then return true end
P.endCounter=P.endCounter+1
if P.endCounter>120 then pauseGame()end
end
function task.lose(P)
P.endCounter=P.endCounter+1
if P.endCounter>80 then
for i=1,#P.field do
for j=1,10 do
if P.visTime[i][j]>0 then
P.visTime[i][j]=P.visTime[i][j]-1
end
end
end
if P.endCounter==120 then
while P.field[1]do
removeRow(P.field)
removeRow(P.visTime)
end
if #players==1 and scene=="play"then
pauseGame()
end
return true
end
end
end
function task.throwBadge(A,data)
data[2]=data[2]-1
if data[2]%4==0 then
local S,R=data[1],data[1].lastRecv
local x1,y1,x2,y2
if S.small then
x1,y1=S.centerX,S.centerY
else
x1,y1=S.x+308*S.size,S.y+450*S.size
end
if R.small then
x2,y2=R.centerX,R.centerY
else
x2,y2=R.x+66*R.size,R.y+344*R.size
end
FX_badge[#FX_badge+1]={x1,y1,x2,y2,t=0}
--generate badge object
if not A.ai and data[2]%8==0 then
SFX.play("collect")
end
end
if data[2]<=0 then return true end
end
function task.bgmFadeOut(_,id)
local src=BGM.list[id]
local v=src:getVolume()-.025*setting.bgm*.1
src:setVolume(v>0 and v or 0)
if v<=0 then
src:stop()
return true
end
end
function task.bgmFadeIn(_,id)
local src=BGM.list[id]
local v=min(src:getVolume()+.025*setting.bgm*.1,setting.bgm*.1)
src:setVolume(v)
if v>=setting.bgm*.1 then return true end
end
function task.settingSaved(_,T)
T[1]=T[1]-1
if T[1]==0 then
if scene.cur=="main"then
TEXT(text.settingSaved,370,330,30,"appear")
end
return true
end
end
return task

8
parts/vib.lua Normal file
View File

@@ -0,0 +1,8 @@
local level={0,.015,.02,.03,.04,.05,.06,.07,.08,.09}
local _=love.system.vibrate
return function(t)
local L=setting.vib
if L>0 then
_(level[L+t])
end
end

38
parts/voice.lua Normal file
View File

@@ -0,0 +1,38 @@
local rnd=math.random
function getVoice(str)
local L=voiceBank[str]
local n=1
while L[n]:isPlaying()do
n=n+1
if not L[n]then
L[n]=L[n-1]:clone()
L[n]:seek(0)
break
end
end
return L[n]
--load voice with string
end
function getFreeVoiceChannel()
local i=#voiceQueue
for i=1,i do
if #voiceQueue[i]==0 then return i end
end
voiceQueue[i+1]={s=0}
return i+1
end
function VOICE(s,chn)
if setting.voc>0 then
if chn then
local L=voiceQueue[chn]
local _=voiceList[s]
L[#L+1]=_[rnd(#_)]
L.s=1
--添加到queue[chn]
else
voiceQueue[getFreeVoiceChannel()]={s=1,voiceList[s][rnd(#voiceList[s])]}
--自动创建空轨/播放
end
end
end