fix(market): returning an item to the club ends its auction; close the panel probe

CLOSES the active-own-auction Actions-panel investigation. Live client plus the RE
corpus plus historical FUT behaviour all agree: an active auction is COMMITTED until
sale or expiry and is not seller-actionable, while an expired unsold item becomes
actionable (relist / return to club). Every observation fits that lifecycle --
active+frozen expires was non-selectable, expired was selectable and relisted fine,
relisting made it active and non-selectable again, and the client never emits a
cancel. Documented with confidence tags, and the dead ends are named so they are not
retried: MAY_BE_REMOVED is a constant 1, and the eight-flag array is the CLUB-CARD
menu with no auction-cancellation flag in it.

Implements the return-to-club transition that closure exposes. A pile move to `club`
now cancels any ACTIVE listing on that item, because the auction that put the card
in the pile has to end with it. Otherwise the pile reads `club` while the row stays
`active`, so the card is filtered out of /club (exclusion keys on active listings)
AND still rendered in the Transfer List: the move appears to do nothing. This is the
same limbo class as the earlier pile-vs-listing bug, found by reasoning about the
transition rather than by another live failure.

Scoped to `active` only: a `reserved` row is mid-sale and a `sold` row is already
gone, so cancelling either would let one card be both sold and returned. Two tests
cover exactly that boundary.

338 tests pass, 0 failed, clippy clean.
This commit is contained in:
funman300
2026-08-17 19:56:06 +00:00
parent 6cc22e5cc5
commit 4e31fb98a2
4 changed files with 206 additions and 8 deletions
+61
View File
@@ -269,3 +269,64 @@ perfectly while still being behaviourally wrong, because FIFA expects an **evolv
server-side state machine** rather than a static object that looks like one. The
frozen `expires` is the canonical example: every field was the right name, type and
vocabulary, and the feature was still broken.
---
## INVESTIGATION CLOSED — active own auction is not seller-actionable
**Do not reopen without new direct FIFA17.exe evidence contradicting the lifecycle
below.** The correct FIFA 17 lifecycle is:
```text
ACTIVE AUCTION tradeState=active, expires>0/counting down
-> seller CANNOT withdraw it through Transfer List actions
-> the item is not seller-actionable while the auction runs
EXPIRED UNSOLD tradeState=expired, expires=0
-> the item becomes actionable again
-> relist / return-to-club / other expired-item actions
```
### Confidence tags
```text
CONFIRMED — live FIFA17.exe:
active listing with ticking expires is NON-selectable
expired listing IS selectable
relisting makes it active and therefore non-selectable again
no cancel request is ever emitted by the client
expires must advance with the wall clock
no button prompt is offered on the Transfer List for an active auction
CONFIRMED — local RE corpus:
every CardsDLL-side prerequisite passes (IS_TRADING_ENABLED=1,
TRADE_PILE_SIZE=100, watch-list=50, item+0x49 tradeable)
MAY_BE_REMOVED is a CONSTANT 1 — it cannot be the gate and the server
cannot move it
the eight-flag array FUN_18003e370 publishes is the CLUB-CARD Actions menu
and contains NO transfer-auction cancellation flag
the auction parser is limited to the known twelve atoms
HISTORICAL FUT / FIFA17-era:
active auctions are committed until sale or expiry
expired Transfer List items expose relist/return actions
FIFA 17 trading guidance tells players to relist once auctions expire
UNKNOWN, and no longer required for backend fidelity:
the exact Flash/ActionScript branch that makes active cards non-selectable
```
### Explicitly out of scope now
Do NOT add auction fields, change `itemState`, revisit `tradeOwner`, probe
`MAY_BE_REMOVED`, add an active-auction cancel feature, or disassemble Flash in
order to make active auctions selectable. Three of those were already tried and
refuted; the rest are ruled out above.
### Return-to-club transition (implemented)
A pile move to `club` now ENDS any `active` auction on that item. Without it the
pile reads `club` while the listing row stays `active`, so the card is filtered out
of `/club` (exclusion keys on active listings) AND still rendered in the Transfer
List — the move silently appears to do nothing. `reserved` (mid-sale) and `sold`
rows are never touched, so a card can never be both sold and returned.