Разбор порядка отрисовки падающей плиты: найден корень, выбран вариант B

СИМПТОМ (пользователь, ур.11 к.14).  Кусок, отвалившийся от плиты нижнего
ряда, рисуется ПОВЕРХ соседней трясущейся плиты; при этом передний торец
соседа лежит поверх куска — порядок противоречив в разных частях
перекрытия.

КОРЕНЬ.  draw_mob (seg007:13E5) считает ряд объекта как
y_to_row_mod4(y) = (y+60)/63 % 4 - 1.  Из-за % 4 ряд 3 (кусок ушёл ниже
комнаты) и ряд −1 (кусок у потолка) дают ОДНО значение −1.  Оригинал
прогоняет его через get_tilepos -> get_tilepos_nominus и получает тайл 30,
а объекты с тайлом 30 рисуются в redraw_needed_tiles ПЕРВЫМИ, до всего
обхода тайлов.  Мы же передаём сырой −1 в мид-оверлей как «тайл объекта», и
гейт `row > pop_bg_obj_row` читает его как «объект в последнем ряду обхода»,
то есть «объект поверх всего», и отбрасывает возврат соседа.  Один и тот же
−1 у нас значит «сверху», у оригинала — «снизу».

Торец при этом виден потому, что приходит из ДРУГОГО слоя: draw_loose кладёт
loose_fram_bottom в backtable и foretable, минуя ptr_add_table, — тело плиты
обязан вернуть мид-оверлей, а его и выключает гейт.

ЧТО ПРОВЕРЕНО ЗАМЕРОМ (журнал решений в pop_dbg_ovl/pop_dbg_pass, зонды
ВРЕМЕННЫЕ и будут сняты):
 - на застывшем кадре: слот draw_y=194, r=−1, rt=2, оверлей позван, внутри
   отбрасывается гейтом;
 - пропуск оверлея на последнем кадре полёта ЗАКОНЕН: габарит куска уже
   ниже габарита тайла, перекрывать нечего;
 - в 13/23 кусок перекрывают 2-4 тайла (накопленно за полёт), включая СВОЮ
   клетку, — то есть «сосед справа» покрытие не исчерпывает;
 - перерисовок тайлов за кадр в 13/23: максимум 6, в покое 0.

ТУПИКИ, чтобы не ходить второй раз.  Клип объекта тут ни при чём:
add_mob_to_objtable ставит clip.right = 40, но клип применяется только при
chtab_flip_clip[chtab_id], а для chtab_6_environment там 0 — поле
игнорируется и в оригинале.  Пункт MOB-CLIP-RIGHT закрывается как
несуществующий.  Добавлять торец плиты в мид-оверлей тоже не надо: в
foretable он уже кладётся из fore_tile.

ВЫБРАН ВАРИАНТ B: классифицировать ряд объекта (вне 0..2 = корзина 30),
отдавать оверлею ориентир «раньше любого тайла» и расширить набор
перекрываемых тайлов на СВОЮ клетку.  Переносить проход отрисовки не нужно —
heal при этом не участвует, работа та же (оверлей = два блита в окне клипа),
разница с узким вариантом A всего один-два оверлея на кусок.

Заодно записана ОБЯЗАТЕЛЬНАЯ задача HEAL-WIDTH: ширины точечных heal'ов
взяты по клеткам (64), а фактический след плиты — 58/57 (замерено по
атласам: верх 32, правая грань 26 в подземелье и 25 во дворце).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 22:51:00 +03:00
parent cdac5746ac
commit 272cf8f195
6 changed files with 114 additions and 17 deletions
+4 -14
View File
@@ -781,20 +781,10 @@ static void overlay_mid_tile(int row, int col)
} else if (t->bottom_id) {
pop_env_b(t->bottom_id, x, dby);
}
/* draw_loose(0) — ПЕРЕДНИЙ ТОРЕЦ плиты, последний вызов draw_tile2
* (seg008: draw_tile_right, draw_tile_anim_right, draw_tile_base,
* draw_tile_anim, draw_tile_bottom, draw_loose). У loose в
* pop_tile_table bottom_id = 0, поэтому ветка выше его НЕ рисует, и в
* оверлее торца не было вовсе: падающий кусок оставался ПОВЕРХ торца
* соседней плиты (найдено пользователем 2026-08-18, ур.11 к.14 —
* трясущаяся плита (2,6) и кусок, отвалившийся от (2,5)).
*
* Кадр берётся по ЖИВОМУ modif, как и верх плиты выше: оверлей рисуется
* поверх уже готовой картинки, и дрожащая плита обязана остаться
* дрожащей. */
if (code == 11 && row >= 0)
pop_env_b(POP_LOOSE_FRAM_BOTTOM[pop_loose_frame(pop_loose_modif[row * 10 + col])],
x, dby);
/* draw_loose тут НЕТ, и это не забывчивость: в оригинале (seg008
* draw_loose) нижняя грань плиты идёт в add_backtable + add_foretable,
* мимо ptr_add_table — то есть в midtable не попадает никогда. Перекрыть
* ею падающий кусок должен ПЕРЕДНИЙ слой (fore_only_tile), а не оверлей. */
}
/* draw_tile_fore (seg008:690) — ТОЛЬКО передний слой (add_foretable): он