L5-SHADOW: тень уровня 5 крадёт зелье (спецсобытие комнаты 24)
Порт seg002: check_shadow (0064), do_init_shad (0000), do_auto_moves (1089),
autocontrol_shadow_level5 (1157) + таблица shad_drink_move (data.h:866).
Механика. При входе в комнату 24 уровня 5, если зелье (кол 3, ряд 0) ещё
на месте, слот соперника занимает ТЕНЬ — и занимает его ВМЕСТО стража:
enter_guard в этой комнате оригинал не зовёт НИКОГДА (в данных страж есть,
guards_tile[23] = 8, но check_shadow уходит в return до него — в том числе
когда зелье уже выпито). Поэтому pop_check_shadow вернула 1 = «событие
обработано, стража не поднимать», и вызов стоит ПЕРЕД pop_guard_enter.
Тень стоит, пока не откроются ворота комнаты (openness >= 80), затем
проигрывает ЗАПИСЬ ходов: подойти, взять, выпить, развернуться, уйти за
левый край. do_auto_moves — тот же движок, что у демо-режима заставки;
тонкость выбора записи (при достигнутом времени индекс сдвигается, а ход
берётся из ещё не сдвинутой записи) портирована дословно.
Три вещи, найденные по дороге:
1. ГЕЙТ ВЫКЛЮЧЕННОГО ПЕРСОНАЖА. play_guard_frame (seg000:1248) начинается
с `if (Guard.direction != dir_56_none)`, и clear_char выключает
персонажа именно так — он не трогает charid. У нас гейт был только по
charid, поэтому ушедшая за край тень продолжала тикать: do_auto_moves за
концом таблицы отдаёт последнюю запись {0x31,1} = «вперёд», тень
разворачивалась, вбегала обратно, пробегала верхний ряд и падала в проём
(наблюдение пользователя в MAME). Гейт добавлен и в pop_guard_tick, и в
pop_guard_phys_tick.
2. ЭФФЕКТ ЗЕЛЬЯ — ТОЛЬКО КИДУ. proc_get_object (seg006:16CB) начинается с
`if (Char.charid != charid_0_kid || ...) return`: предмет забирает любой
персонаж, а эффект достаётся только Киду. На этом стоит всё спецсобытие
— тень пьёт, зелье исчезает и не достаётся никому. Без проверки
hitp_delta уходил бы Киду, то есть тень его ЛЕЧИЛА бы.
3. ВЕТКА ТЕНИ в check_guard_fallout (seg002:0241): исчезает, только если
реально падает (action == 4). Была помечена в коде как «появится с
L3-SKEL» — на самом деле она про тень.
Чит ROOMNAV: телепорт ставил Кида в первый попавшийся пол, то есть почти
всегда (0,0). Теперь ищет пол С МАКСИМАЛЬНЫМ Y (ряд 2 -> 1 -> 0, по
просьбе пользователя): в комнате 24 старая посадка была вплотную к тени, и
вместо сцены кражи начиналась схватка, которой там быть не должно.
Отладочный тумблер POP_DBG_SHADOW_NOWAIT (pop_tune.h, по умолчанию 0) —
посмотреть сцену, не проходя уровень до кнопки.
Проверено в MAME (уровень 5, комната 24): при закрытых воротах тень стоит
за левым краем и не видна; с тумблером — подошла, выпила (зелье исчезло),
развернулась, ушла за край, выключилась и НЕ вернулась. tests-host 5/5,
make size-check OK. Цена: резидент +102 Б (24637 -> 24739), банк 1
+368 Б, банк 3 +11 Б.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -115,9 +115,11 @@ void pop_do_delta_hp(void)
|
||||
* стража там больше нет и после возврата. У нас тот же смысл — запомнить
|
||||
* состояние с tile = 30 («стража в комнате больше нет»).
|
||||
*
|
||||
* Ветки тени (падает, только если она в свободном полёте) и скелета (тот
|
||||
* возрождается в комнате 3) появятся вместе с L3-SKEL — сейчас в слоте
|
||||
* бывает только обычный страж.
|
||||
* Ветка ТЕНИ (seg002:0241): она исчезает, только если РЕАЛЬНО падает
|
||||
* (`action == actions_4_in_freefall`) — иначе тень, зашедшую низко по
|
||||
* своим делам (уровень 5 идёт по нижнему ряду за зельем), убрало бы с
|
||||
* экрана на ровном месте. Ветка скелета — ниже, он не гибнет, а
|
||||
* возрождается.
|
||||
*
|
||||
* Полосу HP перерисовывать отдельно не надо: pop_hp_draw сравнивает числа
|
||||
* и сам увидит, что стража не стало. */
|
||||
@@ -128,9 +130,23 @@ void pop_do_delta_hp(void)
|
||||
#define SKEL_REAPPEAR_X 133
|
||||
#define SKEL_REAPPEAR_ROW 1
|
||||
|
||||
/* actions_4_in_freefall (seg005) — тот же номер, что ACT_FREEFALL в
|
||||
* pop_map.c; здесь свой define, потому что тот приватный для карты. */
|
||||
#define ACT_4_IN_FREEFALL 4
|
||||
|
||||
void pop_guard_fallout(void)
|
||||
{
|
||||
if (Guard.charid == 0 || Guard.y < 211) return;
|
||||
if (Guard.charid == CHARID_1_SHADOW) {
|
||||
/* Тень исчезает только в свободном падении; иначе — не наше дело. */
|
||||
if (Guard.action != ACT_4_IN_FREEFALL) return;
|
||||
Guard.direction = DIR_56_NONE;
|
||||
Guard.alive = 0;
|
||||
Guard.action = 0;
|
||||
Guard.charid = 0;
|
||||
guardhp_curr = 0;
|
||||
return;
|
||||
}
|
||||
if (Guard.charid == CHARID_4_SKELETON) {
|
||||
uint8_t down = pop_room_link(Guard.room, 3 /* вниз */);
|
||||
if (down == SKEL_REAPPEAR_ROOM) {
|
||||
|
||||
Reference in New Issue
Block a user