diff --git a/fifa17-recon/tools/utas_server.py b/fifa17-recon/tools/utas_server.py index 3bda61c..33c97b2 100755 --- a/fifa17-recon/tools/utas_server.py +++ b/fifa17-recon/tools/utas_server.py @@ -1305,10 +1305,34 @@ def sweep_window(): # fetches; one probe at the end reads them all. _SWEEP_SPEC = None _SWEEP_POS = 0 +_SWEEP_SUBTYPE = 0 # 0..3 = player; see _parse_window for the other tables def _parse_window(win): - """'lo-hi' or 'auto:lo-hi:step' -> (lo, hi, step or None). None on garbage.""" + """'lo-hi' or 'auto:lo-hi:step' -> (lo, hi, step or None). None on garbage. + + An optional 't@' prefix sweeps a NON-PLAYER card table. The merge + FUN_180141660 dispatches on record+0x4c, which FUN_1800d8330 derives from + cardsubtypeid alone, and each branch queries a different table by + carddbid = record+0x18 (the same field players use for playerid): + + 0..3 -> 1 players 5 -> 3 headcoachcards + 4 -> 2 manager 8 -> 4 fitnesscoachcards + 6 -> 10 gkcoachcards 7 -> 5 physiocards + 9..b -> 7 (unidentified) absent -> 0x156 -> 0, NO merge at all + + So 't5@auto:1-20000:5000' sweeps head coaches exactly the way the default + sweeps players. Nothing about the non-player branches is live-proven yet; + they are read out of the binary. + """ + global _SWEEP_SUBTYPE + _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 auto = win.startswith("auto:") step = None if auto: @@ -1358,13 +1382,21 @@ def sweep_items(): else: start, end = lo, hi - out = [_item(SWEEP_ID_BASE + (pid - lo), pid, SWEEP_SENTINEL_RATING, - "ST", 0, 0, 0, [1, 1, 1, 1, 1, 1]) - for pid in range(start, end + 1)] - log(" SWEEP: serving %d candidate playerid(s) %d..%d%s " + 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 " "[synthetic, nothing saved]" % (len(out), start, end, - (" (auto, %d..%d done)" % (lo, end)) if step else "")) + (" (auto, %d..%d done)" % (lo, end)) if step else "", _SWEEP_SUBTYPE)) return out