Залипший блеск меча: trob_drawn обнулялся, а комната рисовалась по живому modif
Найдено пользователем (2026-08-17, уровень 1 комната 15): при входе в комнату
блеск меча иногда горит несколько секунд вместо одиночной вспышки. Повторить
не удавалось.
Порядок в enter_room:
1) pop_trob_room_changed() обнуляет trob_drawn[] для ВСЕХ тайлов
= «нарисовано без блеска»;
2) pop_trob_anim_room() задаёт мечу СЛУЧАЙНУЮ фазу счётчика 0..31
(start_anim_sword, seg007:087C);
3) pop_room_draw() рисует комнату по ЖИВОМУ modif.
Если случайная фаза попала ровно на 1, комната рисуется С БЛЕСКОМ (draw_tile
берёт кадр (modif==1)+10), а trob_drawn говорит «блеска нет». На следующем
кадре animate_sword уводит счётчик с 1, признак снова 0 — и СОВПАДАЕТ со
стоячим trob_drawn, поэтому перерисовка не помечается. Блеск остаётся
запечённым в фон.
Оба наблюдённых числа сходятся:
вероятность ровно 1/32 на вход в комнату — отсюда «редко»;
длительность animate_sword считает ВНИЗ и на нуле берёт новый период
0x28..0x67, то есть до 103 логических кадров ~ 6 секунд.
Фикс: trob_drawn для меча инициализируется тем, что реально нарисует комната
(mod == 1), а не нулём. Одно присваивание на вход в комнату — в кадре ноль.
ПОДТВЕРЖДЕНО АРТЕФАКТОМ, а не рассуждением: временная сборка с подменой фазы
на mod[i] = 1 давала баг на КАЖДОМ входе в комнату 15 (пользователь
подтвердил), с фиксом — ни на одном. Временный форсаж снят.
У КНОПКИ той же дыры нет, хотя механизм общий (оба используют trob_drawn):
её признак — ДЛИТЕЛЬНОЕ состояние (нажата/нет), рассогласование само
исправляется на первой же смене. У блеска признак — одиночная вспышка в
ОДНОМ кадре из 40..103, и пропущенная смена стоит целого периода. Записано в
комментарии, чтобы их не «унифицировали» обратно.
8 наборов tests-host зелёные.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -177,6 +177,27 @@ void pop_trob_anim_room(uint8_t room) __banked
|
||||
} else if (code == TILE_SWORD) {
|
||||
/* start_anim_sword (seg007:087C): случайная фаза счётчика блеска. */
|
||||
mod[i] = (uint8_t)(trob_prandom(0xFF) & 0x1F);
|
||||
/* trob_drawn обязан описывать то, что НАРИСУЕТ полная отрисовка
|
||||
* комнаты, а она идёт ПОСЛЕ этой функции и берёт ЖИВОЙ modif.
|
||||
* Обнулять его (как делает pop_trob_room_changed для всех тайлов)
|
||||
* тут нельзя: если случайная фаза попала ровно на 1, комната
|
||||
* рисуется С БЛЕСКОМ, а trob_drawn говорит «блеска нет» — и на
|
||||
* следующем кадре счётчик уходит с 1, sig снова 0, СОВПАДАЕТ со
|
||||
* стоячим trob_drawn, и перерисовка НЕ помечается. Блеск остаётся
|
||||
* запечённым в фон до конца периода: animate_sword считает вниз и
|
||||
* выдаёт новый период 0x28..0x67, то есть до 103 логических кадров
|
||||
* ≈ 6 секунд. Вероятность ровно 1/32 на вход в комнату — отсюда
|
||||
* «редко воспроизводится» (найдено пользователем 2026-08-17,
|
||||
* уровень 1 комната 15). Проверено ПРИНУДИТЕЛЬНО: со временной
|
||||
* подменой фазы на mod[i] = 1 баг ловится на КАЖДОМ входе в
|
||||
* комнату, а с этой строкой не ловится ни на одном.
|
||||
*
|
||||
* У КНОПКИ той же дыры нет, хотя механизм общий: её признак —
|
||||
* ДЛИТЕЛЬНОЕ состояние (нажата/нет), и рассогласование само
|
||||
* исправляется на первой же смене. У блеска признак — одиночная
|
||||
* вспышка в ОДНОМ кадре из 40..103, и пропущенная смена стоит
|
||||
* целого периода. */
|
||||
trob_drawn[i] = (uint8_t)(mod[i] == 1);
|
||||
pop_add_trob(room, i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user