Cosine256 / spelunky-2-tas-wizard

A mod for creating tool-assisted speedruns of Spelunky 2.
MIT License
0 stars 0 forks source link

Fixing the shortcomings of pausing and Overlunky interoperability #1

Closed Dregu closed 6 months ago

Dregu commented 10 months ago

I do have some OL updates planned, like

However, the best thing you can actually do, with or without these updates, is implement all of the required OL features in the mod, so it is not dependent on OL. I spruced up my old mod to test these features on PL some more and you can almost use it as is if you want to. It allows for (automatic) first frame pausing and even pre-first frame pausing, frame advancing cutscenes, skipping fades or disabling slowhack during fades.

https://gist.github.com/Dregu/bd3c68931d8591d2f4baa2a487569159

It will however clash with the default overlunky keys for the time being.

I didn't actually even test this with TASW and I'm not sure TASW is even compatible with first frame movement atm.

Cosine256 commented 10 months ago

These sound like great additions to the script API. What I eventually want is for TASW to be practical without OL, but to still be able to have OL running without hotkey conflicts (for OL stuff like the entity viewer, hitbox viewer, etc).

For pausing specifically, I really just want the PRE_UPDATE pausing to work, rather than the hacky state.pause pauses. The only reason TASW is using state.pause pausing right now is because that's the only way it could work with OL's frame advance, and I picked fade pauses in particular because they seem to be the least janky. If I could suppress OL keybinds or disable its pause feature, then I would happily implement the PRE_UPDATE pauses myself like in that example script you linked. I honestly wouldn't mind if state.pause frame advance disappears forever after PRE_UPDATE becomes viable.

I don't mind adding my own camera hack into TASW. There are a couple TASW-specific features I want to add anyways, such as fitting to level height, instantly snapping after teleports, and forcing the camera to zoom out and extend past the level boundaries to try to keep the GUI windows off the vanilla camera region.

One possible complication with the hotkeys is that Playlunky + Overlunky is a valid use case if you want skins or level gen mods alongside TASW, and still want all the other OL toys. If a user also runs TASW via PL, would it be able to suppress the OL hotkeys? Does the shared memory structure idea deal with this problem?

TASW can record and play back first-frame movement, but it can't fade pause during that frame, so you have to hold the inputs down as the level fades in while recording, or else you need to go back and edit the first frame if you miss it or hold the wrong direction.

Dregu commented 10 months ago

Yep I actually implemented hotkey suppressing from PL side in the mentioned PR already, with an updated example how to do that.

Cosine256 commented 10 months ago

That's excellent, thank you for working on this. Besides the GUI clutter, the limited frame advance is one of the biggest pain points I have with TASW and I'd love to fix that.

Dregu commented 10 months ago

Most of those went in yesterday, but next I'm adding a hook that lets you pause and frame advance menus too. You might want to wait for that.

Dregu commented 10 months ago

I'm done messing with TAS/camera/pause related UI and API for now. With the amount of useful tools in OL now, requiring OL seems even more logical, but maybe implement the bare minimum (frame advance) in mod when OL is not present.

Cosine256 commented 10 months ago

I looked over all the new pause changes and I want to clarify a couple things before I start working with the new system.

  1. Should I actually try to integrate with OL's pause system, or should I recreate the PRE_GAME_LOOP freeze pauses myself in TASW? I'm inclined to do the latter, and just suppress OL's pause hotkeys if needed. It looks like I could technically import "overlunky/pause" to use OL's pauses, but that's undocumented API behavior and you mentioned wanting to move that code to C++. Did I miss some other OL call that can get/set freeze pauses? PRE_GAME_LOOP freeze pauses seem to be the best ones for TASing anyways, so I'd rather not try to support the other OL pause types if I don't have to.
  2. I want to make sure I understand what set_start_level_paused is doing internally. It looks like it skips the game code that would have unpaused the game engine during the update where the fade-in ends, and leaves the game in a fade pause. Assuming I give TASW its own pause controls, I think I have a couple options. I could force this setting to turn off and do a freeze pause on the last fade-in frame to get roughly the same effect. Alternately, if start_level_paused is active, then I could clear the fade flag at the end of the update and swap it out for a TASW freeze pause at the start of the next frame. Is this setting shared between OL and PL? For that matter, are all of these write_mem_recoverable changes always shared between OL and PL?
Dregu commented 10 months ago

1. Ugh, I was supposed to implement all the features of the pause script's exports system in the bucket so you could command it from playlunky too, but I guess I missed setting the actual paused state, only added pause_type. Fixed some of that on WHIP now.

But yeah doing the pause system yourself and disabling the OL keys would probably still be the simplest way to make sure you only have to support one pause type and do it well. The camera update also makes it possible to only do one PRE_GAME_LOOP and adding all the conditions (during fading, menu, transition, start of level etc) there, without touching any state.pause flags at all. The bucket also only updates the overlunky options on next render loop, which might actually be too slow for what you're doing in 60Hz land.

2. Yeah the loading/fade unpause line in game code is simply removed, so theoretically nothing should have a chance to update in the level. Swapping the state pause to a freeze on one of the callbacks should also be seamless. Then again the !pause_loading option does only the "roughly the same effect".

The status of dirty/original recoverable memory is not shared between the tools yet, but it should really move to the bucket now, so one tool can enable a hack and other can disable it. It's very confusing for the tools atm. If one has already edited the memory before the other was even launched, it has no idea what the original code was.

TL;DR: Maybe just do it all yourself in PRE_GAME_LOOP if you want it done right, disabling all OL pause features. I'll even give you an option to make it impossible to use them.

Cosine256 commented 6 months ago

I've released TASW 1.1.0, which stops using fade pauses and upgrades to the new pause API. That should take care of all the pause interoperability issues with Overlunky. Thanks for all your work on the script API side of things.