PoP roomtest: меч — отрисовка на полу, подъём по Shift, статус have_sword

Комната 15, тайл (2,2): меч не рисовался вовсе — в draw_tile не было
ветки tiles_22_sword (seg008 draw_tile_anim):

    add_midtable(chtab_1, (modifier == 1) + 10, draw_xh, 0, draw_main_y - 3, ...)

Спрайты уже лежали в нашем pot-атласе (chtab_1 пакуется целиком, id 1..23),
так что понадобился только вызов.  У нас предмет рисуется статикой в фоне,
а не в midtable: пока меч лежит, он не анимируется, а Kid и так поверх фона.

Подъём — порт цепочки оригинала:
- check_get_item/get_item (seg005:061F/073E) -> pop_get_item_action() в
  pop_map (тайлы): стоя НА предмете отступить на тайл назад, подровняться
  по кромке и присесть; из приседа над мечом — поднять;
- do_pickup (seg006:1671): тайл -> пол, pop_item_taken = tilepos+1;
  roomtest запекает пол на ОБЕИХ страницах (pop_floor_bake) и пишет
  per-room override, чтобы меч не воскресал при возврате в комнату;
- триггер — Shift (control_shift2) в стойке и в приседе, как в
  control_standing/control_crouched;
- seq_91 pickupsword: опкод SEQ_GET_ITEM с аргументом 1 в play_seq теперь
  зовёт pop_proc_get_object (seg006:16CB) -> pop_have_sword = 1.

Статус: pop_have_sword.  Боевой режим (стойка с мечом, бой) НЕ делаем и
он тут не нужен: seq_91 сам заканчивается убиранием меча в ножны
(кадры 230..240) и возвратом в обычную стойку — как в оригинале до
встречи со стражем.  Питьё зелий не портировано: над зельем Kid только
приседает (get_item возвращает «не обработано»).

Проверено в MAME (комната 15): меч виден на полу, Shift над ним даёт
присед -> кадр 229 «нашёл меч» -> ножны -> стойка; меч с пола исчезает,
pop_have_sword = 1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 16:46:09 +03:00
parent 6769b6a01b
commit 1c91c5f92a
8 changed files with 120 additions and 2 deletions
+62
View File
@@ -69,6 +69,9 @@
#define SEQ_73_CLIMB_UP_TO_GATE 73 /* подъём к закрытой калитке */
#define SEQ_51_SPIKED 51 /* напороться на пики (смерть) */
#define TILE_FLOOR 1
#define FRAME_109_CROUCH 109
/* Кадры анимации для check_spiked (seg006:0658). */
#define FRAME_7_RUN 7
#define FRAME_26_STANDJUMP_LAND 26
@@ -763,6 +766,65 @@ uint8_t pop_down_action(void)
return 0;
}
/* ---- Предметы: меч (seg005 check_get_item/get_item + seg006 do_pickup/
* proc_get_object) --------------------------------------------------- *
* pop_have_sword — порт глобала have_sword: «меч у Кида». Боевой режим
* (стойка с мечом, бой) НЕ реализован и здесь не нужен: сиквенс подъёма
* seq_91 сам заканчивается убиранием меча в ножны (кадры 230..240 sheathe)
* и возвратом в обычную стойку — как в оригинале до встречи со стражем. */
uint8_t pop_have_sword;
uint8_t pop_item_taken; /* 0 = нет; иначе tilepos+1 поднятого */
static int8_t pickup_obj_type; /* -1 = меч (порт pickup_obj_type) */
/* do_pickup (seg006:1671): стереть предмет с карты (тайл → пол) и запомнить
* тип; сам эффект применяет опкод GET_ITEM внутри сиквенса. */
static void do_pickup(int8_t obj_type, uint8_t tilepos)
{
pickup_obj_type = obj_type;
g_fg[tilepos] = TILE_FLOOR;
pop_item_taken = (uint8_t)(tilepos + 1);
}
/* proc_get_object (seg006:16CB): эффект поднятого предмета. Зовётся из
* play_seq по опкоду SEQ_GET_ITEM с аргументом 1 (pop_kid). */
void pop_proc_get_object(void)
{
if (pickup_obj_type == -1)
pop_have_sword = 1; /* в оригинале have_sword = -1 */
pickup_obj_type = 0; /* зелья (типы 1..6) не портированы */
}
/* check_get_item + get_item (seg005:061F/073E). Возврат: 0 — предмета нет
* (управление идёт обычной веткой); 1 — присесть (caller зовёт crouch());
* 2 — поднять меч (caller ставит seq_91). */
uint8_t pop_get_item_action(void)
{
uint8_t t;
int8_t icol;
t = get_tile_at_char();
if (t == TILE_POTION || t == TILE_SWORD) { /* стоим НА предмете */
if (!tile_is_floor(get_tile_behind_char())) return 0;
Kid.x = (uint8_t)char_dx_forward(-TILE_SIZEX); /* отступить на тайл */
determine_col();
}
t = get_tile_infrontof_char(); /* заодно ставит g_infrontx */
if (t != TILE_POTION && t != TILE_SWORD) return 0;
icol = g_infrontx;
if (icol < 0 || icol > 9) return 0; /* предмет за швом — не наш */
if (Kid.frame != FRAME_109_CROUCH) {
/* Ещё стоим: подровняться к предмету и присесть. */
int d = pop_edge_distance(); /* ставит g_edge_type */
if (g_edge_type != EDGE_FLOOR)
Kid.x = (uint8_t)char_dx_forward((int8_t)d);
if (Kid.direction >= 0)
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;
}
/* ---- Диспетчер ----------------------------------------------------- */
static void check_on_floor(void)
{