BUG-CTRL-FRAME-1: геометрия Кида считалась по кадру стража
cur_frame — один глобал на всех персонажей (как в оригинале), владелец — тот, кто последним прошёл load_frame. Последним в кадре тикает страж, поэтому к моменту control() Кида там лежал кадр СТРАЖА, а через kid_cur_dx/dy/flags по нему считается вся геометрия управления: dx_weight -> determine_col -> distance_to_edge_weight -> get_edge_distance -> выбор ветки в check_jump_up. Оригинал зовёт load_fram_det_col() (seg006:0144) сразу после loadkid/loadshad и ДО control() — play_kid_frame (seg000:1211) и play_guard_frame (seg000:1248). У нас этого не было. Замерено брейкпоинтом на pop_jump_up_seq: Kid x=156 col=6 кадр 15 (dx=0 weight_x=3) при кадре стража image17 (dx=-1 weight_x=8) дал curr_col=7 и distance=2 вместо 6 и 10 — то есть jump_up_plain (вернулось A=28, пустой прыжок) вместо «шаг назад на x=160 + зацеп». Предсказание по кадру стража совпало с намеренным до единицы. Отсюда же плавающее поведение: кадр стража меняется каждый тик, distance Кида скакал через порог 6 — то прыжок, то попытка зацепа с неверной X. И «голова Кида поверх плиты (1,6)» — не баг отрисовки, а следствие позы, которой в оригинале в этом месте не бывает. Фикс: pop_load_fram_det_col() (pop_kid.c) + вызовы в pop_ctrl_tick и pop_guard_tick. determine_col — только на ветке Кида: у нас он существует лишь для него (pop_map работает с Kid, а не с Char). Разбор с числами — bug_closed.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include "pop_state.h"
|
||||
#include "pop_trob.h" /* room_modif + trob-список (пики/ворота) */
|
||||
#include "pop_level.h" /* pop_level_start_room — вход в дверь уровня */
|
||||
#include "pop_guard.h" /* SWORD_2_DRAWN — ветка приземления с мечом */
|
||||
|
||||
/* ---- Тайлы / действия / seq id (подмножество PoP) ------------------ */
|
||||
#define TILE_EMPTY 0
|
||||
@@ -80,6 +81,7 @@
|
||||
#define SEQ_73_CLIMB_UP_TO_GATE 73 /* подъём к закрытой калитке */
|
||||
#define SEQ_51_SPIKED 51 /* напороться на пики (смерть) */
|
||||
#define SEQ_22_CRUSHED 22 /* разбиться при падении (смерть) */
|
||||
#define SEQ_63_ACTIVE_AFTER_FALL 63 /* стойка С МЕЧОМ после приземления */
|
||||
|
||||
#define TILE_FLOOR 1
|
||||
#define FRAME_109_CROUCH 109
|
||||
@@ -365,6 +367,11 @@ static void determine_col(void)
|
||||
Kid.curr_col = get_tile_div_mod_m7(dx_weight());
|
||||
}
|
||||
|
||||
/* determine_col наружу — для pop_load_fram_det_col (pop_kid): порт связки
|
||||
* load_frame + determine_col (seg006:0144), которую оригинал зовёт перед
|
||||
* control(). См. разбор там. */
|
||||
void pop_determine_col(void) __banked { determine_col(); }
|
||||
|
||||
/* расстояние до края тайла (для in_wall). */
|
||||
static int distance_to_edge(int xpos)
|
||||
{
|
||||
@@ -478,7 +485,20 @@ static void land(void)
|
||||
* приложение рисует «брызги» И даёт КРАСНУЮ вспышку фона (flash_if_hurt,
|
||||
* seg003:0AFC). */
|
||||
if (Kid.fall_y < 22) {
|
||||
seq = SEQ_17_SOFT_LAND;
|
||||
/* seg005:176 — ВЕТКА С МЕЧОМ, и она не косметика. seq_17_soft_land
|
||||
* заканчивается ВЕЧНЫМ циклом на кадре 109 (`jmp softland_crouch` в
|
||||
* seqtbl), из которого выводит только control_crouched(). А
|
||||
* control() при `Char.sword == sword_2_drawn` до него не доходит:
|
||||
* управление уходит в control_with_sword, который знает лишь кадр
|
||||
* 171 (стойка с мечом). То есть Кид, упавший на этаж С ВЫНУТЫМ
|
||||
* МЕЧОМ, в этот присед садится НАВСЕГДА — ровно то, что поймали на
|
||||
* приёмке уровня 2 (BUG-LAND-SWORD-1). Оригинал такой позы не
|
||||
* допускает: с мечом приземление даёт боевую стойку. */
|
||||
if (Kid.sword == SWORD_2_DRAWN) {
|
||||
seq = SEQ_63_ACTIVE_AFTER_FALL;
|
||||
} else {
|
||||
seq = SEQ_17_SOFT_LAND;
|
||||
}
|
||||
} else {
|
||||
uint8_t deadly = (uint8_t)(Kid.fall_y >= 33); /* СНЯТЬ до обнуления */
|
||||
pop_kid_hurt = 1;
|
||||
|
||||
Reference in New Issue
Block a user