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

Tweak: Better Easy Pause Buffer input tracking #3054

Merged

Conversation

Archez
Copy link
Contributor

@Archez Archez commented Jul 1, 2023

We have two cheats to help with buffering inputs during un-pause for frame perfect tricks. The implementation for this had limitations and conflicts.

How it currently works

The vanilla game treats held inputs from before pausing as still held, and newly held inputs when un-pause finishes as ignored (unless frame perfect).

Enabling "Easy Input Buffering" makes it so during un-pause, any held inputs are triggered as pressed on first frame. This worked by blocking input from the pad manager during the un-pause. This has the effect that once unblocked, any held buttons will by seen as "newly pressed". This was timed such that it would happen on the first game frame after un-pause is finished. Coupled with "Easy Frame Advance" we would wait one extra frame then re-trigger the pause menu if start was held.

The Problems

There are two main issues with this approach:

  1. Any held inputs from before the pause (like Z-Target) are treated as repressed, messing up certain tricks like chu mega flips.
  2. Combining these cheats with simulated input lag would cause the pause menu to re-open even if you didn't hold start, as input blocking does not clear the controller input buffer (meaning blocking for 30 seconds means that on first frame(s) after unblock, simulated lag will replay the inputs from before the blocking.

The Proposed Changes

Instead of relying on input blocking, I have adjusted the flow to remember all held inputs when pausing, and then at the last frame of un-pause, those last held inputs are re-assigned to the pad manager prev inputs. This addresses both problems above by maintaining previously held inputs, and treating newly held inputs as "pressed" on first game frame, making it so inputs are dropped, and simulated lag has no impact on the behavior.

Build Artifacts

@inspectredc
Copy link
Contributor

Just one note on behaviour, in vanilla/n64 oot certain input presses can still be buffered in even if the input was being held down before the pause, e.g. rolling with a button. On this build it seems if the button was being pressed on the frame you paused there is no way to now input it

@Archez
Copy link
Contributor Author

Archez commented Jul 1, 2023

Just one note on behaviour, in vanilla/n64 oot certain input presses can still be buffered in even if the input was being held down before the pause, e.g. rolling with a button. On this build it seems if the button was being pressed on the frame you paused there is no way to now input it

With the idea of "Easy Input Buffering", I can't think of an elegant way to intentionally choose re-press vs not that isn't awkward for the user.
e.g. Z-target was held, then you use press Z to navigate kaleido, then hold it again before un-pausing. Should that be treated as a re-trigger or not?

I'm inclined to say that maybe that behavior is too complex for the "easy cheat" concept.

How often is that behavior leveraged for setups?

@inspectredc
Copy link
Contributor

So when i first thought about the problem for this I was thinking that maybe the z-targeting can just be special cased but not sure what your thoughts are on that.

The behaviour itself is not used by setups but rather it makes certain things work and feel better. For example, if you want to pull a bomb out on the first frame available after a roll or something, then you would be able to buffer in the bomb input on each frame. Another issue I can imagine happening is for doing something like a roll into a sideflip you may still be holding the roll button when you pause for the sideflip frame, and now it's not possible to input the flip despite being paused on the right frame.

@Archez
Copy link
Contributor Author

Archez commented Jul 1, 2023

So when i first thought about the problem for this I was thinking that maybe the z-targeting can just be special cased but not sure what your thoughts are on that.

Honestly, I'd rather prefer to not special-case. There's no real reason when/why a certain input should be special-cased, and I'd rather not make this more complicated.

For example, if you want to pull a bomb out on the first frame available after a roll or something, then you would be able to buffer in the bomb input on each frame.

By this do you mean holding bomb input on every from during the roll, so that on the first frame the bomb is allowed to come out, it will?


If it was to change, my suggestion would be to detect any button releases during the pause menu, and then upon un-pause those released buttons would be filtered from the "last inputs", allowing them to be re-pressed if they were held during close.

e.g. Hold A from roll, pause (A is tracked), during pause menu re-lease and re-hold A (A is subtracted from the tracked inputs), then on un-pause, A is seen as a re-press.

So then the only way to prevent a re-press would be to never let go of the button during the pause menu.

@inspectredc
Copy link
Contributor

Honestly, I'd rather prefer to not special-case. There's no real reason when/why a certain input should be special-cased, and I'd rather not make this more complicated.

Yea thats fair enough

By this do you mean holding bomb input on every from during the roll, so that on the first frame the bomb is allowed to come out, it will?

With pausing on each frame yes. The scenario I thought of was I paused and buffered an input 1 frame too early before I could pull an item, and now i have to wait 2 frames before I can input that item again.

If it was to change, my suggestion would be to detect any button releases during the pause menu, and then upon un-pause those released buttons would be filtered from the "last inputs", allowing them to be re-pressed if they were held during close.

The issue with this is that a lot of the buttons are needed to navigate the menu


The only other suggestion I could think of would be to check for inputs in that brief period after unpausing and consider them as new inputs rather than as part of the previous inputs. I feel that would restore behaviour in the closest way to n64 as possible since that closing menu time window is still decently large enough for players to use and is similar to the unpause lag.

@Archez
Copy link
Contributor Author

Archez commented Jul 1, 2023

If it was to change, my suggestion would be to detect any button releases during the pause menu, and then upon un-pause those released buttons would be filtered from the "last inputs", allowing them to be re-pressed if they were held during close.

The issue with this is that a lot of the buttons are needed to navigate the menu

The only other suggestion I could think of would be to check for inputs in that brief period after unpausing and consider them as new inputs rather than as part of the previous inputs. I feel that would restore behaviour in the closest way to n64 as possible since that closing menu time window is still decently large enough for players to use and is similar to the unpause lag.

At this point, it's really feeling like it is leaving the bounds of "easy pause buffer" cheat, if it would require near frame perfect action from the user.
That sounds more in line of a "restore pause menu lag" as a restoration and then like people chose if they want that vs the "easy" cheat.

I dunno, but I was trying to find a middle ground of "easy and versatile" for the existing cheat.

Comment on lines +29 to +30
CVarClear("gCheatEasyPauseBufferLastInputs");
CVarClear("gCheatEasyPauseBufferTimer");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do these need to be cvars? i don't have a better idea for where to put them off the top of my head but cvars don't quite feel right

Copy link
Contributor Author

@Archez Archez Aug 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something where a CVar rework/support for in-memory only CVars would be convenient for.

Alternatively, I could see these maybe moved to the GameInteractor state properties with extern C get/set methods, just would be a bit boiler plate-y to setup.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess even with in-memory only cvars I'd think of them more as "settings" than "state variables," so maybe GI state would be a cool pattern to set up? I'd love to hear what other people think about this.

Copy link
Contributor

@briaguya-ai briaguya-ai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can worry about cvar stuff when we do a bigger cvar cleanup push

Copy link
Contributor

@garrettjoecox garrettjoecox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works as advertised, and makes the code more understandable 🚀

@leggettc18 leggettc18 merged commit 91c6eba into HarbourMasters:develop-sulu Aug 13, 2023
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants