L2: падение с мечом, разбег-прыжок через 3 тайла, стартовое состояние ворот
BUG-FALL-SWORD-1 — start_fall (seg006:1044) был портирован не целиком: не хватало трёх веток выбора последовательности и уборки меча в ножны. Из-за seq_7 с set_fall(1,15) (дрейф 1 px/кадр) Кид с мечом уезжал примерно на тайл вбок; в оригинале это seq_81_fightfall — падение строго вниз. Сверено по логу SDLPoP: кадры 102..105 дают x = 155,157,159,160. BUG-RJUMP-1 — run_jump (seg005:0AA8) не выравнивал Кида по кромке пола перед толчком, а был заглушкой «полировка K3». Суммарный dx seq_4 — 62 px при тайле 14, то есть провал ровно в три тайла берётся ТОЛЬКО с кромки: без выравнивания Кид не перепрыгивал его никогда. Порт — pop_run_jump_align() в pop_map (беззнаковое сравнение оригинала = «сдвиг не попал в [-8,-1]»). На харнессе: было — толчок с x=165, кадр 44 в колонке 3 (провал); стало — 5 кадров добега, толчок с x=149, кадр 44 даёт x=87 col=1 row=1. Остальные 8 сценариев не изменились. BUG-GATEMOD-1 — load_alter_mod (seg008:198E) был портирован только для зелий, поэтому ворота с bg=1 («Open» по спецификации DAT, табл. 8) стартовали закрытыми. Добавлены ветки gate (1 -> 188) и loose. Ветка wall намеренно НЕ портируется: связи стен наш pop_bg считает по типам соседей в момент отрисовки. На уровнях 1-3 таких ворот всего двое (ур. 1 комн. 5 (0,9); ур. 2 комн. 13 (1,5)) — у остальных bg=2, а 2 и 0 ведут себя одинаково. Убран временный трассировщик pop_dbg_trace/pop_dbg_draw; pop_dbg_trap() оставлен как многоразовый инструмент. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -82,6 +82,7 @@
|
||||
#define SEQ_51_SPIKED 51 /* напороться на пики (смерть) */
|
||||
#define SEQ_22_CRUSHED 22 /* разбиться при падении (смерть) */
|
||||
#define SEQ_63_ACTIVE_AFTER_FALL 63 /* стойка С МЕЧОМ после приземления */
|
||||
#define SEQ_81_FIGHTFALL 81 /* fightfall: падение из боевой стойки */
|
||||
|
||||
#define TILE_FLOOR 1
|
||||
#define FRAME_109_CROUCH 109
|
||||
@@ -522,11 +523,34 @@ static void land(void)
|
||||
static void start_fall(void)
|
||||
{
|
||||
uint8_t frame = Kid.frame, seq, tile;
|
||||
/* seg006:1044 первым делом убирает меч в ножны: дальше падением рулит
|
||||
* не боевой диспетчер, а обычный. Без этого Kid летит «с клинком», и
|
||||
* control_with_sword разбирает кадры падения как боевые. */
|
||||
Kid.sword = SWORD_0_SHEATHED;
|
||||
inc_curr_row();
|
||||
/* start_chompers() — чомперов ещё нет (L3-CHOMP). */
|
||||
/* seg006:1044 start_fall: frame 9 -> seq_7, 13 -> seq_19 (лишний dx(1)) */
|
||||
if (frame == 13) seq = SEQ_19_FALL;
|
||||
else if (frame == 26) seq = SEQ_18_FALL_STANDJUMP;
|
||||
else if (frame == 44) seq = SEQ_21_FALL_RUNJUMP;
|
||||
else if (frame >= 81 && frame < 86) {
|
||||
/* сорвался, приземляясь после прыжка вверх: сдвиг ВПЕРЁД на 5 */
|
||||
seq = SEQ_19_FALL;
|
||||
Kid.x = (uint8_t)char_dx_forward(5);
|
||||
pop_load_fram_det_col();
|
||||
}
|
||||
else if (frame >= 150 && frame < 180) {
|
||||
/* Кадры С МЕЧОМ (150..179) — отступил в провал. У оригинала это
|
||||
* ОТДЕЛЬНАЯ последовательность seq_81 (fightfall): падение строго
|
||||
* вниз (set_fall(0,15)), а не seq_7 с дрейфом fall_x=1 — из-за
|
||||
* дрейфа наш Kid уезжал на ~тайл в сторону за время падения.
|
||||
* Плюс сдвиг на 5 назад, если стоит у самой кромки лицом влево.
|
||||
* Ветка стража (seq_82/83) не нужна: start_fall — только Kid.
|
||||
* TODO: droppedout=1 (guard_follows_kid_down, guards.c:296). */
|
||||
if (Kid.direction < 0 && distance_to_edge_weight() <= 7)
|
||||
Kid.x = (uint8_t)char_dx_forward(-5);
|
||||
seq = SEQ_81_FIGHTFALL;
|
||||
}
|
||||
else seq = SEQ_7_FALL; /* frame 9 + stand/step/crouch */
|
||||
kid_set_seq(seq);
|
||||
pop_kid_play();
|
||||
@@ -760,6 +784,47 @@ uint8_t pop_jump_up_seq(void) __banked
|
||||
return jump_up_plain();
|
||||
}
|
||||
|
||||
/* run_jump (seg005:0AA8), часть «выровнять по кромке» ------------------ *
|
||||
* Оригинал НЕ отталкивается откуда попало: перед разбег-прыжком он смотрит
|
||||
* на 1–2 тайла вперёд и, если там провал (или пика), подгоняет X так, чтобы
|
||||
* толчок пришёлся ровно на кромку пола. Иначе прыжок стартует в случайной
|
||||
* фазе бегового цикла — а запаса у seq_4 почти нет: суммарный dx кадров
|
||||
* 34..44 равен 62 px при ширине тайла 14, то есть ровно 4 колонки и меньше
|
||||
* половины тайла сверху. Поэтому без выравнивания провал в ТРИ пустых
|
||||
* тайла (перелёт с колонки 5 на колонку 1) становится непроходимым —
|
||||
* BUG-RJUMP-1, уровень 2, комнаты 1 и 9.
|
||||
*
|
||||
* Возврат: 1 — прыгать (Kid.x уже подогнан), 0 — прыжок ОТМЕНИТЬ. Отмена
|
||||
* в оригинале НЕ гасит control_up: Кид бежит дальше с зажатой «вверх», и на
|
||||
* следующем кадре попытка повторяется — так игрок ловит нужную фазу, просто
|
||||
* удерживая клавишу. */
|
||||
uint8_t pop_run_jump_align(void) __banked
|
||||
{
|
||||
int xpos = char_dx_forward(4);
|
||||
int8_t col = get_tile_div_mod_m7(xpos);
|
||||
uint8_t tf;
|
||||
|
||||
for (tf = 0; tf < 2; tf++) {
|
||||
uint8_t t;
|
||||
col = (int8_t)(col + dir_front[Kid.direction + 1]);
|
||||
t = get_tile(col, Kid.curr_row);
|
||||
if (t != TILE_SPIKE && tile_is_floor(t)) continue; /* тут пол — дальше */
|
||||
|
||||
{
|
||||
int adj = distance_to_edge(xpos) + TILE_SIZEX * (int)tf - TILE_SIZEX;
|
||||
/* Оригинал сравнивает БЕЗЗНАКОВО:
|
||||
* if ((word)adj < (word)-8 || adj >= 2) { if (adj < 128) return; adj = -3; }
|
||||
* что означает ровно «adj НЕ попал в [-8,-1] → прыжка нет».
|
||||
* Ветка с adj = -3 недостижима: distance_to_edge ∈ [0,13] и
|
||||
* tf ∈ {0,1} дают adj ∈ [-14,13], а туда нужно adj >= 128. */
|
||||
if (adj < -8 || adj > -1) return 0;
|
||||
Kid.x = (uint8_t)char_dx_forward((int8_t)(adj + 4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Стена впереди достаточно близко для стопа бега? Детект (без сдвига —
|
||||
* позицию держит check_bumped=in_wall). d<=2: передний край почти у грани. */
|
||||
int pop_wall_ahead(void) __banked
|
||||
|
||||
Reference in New Issue
Block a user