Merge Electra's enhanced IRS

This commit is contained in:
MrZ_26
2024-09-03 21:12:32 +08:00
parent 9672a4fe57
commit 7407911914
15 changed files with 203 additions and 50 deletions

View File

@@ -1,8 +1,9 @@
return {
das=10,arr=2,
dascut=0,dropcut=0,
dascut=0,irscut=6,dropcut=0,
sddas=2,sdarr=2,
ihs=true,irs=true,ims=true,
logicalIHS=true,logicalIRS=true,logicalIMS=true,
ghostType='gray',
block=true,ghost=.3,center=1,

View File

@@ -270,27 +270,61 @@ function Player:act_rotRight()
if not self.control then return end
if self.cur then
self.ctrlCount=self.ctrlCount+1
if self.bufferedIRS then
-- Ensure IRS is spent before the rotation is processed so it doesn't throw things off.
-- This is so that if you for instance, are holding left IRS and then rotate right, it doesn't process
-- the left and right rotates in the reverse order.
self.keyPressing[3]=false
self:resolveIRS()
self.keyPressing[3]=true
end
self:spin(1)
self:_triggerEvent('hook_rotate',1)
self.keyPressing[3]=false
-- Disable held inputs if IRS is off
if not self.gameEnv.irs then
self.keyPressing[3]=false
end
end
end
function Player:act_rotLeft()
if not self.control then return end
if self.cur then
self.ctrlCount=self.ctrlCount+1
if self.bufferedIRS then
-- Ensure IRS is spent before the rotation is processed so it doesn't throw things off.
-- This is so that if you for instance, are holding left IRS and then rotate right, it doesn't process
-- the left and right rotates in the reverse order.
self.keyPressing[4]=false
self:resolveIRS()
self.keyPressing[4]=true
end
self:spin(3)
self:_triggerEvent('hook_rotate',3)
self.keyPressing[4]=false
-- Disable held inputs if IRS is off
if not self.gameEnv.irs then
self.keyPressing[4]=false
end
end
end
function Player:act_rot180()
if not self.control then return end
if self.cur then
self.ctrlCount=self.ctrlCount+2
if self.bufferedIRS then
-- Ensure IRS is spent before the rotation is processed so it doesn't throw things off.
-- This is so that if you for instance, are holding left IRS and then rotate right, it doesn't process
-- the left and right rotates in the reverse order.
self.keyPressing[5]=false
self:resolveIRS()
self.keyPressing[5]=true
end
self:spin(2)
self:_triggerEvent('hook_rotate',2)
self.keyPressing[5]=false
-- Disable held inputs if IRS is off
if not self.gameEnv.irs then
self.keyPressing[5]=false
end
end
end
function Player:act_hardDrop()
@@ -300,6 +334,10 @@ function Player:act_hardDrop()
if self.lastPiece.autoLock and self.frameRun-self.lastPiece.frame<ENV.dropcut then
SFX.play('drop_cancel',.3)
else
if self.bufferedIRS then
-- If the player drops quicker than their IRS cut delay, make sure IRS still resolves.
self:resolveIRS()
end
if self.curY>self.ghoY then
self:createDropFX()
self.curY=self.ghoY
@@ -344,7 +382,10 @@ function Player:act_hold()
if not self.control then return end
if self.cur then
if self:hold() then
self.keyPressing[8]=false
-- Disable held inputs if IHS is off
if not self.gameEnv.ihs then
self.keyPressing[8]=false
end
self:_triggerEvent('hook_hold')
end
end
@@ -1164,34 +1205,67 @@ function Player:resetBlock()-- Reset Block's position and execute I*S
self.curY=y
self.minY=y+sc[1]
local ENV=self.gameEnv
-- In the game settings, there are user-set control flags for irs,irs,ims
-- These control in what way the user can buffer their rotate/hold/move inputs.
-- (If enabled, they may hold these inputs from the previous piece instead of just Entry Delay)
-- And mode-set flags for logicalIRS,logicalIHS,logicalIMS
-- These control whether IRS/IHS/IMS are effective in modifying what you can do.
-- (For instance, changing your piece's spawn position in 20g, or saving you from a death).
-- If logical IRS is disabled, the player may still IRS, but it will just buffer their input,
-- not actually allowing them to survive in a way they could not without.
local pressing=self.keyPressing
-- IMS
if self.gameEnv.ims and (pressing[1] and self.movDir==-1 or pressing[2] and self.movDir==1) and self.moving>=self.gameEnv.das then
local x=self.curX+self.movDir
if not self:ifoverlap(C.bk,x,y) then
self.curX=x
-- IMS is enabled only when logicalIMS is enabled, because otherwise, it's just faster DAS.
if ENV.logicalIMS and (pressing[1] and self.movDir==-1 or pressing[2] and self.movDir==1) and self.moving>=self.gameEnv.das then
-- To avoid a top-out
if self:ifoverlap(C.bk,self.curX,self.curY) then
-- Always perform the shift, since you're topped out anyway
self.curX=self.curX+self.movDir
elseif ENV.wait>0 and ENV.ims then
-- Otherwise, only check IMS if it's enabled and you're in a mode with entry delay (20g)
local x=self.curX+self.movDir
if not self:ifoverlap(C.bk,x,y) then
self.curX=x
end
end
end
-- IRS
if self.gameEnv.irs then
if not ENV.logicalIRS then
-- If logical IRS is disabled, all IRS inputs will be buffered to prevent survival.
self.bufferedIRS=true
self.bufferedDelay=0
if ENV.wait==0 then
self.bufferedDelay=ENV.irscut
end
elseif ENV.wait==0 and ENV.irscut>0 and not self:ifoverlap(C.bk,self.curX,self.curY) then
-- If IRS cut delay is enabled and we aren't currently dying, buffer the input instead.
self.bufferedIRS=true
self.bufferedDelay=ENV.irscut
else
-- If we're currently dying or in an entry-delay mode (20g), perform the rotation right away.
if pressing[5] then
self:spin(2,true)
self:act_rot180()
elseif pressing[3] then
if pressing[4] then
self:spin(2,true)
self:act_rot180()
else
self:spin(1,true)
self:act_rotRight()
end
elseif pressing[4] then
self:spin(3,true)
self:act_rotLeft()
end
end
-- Disable held inputs if IRS is off
if not ENV.irs then
pressing[3],pressing[4],pressing[5]=false,false,false
end
-- DAS cut
if self.gameEnv.dascut>0 then
self.moving=self.moving-(self.moving>0 and 1 or -1)*self.gameEnv.dascut
if ENV.dascut>0 then
self.moving=self.moving-(self.moving>0 and 1 or -1)*ENV.dascut
end
-- Spawn SFX
@@ -1511,9 +1585,29 @@ function Player:_popNext(ifhold)-- Pop nextQueue to hand
local pressing=self.keyPressing
-- IHS
if not ifhold and pressing[8] and ENV.ihs and self.holdTime>0 then
self:hold(true)
pressing[8]=false
if not ifhold and pressing[8] and self.holdTime>0 then
if not ENV.logicalIHS then
-- If logical IHS is disabled, all IHS inputs will be buffered to prevent survival.
self.bufferedIRS=true
self.bufferedIHS=true
self.bufferedDelay=0
if ENV.wait==0 then
self.bufferedDelay=ENV.irscut
end
elseif ENV.wait==0 and ENV.irscut>0 and not self:willDieWith(self.cur) then
-- If IRS cut delay is enabled and we're not currently dying, buffer the input instead.
self.bufferedIRS=true
self.bufferedIHS=true
self.bufferedDelay=ENV.irscut
self:resetBlock()
else
-- If we're currently dying or in an entry-delay mode (20g), perform the hold immediately.
self:hold(true)
end
-- Disable held inputs if IHS is off
if not ENV.ihs then
pressing[8]=false
end
else
self:resetBlock()
end
@@ -1827,7 +1921,7 @@ do
end
end
local yomi = ""
local yomi=''
piece.spin,piece.mini=dospin,false
piece.pc,piece.hpc=false,false
@@ -1838,7 +1932,7 @@ do
cscore=(spinSCR[C.name] or spinSCR[8])[cc]
if self.b2b>800 then
self:showText(text.b3b..text.block[C.name]..text.spin..text.clear[cc],0,-30,35,'stretch')
yomi = yomi..text.b3b..text.block[C.name]..text.spin..text.clear[cc]
yomi=yomi..text.b3b..text.block[C.name]..text.spin..text.clear[cc]
atk=b2bATK[cc]+cc*.5
exblock=exblock+1
cscore=cscore*2
@@ -1848,7 +1942,7 @@ do
end
elseif self.b2b>=50 then
self:showText(text.b2b..text.block[C.name]..text.spin..text.clear[cc],0,-30,35,'spin')
yomi = yomi..text.b2b..text.block[C.name]..text.spin..text.clear[cc]
yomi=yomi..text.b2b..text.block[C.name]..text.spin..text.clear[cc]
atk=b2bATK[cc]
cscore=cscore*1.2
Stat.b2b=Stat.b2b+1
@@ -1857,13 +1951,13 @@ do
end
else
self:showText(text.block[C.name]..text.spin..text.clear[cc],0,-30,45,'spin')
yomi = yomi..text.block[C.name]..text.spin..text.clear[cc]
yomi=yomi..text.block[C.name]..text.spin..text.clear[cc]
atk=2*cc
end
sendTime=20+atk*20
if mini then
self:showText(text.mini,0,-80,35,'appear')
yomi = text.mini..' '..yomi
yomi=text.mini..' '..yomi
atk=atk*.25
sendTime=sendTime+60
cscore=cscore*.5
@@ -1884,7 +1978,7 @@ do
cscore=clearSCR[cc]
if self.b2b>800 then
self:showText(text.b3b..text.clear[cc],0,-30,50,'fly')
yomi = text.b3b..text.clear[cc]..yomi
yomi=text.b3b..text.clear[cc]..yomi
atk=4*cc-10
sendTime=100
exblock=exblock+1
@@ -1895,7 +1989,7 @@ do
end
elseif self.b2b>=50 then
self:showText(text.b2b..text.clear[cc],0,-30,50,'drive')
yomi = text.b2b..text.clear[cc]..yomi
yomi=text.b2b..text.clear[cc]..yomi
sendTime=80
atk=3*cc-7
cscore=cscore*1.3
@@ -1905,7 +1999,7 @@ do
end
else
self:showText(text.clear[cc],0,-30,70,'stretch')
yomi = text.clear[cc]..yomi
yomi=text.clear[cc]..yomi
sendTime=60
atk=2*cc-4
end
@@ -1913,7 +2007,7 @@ do
piece.special=true
else
self:showText(text.clear[cc],0,-30,35,'appear',(8-cc)*.3)
yomi = text.clear[cc]..yomi
yomi=text.clear[cc]..yomi
atk=cc-.5
sendTime=20+floor(atk*20)
cscore=cscore+clearSCR[cc]
@@ -1932,7 +2026,7 @@ do
atk=atk+1
end
self:showText(text.cmb[min(cmb,21)],0,25,15+min(cmb,15)*5,cmb<10 and 'appear' or 'flicker')
yomi = yomi..' '..text.cmb[min(cmb,21)]
yomi=yomi..' '..text.cmb[min(cmb,21)]
cscore=cscore+min(50*cmb,500)*(2*cc-1)
end
@@ -2460,6 +2554,28 @@ local function _updateFX(P,dt)
end
end
end
function Player:resolveIRS()
if self.bufferedIHS then
self:hold(true)
self.bufferedIHS=false
end
self.bufferedIRS=false
local pressing=self.keyPressing
if pressing[5] then
self:act_rot180()
elseif pressing[3] then
if pressing[4] then
self:act_rot180()
else
self:act_rotRight()
end
elseif pressing[4] then
self:act_rotLeft()
end
end
local function update_alive(P,dt)
local ENV=P.gameEnv
@@ -2518,6 +2634,18 @@ local function update_alive(P,dt)
end
end
-- Buffer IRS after IRS cut delay has elapsed.
-- The purpose of this is to allow the player to release their rotate key during the IRS cut delay,
-- which will allow them to avoid accidentally using IRS.
if P.bufferedDelay then
P.bufferedDelay=P.bufferedDelay-1
if P.bufferedDelay<=0 then
if P.bufferedIRS then
P:resolveIRS()
end
end
end
-- Moving pressed
if P.movDir~=0 then
local das,arr=ENV.das,ENV.arr
@@ -2877,7 +3005,7 @@ function Player:revive()
SFX.play('emit')
end
function Player:torikanEnd(requiredTime)
if self.stat.time < requiredTime then
if self.stat.time<requiredTime then
return false
end
self:_die()