From 340c31f34e54de57aa4f724a584c88fe2b004775 Mon Sep 17 00:00:00 2001 From: funman300 Date: Wed, 5 Aug 2026 10:04:21 -0700 Subject: [PATCH] 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 Claude-Session: https://claude.ai/code/session_01VUT92pz6RWKih9dSr8ZpxW --- fifa17-recon/data/consumables.json | 4438 +++++++++++++++++++++++ fifa17-recon/tools/build_consumables.py | 245 ++ fifa17-recon/tools/fut_consumables.py | 262 ++ 3 files changed, 4945 insertions(+) create mode 100644 fifa17-recon/data/consumables.json create mode 100644 fifa17-recon/tools/build_consumables.py create mode 100644 fifa17-recon/tools/fut_consumables.py diff --git a/fifa17-recon/data/consumables.json b/fifa17-recon/data/consumables.json new file mode 100644 index 0000000..35dd8d2 --- /dev/null +++ b/fifa17-recon/data/consumables.json @@ -0,0 +1,4438 @@ +{ + "generated_by": "tools/build_consumables.py", + "derived_from": [ + "FUN_1800d8330", + "FUN_18013f4d0", + "FUN_1801bfac0", + "FUN_1801aa230", + "FUN_180048780", + "data/tables/fcc_trainingcards.json", + "data/tables/fcc_healingcards.json", + "data/tables/fcc_contractcards.json" + ], + "record_offsets": { + "0x4c": "cardtype (FUN_1800d8330(cardsubtypeid))", + "0x50": "cardsubtypeid (atom 0x6c). default 342 -> cardtype 0", + "0x54": "level: 1 if rating<65, 2 if <75, else 3 (shared tail of FUN_180141660)", + "0x58": "rareflag (atom 0x271, u32). THE TRAP: ==1 flips subtype 219 to squad fitness", + "0x18": "resourceId (atom 0x287) -- overwritten by FUN_18013f4d0 param_2", + "0x88": "playStyle (atom 0x23f, mapped 250..273 -> 0..23)", + "0x8c": "contract (atom 0xb8) -- the contract card's games count", + "0xb4": "rating (atom 0x274)", + "0xb8": "consumable CATEGORY (written by FUN_18013f4d0)", + "0xbc": "int16 sub-selector: attribute / injury area / formationid / from-position / playstyle index / leagueid", + "0xbe": "int8 playstyle artwork variant = (byte)amount", + "0xbf": "int8 amount, or to-position for position mods", + "0xc0": "bool single-target" + }, + "club_type_values_for_consumables": { + "contract": "FUN_18012ec50 arm 24 -> atom 0xb8", + "training": "arm 25 -> atom 0x337", + "healing": "arm 23 -> atom 0x156", + "development": "arm 6 -> atom 0xd3 (best candidate for position/formation/playStyle/managerLeague)", + "STATUS": "ALL FOUR UNOBSERVED ON THE WIRE. Only type=player, type=manager and type=custom have ever been seen from this client." + }, + "subtypes": [ + { + "cardsubtypeid": 51, + "kind": "gk_training", + "category": 0, + "bc": 0, + "bf": "amount", + "c0": 1, + "detail": "FUT_UC_DIVING", + "loc_name": "FUT_CONSUMABLE_NAME_KEEPERTRAINING", + "loc_desc": "FUT_CONSUMABLE_KEEPERTRAINING", + "artwork": "5000001_0", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003001, + "amount": 5, + "rating": 55, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003002, + "amount": 10, + "rating": 65, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003003, + "amount": 15, + "rating": 85, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 52, + "kind": "gk_training", + "category": 0, + "bc": 1, + "bf": "amount", + "c0": 1, + "detail": "FUT_UC_HANDLING", + "loc_name": "FUT_CONSUMABLE_NAME_KEEPERTRAINING", + "loc_desc": "FUT_CONSUMABLE_KEEPERTRAINING", + "artwork": "5000001_1", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003004, + "amount": 5, + "rating": 55, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003005, + "amount": 10, + "rating": 65, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003006, + "amount": 15, + "rating": 85, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 53, + "kind": "gk_training", + "category": 0, + "bc": 2, + "bf": "amount", + "c0": 1, + "detail": "FUT_UC_KICKING", + "loc_name": "FUT_CONSUMABLE_NAME_KEEPERTRAINING", + "loc_desc": "FUT_CONSUMABLE_KEEPERTRAINING", + "artwork": "5000001_2", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003007, + "amount": 5, + "rating": 55, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003008, + "amount": 10, + "rating": 65, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003009, + "amount": 15, + "rating": 85, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 54, + "kind": "gk_training", + "category": 0, + "bc": 4, + "bf": "amount", + "c0": 1, + "detail": "FUT_UC_SPEED", + "loc_name": "FUT_CONSUMABLE_NAME_KEEPERTRAINING", + "loc_desc": "FUT_CONSUMABLE_KEEPERTRAINING", + "artwork": "5000001_4", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003010, + "amount": 5, + "rating": 55, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003011, + "amount": 10, + "rating": 65, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003012, + "amount": 15, + "rating": 85, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 55, + "kind": "gk_training", + "category": 0, + "bc": 5, + "bf": "amount", + "c0": 1, + "detail": "FUT_UC_POSITIONING", + "loc_name": "FUT_CONSUMABLE_NAME_KEEPERTRAINING", + "loc_desc": "FUT_CONSUMABLE_KEEPERTRAINING", + "artwork": "5000001_5", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003013, + "amount": 5, + "rating": 55, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003014, + "amount": 10, + "rating": 65, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003015, + "amount": 15, + "rating": 85, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 56, + "kind": "gk_training", + "category": 0, + "bc": 3, + "bf": "amount", + "c0": 1, + "detail": "FUT_UC_REFLEXES", + "loc_name": "FUT_CONSUMABLE_NAME_KEEPERTRAINING", + "loc_desc": "FUT_CONSUMABLE_KEEPERTRAINING", + "artwork": "5000001_3", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003016, + "amount": 5, + "rating": 55, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003017, + "amount": 10, + "rating": 65, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003018, + "amount": 15, + "rating": 85, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 57, + "kind": "gk_training", + "category": 0, + "bc": 6, + "bf": "amount", + "c0": 0, + "detail": "FUT_FITNESS_UC", + "loc_name": "FUT_CONSUMABLE_NAME_KEEPERTRAINING", + "loc_desc": "FUT_CONSUMABLE_KEEPERTRAINING", + "artwork": "5000001_6", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003019, + "amount": 3, + "rating": 64, + "weightrare": 2, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003020, + "amount": 6, + "rating": 74, + "weightrare": 2, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003021, + "amount": 10, + "rating": 95, + "weightrare": 2, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 58, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 59, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 60, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 61, + "kind": "player_training", + "category": 0, + "bc": 0, + "bf": "amount", + "c0": 1, + "detail": "FUT_MC_PACE", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERTRAINING", + "loc_desc": "FUT_CONSUMABLE_PLAYERTRAINING", + "artwork": "5000000_0", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003022, + "amount": 5, + "rating": 55, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003023, + "amount": 10, + "rating": 65, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003024, + "amount": 15, + "rating": 85, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 62, + "kind": "player_training", + "category": 0, + "bc": 1, + "bf": "amount", + "c0": 1, + "detail": "FUT_MC_SHOOTING", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERTRAINING", + "loc_desc": "FUT_CONSUMABLE_PLAYERTRAINING", + "artwork": "5000000_1", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003025, + "amount": 5, + "rating": 55, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003026, + "amount": 10, + "rating": 65, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003027, + "amount": 15, + "rating": 85, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 63, + "kind": "player_training", + "category": 0, + "bc": 2, + "bf": "amount", + "c0": 1, + "detail": "FUT_MC_PASSING", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERTRAINING", + "loc_desc": "FUT_CONSUMABLE_PLAYERTRAINING", + "artwork": "5000000_2", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003028, + "amount": 5, + "rating": 55, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003029, + "amount": 10, + "rating": 65, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003030, + "amount": 15, + "rating": 85, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 64, + "kind": "player_training", + "category": 0, + "bc": 3, + "bf": "amount", + "c0": 1, + "detail": "FUT_MC_DRIBBLING", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERTRAINING", + "loc_desc": "FUT_CONSUMABLE_PLAYERTRAINING", + "artwork": "5000000_3", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003031, + "amount": 5, + "rating": 55, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003032, + "amount": 10, + "rating": 65, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003033, + "amount": 15, + "rating": 85, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 65, + "kind": "player_training", + "category": 0, + "bc": 5, + "bf": "amount", + "c0": 1, + "detail": "FUT_MC_HEADING", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERTRAINING", + "loc_desc": "FUT_CONSUMABLE_PLAYERTRAINING", + "artwork": "5000000_5", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003034, + "amount": 5, + "rating": 55, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003035, + "amount": 10, + "rating": 65, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003036, + "amount": 15, + "rating": 85, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 66, + "kind": "player_training", + "category": 0, + "bc": 4, + "bf": "amount", + "c0": 1, + "detail": "FUT_MC_DEFENDING", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERTRAINING", + "loc_desc": "FUT_CONSUMABLE_PLAYERTRAINING", + "artwork": "5000000_4", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003037, + "amount": 5, + "rating": 55, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003038, + "amount": 10, + "rating": 65, + "weightrare": 0, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003039, + "amount": 15, + "rating": 85, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 67, + "kind": "player_training", + "category": 0, + "bc": 6, + "bf": "amount", + "c0": 0, + "detail": "FUT_FITNESS_MC", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERTRAINING", + "loc_desc": "FUT_CONSUMABLE_PLAYERTRAINING", + "artwork": "5000000_6", + "needs": [ + "amount" + ], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [ + { + "carddbid": 5003040, + "amount": 3, + "rating": 64, + "weightrare": 2, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003041, + "amount": 6, + "rating": 74, + "weightrare": 2, + "table": "fcc_trainingcards" + }, + { + "carddbid": 5003042, + "amount": 10, + "rating": 95, + "weightrare": 2, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 68, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 69, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 70, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 71, + "kind": "manager_formation_mod", + "category": 6, + "bc": 23, + "bf": 0, + "c0": null, + "detail": "formationid=23", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 72, + "kind": "manager_formation_mod", + "category": 6, + "bc": 24, + "bf": 0, + "c0": null, + "detail": "formationid=24", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 73, + "kind": "manager_formation_mod", + "category": 6, + "bc": 25, + "bf": 0, + "c0": null, + "detail": "formationid=25", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 74, + "kind": "manager_formation_mod", + "category": 6, + "bc": 27, + "bf": 0, + "c0": null, + "detail": "formationid=27", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 75, + "kind": "manager_formation_mod", + "category": 6, + "bc": 14, + "bf": 0, + "c0": null, + "detail": "formationid=14", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 76, + "kind": "manager_formation_mod", + "category": 6, + "bc": 3, + "bf": 0, + "c0": null, + "detail": "formationid=3", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 77, + "kind": "manager_formation_mod", + "category": 6, + "bc": 13, + "bf": 0, + "c0": null, + "detail": "formationid=13", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 78, + "kind": "manager_formation_mod", + "category": 6, + "bc": 6, + "bf": 0, + "c0": null, + "detail": "formationid=6", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 79, + "kind": "manager_formation_mod", + "category": 6, + "bc": 7, + "bf": 0, + "c0": null, + "detail": "formationid=7", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 80, + "kind": "manager_formation_mod", + "category": 6, + "bc": 8, + "bf": 0, + "c0": null, + "detail": "formationid=8", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 81, + "kind": "manager_formation_mod", + "category": 6, + "bc": 19, + "bf": 0, + "c0": null, + "detail": "formationid=19", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 82, + "kind": "manager_formation_mod", + "category": 6, + "bc": 16, + "bf": 0, + "c0": null, + "detail": "formationid=16", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 83, + "kind": "manager_formation_mod", + "category": 6, + "bc": 21, + "bf": 0, + "c0": null, + "detail": "formationid=21", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 84, + "kind": "manager_formation_mod", + "category": 6, + "bc": 29, + "bf": 0, + "c0": null, + "detail": "formationid=29", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 85, + "kind": "manager_formation_mod", + "category": 6, + "bc": 30, + "bf": 0, + "c0": null, + "detail": "formationid=30", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 86, + "kind": "manager_formation_mod", + "category": 6, + "bc": 31, + "bf": 0, + "c0": null, + "detail": "formationid=31", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 15, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 87, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 88, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 89, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 90, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 91, + "kind": "position_mod", + "category": 8, + "bc": 8, + "bf": 7, + "c0": null, + "detail": "LWB >> LB", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003059, + "amount": 0, + "rating": 95, + "weightrare": 10, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 92, + "kind": "position_mod", + "category": 8, + "bc": 7, + "bf": 8, + "c0": null, + "detail": "LB >> LWB", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003060, + "amount": 0, + "rating": 90, + "weightrare": 20, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 93, + "kind": "position_mod", + "category": 8, + "bc": 2, + "bf": 3, + "c0": null, + "detail": "RWB >> RB", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003061, + "amount": 0, + "rating": 95, + "weightrare": 10, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 94, + "kind": "position_mod", + "category": 8, + "bc": 3, + "bf": 2, + "c0": null, + "detail": "RB >> RWB", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003062, + "amount": 0, + "rating": 90, + "weightrare": 20, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 95, + "kind": "position_mod", + "category": 8, + "bc": 16, + "bf": 27, + "c0": null, + "detail": "LM >> LW", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003063, + "amount": 0, + "rating": 95, + "weightrare": 20, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 96, + "kind": "position_mod", + "category": 8, + "bc": 12, + "bf": 23, + "c0": null, + "detail": "RM >> RW", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003064, + "amount": 0, + "rating": 95, + "weightrare": 20, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 97, + "kind": "position_mod", + "category": 8, + "bc": 27, + "bf": 16, + "c0": null, + "detail": "LW >> LM", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003065, + "amount": 0, + "rating": 95, + "weightrare": 20, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 98, + "kind": "position_mod", + "category": 8, + "bc": 23, + "bf": 12, + "c0": null, + "detail": "RW >> RM", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003066, + "amount": 0, + "rating": 95, + "weightrare": 20, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 99, + "kind": "position_mod", + "category": 8, + "bc": 27, + "bf": 22, + "c0": null, + "detail": "LW >> LF", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003067, + "amount": 0, + "rating": 90, + "weightrare": 10, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 100, + "kind": "position_mod", + "category": 8, + "bc": 23, + "bf": 20, + "c0": null, + "detail": "RW >> RF", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003068, + "amount": 0, + "rating": 95, + "weightrare": 10, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 101, + "kind": "position_mod", + "category": 8, + "bc": 22, + "bf": 27, + "c0": null, + "detail": "LF >> LW", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003069, + "amount": 0, + "rating": 90, + "weightrare": 10, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 102, + "kind": "position_mod", + "category": 8, + "bc": 20, + "bf": 23, + "c0": null, + "detail": "RF >> RW", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003070, + "amount": 0, + "rating": 95, + "weightrare": 10, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 103, + "kind": "position_mod", + "category": 8, + "bc": 14, + "bf": 18, + "c0": null, + "detail": "CM >> CAM", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003071, + "amount": 0, + "rating": 90, + "weightrare": 20, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 104, + "kind": "position_mod", + "category": 8, + "bc": 18, + "bf": 14, + "c0": null, + "detail": "CAM >> CM", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003072, + "amount": 0, + "rating": 95, + "weightrare": 20, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 105, + "kind": "position_mod", + "category": 8, + "bc": 10, + "bf": 14, + "c0": null, + "detail": "CDM >> CM", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003073, + "amount": 0, + "rating": 95, + "weightrare": 20, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 106, + "kind": "position_mod", + "category": 8, + "bc": 14, + "bf": 10, + "c0": null, + "detail": "CM >> CDM", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003074, + "amount": 0, + "rating": 90, + "weightrare": 20, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 107, + "kind": "position_mod", + "category": 8, + "bc": 18, + "bf": 21, + "c0": null, + "detail": "CAM >> CF", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003075, + "amount": 0, + "rating": 95, + "weightrare": 10, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 108, + "kind": "position_mod", + "category": 8, + "bc": 21, + "bf": 18, + "c0": null, + "detail": "CF >> CAM", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003076, + "amount": 0, + "rating": 95, + "weightrare": 10, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 109, + "kind": "position_mod", + "category": 8, + "bc": 21, + "bf": 25, + "c0": null, + "detail": "CF >> ST", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003077, + "amount": 0, + "rating": 95, + "weightrare": 20, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 110, + "kind": "position_mod", + "category": 8, + "bc": 25, + "bf": 21, + "c0": null, + "detail": "ST >> CF", + "artwork": "5000013", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_POSITIONMOD", + "loc_desc": "FUT_CONSUMABLE_POSITIONMOD", + "myclub_category": 17, + "ui_bucket": "position", + "ea_variants": [ + { + "carddbid": 5003078, + "amount": 0, + "rating": 95, + "weightrare": 20, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 111, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 112, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 113, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 114, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 115, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 116, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 117, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 118, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 119, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 120, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 121, + "kind": "formation_mod", + "category": 7, + "bc": 23, + "bf": 0, + "c0": null, + "detail": "formationid=23", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003079, + "amount": 0, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 122, + "kind": "formation_mod", + "category": 7, + "bc": 24, + "bf": 0, + "c0": null, + "detail": "formationid=24", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003080, + "amount": 0, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 123, + "kind": "formation_mod", + "category": 7, + "bc": 25, + "bf": 0, + "c0": null, + "detail": "formationid=25", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003081, + "amount": 0, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 124, + "kind": "formation_mod", + "category": 7, + "bc": 27, + "bf": 0, + "c0": null, + "detail": "formationid=27", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003082, + "amount": 0, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 125, + "kind": "formation_mod", + "category": 7, + "bc": 14, + "bf": 0, + "c0": null, + "detail": "formationid=14", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003083, + "amount": 0, + "rating": 99, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 126, + "kind": "formation_mod", + "category": 7, + "bc": 3, + "bf": 0, + "c0": null, + "detail": "formationid=3", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003084, + "amount": 0, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 127, + "kind": "formation_mod", + "category": 7, + "bc": 13, + "bf": 0, + "c0": null, + "detail": "formationid=13", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003085, + "amount": 0, + "rating": 99, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 128, + "kind": "formation_mod", + "category": 7, + "bc": 6, + "bf": 0, + "c0": null, + "detail": "formationid=6", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003086, + "amount": 0, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 129, + "kind": "formation_mod", + "category": 7, + "bc": 7, + "bf": 0, + "c0": null, + "detail": "formationid=7", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003087, + "amount": 0, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 130, + "kind": "formation_mod", + "category": 7, + "bc": 8, + "bf": 0, + "c0": null, + "detail": "formationid=8", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003088, + "amount": 0, + "rating": 99, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 131, + "kind": "formation_mod", + "category": 7, + "bc": 19, + "bf": 0, + "c0": null, + "detail": "formationid=19", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003089, + "amount": 0, + "rating": 99, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 132, + "kind": "formation_mod", + "category": 7, + "bc": 16, + "bf": 0, + "c0": null, + "detail": "formationid=16", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003090, + "amount": 0, + "rating": 99, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 133, + "kind": "formation_mod", + "category": 7, + "bc": 21, + "bf": 0, + "c0": null, + "detail": "formationid=21", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003091, + "amount": 0, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 134, + "kind": "formation_mod", + "category": 7, + "bc": 29, + "bf": 0, + "c0": null, + "detail": "formationid=29", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003092, + "amount": 0, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 135, + "kind": "formation_mod", + "category": 7, + "bc": 30, + "bf": 0, + "c0": null, + "detail": "formationid=30", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003093, + "amount": 0, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 136, + "kind": "formation_mod", + "category": 7, + "bc": 31, + "bf": 0, + "c0": null, + "detail": "formationid=31", + "artwork": "-1", + "needs": [], + "loc_name": "FUT_CONSUMABLE_NAME_FORMATIONMOD", + "loc_desc": "FUT_CONSUMABLE_FORMATIONMOD", + "myclub_category": 16, + "ui_bucket": "formation", + "ea_variants": [ + { + "carddbid": 5003094, + "amount": 0, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 201, + "kind": "player_contract", + "category": 2, + "bc": null, + "bf": null, + "c0": null, + "detail": "games from atom `contract` (0xb8) -> record+0x8c, unit fcc_matches", + "artwork": "5000007", + "needs": [ + "contract" + ], + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERCONTRACT", + "loc_desc": "FUT_CONSUMABLE_PLAYERCONTRACT", + "myclub_category": 1, + "ui_bucket": "contracts", + "ea_variants": [ + { + "carddbid": 5001001, + "rating": 50, + "weightrare": 0, + "table": "fcc_contractcards", + "gold": 1, + "silver": 2, + "bronze": 8 + }, + { + "carddbid": 5001002, + "rating": 65, + "weightrare": 0, + "table": "fcc_contractcards", + "gold": 8, + "silver": 10, + "bronze": 10 + }, + { + "carddbid": 5001003, + "rating": 80, + "weightrare": 0, + "table": "fcc_contractcards", + "gold": 13, + "silver": 11, + "bronze": 15 + }, + { + "carddbid": 5001004, + "rating": 60, + "weightrare": 100, + "table": "fcc_contractcards", + "gold": 3, + "silver": 6, + "bronze": 15 + }, + { + "carddbid": 5001005, + "rating": 70, + "weightrare": 100, + "table": "fcc_contractcards", + "gold": 18, + "silver": 24, + "bronze": 20 + }, + { + "carddbid": 5001006, + "rating": 90, + "weightrare": 100, + "table": "fcc_contractcards", + "gold": 28, + "silver": 24, + "bronze": 28 + }, + { + "carddbid": 5001013, + "rating": 90, + "weightrare": 0, + "table": "fcc_contractcards", + "gold": 99, + "silver": 99, + "bronze": 99 + } + ] + }, + { + "cardsubtypeid": 202, + "kind": "manager_contract", + "category": 3, + "bc": null, + "bf": null, + "c0": null, + "detail": "games from atom `contract` (0xb8) -> record+0x8c, unit fcc_matches", + "artwork": "5000008", + "needs": [ + "contract" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERCONTRACT", + "loc_desc": "FUT_CONSUMABLE_MANAGERCONTRACT", + "myclub_category": 2, + "ui_bucket": "contracts", + "ea_variants": [ + { + "carddbid": 5001007, + "rating": 50, + "weightrare": 0, + "table": "fcc_contractcards", + "gold": 1, + "silver": 2, + "bronze": 8 + }, + { + "carddbid": 5001008, + "rating": 65, + "weightrare": 0, + "table": "fcc_contractcards", + "gold": 8, + "silver": 10, + "bronze": 8 + }, + { + "carddbid": 5001009, + "rating": 80, + "weightrare": 0, + "table": "fcc_contractcards", + "gold": 13, + "silver": 11, + "bronze": 11 + }, + { + "carddbid": 5001010, + "rating": 60, + "weightrare": 10, + "table": "fcc_contractcards", + "gold": 3, + "silver": 6, + "bronze": 15 + }, + { + "carddbid": 5001011, + "rating": 70, + "weightrare": 10, + "table": "fcc_contractcards", + "gold": 18, + "silver": 24, + "bronze": 18 + }, + { + "carddbid": 5001012, + "rating": 90, + "weightrare": 10, + "table": "fcc_contractcards", + "gold": 28, + "silver": 24, + "bronze": 24 + } + ] + }, + { + "cardsubtypeid": 203, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 204, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 205, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 206, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 207, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 208, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 209, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 210, + "kind": "DEAD_ZONE", + "category": 0, + "bc": 0, + "bf": 0, + "c0": null, + "detail": "falls through to the bottom default of FUN_18013f4d0; renders as SQUAD TRAINING / attribute index 0, amount 0. NOT a loud error -- do not ship these.", + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "artwork": "5000000_0", + "needs": [], + "myclub_category": 0, + "ui_bucket": "training", + "ea_variants": [] + }, + { + "cardsubtypeid": 211, + "kind": "healing", + "category": 4, + "bc": 0, + "bf": "amount", + "c0": 1, + "detail": "Injury_Head", + "loc_detail": "FUT_HEAD_HEALING", + "artwork": "5000009_0", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERHEALING", + "loc_desc": "FUT_CONSUMABLE_PLAYERHEALING", + "myclub_category": 3, + "ui_bucket": "healing", + "ea_variants": [ + { + "carddbid": 5002007, + "amount": 1, + "rating": 55, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002008, + "amount": 2, + "rating": 70, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002009, + "amount": 5, + "rating": 80, + "weightrare": 0, + "table": "fcc_healingcards" + } + ] + }, + { + "cardsubtypeid": 212, + "kind": "healing", + "category": 4, + "bc": 1, + "bf": "amount", + "c0": 1, + "detail": "Injury_UpperBody", + "loc_detail": "FUT_UPPERBODY_HEALING", + "artwork": "5000009_1", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERHEALING", + "loc_desc": "FUT_CONSUMABLE_PLAYERHEALING", + "myclub_category": 3, + "ui_bucket": "healing", + "ea_variants": [ + { + "carddbid": 5002010, + "amount": 1, + "rating": 55, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002011, + "amount": 2, + "rating": 70, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002012, + "amount": 5, + "rating": 80, + "weightrare": 0, + "table": "fcc_healingcards" + } + ] + }, + { + "cardsubtypeid": 213, + "kind": "healing", + "category": 4, + "bc": 2, + "bf": "amount", + "c0": 1, + "detail": "Injury_Arm", + "loc_detail": "FUT_ARM_HEALING", + "artwork": "5000009_2", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERHEALING", + "loc_desc": "FUT_CONSUMABLE_PLAYERHEALING", + "myclub_category": 3, + "ui_bucket": "healing", + "ea_variants": [ + { + "carddbid": 5002013, + "amount": 1, + "rating": 55, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002014, + "amount": 2, + "rating": 70, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002015, + "amount": 5, + "rating": 80, + "weightrare": 0, + "table": "fcc_healingcards" + } + ] + }, + { + "cardsubtypeid": 214, + "kind": "healing", + "category": 4, + "bc": 3, + "bf": "amount", + "c0": 1, + "detail": "Injury_Back", + "loc_detail": "FUT_BACK_HEALING", + "artwork": "5000009_3", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERHEALING", + "loc_desc": "FUT_CONSUMABLE_PLAYERHEALING", + "myclub_category": 3, + "ui_bucket": "healing", + "ea_variants": [] + }, + { + "cardsubtypeid": 215, + "kind": "healing", + "category": 4, + "bc": 4, + "bf": "amount", + "c0": 1, + "detail": "Injury_Knee", + "loc_detail": "FUT_KNEE_HEALING", + "artwork": "5000009_4", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERHEALING", + "loc_desc": "FUT_CONSUMABLE_PLAYERHEALING", + "myclub_category": 3, + "ui_bucket": "healing", + "ea_variants": [ + { + "carddbid": 5002019, + "amount": 1, + "rating": 55, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002020, + "amount": 2, + "rating": 70, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002021, + "amount": 5, + "rating": 80, + "weightrare": 0, + "table": "fcc_healingcards" + } + ] + }, + { + "cardsubtypeid": 216, + "kind": "healing", + "category": 4, + "bc": 5, + "bf": "amount", + "c0": 1, + "detail": "Injury_Leg", + "loc_detail": "FUT_LEG_HEALING", + "artwork": "5000009_5", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERHEALING", + "loc_desc": "FUT_CONSUMABLE_PLAYERHEALING", + "myclub_category": 3, + "ui_bucket": "healing", + "ea_variants": [ + { + "carddbid": 5002022, + "amount": 1, + "rating": 55, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002023, + "amount": 2, + "rating": 70, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002024, + "amount": 5, + "rating": 80, + "weightrare": 0, + "table": "fcc_healingcards" + } + ] + }, + { + "cardsubtypeid": 217, + "kind": "healing", + "category": 4, + "bc": 6, + "bf": "amount", + "c0": 1, + "detail": "Injury_Foot", + "loc_detail": "FUT_FOOT_HEALING", + "artwork": "5000009_6", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERHEALING", + "loc_desc": "FUT_CONSUMABLE_PLAYERHEALING", + "myclub_category": 3, + "ui_bucket": "healing", + "ea_variants": [ + { + "carddbid": 5002025, + "amount": 1, + "rating": 55, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002026, + "amount": 2, + "rating": 70, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002027, + "amount": 5, + "rating": 80, + "weightrare": 0, + "table": "fcc_healingcards" + } + ] + }, + { + "cardsubtypeid": 218, + "kind": "healing", + "category": 4, + "bc": 7, + "bf": "amount", + "c0": 0, + "detail": "Injury_All", + "loc_detail": "FUT_PLAYER_HEALING", + "artwork": "5000009_7", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERHEALING", + "loc_desc": "FUT_CONSUMABLE_PLAYERHEALING", + "myclub_category": 3, + "ui_bucket": "healing", + "ea_variants": [ + { + "carddbid": 5002028, + "amount": 1, + "rating": 60, + "weightrare": 20, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002029, + "amount": 2, + "rating": 74, + "weightrare": 20, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002030, + "amount": 4, + "rating": 85, + "weightrare": 20, + "table": "fcc_healingcards" + } + ] + }, + { + "cardsubtypeid": 219, + "kind": "player_fitness", + "category": 5, + "bc": 0, + "bf": "amount", + "c0": 1, + "detail": "RAREFLAG TRAP: rareflag==1 renders 219 as SQUAD fitness", + "artwork": "5000010", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERFITNESS", + "loc_desc": "FUT_CONSUMABLE_PLAYERFITNESS", + "myclub_category": 4, + "ui_bucket": "fitness", + "ea_variants": [ + { + "carddbid": 5002001, + "amount": 20, + "rating": 55, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002002, + "amount": 40, + "rating": 70, + "weightrare": 0, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002003, + "amount": 60, + "rating": 80, + "weightrare": 0, + "table": "fcc_healingcards" + } + ] + }, + { + "cardsubtypeid": 220, + "kind": "squad_fitness", + "category": 5, + "bc": 0, + "bf": "amount", + "c0": 0, + "detail": "always squad fitness", + "artwork": "5000011", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_SQUADTRAINING", + "loc_desc": "FUT_CONSUMABLE_SQUADTRAINING", + "myclub_category": 4, + "ui_bucket": "fitness", + "ea_variants": [ + { + "carddbid": 5002004, + "amount": 10, + "rating": 55, + "weightrare": 70, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002005, + "amount": 20, + "rating": 70, + "weightrare": 70, + "table": "fcc_healingcards" + }, + { + "carddbid": 5002006, + "amount": 30, + "rating": 80, + "weightrare": 70, + "table": "fcc_healingcards" + } + ] + }, + { + "cardsubtypeid": 250, + "kind": "player_playstyle", + "category": 9, + "bc": 0, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_0", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003095, + "amount": 0, + "rating": 75, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 251, + "kind": "player_playstyle", + "category": 9, + "bc": 1, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_1", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003096, + "amount": 1, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 252, + "kind": "player_playstyle", + "category": 9, + "bc": 2, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_2", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003097, + "amount": 1, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 253, + "kind": "player_playstyle", + "category": 9, + "bc": 3, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_3", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003098, + "amount": 1, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 254, + "kind": "player_playstyle", + "category": 9, + "bc": 4, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_4", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003099, + "amount": 1, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 255, + "kind": "player_playstyle", + "category": 9, + "bc": 5, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_5", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003100, + "amount": 1, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 256, + "kind": "player_playstyle", + "category": 9, + "bc": 6, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_6", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003101, + "amount": 2, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 257, + "kind": "player_playstyle", + "category": 9, + "bc": 7, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_7", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003102, + "amount": 2, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 258, + "kind": "player_playstyle", + "category": 9, + "bc": 8, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_8", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003103, + "amount": 2, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 259, + "kind": "player_playstyle", + "category": 9, + "bc": 9, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_9", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003104, + "amount": 2, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 260, + "kind": "player_playstyle", + "category": 9, + "bc": 10, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_10", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003105, + "amount": 2, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 261, + "kind": "player_playstyle", + "category": 9, + "bc": 11, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_11", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003106, + "amount": 3, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 262, + "kind": "player_playstyle", + "category": 9, + "bc": 12, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_12", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003107, + "amount": 3, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 263, + "kind": "player_playstyle", + "category": 9, + "bc": 13, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_13", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003108, + "amount": 3, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 264, + "kind": "player_playstyle", + "category": 9, + "bc": 14, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_14", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003109, + "amount": 3, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 265, + "kind": "player_playstyle", + "category": 9, + "bc": 15, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_15", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003110, + "amount": 3, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 266, + "kind": "player_playstyle", + "category": 9, + "bc": 16, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_16", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003111, + "amount": 4, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 267, + "kind": "player_playstyle", + "category": 9, + "bc": 17, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_17", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003112, + "amount": 4, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 268, + "kind": "player_playstyle", + "category": 9, + "bc": 18, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_18", + "loc_name": "FUT_CONSUMABLE_NAME_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003113, + "amount": 4, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 269, + "kind": "gk_playstyle", + "category": 9, + "bc": 19, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_19", + "loc_name": "FUT_CONSUMABLE_NAME_GK_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003114, + "amount": 5, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 270, + "kind": "gk_playstyle", + "category": 9, + "bc": 20, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_20", + "loc_name": "FUT_CONSUMABLE_NAME_GK_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003115, + "amount": 5, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 271, + "kind": "gk_playstyle", + "category": 9, + "bc": 21, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_21", + "loc_name": "FUT_CONSUMABLE_NAME_GK_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003116, + "amount": 5, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 272, + "kind": "gk_playstyle", + "category": 9, + "bc": 22, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_22", + "loc_name": "FUT_CONSUMABLE_NAME_GK_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003117, + "amount": 5, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 273, + "kind": "gk_playstyle", + "category": 9, + "bc": 23, + "be": "amount", + "bf": null, + "c0": null, + "detail": "FUT_PLAYSTYLE_23", + "loc_name": "FUT_CONSUMABLE_NAME_GK_PLAYERSTYLE", + "artwork": "5000015_", + "needs": [ + "amount" + ], + "loc_desc": "FUT_CONSUMABLE_PLAYERSTYLE", + "myclub_category": 23, + "ui_bucket": "playStyle", + "ea_variants": [ + { + "carddbid": 5003118, + "amount": 5, + "rating": 75, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 300, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003119, + "amount": 1, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 301, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003120, + "amount": 4, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 302, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003121, + "amount": 7, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 303, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003122, + "amount": 10, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 304, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003123, + "amount": 13, + "rating": 95, + "weightrare": 15, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 305, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003124, + "amount": 14, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 306, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003125, + "amount": 16, + "rating": 95, + "weightrare": 15, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 307, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003126, + "amount": 17, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 308, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003127, + "amount": 19, + "rating": 95, + "weightrare": 15, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 309, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003128, + "amount": 20, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 310, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003129, + "amount": 31, + "rating": 95, + "weightrare": 15, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 311, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003130, + "amount": 32, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 312, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003131, + "amount": 39, + "rating": 95, + "weightrare": 15, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 313, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003132, + "amount": 41, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 314, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003133, + "amount": 50, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 315, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003134, + "amount": 53, + "rating": 95, + "weightrare": 15, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 316, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003135, + "amount": 54, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 317, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003136, + "amount": 56, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 318, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003137, + "amount": 60, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 319, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003138, + "amount": 61, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 320, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003139, + "amount": 63, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 321, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003140, + "amount": 65, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 322, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003141, + "amount": 66, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 323, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003142, + "amount": 67, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 324, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003143, + "amount": 68, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 325, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003144, + "amount": 80, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 326, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003145, + "amount": 83, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 327, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003146, + "amount": 189, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 328, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003147, + "amount": 308, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 329, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003148, + "amount": 332, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 330, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003149, + "amount": 335, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 331, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003150, + "amount": 336, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 332, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003151, + "amount": 341, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 333, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003152, + "amount": 347, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 334, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003153, + "amount": 350, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 335, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003154, + "amount": 351, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 336, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003155, + "amount": 353, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 337, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003156, + "amount": 2118, + "rating": 95, + "weightrare": 1, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 338, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003157, + "amount": 322, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 339, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003158, + "amount": 349, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 340, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [ + { + "carddbid": 5003159, + "amount": 2025, + "rating": 95, + "weightrare": 0, + "table": "fcc_trainingcards" + } + ] + }, + { + "cardsubtypeid": 341, + "kind": "manager_league", + "category": 10, + "bc": "clamp_i16(amount)", + "bf": null, + "c0": null, + "detail": "ML: ", + "artwork": "5000016", + "needs": [ + "amount" + ], + "loc_name": "FUT_CONSUMABLE_NAME_MANAGERLEAGUE", + "loc_desc": "FUT_CONSUMABLE_MANAGERLEAGUE", + "myclub_category": 24, + "ui_bucket": "managerLeagueModifier", + "ea_variants": [] + } + ] +} \ No newline at end of file diff --git a/fifa17-recon/tools/build_consumables.py b/fifa17-recon/tools/build_consumables.py new file mode 100644 index 0000000..ca30a1d --- /dev/null +++ b/fifa17-recon/tools/build_consumables.py @@ -0,0 +1,245 @@ +#!/usr/bin/env python3 +"""Generate data/consumables.json -- the complete FIFA 17 consumable (cardtype 6) +enum, derived from the binary and cross-checked against the client's own tables. + +SOURCES, all verified 2026-08-05 (slug `consumables`): + * FUN_1800d8330 (714 chars, full) cardsubtypeid -> cardtype + * FUN_18013f4d0 (8354 chars, full) cardsubtypeid -> category(+0xb8), +0xbc, +0xbe, + +0xbf, +0xc0. Two callees only: + FUN_180136480 (playstyle index) and + FUN_1800d7ad0 (int16 clamp). No DB handle. + * FUN_1801bfac0 (42813 chars, full) category -> FUT_CONSUMABLE_* loc keys + the + fixed 5000xxx artwork ids. + * FUN_1801aa230 (6, category) -> fcc_myclubscategories id + * FUN_180048780 (3455 chars, full) that id -> the UI bucket name + * data/tables/fcc_trainingcards.json (143 rows) and fcc_healingcards.json (27), + fcc_contractcards.json (13): EA's own authored amount/rating per subtype. + +NOTHING here needs the live game. Run it any time; it only reads files. +""" +import json, os, collections + +HERE = os.path.dirname(os.path.abspath(__file__)) +TABLES = os.path.join(HERE, "..", "data", "tables") +OUT = os.path.join(HERE, "..", "data", "consumables.json") + +POS = ["GK","SW","RWB","RB","RCB","CB","LCB","LB","LWB","RDM","CDM","LDM","RM","RCM", + "CM","LCM","LM","RAM","CAM","LAM","RF","CF","LF","RW","RS","ST","LS","LW"] + +# FUN_18013f4d0, arm by arm. value = (category, bc, bf, c0_is_single) +# bf/bc of None means "taken from the `amount` atom at parse time". +GK_ATTR = ["FUT_UC_DIVING","FUT_UC_HANDLING","FUT_UC_KICKING","FUT_UC_REFLEXES", + "FUT_UC_SPEED","FUT_UC_POSITIONING","FUT_FITNESS_UC"] +PL_ATTR = ["FUT_MC_PACE","FUT_MC_SHOOTING","FUT_MC_PASSING","FUT_MC_DRIBBLING", + "FUT_MC_DEFENDING","FUT_MC_HEADING","FUT_FITNESS_MC"] +HEAL_AREA = ["Injury_Head","Injury_UpperBody","Injury_Arm","Injury_Back","Injury_Knee", + "Injury_Leg","Injury_Foot","Injury_All"] +HEAL_LOC = ["FUT_HEAD_HEALING","FUT_UPPERBODY_HEALING","FUT_ARM_HEALING", + "FUT_BACK_HEALING","FUT_KNEE_HEALING","FUT_LEG_HEALING", + "FUT_FOOT_HEALING","FUT_PLAYER_HEALING"] + +GK_TRAIN = {51:0, 52:1, 53:2, 54:4, 55:5, 56:3, 57:6} # 0x33..0x39 +PL_TRAIN = {61:0, 62:1, 63:2, 64:3, 65:5, 66:4, 67:6} # 0x3d..0x43 +FORMATION = [23,24,25,27,14,3,13,6,7,8,19,16,21,29,30,31] # identical in both arms +POSMOD = { # 0x5b..0x6e (bc=from, bf=to) + 91:(8,7), 92:(7,8), 93:(2,3), 94:(3,2), 95:(16,27), 96:(12,23), + 97:(27,16), 98:(23,12), 99:(27,22), 100:(23,20),101:(22,27),102:(20,23), + 103:(14,18),104:(18,14),105:(10,14),106:(14,10),107:(18,21),108:(21,18), + 109:(21,25),110:(25,21), +} + +CAT_LOC = { # category -> (name loc key, desc loc key, artwork base, myclub cat, ui bucket) + 0: ("FUT_CONSUMABLE_NAME_PLAYERTRAINING", "FUT_CONSUMABLE_PLAYERTRAINING", "5000000_", 0, "training"), + 2: ("FUT_CONSUMABLE_NAME_PLAYERCONTRACT", "FUT_CONSUMABLE_PLAYERCONTRACT", "5000007", 1, "contracts"), + 3: ("FUT_CONSUMABLE_NAME_MANAGERCONTRACT","FUT_CONSUMABLE_MANAGERCONTRACT","5000008", 2, "contracts"), + 4: ("FUT_CONSUMABLE_NAME_PLAYERHEALING", "FUT_CONSUMABLE_PLAYERHEALING", "5000009_", 3, "healing"), + 5: ("FUT_CONSUMABLE_NAME_PLAYERFITNESS", "FUT_CONSUMABLE_PLAYERFITNESS", "5000010", 4, "fitness"), + 6: ("FUT_CONSUMABLE_NAME_FORMATIONMOD", "FUT_CONSUMABLE_FORMATIONMOD", "-1", 15, "training"), + 7: ("FUT_CONSUMABLE_NAME_FORMATIONMOD", "FUT_CONSUMABLE_FORMATIONMOD", "-1", 16, "formation"), + 8: ("FUT_CONSUMABLE_NAME_POSITIONMOD", "FUT_CONSUMABLE_POSITIONMOD", "5000013", 17, "position"), + 9: ("FUT_CONSUMABLE_NAME_PLAYERSTYLE", "FUT_CONSUMABLE_PLAYERSTYLE", "5000015_", 23, "playStyle"), + 10: ("FUT_CONSUMABLE_NAME_MANAGERLEAGUE", "FUT_CONSUMABLE_MANAGERLEAGUE", "5000016", 24, "managerLeagueModifier"), +} + + +def cardtype(s): + """FUN_1800d8330, verbatim.""" + if 0 <= s <= 3: return 1 + if s == 4: return 2 + if s == 5: return 3 + if s == 6: return 10 + if s == 7: return 5 + if s == 8: return 4 + if s in (9, 10, 11): return 7 + if s in (30, 31, 145,146,147,148,149,150, 231,232,233, 236): return 9 + if 0 <= s - 0x33 <= 0x55: return 6 # 51..136 + if 0 <= s - 0xc9 <= 0x13: return 6 # 201..220 + if 0 <= s - 0xfa <= 0x17: return 6 # 250..273 + if 0 <= s - 300 < 0x2a: return 6 # 300..341 + return 0 + + +def rows(): + out = [] + for s in range(0, 400): + if cardtype(s) != 6: + continue + r = {"cardsubtypeid": s} + if s in GK_TRAIN: + i = GK_TRAIN[s] + r.update(kind="gk_training", category=0, bc=i, bf="amount", + c0=int(s != 57), detail=GK_ATTR[i], + loc_name="FUT_CONSUMABLE_NAME_KEEPERTRAINING", + loc_desc="FUT_CONSUMABLE_KEEPERTRAINING", + artwork="5000001_%d" % i, needs=["amount"]) + elif s in PL_TRAIN: + i = PL_TRAIN[s] + r.update(kind="player_training", category=0, bc=i, bf="amount", + c0=int(s != 67), detail=PL_ATTR[i], + loc_name="FUT_CONSUMABLE_NAME_PLAYERTRAINING", + loc_desc="FUT_CONSUMABLE_PLAYERTRAINING", + artwork="5000000_%d" % i, needs=["amount"]) + elif 71 <= s <= 86: + f = FORMATION[s - 71] + r.update(kind="manager_formation_mod", category=6, bc=f, bf=0, c0=None, + detail="formationid=%d" % f, artwork="-1", needs=[]) + elif s in POSMOD: + a, b = POSMOD[s] + r.update(kind="position_mod", category=8, bc=a, bf=b, c0=None, + detail="%s >> %s" % (POS[a], POS[b]), + artwork="5000013", needs=[]) + elif 121 <= s <= 136: + f = FORMATION[s - 121] + r.update(kind="formation_mod", category=7, bc=f, bf=0, c0=None, + detail="formationid=%d" % f, artwork="-1", needs=[]) + elif s == 201: + r.update(kind="player_contract", category=2, bc=None, bf=None, c0=None, + detail="games from atom `contract` (0xb8) -> record+0x8c, unit fcc_matches", + artwork="5000007", needs=["contract"]) + elif s == 202: + r.update(kind="manager_contract", category=3, bc=None, bf=None, c0=None, + detail="games from atom `contract` (0xb8) -> record+0x8c, unit fcc_matches", + artwork="5000008", needs=["contract"]) + elif 211 <= s <= 218: + i = s - 211 + r.update(kind="healing", category=4, bc=i, bf="amount", c0=int(s != 218), + detail=HEAL_AREA[i], loc_detail=HEAL_LOC[i], + artwork="5000009_%d" % i, needs=["amount"]) + elif s in (219, 220): + r.update(kind="player_fitness" if s == 219 else "squad_fitness", + category=5, bc=0, bf="amount", c0=int(s != 220), + detail="RAREFLAG TRAP: rareflag==1 renders 219 as SQUAD fitness" + if s == 219 else "always squad fitness", + artwork="5000010" if s == 219 else "5000011", needs=["amount"]) + if s == 220: + # 0xdc == 220 is the FIRST half of the squad-fitness test in + # FUN_1801bfac0 case 5, so 220 ALWAYS takes that branch -- and that + # branch writes FUT_CONSUMABLE_NAME_SQUADTRAINING. There is no + # FUT_CONSUMABLE_NAME_SQUADFITNESS string in the binary at all + # (24-string census); squad fitness reuses the squad-training name. + r.update(loc_name="FUT_CONSUMABLE_NAME_SQUADTRAINING", + loc_desc="FUT_CONSUMABLE_SQUADTRAINING") + elif 250 <= s <= 273: + i = s - 250 + r.update(kind="gk_playstyle" if s >= 269 else "player_playstyle", + category=9, bc=i, be="amount", bf=None, c0=None, + detail="FUT_PLAYSTYLE_%d" % i, + loc_name=("FUT_CONSUMABLE_NAME_GK_PLAYERSTYLE" if s >= 269 + else "FUT_CONSUMABLE_NAME_PLAYERSTYLE"), + artwork="5000015_", needs=["amount"]) + elif 300 <= s <= 341: + r.update(kind="manager_league", category=10, bc="clamp_i16(amount)", + bf=None, c0=None, detail="ML: ", + artwork="5000016", needs=["amount"]) + else: + # FUN_1801bfac0 case 0 tests `subtype - 0x33 < 7` (GK training) then + # `subtype - 0x3d < 7` (player training) and otherwise falls to the + # SQUAD-training branch. No dead-zone subtype satisfies either test, so + # the name is SQUADTRAINING, not PLAYERTRAINING (which is what CAT_LOC[0] + # would otherwise have stamped here). + r.update(kind="DEAD_ZONE", category=0, bc=0, bf=0, c0=None, + detail="falls through to the bottom default of FUN_18013f4d0; " + "renders as SQUAD TRAINING / attribute index 0, amount 0. " + "NOT a loud error -- do not ship these.", + loc_name="FUT_CONSUMABLE_NAME_SQUADTRAINING", + loc_desc="FUT_CONSUMABLE_SQUADTRAINING", + artwork="5000000_0", needs=[]) + c = r["category"] + if "loc_name" not in r: r["loc_name"] = CAT_LOC[c][0] + if "loc_desc" not in r: r["loc_desc"] = CAT_LOC[c][1] + r["myclub_category"] = CAT_LOC[c][3] + r["ui_bucket"] = CAT_LOC[c][4] + out.append(r) + return out + + +def merge_ea(): + """EA's authored (amount, rating) per subtype, straight out of the resident DB.""" + ea = collections.defaultdict(list) + for f in ("fcc_trainingcards", "fcc_healingcards"): + d = json.load(open(os.path.join(TABLES, f + ".json"))) + for row in d["rows"]: + ea[row["cardsubtype"]].append( + {"carddbid": row["carddbid"], "amount": row["amount"], + "rating": row["rating"], "weightrare": row["weightrare"], + "table": f}) + d = json.load(open(os.path.join(TABLES, "fcc_contractcards.json"))) + for row in d["rows"]: + ea[row["cardsubtype"]].append( + {"carddbid": row["carddbid"], "rating": row["rating"], + "weightrare": row["weightrare"], "table": "fcc_contractcards", + "gold": row["gold"], "silver": row["silver"], "bronze": row["bronze"]}) + return ea + + +def main(): + rs = rows() + ea = merge_ea() + for r in rs: + r["ea_variants"] = ea.get(r["cardsubtypeid"], []) + doc = { + "generated_by": "tools/build_consumables.py", + "derived_from": ["FUN_1800d8330", "FUN_18013f4d0", "FUN_1801bfac0", + "FUN_1801aa230", "FUN_180048780", + "data/tables/fcc_trainingcards.json", + "data/tables/fcc_healingcards.json", + "data/tables/fcc_contractcards.json"], + "record_offsets": { + "0x4c": "cardtype (FUN_1800d8330(cardsubtypeid))", + "0x50": "cardsubtypeid (atom 0x6c). default 342 -> cardtype 0", + "0x54": "level: 1 if rating<65, 2 if <75, else 3 (shared tail of FUN_180141660)", + "0x58": "rareflag (atom 0x271, u32). THE TRAP: ==1 flips subtype 219 to squad fitness", + "0x18": "resourceId (atom 0x287) -- overwritten by FUN_18013f4d0 param_2", + "0x88": "playStyle (atom 0x23f, mapped 250..273 -> 0..23)", + "0x8c": "contract (atom 0xb8) -- the contract card's games count", + "0xb4": "rating (atom 0x274)", + "0xb8": "consumable CATEGORY (written by FUN_18013f4d0)", + "0xbc": "int16 sub-selector: attribute / injury area / formationid / from-position / playstyle index / leagueid", + "0xbe": "int8 playstyle artwork variant = (byte)amount", + "0xbf": "int8 amount, or to-position for position mods", + "0xc0": "bool single-target", + }, + "club_type_values_for_consumables": { + "contract": "FUN_18012ec50 arm 24 -> atom 0xb8", + "training": "arm 25 -> atom 0x337", + "healing": "arm 23 -> atom 0x156", + "development": "arm 6 -> atom 0xd3 (best candidate for position/formation/playStyle/managerLeague)", + "STATUS": "ALL FOUR UNOBSERVED ON THE WIRE. Only type=player, type=manager and " + "type=custom have ever been seen from this client.", + }, + "subtypes": rs, + } + with open(OUT, "w") as f: + json.dump(doc, f, indent=1) + live = [r for r in rs if r["kind"] != "DEAD_ZONE"] + dead = [r for r in rs if r["kind"] == "DEAD_ZONE"] + print("cardtype-6 subtypes: %d (live %d, dead-zone %d)" % (len(rs), len(live), len(dead))) + print("dead zones:", sorted(r["cardsubtypeid"] for r in dead)) + print("with EA variants:", len([r for r in rs if r["ea_variants"]])) + print("live but NO EA variant:", + sorted(r["cardsubtypeid"] for r in live if not r["ea_variants"])) + print("wrote", os.path.normpath(OUT)) + + +if __name__ == "__main__": + main() diff --git a/fifa17-recon/tools/fut_consumables.py b/fifa17-recon/tools/fut_consumables.py new file mode 100644 index 0000000..726add8 --- /dev/null +++ b/fifa17-recon/tools/fut_consumables.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""Consumable cards (cardtype 6) for the FIFA 17 offline backend. + +THE CHEAPEST WHOLE FAMILY IN THE GAME: no id space has to be discovered, because a +consumable carries no identity at all. `FUN_18013f4d0` (8,354 chars, read to its +closing brace) has exactly two callees -- a range clamp and an enum map -- and never +touches a DB handle. Everything on the card comes from `cardsubtypeid` alone: + + cardsubtypeid --FUN_1800d8330--> cardtype 6 + --FUN_18013f4d0--> category -> record+0xb8 + sub-sel -> record+0xbc (i16) + amount -> record+0xbf (i8) [or +0xbe playstyle] + single -> record+0xc0 + +and `FUN_1801bfac0` then renders category + those bytes into a FUT_CONSUMABLE_* +string and a hardcoded 5000xxx artwork constant. resourceId NEVER reaches the screen +for a consumable, which is why we can pick ids freely -- we still use EA's own +`fcc_*` carddbids so nothing drifts out of their space. + +THE TWO THINGS WE MUST GET RIGHT +-------------------------------- +1. `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 into + record+0xbf -- and the accessors FUN_1801a8040/FUN_1801a8060 both do + `(int)*(char *)`, i.e. SIGNED, so the card reads "-1", not "255". Categories 2 and + 3 (the two contract cards) take their number from a DIFFERENT atom, `contract` + (0xb8) -> record+0x8c, and IGNORE `amount` entirely. +2. rareflag must be 0 on subtype 219. See fut_store._SQUAD_FITNESS_TRAP: rareflag 1 + silently converts a Player Fitness card into a Squad Fitness card. + +A WRONG SUBTYPE IS SILENT *AND LOOKS PLAUSIBLE*. There is no "DB Error" analogue +here: a dead-zone subtype falls to the bottom default of FUN_18013f4d0 (category 0, ++0xbc = 0, +0xbf = 0) and FUN_1801bfac0 then renders it as a perfectly ordinary Squad +Training (Pace) card with amount 0. That is why every subtype we ship comes out of +data/consumables.json and `consumable_item` REFUSES a dead zone rather than trusting +the caller. + +data/consumables.json is generated by tools/build_consumables.py from the three +decompiles above plus EA's own authored variants in fcc_trainingcards (143 rows), +fcc_healingcards (27) and fcc_contractcards (13). +""" +import json, os + +HERE = os.path.dirname(os.path.abspath(__file__)) +DATA = os.path.join(os.path.dirname(HERE), "data", "consumables.json") + +with open(DATA) as _f: + _DOC = json.load(_f) + +SUBTYPES = _DOC["subtypes"] +BY_SUBTYPE = {r["cardsubtypeid"]: r for r in SUBTYPES} + +# ?type= -> the consumable CATEGORIES that arm asks for. +# +# The vocabulary is certain: FUN_18012ec50's 29 arms resolve through the atom table +# to healing=23, contract=24, training=25, development=6 (and there is NO fitness, +# position, formation, playstyle or managerLeague arm). The category grouping below +# is INFERRED from FUN_180048780's UI-bucket names, because the tab-to-arm binding +# has NEVER been observed on the wire -- only type=player, type=manager and +# type=custom have ever come from this client. Hence the flag, and hence the log line +# in utas_server's club_route that prints every ?type= it is asked for. +TYPE_CATEGORIES = { + "contract": {2, 3}, # player contract, manager contract + "training": {0}, # GK training + player training + "healing": {4, 5}, # healing, and fitness has no arm of its own + "development": {6, 7, 8, 9, 10}, # formation, position, playstyle, mgr league +} + +# Families worth shipping: they have EA-authored variants and none needs a lookup the +# client cannot do from the subtype alone. +# +# THREE FAMILIES ARE DELIBERATELY EXCLUDED, each for a named reason: +# manager_formation_mod (71-86, category 6) vestigial AND a crash candidate: +# zero rows in the 143-row fcc_trainingcards (the carddbid run jumps 5003042 -> +# 5003059, exactly 16 ids), and FUN_1801bfac0 case 6 calls FUN_1801a0100 on the +# formations query result WITHOUT the `if (0 < rowcount)` guard its otherwise +# identical case 7 has. +# formation_mod (121-136, category 7) guarded, but its artwork constant is -1, so +# there is nothing to look at yet. Left for a later round. +# manager_league (300-341, category 10) FUN_1801bfac0 case 10 formats the label as +# literally "ML: %d" from record+0xbc -- a raw number, no league-name lookup -- +# and one shipped amount (2118, subtype 337) is in neither leagues.json nor +# fcc_leagues.json. +CORE_KINDS = ("player_contract", "manager_contract", "healing", + "player_fitness", "squad_fitness", "gk_training", "player_training", + "position_mod", "player_playstyle", "gk_playstyle") + +CONSUMABLE_ID_BASE = 940000000 # distinct from the save (1e8), the sweep (9e8) + # and the staff overlay (9.5e8) + + +def variants(subtype): + """EA's own authored (carddbid, amount, rating, weightrare) rows for a subtype.""" + return BY_SUBTYPE[subtype].get("ea_variants", []) + + +def consumable_item(item_id, subtype, amount=None, contract=None, rating=None, + resource_id=None, rareflag=0, untradeable=True): + """Build one consumable item. + + Eleven common keys plus at most one class key. Every one of the eleven is already + proven on the wire by the live player path, so this introduces NO new wire shape + -- which matters, because a scalar where the parser wants an object busy-loops the + client at 0x1801c7f1a. + + id -> rec+0x08 our handle + resourceId -> rec+0x18 written by FUN_18013f4d0 from its param_2; never + rendered for a consumable (artwork is a constant), so + this is bookkeeping only. Defaults to EA's carddbid. + assetId/cardassetid same value, for our own readers + cardsubtypeid -> rec+0x50 THE ONLY selector. Category, artwork, name and both + stat bytes all derive from it. + itemType "player": the ONLY value this client has ever been + sent. cardtype is derived from cardsubtypeid alone + (FUN_18013fe00 line 713), so the string cannot affect + the render. If the consumables tab comes back empty + this is the first thing to vary; the candidates from + the atom table are "training"/"contract"/"healing". + rareflag -> rec+0x58 0 by default. Read unconditionally into the card's + rare/backing art AND, in category 5 only, as the + squad-fitness selector -- see the 219 guard below. + rating -> rec+0xb4 drives level (rec+0x54: <65 bronze, <75 silver, else + gold) and therefore the fcc_discardcoins price. + itemState / owners / untradeable same meaning as on a player. + + amount -> rec+0xbf (or +0xbe for playstyle). MANDATORY where `needs` + says so: omitting it stamps -1, not 0. + contract -> rec+0x8c categories 2 and 3 only. + + DELIBERATELY ABSENT: preferredPosition, nation, teamid, leagueId, playStyle, + attributeList, fitness (all player-only), definitionId (not an atom at all -- the + parser has always been skipping it), and discardValue (the client computes it from + fcc_discardcoins on (cardtype 6, level, rare), and real rows exist for both rare + values, so omission is safe). + """ + r = BY_SUBTYPE.get(subtype) + if r is None: + raise ValueError("cardsubtypeid %r is not a cardtype-6 subtype" % (subtype,)) + if r["kind"] == "DEAD_ZONE": + raise ValueError( + "cardsubtypeid %d is a DEAD ZONE: it renders as a plausible Squad " + "Training (Pace) card with amount 0 and gives no hint anything is wrong" + % subtype) + needs = set(r.get("needs", ())) + if "amount" in needs and amount is None: + raise ValueError("cardsubtypeid %d needs `amount`; omitting it reads back as " + "-1 on screen, not 0" % subtype) + if "contract" in needs and contract is None: + raise ValueError("cardsubtypeid %d needs `contract` (atom 0xb8)" % subtype) + if subtype == 219 and rareflag: + # Same fact as fut_store._SQUAD_FITNESS_TRAP, enforced at the other end so a + # caller cannot reintroduce it by passing rareflag through. + raise ValueError("rareflag must be 0 on subtype 219: FUN_1801bfac0 case 5 " + "renders a rare Player Fitness card as a SQUAD Fitness card") + + ev = variants(subtype) + if resource_id is None: + resource_id = ev[0]["carddbid"] if ev else 5000000 + subtype + if rating is None: + rating = ev[0]["rating"] if ev else 55 + + it = { + "id": item_id, + "resourceId": resource_id, + "assetId": resource_id, + "cardassetid": resource_id, + "cardsubtypeid": subtype, + "itemType": "player", + "rareflag": rareflag, + "rating": rating, + "itemState": "free", + "owners": 1, + "untradeable": untradeable, + } + if amount is not None: + it["amount"] = int(amount) + if contract is not None: + it["contract"] = int(contract) + return it + + +def item_from_variant(item_id, subtype, variant): + """Build the item EA itself authored: their carddbid, their amount, their rating.""" + r = BY_SUBTYPE[subtype] + kw = dict(resource_id=variant["carddbid"], rating=variant["rating"]) + if "amount" in r.get("needs", ()): + kw["amount"] = variant["amount"] + if "contract" in r.get("needs", ()): + # fcc_contractcards has NO amount column at all (schema: carddbid, cardsubtype, + # weightrare, cardassetid, gold, rating, bronze, silver), so the games count is + # NOT in the shipped data. 7 is INVENTED. Live test 3 is exactly the test that + # makes that safe: the client displays whatever `contract` we send. + kw["contract"] = variant.get("contract", 7) + return consumable_item(item_id, subtype, **kw) + + +# The starter shelf: every core family, every EA variant of it, in subtype order. +# Contracts, healing, fitness and training are what a club actually spends. +def starter_consumables(next_id): + """[(item)] for one of each EA-authored variant of every CORE_KIND. + + `next_id` is a zero-argument allocator (or an int base). Ids come from + CONSUMABLE_ID_BASE by default because these are served as an OVERLAY -- they are + not written into the save, so they must not consume the save's id space. + """ + if isinstance(next_id, int): + base = [next_id] + alloc = lambda: (base.__setitem__(0, base[0] + 1), base[0] - 1)[1] + else: + alloc = next_id + out = [] + for r in SUBTYPES: + if r["kind"] not in CORE_KINDS: + continue + for v in r.get("ea_variants", []): + out.append(item_from_variant(alloc(), r["cardsubtypeid"], v)) + return out + + +def items_for_type(kind, next_id=CONSUMABLE_ID_BASE): + """The starter shelf filtered to one ?type= arm. [] if the arm is not ours.""" + cats = TYPE_CATEGORIES.get(kind) + if cats is None: + return [] + return [i for i in starter_consumables(next_id) + if BY_SUBTYPE[i["cardsubtypeid"]]["category"] in cats] + + +# resourceId -> cardsubtypeid, for the item-DEFINITION route (ut/%s/item/resource). +# Without this a def request for a consumable is answered with cardsubtypeid 0, which +# makes it cardtype 0 -- a player with no merge, i.e. plausible garbage. +DEF_BY_RESOURCE = {} +for _r in SUBTYPES: + for _v in _r.get("ea_variants", []): + DEF_BY_RESOURCE[_v["carddbid"]] = (_r["cardsubtypeid"], _v) + + +def def_for(rid): + """The item-definition body for a consumable resourceId, or None.""" + hit = DEF_BY_RESOURCE.get(rid) + if hit is None: + return None + subtype, v = hit + return item_from_variant(rid, subtype, v) + + +if __name__ == "__main__": + import sys + if "--json" in sys.argv: + print(json.dumps({"itemData": starter_consumables(CONSUMABLE_ID_BASE)}, indent=1)) + else: + live = [r for r in SUBTYPES if r["kind"] != "DEAD_ZONE"] + print("%d cardtype-6 subtypes (%d live, %d dead zones)" + % (len(SUBTYPES), len(live), len(SUBTYPES) - len(live))) + shelf = starter_consumables(CONSUMABLE_ID_BASE) + print("starter shelf: %d items across %d subtypes" + % (len(shelf), len({i["cardsubtypeid"] for i in shelf}))) + for k, cats in sorted(TYPE_CATEGORIES.items()): + n = len(items_for_type(k)) + print(" type=%-12s categories %-18s -> %2d item(s)" + % (k, sorted(cats), n))