План модуля «control-fix» — регрессия управления на старте (1.0.0)
Внутренний документ. Контракты — docs/contracts/control-fix.md, журнал — docs/archive/plan/control-fix-progress.md. Ветка feature/control-fix, копия ~/deltaplan-control-fix (от main 3820bda = v1.0.0).
Цель
Жалоба пилота на 1.0.0 (по смыслу): «что-то с управлением изменилось. Когда включаю игру, он сам начинает полёт — разбежаться не получается, ручку подтянуть, исправить крен на старте не получается… заваливается в крыло, падает. Мышью не корректирует положение носа и крена».
Симптомы:
- На старте аппарат сам начинает движение/полёт без действия пилота (нет фазы стояния и разбега).
- Нельзя подтянуть ручку / выровнять крен на старте — крыло валится, срыв.
- Мышь не меняет тангаж и крен (на земле и/или в воздухе).
Найти причину (коммит, файл:строка) с доказательством, исправить у причины, добавить регрессионные тесты. В main не вливаем — шлюз главной сессии.
Решения пользователя (не обсуждаются)
Действуют решения модуля start-fixes (docs/archive/plan/start-fixes.md, «Решения пользователя», п. 3): стоя пилот вертикален, A/D на земле — только курс (крыло не кренят), крен держит «рука пилота» с ограниченной силой ∝ доле веса на ногах; опасность учит последствием, без подсказок. Если причина регрессии — в самих этих решениях, это шлюз (варианты пользователю), а не правка исполнителем.
Решения пользователя модуля (01.10, шлюз «управление крылом на земле»)
- Вариант В «гибрид»: стоя и шагом — как сейчас (W/S — шаг, A/D — поворот на месте), крылом (нос и крен) управляют стрелки, мышь, стик. С зажатым Shift (разбег) W/S, A/D, стрелки и мышь управляют носом и креном крыла как в воздухе; курс на бегу — от крена крыла (дуга). Защёлку клавиш при отрыве убрать. Это отменяет в start-fixes п. 3 «стоит — только поворот» и «A/D на бегу заворачивают по дуге» в части крыла: крыло на земле кренит пилот; «рука пилота» с ограниченной силой ∝ доле веса на ногах остаётся.
- Мышь по умолчанию — «трапеция» (
bar); осмотреться — с зажатой правой кнопкой. - Мышь и клавиши «трапеции» — те же действия ввода, что в полёте; знак клавиш задаёт только карта ввода (раскладка W — от себя — модуль feature/ui-controls).
- Никаких фиксированных времён старта и взлёта (01.10, по отзыву пилота «на взлёт дано 2 с»): отрыв — только физика (L ≥ W от воздушной скорости: бег + ветер); в штиль бежать можно сколько нужно; без бега и ветра отрыва нет. Все таймеры, задержки, мин./макс. длительности фаз «стоит → бег → отрыв → полёт», защита после отрыва, таймеры автопилота/ботов на земле, подготовка/таймауты старта — заменить физическими условиями (силы, скорость, контакт, геометрия). Технически нужное (антидребезг контакта в 1–2 шага физики) — с обоснованием. Тест: время отрыва разное на разных склонах и ветрах и определяется только физикой.
Что известно до запуска (координатор, 01.10)
- С v0.8.0 (0ac895d) до v1.0.0 в полёте/земле менялись: SF-3 «рука пилота» (800b84e, 3384aa8, 5f8990e) —
GroundRun._ground_bankзаменён динамикой крена, A/D больше не кренят крыло, срывcrosswindпроверяется и стоя (до разбега); SF-4 (3707069) — тангаж стоя от направления склона; паспорта крыльев (4200e0f — масса и др. в конфигах), новые крылья; модель воздуха AM-04…AM-09 (поле ветра у старта, рывки и обратный поток за гребнем — 0d1ecf2); отладочные слои F1/F2/F5/F6 и аддоны Debug Draw 3D / Debug Menu (fffc741, 67dc73a). scripts/game/input_controller.gdс v0.8.0 не менялся. Мышь по умолчанию — режимlook(голова),bar— запасной; на земле (_update_ground) мышь не используется вовсе. Ввод мыши — через_unhandled_input(может съедаться GUI сmouse_filter = STOP).
Задачи (одна волна, параллельно)
| Задача | Что | Тип | Оценка |
|---|---|---|---|
| CF-1 | Старт с земли: «сам начинает полёт», крен валится — причина, исправление, регрессия | dp-engineer | 0,5–1 дн |
| CF-2 | Мышь не управляет тангажом/креном — причина, исправление, регрессия | dp-engineer | 0,5 дн |
CF-1. Старт с земли
- Скоуп: воспроизвести headless в условиях игры по умолчанию (
FlightSettings.defaults(): локация, крыло, ветер «встречный на старте», прогноз; поле воздуха как в игре —AirRuntime/WindFieldу старта, а не штиль), без ввода: что происходит (фаза, скорость,feet_load,wind_moment_nm,hold_limit_nm, крен, α, причина срыва/отрыва) по времени. Сравнить с v0.8.0 и промежуточными коммитами (bisect: 800b84e, 3707069, 5f8990e, 4200e0f, 0d1ecf2 и т. п.). Найти коммит и строку. Исправить у причины, физически обоснованно. - Ключевые файлы:
scripts/flight/ground_run.gd,scripts/flight/flight_model.gd(стык GROUND→AIR),configs/flight.json,configs/pilot.json, конфиги крыльев (если причина в паспортах),scripts/game/game.gd(спавн, только при доказанной причине),tests/flight/. - Не трогать:
scripts/game/input_controller.gd, UI, отладочные слои (CF-2) — нужна правка там → через координатора. - Приёмка (headless):
- Отчёт о причине: коммит, файл:строка, числа «до/после» (таблица по времени для v0.8.0, v1.0.0 и исправления).
- Тест: на старте по умолчанию (локация, крыло, ветер и поле воздуха как в игре) без ввода 10 с — аппарат стоит: не отрывается (
TOOK_OFFнет), не срывается (FAILEDнет), |крен| < 3°, смещение < 1 м. - Тест: разбег (run) с нейтральной, подтянутой и отданной трапецией на том же старте — нейтральная отрывается; на себя/от себя — разное время/исход как по физике (числа в отчёте); крен на разбеге при встречном ветре < 3°.
- Условия приёмки SF-3 (
docs/archive/plan/start-fixes.md, SF-3 п. 1–6) не сломаны. --filter=flight,--filter=game,--filter=start_,--filter=contracts— зелёные (известные падения под нагрузкой иtest_headwind_launchatlas — назвать отдельно).
- Шлюз: если устранение причины противоречит решениям пользователя start-fixes (A/D не кренят, предел руки, срыв стоя) — остановиться, вернуть варианты координатору.
CF-2. Мышь
- Скоуп: проследить путь мыши в игре (сцена полёта, не только
InputControllerв тесте): захват курсора при старте (capture_on_start), режим (look/bar) по умолчанию и изuser://configs/controls.json, доставкаInputEventMouseMotionв_unhandled_input(кто съедает: новые Control отладочных слоёв, аддон Debug Menu, объекты мира, меню), фазы земля/воздух. Сравнить с v0.8.0. Воспроизвести headless (Input.parse_input_eventв загруженной сцене полёта), исправить у причины. - Ключевые файлы:
scripts/game/input_controller.gd,scripts/game/debug_overlays.gd,scripts/game/game.gd(захват мыши),scripts/ui/*,addons/(только настройка, не код аддона),configs/controls.json,tests/game/. - Не трогать:
scripts/flight/*,configs/flight.json,configs/pilot.json(CF-1). - Приёмка (headless):
- Отчёт о причине: коммит, файл:строка (или «регрессии в коде нет» с доказательством — тогда что видит пилот и почему).
- Тест: в сцене полёта с захваченной мышью в режиме
barдвижение мыши меняетControlInput.pitch/rollи тангаж/крен модели в воздухе (знак по контракту С1); события мыши доходят доInputControllerпри всех слоях интерфейса полёта по умолчанию. --filter=game,--filter=ui,--filter=contracts— зелёные.
- Шлюз: если мышь на земле (нос/крен) никогда не работала и её надо добавить — это новое поведение, развилка для пользователя через координатора.
CF-3. Управление крылом на земле (вариант В) — после CF-1
- Скоуп: реализовать С1 v2, С2 v2, К3 v3 (
docs/contracts/control-fix.md): полеControlInput.turn; на землеpitch— нос крыла,roll— заданный крен крыла «рукой пилота» (стоя, шагом, на бегу); стоя/шагом — крыло стрелками, мышью (bar), стиком, W/S — шаг, A/D — поворот на месте (turn); Shift — разбег (без W), на бегу W/S, A/D, стрелки, мышь — нос и крен как в воздухе, курс — от крена крыла; убрать защёлку отрыва; мышь по умолчаниюbar. Боты/автопилот/сеть — перевести на новый смысл полей. Физика: заданный крен, предел руки, дуга от крена — с обоснованием вdocs/guide/flight.md; экран «Управление» и подсказки клавиш — по новой раскладке. - Ключевые файлы:
scripts/core/control_input.gd,scripts/game/input_controller.gd,scripts/flight/ground_run.gd,configs/controls.json,configs/pilot.json,configs/flight.json → ground_bank, автопилот/боты (autopilot.gd,bot_pilot.gd),scripts/ui/controls_screen.gd, локали,docs/guide/flight.md,docs/guide/game.md, тесты. - Приёмка (headless):
- Стоя (штиль и 6 м/с встречный, «Славутич» и «спорт»): ↑/↓, мышь — нос меняется на полный ход (α числами), ←/→, мышь — крен крыла меняется к заданному (числа), W/S — шаг, A/D — поворот на месте без крена крыла.
- На бегу: W/S/стрелки/мышь — нос, A/D/стрелки/мышь — крен; курс — дугой от крена, |боковое ускорение| ≤
turn_accel_max_ms2; без ввода крена — прямо. - Отрыв без скачка трапеции и крена (|Δpitch|, |Δroll| за шаг ≈ 0), защёлки нет.
- Разбег 0/3/6/10 м/с × советское/учебное/спортивное крыло с разумным вводом — исход и длина разбега (таблица); 6 м/с «Славутич» — взлёт.
- Контрактный тест С1 v2/С2 v2/К3 v3,
--filter=flight,game,ui,start_,contracts, боты — зелёные.
Риски
- Причина в поле ветра у старта (модель воздуха) — тогда исправление вне модуля; шлюз.
- Профиль пилота
user://недоступен: что у него в настройках (режим мыши), неизвестно — вопрос пилоту через главную сессию.