View on GitHub

FOnline: The Life After

Fallout-like game based on the FOnline Engine

Scripts Refactoring Plan

This document is the plan and running status for the end-to-end refactor of the TLA AngelScript gameplay layer (Scripts/*.fos). The code is old, has been through many engine migrations, and is inhomogeneous (mixed idioms, dead/relic code, latent bugs). The goal is tidy, reliable, correct code: ordered modules, clearer naming and readability, fewer stray comments (more where they help), and bugs fixed with the original intent restored.

Scope is Scripts/*.fos (≈262 editable files) plus the supporting validators under Tools/ScriptQuality/. Scripts/Content.fos and Scripts/GuiScreens.fos are generated — do not hand-edit (see AGENTS.md).

Principles and constraints

Approved decisions

  1. Split Tla.fos (a ~2400-line god-module holding most of the project’s ///@ metadata plus shared helpers) into domain modules, with full bake + headless verification.
  2. Serialized-name alignment to a single TLA standard and typo fixes, packaged through ///@ MigrationRule. Cross-project-sensitive renames are confirmed case by case.
  3. Process: validators → full audit → phased implementation.

Phases

Module order: low-coupling leaves first, core (Tla/Main/Parameters) last. Each change is compiled, baked, and smoke-tested as above.

Validators and verification

Tools/ScriptQuality/validate_scripts.py is a report-only quality validator (not a formatter) for Scripts/*.fos: trailing-blank-line, namespace==filename, preprocessor-guard balance, component == null probes (errors); banner tags, textpack magic ids, hand-rolled utils, redundant bool returns, commented-out code, file-too-large (warnings; the cyrillic-comment check was retired 2026-06-20 — comments are Russian now). Modes: --summary, --baseline, --ratchet (fail only on new violations vs baseline.json), --fix (safe autofixes). Run via the VS Code task Analyze :: Script Quality. See also Tools/NullableEstimate/.

Adversarial bug-hunting uses read-only finder agents over modules (whole-file or line-range chunks for the giants), then independent skeptic agents that try to refute each finding; only findings that survive majority verification are applied, after a manual re-check.

Status

Remaining / deferred

The active phases above are complete. What is intentionally not changed, and why:

Notes / lessons


Round 2 (2026-06-20) — Polish, headers, comments, bug fixes, tests

Reopened by the owner after the Phase 0–4 close. New goal: bring every Scripts/*.fos module to a uniformly readable, well-documented, correct state. The detailed style rules live in ScriptStyle.md; this section is the plan and running status.

Owner decisions (2026-06-20)

  1. Comment language = Russian, including translating existing English comments. This reverses the prior English-only convention and the 2026-06-17 “don’t touch comments” feedback. AGENTS.md and memory are updated so future agents don’t revert it. Serialized names (///@ Property/Enum/Setting/Event, proto ids, text-pack keys) stay English.
  2. File headers everywhere. Every non-generated script gets a Russian header block above namespace describing its purpose and side (SERVER/CLIENT/MAPPER).
  3. Aggressive behavior changes allowed. Bug fixes and cross-file function relocation are applied in-pass, verified by compile + bake + headless smoke. Gameplay/quest changes that smoke can’t catch are still applied but flagged in the batch report (owner playtest). Serialized-contract changes still gate on ///@ MigrationRule + owner confirmation.

Scope

269 Scripts/*.fos + 3 Scripts/Json/*.fos. Generated files excluded (Content.fos, GuiScreens.fos). Work proceeds in domain batches, low-coupling leaves first, core (Tla/Main/Parameters) last — same ordering principle as round 1.

Phases

Testing strategy — decided (2026-06-20): B, lightweight harness

Owner chose tier B. Port a compact Testing.fos from lf-7 down to TLA’s systems (RegisterTest / Expect / Pass / Fail + fixtures: isolated location, spawn NPC/player/item, cleanup with leak check), gated by a Testing.Enabled setting, plus a Launch :: Tests task. Then Test_* suites starting with pure helpers (Reputation, Math/Flags, GameTime, WeaponHelpers), growing into critical server flows. Done as phase R2-3 after the polish batches establish stable module shapes.

For the record, the tiers considered:

Verification & process

Per ScriptStyle.md §9. Do not commit/stage/push (owner reviews). Surface contentious or gameplay-affecting changes in each batch report rather than applying silently.

R2-2 progress — header coverage complete + verified bug batch (2026-07-03)

Headers/polish batch (workflow, 116 files). All remaining Scripts/*.fos without a header block were taken through the strict-safe polish (Russian header above namespace + English→Russian comment translation), giving header coverage across the whole tree. 103 modules got the full comment polish; the 13 giants (Worldmap, Caravan, Combat, Poker, Parameters, Main, ClientMain, MapperMain, NpcPlanes, ChosenActions, FixBoy, GlobalmapGroup, Purgatory) got header-only — their full comment polish is deferred, to be done carefully in chunks. Machine-verified code-equivalent vs HEAD (Build/_auditall_head.py: no code / ///@-tag / midline drift, CRLF); Format (changed 0) → Compile → Bake → --ratchet all green.

Verified bug batch (adversarial workflow). The 264 suspicions the polish agents flagged were triaged: 111 bug/gameplay candidates run through a triage verifier + a 2-skeptic panel (consumer-contract and git-intent lenses, refute-by-default). 14 survived (97 refuted). 11 applied (each re-checked by reading the code + git):

Confirmed but NOT applied (owner follow-up):

Verification: Compile + ForceBake (550 maps) + --ratchet + headless smoke → “Start server complete!” (0 exceptions). Only the 11 fix files changed code; the other 105 polished files are comment-only. Not committed (owner reviews). Full flag data lives in the workflow task journals / Build/ scratch.

Giants comment polish (2026-07-03, follow-up workflow). The 13 giants had header-only before; a chunked workflow (large files split into sequential ~2000-line ranges, files in parallel) translated their English comments to Russian — 776 comments across the 13 modules (Worldmap 132, Combat 142+8, ClientMain 97, Main 115, GlobalmapGroup 81, NpcPlanes 52, Parameters 51, MapperMain 43, ChosenActions 40, Poker 13, Caravan 9, FixBoy 1, Purgatory already-RU). One Combat chunk hit the account session limit; its residual (~8 real labels) was finished by hand, leaving clang-format directives / Fallout2.exe offset references / code breadcrumbs untranslated by design. Code-equivalence re-verified (still exactly the 11 fix files changed code; giants comment-only) + Compile + Bake + --ratchet green. So every non-generated Scripts/*.fos now has a Russian header and Russian comments.

Those translation agents surfaced 69 more (unverified) flags. Notable candidates for a future verify+fix pass (NOT applied): ChosenActions cast<AbstractItem> on possibly-null GetItem (nullability); Poker ModChFr / GameNum possible divide-by-zero (GameNum inits 0); ClientMain SexTagFemale double-assign around an empty if (cr.IsChosen) {}; Worldmap CheckCompareAnyVar is a byte-for-byte duplicate of CheckCompareAnyParam (the “Var” variant likely meant to read a different source); MapperMain ConvertMaps fail-counter never incremented. Plus content-table smells in Worldmap (weight-0 encounters, duplicate location pids, reused special-encounter ids) — designer review. Saved to Build/scratch.