From 75a51fb1db3f2340485f6682fe4f06502fd40bd0 Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Thu, 30 Jul 2026 22:09:36 +0300 Subject: [PATCH] =?UTF-8?q?PoP=20roomtest:=20=D0=B2=D1=8B=D0=BF=D0=B8?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B5=D0=BB=D1=8C=D1=8F?= =?UTF-8?q?=20(=D1=83=D1=80=D0=BE=D0=B2=D0=B5=D0=BD=D1=8C=201=20=E2=80=94?= =?UTF-8?q?=20=D1=81=D0=BA=D0=BB=D1=8F=D0=BD=D0=BA=D0=B0=20=D0=B7=D0=B4?= =?UTF-8?q?=D0=BE=D1=80=D0=BE=D0=B2=D1=8C=D1=8F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Каркас предметов уже был (check_get_item/do_pickup/proc_get_object), пустой оставалась только ветка зелий. Порт seg005 get_item + seg006 proc_get_object: - pop_get_item_action теперь отдаёт 3 = «пить» и делает do_pickup с ТИПОМ зелья, который лежит в старших битах модификатора тайла (modif >> 3); - pop_ctrl на код 3 запускает seq_78_drink; - эффекты: тип 1 (здоровье) — +1 HP через hitp_delta и красная вспышка, причём как в оригинале только если HP не полные; тип 5 («злое») — −1 HP. Типы 2/3/4/6 (жизнь, перо, переворот, открыть ворота) — свойства поздних уровней, портируем вместе с ними. Вспышка фона получила цвет: меч даёт ярко-жёлтую (было), зелье — красную (flash_color оригинала; двух значений достаточно, других в игре нет). Co-Authored-By: Claude Opus 5 --- applications/PoP/roomtest/pop_ctrl.c | 6 ++++ applications/PoP/roomtest/pop_map.c | 41 +++++++++++++++++++++++++--- applications/PoP/roomtest/pop_map.h | 4 ++- applications/PoP/roomtest/roomtest.c | 6 +++- 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/applications/PoP/roomtest/pop_ctrl.c b/applications/PoP/roomtest/pop_ctrl.c index 8e66c55..6773809 100644 --- a/applications/PoP/roomtest/pop_ctrl.c +++ b/applications/PoP/roomtest/pop_ctrl.c @@ -52,6 +52,7 @@ #define SEQ_49_STAND_UP_FROM_CROUCH 49 #define SEQ_50_CROUCH 50 #define SEQ_79_CROUCH_HOP 79 +#define SEQ_78_DRINK 78 /* выпить зелье */ #define SEQ_91_PICKUP_SWORD 91 /* поднять меч (pickupsword) */ #define SEQ_STEP_BASE 28 /* +distance(1..14) = seq 29..42 шаг-N */ #define SEQ_39_UNSAFE_STEP 39 /* шаг за кромку (distance 11) */ @@ -126,6 +127,11 @@ static uint8_t get_item_action(void) seqtbl_offset_char(SEQ_91_PICKUP_SWORD); return 1; } + if (a == 3) { /* зелье — выпить (get_item) */ + control_shift2 = CONTROL_IGNORE; + seqtbl_offset_char(SEQ_78_DRINK); + return 1; + } return 0; } diff --git a/applications/PoP/roomtest/pop_map.c b/applications/PoP/roomtest/pop_map.c index 619b129..e93b9af 100644 --- a/applications/PoP/roomtest/pop_map.c +++ b/applications/PoP/roomtest/pop_map.c @@ -809,6 +809,9 @@ uint8_t pop_down_action(void) __banked uint8_t pop_have_sword; uint8_t pop_item_taken; /* 0 = нет; иначе tilepos+1 поднятого */ uint8_t pop_flash_time; /* кадров вспышки фона (flash_time) */ +/* Цвет вспышки: 0 = ярко-жёлтая (меч), 1 = красная (зелье). В оригинале это + * flash_color; нам хватает двух значений, которые реально встречаются. */ +uint8_t pop_flash_red; static int8_t pickup_obj_type; /* -1 = меч (порт pickup_obj_type) */ /* do_pickup (seg006:1671): стереть предмет с карты (тайл → пол) и запомнить @@ -832,7 +835,29 @@ void pop_proc_get_object(void) __banked * чёрное поле экрана. У нас так же (gfx_pal_set 0), см. roomtest. */ pop_flash_time = 8; } - pickup_obj_type = 0; /* зелья (типы 1..6) не портированы */ + else { + /* proc_get_object (seg006:1927), ветка зелий. Типы 3/4/6 + * (перо/переворот/открыть все ворота) — свойства поздних уровней, + * их портируем вместе с этими уровнями. */ + switch (pickup_obj_type) { + case 1: /* здоровье: +1 HP, красная вспышка */ + if (hitp_curr != hitp_max) { + hitp_delta = 1; + pop_flash_red = 1; + pop_flash_time = 2; + } + break; + case 5: /* «злое» зелье: −1 HP */ + hitp_delta = -1; + pop_flash_red = 1; + pop_flash_time = 2; + break; + default: /* 2 жизнь / 3 перо / 4 переворот / + * 6 открыть — TODO с их уровнями */ + break; + } + } + pickup_obj_type = 0; } /* check_get_item + get_item (seg005:061F/073E). Возврат: 0 — предмета нет @@ -861,9 +886,17 @@ uint8_t pop_get_item_action(void) __banked Kid.x = (uint8_t)char_dx_forward((int8_t)((t == TILE_POTION) - 2)); return 1; } - if (t != TILE_SWORD) return 0; /* питьё зелий не портировано */ - do_pickup(-1, (uint8_t)(Kid.curr_row * 10 + icol)); - return 2; + { + uint8_t tp = (uint8_t)(Kid.curr_row * 10 + icol); + if (t == TILE_SWORD) { + do_pickup(-1, tp); + return 2; /* поднять меч (seq_91) */ + } + /* Зелье: тип лежит в СТАРШИХ битах модификатора (get_item, + * seg005: do_pickup(curr_room_modif[curr_tilepos] >> 3)). */ + do_pickup((int8_t)(pop_trob_modif(g_room)[tp] >> 3), tp); + return 3; /* пить (seq_78) */ + } } /* ---- Диспетчер ----------------------------------------------------- */ diff --git a/applications/PoP/roomtest/pop_map.h b/applications/PoP/roomtest/pop_map.h index 63e980c..73b2fe8 100644 --- a/applications/PoP/roomtest/pop_map.h +++ b/applications/PoP/roomtest/pop_map.h @@ -53,7 +53,9 @@ extern uint8_t pop_item_taken; /* Вспышка фона (do_flash/set_bg_attr, seg001:0908): счётчик кадров, пока * НУЛЕВАЯ запись палитры подменена ярко-жёлтым. Тикает вызывающий. */ extern uint8_t pop_flash_time; -uint8_t pop_get_item_action(void) __banked; /* 0 нет / 1 присесть / 2 поднять меч */ +/* Цвет вспышки: 0 = ярко-жёлтая (подобран меч), 1 = красная (зелье). */ +extern uint8_t pop_flash_red; +uint8_t pop_get_item_action(void) __banked; /* 0 нет / 1 присесть / 2 поднять меч / 3 пить */ void pop_proc_get_object(void) __banked; /* эффект — из play_seq (опкод GET_ITEM) */ /* Уход из комнаты ВБОК/ВВЕРХ: 0=нет; 1=left,2=right,3=up (= side+1 для diff --git a/applications/PoP/roomtest/roomtest.c b/applications/PoP/roomtest/roomtest.c index f29e429..07bc737 100644 --- a/applications/PoP/roomtest/roomtest.c +++ b/applications/PoP/roomtest/roomtest.c @@ -488,8 +488,12 @@ int main(void) * Приоритет как в оригинале: активный flash_time > кадр урона * (hitp_delta<0 -> ярко-красный, ровно на один кадр). */ if (pop_flash_time) { - flash_bg(255, 255, 85); /* color_14_brightyellow */ + /* Цвет вспышки: меч — ярко-жёлтый, зелье — красный (flash_color + * оригинала; нам хватает этих двух). */ + if (pop_flash_red) flash_bg(255, 0, 0); /* color_4_red */ + else flash_bg(255, 255, 85); /* color_14_brightyellow */ pop_flash_time--; + if (!pop_flash_time) pop_flash_red = 0; flash_on = 1; } else if (pop_kid_hurt) { flash_bg(255, 85, 85); /* color_12_brightred */