-
I always split on explosion, which seemed to be what everyone else was doing when I learned the run.
-
We don't use loadless time anymore, there's no apparent consistent way to do it and loads have gotten much faster, so just use the real time.
New update just released today for PC. Big changes are performance, lag, and loading optimizations. "Added dedicated keyboard input for Dashing instead of it only ever being Double Tap Direction" which should be very helpful for keyboard runners. They seem to have fixed most of the issues introduced in the last update (especially with Broden).
Of concern was "Fixed zipline traversal issues" and "Fixes to various boss AI logic bugs" which made me worry they patched some glitches but testing out the levels that sounded most likely to be changed I haven't seen many issues, though I haven't done a full run yet.
One change that impacts speedruns: hitting 'space' to damage Sky Fortress has been patched, so you'll have to beat that boss normally.
Unfortunately, I haven't been able to get my autosplitter working with the new version. Given the difficulty of maintaining this and the difficulty using these autosplitters is causing for new runners, I would recommend that we go back to using real time as the primary timing method.
I keep my version updated at https://gist.github.com/argusdusty/7fea0526d09c74184f71c4d6c0911480
I experimented further with has_been_setup and found it performed poorly in later levels - not marking large sections of loading time correctly. So I found a different variable instead: "float level_start_counter : "Broforce_beta.exe", 0xA25234, 0x100, 0x0, 0x28;" (hopefully that path works for everyone) which is set to 2.0 when loading and counts downward while playing the level. It's a part of the GameModeController Mono object. It also excludes those helicopter transition screens.
I updated my autosplitter to use it and tested out a full run with it and it appears to be working fine (had to make a minor patch to get it working on the first level - see "initial_load" in my autosplitter for that). Hopefully I'll be submitting some runs with this soon so I can take back top spot on the leaderboards. My 41:05 run probably has an IGT well below 38m, but I guess there's no way to know for sure.
I put up an update to my autosplitter at https://gist.github.com/argusdusty/7fea0526d09c74184f71c4d6c0911480 with new isLoading code. Uses a "has_been_setup" byte that is 0 when a map is being loaded. The issue with finding the pointer is that it's assigned a new address on every level load.
Hopefully the default value I picked works for everyone, but I put up instructions for finding it with Cheat Engine in the comments at the gist link above, and can provide pointermaps on request. If it's not working, it should be equivalent to subtracting all the time where "LOADING" is on the screen, though I only did some brief testing.
I believe my version of the autosplitter at https://gist.github.com/argusdusty/7fea0526d09c74184f71c4d6c0911480, which I try to keep updated, should be working for the final split.
The latest update really messed with the code, I had to remove to IGT timer sections as I couldn't get that working anymore. Not sure how the newest runs are counting that - I assume they are manually adding up the time from all the individual levels?
Did a test any% run with the update. Took me awhile to rewrite my auto-splitter (broken by the update). Total load time went from 3 minutes under the old version to 1 minute with the update. Definitely saves a lot of time.
The GR666 cutscene skip is gone, but it only costs a second or so. The cutscene now triggers when you land and you can quickly skip through it and continue on with the quick kill.
Aside from the occasional new bug, I didn't notice any other speedrun-relevant changes, though there could be some in Campaign mode.
Hi all,
I've updated my autosplitter with my own isLoading method utilizing the in-game timers. The game keeps 2 timers representing the time taken on each level. The first is nil (which livesplit treats as '0') during the 'level complete' screen and '0' during loading. The second is computed at the 'level complete' screen and is '0' otherwise. Checking when both are '0' gives you only the loading screen, which works pretty well for me (I've done a complete run with an in-game timer - loading accounted for about 3m).
I'm trying to get the autosplitter into a more complete state now. I rescanned all the 'mono.dll' paths with a longer path length, which apparently they require. It's prohibitively expensive, computationally, to scan paths that long, so I determined the final offsets (using cheatengine's mono tools) for each variable and included them as comments in the script:
https://gist.github.com/argusdusty/7fea0526d09c74184f71c4d6c0911480
Hopefully this is working for everyone. If not, let me know what parts are acting up so I can further narrow down the pointer paths.
Update on that boss_health value: as it turns out, you can get game_speed < 0.3 outside of the final cutscene, using Bro Lee's special (0.01). I instead found another value near the health that can be used instead: float final_death_countdown : "mono.dll", 0x1F46AC, 0x8, 0x438, 0x18, 0x98, 0x1C4; Should be 0x24 offset from the health value (1C4 instead of 1E8). It decreases from 5 to 0 after the final hit on the boss, hitting 3 when the boss explodes. I updated my autosplitter to use that instead.
Hey lachszunge, My boss_health pointer apparently doesn't work for me either. I'm guessing that LiveSplit was treating an invalid pointer as 0 and thus current.boss_health <= 0 was always true. To the best of my knowledge the only way to get below 30% game_speed on the final level is by triggering the final cutscene/ending, so (current.game_speed < 0.30) on the final level should be sufficient without needing the boss_health variable at all.
However, I did rescan for the boss_health parameter and found that the pointer path varied for each boss. Scanning just for the final boss, I ended up with a single pointer path: "mono.dll", 0x1F46AC, 0x8, 0x438, 0x18, 0x98, 0x1E8; I noticed the freezing above 0 as well - if you want to use that variable you'll probably have to set the threshold to the maximum possible damage you can do (idk, maybe 100?). Though for now I'll leave it disabled in my script because not having it seems to work fine.
I tried your is_loading parameter and had no success. I also tried scanning for a 1 or 0 that indicated loading and had no success. I did, however, discover an interesting memory region that may be useful. I haven't been able to get a pointer path to it yet, but you hopefully can find it by searching for a 4-byte value, usually in the 15XXXXXX or 16XXXXXX range, with the properties:
- When playing normally: has the value 2000810396 (or is a pointer to the value 3277710731)
- When loading: is a pointer to the value 1945225193
- When in or after a boss cutscene (level 16 is a good test): has the value 0 (a nil pointer)
- At a constant address on each run of Broforce.exe Those 4 bytes and the surrounding memory region appear to be useful for getting an is_loading boolean. Hopefully you'll have better luck deciphering it than I did.
I would also be interested in having a Discord for the game. I have my Discord contact info in my profile, but there's no server for this game that I'm aware of.
For Arcade mode, it should just take you through all the levels in order on your first play-through without needing to play Campaign mode. And as Gammler33 notes you can get a level-select menu by beating the first level (IIRC it only goes up to the levels you've beaten before, but it's been a long while since I first completed Arcade mode so I only see every level). For NG+, however, you probably want to have all the bros unlocked (which takes a couple hours playing normally).
Oh wow, I can confirm this does work with controller, D-pad or analog stick. Makes that fight a lot easier.
For anyone else reading this, since it took me a few tries to figure out what's happening in the video - the trick is to be jumping upward (if you're falling it won't work) into the oncoming laser while holding 'up'. It's very easy to pull off.
Hey lachszunge,
I tested with your pointerlist and there are 2 which appear to work consistently for me: byte level : "mono.dll", 0x20A14C, 0x0, 0x364, 0x10, 0x18; byte level : "mono.dll", 0x20A14C, 0x0, 0x48C, 0x18, 0x18;
I'll update my script to use the first since it's the pointer you're already using.
I have my own pointerlist which doesn't overlap with yours at all, with 8 pointers: http://www.mediafire.com/file/qtbrrkrnql3m22p/broforce_level.zip
I also have a pointerlist for the boss health value, unfortunately over 8000 pointers: http://www.mediafire.com/file/6292s9k2d8k5c9p/broforce_health.zip The other value that could be causing issues with the split on Satan is game_speed, and I don't have a pointerlist for that. If you need to search for it, it's a float that goes from 1.0 to a smaller value when the game slows for some cutscenes/timebro. Should be -> 0.1 for Satan death and 0.35 for timebro's ability if I have the numbers right.
Hi all,
I extended lachszunge and Gammler33's auto splitter to be more fully featured. It will auto-start a run at the start, it will split at the end of the run, it will end the run when you return to the main menu, and it supports campaign mode (which you can enable by flipping some switches in a settings menu). You install it the same way as lachszunge explained in the first comment on this thread.
You can get the script here: https://gist.github.com/argusdusty/7fea0526d09c74184f71c4d6c0911480
Hopefully it works for everyone. I was hoping to narrow down the variable paths a bit before posting but it's been working consistently for me for awhile now.
I managed to replicate this in single player - it can be done when there's a drop next to the spike you revive on. I used to think reviving with Broniversal Soldier while on a spike was effectively a soft-lock and you had to restart the level, so this is cool.
This trick can be used to do level 59 quickly and consistently with Broniversal Solider, if you happen to get him. Not very likely in a run, but it just makes being able to do level 59 quickly a bit more likely (by my count there's now at least 8 bros who can do that jump consistently). Here's a video showcasing it:
Hi lachszunge, Nice find with the first Satan fight skip! I took a look at the run you posted and it looks like it's an OoB trick similar to the one used on level 15 - I've confirmed from past experiments on that level that you can do the trick with (at least) 3 bros - The Brode, Bro Lee, and The Brofessional. I've uploaded a video showcasing this:
I've also confirmed all 3 can do the Satan fight skip. I tried to use the OoB trick from level 15 (ledge climbing) to also skip Satan with any bro, and also tried having his mini-deathfield push you out, but it appears you can only get 1-2 blocks out of bounds with other bros without further tricks.
You can use those 3 bros to go OoB in a couple of places in the run - in addition to level 15 and the Satan fight, also the cutscene for the Acid Crawler on level 35 and the Satan cutscene on level 57 (if you go that route), though neither of those saves nearly as much time.
Hi Gammler33,
That path I posted above appears to stop working for me when I play around in the level editor, so I restarted my search with expanded parameters and messing about with the level editor, and have gotten it down to 634 paths. I've uploaded the PTR files here: http://www.mediafire.com/file/va1tsc79xmil98c/Pointer_Scan.zip
Those are from CheatEngine version 6.6, however.
I chose the new path to be closest to the one you originally had: "mono.dll", 0x1F6740, 0xA4, 0x7C, 0xC, 0xC0, 0x18;
, changing 0xC8 to 0xC0. Hopefully that remains consistent for me.
Hi lachszunge. Thanks for that guide. I used Cheat Engine 6.6, unfortunately, so I wasn't able to compare with your pointer scan, but following your method and repeating across restarts of the program, I narrowed the list to 56 pointer paths that appear to be consistent.
I picked one of the 56 paths at random - "mono.dll", 0x1F64D4, 0x30C, 0x10, 0x31C, 0x568;
works on my system. Hopefully it also works for anyone else trying to use this. It splits the instant the "Area Liberated" screen begins to appear, which is earlier than I usually split, but it does the job.
Hi lachszunge! This is excellent work and a very useful tool! Unfortunately I wasn't able to get the script working for me. Might vary from system to system. I put in a print statement to output current.level, and it appeared to be stuck on a single number, apparently random every time I started the program (124, 4, 68).
I'd love to work on this, but I'm afraid I don't have much experience with dll files. What was your process for tracking down the location of the level byte?