Уровни 12 и 13: тень, Джафар, падающие плиты + разбор слоёв
Уровень 12 (тень) — порт seg002/seg006: - check_shadow: подъём тени в комнате 15 по условию «меч подобран», init_shad_12, вход падением (seq 7); - autocontrol_shadow_level12: ждать Кида, бой, сближение, СЛИЯНИЕ; - общий урон (ранил тень — ранил себя) и check_killed_shadow (убил тень — убил себя); - таймер вспышки слияния 42 -> -1, sword_disappears при уходе из комнаты 18, появление плит в комнатах 2/13 после слияния. Переход 12 -> 13 бесшовный: двери у уровня нет, он кончается фактом попадания в комнату 23 (tbl_seamless_exit); флаг pop_seamless не даёт сбросить HP. Чит навигации по комнатам этот триггер придерживает — иначе комнату 23 двенадцатого уровня не посмотреть в принципе. Уровень 13 (Джафар): guard_notice_timer (фора после встречи), on_guard_killed + Jaffar_exit, check_fall_flo (гряда плит сверху) и три исключения loose-механики. Плюс спрайты визиря VIZIER.DAT — без них он рисовался обычным стражем; заодно цвет из данных комнаты применяется только к обычному стражу, как в оригинале. Падающие плиты — семь дефектов, найденных прогонами: - MOB_MAX 4 -> 14: check_fall_flo роняет шесть плит разом, лишние терялись без щебня; - одиночные сигналы посадки/провала больше не затираются в кадре; - честный loose_fall: сбитая плита рождается в том же кадре, от места удара, с половинной скоростью; - при снятии плиты метится и сосед справа (висел передний торец); - heal и отрисовка кусков разнесены на два прохода; - куски рисуются ПОСЛЕ фона, порядок между собой — по убыванию y (compare_curr_objs для пары 0x80 сортирует наоборот); - wall_pattern убран из ceil_over_kid_tile: у оригинала узор из draw_tile_bottom идёт в фон, а не в передний слой. Хост-тесты: два новых набора, t_shadow (45 проверок) и t_jaffar (44). TK_ROOMS 8 -> 24 — спецсобытия адресуют комнаты по реальным номерам. Осознанные расхождения (docs/impl_diff.md): нет мигания Кида спрайтами тени при слиянии, чит навигации не запускает бесшовный переход, чит K убивает через штатный путь смерти. Открытым остаётся разбор слоёв: MOB-CLIP-RIGHT, MID-OVERLAY-LAYER, GUARD-FALLOUT-VICTORY, BG-ONCE (BUGS_OPEN.md / TASKS_OPEN.md). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -66,6 +66,9 @@
|
||||
#define CHARID_0_KID 0
|
||||
#define CHARID_1_SHADOW 1
|
||||
#define CHARID_2_GUARD 2
|
||||
/* charid_3 не используется: Джафар (уровень 13) — обычный charid_2_guard,
|
||||
* своим charid оригинал помечает ТОЛЬКО скелета (enter_guard, seg002:196).
|
||||
* Отличают Джафара набор спрайтов (VIZIER.DAT), skill 9 и три события. */
|
||||
#define CHARID_4_SKELETON 4
|
||||
#define CHARID_5_PRINCESS 5
|
||||
/* МЫШЬ (спецсобытие уровня 8) — тоже персонаж слота Guard: своей таблицы
|
||||
@@ -129,8 +132,41 @@
|
||||
|
||||
/* Единственный уровень, где тень — БОЕВОЙ персонаж (seg003:702). На всех
|
||||
* остальных (4 зеркало, 5 зелье, 6 плита) она Кида «не видит»: см.
|
||||
* pop_check_can_guard_see_kid. */
|
||||
* pop_check_can_guard_see_kid.
|
||||
*
|
||||
* Сцена целиком (seg002:0070 + seg002:1184): в комнате 15 лежит МЕЧ (0,1);
|
||||
* пока он на месте, тень не появляется. Кид его берёт — тень падает в ту
|
||||
* же комнату, и дальше либо бой (у обоих клинки), либо, если Кид уберёт
|
||||
* меч, — слияние. Комната 18 при уходе ВПРАВО «съедает» меч с карты
|
||||
* (sword_disappears), чтобы вернуться и подобрать его второй раз было
|
||||
* нельзя. Проверено по res2012.bin, ../docs/levels_12_15_plan.md §7.3. */
|
||||
#define SHADOW_FIGHT_LEVEL 12
|
||||
#define SHADOW_FIGHT_ROOM 15
|
||||
#define SHADOW_SWORD_TILEPOS 1 /* (кол 1, ряд 0) — меч уровня 12 */
|
||||
#define SWORD_GONE_ROOM 18 /* уход ВПРАВО отсюда убирает меч */
|
||||
/* Слияние (autocontrol_shadow_level12): дистанция, вспышка, её длительность. */
|
||||
#define SHADOW_UNITE_DIST 10
|
||||
#define SHADOW_UNITE_TIME 42
|
||||
|
||||
/* Уровень 13 — ДЖАФАР (custom->jaffar_*, дефолты SDLPoP). Своего ИИ у него
|
||||
* нет вовсе: `autocontrol_Jaffar` (seg002:085A) — это `autocontrol_guard`,
|
||||
* то есть обычный бой стражи. Отличают его только данные (VIZIER.DAT,
|
||||
* skill 9, 6 HP — всё уже в pop_level_cold.c) и три события ниже.
|
||||
*
|
||||
* Встреча: Кид уходит ВПРАВО из комнаты 3 — а `комната 3.right = 1`, где
|
||||
* Джафар и стоит (проверено по res2013.bin, ../docs/levels_12_15_plan.md
|
||||
* §7.2). Ему даётся фора JAFFAR_NOTICE_TIME кадров: пока таймер идёт, он не
|
||||
* встаёт в боевую стойку, и это единственная пауза во всей сцене.
|
||||
*
|
||||
* Выход: смерть Джафара сама дверь НЕ открывает — она ставит
|
||||
* pop_leveldoor_open = 2, а дверь открывает КНОПКА комнаты 24 (tilepos 0,
|
||||
* реальный opener), «нажимаемая» при уходе Кида ВЛЕВО. */
|
||||
#define JAFFAR_LEVEL 13
|
||||
#define JAFFAR_MEET_ROOM 3 /* уход ВПРАВО отсюда будит Джафара */
|
||||
#define JAFFAR_NOTICE_TIME 28 /* ≈2,3 с форы (28/12) */
|
||||
#define JAFFAR_EXIT_ROOM 24
|
||||
#define JAFFAR_EXIT_TILEPOS 0
|
||||
#define JAFFAR_FLASH_TIME 18
|
||||
|
||||
/* Градаций мастерства стража (seg002: таблицы вероятностей по 12 записей). */
|
||||
#define NUM_GUARD_SKILLS 12
|
||||
@@ -184,6 +220,23 @@ extern int8_t guard_refrac, justblocked, kid_sword_strike;
|
||||
* holding_sword — клинок в руке (для индикатора HP стража). */
|
||||
extern int8_t offguard, holding_sword;
|
||||
|
||||
/* Спецсобытие уровня 12 — СЛИЯНИЕ С ТЕНЬЮ (united_with_shadow, seg000:288).
|
||||
* Значение читается как три разных состояния, и это НЕ флаг:
|
||||
* 0 — тень ещё отдельный персонаж (или уровень не 12);
|
||||
* >0 — идёт вспышка слияния, счётчик кадров (42 → 1), убывает в
|
||||
* pop_shadow_timer; пока он идёт, Кид мигает спрайтами тени;
|
||||
* −1 — «уже слились», навсегда до конца уровня. Именно по нему
|
||||
* check_shadow больше не поднимает тень, а в комнатах 2/13
|
||||
* появляются недостающие плиты пола.
|
||||
* Переход 0 → −1 идёт ЧЕРЕЗ счётчик: таймер, досчитав до нуля, уводит его
|
||||
* ещё на единицу вниз (seg003:503) — отсюда и знаковый тип.
|
||||
*
|
||||
* pop_shadow_init (shadow_initialized, seg000:309) — «тень уже дождалась
|
||||
* Кида в комнате 15»: до этого autocontrol_shadow_level12 роняет её заново
|
||||
* каждый кадр, чтобы Кид застал падение, а не готовую стойку. */
|
||||
extern int8_t pop_united_shadow;
|
||||
extern uint8_t pop_shadow_init;
|
||||
|
||||
/* Сид бросков боёвки (свой домен последовательности, см. pop_geom.h). */
|
||||
extern pop_rnd_t pop_fight_seed;
|
||||
|
||||
@@ -215,6 +268,33 @@ void pop_check_mouse(void) __banked;
|
||||
* возвращается и во втором случае тоже. */
|
||||
uint8_t pop_check_shadow(uint8_t room) __banked;
|
||||
|
||||
/* sword_disappears (seg002:0536) — спецсобытие уровня 12: уход ВПРАВО из
|
||||
* комнаты 18 убирает меч из комнаты 15. Звать при уходе вбок ДО смены
|
||||
* комнаты, рядом с чекпойнтом уровня 3. */
|
||||
void pop_sword_disappears(void) __banked;
|
||||
|
||||
/* meet_Jaffar (seg002:0544) — уход ВПРАВО из комнаты 3 уровня 13 даёт
|
||||
* Джафару фору; звать рядом с pop_sword_disappears (та же ветка leave_room).
|
||||
* Jaffar_exit (seg002:0517) — уход ВЛЕВО при pop_leveldoor_open == 2 жмёт
|
||||
* кнопку комнаты 24 и открывает дверь уровня. */
|
||||
void pop_meet_jaffar(void) __banked;
|
||||
void pop_jaffar_exit(void) __banked;
|
||||
|
||||
/* check_killed_shadow (seg006:2033) — спецсобытие уровня 12: смерть тени
|
||||
* убивает Кида и наоборот. Звать раз в кадр ДО тиков персонажей, рядом с
|
||||
* pop_check_skel; на прочих уровнях выходит первой строкой. */
|
||||
void pop_check_killed_shadow(void) __banked;
|
||||
|
||||
/* timers (seg003:0735) — кадровые счётчики спецсобытий: вспышка слияния с
|
||||
* тенью и фора Джафара. Звать раз в кадр из главного цикла. Резидент: два
|
||||
* вычитания, банк ради них не разворачиваем. */
|
||||
void pop_frame_timers(void);
|
||||
|
||||
/* guard_notice_timer (seg000:307) — фора Джафара после встречи: пока >0, он
|
||||
* не встаёт в боевую стойку. Ставит pop_meet_jaffar, убавляет
|
||||
* pop_frame_timers, читает autocontrol_guard_inactive. */
|
||||
extern int8_t pop_guard_notice_timer;
|
||||
|
||||
/* Боёвка: пометить попадания (обе стороны) и применить их. Порядок в
|
||||
* кадре как в play_frame: hurting -> hurt -> do_delta_hp. */
|
||||
void pop_check_sword_hurting(void) __banked;
|
||||
|
||||
Reference in New Issue
Block a user