PoP: скелет уровня 3, цвета стражей, окклюзия соперника; кэш соседних комнат
Скелет (L3-SKEL, ассеты + механика): - pop_pack_guard.py получил параметр набора (GUARD/SKEL): атлас скелета poc/res/skel/g0..g3.atl (28 кадров), палитра — из его res750.pal (на ур. 3 curr_guard_color = 0, оригинал палитру не подменяет); - pop_guard_load выбирает набор по tbl_guard_type и перезагружается ПРИ СМЕНЕ УРОВНЯ (load_lev_spr, seg000:1092) — без этого скелет рисовался атласом стража и был невидим; - load_frame: charid_4_skeleton идёт по таблице стража (seg006:529), тень — только в кадрах 150..189. Пока ветка была одна (charid_2_guard), скелет получал image из таблицы Кида (180 при 28 спрайтах) и не рисовался; - check_skel (seg002:1042), ветка charid_4 в enter_guard, возрождение в комнате 3 при падении (seg002:252), autocontrol_skeleton; - leveldoor_open (seg007:456) — новый флаг, сбрасывается стартом уровня. Цвета стражей (BUG-GUARD-COLOR-1, закрыт): - все 7 палитр res10.bin -> pop_guard_pal.h, заливка 16 слотов по guards_color комнаты перед отрисовкой (set_chtab_palette, seg003:257). Проверено в MAME: ур. 2 комн. 11 = цвет 1, комн. 7 = цвет 3, полоса HP меняется вместе со стражем. Грабля: gfx_pal_load отдаёт указатель в BIOS, а тот читает только #4000-#BFFF — таблицу из банка копируем в стек. Кэш соседних комнат (BUG-SWORD-GHOST-1, закрыт): - pop_map кэширует fg соседей слева/справа ЦЕЛИКОМ и резолвит col -10..19. Было -2..11, дальше мнимая стена: луч видимости упирался в неё (страж после follow_guard в col 12), Кид прятал меч посреди боя и не мог достать обратно. +48 байт W2. Окклюзия соперника: - pop_fore_over_char получил проход other_overlay_tile (порядок midtable, seg008:1B06) и расширение перебора объединённым прямоугольником «персонаж + клинок + брызги» — падающий скелет больше не рисуется поверх кладки и верхней грани пола; - клип полем 192 строк (reset_obj_clip, seg006:0507) для спрайта, клинка (общий pop_sword_draw) и брызг — спрайт не залезает на полосу HP; - ROOMNAV после смерти Кида делает честный pop_start_level: телепорт «оживлял» мёртвого мимо старта уровня, оставляя живого скелета рядом с вернувшейся кучей костей. Ассеты чомпера (под L3-CHOMP): весь набор кадров в атласе явным списком (101-105 низ, 111-113 верх, 106-110 фронт, 114-123 кровь mono-силуэтом) — render_room анимированные тайлы пропускает, и в атласе не было ни одного. Число EMM-страниц не изменилось. Тесты: tests-host все 5 наборов зелёные, t_char вырос до 65 проверок (резолв колонок за краем комнаты, возрождение скелета); в testkit добавлен гард «код наехал на данные» (DATA_LOC). Доски: TASKS.md разнесён на TASKS_OPEN/TASKS_CLOSED, закрытые баги с разбором корней — в bug_closed.md; заведены DRAW-CHAR (отрисовка одна на всех Char, как физика после GUARD-PHYS) и L3-COLOR (зелёная кладка уровня 3: level_var_palettes = ресурс 20, есть в MSDOS/PRINCE.DAT). В roomtest.c временно оставлен автостоп на падении соперника (отладка падений скелета) — помечен ВРЕМЕННО. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -33,7 +33,9 @@
|
||||
#define SEQ_66_STRIKE_AFTER_PARRY 66
|
||||
#define SEQ_71_DYING 71
|
||||
#define SEQ_75_STRIKE 75 /* удар (Кид) */
|
||||
#define SEQ_63_GUARD_ACTIVE_AFTER_FALL 63 /* стойка АКТИВНОГО (скелет) */
|
||||
#define SEQ_77_GUARD_STAND_INACTIVE 77
|
||||
#define SEQ_88_SKEL_WAKE_UP 88 /* скелет встаёт (спецсобытие) */
|
||||
#define SEQ_80_STAND_FLIPPED 80
|
||||
#define SEQ_86_FORWARD_WITH_SWORD 86 /* шаг вперёд с мечом (Кид) */
|
||||
#define SEQ_87_GUARD_BECOME_INACT 87
|
||||
@@ -76,6 +78,23 @@ extern pop_char_t Guard; /* страж ТЕКУЩЕЙ комнаты
|
||||
extern uint8_t guardhp_curr, guardhp_max;
|
||||
extern int8_t guardhp_delta; /* <0 = в этом кадре отняли HP */
|
||||
|
||||
/* take_hp (seg006:06BD): отнять count HP у АКТИВНОГО персонажа (Char) —
|
||||
* Киду из `hitp_*`, любому другому из `guardhp_*`. Возврат 1 = HP кончились
|
||||
* (для вызывающего это «умер»); саму дельту применяет pop_do_delta_hp раз в
|
||||
* кадр, как в оригинале.
|
||||
*
|
||||
* Живёт в резиденте W1/W2, потому что зовут ОБА банка: боёвка (guards.c,
|
||||
* банк 1) и физика (pop_map.c, банк 3) — раньше у каждого была своя копия,
|
||||
* причём у pop_map неверная (правила hitp_curr напрямую, мимо дельты, и не
|
||||
* знала про не-Кидов). Чит бессмертия ловится здесь же. */
|
||||
uint8_t pop_take_hp(uint8_t count);
|
||||
|
||||
/* Взводится в кадре, когда СТРАЖУ убавили HP (guardhp_delta < 0 оригинала):
|
||||
* по нему pop_guard_draw рисует «брызги» удара, как draw_guard в seg008:1654.
|
||||
* Снимает главный цикл после отрисовки — стража могло не оказаться в
|
||||
* отрисованной комнате, и тогда флаг обязан просто пропасть. */
|
||||
extern uint8_t pop_guard_hurt;
|
||||
|
||||
/* Видит ли страж Кида (порт can_guard_see_kid, seg003:688):
|
||||
* 0 — не видит, 1 — видит, но не пойдёт (между ними loose/чомпер/дыра),
|
||||
* 2 — видит и пойдёт. Считает pop_check_can_guard_see_kid (банк) раз в
|
||||
@@ -109,6 +128,12 @@ extern pop_rnd_t pop_fight_seed;
|
||||
* check_can_guard_see_kid стоит в play_frame перед play_kid_frame). */
|
||||
void pop_check_can_guard_see_kid(void) __banked;
|
||||
|
||||
/* check_skel (seg002:1042) — СПЕЦСОБЫТИЕ уровня 3: скелета нет в данных
|
||||
* уровня (guards_tile пуст во всех комнатах), он поднимается сам, когда Кид
|
||||
* доходит до нужной колонки комнаты 1 при открытой двери уровня. Звать раз
|
||||
* в кадр, ДО логики персонажей (порядок play_frame, seg000:868). */
|
||||
void pop_check_skel(void) __banked;
|
||||
|
||||
/* Боёвка: пометить попадания (обе стороны) и применить их. Порядок в
|
||||
* кадре как в play_frame: hurting -> hurt -> do_delta_hp. */
|
||||
void pop_check_sword_hurting(void) __banked;
|
||||
@@ -119,6 +144,11 @@ void pop_check_sword_hurt(void) __banked;
|
||||
extern kframe pop_gframe;
|
||||
void pop_guard_load_frame(void);
|
||||
|
||||
/* check_guard_fallout (seg002:0241): убрать персонажа слота Guard, если он
|
||||
* провалился ниже комнаты. Звать раз в кадр после физики и HP — как
|
||||
* play_frame (seg000:884). */
|
||||
void pop_guard_fallout(void);
|
||||
|
||||
/* Есть ли живой страж в отрисованной комнате (для главного цикла). */
|
||||
uint8_t pop_guard_present(void);
|
||||
|
||||
@@ -135,6 +165,13 @@ void pop_guard_enter(uint8_t room);
|
||||
* enter_room, пока Guard ещё держит прежнего. */
|
||||
void pop_guard_leave(void);
|
||||
|
||||
/* Страж идёт ЗА КИДОМ в соседнюю комнату — порт ветки стража из exit_room
|
||||
* (seg002:0340) + follow_guard (seg002:039E). Звать ВМЕСТО пары
|
||||
* leave/enter при смене комнаты: 1 = страж уже перенесён в new_room (ни
|
||||
* leave, ни enter звать нельзя), 0 = остаётся в старой (всё как раньше).
|
||||
* side — куда ушёл КИД: 0 left, 1 right, 2 up, 3 down. */
|
||||
uint8_t pop_guard_follow(uint8_t new_room, uint8_t side);
|
||||
|
||||
/* Нарисовать текущий кадр стража на back-странице (банк GFX_BANK_SPRITE,
|
||||
* как kid_draw) и стереть прошлый (heal). Реализация — pop_gdraw.c
|
||||
* (резидент W3), поэтому звать ТОЛЬКО из главного цикла, не из банка. */
|
||||
@@ -144,6 +181,12 @@ void pop_hp_draw(void) __banked;
|
||||
/* Полоса стёрта перерисовкой фона (вход в комнату) — обновить обе страницы. */
|
||||
void pop_hp_invalidate(void) __banked;
|
||||
|
||||
/* Цвет стража — подменой 16 слотов палитры (порт set_chtab_palette,
|
||||
* seg003:257): спрайты лежат в индексах POP_GUARD_PAL_BASE + v, а цвет
|
||||
* задаёт level.guards_color[room-1] (1..7; 0 = не менять). Звать ДО
|
||||
* отрисовки комнаты, как это делает redraw_screen. */
|
||||
void pop_guard_set_palette(uint8_t color) __banked;
|
||||
|
||||
void pop_guard_heal(void) __banked;
|
||||
void pop_guard_draw(void) __banked;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user