sbc: document reversed elgReq ordinal finding; elgReq stays empty

Reversed from the pinned CardsDLL (4706a881): eligibilityKey and
eligibilityOperation are localization ordinals (LOC_SBC_ELG_KEY_%d),
not the atom hex ids. The client's only consumer is the requirement-
display string builder at ~0x1800ef900 (formats via indexed locale
keys, no comparison/gate). The ordinal->string map lives only in the
packed locale (absent from all assets we hold), so any emitted value
would render the WRONG requirement text. Submission stays fully
validated server-side by Core; the empty elgReq is display-only.
Correct ENDPOINT_MAP.md's implied atom-id==ordinal assumption and
pin the exact remaining blocker at the emit site.
This commit is contained in:
funman300
2026-08-19 15:00:18 +00:00
parent 13a22c4507
commit 89dc1b1d85
2 changed files with 38 additions and 2 deletions
+19
View File
@@ -424,6 +424,25 @@ Chemistry/rating/nation/league-count constraints (`teamChemistry 0x307`, `starRa
generically as `{eligibilityKey, eligibilityOperation, eligibilityValue}` triples, **not** as
named scalar fields on the record. **FREEZE-RISK: elgReq must be a JSON array of objects.**
> **2026-08-19 — `eligibilityKey`/`eligibilityOperation` are LOCALIZATION ORDINALS, not the
> atom hex ids above.** Reversed from the pinned CardsDLL (`4706a881…`). The client's sole
> confirmed consumer of these fields is the requirement-display string builder at
> `~0x1800ef900`: it loads the eligibility int fields (`0x148(rcx)`) and formats them through
> *indexed localization keys* — `ELIGIBILITY_STRING%d` (`0x1802186b8`), `LOC_SBC_ELG_KEY_%d`
> (`0x180226710`), `ELIGIBILITY_OPERATION` (`0x1802186e8`) — appending to a string builder via
> vtable `*0x10`/`*0x20`. There is **no comparison/branch**: the client does not validate on
> these ints, it renders `LOC_SBC_ELG_KEY_<eligibilityKey>` (and an operation string) as
> display text. Therefore `eligibilityKey` is a small ordinal that indexes the **packed FIFA17
> locale**, NOT `0x307`/`0x22f`/etc. (those hex values are the atom ids of the *named* fields
> the encoding replaces, not the ordinal values). CONSEQUENCE: correct projection needs the
> ordinal→locale-string map, which lives only in the packed locale (absent from CardsDLL and
> every `fifa17-recon/data` file; a game-dir locale probe on the live client found none) or a
> real EA `elgReq` capture (unavailable on a private server). Emitting a *guessed* ordinal
> renders the WRONG requirement text to the player, so `elgReq` stays `[]` until the ordinal
> map is recovered. This is a display-only gap: SBC submission is fully validated server-side
> (Core), and an invalid squad's generic comms modal originates from the server 400, not from
> the empty `elgReq`.
**awards / grantedAwards** — nested array of reward objects (atoms: `rewardType 0x28e`,
`rewardValue 0x28f`, `rewardQuantity 0x28d`, `rewardMultiplier 0x28c`, `awardCount 0x40`,
`awardSet 0x45`, `awardSetId 0x46`, `prizeSet 0x253`). **FREEZE-RISK: must be array.**
+19 -2
View File
@@ -116,6 +116,15 @@ pub fn challenges_body(set_id: i64, challenges: &[ChallengeView]) -> Value {
"status": "OPEN",
"timesCompleted": times_completed,
"awards": [],
// `elgReq` stays empty deliberately. Reversed from the pinned CardsDLL
// (2026-08-19, see ENDPOINT_MAP.md "Shared record shapes"): the client
// consumes `eligibilityKey`/`eligibilityOperation` only as ordinals that
// index the packed locale (`LOC_SBC_ELG_KEY_%d`) to render requirement
// text — it does NOT validate on them. The ordinal->string map is not
// recoverable from any asset we have, so any value we emit would show the
// WRONG requirement to the player. Submission is validated server-side by
// Core regardless; leaving this empty is display-only, never a correctness
// gap. Populate ONLY once the locale ordinal map is captured.
"elgReq": []
})
})
@@ -360,8 +369,16 @@ mod tests {
assert_eq!(
parse_wire_item_ids(retail).unwrap(),
[
100_004_227, 100_004_233, 100_001_317, 100_001_531, 100_000_966,
100_001_947, 100_000_169, 100_002_017, 100_002_765, 100_000_147,
100_004_227,
100_004_233,
100_001_317,
100_001_531,
100_000_966,
100_001_947,
100_000_169,
100_002_017,
100_002_765,
100_000_147,
100_000_311
],
"exactly the 11 non-zero players in wire order; manager and empty slots ignored"