Кнопка в ШВЕ срабатывала как чужая связь (нашёл пользователь на ур. 5)

Симптом: Кид встаёт на плиту, которая физически в СОСЕДНЕЙ комнате (стоя в
шве, curr_col = −1), и вместо одних ворот открываются двое — на уровне 5
плита комнаты 11 открывала и нижние ворота комнаты 24, и верхние, хотя
связана только с нижними.

Причина.  check_press читал тайл через get_tile (тот резолвит шов в
соседнюю комнату), а комнату и tilepos для trigger_button брал из
координат персонажа: (своя комната, row*10 + curr_col).  При curr_col = −1
это tilepos 9 СВОЕЙ комнаты — там стена с bg = 0, то есть индекс цепочки
LINKLOC 0.  Цепочка от нуля в данных уровня 5 ведёт на ДВА тайла: нижние
ворота (link[0], next=1) и верхние (link[1]) — ровно то, что наблюдалось.
Настоящая кнопка имеет индекс 9 и одну цель.

В оригинале этого нет по построению: get_tile зовёт find_room_of_tile
(seg006:005D) и ПЕРЕСТАВЛЯЕТ curr_room/curr_tilepos, а trigger_button
работает уже с ними.  У нас резолв комнаты жил только внутри get_tile, а
наружу не отдавался.

Фикс: tile_room_of(col,row) — комната и tilepos клетки с учётом швов (по
образцу gate_modif, который так делал давно), check_press зовёт
trigger_button с резолвнутыми room/tilepos.  Ветка loose там же оставлена
на координатах персонажа: make_loose_fall работает с g_fg своей комнаты.

Два других вызова trigger_button (зацеп за кромку, севшая на кнопку плита)
правки не требуют — оба ограничены колонками 0..9 своей комнаты.

Заведён GATE-FORE-KID (BUGS_OPEN.md): Кид, стоящий В ПРОЁМЕ ворот, виден
поверх решётки — у нас портирован только шовный случай окклюзии, а
draw_tile_fore (seg008:0D15) рисует решётку поверх персонажа и внутри
комнаты.  Чинить в fore-слое отдельно, он горячий.

tests-host 5/5, make size-check OK.  Банк 3: 10648 -> 10828 Б.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 17:32:11 +03:00
parent 8dc53e6b57
commit 36a60f54ba
2 changed files with 73 additions and 4 deletions
+43
View File
@@ -14,6 +14,7 @@
| ID | что | тип | статус |
|----|-----|-----|--------|
| [GATE-FORE-KID](#gate-fore-kid) | Кид в проёме ворот виден поверх решётки | окклюзия | открыт: портирован только шовный случай |
| [FORE-DUP](#fore-dup) | передний слой тайла рисуется дважды при перекрытии объектов | оптимизация | открыт: **сначала замерить**, потом чинить |
| [DIED-ON-BUTTON](#died-on-button) | `died_on_button` (seg007:776) не портирован | порт | открыт |
| [TORCH-ANIM-RIGHT](#torch-anim-right) | под запечённым пламенем застывают не только челюсти чомпера | **низкий** | открыт: на уровнях 1-4 такого соседства нет |
@@ -335,3 +336,45 @@ for (tile_row = x_top_row; tile_row <= char_bottom_row; ++tile_row)
Если дубль мал — оставить как есть и закрыть запись.
---
---
<a id="gate-fore-kid"></a>
## GATE-FORE-KID. Кид, стоящий В ПРОЁМЕ ворот, виден ПОВЕРХ решётки
Нашёл пользователь 2026-08-11 (уровень 5, комната 24, верхние ворота):
Кид стоит на тайле ворот, а решётка рисуется ПОД ним — он виден целиком,
хотя должен быть за прутьями.
**Как в оригинале.** `draw_tile_fore` (seg008:0D15) первой же строкой:
```c
if (tile_left == tiles_4_gate && Kid.curr_row == drawn_row &&
Kid.curr_col == drawn_col - 1 && Kid.room != room_R) {
draw_gate_fore();
}
```
то есть когда Кид стоит ИМЕННО на тайле ворот, их решётка дорисовывается
в **foretable** — поверх персонажа: `draw_gate_fore` (seg008) кладёт спрайт
51 (низ решётки) и дальше вверх кусками по 8 px спрайтом 52, до
`gate_top_y`, прозрачным блитом.
**Что есть у нас.** Портирован только ШОВНЫЙ случай (`pop_bg.c`,
`pop_fore_over_char`): если футпринт зашёл за левый шов и у соседа слева в
этом ряду ворота — их бары перерисовываются поверх персонажа через
`draw_gate_back`. Случая «ворота ВНУТРИ комнаты, персонаж на их тайле»
нет вовсе, отсюда симптом.
**Почему не чинится одной строкой.** Правка идёт в `pop_fore_over_char`
самый горячий путь кадра (memory `pop_fore_layer_cost`: когда-то 78 %
кадра, окно клипа дало 3.2×). Добавлять проверку надо так, чтобы она не
стоила ничего на каждом тайле футпринта: условие дешёвое (`тайл под
персонажем == ворота`), но рисование — это ещё один блит на кадр, пока
Кид стоит в проёме. Плюс нужен свой расчёт полосы (`gate_top_y` по
живому openness), а не готовый `draw_gate_back`, который рисует ЗА
персонажем.
**Проверять:** уровень 5, комната 24 — встать в проём верхних ворот
(колонка 1 ряда 0) при частично поднятой решётке; прутья должны
перекрывать Кида. Тот же случай — любые ворота на уровнях 1-3.