View on GitHub

FOnline: The Life After

Fallout-like game based on the FOnline Engine

Критерии рефакторинга и форматирования скриптов (TLA)

Единый стандарт для приведения Scripts/*.fos к читаемому, аккуратному и консистентному виду. Документ — рабочий чек-лист для рефакторинга «раунда 2» (полировка + заголовки + комментарии + багфиксы + тесты). План и статус ведутся в Refactoring.md; этот файл описывает как должен выглядеть код.

Язык комментариев — русский (решение владельца, 2026-06-20). Это сознательный разворот прежней англоязычной конвенции; см. AGENTS.md. Сериализуемые имена (///@ Property/Enum/Setting/Event, прото-id, ключи) остаются на английском — их трогать нельзя (риск миграции данных).


0. Принципы (поверх всего)

  1. Поведение сохраняем, если явно не чиним баг. Косметика (формат, заголовки, комментарии, переименование локалей) — строго без смены поведения. Багфиксы — отдельным осознанным шагом, с восстановлением исходного замысла (чтение кода + git, где это несущее).
  2. Без бездумных пакетных правок. Воркфлоу-агенты анализируют и предлагают; применяем обдуманно, малыми порциями, с верификацией. Спорное и меняющее геймплей — выносим списком на решение владельца. См. [feedback в памяти про careful-refactor].
  3. Закомментированный код не удаляем пакетно. Часто это breadcrumb к миграции (отключённые init-ы подсистем, ссылочные алгоритмы Fallout2). Каждый блок — точечное решение: оставить / правильно мигрировать / удалить только если точно мёртв.
  4. Нельзя ломать сборку. Каждая порция проходит верификацию (раздел 9). Предупреждения = ошибки.
  5. Не трогаем генерируемое: Content.fos, GuiScreens.fos (правка — через .fogui + генератор), Baking/, Cache/, VERSION.

1. Заголовок файла (обязательно во всех скриптах)

В начало каждого Scripts/*.fos (кроме генерируемых) добавляем блок-описание на русском — что делает модуль, его зона ответственности и сторона исполнения. Ставится над строкой namespace.

Формат:

// <Имя модуля> — <одно-два предложения: за что отвечает модуль>.
// <Опционально: ключевые обязанности списком, связи с другими модулями,
//  особенности (сторона SERVER/CLIENT/MAPPER, async, точки подписки)>.
namespace ModuleName
{

Правила:

Пример:

// Reputation — пороги и уровни репутации/кармы игрока.
// SERVER: чистые предикаты уровня репутации по числовому значению.
// CLIENT: преобразование числа в KarmaLevel/ReputationLevel для интерфейса.
namespace Reputation
{

2. Комментарии к блокам кода

Цель — чтобы по комментариям читалось намерение, а не механика строк.


3. Нейминг

Сущность Стиль Пример
namespace PascalCase == имя файла namespace Combat в Combat.fos
Функции PascalCase GetKarmaLevel, IsReputationLiked
Локали/параметры camelCase playerCr, targetHex, apCost
Новые константы PascalCase const int MaxRetries
Легаси флаг-группы (сериализуемые/битовые) UPPER_SNAKE — не трогаем HF_DEAD, USE_RELOAD, AP_DIVIDER
///@ Property/Enum/Setting PascalCase, владеет TLA CurrentHp, MaxLife

Правила:


4. Структура модуля (порядок сверху вниз)

Внутри namespace держим стабильный порядок — от «контракта» к деталям:

  1. Метаданные ///@ Setting / Enum / Property / Event / RemoteCall / RefType — вверху.
  2. Константы модуля (const ...).
  3. [[ModuleInit]] + подписки на события (точка входа модуля).
  4. Публичные функции (то, что зовут другие модули) — высокоуровневое раньше.
  5. Обработчики событий ([[Event]], [[TimeEvent]], [[*RemoteCall]]).
  6. Приватные хелперы — низкоуровневые детали внизу.

Дополнительно:


5. Механическое форматирование (отдаём форматтеру)

Источник правды — Scripts/.clang-format + постобработка Tools/Formatter/format_project.py (VS Code task Format :: Scripts). Руками не воюем с форматтером. Ключевое из конфигурации:


6. Идиомы AngelScript (приводим к современным)


7. Антипаттерны (выпрямляем)


8. Багфиксы (раунд агрессивный — применяем, но верифицируем)


9. Верификация (каждая порция — обязательно)

Порядок (предупреждения трактуем как ошибки):

  1. Compile AngelScriptTLA_ASCompiler.log / Build/_errors.txt (0 warnings).
  2. Bake Resources (после переноса ///@ PropertyForce Bake).
  3. Затронутые Build :: TLA_* (минимум TLA_Server, при клиентских правках TLA_Client).
  4. Серверо-поведенческое — TLA_ServerHeadless до "Start server complete!" без исключений.
  5. Analyze :: Script Quality (--ratchet: без новых нарушений) + validate_nullable.py.
  6. Затронут движок/нативная граница — TLA_UnitTests.
  7. Format :: Scripts перед сдачей порции.

Не коммитим/не стейджим/не пушим — владелец ревьюит и коммитит сам.


10. Тесты («обкладываем тестами»)

Сейчас в TLA нет скриптового геймплей-харнесса (только C++ Test_*.cpp в движке). Эталон H:/lf-7 имеет полноценный AngelScript-харнесс (Scripts/Testing.fos + Scripts/Tests/Test_*.fos, ~72 сьюта); движок TLA нужные API уже предоставляет (Game.GetEntityRegistryCount, CreateUnloginedPlayer, GetAllocatorMemoryUsage, verify(...) и т.д.).

Стратегия тестирования выбирается владельцем (см. план в Refactoring.md, раздел «Round 2»). Базовый принцип: пишем детерминированные тесты, начиная с чистых функций-хелперов (Reputation, Math/Flags, GameTime, WeaponHelpers), затем — критичные серверные флоу через фикстуры (создать изолированную локацию → заспавнить криттера/предмет → проверить → прибрать без утечек).


11. Готовность порции (Definition of Done)

</content> </invoke>