L1-START + L1-EXIT: старт по данным уровня и выход через дверь уровня
L1-START. Старт и оба рестарта (смерть, выпадение из уровня) сведены в pop_start_level() — порт start_level + do_startpos + set_start_pos (seg003). Комната/тайл/направление берутся из pop_level_start_*, направление инвертируется (~start_dir), поза входа — из tbl_entry_pose: у уровня 1 это падение внутрь (seq_7_fall) плюс нажатие кнопки room5(0,2), то самое, что захлопывает решётку за спиной. Жёсткие START_ROOM/COL/ROW убраны. Проверено в MAME: старт даёт room 1, col 0, падение на row 1 — как по данным. L1-EXIT. Ветка двери уровня из up_pressed + go_up_leveldoor (seg005:0482/ 0574): тайлы и геометрия — pop_leveldoor_enter() в pop_map, последовательность seq_70 — в pop_ctrl. Опкод 0xF1 END_LEVEL в play_seq инкрементит pop_next_level (порт next_level), главный цикл по нему перезапускает уровень — ровно та точка, куда levels_plan §2.2 подключит загрузку уровня 2. Открытость двери проверяется по modifier >= 42 (ветка fix_exit_door), а не по ванильному leveldoor_open: иначе можно войти в ещё ползущую створку. Отдельно стоило разбора: go_up_leveldoor сначала писал Char.x/Char.direction, и оба присваивания молча терялись — окно Char вокруг диспетчера возвращает назад только curr_seq и sword (pop_savekid_state). Направление оставалось «вправо», а все DX в seq_70 отрицательные, поэтому Кид уходил ИЗ проёма влево (поймано стоп-кадром). Геометрию персонажа в этом порте меняет pop_map, пишет в Kid — как pop_down_action и pop_jump_up_seq. Известный остаток — BUG-DOOR-CLIP в bug_list.md: нет обрезки силуэта правым косяком проёма (недопортирован obj_clip_right в clip_char); нужен вариант колоночного блита с ограничением ширины. ROOMNAV пока оставлен включённым — он нужен, чтобы попадать в комнату 9 для этой работы. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
#include "pop_bg.h"
|
||||
#include "pop_state.h"
|
||||
#include "pop_trob.h" /* room_modif + trob-список (пики/ворота) */
|
||||
#include "pop_level.h" /* pop_level_start_room — вход в дверь уровня */
|
||||
|
||||
/* ---- Тайлы / действия / seq id (подмножество PoP) ------------------ */
|
||||
#define TILE_EMPTY 0
|
||||
@@ -46,6 +47,7 @@
|
||||
#define TILE_POTION 10 /* зелье */
|
||||
#define TILE_SWORD 22 /* меч на полу */
|
||||
#define TILE_OPENER 15 /* кнопка-открывалка (RAISE, 0x0F) */
|
||||
#define TILE_LEVELDOOR_LEFT 16 /* ЛЕВАЯ половина двери уровня (на ней modif) */
|
||||
#define ACT_STAND 0
|
||||
#define ACT_RUNJUMP 1
|
||||
#define ACT_HANGCLIMB 2
|
||||
@@ -777,6 +779,58 @@ uint8_t pop_hang_fall_seq(void) __banked
|
||||
* либо спуск seq_68 через зацеп, либо отступ от передней кромки), 0 =
|
||||
* приседать. Меняет Kid.x. Kid развёрнут от края (край сзади) у кромки
|
||||
* пола + под соседним тайлом есть за что зацепиться → спуск на этаж вниз. */
|
||||
/* Ветка «войти в дверь уровня» из up_pressed (seg005:0482) вместе с
|
||||
* go_up_leveldoor (seg005:0574). Дверь рядом и открыта → поставить Кида в
|
||||
* проём, вернуть 1 (последовательность seq_70 ставит вызывающий — это его
|
||||
* слой); иначе 0 и Кид не тронут.
|
||||
*
|
||||
* Геометрию персонажа меняем в Kid, а НЕ в Char: окно Char вокруг
|
||||
* диспетчера возвращает назад ТОЛЬКО curr_seq и sword
|
||||
* (pop_savekid_state), поэтому во всём порте позицию правит pop_map — как
|
||||
* в pop_down_action и pop_jump_up_seq. Запись в Char.x/Char.direction
|
||||
* отсюда молча теряется (проверено: Кид уходил из проёма влево).
|
||||
*
|
||||
* Порядок проб как в оригинале и с той же семантикой `else if`: берём
|
||||
* ПЕРВУЮ клетку, в которой стоит дверь (под персонажем → за спиной → перед
|
||||
* лицом), и уже её проверяем на открытость — а не ищем «первую открытую».
|
||||
*
|
||||
* Открытость: `modifier >= 42`, то есть створка доехала до верха. Это
|
||||
* ветка fix_exit_door, а не ванильный глобал leveldoor_open: с ванильным
|
||||
* условием в дверь можно войти, пока она ещё ползёт вверх, и персонаж
|
||||
* проходит сквозь опущенную створку.
|
||||
*
|
||||
* Стартовая комната исключена (`level.start_room != drawn_room`): в первой
|
||||
* комнате уровня дверь — та, через которую вошли, и обратно в неё нельзя. */
|
||||
uint8_t pop_leveldoor_enter(void) __banked
|
||||
{
|
||||
int8_t cols[3];
|
||||
uint8_t i;
|
||||
|
||||
if (pop_level_start_room() == g_room) return 0;
|
||||
|
||||
cols[0] = Kid.curr_col;
|
||||
cols[1] = (int8_t)(dir_behind[Kid.direction + 1] + Kid.curr_col);
|
||||
cols[2] = (int8_t)(dir_front[Kid.direction + 1] + Kid.curr_col);
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (get_tile(cols[i], Kid.curr_row) != TILE_LEVELDOOR_LEFT)
|
||||
continue;
|
||||
/* дверь найдена — дальше решает только её modif (см. выше) */
|
||||
if (cols[i] < 0 || cols[i] > 9) return 0; /* дверь в шве: не наша */
|
||||
if (pop_trob_modif(g_room)[Kid.curr_row * 10 + cols[i]] < 42)
|
||||
return 0;
|
||||
/* go_up_leveldoor (seg005:0574): встать РОВНО в проём и развернуться
|
||||
* ВЛЕВО. Направление тут не косметика: все DX последовательности
|
||||
* seq_70 ОТРИЦАТЕЛЬНЫЕ (−5,−4,−4,−2,−3,−1,−3,−1,−2), а
|
||||
* char_dx_forward при взгляде влево меняет им знак — то есть именно
|
||||
* dir_FF_left и гонит персонажа ВПРАВО-ВВЕРХ по лестнице. При
|
||||
* взгляде вправо тот же seq уводит его влево, ИЗ проёма. */
|
||||
Kid.x = (uint8_t)(pop_x_bump[cols[i] + FIRST_ONSCREEN_COLUMN] + 10);
|
||||
Kid.direction = -1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t pop_down_action(void) __banked
|
||||
{
|
||||
if (!tile_is_floor(get_tile_infrontof_char()) && distance_to_edge_weight() < 3) {
|
||||
|
||||
Reference in New Issue
Block a user