5bf2c7ddc1abd38db801ba655efa357a69e5e390
2 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3b58b29094 |
fifa17-recon: club-item counts, and packs that contain more than footballers
Correcting an overstatement first: I said every card family works. Balls, stadia,
badges and kits do not, and this is the start of that, not the finish.
CLUB ITEMS (FUT_CLUBITEMS=1, default off). tools/fut_clubitems.py builds shelves from
the game's own tables: fcc_balls 42, fcc_stadium 78, fcc_badgecards 656,
fcc_kitcards 1482, fcc_leaguelogos 44, each with its real carddbid AND its real
cardassetid. Counts are wired into the club stat set, replacing the honest zeros
rather than appending a second row per id (the deserializer does
store[ctx][statId] = value, so two rows for one id is a coin toss).
Counts FIRST and on purpose. The consumables round proved the count gates the fetch:
the client does not ask for an item list until club/stats reports a non-zero count,
and the CLUB tab reads 0x1e balls, 0x28 kits, 0x14 stadia. Arming the counters is what
makes the client name the item route, which is the one thing static reading has never
produced for this family -- cardtype 9 has NO arm in the merge, so nothing about it is
discoverable from the card DB.
What is deliberately NOT guessed: which cardsubtypeid means ball versus stadium. The
eight values that reach cardtype 9 are {30,31,145..150} and the assignment appears in
none of the 149 dumped tables. probe_shelf() serves one item per candidate so the
screen can say which is which, rather than shipping a guess into someone's club.
PACKS (FUT_PACK_MIX=1, default on). A pack is no longer eleven footballers: roughly a
quarter of each pack is now consumables and occasionally staff, as a ratio so it
scales from a 5-card bronze to an 11-card premium. Club items are excluded until their
subtypes are verified -- a pack is the worst place to discover a wrong subtype,
because the card lands in the save and has to be cleaned out by hand.
Also fixes the art id AT THE SOURCE. fut_consumables now sets cardassetid from the
fcc_ tables, so a pack-granted consumable renders correctly too. The earlier fix only
corrected the copy served by the club route, which meant packs would have dealt cards
with the green NOT FOUND box again.
Pack tests run against a COPY of the profile, after an earlier test persisted 15 cards
into the live save and had to be undone by hand.
439 + 414 checks green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUT92pz6RWKih9dSr8ZpxW
|
||
|
|
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
|