project-slippi / slippi-js

Parse slp files and compute stats
GNU Lesser General Public License v3.0
148 stars 79 forks source link

Fixed conversion detection for mario/doc's Cape #130

Open Walnut356 opened 1 year ago

Walnut356 commented 1 year ago

An individual on r/ssbm pointed out that cape is not detected at all for conversion and combo detection. This is due to cape not changing a character's action state on hit. A hitlag check would pick it up, but to maintain 0.2.0 compatibility i try to avoid that. Here are the checks i used:

This should not only cover cape, but also some weird edge cases like fox's laser and phantom hits. The flaw of this is that if 2 of them happen in a row, last attack landed won't change so it'll be missed. That's pretty rare though, so the next check isn't 100% necessary if it turns out to be too far

Fully staled minimum damage cape does 3.15%. 3.1% is high enough that it won't trigger on magnifying glass or any form of pichu's self damage (which maxes out at 3%). The only other self damage i can think of that doesn't trigger any of the isDamaged states would be roy's fully charged neutral B

Alternatively, a more targeted check could work. Cape doesn't change the recipient's state, but it does incur hitlag and pause the action state counter. Checking for a change in the action state counter would also resolve the magnifying glass bug. As a side note, cape doesn't turn you around instantly, so you can't use facingDirection to detect it unfortunately =(

This isn't super well tested though, mainly because i have very few mario/doc replays laying around, and even fewer for most low tiers whose edge cases i'm probably forgetting. If y'all have some laying around, i'd be very grateful if you shot them my way. If not, i'll do my best to source a few hundred so i can test it fully before finalizing.

Walnut356 commented 11 months ago

I wasn't super pleased with the initial ideas I had for those checks. It's hard to test for all the niche cases, and it feels like there's a decent bit of wiggle room. Instead, I just added a (backwards compatible) hitstun check since it'll affect almost all replays that exist.

Slippi-js currently skips over the flags, so I had to add that into the parser. Long story short, State Bitfields 1-5 are read directly into a bigint (which is necessary due to JS not supporting more than 32 bits for bitwise number operations) and are treated as a 40-bit bitfield. I also added a Flag enum to support easy checks for the flag values. For completeness, every bit value is present, but if you'd like I can pare it down to only the documented ones.