Q2PRO-X 1.0 — Техническое руководство

Просмотр документа на сайте Q2PRO-X. Оригинальный файл можно скачать из окна сайта.

  • Релиз 1.0 фиксирует финальную архитектуру modern cvar browser и overlay UX wave.
  • Browser-local EN+RU font pipeline, UTF-8 wrap, detail scroll и browser-local scale завершены.
  • Добавлены settings-gear переходы с tracked return flow обратно в исходный оверлей.
  • LAGHAX HUD получил собственную alpha-модель и read-only runtime snapshot weapon predict.
  • Data-layer 1.0 теперь явно включает q2pro-x.menu2 и q2prox_cvar_font.png как обязательные runtime-ресурсы.
  • Server-authority по weapon predict сохранена: новая диагностика не меняет gameplay logic.

Архитектурные обновления релиза 1.0 относительно beta 0.99

  • Modern cvar browser: переход от ASCII/console-style path к browser-local font/layout с единым EN+RU atlas и корректным UTF-8 wrap.
  • Browser chrome переведён на runtime metrics от cl_cvar_browser_scale; текст и text-driven chrome больше не наезжают на кнопки и собственные границы.
  • Overlay settings buttons теперь открывают menu flow с return-командой, а не просто выбрасывают пользователя в оторванное состояние UI.
  • LAGHAX HUD использует отдельный global alpha cvar и новый snapshot API Ghost_GetRuntimeStats() для read-only runtime diagnostics.
  • Release 1.0 закрепляет обязательный data-layer: q2pro-x.menu, q2pro-x.menu2, q2pro.modhelp, q2prox_cvar_font.png.

Обновления релиза 1.0 (архитектура)

Modern Cvar Browser: final UI architecture

Главный архитектурный итог 1.0 — modern cvar browser перестал быть надстройкой над legacy console-text path и получил собственный browser-local рендер текста, независимые метрики и отдельный font atlas для EN+RU.

Это позволило одновременно решить проблемы качества кириллицы, UTF-8 wrap/layout, внутренних scroll/clipping правил и user-facing scale control без влияния на общий HUD проекта.

Browser-local alpha теперь считается отдельно от scr_alpha, что делает поведение справочника cvar независимым и объяснимым на уровне UI-политики.

Overlay settings return flow

Шестерёнки в новых оверлеях реализуют tracked menu flow. При переходе в настройки клиент сохраняет источник вызова и при закрытии меню возвращает пользователя ровно в тот оверлей, из которого тот пришёл.

Это устраняет UX-разрыв между overlay-layer и menu-layer и делает настройки оверлеев частью единой пользовательской модели.

LAGHAX HUD: separate alpha + runtime snapshot

Добавление cl_laghax_hud_alpha отделило laghax HUD от общей alpha-политики scr_alpha. Итоговая прозрачность теперь следует модели modern overlays: собственный cvar × OLED UI alpha.

Новый runtime-блок weapon predict реализован как read-only snapshot API. screen.c не читает внутренние поля ghost.c напрямую; ответственность за сериализацию runtime-state остаётся внутри ghost.c.

Packaging layer for 1.0

Релиз 1.0 окончательно закрепляет правило additive-layer packaging. Клиентский пакет ship'ит только собственные бинарники, runtime-библиотеки и минимальный Q2PRO-X data-layer.

Новая обязательная часть этого data-layer — q2pro-x.menu2 и browser-local font atlas q2prox_cvar_font.png. Generated-конфиги пользователя в пакет не входят.

Multiplayer fairness note

Состояние 1.0 сохраняет server-authority по weapon predict: сервер остаётся источником истины для скорострельности, ammo, projectile spawn и damage. Runtime diagnostics LAGHAX HUD ничего не меняют в timing или боевой логике.

  • Q2PRO-X 1.0
  • Техническое руководство

Главный автор проекта, инициатор ключевых идей и основной тестировщик: ly

Тестирование: Quake II community

Документ актуализирован для релиза 1.0; новые разделы в конце фиксируют архитектурные изменения относительно beta 0.99.

Оглавление

2. Packaging и release philosophy 4

3. Menu overlay architecture 4

4. Config architecture: split by ownership and scope 4

5. Movement, predict и feel-совместимость 5

6. Weapon predict architecture 6

7. Laghax internals 6

8. Renderer architecture 6

8.1. win32egl and desktop fullscreen 6

8.2. Internal render scale paths 6

8.3. Visual FX stack 7

9. Modern server browser 7

10. Visibility/highlighting architecture 7

11. Sound architecture 8

11.1. OpenAL profiles, reverb and routing 8

11.2. Resamplers and high-precision output 8

11.3. Binaural layer and OpenAL Soft 8

12. Mod command overlay internals 8

13. Restart policy and live-apply policy 8

14. Known limitations и честные ограничения 9

15. Донорская карта проекта 9

16. 0.96: 4:3 pillarbox, resolution picker и fullscreen semantics 11

16.1. Практическая логика режимов 11

16.2. Почему это важно для beta/release layer 11

17. 0.97: OLED protection architecture 12

18. 0.97: weapon prediction follow-up and accepted limitations 12

19. 0.97: laghax HUD as a live diagnostic surface 12

20. 0.97: step smoothing lift jitter fix 13

16. Архитектурные обновления beta 0.98 относительно 0.97 13

16.1. Display mode state: windowed / desktop / exclusive 13

16.2. Runtime audio gain вместо грубого mute-переключателя 14

16.3. Предикт оружия: новая стабилизированная архитектура 14

16.4. Переключение оружия и непрерывная стрельба: почему это теперь работает лучше 15

16.5. HyperBlaster и rockets: точное сопоставление вместо грубого suppression 15

16.6. Laghax: starvation detector hardening 15

16.7. Server Browser Favorites: composite persistence model 16

16.8. UI correctness: single-predicate visibility for Favorites action 16

1. Роль Q2PRO-X относительно исходного Q2PRO

Q2PRO-X — это не просто форк с набором случайных патчей. Архитектурно это layered client build: базовая совместимость и поведение Q2PRO сохраняются, а новые функции добавляются как контролируемые user-facing слои поверх исходной базы.

  • Базовая кодовая база: Q2PRO r3832.
  • Новые системы по возможности живут отдельно, а не ломают старый путь насильно.
  • Почти всё новое экспонируется через cvar и меню, а не скрытые магические переключатели.
  • Приоритет у воспроизводимого поведения и у честной диагностики requested/applied состояния.

2. Packaging и release philosophy

Бета-пакет intentionally собирается как additive release layer. Это важно не только для удобства тестеров, но и для корректной архитектуры распространения: Q2PRO-X не должен зависеть от того, какое именно q2pro.menu или какие пользовательские cfg лежат у человека в baseq2.

3. Menu overlay architecture

Q2PRO-X menu architecture основана на отдельном q2pro-x.menu и inject-блоках. Это ключевое решение: клиент получает модульность меню и перестаёт зависеть от прямой правки пользовательского q2pro.menu.

  • q2pro.menu грузится первым как base menu tree.
  • Дополнительные menu overlays загружаются после него.
  • Inject с parent/order semantics добавляет entry в существующий parent menu.
  • Для одинаковых parent/order порядок должен быть детерминированным.

Практический вывод: Q2PRO-X можно распространять без перезаписи чужого q2pro.menu, что особенно важно для тестовых групп с уже настроенной средой.

4. Config architecture: split by ownership and scope

Конфиги Q2PRO-X намеренно отделены от обычного config.cfg. Более того, они разделены на global и mod-local scopes. Это избавляет от проблемы, когда пользователь настраивает клиент под себя, а потом теряет эти настройки при переключении на другой mod.

  • Mod-local config не может перебивать global-owned cvars.
  • При попытке ручного override клиент пишет точный warning с путём offending файла.
  • Autosave, save и defaults обязаны уважать scope отдельно.
  • Bind ownership split так же важен, как и cvar ownership split.

5. Movement, predict и feel-совместимость

В Q2PRO-X важно различать физику, client prediction backend, scheduler и purely local camera feel. Эти вещи тесно связаны в ощущениях игрока, но архитектурно их надо разделять.

Такое расщепление позволяет комбинировать старый feel предикта с современным fixedmove и отдельно выбирать R1Q2-like сглаживание ступенек, не скатываясь в один giant legacy mode.

Отдельно здесь живёт cl_movement_feel_mode. Это не ещё один predict backend, а именно command-timing / scheduler feel selector: 0 = current q2pro path, 1 = r1q2-like path.

  • Важно не смешивать его с cl_predict_move_mode. predict backend отвечает за клиентское предсказание движения, а movement feel mode — за applied cadence формирования movement command.
  • r1q2-like mode intentionally bypasses cl_fixedmove subdivision и возвращает classic monolithic phys_frame cadence. Именно поэтому в UI честно сказано, что fixed move в этом режиме ignored как feel-defining scheduler.
  • При этом step smoothing остаётся независимым axis. Пользователь может выбрать q2pro / r1q2-like movement feel и отдельно добавить один из R1Q2-style вариантов сглаживания ступенек, если ему нравится именно такая комбинация.

Архитектурно это и было целью: не делать giant switch "become old client", а разнести predict backend, scheduler feel и camera smoothing на отдельные управляемые слои.

6. Weapon predict architecture

Weapon predicts в Q2PRO-X — это набор отдельных ghost/model/impact paths, а не одна большая общая галка. Такая декомпозиция нужна потому, что разные типы оружия имеют разные временные окна, разные формы server confirmation и разную чувствительность к визуальным артефактам.

  • Rocket path включает и projectile, и optional explosion prediction.
  • Railgun и hitscan-оружие требуют отдельной timing-модели и suppression duplicate effects.
  • Shotgun и super shotgun работают через локальную правдоподобность fire feedback, а не через попытку симулировать серверную баллистику.
  • Impact volume control позже завязан на recent-fire context, а не на простое имя wav-файла.

7. Laghax internals

Laghax adaptive mode — это stress-based window selection, а не просто линейный lerp. Внутри участвуют ping, jitter, packet disturbance, prediction debt и authority-gap.

  • Малые ошибки можно снапать сразу, чтобы не превращать движение в мыло.
  • При росте стресса окно коррекции растёт, но остаётся ограниченным hard cap.
  • Loss-dominant low-ping refinement переоценивает роль потерь и burst-ов там, где jitter сигнал загрязнён именно ими.
  • Debug/HUD path нужен не только для красивой визуализации, а для реального разбора поведения на проблемной линии.

8. Renderer architecture

Визуальные доработки Q2PRO-X не собраны в один гигантский rewrite. Архитектурно это набор слоёв: modern video backend, render scale subsystem, local visual fx, menu transparency и вспомогательные overlay UI.

8.1. win32egl and desktop fullscreen

win32egl в Q2PRO-X важен не только как второй video driver, а как supported path для современных desktop/hdr/capture сценариев. Поэтому в релизе есть ANGLE bundle, а desktop fullscreen и Alt+Tab/Alt+F4 входят в документированное поведение.

8.2. Internal render scale paths

Дополнительно quality resolve нельзя сводить к одному bilinear collapse. Именно поэтому в Q2PRO-X появился progressive downsample chain и tiled guard-band, иначе на высоких процентах scale начинается рябь и seam-артефакты.

8.3. Visual FX stack

Visual FX intentionally живёт на существующем scene/postprocess pipeline. Это позволяет держать live-apply и общую диагностику visual fx info, не плодя отдельный параллельный renderer.

9. Modern server browser

Новый browser не переписывает discovery backend. Архитектурно это новый frontend/window/UI layer поверх старой серверной информации, что снижает риск и делает развитие интерфейса самостоятельным направлением.

  • Legacy browser сохраняется как fallback и user choice.
  • Modern browser должен поддерживать both mouse-first and keyboard navigation.
  • Address/connect target semantics должны быть честно разведены с тем, как строка красиво отображается в details.
  • Custom source — это часть пользовательского workflow, а не только скрытый runtime preset.

10. Visibility/highlighting architecture

Visibility/highlighting развивалась по стадиям: сначала items, затем players, потом team-aware logic. Это позволило сначала опереться на strong truth, а только потом идти в более рискованные heuristics.

  • Items классифицируются надёжнее, чем player team semantics, поэтому они и шли первым этапом.
  • Player highlighting использует разные режимы и confidence hold, а не коммитится по одному кадру.
  • Team auto допускается только при наличии strong team truth, а не по магическому предположению.
  • Future safe screen-space outline зафиксирован отдельно, потому что world-scale > 1.0 в competitive context быстро становится exploit path.

11. Sound architecture

Звук в Q2PRO-X — это уже не только OpenAL on/off. Внутри есть несколько осей: OpenAL profile, acoustics/reverb, routing slots, sound profiles, per-weapon volumes, resamplers, high-precision output и binaural layer.

11.1. OpenAL profiles, reverb and routing

al_profile и al_reverb intentionally orthogonal. Первый отвечает за базовое feel behavior OpenAL path, второй — за пространственную акустику и EFX routing.

  • Profile 0 = current Q2PRO-X baseline.
  • Profile 1 = R1Q2-like feel with inverse-distance style behavior.
  • al_reverb строится через OpenAL Soft / EFX, а не legacy hardware assumptions.
  • Routing развивается от single-slot fallback к dual/triple/quad topology.

11.2. Resamplers and high-precision output

Архитектурно сначала был закрыт quality вопрос SRC, а уже потом high-precision output. Это важная последовательность: смысл float32/96kHz невысок, если sample-rate conversion path остаётся грубым.

11.3. Binaural layer and OpenAL Soft

Binaural/3D sound intentionally реализован как control layer поверх OpenAL Soft HRTF и app-local alsoft.ini. Это даёт хороший баланс между мощностью и совместимостью.

  • al_hrtf сохранён как совместимый alias.
  • al_binaural_profile управляет только binaural-specific ручками.
  • Bundled soft_oal.dll — часть осознанной portable-runtime стратегии.

12. Mod command overlay internals

Overlay давно вышел за рамки простого справочника. Сейчас это mod-aware command assistant с ролями, confirm logic, search, pins, local overrides и prompt suggestions.

Отдельно важно, что prompt input path нельзя путать с обычным игровым input suppression: игровые bind'ы должны гаситься, но текст для vote map, vote kick и других prompt-команд должен вводиться полноценно.

13. Restart policy and live-apply policy

Q2PRO-X deliberately старается минимизировать ручные restart-ритуалы. Там, где restart неизбежен, пользователь должен видеть это честно, а система должна сама безопасно завершать промежуточные шаги.

14. Known limitations и честные ограничения

  • game cvar after mod server — известное ограничение, а не скрытый баг.
  • Некоторые applied audio/video states зависят от реального устройства и backend capabilities.
  • Future safe outline intentionally не внедрён в текущий visibility path, потому что это отдельная серьёзная задача.

15. Донорская карта проекта

Приложение A. Технические изменения beta 0.95-a и 0.96

Weapon predict hidden-gun path: player_ent resolver теперь корректно декодирует MODELINDEX_PLAYER + skinnum >> 8 и больше не зависит от cl_vwep. Имена weapon attachments берутся из #-prefixed weapon model configstrings, поэтому режимы cl_gun 0 и cl_gun 1 + hand 2 больше не завязаны на видимость view gun.

Blaster held-fire: локальный ghost path больше не ограничен только rising-edge нажатием. Для бластера используется удерживаемая cadence-модель с тем же интервалом, что и раньше, но без ложных пропусков при зажатой атаке.

win32egl stabilization: EGL init теперь живёт в двухшаговой схеме. Если ANGLE platform display инициализируется, но дальше даёт 0 configs или другой поздний fail, клиент делает полноценный fallback на legacy eglGetDisplay path, а не остаётся с тёмным экраном.

Input/config layer: Alt+F4 вынесен в global Q2PRO-X cvar cl_altf4_exit. Горячая клавиша всё ещё перехватывается централизованно, но теперь поведение можно выключить без ручной правки bind-логики.

16. 0.96: 4:3 pillarbox, resolution picker и fullscreen semantics

Ветка 0.97 закрывает конкретный пользовательский pain point из beta 0.95-a: классический 4:3 fullscreen на современных 16:9/16:10 desktop-сценариях больше не должен зависеть от внешнего NVIDIA scaling, слепого перебора vid_modelist и случайного поведения borderless window.

  • vid_desktop_fullscreen 1 теперь надо понимать как desktop-native presentation path: сам монитор остаётся в текущем desktop mode, а выбранные resolution / refresh используются для content aspect и для выбора подходящего fullscreen mode внутри клиентской логики.
  • vid_desktop_fullscreen 0 остаётся классическим exclusive/fullscreen mode-switch path. В этом режиме Q2PRO-X действительно просит Windows и драйвер переключить дисплей в выбранный видеорежим через старую fullscreen-механику.
  • vid_desktop_fullscreen_fit вводит presentation-rect layer: логическая игровая картинка рисуется в центр окна, а остальная площадь заполняется явными чёрными барами. Это детерминированное клиентское поведение, а не надежда на то, что монитор сам красиво сделает aspect scaling.
  • vid_resolution и vid_refresh живут как глобальные string-picker cvars. Их значения собираются из EnumDisplaySettings, а затем сопоставляются с vid_modelist, чтобы меню и реальный mode backend говорили об одном и том же наборе дисплейных режимов.
  • Startup-sync решает раннюю инициализационную дыру: q2pro-x.cfg исполняется раньше Win_Init, поэтому сохранённые resolution/refresh теперь дополнительно применяются в Win_GetModeList до первого set_mode. Иначе пользователь видел бы сохранённые строки в cvar, но не получал бы нужный режим на первом кадре.
  • Black-bar input rejection завершает feature с точки зрения UX: мышиные клики и колесо за пределами content rect не должны трогать UI-элементы на кромке. Это особенно важно для server browser и mod overlay, где активные зоны плотнее, чем в обычном меню.

16.1. Практическая логика режимов

Для centred 4:3 внутри современного desktop fullscreen правильная комбинация такая: resolution = 800x600 или 1024x768, desktop fullscreen = yes, fullscreen fit = aspect. При этом display mode монитора не меняется, зато content aspect у игры становится строго 4:3.

  • Если пользователю нужен именно настоящий 800x600 fullscreen mode switch, надо отключать desktop fullscreen. Тогда resolution/refresh становятся запросом к реальному видеорежиму, а итоговое масштабирование уже зависит от GPU/монитора.
  • Если цель — просто fullscreen без лишних полос, resolution = desktop + desktop fullscreen = yes + fullscreen fit = fill возвращает пользователя к привычному borderless-native path.
  • Разница между 800x600 и 1024x768 в Q2PRO-X не магическая: это два разных 4:3 content size. Выбор между ними — вопрос визуальной резкости, ретро-feel и производительности, а не вопрос разной логики клиента.

16.2. Почему это важно для beta/release layer

Для beta-дистрибутива это также важная release-story: тестировщику не нужно лезть в чужой q2pro.menu или собирать сторонние скрипты ради старых fullscreen-сценариев. Вся логика теперь живёт в стандартном Q2PRO-X menu/config layer и документируется как часть официального user-facing behaviour.

17. 0.97: OLED protection architecture

OLED-ветка в Q2PRO-X — это не одна опция, а небольшой набор независимых runtime-подсистем поверх существующего рендера. Архитектурно они объединены мастер-cvar vid_oled_enable, но внутри разделены на bar protection, idle full-screen dim и UI alpha protection.

  • Bar protection активируется только там, где действительно есть aspect-fit black bars. То есть обычный full-fill режим не тратит на это логику зря.
  • Idle protection работает поверх всего окна: уровень, HUD, меню, console, modern server browser, loading plaque и pillarbox-области затемняются единым слоем.
  • Cursor suppression привязан не к одному draw-path, а к Windows cursor visibility layer: когда idle-пульс реально активен, системный курсор тоже уходит, а потом восстанавливается по user activity.
  • UI alpha protection не переписывает scr_alpha, cl_serverbrowser_alpha или другие пользовательские cvar. Вместо этого вводится временный render-time multiplier, который мягко домножает итоговую alpha на лету.
  • Pillarbox workspace для laghax HUD и server browser использует уже существующую геометрию aspect-fit presentation, а не отдельную систему координат поверх клиента.

Практический смысл такой декомпозиции: каждая подветка может быть включена или выключена отдельно, а в hot path при vid_oled_enable = 0 остаётся почти нулевой overhead.

18. 0.97: weapon prediction follow-up and accepted limitations

Главный архитектурный итог 0.97 по weapon predict: continuous-fire weapon-view animation не должна предсказываться клиентом вслепую. Для chain/machine/hyperblaster знания о fire-loop и wrap-frame живут в game DLL, а не в клиенте. Поэтому shipping-path intentionally оставляет gun model server-driven, чтобы не рисовать неверные кадры при переходах вроде 11 -> 6.

При этом hyperblaster projectile handoff был реально усилен. Прежняя логика опиралась на EF_HYPERBLASTER и потому пропускала effectless болты из стандартного fire loop. В 0.97 клиент классифицирует свои server HB bolts по модели projectile, проверке recent local burst, corridor/spawn consistency и затем матчится по FIFO seq. После совпадения включается точечное entnum suppression с узким fallback на самый первый кадр.

Это важно как пример общего правила Q2PRO-X: быстрый local feel допускается, пока он не начинает ломать truthfulness картинки. Когда риск неверного поведения выше пользы, клиент сознательно останавливается на documented limitation.

19. 0.97: laghax HUD as a live diagnostic surface

Laghax HUD в 0.97 перестаёт быть только окном про smoothing-window. Теперь это компактная live surface, где отражаются реально включённые predict и physics-параметры. Архитектурно это сделано без ручного кэша меню: overlay собирает состояние непосредственно из текущих cvar и поэтому сразу отражает изменения из Q2PRO-X menu.

  • show weapons & player predicts enabled params — перечисляет только реально включённые weapon/player predict-path.
  • show physics enabled params — всегда показывает movement feel и step smoothing, а legacy predict и fixed move выводит только когда они действительно определяют effective path.
  • pillarbox workspace — переводит координатную базу overlay из gameplay viewport в full presentation area, что даёт корректный drag/hit-test для 4:3 aspect-fit режима.

20. 0.97: step smoothing lift jitter fix

Bugfix по лифтам живёт целиком в predict-layer и не требует правок в entities.c. Корневая проблема была в том, что R1Q2-style stair heuristic видел vertical mover как очередную ступеньку: игрок стоял on ground, origin Z рос, и predicted_step re-arm происходил каждый prediction tick.

В 0.97 добавлен вертикальный mover guard: если pm.groundentity — это движущийся brush-model с ненулевым vertical delta, step-smoothing path для режимов r1q2-1/2/3 принудительно сбрасывает predicted_step carry-over. Mode 0 намеренно не менялся: у него другая additive-семантика, и пользовательский багрепорт был не про него.

С практической точки зрения это один из тех патчей, где Q2PRO-X осознанно отступает от donor-purity. R1Q2-подобный stair feel сохранён, но плохое поведение на lift/mover больше не считается sacred behaviour.

16. Архитектурные обновления beta 0.98 относительно 0.97

Beta 0.98 не меняет базовую layered-модель Q2PRO-X, но добавляет несколько важных уточнений на уровне архитектуры: маршрутизация предикта оружия, display-mode state, runtime audio control, adaptive laghax classification и modern browser Favorites persistence.

16.1. Display mode state: windowed / desktop / exclusive

Вместо старой неявной модели, где vid picker мог незаметно уводить игру в exclusive fullscreen, теперь display mode разведен на два независимых состояния:

  • `vid_windowed` — отвечает за normal resizable window.
  • `vid_fullscreen_type` — хранит предпочтительный fullscreen path (`desktop` / `exclusive`) для случая, когда windowed выключен.

Такое разделение важно не только для меню, но и для корректного bootstrap/reverse-sync поведения. Оно убирает зависимость от случайного состояния legacy picker cvar и делает Alt+Enter предсказуемым переключателем windowed on/off.

16.2. Runtime audio gain вместо грубого mute-переключателя

Для audio inactivity / OLED idle path выбрана правильная архитектура runtime-gain слоя, а не перезапись пользовательских громкостей.

Это позволяет безопасно сочетать `mute when inactive` и `mute audio on idle protect`, а также плавное затухание по OLED idle fade / restore без порчи пользовательских настроек.

16.3. Предикт оружия: новая стабилизированная архитектура

Самая недооценённая, но архитектурно важная часть beta 0.98 — это стабилизация предикта оружия после нескольких beta-review циклов. Здесь важно понимать, что Q2PRO-X больше не пытается `одним механизмом` предсказывать всё подряд. Финальная схема намеренно разделена на четыре слоя.

Такой расклад и есть главное архитектурное изменение: не «больше предикта любой ценой», а предсказание только там, где это устойчиво и не создаёт ложные визуальные состояния.

16.4. Переключение оружия и непрерывная стрельба: почему это теперь работает лучше

Проблема старых итераций состояла в том, что предиктор пытался принять решение о состоянии выстрела слишком рано, когда оружие ещё находилось в фазе switch / weapon-up и сервер не успел подтвердить новый класс оружия. Отсюда возникали ложные выстрелы старого оружия и повреждённая анимация при удержании атаки.

В финальной архитектуре используется phase gate по метаданным (Option E): у каждого vanilla weapon есть описанные границы activate / fire / idle фаз, а ghost fire разрешается только когда authoritative `ps->gunframe` вышел из weapon-up фазы.

Отдельно был принят важный архитектурный компромисс: для непрерывно стреляющего оружия (machinegun / chaingun / hyperblaster) Q2PRO-X не рисует выдуманную client-only gun animation. Анимация view-weapon остаётся серверно-управляемой, а локально предсказываются звук, вспышка, попадания, локальный расход патронов и визуальная обратная связь по снарядам. Это сильно уменьшает риск неверной локальной анимации и делает систему честнее к серверной логике.

16.5. HyperBlaster и rockets: точное сопоставление вместо грубого suppression

HyperBlaster в beta 0.98 больше не живёт по примитивной схеме `спавним локальный bolt и надеемся, что сервер потом как-нибудь совпадёт`. Финальная схема использует classifier `Ghost_IsHBServerCandidate()`, локальное окно недавней очереди, пространственный коридор, FIFO-сопоставление по `seq` и точное `entnum`-совпадение после handoff.

Поверх этого локальная трасса HyperBlaster получила stop-on-hit, локальный эффект удара и suppression дубликатов `TE_BLASTER`, чтобы поток выглядел как единая трасса, а не как два несвязанных источника визуала.

Rocket path тоже стал строже. Предикт больше не должен скрывать чужие ракеты только потому, что у нас есть какой-то локальный paired ghost. Быстрый путь после handoff теперь привязан к конкретному entity: используется точный `entnum`, а не широкое условие `какая-то локальная ракета уже была paired`. Это и есть ключ к безопасному projectile prediction в мультиплеере.

Дополнительно введён runtime reset ghost-state на death / respawn, чтобы локальное владение projectile-объектами не протекало через смену жизненного состояния игрока.

16.6. Laghax: starvation detector hardening

В `cl_laghax 2` усилена классификация low-ping starvation-кейсов. Вместо попытки решать проблему только коэффициентами adaptive model получил два внутренних starvation proxy:

  • receive-cadence starvation score (`rxgap`) — быстрый сигнал по интервалам между приходящими authoritative packet-ами;
  • slow total-loss ratio (`tloss`) — медленный сигнал по общей картине server-to-client потерь.

Ни один новый пользовательский cvar при этом не добавлялся. Для игрока это остаётся тем же `cl_laghax 2`, но с лучшей автоматической реакцией на патологические low-ping packet-loss случаи.

16.7. Server Browser Favorites: composite persistence model

Favorites в modern browser пришлось делать с оглядкой на существующую composite-source модель, где одновременно участвуют:

  • `favorites://` → legacy Address Book `adr0..adr15`
  • `file:///servers.lst`
  • `broadcast://` как transient source

Поэтому add-path пишет только в `servers.lst`, а remove-path обязан чистить и `servers.lst`, и совпадающие `adrN`, иначе удалённый сервер немедленно вернётся через вторую половину composite-source.

Отдельно была закрыта Windows-специфичная проблема с двойной текстовой трансляцией line endings при rewrite `servers.lst`: финальный код теперь работает через normalized read + raw write, чтобы не получать `CR-CR-LF` corruption.

16.8. UI correctness: single-predicate visibility for Favorites action

В процессе review выяснилось, что Favorites action button в modern browser мог оказаться невидимым, но всё ещё доступным через stale hit-rect или keyboard focus.

Финальная версия beta 0.98 использует один общий predicate (`fav_drawn`) для draw, mouse hit-testing, keyboard activation и Tab traversal. Это маленькое, но важное правило UI-целостности: скрытая кнопка не должна оставаться интерактивной.

Обновления 0.99 (архитектура)