Закрыты BUG-GRAB-1 и BUG-GATEMOD-1; BUG-SPIKE-1 — в низкоприоритетные
Оба фикса подтверждены игрой, записи с разбором корней переехали в bug_closed.md. BUG-GATE-PASS-1 остался ждать сценария, но его оговорка про BUG-GATEMOD-1 обновлена (тот закрыт). BUG-SPIKE-1 понижен до низкого приоритета: маловоспроизводим, смертельность пик подтверждена замером. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,152 @@
|
||||
|
||||
---
|
||||
|
||||
## BUG-GRAB-1. Прыжок с места через провал в 3 тайла: зацепа нет — **ЗАКРЫТ 2026-08-05**
|
||||
|
||||
**Проверено в игре (пользователь):** «зацеп работает». Физика была верна с
|
||||
самого начала, чинить пришлось клавиатуру — [BUG-KBD-5](#bug-kbd-5).
|
||||
|
||||
> **Итог 2026-08-05.** Физика тут ни при чём — виновата клавиатура.
|
||||
> Зажатый Shift снимался автоповтором зажатой стрелки, поэтому к кадрам
|
||||
> 102…106 (окно зацепа) движок видел Shift отпущенным. Полный разбор и
|
||||
> фикс — [BUG-KBD-5](bug_closed.md#bug-kbd-5); поведение Shift в MAME
|
||||
> проверено замером карты `_kbdraw_down`. Осталось подтвердить сам зацеп
|
||||
> живой игрой; версии 2 и 3 ниже проверять только если он всё ещё не выйдет.
|
||||
|
||||
|
||||
**Симптом.** Уровень 2, комната 9. Перепрыгнув на (1,1), Кид должен
|
||||
вернуться обратно: разбегаться негде, поэтому он встаёт на самый край
|
||||
плиты, прыгает с места и **цепляется руками за (1,5)**, после чего
|
||||
подтягивается. У нас Кид с зажатым Shift всё равно срывается.
|
||||
|
||||
**Что уже точно известно (и не надо перепроверять).**
|
||||
|
||||
1. **Физика прыжка у нас совпадает с оригиналом кадр в кадр.** Сверено по
|
||||
логу SDLPoP против трассы харнесса при одинаковом старте `x=95`:
|
||||
|
||||
```
|
||||
кадр 16 18 22 23 24 25 102 103 104 105
|
||||
SDLPoP 95 97 105 112 121 126 128 130 131 133
|
||||
наш 95 97 105 112 121 126 128 130 131 133
|
||||
```
|
||||
Совпадает и по `y`, и по колонке/ряду, и по приземлению на 107–108.
|
||||
|
||||
2. **В оригинале зацеп срабатывает на кадре 106, а не 102..105.**
|
||||
`check_grab` зовётся из ДВУХ мест: ветка «в воздухе» в `check_action`
|
||||
(кадры 102..105) и `do_fall` (seg005) для `actions_4_in_freefall`.
|
||||
Успешная попытка из лога:
|
||||
|
||||
```
|
||||
GRAB try f=106 x=135 y=166 col=4 row=2 fall_y=18
|
||||
GRAB probe x=127 col=4 through=0 front_above=3 modif=0
|
||||
GRAB can_grab=1
|
||||
GRAB OK dist=9
|
||||
-> f=91 x=136 y=181 col=5 row=2 act=2 (повис)
|
||||
```
|
||||
Наш `do_fall` (`pop_map.c`) `check_grab()` из этой ветки тоже зовёт —
|
||||
то есть структура на месте, расходится что-то внутри.
|
||||
|
||||
3. **По харнессу зацеп у нас РАБОТАЕТ**: окно стартовых `x = 91…95`, и
|
||||
короткий шаг ставит Кида ровно туда (91 после первого нажатия, 95 после
|
||||
второго). Зафиксировано тестом `t_grab`.
|
||||
|
||||
**Отсюда главный вопрос был: почему харнесс говорит «работает», а живая
|
||||
машина — «нет».** Расхождение между ними и оказалось уликой; версии
|
||||
выдвигались по убыванию правдоподобия, и сработала первая:
|
||||
|
||||
- **Shift не доезжает до движка — ПОДТВЕРЖДЕНО, это и была причина.**
|
||||
Харнесс подменяет клавиатуру и потому этот путь не проверяет вовсе, а у
|
||||
нас есть история проблем ровно с «Shift + стрелки» (KBD-1, BUG-KBD-3/4).
|
||||
Замер в MAME: при зажатом Shift и зажатой стрелке бит `LSh` в
|
||||
`_kbdraw_down` стоял в нуле. Разбор — [BUG-KBD-5](bug_closed.md#bug-kbd-5).
|
||||
- **Сцена харнесса не равна комнате 9.** Там изолированная комната
|
||||
(соседи — стена), а в игре слева комната 8; кромки шва участвуют в
|
||||
`get_tile`. Проверять чтением `Kid.x` в момент прыжка: попал ли он в
|
||||
окно 91…95 вообще.
|
||||
- **Расхождение в `check_grab`.** Наш вариант зовёт `determine_col()`
|
||||
там, где оригинал зовёт `load_fram_det_col()` (перезагрузка кадра +
|
||||
колонка). Для Кида это обычно одно и то же (`cur_frame` в фазе физики
|
||||
принадлежит ему), но проверить стоит.
|
||||
|
||||
**Инструменты готовы.** В SDLPoP включена отладка (пометка `DBG-GRAB`):
|
||||
`JMP` — покадровая трасса прыжка/падения/виса, `GRAB try|probe|fail|OK` —
|
||||
вход в `check_grab` и причина отказа. Снимается поиском по `DBG-GRAB`.
|
||||
|
||||
**Найдено попутно, отдельным наблюдением.** После касания площадки на
|
||||
кадрах 107–108 (x=140) оба движка снова падают, но X расходится: SDLPoP
|
||||
уводит Кида на 134 (колонка 4), мы — на 141 (колонка 5). Похоже на разную
|
||||
отработку `in_wall()` у стены (2,7). На зацеп не влияет.
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## BUG-GATEMOD-1. Ворота стартуют закрытыми, хотя в уровне открыты — **ЗАКРЫТ 2026-08-05**
|
||||
|
||||
**Проверено в игре (пользователь).**
|
||||
|
||||
**Симптом (пользователь, 2026-08-04).** Уровень 2, комната 13: решётка
|
||||
между (2,5) и (2,6) обязана быть ОТКРЫТА в начале и захлопнуться, когда Кид
|
||||
нажмёт кнопку (2,4) — после этого назад дороги нет. У нас она закрыта
|
||||
сразу, кнопка бессмысленна, проход не работает.
|
||||
|
||||
**Корень.** Модификатор тайла в ФАЙЛЕ уровня и модификатор в РАНТАЙМЕ —
|
||||
разные величины; оригинал переводит их при загрузке в `load_alter_mod`
|
||||
(seg008:198E), которую зовёт `alter_mods_allrm` из `load_level`:
|
||||
|
||||
```c
|
||||
case tiles_4_gate: *modif = (*modif == 1) ? 188 : 0; break;
|
||||
case tiles_11_loose:*modif = 0; break;
|
||||
case tiles_10_potion:*modif <<= 3; break;
|
||||
```
|
||||
|
||||
Наш `pop_trob_modif` портировал из неё **только зелье**. Для ворот
|
||||
`bg = 1` — это «открыты» (Table 8 спецификации DAT), а в рантайме открытость
|
||||
измеряется высотой подъёма 0..188; мы клали в рантайм-модификатор сырую
|
||||
единицу, то есть «закрыты на 1/188».
|
||||
|
||||
**Фикс.** Ветки ворот и loose дописаны в ленивую инициализацию
|
||||
`pop_trob_modif` (`pop_trob.c`). Ветка СТЕН не портируется намеренно: у нас
|
||||
`pop_bg` считает связи кладки по типам соседей прямо при отрисовке
|
||||
(`wall_modifier`), сохранённый модификатор стены не читается.
|
||||
|
||||
**Что это ещё задевает.** Решётка (0,9) комнаты 5 уровня 1 тоже имеет
|
||||
`bg = 1`, то есть обязана стартовать открытой — Кид сваливается в комнату 1
|
||||
именно через неё, и она захлопывается у него за спиной. Закрывает её
|
||||
стартовый триггер `do_startpos` (seg003:167): для уровней с
|
||||
`tbl_entry_pose == 1` оригинал ВИРТУАЛЬНО ЖМЁТ кнопку комнаты 5 (0,2) —
|
||||
|
||||
```c
|
||||
// Special event: press button + falling entry
|
||||
get_tile(5, 2, 0); trigger_button(0, 0, -1); seqtbl_offset_char(seq_7_fall);
|
||||
```
|
||||
|
||||
Замер в SDLPoP (лог по кадрам): `gate(5,0,9)` идёт `188 → 148 → 88 → 8 → 0`,
|
||||
шаги 40/60/80 — это `gate_close_speeds`, то есть быстрое закрытие
|
||||
(`trigger_gate` вернул тип 3). У нас этот триггер портирован, и закрытие
|
||||
работает.
|
||||
|
||||
Полный список ворот с `bg = 1`: ур. 1 комн. 5 (0,9); ур. 2 комн. 13 (1,5).
|
||||
Остальные ворота уровней 1–3 имеют `bg = 2` → 0, и для них ничего не
|
||||
меняется (при модификаторе 2 и 0 и отрисовка, и `can_bump_into_gate` дают
|
||||
одно и то же).
|
||||
|
||||
**Побочная находка: чит обхода комнат отматывал мир.** После фикса
|
||||
пользователь увидел «ворота снова открылись», пройдя `+` в комнату 2 и `-`
|
||||
обратно. Причина не в воротах: `ROOMNAV` звал `pop_trob_reset()` перед
|
||||
`enter_room`, тот обнулял `room_seen[]`, и `pop_trob_modif()` перечитывал
|
||||
модификаторы из уровня заново — то есть чит откатывал открытые/закрытые
|
||||
ворота, выдвинутые пики и нажатые кнопки. Пока ворота с `bg=1` ошибочно
|
||||
стартовали закрытыми, откат был не виден. `pop_trob_reset()` из навигации
|
||||
убран: она обязана только телепортировать, исходное состояние даёт
|
||||
перезапуск уровня. Замер, который это показал: `room_modif` комнаты 5
|
||||
после `+`/`-` = `00 00 0B 00 09 00 08 01 00 BC` — последний байт 0xBC = 188,
|
||||
файловое значение.
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## BUG-GUARD-DEAF-1. Страж не оборачивался на вернувшегося Кида — **ЗАКРЫТ 2026-08-05**
|
||||
|
||||
**Наблюдение (пользователь, 2026-08-05).** Уровень 2, комната 11, идёт бой
|
||||
|
||||
Reference in New Issue
Block a user