SL2 Analyzer
Read a FromSoftware .sl2 save and report what is in it
Loading...
Searching...
No Matches
gen_sdt_lot_flags.py
Go to the documentation of this file.
1
#!/usr/bin/env python3
2
"""Regenerate db_sdt/lot_flags.json: the flag each Sekiro item lot REALLY sets.
3
4
`db_sdt/item_flags.json` files every world pickup under `50000000 + lot id`, and for
5
most lots that is the flag the game writes. Not for all of them. The game's own
6
`ItemLotParam` gives each lot a `getItemFlagId`, and a hundred rows in the table point
7
somewhere else — including every prosthetic part, every esoteric text, every Gourd Seed
8
and every world Prayer Bead in the nine areas the tool reads. Those lots set a GLOBAL
9
flag (`6500` for the Shuriken Wheel, `6725` for the courtyard Gourd Seed), so reading
10
the lot-shaped id reported them "still out there" on a save that had picked up all of
11
them hours earlier.
12
13
This joins the two and writes only the corrections, so `item_flags.json` itself is not
14
hand-edited:
15
16
moved {row id: the flag the lot actually sets}, where the two differ
17
misfiled [[row id, name]] for rows whose lot hands out a DIFFERENT item, so the
18
row's id says nothing about the item it names
19
20
A row counts as the lot's item when one of the lot's item names starts with the row's
21
name — the game's own names carry suffixes the table drops (`Sabimaru Memo (Bought)`,
22
`Sweet Rice Ball 2`). An id with no English name is no evidence either way and leaves
23
the row alone.
24
25
Input is `ItemLotParam` as `gen_sdt_from_regulation.py` extracts it, one row per lot:
26
27
python3 tools/gen_sdt_from_regulation.py --game-root ... --paramdex ... --out DIR
28
python3 tools/gen_sdt_lot_flags.py --lots DIR/item_flags.tsv [--write]
29
30
Without --write it prints the delta and writes nothing.
31
"""
32
33
import
argparse
34
import
csv
35
import
json
36
import
os
37
import
sys
38
39
BASE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
40
DB = os.path.join(BASE,
"db_sdt"
)
41
42
## The pickup family's id rule: a row id is this plus the lot id.
43
LOT_FLAG_BASE = 50000000
44
## ItemLotParam carries eight item slots per lot.
45
LOT_SLOTS = 8
46
47
48
def
load_json
(name):
49
with
open(os.path.join(DB, name), encoding=
"utf-8"
)
as
f:
50
return
json.load(f)
51
52
53
def
item_names
():
54
names = {}
55
for
stem
in
(
"weapons"
,
"goods"
):
56
for
k, v
in
load_json
(stem +
".json"
).items():
57
names.setdefault(int(k), []).append(v)
58
return
names
59
60
61
def
load_lots
(path):
62
with
open(path, encoding=
"utf-8"
, newline=
""
)
as
f:
63
return
{int(r[
"id"
]): r
for
r
in
csv.DictReader(f, delimiter=
"\t"
)}
64
65
66
def
lot_items
(lot, names):
67
out = []
68
for
i
in
range(1, LOT_SLOTS + 1):
69
iid = int(lot[f
"lotItemId{i:02d}"
])
70
if
iid:
71
out += names.get(iid, [])
72
return
out
73
74
75
def
build
(lots, rows, names):
76
moved, misfiled = {}, []
77
for
fid, name, _where
in
rows:
78
lot = lots.get(fid - LOT_FLAG_BASE)
79
if
lot
is
None
:
80
continue
81
items =
lot_items
(lot, names)
82
if
items
and
not
any(n.startswith(name)
for
n
in
items):
83
misfiled.append([fid, name])
84
continue
85
flag = int(lot[
"getItemFlagId"
])
86
if
flag > 0
and
flag != fid:
87
moved[str(fid)] = flag
88
return
{
"moved"
: moved,
"misfiled"
: misfiled}
89
90
91
## House style for db_*/: one-space indent, a short pair kept on one line.
92
def
dump
(table):
93
moved =
",\n"
.join(f
' "{k}": {v}'
for
k, v
in
table[
"moved"
].items())
94
misfiled =
",\n"
.join(
95
f
" {json.dumps(r, ensure_ascii=False)}"
for
r
in
table[
"misfiled"
]
96
)
97
return
f
'{{\n "moved": {{\n{moved}\n }},\n "misfiled": [\n{misfiled}\n ]\n}}\n'
98
99
100
def
main
():
101
ap = argparse.ArgumentParser(description=__doc__.split(
"\n"
)[0])
102
ap.add_argument(
"--lots"
, required=
True
, help=
"ItemLotParam TSV (item_flags.tsv)"
)
103
ap.add_argument(
"--write"
, action=
"store_true"
, help=
"write db_sdt/lot_flags.json"
)
104
args = ap.parse_args()
105
106
rows =
load_json
(
"item_flags.json"
).get(
"item_pickup"
, [])
107
table =
build
(
load_lots
(args.lots), rows,
item_names
())
108
print(f
"{len(table['moved'])} rows moved, {len(table['misfiled'])} misfiled"
)
109
for
fid, name
in
table[
"misfiled"
]:
110
print(f
" misfiled {fid} {name}"
)
111
if
args.write:
112
with
open(os.path.join(DB,
"lot_flags.json"
),
"w"
, encoding=
"utf-8"
)
as
f:
113
f.write(
dump
(table))
114
print(
"wrote db_sdt/lot_flags.json"
)
115
return
0
116
117
118
if
__name__ ==
"__main__"
:
119
sys.exit(
main
())
gen_sdt_lot_flags.item_names
item_names()
Definition
gen_sdt_lot_flags.py:53
gen_sdt_lot_flags.load_lots
load_lots(path)
Definition
gen_sdt_lot_flags.py:61
gen_sdt_lot_flags.main
main()
Definition
gen_sdt_lot_flags.py:100
gen_sdt_lot_flags.lot_items
lot_items(lot, names)
Definition
gen_sdt_lot_flags.py:66
gen_sdt_lot_flags.build
build(lots, rows, names)
Definition
gen_sdt_lot_flags.py:75
gen_sdt_lot_flags.load_json
load_json(name)
Definition
gen_sdt_lot_flags.py:48
gen_sdt_lot_flags.dump
dump(table)
House style for db_*/: one-space indent, a short pair kept on one line.
Definition
gen_sdt_lot_flags.py:92
tools
gen_sdt_lot_flags.py
Generated by
1.9.8