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:
@@ -11,6 +11,155 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## BUG-CTRL-FRAME-1. Геометрия Кида считалась по кадру СТРАЖА — **ЗАКРЫТ 2026-08-04**
|
||||||
|
|
||||||
|
Самый неприятный класс: не косметика, а неверные РЕШЕНИЯ движка, причём
|
||||||
|
плавающие — одна и та же поза Кида давала разный результат в зависимости от
|
||||||
|
того, в какой фазе анимации находится страж.
|
||||||
|
|
||||||
|
**Симптом (приёмка уровня 2, комната 4).** Кид под сплошной плитой (1,6),
|
||||||
|
справа от него дыра от упавшей loose-плиты. По ↑ он то прыгает вверх
|
||||||
|
впустую (упираясь головой в плиту), то пытается зацепиться — но **не с той
|
||||||
|
координаты X**, с которой запрыгивает оригинал. Наблюдение пользователя,
|
||||||
|
оказавшееся точным: «похоже, дело в страже — в комнатах без стража то же
|
||||||
|
самое рисуется и работает правильно».
|
||||||
|
|
||||||
|
**Замер (брейкпоинт на входе `pop_jump_up_seq`, состояние снято в момент
|
||||||
|
решения).**
|
||||||
|
|
||||||
|
```
|
||||||
|
_Kid frame=15 (стойка) x=156 y=181 dir=влево curr_col=6 curr_row=2
|
||||||
|
кадр 15 Кида (kid_data.bin): dx=0 weight_x=3
|
||||||
|
pop_gframe (кадр СТРАЖА, image 17): dx=-1 weight_x=8
|
||||||
|
```
|
||||||
|
|
||||||
|
Считаем `dx_weight()` обоими кадрами:
|
||||||
|
|
||||||
|
| | кадр Кида (правильно) | кадр стража (что было) |
|
||||||
|
|---|---|---|
|
||||||
|
| `dx_weight()` | 156+3 = **159** | 156+9 = **165** |
|
||||||
|
| `m7()` | (159−7−58)/14 = 6 ост. **10** | (165−7−58)/14 = 7 ост. **2** |
|
||||||
|
| `curr_col` | 6 | **7** ← намерено |
|
||||||
|
| `distance_to_edge_weight()` | **10** | **2** |
|
||||||
|
| ветка `jump_up_or_grab` | 10 ≥ 6 → шаг назад + зацеп | 2 < 6 → `jump_up_plain` |
|
||||||
|
| результат | x 156 → **160**, `seq_24/8` | x без изменений, **`seq_28`** ← намерено (A=28 на выходе) |
|
||||||
|
|
||||||
|
Обе строки «намерено» совпали с предсказанием по кадру стража до единицы —
|
||||||
|
диагноз подтверждён, а не выведен.
|
||||||
|
|
||||||
|
**Корень.** `cur_frame` (`pop_kid.c:200`) — ОДИН глобал на всех персонажей
|
||||||
|
(так и в оригинале), его владелец — тот, кто последним прошёл `load_frame`.
|
||||||
|
В нашем кадре последним тикает страж (`pop_guard_tick`), поэтому к моменту
|
||||||
|
управления Кидом там лежит кадр стража. А `kid_cur_dx/dy/flags` читают этот
|
||||||
|
глобал напрямую, и через него считается ВСЯ геометрия управления:
|
||||||
|
`dx_weight` → `determine_col` → `distance_to_edge_weight` →
|
||||||
|
`get_edge_distance` → выбор ветки в `check_jump_up`.
|
||||||
|
|
||||||
|
Оригинал страхуется явно и симметрично: `play_kid_frame` (seg000:1209) и
|
||||||
|
`play_guard_frame` (seg000:1246) сразу после `loadkid`/`loadshad` зовут
|
||||||
|
**`load_fram_det_col()`** (= `load_frame` + `determine_col`, seg006:0144) —
|
||||||
|
ДО `control()`. У нас этого вызова не было; в `pop_ctrl_tick` стоял
|
||||||
|
комментарий «кадр не перезагружаем — play_seq в kid_tick сделает это
|
||||||
|
следующим шагом», и он был неверен: `control()` читает `cur_frame` РАНЬШЕ,
|
||||||
|
чем `play_seq` его обновит.
|
||||||
|
|
||||||
|
**Фикс.** `pop_load_fram_det_col()` (`pop_kid.c`) — порт связки; зовётся
|
||||||
|
после `pop_loadkid()` в `pop_ctrl_tick` и после `pop_loadshad_and_opp()` в
|
||||||
|
`pop_guard_tick`. Вторая половина связки (`determine_col`) выполняется
|
||||||
|
только на ветке Кида: `determine_col` у нас существует лишь для него —
|
||||||
|
`pop_map` работает с `Kid` напрямую, а не с абстрактным `Char`.
|
||||||
|
|
||||||
|
**Что это объясняет задним числом.** Плавающее поведение прыжка — кадр
|
||||||
|
стража меняется каждый тик, вместе с ним `dx`/`weight_x`, и `distance`
|
||||||
|
Кида скакал через порог 6. А «голова Кида поверх плиты (1,6)», с которой
|
||||||
|
начался разбор, — не баг отрисовки: Кид просто оказывался в позе, которой
|
||||||
|
в оригинале в этом месте не бывает.
|
||||||
|
|
||||||
|
**Урок.** Любой глобал, который в оригинале «принадлежит активному
|
||||||
|
`Char`», у нас обязан перезагружаться на КАЖДОМ входе в окно `Char` — иначе
|
||||||
|
между персонажами течёт состояние, и баг проявляется только когда в комнате
|
||||||
|
есть второй персонаж. Здесь такой глобал уже ловили однажды: см. запись
|
||||||
|
про кэш кадра отрисовки в `load_frame` (`pop_kid.c:342`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## BUG-LAND-SWORD-1. Кид навсегда застревает в приседе после падения с мечом — **ЗАКРЫТ 2026-08-04**
|
||||||
|
|
||||||
|
**Симптом (приёмка уровня 2).** Страж ударил Кида, Кид потерял HP,
|
||||||
|
провалился через loose-плиту на этаж ниже — и **сел в присед, из которого
|
||||||
|
не выходит**: клавиши не действуют вообще.
|
||||||
|
|
||||||
|
**Что показало ЖИВОЕ состояние в MAME** (мост `mame-z80`, чтение по
|
||||||
|
адресам из `roomtest.noi` — окно застало багу в момент):
|
||||||
|
|
||||||
|
```
|
||||||
|
_Kid frame=109 x=144 y=181 dir=-1 col=6 row=2 action=1 room=4
|
||||||
|
sword=2 (ВЫНУТ) alive=-1 curr_seq=0x2037
|
||||||
|
_holding_sword=1 _can_guard_see_kid=0 control_x/y/shift = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
`curr_seq = 0x2037` — это внутри метки `softland_crouch`
|
||||||
|
(`SEQTBL_BASE + 1736 = 0x2036`). Смотрим `seqtbl.c:916`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
LABEL(softland) // seq_17_soft_land
|
||||||
|
act(actions_5_bumped), SEQ_KNOCK_DOWN, dx(1), frame_107_fall_land_1,
|
||||||
|
dx(2), frame_108_fall_land_2,
|
||||||
|
act(actions_1_run_jump), LABEL(softland_crouch) frame_109_crouch,
|
||||||
|
jmp(softland_crouch), // ВЕЧНЫЙ ЦИКЛ на кадре 109
|
||||||
|
```
|
||||||
|
|
||||||
|
То есть `seq_17_soft_land` **не заканчивается сам** — он крутится на кадре
|
||||||
|
109, и вывести из него может ТОЛЬКО `control_crouched()`.
|
||||||
|
|
||||||
|
**Корень.** `control()` (seg005:252) до `control_crouched` при вынутом
|
||||||
|
мече не доходит — раньше срабатывает ветка
|
||||||
|
|
||||||
|
```c
|
||||||
|
} else if (Char.sword == sword_2_drawn) {
|
||||||
|
control_with_sword();
|
||||||
|
```
|
||||||
|
|
||||||
|
а `control_with_sword` (seg005:964) в мирной обстановке
|
||||||
|
(`can_guard_see_kid < 2`, под ногами не loose) умеет ровно одно: если кадр
|
||||||
|
== 171 (стойка с мечом) — убрать меч. Кадр 109 он не знает. **Замкнутый
|
||||||
|
круг: последовательность ждёт control_crouched, а диспетчер туда не
|
||||||
|
пускает.**
|
||||||
|
|
||||||
|
Оригинал такой позы просто не допускает — `land()` (seg005:176):
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (Char.charid >= charid_2_guard || Char.sword == sword_2_drawn) {
|
||||||
|
Char.sword = sword_2_drawn;
|
||||||
|
seq_id = seq_63_guard_active_after_fall; // боевая стойка
|
||||||
|
} else {
|
||||||
|
seq_id = seq_17_soft_land; // присед
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**У нас этой ветки не было** — `pop_map.c land()` ставил
|
||||||
|
`SEQ_17_SOFT_LAND` безусловно. На уровне 1 не всплывало, потому что там
|
||||||
|
меч подбирается поздно и падать с ним особо негде; на уровне 2 меч у Кида
|
||||||
|
**с первого кадра** (`have_sword = level >= 2`), а в комнате 4 страж стоит
|
||||||
|
в одном ряду с двумя loose-плитами — сценарий собирается сам.
|
||||||
|
|
||||||
|
**Фикс.** Порт недостающей ветки: при `Kid.sword == SWORD_2_DRAWN`
|
||||||
|
падение на один этаж даёт `seq_63` (боевая стойка), а не присед. Ветка
|
||||||
|
`charid >= charid_2_guard` нам не нужна — наш `land()` работает только с
|
||||||
|
Кидом.
|
||||||
|
|
||||||
|
**Почему не задело падение на ДВА этажа** (`seq_20_medium_land`): там
|
||||||
|
`jmp` в конце нет — 29 кадров приседа и автоматический подъём
|
||||||
|
(`seqtbl.c:934`), поэтому оно развязывается само. Вечный цикл только у
|
||||||
|
`softland`.
|
||||||
|
|
||||||
|
**Урок на будущее.** Симптом «персонаж не реагирует на управление» стоит
|
||||||
|
диагностировать не по кадру, а по `curr_seq`: адрес прямо показывает, в
|
||||||
|
какой метке `seqtbl` он завис, и дальше видно, кто обязан был его оттуда
|
||||||
|
вывести.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Проверено в MAME 2026-08-01 (ревизия L1-TRIAGE)
|
## Проверено в MAME 2026-08-01 (ревизия L1-TRIAGE)
|
||||||
|
|
||||||
Три бага стояли как **Critical** с 2026-07-21 и по исходникам выглядели
|
Три бага стояли как **Critical** с 2026-07-21 и по исходникам выглядели
|
||||||
|
|||||||
@@ -491,6 +491,9 @@ void pop_guard_tick(void) __banked
|
|||||||
{
|
{
|
||||||
if (Guard.charid == 0) return; /* стража в комнате нет */
|
if (Guard.charid == 0) return; /* стража в комнате нет */
|
||||||
pop_loadshad_and_opp(); /* Char = Guard, Opp = Kid */
|
pop_loadshad_and_opp(); /* Char = Guard, Opp = Kid */
|
||||||
|
/* Симметрично Киду (play_guard_frame, seg000:1248): cur_frame один на
|
||||||
|
* всех, и до этой строки в нём лежит кадр КИДА — он тикал раньше. */
|
||||||
|
pop_load_fram_det_col();
|
||||||
play_guard();
|
play_guard();
|
||||||
/* Анимация: та же seqtbl, что у Кида, но своя таблица кадров —
|
/* Анимация: та же seqtbl, что у Кида, но своя таблица кадров —
|
||||||
* выбирается по Char.charid внутри load_frame (seg006:0293). */
|
* выбирается по Char.charid внутри load_frame (seg006:0293). */
|
||||||
|
|||||||
@@ -707,9 +707,16 @@ void pop_ctrl_tick(void)
|
|||||||
read_user_control();
|
read_user_control();
|
||||||
/* Окно Char вокруг диспетчера: control() работает с АКТИВНЫМ
|
/* Окно Char вокруг диспетчера: control() работает с АКТИВНЫМ
|
||||||
* персонажем (как в оригинале), поэтому ввод игрока применяется к
|
* персонажем (как в оригинале), поэтому ввод игрока применяется к
|
||||||
* Киду только внутри loadkid/savekid. Кадр не перезагружаем —
|
* Киду только внутри loadkid/savekid.
|
||||||
* play_seq в kid_tick сделает это следующим шагом. */
|
*
|
||||||
|
* load_fram_det_col ОБЯЗАТЕЛЕН здесь — порт play_kid_frame
|
||||||
|
* (seg000:1209), где он стоит ровно между loadkid_and_opp() и
|
||||||
|
* play_kid(). cur_frame один на всех персонажей, и в кадре последним
|
||||||
|
* его перезаписывает страж; без перезагрузки диспетчер считает
|
||||||
|
* геометрию Кида (dx_weight -> determine_col -> distance_to_edge_weight
|
||||||
|
* -> get_edge_distance) по кадру СТРАЖА. Замерено: BUG-CTRL-FRAME-1. */
|
||||||
pop_loadkid();
|
pop_loadkid();
|
||||||
|
pop_load_fram_det_col();
|
||||||
user_control(); /* -> pop_control(): может сменить Char.curr_seq */
|
user_control(); /* -> pop_control(): может сменить Char.curr_seq */
|
||||||
pop_savekid_state();
|
pop_savekid_state();
|
||||||
save_ctrl_1();
|
save_ctrl_1();
|
||||||
|
|||||||
@@ -450,6 +450,40 @@ void play_seq(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* load_fram_det_col (seg006:0144) = load_frame() + determine_col().
|
||||||
|
*
|
||||||
|
* Зачем это отдельной публичной точкой. cur_frame — ОДИН глобал на всех
|
||||||
|
* персонажей (так и в оригинале), и его владелец — тот, кто последним
|
||||||
|
* прошёл load_frame. В кадре последним тикает страж, поэтому к моменту
|
||||||
|
* управления Кидом в cur_frame лежит кадр СТРАЖА. А через cur_frame
|
||||||
|
* считается вся геометрия: dx_weight -> determine_col ->
|
||||||
|
* distance_to_edge_weight -> get_edge_distance, то есть буквально выбор
|
||||||
|
* ветки в check_jump_up.
|
||||||
|
*
|
||||||
|
* Оригинал от этого страхуется явно: play_kid_frame (seg000:1209) и
|
||||||
|
* play_guard_frame (seg000:1246) сразу после loadkid/loadshad зовут
|
||||||
|
* load_fram_det_col() — ДО control(). У нас этого не было, и Кид считал
|
||||||
|
* свой прыжок по кадру стража (BUG-CTRL-FRAME-1): при distance 2 вместо 10
|
||||||
|
* check_jump_up уходил в «пустой прыжок вверх» вместо «шаг назад и
|
||||||
|
* зацеп». Результат менялся от кадра к кадру — вместе с анимацией стража.
|
||||||
|
*
|
||||||
|
* determine_col у нас существует только для Кида: pop_map работает с Kid
|
||||||
|
* напрямую, а не с абстрактным Char. Поэтому вторую половину связки делаем
|
||||||
|
* только на его ветке — стражу пока хватает перезагрузки самого кадра (его
|
||||||
|
* колонку ведёт pop_guard_enter/leave). Char.curr_col синхронизируем
|
||||||
|
* руками: окно Char — копия Kid. */
|
||||||
|
void pop_load_fram_det_col(void)
|
||||||
|
{
|
||||||
|
if (!kdat_ok) return;
|
||||||
|
gfx_w0_map(kdat_page);
|
||||||
|
load_frame();
|
||||||
|
gfx_w0_unmap();
|
||||||
|
if (Char.charid == CHARID_0_KID) {
|
||||||
|
pop_determine_col();
|
||||||
|
Char.curr_col = Kid.curr_col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Прокрутить последовательность КОНКРЕТНОГО персонажа (порт связки
|
/* Прокрутить последовательность КОНКРЕТНОГО персонажа (порт связки
|
||||||
* loadkid/play_seq/savekid, seg006). Звать вместо голого play_seq: тот
|
* loadkid/play_seq/savekid, seg006). Звать вместо голого play_seq: тот
|
||||||
* работает с Char и сам по себе не знает, чей это персонаж. */
|
* работает с Char и сам по себе не знает, чей это персонаж. */
|
||||||
|
|||||||
@@ -97,6 +97,13 @@ void pop_char_set_seq(uint8_t seq_id); /* seq активного персон
|
|||||||
void pop_kid_play(void);
|
void pop_kid_play(void);
|
||||||
void pop_guard_play(void);
|
void pop_guard_play(void);
|
||||||
|
|
||||||
|
/* load_fram_det_col (seg006:0144) — перезагрузить cur_frame под АКТИВНОГО
|
||||||
|
* персонажа (Char) и пересчитать его колонку. Звать сразу после pop_loadkid/
|
||||||
|
* pop_loadshad и ДО диспетчера control(), как это делают play_kid_frame /
|
||||||
|
* play_guard_frame (seg000:1209/1246): cur_frame один на всех, и без этого
|
||||||
|
* геометрия одного персонажа считается по кадру другого. */
|
||||||
|
void pop_load_fram_det_col(void);
|
||||||
|
|
||||||
/* Поля текущего кадра kid_frames[Kid.frame] (pop_map, без дублирования
|
/* Поля текущего кадра kid_frames[Kid.frame] (pop_map, без дублирования
|
||||||
* таблицы во втором TU). */
|
* таблицы во втором TU). */
|
||||||
int8_t kid_cur_dx(void);
|
int8_t kid_cur_dx(void);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "pop_state.h"
|
#include "pop_state.h"
|
||||||
#include "pop_trob.h" /* room_modif + trob-список (пики/ворота) */
|
#include "pop_trob.h" /* room_modif + trob-список (пики/ворота) */
|
||||||
#include "pop_level.h" /* pop_level_start_room — вход в дверь уровня */
|
#include "pop_level.h" /* pop_level_start_room — вход в дверь уровня */
|
||||||
|
#include "pop_guard.h" /* SWORD_2_DRAWN — ветка приземления с мечом */
|
||||||
|
|
||||||
/* ---- Тайлы / действия / seq id (подмножество PoP) ------------------ */
|
/* ---- Тайлы / действия / seq id (подмножество PoP) ------------------ */
|
||||||
#define TILE_EMPTY 0
|
#define TILE_EMPTY 0
|
||||||
@@ -80,6 +81,7 @@
|
|||||||
#define SEQ_73_CLIMB_UP_TO_GATE 73 /* подъём к закрытой калитке */
|
#define SEQ_73_CLIMB_UP_TO_GATE 73 /* подъём к закрытой калитке */
|
||||||
#define SEQ_51_SPIKED 51 /* напороться на пики (смерть) */
|
#define SEQ_51_SPIKED 51 /* напороться на пики (смерть) */
|
||||||
#define SEQ_22_CRUSHED 22 /* разбиться при падении (смерть) */
|
#define SEQ_22_CRUSHED 22 /* разбиться при падении (смерть) */
|
||||||
|
#define SEQ_63_ACTIVE_AFTER_FALL 63 /* стойка С МЕЧОМ после приземления */
|
||||||
|
|
||||||
#define TILE_FLOOR 1
|
#define TILE_FLOOR 1
|
||||||
#define FRAME_109_CROUCH 109
|
#define FRAME_109_CROUCH 109
|
||||||
@@ -365,6 +367,11 @@ static void determine_col(void)
|
|||||||
Kid.curr_col = get_tile_div_mod_m7(dx_weight());
|
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). */
|
/* расстояние до края тайла (для in_wall). */
|
||||||
static int distance_to_edge(int xpos)
|
static int distance_to_edge(int xpos)
|
||||||
{
|
{
|
||||||
@@ -478,7 +485,20 @@ static void land(void)
|
|||||||
* приложение рисует «брызги» И даёт КРАСНУЮ вспышку фона (flash_if_hurt,
|
* приложение рисует «брызги» И даёт КРАСНУЮ вспышку фона (flash_if_hurt,
|
||||||
* seg003:0AFC). */
|
* seg003:0AFC). */
|
||||||
if (Kid.fall_y < 22) {
|
if (Kid.fall_y < 22) {
|
||||||
|
/* 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;
|
seq = SEQ_17_SOFT_LAND;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
uint8_t deadly = (uint8_t)(Kid.fall_y >= 33); /* СНЯТЬ до обнуления */
|
uint8_t deadly = (uint8_t)(Kid.fall_y >= 33); /* СНЯТЬ до обнуления */
|
||||||
pop_kid_hurt = 1;
|
pop_kid_hurt = 1;
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ void pop_map_set_room(uint8_t room) __banked;
|
|||||||
* (guards.c): он идёт по ряду между Кидом и стражем. */
|
* (guards.c): он идёт по ряду между Кидом и стражем. */
|
||||||
uint8_t pop_tile_at(int8_t col, int8_t row) __banked;
|
uint8_t pop_tile_at(int8_t col, int8_t row) __banked;
|
||||||
|
|
||||||
|
/* determine_col (seg006:014D): Kid.curr_col = m7(dx_weight()). Наружу — для
|
||||||
|
* pop_load_fram_det_col (pop_kid.c), порт load_fram_det_col. */
|
||||||
|
void pop_determine_col(void) __banked;
|
||||||
|
|
||||||
/* HP/смерть. pop_kid_dead=1 когда Kid убит (пики); hitp_curr — текущее HP.
|
/* HP/смерть. pop_kid_dead=1 когда Kid убит (пики); hitp_curr — текущее HP.
|
||||||
* pop_kid_hp_reset() ставит старт HP и снимает смерть (звать в kid_init/
|
* pop_kid_hp_reset() ставит старт HP и снимает смерть (звать в kid_init/
|
||||||
* респавн). */
|
* респавн). */
|
||||||
|
|||||||
Reference in New Issue
Block a user