/* * pop_demo.c — воспроизведение attract-demo SDLPoP, банк 9 (FG7). * * Это не отдельная физика и не сценарные телепорты. Таблица custom->demo_moves * подаёт ровно те же control_* в pop_ctrl_auto_move(), через которые идут * игрок и автоконтроль персонажей. Поэтому демо проверяет настоящий маршрут * level 0, а не его нарисованную имитацию. */ #include #include #include "pop_ctrl.h" #include "pop_guard.h" #include "pop_map.h" /* hitp_curr — смерть demo имеет приоритет над AI */ #include "pop_demo.h" typedef struct { uint8_t time; int8_t move; } demo_move_t; /* data.h SDLPoP: демо пробегает уровень 0 до комнаты 24. Последний -1 * означает «больше не менять уже поданный control_*», а не ввод. */ static const demo_move_t demo_moves[] = { {0x00, 0}, {0x01, 1}, {0x0D, 0}, {0x1E, 1}, {0x25, 5}, {0x2F, 0}, {0x30, 1}, {0x41, 0}, {0x49, 2}, {0x4B, 0}, {0x63, 2}, {0x64, 0}, {0x73, 5}, {0x80, 6}, {0x88, 3}, {0x9D, 7}, {0x9E, 0}, {0x9F, 1}, {0xAB, 4}, {0xB1, 0}, {0xB2, 1}, {0xBC, 0}, {0xC1, 1}, {0xCD, 0}, {0xE9, -1}, /* do_auto_moves читает moves[demo_index] ещё после сдвига индекса. * Это недостижимая метка из data.h, не команда: она держит индекс в * границах, пока demo_time доходит до 0xFE. */ {0xFF, -2} }; static uint8_t demo_time; static uint8_t demo_index; void pop_demo_begin(void) __banked { demo_time = 0; demo_index = 0; } uint8_t pop_demo_tick(void) __banked { uint8_t index; int8_t move; /* Урон мечом сводится ПОСЛЕ этого вызова в предыдущем игровом кадре. * На следующем тике HP уже ноль, но pop_kid_dead ещё не поднят: обычный * pop_ctrl_tick делает это в ctrl_kid_death(), а demo обходит его своим * AI. Без этого гарда AI снова управлял мёртвым Кидом, возвращал его в * стойку и страж убивал его по кругу. Attract-demo при смерти кончается; * текущий главный цикл ещё дорисует один последний кадр и уйдёт в title. */ if (hitp_curr == 0) return 1; /* do_demo(): в бою запись времени/кнопок стоит, Кидом управляет тот же * combat AI, что стражами, но с отдельным skill 10. */ if (pop_demo_kid_ai()) return 0; if (demo_time >= 0xFE) return 1; ++demo_time; index = demo_index; if (demo_moves[index].time <= demo_time) ++demo_index; else index = (uint8_t)(demo_index - 1); move = demo_moves[index].move; pop_ctrl_auto_move(move); return (uint8_t)(demo_time >= 0xFE); } uint8_t pop_demo_user_input(void) __banked { return kbd_raw_any_down(); }