L2: переход между уровнями и игра уровня 2
Порт levels_plan.md §2 (шаг 1) — машинерия смены уровня целиком. - Номер уровня стал состоянием: pop_current_level (порт current_level), pop_next_level больше не флаг, а НОМЕР; главный цикл срабатывает по расхождению next != current (порт play_level_2, seg003:0386). - pop_level_load_num(n): LEVELS\res20NN.bin (fallback a:\), старая EMM-страница отпускается только после успешной загрузки новой. На диск кладутся все 15 уровней (34 КБ). - Потабличные различия (data.h:840..848) — таблицы по 16 в pop_level.c: tbl_entry_pose, tbl_guard_hp (HP стража ушло из хардкода 3), tbl_guard_type (−1 = стражей на уровне нет), tbl_level_type. - find_start_level_door (seg003:02E6): на уровне 2 стартовый тайл — правая половина двери уровня, без modif=43 + add_trob(...,3) Кид материализуется внутри глухой створки. Тип 3 = дверь захлопывается за спиной, как в оригинале. - HP через уровень: hitp_beg_lev (seg003) — рестарт уровня откатывает HP к нему, пройденный уровень подтягивает его к hitp_max. Заодно большая склянка add_life (тип зелья 2: +1 к потолку HP до 10) — на уровне 2 она есть, комната 20. - have_sword = level >= 2 (play_level, seg003:106). - Чит Shift+L — следующий уровень (seg000:698). Проверено в MAME: уровень 1 → Shift+L → уровень 2 (комната 5, новые для нас тайлы 8/9 «большая колонна» на месте, дверь захлопнута, HP 3) → влево в комнату 4 со стражем → Shift+L → уровень 3. Вход в стартовую дверь уровня 2 по Up не срабатывает — как и должно (start_room-гард). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -444,6 +444,88 @@ BUG-1 (провал на row 1 при переходе через открыты
|
||||
вверх, шов при анимации решётки, грани дальней колонны) и подъём на
|
||||
тайл-кнопку: см. оговорку к BUG-3 в [`bug_closed.md`](bug_closed.md).
|
||||
|
||||
### L2. Переход на уровень 2 и его игра — **МАШИНЕРИЯ СДЕЛАНА 2026-08-04**
|
||||
|
||||
Порт `levels_plan.md` §2 (шаг 1). Что появилось:
|
||||
|
||||
- **Номер уровня стал состоянием.** `pop_current_level` (порт
|
||||
`current_level`) в `pop_level.c`; `pop_next_level` больше не флаг, а
|
||||
НОМЕР — `END_LEVEL` его инкрементит (как `++next_level`, seg006:662), а
|
||||
главный цикл срабатывает по расхождению `pop_next_level !=
|
||||
pop_current_level` (порт `play_level_2`, seg003:0386).
|
||||
- **Загрузка по номеру** — `pop_level_load_num(n)`: `LEVELS\res20NN.bin`
|
||||
(fallback `a:\`), старая EMM-страница отпускается ТОЛЬКО после успешной
|
||||
загрузки новой (нет файла — играем дальше на текущем). На диск кладутся
|
||||
все 15 уровней (34 КБ).
|
||||
- **Потабличные различия** (`data.h:840..848`) — таблицы по 16 в
|
||||
`pop_level.c`: `tbl_entry_pose` (поза входа), `tbl_guard_hp` (HP стража,
|
||||
ушло из хардкода `3`), `tbl_guard_type` (**−1 = стражей нет**, иначе на
|
||||
14/15 они полезли бы из данных комнат), `tbl_level_type` (тайлсет —
|
||||
пока только читается).
|
||||
- **`find_start_level_door`** (seg003:02E6) — на уровне 2 это НЕ косметика:
|
||||
стартовый тайл (комната 5, ряд 1, колонка 3) — правая половина двери
|
||||
уровня, и без `modif = 43` + `add_trob(...,3)` Кид материализуется внутри
|
||||
глухой створки. Тип 3 = «быстро закрыть»: дверь захлопывается за спиной
|
||||
за три кадра, как в оригинале.
|
||||
- **HP через уровень** — `hitp_beg_lev` (seg003): рестарт уровня
|
||||
откатывает HP к нему, пройденный уровень подтягивает его к `hitp_max`.
|
||||
Заодно реализована **большая склянка** (`add_life`, тип зелья 2: +1 к
|
||||
ПОТОЛКУ HP до 10) — на уровне 2 она есть, комната 20.
|
||||
- **Меч** — `have_sword = level >= 2` (play_level, seg003:106), а не
|
||||
жёсткий ноль.
|
||||
- **Чит Shift+L** (seg000:698) — `pop_next_level = pop_current_level + 1`.
|
||||
NB: `L` без Shift занят отладочным «осторожным шагом вправо»
|
||||
(`pop_ctrl` `KBD_DBG_STEPR`); с Shift шаг тоже пройдёт, но уровень тут же
|
||||
сменится — на практике не мешает.
|
||||
|
||||
**Проверено в MAME (2026-08-04):** старт уровня 1 → Shift+L → уровень 2
|
||||
рисуется правильно (комната 5, большие колонны — новые для нас тайлы 8/9 —
|
||||
на месте, дверь захлопнута, HP 3) → влево в комнату 4, страж на месте →
|
||||
Shift+L → уровень 3 (комната 9). То есть цепочка загрузок работает
|
||||
повторно, а не только один раз.
|
||||
|
||||
**Что осталось по уровню 2 (не машинерия, а контент):**
|
||||
- сквозное прохождение уровня 2 руками — приёмка, как L1-PASS;
|
||||
- выход через дверь уровня 2 (комната 23) вживую: путь тот же, что уже
|
||||
закрыт на уровне 1 (L1-EXIT), но не прогнан на этом уровне;
|
||||
- цвет стража из данных (`guards_color`, на уровне 2 их три разных) — у нас
|
||||
один атлас; отдельная задача, к переходам отношения не имеет.
|
||||
|
||||
### DBG-CHEATS. Отладочные читы SDLPoP — разведка сделана, код не написан
|
||||
|
||||
Записано 2026-08-03 (по ходу охоты за BUG-GATE-PASS-1, отложено на потом).
|
||||
Мотив прямой: мост MAME **теряет нажатия при быстрой отправке**, поэтому
|
||||
подогнать Кида в нужную позу для отладки автоматикой сейчас нельзя — именно
|
||||
на это упёрлись BUG-LOOSE-2 и BUG-GATE-PASS-1.
|
||||
|
||||
**Берём (дёшево и бьёт в наш класс багов):**
|
||||
|
||||
- **`[` / `]` — сдвинуть Кида на пиксель влево/вправо.** Оригинал —
|
||||
`../SDLPoP/src/seg000.c:1828`:
|
||||
```c
|
||||
if (key_states[SDL_SCANCODE_RIGHTBRACKET] & key_state) ++Char.x;
|
||||
else if (key_states[SDL_SCANCODE_LEFTBRACKET] & key_state) --Char.x;
|
||||
```
|
||||
У нас: коды PS/2 set 2 `[` = **0x54**, `]` = **0x5B** в `pop_cheat.h`
|
||||
рядом с `KBD_CHEAT_KILL/IMMO/SWORD`; обработка — в том же блоке читов
|
||||
`roomtest.c` (~строка 479), **по фронту** (`*_prev`, как у остальных),
|
||||
иначе одно нажатие уедет на десяток пикселей. Работает по `Kid.x`
|
||||
напрямую: геометрию персонажа в этом порте меняет не диспетчер (см.
|
||||
грабли L1-EXIT).
|
||||
Первый же потребитель — BUG-GATE-PASS-1: там надо снять `Kid.x` и
|
||||
`Kid.curr_col` в момент, когда решётка уже закрылась, а Кид ещё стоит
|
||||
на её тайле.
|
||||
- **Shift+L — следующий уровень.** Уже входит в L2-машинерию
|
||||
(`../docs/levels_plan.md` §2.4): `++pop_next_level` и всё.
|
||||
|
||||
**Остальные — оценка, а не обязательство:**
|
||||
|
||||
| Чит | Вердикт |
|
||||
|-----|---------|
|
||||
| **T — таймер** | **не сейчас**: таймера уровня у нас нет вообще (Фаза 6), чит пришлось бы делать вместе с механикой |
|
||||
| **F — остаток feather-fall** | **вместе с Shift+W**: ветка `JMP_IF_FEATHER` (опкод `0xF7`) в `play_seq` есть, но не проверена ничем; индикатор без самого зелья бесполезен, а пара «включить + видеть остаток» закрывает ветку целиком. Перо — уровень 7, так что не срочно |
|
||||
| **Shift+F9 — quickload с тем же уровнем** | **самое ценное и самое дорогое**: это сериализация `Char` + `room_modif` всех комнат + trob'ов + стражей (`levels_plan.md` §4). Даёт воспроизводимый регресс «вот кадр, где баг» вместо ручной подгонки. Кандидат сразу после того, как заработают уровни |
|
||||
|
||||
---
|
||||
|
||||
## Отложено осознанно (не брать, пока не появится причина)
|
||||
|
||||
Reference in New Issue
Block a user