fifa17-recon: sweep every staff table at once (t*@)

The manager sweep (subtype 4, ids 1-5000) came back with 5000 records at
cardtype 2 -- confirming FUN_1800d8330(4)=2 live -- and NOTHING written: no name,
no nation, no teamid, and no miss-fill either. Our sentinel rating 7, position 25
and attributes all survived. So either manager ids are not in 1-5000 or that
branch keys off something the player branch does not.

Guessing the id space costs a club visit per guess, so 't*@lo-hi' now fans all
five non-player tables across one range in a single response: 4 managercards,
5 headcoachcards, 6 gkcoachcards, 7 physiocards, 8 fitnesscoachcards. One staff
tab load tests 1000 ids against all five.

The full table set, from the DLL's own strings: players, managercards,
headcoachcards, fitnesscoachcards, gkcoachcards, physiocards, fancards, newcards
-- plus a consumables family (contract, fitness, healing, position, training and
playstyle modifiers, formation and league mods) and club items (badges, balls,
kits) which are almost certainly NOT DB-resolved the way cards are.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUT92pz6RWKih9dSr8ZpxW
This commit is contained in:
funman300
2026-08-04 21:25:43 -07:00
parent 1b1c178c09
commit b996c0673d
+29 -15
View File
@@ -1306,6 +1306,10 @@ def sweep_window():
_SWEEP_SPEC = None
_SWEEP_POS = 0
_SWEEP_SUBTYPE = 0 # 0..3 = player; see _parse_window for the other tables
# The five non-player card tables, as dispatched by FUN_1800d8330:
# 4 -> managercards 5 -> headcoachcards 6 -> gkcoachcards
# 7 -> physiocards 8 -> fitnesscoachcards
_STAFF_SUBTYPES = [4, 5, 6, 7, 8]
def _parse_window(win):
@@ -1329,10 +1333,13 @@ def _parse_window(win):
_SWEEP_SUBTYPE = 0
if win.startswith("t") and "@" in win:
head, win = win.split("@", 1)
try:
_SWEEP_SUBTYPE = int(head[1:], 0)
except ValueError:
return None
if head == "t*":
_SWEEP_SUBTYPE = -1 # fan every staff table across the range
else:
try:
_SWEEP_SUBTYPE = int(head[1:], 0)
except ValueError:
return None
auto = win.startswith("auto:")
step = None
if auto:
@@ -1382,21 +1389,28 @@ def sweep_items():
else:
start, end = lo, hi
# 't*@' fans EVERY staff subtype across the range at once, so one staff-tab
# load tests managercards / headcoachcards / fitnesscoachcards / physiocards /
# gkcoachcards together instead of costing five separate visits.
subs = _STAFF_SUBTYPES if _SWEEP_SUBTYPE == -1 else [_SWEEP_SUBTYPE]
# Only cardsubtypeid ever changes. itemType stays "player" because the merge
# dispatches on the subtype alone and the wire shape of a real staff item has
# never been observed -- inventing one is the change class that freezes this
# client.
out = []
for pid in range(start, end + 1):
it = _item(SWEEP_ID_BASE + (pid - lo), pid, SWEEP_SENTINEL_RATING,
"ST", 0, 0, 0, [1, 1, 1, 1, 1, 1])
if _SWEEP_SUBTYPE:
# Only the subtype is changed. itemType stays "player" because the
# merge dispatches on cardsubtypeid alone and the wire shape for a
# staff item has never been observed -- inventing one is the change
# class that freezes the client.
it["cardsubtypeid"] = _SWEEP_SUBTYPE
out.append(it)
log(" SWEEP: serving %d candidate id(s) %d..%d%s subtype=%d "
for si, sub in enumerate(subs):
it = _item(SWEEP_ID_BASE + (pid - lo) * len(subs) + si, pid,
SWEEP_SENTINEL_RATING, "ST", 0, 0, 0, [1, 1, 1, 1, 1, 1])
if sub:
it["cardsubtypeid"] = sub
out.append(it)
log(" SWEEP: serving %d item(s) for id(s) %d..%d%s subtype(s)=%s "
"[synthetic, nothing saved]"
% (len(out), start, end,
(" (auto, %d..%d done)" % (lo, end)) if step else "", _SWEEP_SUBTYPE))
(" (auto, %d..%d done)" % (lo, end)) if step else "",
",".join(str(s) for s in subs)))
return out