Giter Club home page Giter Club logo

hollowknight-autosplit-wasm's Introduction

hollowknight-autosplit-wasm

An auto splitter for Hollow Knight that supports Windows, Mac, and Linux.

Installation

Download the hollowknight_autosplit_wasm.wasm file from the Latest Release.

Or follow the steps in Compilation and use target/wasm32-wasi/release/hollowknight_autosplit_wasm.wasm.

To configure LiveSplit or a LiveSplit One prototype to use this, see:

Compilation

This auto splitter is written in Rust. In order to compile it, you need to install the Rust compiler: Install Rust.

Afterwards install the WebAssembly target:

rustup target add wasm32-wasi --toolchain stable

The auto splitter can now be compiled:

cargo release

The auto splitter is then available at:

target/wasm32-wasi/release/hollowknight_autosplit_wasm.wasm

Make sure too look into the API documentation for the asr crate.

You can use the debugger while developing the auto splitter to more easily see the log messages, statistics, dump memory, step through the code and more.

The repository comes with preconfigured Visual Studio Code tasks. During development it is recommended to use the Debug launch action to run the asr-debugger. You need to install the CodeLLDB extension to run it.

You can then use the Build Auto Splitter (Debug) task to manually build the auto splitter. This will automatically hot reload the auto splitter in the asr-debugger.

Alternatively you can install the cargo watch subcommand and run the Watch Auto Splitter task for it to automatically build when you save your changes.

The debugger is able to step through the code. You can set breakpoints in VSCode and it should stop there when the breakpoint is hit. Inspecting variables currently does not work all the time.

Instructions for LiveSplit Windows

LiveSplit connects to this autosplitter and its settings via a LiveSplit Layout (.lsl) file. Make sure to use a different copy of your Layout for every different splits file you run with this autosplitter.

For hit-counter mode, best to use a layout that formats times and deltas without the decimals, such as the splits/hits/layout-direct.lsl file included in this repository.

Right-click -> Edit Layout... and you should see a Layout Editor with components like Title, Splits, Timer, etc. If it does not have a component named Auto Splitting Runtime, add one using the + Plus button -> Control -> Auto Splitting Runtime. Once that's there, click Layout Settings -> Auto Splitting Runtime, and next to Script Path, click Browse..., then navigate to the hollowknight_autosplit_wasm.wasm file. Then click Import Splits and select your splits file.

For hit-counter mode, change the Timing Method setting to either Hits / dream falls or Hits / damage.

Click Ok and and save the layout with Save Layout As..., with a name specific to the splits you're running with.

Deactivate the existing Hollow Knight autosplitter by Right-click -> Edit Splits... then next to Configurable Load Remover / Auto Splitter. (By DevilSquirrel), click Deactivate.

Then add this autosplitter via the Layout file you saved earlier. In the same Splits Editor from Right-click -> Edit Splits..., below where Configurable Load Remover / Auto Splitter. (By DevilSquirrel) was, check the Use Layout checkbox, click Browse next to that, and navigate to the Layout file from before. Select it and click Ok.

Finally, do not manually split or skip while running with this autosplitter, unless either it's explicitly marked as ManualSplit or it's the end-split. Don't manually split, skip, or undo splits in any other situation. The autosplitter will not know that you did that, and the autosplitter's state will be out of sync with LiveSplit's state.

Instructions for OBS LiveSplit One

Make sure to use obs-livesplit-one release v0.3.5 or later.

Go to the obs-livesplit-one releases page, and under the Assets section, download the one that matches your architecture and operating system. Follow the instructions in the How to install section of the obs-livesplit-one README file. On Windows, extract the obs-livesplit-one.dll to either C:\Program Files\obs-studio\obs-plugins\64bit or C:\Program Files (x86)\obs-studio\obs-plugins\64bit.

For hit-counter mode, modify your splits file, near the end after </Splits> but before </AutoSplitterSettings>, so that it contains <TimingMethod>HitsDreamFalls</TimingMethod> or <TimingMethod>HitsDamage</TimingMethod>.

Add OBS Source Livesplit One.

Properties:

  • Splits: Select your splits file
  • Use local autosplitter: Check
  • Local Auto Splitter file: Select the hollowknight_autosplit_wasm.wasm file
  • Custom auto splitter settings: Select Import Splits
  • Select a file: Select your splits file

Instructions for LiveSplit One Druid

Note: The main livesplit-one-druid repository might not be up-to-date enough to run this autosplitter.

To install my fork, go to the AlexKnauth LiveSplit One Druid Latest Release page, and under the Assets section, download the one for your architecture and operating system.

For hit-counter mode, modify your splits file before you open it in LiveSplit One Druid: near the end after </Splits> but before </AutoSplitterSettings>, so that it contains <TimingMethod>HitsDreamFalls</TimingMethod> or <TimingMethod>HitsDamage</TimingMethod>. If you need to after you've opened and saved it: modify it so it contains <Setting id="timing_method" type="string" value="HitsDreamFalls" /> or <Setting id="timing_method" type="string" value="HitsDamage" />.

When you run LiveSplit One Druid, it needs to have permission to read memory of other processes. On Mac, that might require running it under sudo.

Right-click or Control-click for the context menu:

  • Splits, Open... : Select your .lss splits file.
  • Layout, Open... : For the Layout, I recommend you use .ls1l layout file for LiveSplit One Druid, not a .lsl layout file. You can make a .ls1l file in the LiveSplit One Web version at https://one.livesplit.org/, or you can use the layout-web.ls1l file included in this repository as a starting point.
  • Open Auto-splitter... : Select the hollowknight_autosplit_wasm.wasm file.
  • Compare Against: Game Time.
  • Settings: Configure the hotkeys you want.

Finally, do not manually split or skip while running with this autosplitter, unless either it's explicitly marked as ManualSplit or it's the end-split. Don't manually split, skip, or undo splits in any other situation. The autosplitter will not know that you did that, and the autosplitter's state will be out of sync with LiveSplit One Druid's state.

Instructions for livesplit-one-desktop

Note: The main livesplit-one-desktop repository might not be up-to-date enough to run this autosplitter.

You can clone my fork with

git clone https://github.com/AlexKnauth/livesplit-one-desktop.git

According to the rust_minifb Build Instructions, on Linux you may need to install these dependencies first:

sudo apt install libxkbcommon-dev libwayland-cursor0 libwayland-dev

In the livesplit-one-desktop repository, modify the config.yaml file so that it contains

general:
  splits: <path-to-splits.lss>
  timing-method: GameTime
  auto-splitter: <path-to-hollowknight_autosplit_wasm.wasm>

where you replace <path-to-splits.lss> with the path to your splits file, and you replace <path-to-hollowknight_autosplit_wasm.wasm> with a path to the hollowknight_autosplit_wasm.wasm file.

To configure it with a layout file, modify the config.yaml file so that it contains

general:
  layout: <path-to-layout.lsl>

where you replace <path-to-layout.lsl> with a path to your layout file. You can use either a .lsl or a .ls1l layout with livesplit-one-desktop.

To configure hotkeys, modify the config.yaml file so that it contains

hotkeys:
  split: Numpad1
  reset: Numpad3
  undo: Numpad8
  skip: Numpad2
  pause: null
  undo_all_pauses: null
  previous_comparison: Numpad4
  next_comparison: Numpad6
  toggle_timing_method: null

Where you can replace those hotkey values with variants from livesplit_hotkey::KeyCode.

When you run livesplit-one-desktop, it needs to have permission to read memory of other processes. On Mac, that might require running it under sudo. For example in the livesplit-one-desktop repository, you can run

cargo build --release
sudo ./target/release/livesplit-one

For hit-counter mode, modify your splits file, near the end after </Splits> but before </AutoSplitterSettings>, so that it contains <TimingMethod>HitsDreamFalls</TimingMethod> or <TimingMethod>HitsDamage</TimingMethod>.

Finally, do not manually split or skip while running with this autosplitter, unless either it's explicitly marked as ManualSplit or it's the end-split. Don't manually split, skip, or undo splits in any other situation. The autosplitter will not know that you did that, and the autosplitter's state will be out of sync with livesplit-one-desktop's state.

The keyboard shortcuts of livesplit-one-desktop assume the Qwerty keyboard layout, so you may need to press where the key would be if you were using Qwerty. For example to save splits is "Control S" on Qwerty, but on a Dvorak keyboard, the Qwerty key "S" is where the Dvorak key "O" is, so use Dvorak "Control O" to save instead.

How to keep it on top over a Full Screen game on Mac: Start dragging the livesplit-one-desktop window, and while dragging it, do a multi-finger swipe motion to switch screens to the Full Screen game, and then stop dragging. It will stay on top of the Full Screen game temporarily, as long as you don't do any more screen-switching after that.

hollowknight-autosplit-wasm's People

Contributors

alexknauth avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar

hollowknight-autosplit-wasm's Issues

Don't split too early on quit-outs: GruzMother, DreamGate, UnchainedHollowKnight

During quit-outs, certain splits sometimes split too early.

When the game starts up, before it gets to the main menu, the PlayerData appears to include these unexpected values:

PlayerData hasDreamGate: true
PlayerData maxHealthBase: 4
PlayerData killedBigFly: true
PlayerData unchainedHollowKnight: true

Then, on some quit-outs, but not all, the game seems to go back to those unexpected values during the quit-out.

So it may sometimes wrongly split DreamGate, GruzMother, or UnchainedHollowKnight during a quit-out.

I've seen this happen with the existing auto-splitter with DreamGate, and I've heard from menmoe that it's been happening with GruzMother on 1221 as well.

Perhaps there should be an extra GameState Playing condition on these splits that this problem has been observed for, and not just on the Menu versions of these splits. Like, don't just fix MenuDreamGate (and MenuGruzMother if that existed), fix DreamGate and GruzMother themselves too.

Add OnObtainAllSkillsShuffleItem

Add OnObtainAllSkillsShuffleItem, and have it set an item variable to the name of the item before it splits, then set item back to blank after it splits.

Then make a splits file with 19 of these for the 19 required items, and run All Skills Shuffle!

The 19 required items are:

  1. Fireball
  2. Dash
  3. Claw
  4. Wraiths
  5. Dive
  6. CDash
  7. DDark
  8. DNail
  9. Cyclone
  10. Shade Soul
  11. Lurien
  12. Dash Slash
  13. Isma's
  14. Wings
  15. Shade Cloak
  16. Shriek
  17. Great Slash
  18. Monomon
  19. Herrah

Make sure "detect manual start" doesn't think its a start when the timer's been running but i just got set to 0

While testing for KilledOblobbles in asr-debugger, I encountered a problem with the manual start detection:

I had ColosseumSiverEntry as a start-triggering autosplit, and then KilledOblobbles, and then ColosseumSilverExit as an end-triggering autosplit.

I killed the Oblobbles and exited Colo 2, and it split both of those correctly, but, since it was asr-debugger and that doesn't know how many splits there are supposed to be, the asr-debugger timer state was still Running, not Ended, but the autosplitter's internal i was at 0.

Currently when the autosplitter sees i at 0 and the timer in Running, it thinks that's from a manual start, but in this case that's wrong because it had been Running the whole time. It should only be a manual start if the timer had been in Ended or NotRunning before, and then changed to Running.

Settings for Load Removed Time vs Hits, dream falls vs damage

A Choice enum setting Timing Method with variants

  • Load Removed Time
  • Hits / dream falls
  • Hits / damage

It should be possible to change this setting only when not in the middle of a run. Only either before starting, after ending, or after resetting.

State gets lost when closing and re-opening the game

During a rando race, closed the game to install a mod that I had forgotten, re-opened the game, and loaded back into the rando file. Before I loaded back in, the timer state was Running, but the auto-splitter's state was waiting to start. When I loaded back in, the start split RandoWake triggered (separate issue #76), causing the auto-splitter to reset and start the timer over again.

The state should be moved outside the process-until-closes block so that it can be preserved through a game re-start.

New autosplits in 3.1.10

  • New transition autosplits: Has Shade Soul, Grimm Flame 1-3, Beast Den
    • TransShadeSoul
  • New menu autosplit: Main Menu w/ Shade Soul
    • split description
  • New fun split: Stinky

Some missing splits

Common themes:

  • splits using mem.PlayerDataStringList with scenesGrubRescued, scenesEncounteredDreamPlantC
  • splits using lowercase names with map, killed, given (tip: use #[serde(rename = "name")] on these variants)
  • splits that should Skip under some other condition

Splits on hksplitmaker:

  • 0geo.json, 100-completion.json, 106.json, 107-comsob.json, 107-everything.json, 112-comsob.json, 112-everything-10-notch.json, 112-everything-11-notch.json, 12ms.json, 16ms.json, 3vf-kings-station.json, 3vf-stag-nest.json, 4ms-0geo.json, 4ms.json, 5-mimics.json, 8ms-fc-stag.json, 8ms.json, a1uba.json, acn-1221.json, acn.json, acnkgpz.json, acnnsc.json
  • al2ba.json, all-geo-chests.json, marissa-audience.json, myla-flower.json
    • ManualSplit Question: should this be in here even if I have to tell people "DO NOT MANUALLY SPLIT" because I don't know what the split index is? If it's only used as the final split it should be fine, but otherwise it seems irresponsible.
  • all-achievements.json, all-bosses-base-game.json, all-bosses-grimm-troupe-nmms.json, all-bosses-grimm-troupe.json, all-bosses-hidden-dreams-nmms.json, all-bosses-hidden-dreams.json, all-bosses-lifeblood.json, all-broken-charms.json
  • all-geo-rocks.json Question: Why does this use HuntersMark as an end-triggering autosplit? Answer: because the Kronk mod at HollowKnight.Kronk/Kronk/Kronk.cs SendMessageToLivesplit sets PlayerData.killedHunterMark to true for 0.1s so that Livesplit has a chance to autosplit.
  • all-hallownest-seals.json, all-keys.json, all-kings-idols.json, all-skills-1432plus.json, all-skills-2023-reroute.json, all-skills-ag.json, all-skills-emilitia.json, all-skills.json, all-stag-stations.json, all-unbreakable-charms-ss.json, all-unbreakable-charms.json, all-wanderers-journals.json, all-whispering-roots.json, any-1432plus-isma.json, any-1432plus-shade-soul.json, any-1432plus-spore.json, any-1432plus.json, any-ag.json, any-nmms-1028.json, any-nmms.json, any-ss.json, any.json, cartographer.json, clawless-shade-cloak.json
  • colo1-waves.json, colo2-waves.json, colo3-waves.json
  • colo1.json, colo2.json, colo3.json All just Manual Split?
  • eat-me-too.json, empty-hall.json, mylas-revenge.json, egg-101.json, egg.json, elderbug.json, elegy.json, enraged-guardian.json, eternal-ordeal-1mg.json, florist.json, fool-1221.json, ggg.json
  • ghostbusters.json
  • godhome-ending.json, godhome.json, gpz.json
  • grass.json
    • ends with manual split but not marked that way: make sure it can use timer state Ended to detect this
  • great-hopper.json, grubsong.json, happy-couple-1221.json, happy-couple.json
  • hiveblood.json although this might be out of date wrt Slopeball?
  • kronk.json Question: Why does this use HuntersMark as an end-triggering autosplit? Answer: because the Kronk mod at HollowKnight.Kronk/Kronk/Kronk.cs SendMessageToLivesplit sets PlayerData.killedHunterMark to true for 0.1s so that Livesplit has a chance to autosplit.
  • lbc.json, low-ab.json, low-ag.json, low-nmms.json, low-te-dropless.json, low.json, marmu.json, max-0-geo.json, menderbug.json, mr-mushroom-ending.json, myla.json, nice-1221.json, nice.json, nkg.json, nmg.json, nosk.json
  • p1.json, p2.json, p3.json, p4.json, p5.json
  • p5bo.json, round.json, pop-percent.json, pop.json
  • pure-snail.json
    • PureSnail Question: is the store.CheckIncreasedBy(Offset.health, 1) check here the right thing? this seems like it would wrongly exclude focusing while already at full health, or DeepFocus to increase by 2, and might wrongly include gaining health by other means such as a bench. is there a better way?
  • rando-te.json, room-timer.json, salubras-blessing.json, save-myla.json, sbaco.json, sbcmo.json, sbico.json, shriek.json, spelless-dreamshield.json, spelless-low.json, spelless-te-dreamshield.json, spelless-te.json, spelless.json, te-1432plus.json, te-ag.json, te-nmms.json, te.json, te-flukamoth.json
  • witness.json
    • ManualSplit Just be careful to only manually split when it's marked ManualSplit
  • worldsoul.json, wp-1315plus.json, wp.json, zote.json

What about the now-deprecated 106-comfy.json, and its PreGrimmShop split? Re-implement as a Lantern Shoptimisation split? See: https://github.com/AlexKnauth/hollowknight-autosplit-wasm/compare/shoptimisation

For witness.json: with so many manual splits, this category could use some new autosplits for Quirrel. But that can be for another time.

How to install using LiveSplitOne

Hey,

I'm having trouble installing the autosplitter. I decided to go for the LiveSplitOne option, as I'm running MacOS. The first thing listed in the README is two links to install, the first one if it's up to date, and if not the second one is there for backup. The first link is out of date, as the latest commit is only as of July 2023. The issue is that the second link doesn't even have anything to download.
I'm not familiar with rust at all so I might just be missing something very basic idk.

This project is something I find very interesting and I think you guys are doing an amazing thing by letting people on alternative operating systems speedrun properly. I hope you are successful with this and wish you all the best!

Colo 3 wave split improvements

Note:

  • only 1 kill left on Armored Squit journal entry at the start
  • only 2 kill left on Battle Obble

Tasks:

  • Gold1 Split skipped. TODO: try removing Squit?
  • Gold3 Split skipped. TODO: try removing Obble?
  • Gold4 Splitted. Heavy Fool: {1} +2 {3}, Belflies: {0} +6 {6}
  • Gold5 Splitted. Loodle: {0} +3 {3}
  • Gold6 Splitted. Loodle: {3} +5 {8}
  • Gold7 Splitted. Loodle: {8} +3 {11}
  • Gold8 Split skipped. DON'T REMOVE SQUIT HERE! already doing the best it can
  • Gold9a Splitted. ... Mantis Traitor: {0} +2 {2}, Mantis Petra: {0} +4 {4}
  • Gold9b Splitted. ... Soul Warrior: {0} +1 {1}
  • Gold10 Splitted. Volt Twister: {0} +3 {3}, Soul Twister: {2} +2 {4}
  • Gold11 Splitted.
  • Gold12a Splitted.
  • Gold12b Splitted.
  • Gold14a Split skipped. DON'T REMOVE SQUIT HERE! already doing the best it can
  • Gold14b Split skipped. DON'T REMOVE OBBLE HERE! already doing the best it can
  • Gold15 Split skipped. DON'T REMOVE SQUIT HERE! already doing the best it can
  • Gold16 Split skipped. DON'T REMOVE LOODLE HERE! already doing the best it can
  • Gold17a Splitted.
  • Gold17b Splitted.
  • Gold17c Split skipped. TODO: try removing Squit?
  • GoldEnd Splitted.

It may be possible to improve those splits that are skipped, by removing kill constraints on enemies such as the Armored Squit that have their journal entries completed by this point. But this should only be done if there's no way to "leave one alive" until the end of the wave. But that can be for later.

Don't count DreamGates for TransitionAfterSaveState

So that using DreamGate instead of a SaveState can work in a similar way.

  • Don't split on DreamGate
  • Split on transition after DreamGate, from the DreamGate scene
  • Split on normal transition, to the DreamGate scene

Initialize pointers for load-remover before timer is running

After CC suggested seeing how it handles stag cutscenes, I tested it with a split file that had RidingStag as a start-triggering autosplit.

Unlike most other start splits, RidingStag does not actually correspond to a load, so this uncovered an issue with the load remover having "startup time" which affects the timer on the first run to a difference of ~0.9 seconds relative to all other runs after that.

To fix this, any pointers used by the load-remover should be initialized before the timer is running, and not during the first tick after the timer is running.

Test multiple HK versions

Testing:

  • Windows 1578
  • Windows 1432
  • Windows 1221
  • Linux 1578
  • Linux 1432
  • Linux 1221
  • Mac 1578
  • Mac 1432
  • Mac 1221

Add Linux support

  • Executable name: Is hollow_knight.x86_64 good now, or is the truncated-15 version hollow_knight.x still needed?
  • Mono module name:
    • On 1221 and 1432, it's libmono.so.
    • However, I don't know for sure what it is on 1578 because I haven't gotten a Linux 1578 version to run yet: my first guess would be libmonobdwgc-2.0.so, but that's only a guess.
  • ELF format: Can I use the Rust asr crate's asr::file_format::elf::symbols iterator for this? Or do I have to roll my own thing with filesystem access?
  • Signature scanning: Try and see if the signature 48 8B 3D can work the same way on Linux as it does on Mac, in the first 0x100 bytes of the ELF format symbol mono_assembly_foreach.
  • Mono offsets:
    • On 1221
    • On 1432
    • On 1578

RandoWake as start triggers even in the middle of playing

RandoWake as start triggers even in the middle of playing an existing file, not just waking up at the start of a new one.

It should only trigger start on waking up at the start.

  • Figure out which field values change when waking up at the start of a rando, and in what order.
  • Does entryGateName or dreamReturnScene or other fields help distinguish Rando Wake from other ways of entering scenes?
  • Implement.
  • Test.

Tricky Ghost Splits

  • Cloth: implement the Traitor Lord dead on entry thing, shouldn't be too hard.
  • Revek: try using gladeGhostsKilled. try using SceneData for all other glade ghosts.
  • Vespa: figure something out that works without relying on Hive Knight, and without relying on Hiveblood if it's possible to get Vespa without that.

Dream-falling in Godseeker mode Atrium

In the Godhome Atrium, when you fall through the clouds below the platforms between the spawn point and the actual pantheons, you don't lose any health, but respawn at the spawn point with all your health still there.

That should count as a hit in the "Hits / dream falling" variant.

Count inventory-knockback-cancels as hits

  • Count inventory-knockback-cancels as hits
    • It currently counts some, but not all. Around 60%: when I get hit with 10 inventory-knockback-cancels in a row, it counts 5, 6, 7, or 8 of those (8 may have been an outlier, but 5 was not).
  • Only count an inventory-knockback-cancel as 1 hit
    • In that ~60% of cases where it detects recoiling during an IKC, make sure it doesn't count that as a 2nd hit
  • Count 2 hazard hits in a row as 2 hits
  • Don't double-count normal knockback hits
  • Don't double-count hazard respawn hits
  • Count a normal knockback wombo-combo into hazard as 2 hits
  • Count an inventory-knockback-cancel wombo-combo into hazard as 2 hits
  • Count a triple wombo-combo of normal, hazard, normal as 3 hits
  • Count a triple wombo-combo of normal, hazard, inventory-knockback-cancel as 3 hits

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.