SprPoP: читы здоровья и пера — фаза C плана keys_plan.md
Shift+S — одна единица HP (малое красное зелье), Shift+T — поднять потолок HP (большая склянка), Shift+W — медленное падение (зелье пера). Механика у всех трёх в движке уже была: читы просто ставят те же переменные, что и подобранное зелье. СВЕРКА С SDLPoP дала деталь, которую легко проглядеть: ветка ЧИТА и ветка ЗЕЛЬЯ различаются. Зелье в seg006:1871 зовёт stop_sounds, а чит в seg000:838 — нет. Повторяем чит, а не зелье. Исключение — перо: там stop_sounds сидит внутри самой feather_fall(), поэтому остаётся. Вторая деталь: Shift+T НЕ проверяет, полное ли HP, — потолок растёт всегда (упираясь в POP_MAX_HITP = 10, как max_hitp_allowed оригинала). У Shift+S условие hitp_curr != hitp_max есть и сохранено. Модификаторы разведены: Shift+S делит скан-код с Ctrl+S (звук), поэтому требует отпущенного Ctrl; Shift+T делит с голым T (таймер), но тот сам требует отпущенного Shift. Проверено в MAME по памяти, а не на глаз: Shift+T 3/3 -> 4/4, Shift+W взводит pop_feather в 148, Shift+S на подпорченном отладчиком HP 2/4 -> 3/4. R (воскрешение) НЕ входит: это не ещё один чит, а правка модели смерти — окно неуязвимости, размазанное по кадровой цепочке (счётчик в seg003:512, пропуск пик и челюстей в seg000:1245, пропуск урона мечом в seg000:876, восстановление позы в seg006:1352). Задевает гейт «мёртв», про который memory pop_level_restart_scope прямо предупреждает. Отложено по решению пользователя. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -51,6 +51,7 @@ extern uint8_t pop_cheats; /* 0 = выключены, иначе включ
|
|||||||
|
|
||||||
/* Наши сверхштатные, все под Ctrl, чтобы не занимать голые буквы. */
|
/* Наши сверхштатные, все под Ctrl, чтобы не занимать голые буквы. */
|
||||||
#define KBD_KEY_P 0x4D /* Ctrl+P — режим скорости (pop_pace.h) */
|
#define KBD_KEY_P 0x4D /* Ctrl+P — режим скорости (pop_pace.h) */
|
||||||
|
#define KBD_KEY_W 0x1D /* Shift+W — медленное падение (feather_fall) */
|
||||||
#define KBD_KEY_D 0x23 /* Ctrl+D — отладочная строка вкл/выкл */
|
#define KBD_KEY_D 0x23 /* Ctrl+D — отладочная строка вкл/выкл */
|
||||||
#define KBD_KEY_F 0x2B /* Ctrl+F — стоп-кадр, вкл/выкл одной клавишей */
|
#define KBD_KEY_F 0x2B /* Ctrl+F — стоп-кадр, вкл/выкл одной клавишей */
|
||||||
|
|
||||||
|
|||||||
@@ -534,6 +534,7 @@ uint8_t pop_dbg_roomnav(uint8_t dir) __banked
|
|||||||
static uint8_t cheat_prev, immo_prev, sound_prev, music_prev, nlvl_prev;
|
static uint8_t cheat_prev, immo_prev, sound_prev, music_prev, nlvl_prev;
|
||||||
static uint8_t upsd_prev, xdec_prev, xinc_prev, cfg_prev;
|
static uint8_t upsd_prev, xdec_prev, xinc_prev, cfg_prev;
|
||||||
static uint8_t time_sub_prev, time_add_prev;
|
static uint8_t time_sub_prev, time_add_prev;
|
||||||
|
static uint8_t hp1_prev, hpmax_prev, feather_prev;
|
||||||
|
|
||||||
void pop_cheat_tick(void) __banked
|
void pop_cheat_tick(void) __banked
|
||||||
{
|
{
|
||||||
@@ -590,7 +591,48 @@ void pop_cheat_tick(void) __banked
|
|||||||
/* C — записать POP.CFG сейчас (отладка MS2, до экрана Settings:
|
/* C — записать POP.CFG сейчас (отладка MS2, до экрана Settings:
|
||||||
* там сохранять будет Apply/выход). */
|
* там сохранять будет Apply/выход). */
|
||||||
uint8_t cf = kbd_raw_down(0x21); /* C (PS/2 set 2) */
|
uint8_t cf = kbd_raw_down(0x21); /* C (PS/2 set 2) */
|
||||||
|
/* ЧИТЫ ЗДОРОВЬЯ И ПЕРА (seg000:838, :845, :795).
|
||||||
|
*
|
||||||
|
* Делают то же, что соответствующие зелья, но НЕ через них:
|
||||||
|
* оригинал в этих ветках не зовёт stop_sounds, хотя ветка
|
||||||
|
* зелья зовёт (seg006:1871). Повторяем чит, а не зелье.
|
||||||
|
* Исключение — перо: там stop_sounds сидит внутри самого
|
||||||
|
* feather_fall(), поэтому остаётся.
|
||||||
|
*
|
||||||
|
* Shift+S делит скан-код с Ctrl+S (звук), поэтому Ctrl обязан
|
||||||
|
* быть отпущен; Shift+T — с голым T (таймер), но тот сам
|
||||||
|
* требует отпущенного Shift. */
|
||||||
|
uint8_t shift = (uint8_t)(kbd_raw_down(KBD_LSHIFT) ||
|
||||||
|
kbd_raw_down(KBD_RSHIFT));
|
||||||
|
uint8_t h1 = (uint8_t)(shift && nomod &&
|
||||||
|
kbd_raw_down(KBD_SOUND_TOGGLE));
|
||||||
|
uint8_t hm = (uint8_t)(shift && kbd_raw_down(KBD_TIMER));
|
||||||
|
uint8_t ff = (uint8_t)(shift && kbd_raw_down(KBD_KEY_W));
|
||||||
if (pop_cheats && k && !cheat_prev) pop_guard_kill();
|
if (pop_cheats && k && !cheat_prev) pop_guard_kill();
|
||||||
|
/* Shift+S — одна единица HP, как малое красное зелье. */
|
||||||
|
if (pop_cheats && h1 && !hp1_prev && hitp_curr != hitp_max) {
|
||||||
|
pop_sfx_play(33);
|
||||||
|
hitp_delta = 1;
|
||||||
|
pop_flash_color = POP_FLASH_RED;
|
||||||
|
pop_flash_time = 2;
|
||||||
|
}
|
||||||
|
/* Shift+T — поднять ПОТОЛОК HP, как большая склянка. Оригинал
|
||||||
|
* здесь условия «не полон» не ставит: потолок растёт всегда. */
|
||||||
|
if (pop_cheats && hm && !hpmax_prev) {
|
||||||
|
pop_sfx_play(30);
|
||||||
|
pop_add_life();
|
||||||
|
pop_flash_color = POP_FLASH_RED;
|
||||||
|
pop_flash_time = 4;
|
||||||
|
}
|
||||||
|
/* Shift+W — медленное падение, как зелье пера. */
|
||||||
|
if (pop_cheats && ff && !feather_prev) {
|
||||||
|
pop_feather = POP_FEATHER_FRAMES;
|
||||||
|
pop_sfx_stop();
|
||||||
|
pop_sfx_play(39);
|
||||||
|
pop_flash_color = POP_FLASH_GREEN;
|
||||||
|
pop_flash_time = 3;
|
||||||
|
}
|
||||||
|
hp1_prev = h1; hpmax_prev = hm; feather_prev = ff;
|
||||||
/* Бессмертие по кругу: 0 выкл -> 1 «только бой» -> 2 «бой и
|
/* Бессмертие по кругу: 0 выкл -> 1 «только бой» -> 2 «бой и
|
||||||
* мелкий урон» -> 0. Что означают уровни — pop_state.h. */
|
* мелкий урон» -> 0. Что означают уровни — pop_state.h. */
|
||||||
if (pop_cheats && i && !immo_prev)
|
if (pop_cheats && i && !immo_prev)
|
||||||
|
|||||||
Reference in New Issue
Block a user