docs(re): record the reversed ApplyCardByRes success contract and the nine-segment consumables vocabulary
This commit is contained in:
@@ -189,3 +189,63 @@ GET /ut/game/fifa17/club/consumables/development -> outcome=unknown_category e
|
||||
served empty. The client demonstrably asks for it, which is exactly the condition
|
||||
that function's own doc says should add an arm. Which families it should map to
|
||||
is NOT guessed here.
|
||||
|
||||
### Success contract — STATIC_REVERSED (2026-08-22)
|
||||
|
||||
The apply completion handler is `0x180035520`:
|
||||
|
||||
```asm
|
||||
0x180035529 mov ecx,DWORD PTR [rdx+0x1c] ; the ONLY field tested
|
||||
0x18003552c test ecx,ecx
|
||||
0x18003552e jne 0x18003555c ; nonzero -> FAILURE
|
||||
0x18003553c lea rdx,[EVENT_CARDS_APPLY_CARD_SUCCESS] ; 0x1801f37f0
|
||||
0x180035569 lea rdx,[EVENT_CARDS_APPLY_CARD_FAILURE] ; 0x1801f3810
|
||||
```
|
||||
|
||||
It tests exactly one 32-bit field — the transport code — and **never inspects
|
||||
the body**. `EVENT_CARDS_APPLY_CARD_SUCCESS` has precisely one reference in the
|
||||
module, so this is the whole verdict path.
|
||||
|
||||
This does NOT resemble the move ack (`0x180128600`), which builds per-item
|
||||
verdict records and reports FAILURE on an EMPTY vector. The "`{}` is
|
||||
known-broken" precedent is specific to that route and does not transfer here.
|
||||
|
||||
Supporting structure: the response object's constructor `0x1800a4ce0` installs
|
||||
vtable `0x1801fb5b0` and initialises its record vector at `+0x50`/`+0x58`/`+0x60`
|
||||
EMPTY (0x20-byte elements); `0x1800682b0` is the matching destructor, freeing
|
||||
that range with a 0x20 stride. An empty result is therefore a legal parsed state
|
||||
for this response, unlike the move.
|
||||
|
||||
Registration site: `0x1800357da` installs the completion handler and
|
||||
`0x1800357e5` the response factory, back to back.
|
||||
|
||||
**Probe response**: `{"itemData":[]}` — an object root (matching how the oracle's
|
||||
method-agnostic `item/resource` route answers this path) containing an empty
|
||||
vector (legal per the constructor). Labelled a PROBE. The client's SUCCESS only
|
||||
requires transport code 0.
|
||||
|
||||
## Consumables categories — nine, not seven (2026-08-22)
|
||||
|
||||
Correcting the earlier claim that the two formation-modifier families "have no
|
||||
group code, so no segment can reach them — the client's own gap". The client's
|
||||
own switch says otherwise. Literal table at `0x1801f5a38` (under
|
||||
`MyClubAdapterClass` / `CONSUMABLE_TYPE`); switch at `0x180048820` indexing by
|
||||
`enum + 1` through the byte table at `0x180048a90` into the case table at
|
||||
`0x180048a6c`:
|
||||
|
||||
| CONSUMABLE_TYPE | segment |
|
||||
|---|---|
|
||||
| **-1 (unset)** | `development` |
|
||||
| 1, 2 | `contracts` |
|
||||
| 3 | `healing` |
|
||||
| 4 | `fitness` |
|
||||
| **16** | `formation` |
|
||||
| 17 | `position` |
|
||||
| 23 | `playStyle` |
|
||||
| 24 | `managerLeagueModifier` |
|
||||
| 0, 5..15, 18..22 | `training` (switch default) |
|
||||
|
||||
`formation` was a SERVER gap, not a client one. `development` is the type-unset
|
||||
bucket — index 0 of an `enum + 1` table — i.e. the unfiltered view; the eight
|
||||
typed segments already reach all thirteen families exactly once, so it owns no
|
||||
family privately and maps to their union.
|
||||
|
||||
Reference in New Issue
Block a user