Files
Sprinter-SDCC/applications/PoP/roomtest/pop_tune.h
T
snark13 361c9d9f78 Мышь уровня 8 + холодная половина главного цикла в банк 8
Спецсобытие уровня 8 (SDLPoP seg003:0545/0ABA, seg002:07EB): когда дверь
уровня открыта, а Кид остаётся в комнате 16, через 150 кадров приходит мышь,
пробегает справа налево по верхнему ряду, наступает на кнопку (0,7) —
решётка (0,3) открывается — и убегает.

Ассетов не потребовалось: кадры 186..188 идут по таблице Кида, их спрайты
(images 130..132) уже лежат в kid16.atl, отрисовка подхватывает мышь сама.

- guards.c: pop_check_mouse, autocontrol_mouse, ветки мыши в
  autocontrol_opponent / play_guard / check_can_guard_see_kid;
- pop_leveldoor_open стал word, как в оригинале (в него же считается
  задержка — байт переполнился бы через 255 кадров);
- leave_guard больше не записывает тень и мышь в данные уровня (seg002:02F5);
- полосы HP у мыши нет (seg000:1159);
- tests-host/t_mouse: 17 проверок, единственный набор с guards.c.

Разгрузка резидента (куча в huge упала до 879 Б): pop_start_level,
find_start_level_door, чит-навигация по комнатам и лейбл номера уехали в
roomtest_cold.c (--bank 8, n_banks = 8).  _CODE 25653 -> 24825, куча -> 1707 Б;
кадровый путь не тронут.

Проверено: tests-host 6/6, make size-check OK, живьём в MAME (мышь появилась,
нажала кнопку, решётка поехала вверх, мышь ушла).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 15:21:20 +03:00

118 lines
9.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* pop_tune.h — НАСТРАИВАЕМЫЕ КОНСТАНТЫ движка (аналог custom_options
* SDLPoP) в одном месте.
*
* Зачем отдельный заголовок. У оригинала «особые события» уровней зашиты
* магическими числами прямо в код (`current_level == 3 && Char.room == 7`),
* и SDLPoP вынес их в структуру `custom_options_type` (types.h) с
* загрузкой из SDLPoP.ini и правкой через меню Settings/Mods. Нам нужно
* то же самое по двум причинам:
*
* 1. ОТЛАДКА. Некоторые сцены руками почти не проверить (успеть в
* закрывающуюся решётку), и единственный вменяемый способ — временно
* растянуть тайминг. Такие крутилки обязаны жить в одном месте, а не
* прятаться числами по трём модулям.
* 2. МОДЫ. Тот, кто захочет свой набор уровней, меняет ровно эти числа.
*
* Пока это только `#define` — ни INI, ни меню нет (см. TASKS_OPEN.md, запись
* TUNE-1). Но правило уже действует: НОВОЕ «особое событие» или тайминг
* заводится ЗДЕСЬ, а не константой по месту. Имена — как у SDLPoP
* (custom->имя), чтобы сверка с оригиналом оставалась механической.
*/
#ifndef POP_TUNE_H
#define POP_TUNE_H
/* ---- Чекпойнт уровня 3 (SDLPoP: checkpoint_*) ----------------------- *
* Оригинал: level3_set_chkp (seg002:0665) взводит флаг, когда Кид уходит
* ВЛЕВО ИЗ комнаты 7 (вызов стоит до goto_other_room, поэтому Char.room там
* ещё старая); do_startpos (seg003:0141) подменяет по
* нему стартовую позицию и убирает loose-плиту, через которую туда
* попадают (иначе после респавна дорога назад была бы уже провалена). */
#define POP_CHKP_LEVEL 3 /* checkpoint_level */
#define POP_CHKP_ROOM 7 /* комната, ИЗ КОТОРОЙ уходят влево (у
* SDLPoP хардкод; это НЕ комната
* назначения — см. roomtest.c) */
#define POP_CHKP_RESPAWN_ROOM 2 /* checkpoint_respawn_room */
#define POP_CHKP_RESPAWN_TILEPOS 6 /* checkpoint_respawn_tilepos */
#define POP_CHKP_RESPAWN_DIR (-1) /* checkpoint_respawn_dir: влево */
#define POP_CHKP_CLEAR_ROOM 7 /* checkpoint_clear_tile_room */
#define POP_CHKP_CLEAR_COL 4 /* checkpoint_clear_tile_col */
#define POP_CHKP_CLEAR_ROW 0 /* checkpoint_clear_tile_row */
/* ---- Отладочные крутилки (в оригинале и в SDLPoP их НЕТ) ------------ *
* POP_DBG_GATE_HOLD — сколько кадров решётка держится поднятой после
* нажатия кнопки, ПРЕЖДЕ чем пойдёт вниз. В оригинале это таймер связи
* дверей: trigger_button ставит 5, animate_button вычитает по единице, и
* решётка стоит, пока таймер > 1 (то есть ~4 кадра после того, как Кид
* сошёл с кнопки). Проверять руками проход в закрывающуюся решётку при
* таком окне почти невозможно, поэтому значение вынесено сюда: поставь
* 30 — и успеешь дойти спокойно. ОБЯЗАН быть 5 в игровой сборке.
*
* ПОТОЛОК 30. Таймер связи — пять бит модификатора кнопки (маска 0x1F), а
* значение 31 у оригинала означает «событие заклинено» (`link_timer != 0x1F`
* в trigger_button). Больше 30 ставить нельзя — кнопка перестанет
* срабатывать вовсе. */
#define POP_DBG_GATE_HOLD 5
/* ---- Улучшения SDLPoP (в ОРИГИНАЛЕ их нет) -------------------------- *
* POP_ENABLE_JUMP_GRAB — зацепиться за кромку можно ПРЯМО В ПРЫЖКЕ, если
* Shift зажат заранее (SDLPoP `enable_jump_grab`, seg006:1228). Ваниль
* разрешает зацеп только в начале падения (`check_grab`, кадры 102..105),
* то есть Shift приходится нажимать уже в полёте — это и раздражало на
* приёмке. 0 — как в оригинале, 1 — как в SDLPoP с включёнными
* enhancements. */
#define POP_ENABLE_JUMP_GRAB 1
/* ---- Чомперы (SDLPoP: custom->chomper_speed) ------------------------ *
* Период смыкания челюстей в кадрах: фаза крутится 1..N и сбрасывается в 1.
* В оригинале 15; SDLPoP выносит это в настройку, потому что на разных
* уровнях моды любят делать чомперы быстрее. Меньше — злее. */
#define POP_CHOMPER_SPEED 15
/* ---- Отладка сцены «тень крадёт зелье» (уровень 5) ------------------ *
* Тень появляется в комнате 24 сразу при входе, но СТОИТ, пока не откроют
* ворота (кол 1, ряд 0, openness >= 80) — так в оригинале
* (autocontrol_shadow_level5, seg002:1157). Чтобы посмотреть саму сцену
* (подход, питьё, уход), не проходя уровень до кнопки, поставь 1: тень
* стартует запись ходов сразу. ОБЯЗАН быть 0 в игровой сборке. */
#ifndef POP_DBG_SHADOW_NOWAIT
#define POP_DBG_SHADOW_NOWAIT 0
#endif
/* ---- Зелье МЕДЛЕННОГО ПАДЕНИЯ (SDLPoP: FEATHER_FALL_LENGTH) ---------- *
* В оригинале длительность эффекта задана НЕ таймером, а звуком: эффект
* держится, пока играет sound_39_low_weight, и снимается принудительно на
* 225-м тике (do_timers, seg003:0517). Звука у нас нет, поэтому берём тот
* же порог напрямую — 225 ИГРОВЫХ КАДРОВ (у оригинала тик do_timers = кадр
* игрового цикла; 225 кадров при его 12 fps и есть FEATHER_FALL_LENGTH =
* 18,75 с из фикса SDLPoP). По ВРЕМЕНИ у нас выйдет короче ровно настолько,
* насколько наша игра быстрее оригинала — это общий вопрос темпа
* (TASKS_OPEN.md, L1-SPEED), а не свойство зелья. */
#define POP_FEATHER_FRAMES 225
/* ---- Спецсобытие «МЫШЬ» (уровень 8, комната 16) ---------------------- *
* Кнопка (0,7) комнаты 16 открывает решётку (0,3) — ту, за которой лежит
* путь через комнату 4 (два чомпера) к кнопке выхода в комнате 3. Сам Кид
* до кнопки с левой площадки не дотягивается (провал в колонках 4..6),
* поэтому, когда дверь уровня уже открыта, а он всё ещё в комнате 16,
* оригинал через 150 тиков присылает мышь: она пробегает справа налево по
* верхнему ряду, наступает на кнопку и убегает обратно (do_timers
* seg003:0545, do_mouse seg003:0ABA, autocontrol_mouse seg002:07EB).
*
* Числа — custom-константы SDLPoP (data.h:821): уровень/комната/задержка/
* стартовая X. Пороги разворота (166) и исчезновения (200) — литералы
* autocontrol_mouse. Задержка в ИГРОВЫХ КАДРАХ, как POP_FEATHER_FRAMES. */
#define POP_MOUSE_LEVEL 8
#define POP_MOUSE_ROOM 16
#define POP_MOUSE_DELAY 150
#define POP_MOUSE_START_X 200
#define POP_MOUSE_TURN_X 166 /* x < этого — развернуться и уйти */
#define POP_MOUSE_LEAVE_X 200 /* x >= этого в стойке — исчезнуть */
/* ---- Уровень зелий (SDLPoP: «potions level», seg006:1894) ------------ *
* На нём синие склянки «вреда» забирают ПОЛОВИНУ запаса HP, а не единицу.
* В оригинале это условие `current_level == 15` прямо в proc_get_object. */
#define POP_POTIONS_LEVEL 15
#endif /* POP_TUNE_H */