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
|
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
|
that function's own doc says should add an arm. Which families it should map to
|
||||||
is NOT guessed here.
|
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