1fb664710a
Adds the app-centric FLE bridge direction (direction.md) replacing the Blaze-backend route as primary plan, plus a corrected foundational test procedure and snapshot/diff/apply tooling for reverse-engineering FLE's Freeze Lineup write mechanism. Also picks up prior untracked research docs (status-review, fut-integration-options, fifa23-startup-flow, track-c) and existing capture/export tooling that hadn't been committed yet.
192 lines
8.4 KiB
Markdown
192 lines
8.4 KiB
Markdown
# Foundational test — live custom XI via Freeze Lineup
|
||
|
||
**Status: PENDING — test has not yet been run.**
|
||
|
||
This is build-order step 1 from `docs/direction.md`: the test everything else
|
||
in the direction pivot depends on.
|
||
|
||
## What changed since the first draft of this doc
|
||
|
||
The first version of this test guessed at a "selection bias" DB field and a
|
||
candidate squad/lineup table name, based on general FIFA-modding precedent
|
||
that turned out not to hold for FLE's documented API — no such field appears
|
||
anywhere in FLE's actual Lua API docs or its own example scripts. While
|
||
researching an unrelated hotkey issue, a **confirmed, FLE-documented**
|
||
mechanism for forcing a starting XI turned up instead: the **Formation
|
||
Editor's "Freeze Lineup" feature** (FLE wiki, `Formation-Editor.md`):
|
||
|
||
> This feature can be used in player career mode if you want to manage the
|
||
> starting lineup of your team. Can be also used in manager career mode to
|
||
> manually manage your next opponent's starting lineup.
|
||
|
||
Steps (GUI, no scripting): open Formation Editor for a team → arrange players
|
||
on the pitch → tick **Freeze Lineup** → `Data → Save`.
|
||
|
||
This is real and documented, but it's GUI-only — there is no Lua function for
|
||
it, and what DB write it actually performs under the hood is undocumented.
|
||
This test is now two phases: confirm the GUI feature works at all, then
|
||
reverse the DB write it makes so it can be replicated programmatically
|
||
(required for the app→game bridge in build-order step 2, which needs this
|
||
driven from outside the game, not from a person clicking checkboxes).
|
||
|
||
Also fixed in this pass: `EditDBTableField`'s real signature, confirmed from
|
||
FLE's own docs and `lua/scripts/99ovr_99pot.lua`, is
|
||
`EditDBTableField(cell)` where `cell` is `row["fieldname"]` with `.value`
|
||
mutated in place — **not** `EditDBTableField(table, row_index, field, value)`
|
||
as originally (incorrectly) written into the first draft of the injector
|
||
script.
|
||
|
||
## What this test settles
|
||
|
||
Whether a *specific, externally-chosen* 11 players can be forced into a
|
||
career (or Kick-Off) match's starting lineup, live, with no restart — and
|
||
whether the mechanism that does it (Freeze Lineup's underlying DB write) can
|
||
be driven by a script instead of a person clicking through the Formation
|
||
Editor UI.
|
||
|
||
If Freeze Lineup itself doesn't actually hold under match start (the wiki
|
||
doesn't show it being tested against a live match, only "you should be able
|
||
to see... when you play against them"), the whole bridge architecture in
|
||
`docs/direction.md` §3 needs rethinking — there is no other documented
|
||
mechanism for forcing a lineup.
|
||
|
||
## Prerequisites
|
||
|
||
- FIFA 23 launched normally (FLE injected, EAAC neutralized — same baseline
|
||
as `track-c-fut-table-test.md`)
|
||
- A career save loaded (Freeze Lineup is documented for career mode
|
||
specifically — confirm separately whether it does anything in Kick-Off,
|
||
don't assume it does)
|
||
- Note 11 player IDs from your club (`tools/squad-exporter/export_squad.lua`
|
||
output, `playerid` field) that are NOT currently your starting XI
|
||
|
||
## Phase 1 — confirm Freeze Lineup actually holds into a match
|
||
|
||
This has zero scripting and should be done first since everything else is
|
||
wasted effort if it fails.
|
||
|
||
1. Open the Live Editor overlay (F9, or `Windows → Settings` from the
|
||
overlay's own menu bar if the hotkey isn't registering — see the umu/Wine
|
||
hotkey note below).
|
||
2. `Features → Teams` → find your team → `Edit`.
|
||
3. `Team → Formation` to open the Formation Editor.
|
||
4. Swap players around on the pitch so the XI differs from your current
|
||
actual starting XI in some checkable way (e.g. swap two outfield players'
|
||
positions, or bench/start a specific player).
|
||
5. Tick **Freeze Lineup**.
|
||
6. `Data → Save`.
|
||
7. Hide Live Editor (F9), save your career **on a new slot** (don't overwrite
|
||
your main save in case this corrupts something), exit to main menu, reload
|
||
that save, and check the team's lineup screen / play a match and watch who
|
||
starts.
|
||
|
||
**Record in the Results table below whether the frozen lineup actually took
|
||
the pitch.** If not, stop here — Phase 2 is moot.
|
||
|
||
## Phase 2 — find the underlying DB write
|
||
|
||
Only proceed if Phase 1 confirmed Freeze Lineup works.
|
||
|
||
1. In FLE's Lua Engine, run `tools/squad-injector/snapshot_lineup_tables.lua`.
|
||
This dumps every DB table whose name contains `squad`, `lineup`,
|
||
`formation`, `tactic`, `teamsheet`, `selection`, `players`, or `teams` to
|
||
`C:\FIFA 23 Live Editor\openfut_snapshot_<timestamp>.json`. Note this
|
||
filename — this is your **before** snapshot.
|
||
2. Without restarting or reloading, repeat the Formation Editor steps from
|
||
Phase 1 (steps 2–6 only — open Formation Editor, change the lineup, tick
|
||
Freeze Lineup, `Data → Save`). Don't save/reload the career between
|
||
snapshot and this step — keep it to a single live session so the diff
|
||
isn't polluted by other state changes.
|
||
3. Run `snapshot_lineup_tables.lua` again. This is your **after** snapshot.
|
||
4. Copy both JSON files out of the Wine prefix (same path pattern as
|
||
`track-c-fut-table-test.md`: `~/Games/umu/.../drive_c/FIFA 23 Live
|
||
Editor/`) and run:
|
||
|
||
```bash
|
||
python3 tools/squad-injector/diff_snapshots.py before.json after.json
|
||
```
|
||
|
||
5. The output shows exactly which table(s) and field(s) changed. This is the
|
||
real, confirmed write Freeze Lineup performs — record it in the Results
|
||
table below.
|
||
|
||
## Phase 3 — replicate the write via script
|
||
|
||
1. Open `tools/squad-injector/apply_lineup_write.lua` and fill in
|
||
`TARGET_TABLE` and `TARGET_FIELDS` using Phase 2's diff output.
|
||
2. Edit `C:\FIFA 23 Live Editor\openfut_test_xi.json`:
|
||
|
||
```json
|
||
{
|
||
"team_id": 12345,
|
||
"xi": [
|
||
{ "player_id": 111111, "position": 0 },
|
||
{ "player_id": 222222, "position": 5 }
|
||
]
|
||
}
|
||
```
|
||
|
||
Use 11 entries. Position codes are **confirmed numeric 0–27**
|
||
(`GK=0, SW=1, RWB=2, RB=3, RCB=4, CB=5, LCB=6, LB=7, LWB=8, RDM=9, CDM=10,
|
||
LDM=11, RM=12, RCM=13, CM=14, LCM=15, LM=16, RAM=17, CAM=18, LAM=19,
|
||
RF=20, CF=21, LF=22, RW=23, RS=24, ST=25, LS=26, LW=27`) — from
|
||
`lua/scripts/export_season_stats.lua`'s `get_pos_name` table in FLE's own
|
||
repo, not a guess.
|
||
3. Run `apply_lineup_write.lua` from FLE's Lua Engine.
|
||
4. Repeat the save-to-new-slot / reload / check-lineup verification from
|
||
Phase 1, but this time without ever opening the Formation Editor — the
|
||
write was made entirely from the script.
|
||
|
||
## Classification criteria
|
||
|
||
### "Confirmed — full mechanism works"
|
||
|
||
Phase 1 holds, Phase 2 finds a clean diff, Phase 3's scripted write produces
|
||
the same in-match result as the manual GUI path.
|
||
|
||
**Verdict:** Build-order step 1 done. Proceed to step 2 (bridge transport) in
|
||
`docs/direction.md`.
|
||
|
||
### "GUI works, script doesn't"
|
||
|
||
Phase 1 holds but Phase 3's replicated write doesn't stick, even though the
|
||
diffed fields matched what changed in Phase 2.
|
||
|
||
**Verdict:** Freeze Lineup likely does more than a single DB field write
|
||
(e.g. an internal engine call beyond `EditDBTableField`'s reach, or a second
|
||
write the diff missed because it happened in a table outside the `KEYWORDS`
|
||
filter in `snapshot_lineup_tables.lua` — widen the filter and redo Phase 2).
|
||
|
||
### "Freeze Lineup doesn't hold at all"
|
||
|
||
Phase 1 fails — the lineup reverts to the game's own AI-picked XI regardless.
|
||
|
||
**Verdict:** No confirmed mechanism exists for forcing a lineup. This kills
|
||
the bridge architecture as designed in `direction.md` §3 and needs a return
|
||
to first principles — there is no fallback documented anywhere in FLE's wiki
|
||
for this specific case.
|
||
|
||
## A note on the umu/Wine F9/F11 hotkey issue
|
||
|
||
If FLE's F9 (hide/show) hotkey isn't registering under umu, this is plausibly
|
||
a Wine keyboard-hook limitation (FLE's global hotkey detection likely uses a
|
||
low-level hook that doesn't translate cleanly through Wine's input layer) —
|
||
not something documented anywhere in FLE's own troubleshooting docs, which
|
||
don't mention Linux/Wine at all. F11 specifically has **no documented FLE
|
||
function** — F9 is the only documented toggle. Workaround: click directly
|
||
into the FLE overlay window (it should still be visible/clickable even if the
|
||
hotkey doesn't fire) and use its own menu bar instead of relying on the
|
||
hotkey.
|
||
|
||
## Results
|
||
|
||
*(To be filled in after the test is run.)*
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| Date run | — |
|
||
| Phase 1: Freeze Lineup holds into a match? | — |
|
||
| Phase 2: table(s)/field(s) changed | — |
|
||
| Phase 3: scripted write reproduces Phase 1 result? | — |
|
||
| **Classification** | **PENDING** |
|