Files
OpenFUT/fifa17-recon/data
funman300 340c31f34e fifa17-recon: consumables -- the whole family, and it needs no id space at all
144 live cardtype-6 subtypes and 28 dead zones, all derived from the binary rather
than guessed, plus EA's own authored variants out of the dumped fcc_* tables.

MEASURED (decompiles read to their closing brace, lengths stated):
  FUN_1800d8330  (714 chars)   cardsubtypeid -> cardtype. The cardtype-6 space is
                               {51..136} u {201..220} u {250..273} u {300..341} = 172.
  FUN_18013f4d0  (8,354 chars) subtype -> category(rec+0xb8), sub-sel(rec+0xbc i16),
                               amount(rec+0xbf i8), single(rec+0xc0). Two callees, a
                               range clamp and an enum map; no DB handle is touched,
                               which is why a consumable has no identity to look up.
  FUN_1801bfac0  (42,813 chars) category -> FUT_CONSUMABLE_* string + a HARDCODED
                               5000xxx artwork constant. resourceId never reaches the
                               screen for a consumable.
  fcc_trainingcards 143 rows / fcc_healingcards 27 / fcc_contractcards 13, each with
  rowcount == rows_emitted == len(rows), so absences below are from a COMPLETE dump.

Two things the family will not forgive, both enforced in the builder rather than
documented and hoped for:
  * `amount` (atom 0x1b) is MANDATORY for categories 0, 4, 5, 9, 10. The parser
    initialises its temp to 0xffffffffffffffff, so omitting it stamps (byte)-1, and
    the accessors FUN_1801a8040/FUN_1801a8060 are `(int)*(char *)` -- SIGNED. The
    card reads "-1", not 0. consumable_item() raises instead.
  * A DEAD-ZONE subtype does not self-label. It falls to the bottom default of
    FUN_18013f4d0 and renders as an ordinary Squad Training (Pace) card with amount
    0. There is no "DB Error" analogue here, so every subtype we ship comes from
    data/consumables.json and the builder refuses the other 28.

Two corrections to the generated data, both from re-reading FUN_1801bfac0 case 5 and
case 0 rather than from the category table:
  * subtype 220 is named FUT_CONSUMABLE_NAME_SQUADTRAINING, not ..._PLAYERFITNESS.
    0xdc == 220 is the FIRST half of the squad-fitness test, so 220 always takes that
    branch, and there is no ..._SQUADFITNESS string in the binary at all.
  * all 28 dead zones are SQUADTRAINING, not PLAYERTRAINING: case 0 tests
    `subtype - 0x33 < 7` then `subtype - 0x3d < 7` and no dead zone satisfies either.
  Exactly 29 of 172 rows changed; nothing else moved.

INFERRED, and flagged as such in the module: the ?type= grouping. The vocabulary is
certain (FUN_18012ec50 arms healing=23, contract=24, training=25, development=6), but
the tab-to-arm binding has NEVER been observed -- only type=player, type=manager and
type=custom have ever come from this client.

Three families deliberately NOT shipped: manager_formation_mod (71-86) has zero rows
in the 143-row table AND FUN_1801bfac0 case 6 calls FUN_1801a0100 on the formations
result without the rowcount guard its twin case 7 has -- a crash candidate;
formation_mod (121-136) has artwork -1; manager_league (300-341) renders literally
"ML: %d" from a raw number and one shipped amount (2118) is in no league table.

Not wired into the server in this commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUT92pz6RWKih9dSr8ZpxW
2026-08-05 10:04:21 -07:00
..