-
Notifications
You must be signed in to change notification settings - Fork 0
1. Quick Start
For simple game parsing, the syntax is similar to other parsers:
example = Game(file)
Combo output works using a ComboComputer object - similarly to the official Slippi-js parser, but with altered logic for higher quality output. See combo_example.py for simple multiprocessed example. Additionally, the combo detection logic is pretty heavily commented for those interested in the nuts and bolts. Everything should be pretty easy to modify for those looking to make bespoke detection logic.
To create the object that handles combo computing:
example = ComboComputer()
Optionally, a file can be passed directly to the ComboComputer constructor - e.g. ComboComputer(file)
- which will parse and prime the replay automatically.
To parse the replay and load the relevant data into the object manually, and/or reuse the ComboComputer:
example.prime_replay(Path)
To generate the list of combos for a specific slippi connect code:
example.combo_compute("CODE#123")
If no connect code is supplied, combos will automatically be generated for both active ports.
Additional optional keyword arguments allow toggling of the various checks that extend a combo. All are set to True by default (hitstun_check, hitlag_check, tech_check, downed_check, offstage_check, dodge_check, shield_check, shield_break_check, ledge_check)
Filter the combos for desired criteria (helper functions included), for example: every combo that killed that has more than 5 hits and does more than 40%, or does more than 70%:
for c in example.combos:
if(
c.did_kill and
(c.minimum_length(5) and c.minimum_damage(40)) or
(c.minimum_damage(60))
):
You can also reference the original parsed replay's metadata - contained within the ComboComputer object - to filter for character, stage, date range, opponent name/character, ranked/unranked, etc.
combo_example.py exports this filtered list to json format that is compatible with Project Clippi, and can be loaded in for playback with no fuss.
Combos are stored as a ComboData object (see: slippi/combo.py). Combo data includes the connect code of the player, a list of the moves used, a boolean flag for a kill, the start/end percent, the start/end frame, the death direction, and stock counts for both players. This allows for a variety of precise filtering options such as: combos contain/do not contain one or multiple instances of a move, filtering for the first, second, etc. or final move of a combo, filtering for combo frame-length, and more.
Stats calculation works through a StatsComputer, much like Combos in the previous section.
A multiprocessed convenience function is present for bulk replay processing: get_stats()
. Fair warning, it is not explicitly limited in any way. It will use 100% of your CPU while active. The following example code took ~3m 28s to process 1386 files on my Ryzen 5 1600x (6 core, 12 thread)
import slippistats as slp
from pathlib import Path
import polars as pl
import time
replay_dir = Path(R"E:\Slippi Replays\Netplay")
connect_code = "NUT#356"
if __name__ == "__main__":
stats = slp.get_stats(replay_dir, connect_code)
stats.wavedashes.write_parquet(R"StatsExamples\Output\wavedashes.parquet")
stats.dashes.write_parquet(R"StatsExamples\Output\dashes.parquet")
stats.techs.write_parquet(R"StatsExamples\Output\techs.parquet")
stats.take_hits.write_parquet(R"StatsExamples\Output\take_hits.parquet")
stats.l_cancels.write_parquet(R"StatsExamples\Output\l_cancels.parquet")
If you'd like more direct control over your output, or you only want a subset of the stats, you can use the StatsComputer objects directly. To create the object that handles stat computing:
example = StatsComputer() # stats computer objects are reusable and don't require a file on instantiation
example = StatsComputer(file_path) # creating with a file will automatically parse the replay to prepare for
StatsComputer objects maintain a member StatsComputer.players
which contains aggregated player metadata and convenience functions for exporting stats to Pandas/Polars - accessible through the StatsComputer.players[i].stats
container and the .to_polars()
/.to_pandas()
methods of each stat type
To parse the replay and load the relevant data into the object:
example.prime_replay(Path) # prime_replay() clears out the old data and replaces it with a fresh replay
To generate the stats, either a specific stat function can be called or all available stat functions can be called. The latter also has default keyword args to selectively disable stat calculations
# Specific stat functions will return the container directly
wavedash = example.wavedash_compute("CODE#123")
take_hit = example.take_hit_compute("CODE#123")
# All stats will return a player object, with stats accessible through .stats
all_stats = example.stats_compute("CODE#123", tech=False).stats
To view stats that have already been generated:
stats = example.get_player("CODE#123").stats # container with stat types
wd = stats.wavedahes # essentially list[WavedashData], has helper functions to_polars(), to_pandas(), and to_excel()