Merge branch '26F-Studio:main' into main

This commit is contained in:
Trebor Huang
2021-08-04 19:53:03 +08:00
committed by GitHub
26 changed files with 187 additions and 114 deletions

View File

@@ -44,15 +44,20 @@ function FILE.save(data,name,mode)
data=tostring(data)
end
if mode:find'd'and fs.getInfo(name)then
MES.new('error',text.saveError_duplicate)
return
end
local F=fs.newFile(name)
F:open'w'
local success,mes=F:write(data)
F:flush()F:close()
if not success then
if success then
return true
else
MES.new('error',text.saveError..(mes or"unknown error"))
MES.traceback()
end
return success
end
function FILE.clear(path)
if fs.getRealDirectory(path)~=SAVEDIR or fs.getInfo(path).type~='directory'then return end

View File

@@ -57,6 +57,7 @@ do--Connect
error((code or"XXX")..":"..(res and res.reason or"Server Error"))
end
end
SOCK:settimeout(0)
end
local YIELD=coroutine.yield

View File

@@ -1,5 +1,5 @@
VERSION={
build=352,
build=353,
code=1600,
short="V0.16.0",
string="Alpha V0.16.0",

View File

@@ -1,6 +1,3 @@
local loveCompress=love.data.compress
local loveDecompress=love.data.decompress
local int=math.floor
local char,byte=string.char,string.byte
local ins=table.insert
@@ -239,10 +236,13 @@ function DATA.pasteQuestArgs(str)
end
--[[
Table data format:
Replay file:
a zlib-compressed json table
Replay data format (table):
{frame,event, frame,event, ...}
Byte data format: (1 byte each period)
Replay data format (byte): (1 byte each period)
dt, event, dt, event, ...
all data range from 0 to 127
large value will be encoded as 1xxxxxxx(high)-1xxxxxxx-...-0xxxxxxx(low)
@@ -357,7 +357,7 @@ do--function DATA.saveReplay()
local fileName=os.date("replay/%Y_%m_%d_%H%M%S.rep")
if not love.filesystem.getInfo(fileName)then
love.filesystem.write(fileName,
loveCompress('string','zlib',
love.data.compress('string','zlib',
JSON.encode{
date=os.date("%Y/%m/%d %H:%M:%S"),
mode=GAME.curModeName,
@@ -378,14 +378,18 @@ do--function DATA.saveReplay()
end
end
function DATA.parseReplay(fileName,ifFull)
local fileData,success,metaData,rep
local fileData
--Read file
fileData=love.filesystem.read(fileName)
return DATA.parseReplayData(fileName,fileData,ifFull)
end
function DATA.parseReplayData(fileName,fileData,ifFull)
local success,metaData,rep
if not(fileData and #fileData>0)then goto BREAK_cannotParse end
--Decompress file
success,fileData=pcall(loveDecompress,'string','zlib',fileData)
success,fileData=pcall(love.data.decompress,'string','zlib',fileData)
if not success then goto BREAK_cannotParse end
--Load metadata
@@ -421,5 +425,4 @@ function DATA.parseReplay(fileName,ifFull)
available=false,
}
end
return DATA

View File

@@ -365,7 +365,7 @@ return{
{"BiRS",
"birs biasrs biasrotationsystem",
"term",
"*Techmino exclusive*\n\nBias Rotation System, Techmino's original rotation system based on XRS and SRS.\nIt sets an offset to rotation if you hold left/right/soft drop when you rotate.\nIf rotation fails when downwards offset is applied, it tries again without the downwards offset.\nThen it tries without left/right offset.\nIf it fails, then rotation will not occur.\n\nCompared to XRS, BiRS only uses a single kick table, making it easier to memorize; also keeps the climbing-over-terrain feature of SRS.\n\nThe final kick offset's euclidean distance can't be larger than sqrt(5) and if there is a horizontal offset, the final kick offset can't be in the opposite direction.",--todo
"*Techmino exclusive*\n\nBias Rotation System, Techmino's original rotation system based on XRS and SRS.\nIt sets an offset to rotation if you hold left/right/soft drop when you rotate.\nIf rotation fails when downwards offset is applied, it tries again without the downwards offset.\nThen it tries without left/right offset.\nIf it fails, then rotation will not occur.\n\nCompared to XRS, BiRS only uses a single kick table, making it easier to memorize; also keeps the climbing-over-terrain feature of SRS.\n\nThe final kick offset's euclidean distance can't be larger than sqrt(5) and if there is a horizontal offset, the final kick offset can't be in the opposite direction.",
},
{"C2RS",
"c2rs",
@@ -395,7 +395,7 @@ return{
{"XRS",
"xrs",
"term",
"X rotation system, a rotation system used in T-ex.\n\nIt introduced a feature to \"use another kick table if you hold a direction key\", making it possible for players to tell the game where they want the piece to go.",--todo
"X rotation system, a rotation system used in T-ex.\n\nIt introduced a feature to \"use another kick table if you hold a direction key\", making it possible for players to tell the game where they want the piece to go.",
},
{"Back to Back",

View File

@@ -56,14 +56,14 @@ return{
ai_fixed="The AI is incompatible with fixed sequences.",
ai_prebag="The AI is incompatible with custom sequences which have nontetramino.",
ai_mission="The AI is incompatible with custom missions.",
saveDone="Data Saved",
saveError="Failed to save:",
loadError="Failed to load:",
switchSpawnSFX="Please turn on the spawn SFX .",
ranks={"D","C","B","A","S"},
needRestart="Retry for the changes to take effect.",
saveDone="Data Saved",
saveError="Failed to save:",
saveError_duplicate="Duplicate filename",
loadError="Failed to load:",
exportSuccess="Exported successfully",
importSuccess="Imported successfully",
dataCorrupted="Data corrupted",
@@ -99,7 +99,7 @@ return{
wsConnecting="Websocket Connecting",
wsFailed="WebSocket Connection Failed",
wsClose="WebSocket Closed: ",
wsClose="WebSocket Closed:",
netTimeout="Network connection timeout",
onlinePlayerCount="Online",

View File

@@ -46,13 +46,13 @@ return{
ai_fixed="La IA no es compatible con secuencias de piezas prefijadas.",
--ai_prebag="The AI is incompatible with custom sequences which have nontetramino.",a IA no es compatible con secuencias de piezas personalizadas.",
ai_mission="La IA no es compatible con misiones personalizadas.",
saveDone="Datos guardados",
saveError="Error al guardar:",
loadError="Error al cargar:",
switchSpawnSFX="Habilita los sonidos de aparición de las piezas ;)",
needRestart="Reinicia Techmino para que los cambios tengan efecto.",
saveDone="Datos guardados",
saveError="Error al guardar:",
-- saveError_duplicate="Duplicate filename",
loadError="Error al cargar:",
exportSuccess="Exportado con éxito",
importSuccess="Importado con éxito",
dataCorrupted="Los datos están corruptos.",
@@ -88,7 +88,7 @@ return{
wsConnecting="Websocket Conectando",
wsFailed="WebSocket conexión fallida",
wsClose="WebSocket cerrado: ",
wsClose="WebSocket cerrado:",
netTimeout="Tiempo de conexión agotado",
onlinePlayerCount="En línea",
@@ -100,7 +100,7 @@ return{
connStream="CONECTANDO",
waitStream="ESPERANDO",
spectating="Especteando",
chatRemain="Usuarios en línea: ",
chatRemain="Usuarios en línea:",
chatStart="------Comienzo del historial------",
chatHistory="------Nuevos mensajes------",
@@ -688,7 +688,7 @@ return{
['pc_n']= {"Desafío de PCs", "Normal", "¡Consigue los PCs que puedas en 100 líneas!"},
['pc_h']= {"Desafío de PCs", "Difícil", "¡Consigue los PCs que puedas en 100 líneas!"},
['pc_l']= {"Desafío de PCs", "Lunático", "¡Consigue los PCs que puedas en 100 líneas!"},
['pc_inf']= {"Desafío de PCs Infinito","", "Consigue todos los PCs que puedas."},
['pc_inf']= {"Desafío de PCs Infinito","", "Consigue todos los PCs que puedas."},
['tech_n']= {"Tech", "Normal", "¡Mantén el B2B!"},
['tech_n_plus']= {"Tech", "Normal+", "¡Sólo se permiten Spins y PCs!"},
['tech_h']= {"Tech", "Difícil", "¡Mantén el B2B!"},

View File

@@ -47,13 +47,13 @@ return{
ai_fixed="L'IA est incompatible avec les séquences fixes.",
--ai_prebag="The AI is incompatible with custom sequences which have nontetramino.",'IA est incompatible avec les séquences personnalisées.",
ai_mission="L'IA est incompatible avec les missions personnalisées.",
saveDone="Données sauvegardées",
saveError="Sauvegarde échouée : ",
loadError="Lecture échouée : ",
switchSpawnSFX="Activez les effets sonores d'apparition des pièces pour jouer",
needRestart="Fonctionnera dès la prochaine partie",
saveDone="Données sauvegardées",
saveError="Sauvegarde échouée : ",
-- saveError_duplicate="Duplicate filename",
loadError="Lecture échouée : ",
exportSuccess="Exporté avec succès",
importSuccess="Importé avec succès",
dataCorrupted="Données corrompues",
@@ -89,7 +89,7 @@ return{
-- wsConnecting="Websocket Connecting",
wsFailed="WebSocket connection échouée",
-- wsClose="WebSocket Closed: ",
-- wsClose="WebSocket Closed:",
-- netTimeout="Network connection timeout",
-- onlinePlayerCount="Online",

View File

@@ -47,13 +47,13 @@ return{
ai_fixed="A inteligência é incompatível com sequências fixas.",
--ai_prebag="The AI is incompatible with custom sequences which have nontetramino.", inteligência é incompatível com sequências fixas.",
ai_mission="A inteligência é incompatível com missões costumizadas.",
saveDone="Data Salva",
saveError="Falha ao salvar:",
loadError="Falha ao ler:",
switchSpawnSFX="Switch on spawn SFX to play",
needRestart="Funciona após reiniciar",
saveDone="Data Salva",
saveError="Falha ao salvar:",
-- saveError_duplicate="Duplicate filename",
loadError="Falha ao ler:",
exportSuccess="Exportado com sucesso",
importSuccess="Importado com sucesso",
dataCorrupted="Data corrompida",
@@ -89,7 +89,7 @@ return{
-- wsConnecting="Websocket Connecting",
wsFailed="WebSocket falha na conexão",
wsClose="WebSocket closed: ",
wsClose="WebSocket closed:",
-- netTimeout="Network connection timeout",
-- onlinePlayerCount="Online",

View File

@@ -34,11 +34,12 @@ return{
ai_fixed="X!!!",
ai_prebag="X!!!",
ai_mission="X!!!",
needRestart="!!*#R#*!!",
saveDone="~~~",
saveError="x!:",
saveError_duplicate="X←→X ?",
loadError="x!:",
needRestart="!!*#R#*!!",
exportSuccess="~Out~",
importSuccess="~In~",
dataCorrupted="XXXXX",

View File

@@ -56,14 +56,14 @@ return{
ai_fixed="不能同时开启AI和固定序列",
ai_prebag="不能同时开启AI和含有非四连块的自定义序列",
ai_mission="不能同时开启AI和自定义任务",
saveDone="保存成功!",
saveError="保存失败:",
loadError="读取失败:",
switchSpawnSFX="请开启方块出生音效",
ranks={"D","C","B","A","S"},
needRestart="重新开始以生效",
saveDone="保存成功!",
saveError="保存失败:",
saveError_duplicate="文件名重复",
loadError="读取失败:",
exportSuccess="导出成功",
importSuccess="导入成功",
dataCorrupted="数据损坏",
@@ -99,7 +99,7 @@ return{
wsConnecting="正在连接",
wsFailed="连接失败",
wsClose="连接被断开: ",
wsClose="连接被断开:",
netTimeout="连接超时",
onlinePlayerCount="在线人数",
@@ -899,6 +899,7 @@ return{
"俄罗斯方块完全可以作为电竞游戏",
"发现有个\"隐形\"皮肤了吗",
"方块不能吃",
"方块不是你生活的全部,适当走出去看看",
"方块教会我们,合群了就会消失,...",
"方块默认出现的方向都是重心在下哦",
"方块能吃吗",
@@ -911,6 +912,7 @@ return{
"感谢Phigros提供部分tip模板(",
"刚接触方块的话多玩玩就行,40行两分钟以外没啥好针对性练习的",
"刚开始练全隐形可以尽量堆平,留一列消四",
"隔壁不在乎玩家意见但是我们在乎,没人提过的合理建议一定会回应",
"隔断消除即将到来!",
"各种画面细节选项都可以在设置里找到哦",
"更换方块皮肤也许能帮助提升成绩?不懂,玄学",
@@ -1120,6 +1122,7 @@ return{
{C.C,"<PURE ",C.P,"MEMORY>"},
{C.C,"15puzzle好玩!"},
{C.C,"魔方好玩!"},
{C.C,"噗哟噗哟好玩!"},
{C.C,"扫雷好玩!"},
{C.C,"Celeste好玩!"},
{C.C,"CYAN"},

View File

@@ -4,7 +4,10 @@ return{
drop=60,lock=60,
freshLimit=15,
fieldH=100,
highCam=true,
fillClear=false,
seqData={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25},
sequence='bag',
bg='none',bgm='there',
},
mesDisp=function(P)
@@ -17,11 +20,11 @@ return{
getRank=function(P)
local B=P.stat.piece
return
B>=260 and 5 or
B>=254 and 4 or
B>=250 and 3 or
B>=243 and 2 or
B>=235 and 1 or
B>=215 and 5 or
B>=208 and 4 or
B>=200 and 3 or
B>=190 and 2 or
B>=180 and 1 or
0
end,
}

View File

@@ -3,6 +3,7 @@ return{
env={
drop=60,lock=60,
freshLimit=15,
highCam=true,
fillClear=false,
bg='none',bgm='there',
},

View File

@@ -4,7 +4,9 @@ return{
drop=60,lock=60,
freshLimit=15,
fieldH=40,
highCam=true,
fillClear=false,
seqData={1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25},
bg='none',bgm='there',
},
mesDisp=function(P)
@@ -17,11 +19,11 @@ return{
getRank=function(P)
local B=P.stat.piece
return
B>=105 and 5 or
B>=101 and 4 or
B>=97 and 3 or
B>=94 and 2 or
B>=90 and 1 or
B>=90 and 5 or
B>=87 and 4 or
B>=83 and 3 or
B>=78 and 2 or
B>=70 and 1 or
0
end,
}

View File

@@ -317,7 +317,7 @@ function NET.createRoom(roomName,description,capacity,roomType,roomData,password
end
end
function NET.enterRoom(room,password)
if NET.lock('enterRoom',2)then
if NET.lock('enterRoom',6)then
SFX.play('reach',.6)
WS.send('play',JSON.encode{
action=2,

View File

@@ -8,7 +8,7 @@ local max,min,modf=math.max,math.min,math.modf
local ins,rem=table.insert,table.remove
local resume,yield,status=coroutine.resume,coroutine.yield,coroutine.status
local SFX,BGM,VOC,VIB,SYSFX,SKIN=SFX,BGM,VOC,VIB,SYSFX,SKIN
local SFX,BGM,VOC,VIB,SYSFX=SFX,BGM,VOC,VIB,SYSFX
local FREEROW,TABLE,TEXT,NET,TASK=FREEROW,TABLE,TEXT,NET,TASK
local PLAYERS,PLY_ALIVE,GAME=PLAYERS,PLY_ALIVE,GAME
@@ -1931,6 +1931,7 @@ function Player:act_hold()
if self.control then
if self.waiting==-1 then
self:hold()
self.keyPressing[8]=false
end
end
end

View File

@@ -222,11 +222,11 @@ return function(P)--Return a piece-generating function for player P
elseif type(s)=='string'and seqGenerators[s]then
return seqGenerators[s]
else
MES.new(
MES.new('warn',
type(s)=='string'and
"No sequence mode called "..s or
"Wrong sequence generator",
'warn')
"Wrong sequence generator"
)
P.gameEnv.sequence='bag'
return seqGenerators.bag
end

View File

@@ -84,7 +84,7 @@ function scene.keyDown(key,isRep)
elseif key=="m"then
SCN.go('custom_mission','swipeD')
elseif key=="delete"then
if sure>20 then
if sure>.3 then
TABLE.cut(FIELD)TABLE.cut(BAG)TABLE.cut(MISSION)
FIELD[1]=DATA.newBoard()
freshMiniFieldVisible()
@@ -96,7 +96,7 @@ function scene.keyDown(key,isRep)
BG.set(CUSTOMENV.bg)
BGM.play(CUSTOMENV.bgm)
else
sure=50
sure=1
end
elseif key=="f1"then
SCN.go('mod','swipeD')
@@ -133,8 +133,8 @@ function scene.keyDown(key,isRep)
end
end
function scene.update()
if sure>0 then sure=sure-1 end
function scene.update(dt)
if sure>0 then sure=sure-dt end
end
function scene.draw()
@@ -184,7 +184,7 @@ function scene.draw()
--Confirm reset
if sure>0 then
gc.setColor(1,1,1,sure*.02)
gc.setColor(1,1,1,sure)
gc.draw(TEXTURE.sure,920,50)
end
gc.translate(0, WIDGET.scrollPos)

View File

@@ -172,12 +172,12 @@ function scene.keyDown(key)
pTouch(penX,penY)
end
elseif key=="delete"then
if sure>20 then
if sure>.3 then
for y=1,20 do for x=1,10 do FIELD[page][y][x]=0 end end
sure=0
SFX.play('finesseError',.7)
else
sure=50
sure=1
end
elseif key=="j"then
demo=not demo
@@ -256,8 +256,8 @@ function scene.keyUp(key)
end
end
function scene.update()
if sure>0 then sure=sure-1 end
function scene.update(dt)
if sure>0 then sure=sure-dt end
end
function scene.draw()
@@ -427,8 +427,8 @@ function scene.draw()
--Confirm reset
if sure>0 then
gc.setColor(1,1,1,sure*.02)
gc.draw(TEXTURE.sure,1070,490)
gc.setColor(1,1,1,sure)
mDraw(TEXTURE.sure,990,530,nil,1.2)
end
--Block name

View File

@@ -62,13 +62,13 @@ function scene.keyDown(key)
end
end
elseif key=="delete"then
if sure>20 then
if sure>.3 then
TABLE.cut(MISSION)
cur=0
sure=0
SFX.play('finesseError',.7)
else
sure=50
sure=1
end
elseif key=="c"and kb.isDown("lctrl","rctrl")or key=="cC"then
if #MISSION>0 then
@@ -116,8 +116,8 @@ function scene.keyDown(key)
end
end
function scene.update()
if sure>0 then sure=sure-1 end
function scene.update(dt)
if sure>0 then sure=sure-dt end
end
function scene.draw()
@@ -184,8 +184,8 @@ function scene.draw()
--Confirm reset
if sure>0 then
gc.setColor(1,1,1,sure*.02)
gc.draw(TEXTURE.sure,980,600)
gc.setColor(1,1,1,sure)
mDraw(TEXTURE.sure,1000,640,nil,.9)
end
end

View File

@@ -67,13 +67,13 @@ function scene.keyDown(key)
end
end
elseif key=="delete"then
if sure>20 then
if sure>.3 then
TABLE.cut(BAG)
cur=0
sure=0
SFX.play('finesseError',.7)
else
sure=50
sure=1
end
elseif key=="="then
local l={1,2,3,4,5,6,7}
@@ -124,8 +124,8 @@ function scene.keyDown(key)
end
end
function scene.update()
if sure>0 then sure=sure-1 end
function scene.update(dt)
if sure>0 then sure=sure-dt end
end
function scene.draw()
@@ -187,8 +187,8 @@ function scene.draw()
--Confirm reset
if sure>0 then
gc.setColor(1,1,1,sure*.02)
gc.draw(TEXTURE.sure,1050,430,nil,.6)
gc.setColor(1,1,1,sure)
mDraw(TEXTURE.sure,1000,460,nil,.8)
end
end

View File

@@ -16,7 +16,7 @@ function scene.draw()
end
scene.widgetList={
WIDGET.newKey{name="setting",fText=TEXTURE.setting,x=1200,y=160,w=90,h=90,code=goScene'setting_game'},
WIDGET.newKey{name="match",x=640,y=500,w=760,h=140,font=60,code=function()MES.new('warn',"Coming soon 开发中,敬请期待")end},
WIDGET.newKey{name="match",x=640,y=500,w=760,h=140,font=60,code=function()MES.new('warn',text.notFinished)end},
WIDGET.newButton{name="back",x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
}

View File

@@ -18,7 +18,7 @@ end
scene.widgetList={
WIDGET.newKey{name="setting",fText=TEXTURE.setting,x=1200,y=160,w=90,h=90,code=goScene'setting_game'},
WIDGET.newButton{name="league", x=640, y=180,w=350,h=120,font=40,color='D',code=goScene'net_league'},
WIDGET.newButton{name="ffa", x=640, y=360,w=350,h=120,font=40,color='D',code=function()MES.new('warn',"Coming soon 开发中,敬请期待")--[[NET.enterRoom({name="ffa"})]]end},
WIDGET.newButton{name="ffa", x=640, y=360,w=350,h=120,font=40,color='D',code=function()MES.new('warn',text.notFinished)--[[NET.enterRoom({name="ffa"})]]end},
WIDGET.newButton{name="rooms", x=640, y=540,w=350,h=120,font=40,code=goScene'net_rooms'},
WIDGET.newButton{name="logout", x=880, y=40,w=180,h=60,color='dR',
code=function()

View File

@@ -59,23 +59,28 @@ function scene.sceneInit()
end
function scene.keyDown(key)
if key=="r"then
if fetchTimer<=7 then
fetchRoom()
end
elseif key=="s"then
SCN.go('setting_game')
elseif key=="n"then
SCN.go('net_newRoom')
elseif key=="escape"then
SCN.back()
elseif roomList:getLen()>0 and key=="return"then
local R=roomList:getSel()
if NET.getlock('fetchRoom')or not R then return end
if R.roomInfo.version==VERSION.room then
NET.enterRoom(R,passwordBox.value)
if NET.getlock('enterRoom')then return end
if WIDGET.sel~=passwordBox then
if key=="r"then
if fetchTimer<=7 then
fetchRoom()
end
elseif key=="s"then
SCN.go('setting_game')
elseif key=="n"then
SCN.go('net_newRoom')
elseif key=="escape"then
SCN.back()
elseif roomList:getLen()>0 and key=="return"then
local R=roomList:getSel()
if NET.getlock('fetchRoom')or not R then return end
if R.roomInfo.version==VERSION.room then
NET.enterRoom(R,passwordBox.value)
else
MES.new('error',"Version doesn't compatible 版本不兼容")
end
else
MES.new('error',"Version doesn't compatible 版本不兼容")
WIDGET.keyPressed(key)
end
else
WIDGET.keyPressed(key)
@@ -96,6 +101,14 @@ function scene.draw()
gc_setColor(1,1,1,.12)
gc_arc('fill','pie',250,630,40,-1.5708,-1.5708-.6283*fetchTimer)
--Joining mark
if NET.getlock('enterRoom')then
gc.setColor(1,1,1)
gc.setLineWidth(15)
local t=TIME()*6.26%6.2832
gc.arc('line','open',640,360,80,t,t+4.26)
end
--Room list
local R=roomList:getSel()
if R then
@@ -135,7 +148,7 @@ scene.widgetList={
WIDGET.newKey{name="refresh", x=250,y=630,w=140,h=120,code=fetchRoom,hideF=function()return fetchTimer>7 end},
WIDGET.newKey{name="new", x=510,y=630,w=260,h=120,code=pressKey"n"},
WIDGET.newKey{name="join", x=780,y=630,w=140,h=120,code=pressKey"return",hideF=function()return roomList:getLen()==0 or NET.getlock('enterRoom')end},
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=pressKey"escape"},
}
return scene

View File

@@ -1,8 +1,9 @@
local gc=love.graphics
local gc_setColor=gc.setColor
local gc_draw,gc_rectangle=gc.draw,gc.rectangle
local gc_rectangle=gc.rectangle
local gc_print,gc_printf=gc.print,gc.printf
local kb=love.keyboard
local setFont=setFont
local listBox=WIDGET.newListBox{name="list",x=50,y=50,w=1200,h=520,lineH=40,drawF=function(rep,id,ifSel)
@@ -54,6 +55,7 @@ local function replay(fileName)
loadGame(rep.mode,true)
resetGameData('r')
PLAYERS[1].username=rep.player
GAME.init=false
GAME.saved=true
GAME.fromRepMenu=true
@@ -65,6 +67,10 @@ end
function scene.sceneInit()
sure=0
listBox:setList(REPLAY)
local hide=listBox:getLen()==0
for i=3,5 do
scene.widgetList[i].hide=hide
end
end
function scene.keyDown(key)
@@ -73,12 +79,42 @@ function scene.keyDown(key)
if rep then
replay(rep.fileName)
end
elseif key=="escape"then
SCN.back()
elseif key=="c"and kb.isDown("lctrl","rctrl")or key=="cC"then
local rep=listBox:getSel()
if rep then
if rep.available and rep.fileName then
local repStr=FILE.load(rep.fileName)
if repStr then
love.system.setClipboardText(love.data.encode('string','base64',repStr))
MES.new('info',text.exportSuccess)
else
MES.new('error',text.replayBroken)
end
else
MES.new('error',text.replayBroken)
end
end
elseif key=="v"and kb.isDown("lctrl","rctrl")or key=="cV"then
local repStr=love.system.getClipboardText()
local res,fileData=pcall(love.data.decode,'string','base64',repStr)
if res then
local fileName=os.date("replay/%Y_%m_%d_%H%M%S_import.rep")
local rep=DATA.parseReplayData(fileName,fileData,false)
if rep.available then
if FILE.save(fileData,fileName,'d')then
table.insert(REPLAY,1,rep)
MES.new('info',text.importSuccess)
end
else
MES.new('error',text.dataCorrupted)
end
else
MES.new('error',text.dataCorrupted)
end
elseif key=="delete"then
local rep=listBox:getSel()
if rep then
if sure>20 then
if sure>.3 then
sure=0
listBox:remove()
love.filesystem.remove(rep.fileName)
@@ -90,31 +126,34 @@ function scene.keyDown(key)
end
SFX.play('finesseError',.7)
else
sure=50
sure=1
end
end
elseif key=="escape"then
SCN.back()
else
WIDGET.keyPressed(key)
end
end
function scene.update()
if sure>0 then sure=sure-1 end
function scene.update(dt)
if sure>0 then sure=sure-dt end
end
function scene.draw()
--Confirm delete
if sure>0 then
gc_setColor(1,1,1,sure*.02)
gc_draw(TEXTURE.sure,910,610)
gc_setColor(1,1,1,sure)
mDraw(TEXTURE.sure,930,640,nil,.9)
end
end
scene.widgetList={
listBox,
WIDGET.newButton{name="play",x=700,y=640,w=170,h=80,color='lY',code=pressKey"return",hideF=function()return listBox:getLen()==0 end,fText=DOGC{50,50,{'fPoly',10,0,49,24,10,49}}},
WIDGET.newButton{name="delete",x=850,y=640,w=80,h=80,color='lR',code=pressKey"delete",hideF=function()return listBox:getLen()==0 end,fText=DOGC{50,50,{'setLW',8},{'line',5,5,45,45},{'line',5,45,45,5}}},
WIDGET.newButton{name="back",x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
WIDGET.newButton{name="export",x=200,y=640,w=70,color='lG',code=pressKey"cC",fText=DOGC{50,50,{'fRect',8,44,34,4},{'fRect',22,17,6,23},{'fPoly',25,5,10,20,40,20}}},
WIDGET.newButton{name="import",x=300,y=640,w=70,color='lN',code=pressKey"cV",fText=DOGC{50,50,{'fRect',8,44,34,4},{'fRect',22,5,6,23},{'fPoly',25,40,10,25,40,25}}},
WIDGET.newButton{name="play",x=700,y=640,w=170,h=80,color='lY',code=pressKey"return",fText=DOGC{50,50,{'fPoly',10,0,49,24,10,49}}},
WIDGET.newButton{name="delete",x=850,y=640,w=80,h=80,color='lR',code=pressKey"delete",fText=DOGC{50,50,{'setLW',8},{'line',5,5,45,45},{'line',5,45,45,5}}},
WIDGET.newButton{name="back",x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
}

View File

@@ -42,9 +42,10 @@ return STRING.split([=[
新BGM:Secret8th Remix(用于master-hard)
新增小亚(xiaoya)语音包
旋转系统新增BiRS(Bias RS)(实验性),ASC,ASCplus(添加180度踢墙,实验性)
新增noInitSZO模式参数,自动跳过开局SZO(目前仅用于马拉松/20G模式) #121
可以通过剪切板导入/导出录像
自定义游戏的序列任务场地等数据退出保存
第一次启动会自动进入语言设置菜单 #150
新增noInitSZO模式参数,自动跳过开局SZO(目前仅用于马拉松/20G模式) #121
改动:
更换更简洁的加载动画,合并intro场景
调整TRS中S5和Z5的踢墙表,增加Ospin时SZ按反的尝试