feat(fifa17): project badges and stadiums, the other two cardtype-7 club items
Kit, badge and stadium are ONE record with ONE client-side resolver (`FUN_180119bd0`, dispatched on `item+0x4c == 7`); they differ only in the field their caption reads. Kits already ship and render, so the record is live-proven — badges and stadiums were being withheld as if unreversed when the authority (`plan-2026-08-06-card-subsystem.md`) marks both CONFIRMED, and its own rollout order is "kits first, then badges, then stadia". So the shaper generalises to the family, and carries exactly what each caption resolves: `teamid` for kit and badge (`TeamName_Abbr15_<teamid>`), withheld for stadium, whose resolver reads `StadiumName_<assetId>` and never looks at teamid. Sending a field the resolver does not read is how this project earned a client freeze. Ball (30) and league logo (31) stay withheld. They are cardtype 9 with NO database name resolver, so their name can only come from `localizedName`: the offset is confirmed, but "the parser reads it" is not "sending it is safe". Verified against the real club on staging: badge 6000005 emits cardsubtypeid 11 / cardassetid 39 / teamid 21, stadium 6200000 emits cardsubtypeid 10 / cardassetid 36 and no teamid, ball and logo emit nothing.
This commit is contained in:
@@ -8,8 +8,8 @@
|
||||
//! * Consumable families and their contiguous `cardsubtypeid` ranges are taken
|
||||
//! verbatim from `fifa17-recon/tools/fut_consumables.py`
|
||||
//! (`BY_SUBTYPE`/`CORE_KINDS`, Ghidra-derived from `FUN_18013f4d0` /
|
||||
//! `FUN_1801bfac0`) and `docs/CARD_TAXONOMY.md` (verified against the `.105`
|
||||
//! `fcc_*.json` tables).
|
||||
//! `FUN_1801bfac0`) and `fifa17-recon/docs/plan-2026-08-06-card-subsystem.md`
|
||||
//! (verified against the `.105` `fcc_*.json` tables).
|
||||
//! * Staff roles are the `FUN_1800d8330` family selector: 4=manager, 5=headcoach,
|
||||
//! 6=gkcoach, 7=physio, 8=fitnesscoach.
|
||||
//!
|
||||
@@ -95,6 +95,25 @@ impl ContentKind {
|
||||
pub fn is_staff_family(&self) -> bool {
|
||||
matches!(self, ContentKind::Manager | ContentKind::Staff)
|
||||
}
|
||||
|
||||
/// True for the three club-customisation kinds that share the **cardtype-7**
|
||||
/// record: kit (9), stadium (10) and badge (11).
|
||||
///
|
||||
/// `FUN_1800d8330` maps all three subtypes to cardtype 7, and one client-side
|
||||
/// resolver (`FUN_180119bd0`, dispatched on `item+0x4c == 7`) captions all
|
||||
/// three. They therefore share ONE wire record
|
||||
/// ([`crate::fut::item::shape_club_item`]) and one identity resolver.
|
||||
///
|
||||
/// Ball (30) and league logo (31) are cardtype 9 and are deliberately NOT in
|
||||
/// this family: they have no database name resolver, so their name can only
|
||||
/// come from `localizedName` on the wire, which is not established as safe
|
||||
/// to send.
|
||||
pub fn is_cardtype7_club_item(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
ContentKind::Kit | ContentKind::Stadium | ContentKind::Badge
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// The functional family + honest display label for a consumable `cardsubtypeid`,
|
||||
|
||||
Reference in New Issue
Block a user