|
SL2 Analyzer
Read a FromSoftware .sl2 save and report what is in it
|
Functions | |
| address (fid, ks) | |
| Flag id -> (distance into the flag region, bit), or None for an unmapped group. | |
| clean (name) | |
| "Crystal Lizard [entity 3200259]" -> "Crystal Lizard". | |
| area_of (text) | |
| "Lothric Castle (m30_01_00_00)" -> "Lothric Castle". | |
| main () | |
Variables | |
| BASE = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
| SRC = os.path.join(BASE, "test", "flag_data", "files7", "ds3_onetime_enemy_flags.csv") | |
| BASES = os.path.join(BASE, "scratch", "ds3flags", "ds3_flag_group_bases.csv") | |
| OUT = os.path.join(BASE, "db_ds3", "enemies.json") | |
| int | SAVE_DELTA = 111 |
Build `db_ds3/enemies.json` — the one-time enemies whose death Dark Souls III flags. Source: `test/flag_data/files7/ds3_onetime_enemy_flags.csv`, itself extracted from the `.emevd` committed in `thefifthmatt/SoulsRandomizers` `dist/Base/`. The rows are calls to `common_func` templates that take a death flag and an entity id -- `20005340`, `20005341`, `20005342`, `20000343` (the mimics), `20005416`, `20005061`, `20005760`, plus map-local events that gate on a flag at start and set it after a death check -- those are deduped by entity id, for the reason given at the dedupe. WHY THIS IS TRUSTED, since a table of ids is worth nothing on its own. Run against a 79-save ladder in play-time order the count climbs 3 -> 98 with ZERO regressions, and the per-area breakdown lands where the player actually was: at 12:17:13 it reads Cathedral 9, Road of Sacrifices 7, High Wall 3, Undead Settlement 3, and nothing at all in Irithyll, Archdragon Peak, the Grand Archives or either DLC. A wrong base reads noise, and noise does not do that. `scratch/ds3_enemy_flags.py` is the check; re-run it if this table moves. The flags do NOT reset on a new journey -- the NG+2 ending save still reads 98, which is `63xx` boss-victory behaviour rather than per-map `13xxxx8xx` behaviour. Five more rows are dropped: their groups (`8`, `9`, `13105`) have no base in the CE table, and an unmapped group is absent rather than guessed, exactly like the three world-pickup groups. `X8` of the mimic template is NOT read -- the packet calls it a drop flag, but all six Irithyll Dungeon copies turn on in one snapshot while their death flags turn on hours apart, which is what an area-enable flag looks like. Run from repo root: python3 tools/gen_ds3_enemies.py
| gen_ds3_enemies.address | ( | fid, | |
| ks | |||
| ) |
Flag id -> (distance into the flag region, bit), or None for an unmapped group.
The byte counts DOWN inside each uint32 word. Same expression as every other DS3 table here, and it reproduces all 77 shipped bonfires exactly.
Definition at line 49 of file gen_ds3_enemies.py.
Referenced by main().
| gen_ds3_enemies.clean | ( | name | ) |
"Crystal Lizard [entity 3200259]" -> "Crystal Lizard".
The entity id is how the extractor kept rows apart; it is not a name, and 47 lines reading "Crystal Lizard [entity ...]" say less than 47 reading the type and a count. Duplicates ACROSS rows are real and are collapsed at render time by count_dupes, the same way seven separate mimics and four Shura Samurai already are — but a duplicate INSIDE one row is one flag covering two enemies, so it collapses here. Rows the source could not name keep their entity id, because "Unnamed enemy" three times would merge three different enemies into one line.
Definition at line 65 of file gen_ds3_enemies.py.
Referenced by main().
| gen_ds3_enemies.area_of | ( | text | ) |
"Lothric Castle (m30_01_00_00)" -> "Lothric Castle".
The map id is what the EMEVD file was called. A reader wants the area, and the spelling has to match nothing else here – this is its own section, not a join.
Definition at line 80 of file gen_ds3_enemies.py.
Referenced by main().
| gen_ds3_enemies.main | ( | ) |
| gen_ds3_enemies.BASE = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
Definition at line 36 of file gen_ds3_enemies.py.
| gen_ds3_enemies.SRC = os.path.join(BASE, "test", "flag_data", "files7", "ds3_onetime_enemy_flags.csv") |
Definition at line 37 of file gen_ds3_enemies.py.
| gen_ds3_enemies.BASES = os.path.join(BASE, "scratch", "ds3flags", "ds3_flag_group_bases.csv") |
Definition at line 38 of file gen_ds3_enemies.py.
| gen_ds3_enemies.OUT = os.path.join(BASE, "db_ds3", "enemies.json") |
Definition at line 39 of file gen_ds3_enemies.py.
| int gen_ds3_enemies.SAVE_DELTA = 111 |
Definition at line 43 of file gen_ds3_enemies.py.