Add Autoskip feature to TAS (#992)
This commit is contained in:
@@ -853,7 +853,7 @@ local commands={} do
|
||||
saveSettings()
|
||||
log("Allow TAS: "..bool)
|
||||
if bool then
|
||||
log("Hot keys: f1=play/pause f2=slow down f3=speed up/next frame")
|
||||
log("Hot keys: f1=play/pause f2=slow down f3=speed up/next frame f4=adjust skip settings")
|
||||
end
|
||||
else
|
||||
log{C.A,"Usage: tas <on|off>"}
|
||||
|
||||
@@ -10,6 +10,7 @@ local setFont,mStr=FONT.set,GC.mStr
|
||||
local noTouch,noKey=false,false
|
||||
local touchMoveLastFrame=false
|
||||
local trigGameRate,gameRate
|
||||
local autoSkip=0
|
||||
local modeTextPos,modeTextWidK
|
||||
|
||||
local replaying
|
||||
@@ -17,55 +18,70 @@ local repRateStrings={[0]="pause",[.125]="0.125x",[.5]="0.5x",[1]="1x",[2]="2x",
|
||||
|
||||
local scene={}
|
||||
|
||||
-- Widget hashmap (key = widget name, value = index)
|
||||
local widgetHashmap={}
|
||||
local function widgetWithName(name)
|
||||
if #widgetHashmap==0 then widgetHashmap=TABLE.kvSwap(TABLE.extract(scene.widgetList,'name')) end
|
||||
return scene.widgetList[widgetHashmap[name]]
|
||||
end
|
||||
|
||||
local function _updateMenuButtons()
|
||||
scene.widgetList.restart.hide=replaying
|
||||
widgetWithName('restart').hide=replaying
|
||||
|
||||
local pos=(GAME.tasUsed or replaying) and 'right' or SETTING.menuPos
|
||||
modeTextWidK=math.min(280/TEXTOBJ.modeName:getWidth(),1)
|
||||
if SETTING.portrait then
|
||||
scene.widgetList.restart.y=25-400
|
||||
scene.widgetList.pause.y=25-400
|
||||
widgetWithName('restart').y=25-400
|
||||
widgetWithName('pause').y=25-400
|
||||
else
|
||||
scene.widgetList.restart.y=25
|
||||
scene.widgetList.pause.y=25
|
||||
widgetWithName('restart').y=25
|
||||
widgetWithName('pause').y=25
|
||||
end
|
||||
if GAME.replaying then
|
||||
scene.widgetList.pause.x=1195
|
||||
widgetWithName('pause').x=1195
|
||||
modeTextPos=1185-TEXTOBJ.modeName:getWidth()*modeTextWidK
|
||||
elseif pos=='right' then
|
||||
scene.widgetList.restart.x=1125
|
||||
scene.widgetList.pause.x=1195
|
||||
widgetWithName('restart').x=1125
|
||||
widgetWithName('pause').x=1195
|
||||
modeTextPos=1115-TEXTOBJ.modeName:getWidth()*modeTextWidK
|
||||
elseif pos=='middle' then
|
||||
scene.widgetList.restart.x=360
|
||||
scene.widgetList.pause.x=860
|
||||
widgetWithName('restart').x=360
|
||||
widgetWithName('pause').x=860
|
||||
modeTextPos=940
|
||||
elseif pos=='left' then
|
||||
scene.widgetList.restart.x=120
|
||||
scene.widgetList.pause.x=190
|
||||
widgetWithName('restart').x=120
|
||||
widgetWithName('pause').x=190
|
||||
modeTextPos=1200-TEXTOBJ.modeName:getWidth()*modeTextWidK
|
||||
end
|
||||
end
|
||||
|
||||
local speedButtons={'rep0','repP8','repP2','rep1','rep2','rep5'}
|
||||
local stepButtons={'step','autoSkip'}
|
||||
local replayButtons=TABLE.combine(speedButtons,stepButtons)
|
||||
local function _updateRepButtons()
|
||||
local L=scene.widgetList
|
||||
if replaying or GAME.tasUsed then
|
||||
for i=1,6 do L[i].hide=false end L[7].hide=true
|
||||
for i=1,#speedButtons do
|
||||
widgetWithName(speedButtons[i]).hide=false
|
||||
end
|
||||
for i=1,#stepButtons do
|
||||
widgetWithName(stepButtons[i]).hide=gameRate~=0
|
||||
end
|
||||
if gameRate==0 then
|
||||
L[1].hide=true
|
||||
L[7].hide=false
|
||||
widgetWithName('rep0').hide=true
|
||||
elseif gameRate==.125 then
|
||||
L[2].hide=true
|
||||
widgetWithName('repP8').hide=true
|
||||
elseif gameRate==.5 then
|
||||
L[3].hide=true
|
||||
widgetWithName('repP2').hide=true
|
||||
elseif gameRate==1 then
|
||||
L[4].hide=true
|
||||
widgetWithName('rep1').hide=true
|
||||
elseif gameRate==2 then
|
||||
L[5].hide=true
|
||||
widgetWithName('rep2').hide=true
|
||||
elseif gameRate==5 then
|
||||
L[6].hide=true
|
||||
widgetWithName('rep5').hide=true
|
||||
end
|
||||
else
|
||||
for i=1,7 do L[i].hide=true end
|
||||
for i=1,#replayButtons do widgetWithName(replayButtons[i]).hide=true end
|
||||
end
|
||||
end
|
||||
local function _speedUp()
|
||||
@@ -115,7 +131,46 @@ local function _rep5()
|
||||
gameRate=5
|
||||
_updateRepButtons()
|
||||
end
|
||||
local function _step() trigGameRate=trigGameRate+1 end
|
||||
local function _skip(P)
|
||||
if P.frameRun<179 then
|
||||
trigGameRate=trigGameRate+(179-P.frameRun)
|
||||
else
|
||||
trigGameRate=trigGameRate+MATH.clamp(P.waiting+P.falling,1,300)
|
||||
end
|
||||
end
|
||||
local fastForwardObj = GC.newText(FONT.get(40),CHAR.icon.fastForward)
|
||||
local nextFrameObj = GC.newText(FONT.get(40),CHAR.icon.nextFrame)
|
||||
local function _updateStepButton()
|
||||
local w=PLAYERS[1].waiting+PLAYERS[1].falling
|
||||
if (autoSkip==1 and w>1) or (autoSkip>0 and PLAYERS[1].frameRun<178) then
|
||||
widgetWithName('step').obj=fastForwardObj
|
||||
else
|
||||
widgetWithName('step').obj=nextFrameObj
|
||||
end
|
||||
end
|
||||
local function _step()
|
||||
local P=PLAYERS[1]
|
||||
if autoSkip>0 then
|
||||
_skip(P)
|
||||
else
|
||||
trigGameRate=trigGameRate+1
|
||||
end
|
||||
end
|
||||
local function _fullSkipCheck()
|
||||
if autoSkip<2 or PLAYERS[1].waiting+PLAYERS[1].falling<=0 then return end
|
||||
_step()
|
||||
end
|
||||
local function _setAS(v)
|
||||
autoSkip=v
|
||||
if v==1 then _updateStepButton() end
|
||||
end
|
||||
local function _autoSkipDisp()
|
||||
return (
|
||||
autoSkip==0 and 'No skip' or
|
||||
autoSkip==1 and 'Semi-skip' or
|
||||
autoSkip==2 and 'Full skip'
|
||||
)
|
||||
end
|
||||
|
||||
local function _restart()
|
||||
resetGameData(PLAYERS[1].frameRun<240 and 'q')
|
||||
@@ -131,6 +186,8 @@ local function _checkGameKeyDown(key)
|
||||
if noKey then return end
|
||||
PLAYERS[1]:pressKey(k)
|
||||
VK.press(k)
|
||||
_updateStepButton()
|
||||
_fullSkipCheck()
|
||||
return
|
||||
elseif not GAME.fromRepMenu then
|
||||
_restart()
|
||||
@@ -155,11 +212,14 @@ function scene.enter()
|
||||
elseif not replaying then
|
||||
if GAME.tasUsed then
|
||||
trigGameRate,gameRate=0,0
|
||||
autoSkip=1
|
||||
else
|
||||
trigGameRate,gameRate=0,1
|
||||
autoSkip=0
|
||||
end
|
||||
end
|
||||
|
||||
_updateStepButton()
|
||||
_updateRepButtons()
|
||||
_updateMenuButtons()
|
||||
end
|
||||
@@ -172,6 +232,8 @@ function scene.touchDown(x,y)
|
||||
if t then
|
||||
PLAYERS[1]:pressKey(t)
|
||||
VK.touch(t,x,y)
|
||||
_updateStepButton()
|
||||
_fullSkipCheck()
|
||||
end
|
||||
end
|
||||
function scene.touchUp(x,y)
|
||||
@@ -250,6 +312,8 @@ function scene.keyDown(key,isRep)
|
||||
elseif not isRep then
|
||||
_speedUp()
|
||||
end
|
||||
elseif key=='f4' then
|
||||
autoSkip=(autoSkip+1)%3
|
||||
end
|
||||
end
|
||||
if key=='escape' then
|
||||
@@ -275,6 +339,8 @@ function scene.gamepadDown(key)
|
||||
if k>0 then
|
||||
PLAYERS[1]:pressKey(k)
|
||||
VK.press(k)
|
||||
_updateStepButton()
|
||||
_fullSkipCheck()
|
||||
else
|
||||
_restart()
|
||||
end
|
||||
@@ -314,6 +380,7 @@ function scene.update(dt)
|
||||
while trigGameRate>=1 do
|
||||
trigGameRate=trigGameRate-1
|
||||
_update_common(dt)
|
||||
_updateStepButton()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -403,15 +470,16 @@ function scene.draw()
|
||||
drawWarning()
|
||||
end
|
||||
scene.widgetList={
|
||||
WIDGET.newKey{name='rep0', x=40, y=50,w=60,code=_rep0, font=40,fText=CHAR.icon.pause},
|
||||
WIDGET.newKey{name='repP8', x=105,y=50,w=60,code=_repP8, font=40,fText=CHAR.icon.speedOneEights},
|
||||
WIDGET.newKey{name='repP2', x=170,y=50,w=60,code=_repP2, font=40,fText=CHAR.icon.speedOneHalf},
|
||||
WIDGET.newKey{name='rep1', x=235,y=50,w=60,code=_rep1, font=40,fText=CHAR.icon.speedOne},
|
||||
WIDGET.newKey{name='rep2', x=300,y=50,w=60,code=_rep2, font=40,fText=CHAR.icon.speedTwo},
|
||||
WIDGET.newKey{name='rep5', x=365,y=50,w=60,code=_rep5, font=40,fText=CHAR.icon.speedFive},
|
||||
WIDGET.newKey{name='step', x=430,y=50,w=60,code=_step, font=40,fText=CHAR.icon.nextFrame},
|
||||
WIDGET.newKey{name='restart',x=0, y=25,w=60,code=_restart, font=40,fText=CHAR.icon.retry_spin},
|
||||
WIDGET.newKey{name='pause', x=0, y=25,w=60,code=pauseGame,font=40,fText=CHAR.icon.pause},
|
||||
WIDGET.newKey {name='rep0', x=40, y=50, w=60, code=_rep0, font=40, fText=CHAR.icon.pause}, -- 1
|
||||
WIDGET.newKey {name='repP8', x=105,y=50, w=60, code=_repP8, font=40, fText=CHAR.icon.speedOneEights}, -- 2
|
||||
WIDGET.newKey {name='repP2', x=170,y=50, w=60, code=_repP2, font=40, fText=CHAR.icon.speedOneHalf}, -- 3
|
||||
WIDGET.newKey {name='rep1', x=235,y=50, w=60, code=_rep1, font=40, fText=CHAR.icon.speedOne}, -- 4
|
||||
WIDGET.newKey {name='rep2', x=300,y=50, w=60, code=_rep2, font=40, fText=CHAR.icon.speedTwo}, -- 5
|
||||
WIDGET.newKey {name='rep5', x=365,y=50, w=60, code=_rep5, font=40, fText=CHAR.icon.speedFive}, -- 6
|
||||
WIDGET.newKey {name='step', x=40, y=50, w=60, code=_step, font=40, fText=CHAR.icon.nextFrame}, -- 7
|
||||
WIDGET.newSlider{name='autoSkip',x=40, y=130,w=100,code=_setAS, axis={0,2,1}, disp=function()return autoSkip end,show=_autoSkipDisp},
|
||||
WIDGET.newKey {name='restart', x=0, y=25, w=60, code=_restart, font=40, fText=CHAR.icon.retry_spin}, -- 10
|
||||
WIDGET.newKey {name='pause', x=0, y=25, w=60, code=pauseGame,font=40, fText=CHAR.icon.pause}, -- 11
|
||||
}
|
||||
|
||||
return scene
|
||||
|
||||
Reference in New Issue
Block a user