Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed Passthrough #1156

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions parts/player/gameEnv0.lua
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ return {

-- Some Events are registered in player/init.lua, see "tableNeedMerge"
extraEvent={
{'attack',4},
{'attack',5},
},
extraEventHandler={
attack=function(P,P2,...)
P:beAttacked(P2,...)
attack=function(P,source,...)
P:beAttacked(source,...)
end,
},

Expand Down
86 changes: 43 additions & 43 deletions parts/player/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,17 @@ local function _loadRemoteEnv(P,confStr)-- Load gameEnv
end
end
end
local tableNeedMerge={
local function _mergeFuncTable(f,L)
if type(f)=='function' then
ins(L,f)
elseif type(f)=='table' then
for i=1,#f do
ins(L,f[i])
end
end
return L
end
local tableNeedMerge = {
'task',
'mesDisp',
'hook_left',
Expand All @@ -250,63 +260,53 @@ local tableNeedMerge={
'hook_spawn',
'hook_hold',
'hook_die',
'extraEvent',
'hook_atk_calculation',
'task',
}
for _,k in next,tableNeedMerge do gameEnv0[k]={} end
local function _mergeFuncTable(f,L)
if type(f)=='function' then
ins(L,f)
elseif type(f)=='table' then
for i=1,#f do
ins(L,f[i])
end
end
return L
end
local function _applyGameEnv(P)-- Finish gameEnv processing
local ENV=P.gameEnv

-- Create event tables
-- Apply events
for i=1,#tableNeedMerge do
ENV[tableNeedMerge[i]]=_mergeFuncTable(ENV[tableNeedMerge[i]],{})
end

-- Apply eventSet
while true do
if not (ENV.eventSet and ENV.eventSet~="X") then
break
end
if type(ENV.eventSet)~='string' then
MES.new('warn',"Wrong event set type: "..type(ENV.eventSet))
break
end
local eventSet=require('parts.eventsets.'..ENV.eventSet)
if not eventSet then
MES.new('warn',"No event set called: "..ENV.eventSet)
break
end
for k,v in next,eventSet do
if k=='extraEventHandler' then
for ev,handler in next,v do
if ENV.extraEventHandler[ev] then
local prevHandler=ENV.extraEventHandler[ev]
ENV.extraEventHandler[ev]=function(...)
prevHandler(...)
handler(...)
if ENV.eventSet and ENV.eventSet~="X" then
if type(ENV.eventSet)=='string' then
local eventSet=require('parts.eventsets.'..ENV.eventSet)
if eventSet then
for k,v in next,eventSet do
if k == "extraEvent" then
for _,ev in ipairs(v) do
table.insert(ENV.extraEvent, ev)
end
elseif k == "extraEventHandler" then
for ev,handler in pairs(v) do
if ENV.extraEventHandler[ev] then
local prevHandler = ENV.extraEventHandler[ev]
ENV.extraEventHandler[ev] = function(...)
prevHandler(...)
handler(...)
end
else
ENV.extraEventHandler[ev] = handler
end
end
elseif TABLE.find(tableNeedMerge,k) then
_mergeFuncTable(v,ENV[k])
elseif type(v)=='table' then
ENV[k]=TABLE.copy(v)
else
ENV.extraEventHandler[ev]=handler
ENV[k]=v
end
end
elseif TABLE.find(tableNeedMerge,k) then
_mergeFuncTable(v,ENV[k])
elseif type(v)=='table' then
ENV[k]=TABLE.copy(v)
else
ENV[k]=v
MES.new('warn',"No event set called: "..ENV.eventSet)
end
else
MES.new('warn',"Wrong event set type: "..type(ENV.eventSet))
end
break
end

P._20G=ENV.drop==0
Expand Down Expand Up @@ -512,4 +512,4 @@ function PLY.newPlayer(id,mini,p)
_applyGameEnv(P)
end
--------------------------</Public>--------------------------
return PLY
return PLY
109 changes: 71 additions & 38 deletions parts/player/player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,13 @@ function Player:act_rotRight()
-- 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.keyPressing[3] = false
self:resolveIRS()
self.keyPressing[3]=true
self.keyPressing[3] = true
end
self:spin(1)
self:_triggerEvent('hook_rotate',1)

-- Disable held inputs if IRS is off
if not self.gameEnv.irs then
self.keyPressing[3]=false
Expand All @@ -295,9 +295,9 @@ function Player:act_rotLeft()
-- 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.keyPressing[4] = false
self:resolveIRS()
self.keyPressing[4]=true
self.keyPressing[4] = true
end
self:spin(3)
self:_triggerEvent('hook_rotate',3)
Expand All @@ -315,9 +315,9 @@ function Player:act_rot180()
-- 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.keyPressing[5] = false
self:resolveIRS()
self.keyPressing[5]=true
self.keyPressing[5] = true
end
self:spin(2)
self:_triggerEvent('hook_rotate',2)
Expand Down Expand Up @@ -909,12 +909,45 @@ function Player:ifoverlap(bk,x,y)
end
end
function Player:attack(R,send,time,line)
self:extraEvent('attack',R.sid,send,time,line)
end
function Player:beAttacked(P2,sid,send,time,line)
if self==P2 or self.sid~=sid then return end
self:receive(P2,send,time,line)
P2:createBeam(self,send)
local sid = R.sid
-- Add the attack to the list of in-transit attacks.
-- These attacks will be able to cancel with incoming attacks that cross them.
if not self.inTransitAttacks then
self.inTransitAttacks = {}
end
if not self.inTransitAttacks[sid] then
self.inTransitAttacks[sid] = {seenAttacks = 0}
end
table.insert(self.inTransitAttacks[sid], {send=send, time=time, line=line})
-- Send the attack
-- We also send the number of seen attacks from this player.
-- This allows that player to know which attacks are still in transit, and which have already arrived.
-- This is because... if a player already saw an attack before sending this one, the attacks did not cross.
-- But if they didn't see the attack, then the attacks must have crossed (and should cancel each other)
self:extraEvent('attack',sid,send,time,line,self.inTransitAttacks[sid].seenAttacks)
end
function Player:beAttacked(source,target_sid,send,time,line,seenCount)
-- Only recieve the attack if you are the target.
if self==source or self.sid~=target_sid then return end

if not self.inTransitAttacks then
self.inTransitAttacks = {}
end
if not self.inTransitAttacks[source.sid] then
self.inTransitAttacks[source.sid] = {seenAttacks = 0}
end
-- Increment the number of seen attacks from that player.
self.inTransitAttacks[source.sid].seenAttacks = self.inTransitAttacks[source.sid].seenAttacks + 1
-- Block against any in-transit attacks before recieving (this prevents passhtrough)
for i=seenCount+1,#self.inTransitAttacks[source.sid] do
local atk = self.inTransitAttacks[source.sid][i]
local cancel = MATH.min(atk.send, send)
atk.send = atk.send - cancel
send = send - cancel
end

self:receive(source,send,time,line)
source:createBeam(self,send)
end
function Player:receive(A,send,time,line)
self.lastRecv=A
Expand Down Expand Up @@ -1205,7 +1238,7 @@ function Player:resetBlock()-- Reset Block's position and execute I*S
self.curY=y
self.minY=y+sc[1]

local ENV=self.gameEnv
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.
Expand All @@ -1221,10 +1254,10 @@ function Player:resetBlock()-- Reset Block's position and execute I*S
-- 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
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
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
Expand All @@ -1235,15 +1268,15 @@ function Player:resetBlock()-- Reset Block's position and execute I*S

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
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
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
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
Expand Down Expand Up @@ -1588,17 +1621,17 @@ function Player:_popNext(ifhold)-- Pop nextQueue to hand
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
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.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.
Expand Down Expand Up @@ -2558,11 +2591,11 @@ end
function Player:resolveIRS()
if self.bufferedIHS then
self:hold(true)
self.bufferedIHS=false
self.bufferedIHS = false
end

self.bufferedIRS=false
local pressing=self.keyPressing
self.bufferedIRS = false
local pressing = self.keyPressing
if pressing[5] then
self:act_rot180()
elseif pressing[3] then
Expand Down Expand Up @@ -2633,13 +2666,13 @@ local function update_alive(P,dt)
end
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
P.bufferedDelay = P.bufferedDelay - 1
if P.bufferedDelay <= 0 then
if P.bufferedIRS then
P:resolveIRS()
end
Expand Down
5 changes: 2 additions & 3 deletions parts/scenes/setting_control.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ function scene.enter()
das,arr=SETTING.das,SETTING.arr
pos,dir,wait=0,1,30
BG.set('bg1')
DiscordRPC.update("Tweaking control settings")
end

local trigFrame=0
Expand Down Expand Up @@ -97,11 +96,11 @@ scene.widgetList={
WIDGET.newSlider{name='dascut', x=250, y=420,lim=230,w=600,axis={0,20,1},disp=SETval('dascut'), show=_sliderShow,code=SETsto('dascut')},
WIDGET.newSlider{name='irscut', x=250, y=480,lim=230,w=600,axis={0,20,1},disp=SETval('irscut'), show=_sliderShow,code=SETsto('irscut')},
WIDGET.newSlider{name='dropcut',x=250, y=540,lim=230,w=300,axis={0,10,1},disp=SETval('dropcut'),show=_sliderShow,code=SETsto('dropcut')},

WIDGET.newSwitch{name='ihs', x=1100, y=240,lim=300, disp=SETval('ihs'), code=SETrev('ihs')},
WIDGET.newSwitch{name='irs', x=1100, y=300,lim=300, disp=SETval('irs'), code=SETrev('irs')},
WIDGET.newSwitch{name='ims', x=1100, y=360,lim=300, disp=SETval('ims'), code=SETrev('ims')},

WIDGET.newButton{name='reset', x=160, y=640,w=200,h=100,color='lR',font=40,
code=function()
local _=SETTING
Expand Down
2 changes: 1 addition & 1 deletion version.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
return {
["apkCode"]=1722,
["code"]=1722,
["string"]="V0.17.22",
["string"]="V0.17.22 + PASSTHROUGHFIXv1.0",
["room"]="ver A-14",
["name"]="暂停 Break",
}
Loading