SprPoP: падение сквозь стену больше не проходит
Портировано опциональное исправление SDLPoP (fix_glide_through_wall, seg005 в do_fall). В ванили персонаж, падающий после разворота в беге, может оказаться внутри кладки и лететь «в стене» — баг оригинала, воспроизведённый пользователем в игре и затем на host-тесте. Решением 2026-08-31 фикс взят в ТЕКУЩИЙ билд: играбельность важнее буквальности. Реализация вынесена отдельной функцией glide_through_wall_guard() в pop_map.c намеренно — при разделении VANILLA/ENHANCED это готовая точка отвязки, достаточно не звать её в ванильном режиме. ПРОВЕРКА. Набор t_wall был заранее написан так, чтобы сторожить ЧИСЛО заходов в кладку: до фикса их было ровно два из четырнадцати стартовых позиций, после — ноль. Остальные 15 наборов (в том числе phys с 1733 проверками и grab) остались зелёными. Живая проверка в MAME пользователем: корректно. Ожидание в тесте обновлено ОСОЗНАННО, прежнее число сохранено рядом отдельной константой с пометкой «сколько было до фикса»: оно измерено, и понадобится, когда появится режим VANILLA — там ожидание станет зависеть от режима. ЦЕНА: +57 байт в банке 3 (свободно 3043), резидент и куча не изменились. По скорости попадание только на кадры падения: пересчёт колонки — одно деление, дистанция до кромки считается лишь если персонаж действительно внутри кладки. Документы: в аудите находка 21 переведена в «портировано» с сохранением исходного разбора; в vanilla_vs_bugfixed статус фикса стал ВЗЯТ, сводка пересчитана (5 взято, 32 кандидата в ENHANCED). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011MsUsEFAQfsjjQpJ7RtKVY
This commit is contained in:
@@ -898,6 +898,40 @@ static uint8_t check_grab_run_jump(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* НЕ ДАТЬ ПРОЛЕТЕТЬ СКВОЗЬ СТЕНУ В ПАДЕНИИ.
|
||||
*
|
||||
* Порт опционального исправления SDLPoP (fix_glide_through_wall, seg005 в
|
||||
* do_fall). В ванили personаж, падающий после разворота в беге, может
|
||||
* оказаться внутри кладки и лететь «в стене» — баг оригинала, известный и
|
||||
* воспроизводимый; у нас он ловится host-тестом (tests/host/t_wall.c,
|
||||
* набор wall_stops_jump_from_left_side).
|
||||
*
|
||||
* ВЗЯТО В ТЕКУЩИЙ БИЛД по решению 2026-08-31: играбельность важнее
|
||||
* буквальности. При разделении VANILLA/ENHANCED эта функция — готовая
|
||||
* точка отвязки: достаточно не звать её в ванильном режиме
|
||||
* (docs/vanilla_vs_bugfixed.md).
|
||||
*
|
||||
* Условие оригинала: персонаж внутри тайла стены, либо внутри верха двери
|
||||
* (в обоих вариантах) при движении ВЛЕВО. Порог 8 и сдвиг на 15 назад —
|
||||
* из исправления; они выбраны так, чтобы вытолкнуть на ту же дистанцию,
|
||||
* что даёт выталкивание из стены при приземлении. Горизонтальную
|
||||
* скорость гасим: иначе следующий кадр внесёт персонажа обратно. */
|
||||
static void glide_through_wall_guard(void)
|
||||
{
|
||||
uint8_t t;
|
||||
int d;
|
||||
|
||||
determine_col();
|
||||
t = get_tile_at_char();
|
||||
if (t != TILE_WALL &&
|
||||
!((t == TILE_DOORTOP || t == TILE_DOORTOP_FLOOR) && Char.direction < 0))
|
||||
return;
|
||||
d = distance_to_edge_weight();
|
||||
if (d < 8) return;
|
||||
Char.x = (uint8_t)char_dx_forward((int8_t)(d - 15));
|
||||
Char.fall_x = 0;
|
||||
}
|
||||
|
||||
static void do_fall(void)
|
||||
{
|
||||
uint8_t nrow = (uint8_t)(Char.curr_row + 1);
|
||||
@@ -908,6 +942,7 @@ static void do_fall(void)
|
||||
if (nrow > 4) nrow = 4; /* защита pop_y_land[] от выхода */
|
||||
if ((uint16_t)pop_y_land[nrow] > (uint16_t)Char.y) {
|
||||
check_grab(); /* ещё летит — попытка зацепа */
|
||||
glide_through_wall_guard(); /* и не сквозь кладку (см. выше) */
|
||||
} else if (Char.curr_row <= 2) {
|
||||
if (get_tile_at_char() == TILE_WALL)
|
||||
in_wall();
|
||||
|
||||
Reference in New Issue
Block a user