/* * pop_guard.h — СОСТОЯНИЕ стража и точки входа в его логику. * * Разделение по окнам (docs/layout_plan_v2.md §4, подтверждено пробником * tests/w3bankgfx): * - СОСТОЯНИЕ живёт здесь, в W1/W2. Писучие статики __banked-модуля * линкуются В СТРАНИЦУ БАНКА и снаружи не читаются, поэтому банк — * только код; * - ЛОГИКА (ИИ, боёвка) — в guards.c, собираемом как --bank 1=guards.c; * - ОТРИСОВКА стража — в pop_gdraw.c, РЕЗИДЕНТЕ W3 (--w3): её зовёт * только главный цикл, а из банка резидент недостижим. Так код * отрисовки не занимает дефицитные W1/W2 (куча). * * Поля char_type — как в оригинале (types.h:302), чтобы порт seg005/seg006 * ложился один в один. */ #ifndef POP_GUARD_H #define POP_GUARD_H #include #include "kid_data.h" /* kframe */ #include "pop_char.h" /* seqids (types.h:1052+) — последовательности стража. */ #define SEQ_55_DRAW_SWORD 55 #define SEQ_77_GUARD_STAND_INACTIVE 77 #define SEQ_80_STAND_FLIPPED 80 #define SEQ_90_EN_GARDE 90 /* frameids (types.h:927) и состояния меча (types.h:332). */ #define FRAME_166_STAND_INACTIVE 166 #define SWORD_0_SHEATHED 0 #define SWORD_2_DRAWN 2 /* charids (types.h:320) — нужны хотя бы для «скелет не убивается читом». */ #define CHARID_0_KID 0 #define CHARID_1_SHADOW 1 #define CHARID_2_GUARD 2 #define CHARID_4_SKELETON 4 #define CHARID_5_PRINCESS 5 /* Тип персонажа — в pop_char.h (общий с Кидом и Char). */ extern pop_char_t Guard; /* страж ТЕКУЩЕЙ комнаты (как в оригинале) */ extern uint8_t guardhp_curr, guardhp_max; extern int8_t guardhp_delta; /* <0 = в этом кадре отняли HP */ /* Видит ли страж Кида (порт can_guard_see_kid, seg003:688): * 0 — не видит, 1 — видит, но не пойдёт (между ними loose/чомпер/дыра), * 2 — видит и пойдёт. Считает pop_check_can_guard_see_kid (банк) раз в * кадр ДО логики персонажей; читают ИИ (autocontrol_*) и боёвка. */ extern int8_t can_guard_see_kid; /* Кид «нашумел» (порт is_guard_notice, seg000:364): заставляет неактивного * стража обернуться, даже если Кид у него за спиной. Ставит источник шума, * снимает сам ИИ. */ extern int8_t is_guard_notice; /* Луч видимости стража — раз в кадр, ДО тиков персонажей (в оригинале * check_can_guard_see_kid стоит в play_frame перед play_kid_frame). */ void pop_check_can_guard_see_kid(void) __banked; /* Текущий кадр стража (порт cur_frame для Char): заполняет логика в W1/W2, * читает отрисовка в резиденте W3. image == 255 — рисовать нечего. */ extern kframe pop_gframe; void pop_guard_load_frame(void); /* Есть ли живой страж в отрисованной комнате (для главного цикла). */ uint8_t pop_guard_present(void); /* Атласы стража (GUARD\\g0..g4.atl) — грузить ДО initgraph, как Kid. * 0 — OK, -1 — ошибка (тогда страж просто не рисуется). */ int pop_guard_load(void) __banked; void pop_guard_free(void) __banked; /* Вход в комнату: поднять стража из данных уровня (порт enter_guard, * seg002:0112) либо убрать его, если в комнате стража нет. */ void pop_guard_enter(uint8_t room); /* Нарисовать текущий кадр стража на back-странице (банк GFX_BANK_SPRITE, * как kid_draw) и стереть прошлый (heal). Реализация — pop_gdraw.c * (резидент W3), поэтому звать ТОЛЬКО из главного цикла, не из банка. */ void pop_guard_heal(void) __banked; void pop_guard_draw(void) __banked; /* Убрать стража со сцены (смена комнаты / инициализация). */ void pop_guard_reset(void); /* Чит «убить стража» (seg000:786, K): скелета не берёт. Вызывать только * при включённых читах — проверку делает вызывающий. */ void pop_guard_kill(void); /* Тик логики стража — В БАНКЕ (guards.c). Состояние берёт отсюда. */ void pop_guard_tick(void) __banked; #endif