Зелье медленного падения (перо) + цвет пузырьков по типу зелья
L7-FEATHER: тип 3 (уровень 7, комната 1) больше не пустой TODO. - pop_map.c: pop_feather — счётчик кадров эффекта (POP_FEATHER_FRAMES = 225, ванильный порог do_timers seg003:0517; привязку к звуку взять неоткуда). fall_accel — ускорение 1 / потолок 4 (seg006:057C) вместо 3 / 33. proc_get_object case 3: взвести эффект + зелёная вспышка на 3 кадра. - pop_kid.c: опкод JMP_IF_FEATHER (0xF7) больше не пропускает адрес безусловно — под пером прыгает по нему, то есть seqtbl уводит падение и удар в ветки stepfloat/bumpfloat (плавные кадры, без урона). - roomtest.c: pop_flash_red -> pop_flash_color (жёлтый/красный/ЗЕЛЁНЫЙ); сброс pop_feather в pop_start_level (seg003:189). - Цвет пузырька по ТИПУ зелья (seg008:652), чего у нас не было вовсе: 3/4 зелёный, 5/6 СИНИЙ, остальные красный. Mono-блиттера с параметром цвета в libbgi нет, поэтому цвет запекается при упаковке: pop_pack_bg.py кладёт те же 7 кадров ещё дважды (id 30..36 зелёные, 40..46 синие), pop_potion_draw выбирает набор. Атлас 23 -> 37 спрайтов (+423 Б). - Синее зелье «−HP» приведено к оригиналу (seg006:1892): своей вспышки не ставит (красный кадр даёт общий flash_if_hurt — иначе экран красился дважды), а на уровне зелий забирает ПОЛОВИНУ запаса HP. Такое зелье стоит уже на пройденном уровне 2 (комната 13, тайл (1,3)), а также ур.8 комн.2 и весь ур.15 — до сих пор оно было красным. Тесты: phys_feather_fall_is_slow_and_harmless (обычное падение с двух рядов разгоняется и стоит HP, под пером скорость <= 4 и HP целое); tests-host 5/5 (1727 в [phys]), size-check OK. Расхождения с ванилью — в docs/impl_diff.md (перо ловит только Кида; синее зелье без своей вспышки). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -118,6 +118,10 @@
|
||||
#define SCREENSPACE_X 58
|
||||
#define FALL_ACCEL 3
|
||||
#define FALL_MAX 33
|
||||
/* Перо (seg006:057C, types.h:1435): ускорение и потолок скорости падения
|
||||
* под зельем медленного падения. */
|
||||
#define FALL_ACCEL_FEATHER 1
|
||||
#define FALL_MAX_FEATHER 4
|
||||
|
||||
#define TILE_MIDX 7
|
||||
#define FRAME_THIN 0x20
|
||||
@@ -158,6 +162,11 @@ static uint8_t *g_fg; /* fg[30], row*10+col (МУТАБЕЛЬНАЯ
|
||||
static uint8_t g_curr_tile; /* = curr_tile2: тайл последнего get_tile */
|
||||
static uint8_t g_obj_xl; /* позиция внутри тайла (get_tile_div_mod) */
|
||||
static uint8_t grab_timer; /* после зацепа (12): блокирует climb-up */
|
||||
/* is_feather_fall (seg000:15F8): кадров, пока действует зелье медленного
|
||||
* падения. У оригинала это флаг + счётчик тиков со сроком по звуку; у нас
|
||||
* просто обратный отсчёт кадров (POP_FEATHER_FRAMES, pop_tune.h). Публичный:
|
||||
* его читают play_seq (опкод JMP_IF_FEATHER, pop_kid.c) и приложение. */
|
||||
uint8_t pop_feather;
|
||||
/* Состояние edge-триггера бампа — массивы флагов перекрытия по колонкам
|
||||
* (порт prev_coll_flags/curr_row_coll_flags, seg004); объявлены ниже, рядом
|
||||
* с check_collisions. Сброс при смене комнаты — coll_prev_row. */
|
||||
@@ -823,8 +832,19 @@ static void do_fall(void)
|
||||
static void fall_accel(void)
|
||||
{
|
||||
if (Char.action == ACT_FREEFALL) {
|
||||
int fy = (uint8_t)Char.fall_y + FALL_ACCEL;
|
||||
if (fy > FALL_MAX) fy = FALL_MAX;
|
||||
int fy;
|
||||
/* Перо (seg006:057C). Оригинал ловит эффектом ЛЮБОГО персонажа в
|
||||
* Char — зелье пьёт только Кид, но флаг глобальный, и страж, упавший
|
||||
* в ту же минуту, тоже парит; SDLPoP чинит это опцией
|
||||
* fix_feather_fall_affects_guards. Берём поведение С ФИКСОМ (только
|
||||
* Кид): расхождение осознанное, запись в ../docs/impl_diff.md. */
|
||||
if (pop_feather && Char.charid == CHARID_0_KID) {
|
||||
fy = (uint8_t)Char.fall_y + FALL_ACCEL_FEATHER;
|
||||
if (fy > FALL_MAX_FEATHER) fy = FALL_MAX_FEATHER;
|
||||
} else {
|
||||
fy = (uint8_t)Char.fall_y + FALL_ACCEL;
|
||||
if (fy > FALL_MAX) fy = FALL_MAX;
|
||||
}
|
||||
Char.fall_y = (int8_t)fy;
|
||||
}
|
||||
}
|
||||
@@ -1157,7 +1177,7 @@ uint8_t pop_item_taken; /* 0 = нет; иначе tilepos+1 подн
|
||||
uint8_t pop_flash_time; /* кадров вспышки фона (flash_time) */
|
||||
/* Цвет вспышки: 0 = ярко-жёлтая (меч), 1 = красная (зелье). В оригинале это
|
||||
* flash_color; нам хватает двух значений, которые реально встречаются. */
|
||||
uint8_t pop_flash_red;
|
||||
uint8_t pop_flash_color;
|
||||
static int8_t pickup_obj_type; /* -1 = меч (порт pickup_obj_type) */
|
||||
|
||||
/* do_pickup (seg006:1671): стереть предмет с карты (тайл → пол) и запомнить
|
||||
@@ -1222,22 +1242,38 @@ void pop_proc_get_object(void) __banked
|
||||
case 1: /* здоровье: +1 HP, красная вспышка */
|
||||
if (hitp_curr != hitp_max) {
|
||||
hitp_delta = 1;
|
||||
pop_flash_red = 1;
|
||||
pop_flash_color = POP_FLASH_RED;
|
||||
pop_flash_time = 2;
|
||||
}
|
||||
break;
|
||||
case 2: /* большая склянка: +1 к ПОТОЛКУ HP */
|
||||
pop_kid_add_life();
|
||||
pop_flash_red = 1;
|
||||
pop_flash_color = POP_FLASH_RED;
|
||||
pop_flash_time = 4; /* seg006:1878 — вспышка длиннее */
|
||||
break;
|
||||
case 5: /* «злое» зелье: −1 HP */
|
||||
hitp_delta = -1;
|
||||
pop_flash_red = 1;
|
||||
pop_flash_time = 2;
|
||||
case 3: /* ПЕРО: медленное падение */
|
||||
/* feather_fall (seg000:15F8): взвести эффект + ЗЕЛЁНАЯ вспышка
|
||||
* на 3 кадра (flash_color = 2). Оригинал здесь же глушит звуки
|
||||
* и играет sound_39_low_weight — по нему же меряет срок; у нас
|
||||
* срок задан кадрами (POP_FEATHER_FRAMES). */
|
||||
pop_feather = POP_FEATHER_FRAMES;
|
||||
pop_flash_color = POP_FLASH_GREEN;
|
||||
pop_flash_time = 3;
|
||||
break;
|
||||
default: /* 3 перо / 4 переворот / 6 открыть —
|
||||
* TODO вместе с их уровнями (7/9) */
|
||||
case 5: /* «злое» зелье (синее): −1 HP */
|
||||
/* seg006:1892. Своей вспышки у этой ветки НЕТ (в отличие от
|
||||
* лечебных): красный кадр даёт общий механизм «Кид ранен»
|
||||
* (flash_if_hurt, seg003:0AFC) — у нас pop_kid_hurt. Раньше мы
|
||||
* ставили вспышку руками, то есть красили экран дважды.
|
||||
* Спецсобытие уровня зелий: там синие склянки забирают ПОЛОВИНУ
|
||||
* запаса, а не одну единицу. */
|
||||
if (pop_current_level == POP_POTIONS_LEVEL)
|
||||
hitp_delta = (int8_t)(-((hitp_max + 1) >> 1));
|
||||
else
|
||||
hitp_delta = -1;
|
||||
break;
|
||||
default: /* 4 переворот / 6 открыть — TODO
|
||||
* вместе с их уровнями (9/13) */
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2556,6 +2592,10 @@ static void check_chomped_guard(void)
|
||||
static void kid_phys(void)
|
||||
{
|
||||
if (grab_timer) grab_timer--;
|
||||
/* do_timers (seg003:0517): срок действия пера тикает раз в игровой кадр.
|
||||
* Место — у Кида, а не у стража: эффект в оригинале снимается общим
|
||||
* таймером главного цикла, а у нас единственный кадровый тик Кида. */
|
||||
if (pop_feather) pop_feather--;
|
||||
fall_accel();
|
||||
fall_speed();
|
||||
determine_col();
|
||||
|
||||
Reference in New Issue
Block a user