Приветик! Наверняка многие играли в замечательную игру от компании Nival Interactive - Проклятые Земли.
![Такое бывает... Такое бывает...](https://habrastorage.org/getpro/habr/upload_files/7db/b5a/a6c/7dbb5aa6cc3676451dd830a44c93e2ad.png)
Кто-то её помнит по сложным на первый взгляд противникам, кто-то по шикарному и удивительному сюжету, кто-то за удивительные фишки (крафт, стелс, возможность красть вражеские вещи из карманов и брать себе напарников) а кто-то полюбил её так, как я, и гоняет орков и кабанчиков по всему аллоду и по сей день.
Что касается уникальных фишек - в ПЗ их действительно очень много! Чего только стоит возможность собирать разные типы оружия из разного материала, да ещё и вставлять в него заклинания! Кстати, с бронёй можно сделать точно так же.
![Сборка оружия в 1-м предоставляющемся главному герою магазине Сборка оружия в 1-м предоставляющемся главному герою магазине](https://habrastorage.org/getpro/habr/upload_files/19c/8c9/21b/19c8c921be94924925a60c8e901f6b05.png)
Следующая же фишка - вообще удивительный элемент геймдизайна как для 2000 года!
![Белые облачка означают область зрения орчихи (вызваны использованием 4-го сверху заклинания "Поле зрения") - она не видит Зака через пенёк Белые облачка означают область зрения орчихи (вызваны использованием 4-го сверху заклинания "Поле зрения") - она не видит Зака через пенёк](https://habrastorage.org/getpro/habr/upload_files/55c/f1b/bee/55cf1bbee841382b696ed09623a0e234.png)
Зак сидит за пеньком прямо перед носом у орков, которые его не видят. Но если встать...
![Стоячий Зак попадает в поле зрение орчихи и она начинает вести стрельбу... Стоячий Зак попадает в поле зрение орчихи и она начинает вести стрельбу...](https://habrastorage.org/getpro/habr/upload_files/c8f/bb8/149/c8fbb8149303d2fa2a62058114dcbebc.png)
То орчиха начинает видеть Зака, ведь теперь он уже выше пенька! Но это далеко не всё то, за что можно выразить огромный респект геймдизайнерам и программистам того времени. Каждый, кто хотя бы на 30 минут запускал ПЗ, наверняка прекрасно помнит тот романтичный момент, когда Заку предоставляется возможность обокрасть первого же встреченного им здоровенного людоеда.
![Кража монет у людоеда Кража монет у людоеда](https://habrastorage.org/getpro/habr/upload_files/859/516/428/859516428e532b4c89f7f01d73871c07.png)
В игре есть 4 способа перемещения: бег, ходьба, на кортанах и лёжа. Последние 2 в оригинальном балансе игры являются абсолютно бесшумными способами передвижения, бег же наоборот своим звуком с большого расстояния собирает подозрительных противников. Потому людоеда я решила обокрасть именно на кортанах чтобы он меня не услышал.
Во время бега запас сил расходуется, а восстанавливается он только если пассивно находиться на одном месте. Атакующие, колдующие и двигающиеся персонажи не могут восстанавливать свой запас сил.
В игре также есть боевая магия. Использование атакующих заклинаний, как и всех других, серьёзно тратит запас сил персонажа. Только посмотрите как красиво Зак кастует молнию в этого лесоруба! Это стоит ему почти всего запаса сил не смотря на неадекватную прокачку.
![Очень хорошо прокачанный персонаж Очень хорошо прокачанный персонаж](https://habrastorage.org/getpro/habr/upload_files/c64/8b7/dae/c648b7dae7b970eb496651b18bfed1fb.png)
Я люблю динамику в играх, но это не самое важное. Самое важное, что довольно глупо смотрится то, как маг стоит на месте и поливает магией своих противников, будто он воин, который надел броню и терпит, а вовсе не маг. Во многих современных играх можно атаковать в движении, что даёт возможность магам держаться от противника на дистанции и не получать в лицо от, допустим, толстого тролля с кучей хп и кучей урона.
В ПЗ же даже анимация такого действа не предусмотрена, потому геймплей магом крайне некрасив. Как, кстати, и стрелком, которому хоть запас сил для стрельбы и не нужен, но убегать от противника он может лишь несколько секунд, а потом сразу выдохнется... Что можно с этим сделать?
Нам понадобятся: Cheat Engine, IDA, HxD ну и сама игра Проклятые Земли.
Запускаем игру и Cheat Engine... Нам нужно узнать что записывает запас сил в память и что читает его у нашего героя из памяти.
![Запас сил = 375 Запас сил = 375](https://habrastorage.org/getpro/habr/upload_files/dd1/6de/3e9/dd16de3e9d29d283069149d5c23d3e65.png)
Вбиваем число напротив синей шкалы и ищем его в памяти процесса game.exe. Довольно легко проверить, что запас сил персонажа - число типа float, как и большинство чисел в этой игре, касающихся характеристик объектов, находящихся на картах.
Чтобы найти нужный адрес достаточно побегать героем по карте, чтобы его запас сил изменился и выбрать для отсеивания в Cheat Engine опцию Decreased value.
![Запас сил героя в памяти игры Запас сил героя в памяти игры](https://habrastorage.org/getpro/habr/upload_files/899/f34/da2/899f34da2ed1c9533851d72e5c2b2948.png)
Уже с 3-й попытки я нашла запас сил в памяти. Теперь пора узнать что его записывает и что его читает. Жмём ПКМ + Find out what writes to this address.
00548323 - D9 57 14 - fst dword ptr [edi+14]
0052382D - D9 5E 14 - fstp dword ptr [esi+14]
0054834B - C7 47 14 00000000 - mov [edi+14],00000000
Получаем такие результаты. 1-е - трата запаса сил, 2-е - восстановление запаса сил, 3-е - полная трата запаса сил. Самое интересное пока - чтобы персонаж не был задохликом и бежал в зависимости от количества сил, а не жалкие 10 секунд.
![Команда сохраняет запас сил в памяти Команда сохраняет запас сил в памяти](https://habrastorage.org/getpro/habr/upload_files/c8e/59c/dd4/c8e59cdd48ce3138c2030e02e70d2d4a.png)
Переходим чуть выше и смотрим что там по адресу EDI+14 и EDI+18. 1-е и 2-е закономерно оказываются запасом сил героя. 1-е - текущий, 2-е - максимальный.
Команда fst записывает в память из регистра FPU, команда fld же наобророт берёт из памяти и пишет в регистр FPU.
Стоит обратить внимание куда именно найденная нами команда fst dword ptr [EDI+14] пишет. Выше команда наоборот берёт оттуда значение.
Далее уже всё понятно: в регистры FPU берутся сначала текущий, потом максимальный запас сил, затем максимум умножается на константу (в оригинале она = 0.006666666666666666, а у меня она изменена на 0.1), это число отнимается от текущего запаса сил и результат кидается на его место. Мне захотелось сделать так, чтобы запас сил расходовался по 0.2, а не по 0.1%. Максимальный запас сил нам не нужен, как и умножение на что-то, нам нужно отнимать само число. Используя сайт https://defuse.ca/online-x86-assembler.htm получаем, что желаемая нами команда имеет такой код:
dc 25 88 f0 73 00 fsub QWORD PTR ds:0x73f088
Вставляем его в движок игры, используя HxD, а остальное можно забить командой NOP.
![Переписываем код игры прямо в HxD! Переписываем код игры прямо в HxD!](https://habrastorage.org/getpro/habr/upload_files/1a1/535/b31/1a1535b3182cad9855ac487977fb0e65.png)
Теперь надо всунуть другую константу чтобы персонаж хоть как-то терял запас сил при беге (отнимать 1/150 - уж очень мало)...
![9A 99 99 99 99 99 C9 3F = 0.2f 9A 99 99 99 99 99 C9 3F = 0.2f](https://habrastorage.org/getpro/habr/upload_files/6cb/ff2/4f8/6cbff24f8bf61574e8720caa34284984.png)
Окей, теперь персонаж бегает, теряя запаса сил не по 1/150 от его части, а по 0.2 единицы. Но это всего лишь значит, что с запасом сил более 30 наш главный персонаж будет бегать дольше, чем в оригинале, но особенной динамики само по себе это не принесёт. В битвах уж точно.
Сам факт восстановления запаса сил нас прекрасно устраивает, нам надо только изменить его условия. Ну а точнее убрать их подальше. Посмотрим, что из кусков кода читает запас сил и что от него отталкивается. Снова запускаем игру и Cheat Engine. Жмём ПКМ + Find out what accesses this address. Надо снова немного побегать и постоять, восстанавливая запас сил героя.
00548679 - D9 47 14 - fld dword ptr [edi+14]
005482D3 - D9 47 14 - fld dword ptr [edi+14]
00548315 - D9 47 14 - fld dword ptr [edi+14]
00522C82 - 8B 51 14 - mov edx,[ecx+14]
0052377A - D9 46 14 - fld dword ptr [esi+14]
00523805 - D8 46 14 - fadd dword ptr [esi+14]
Получаем вот такой контент. 1-е - включение бега, 2-е бег, 3-е - бег, 4-е - изменение запаса сил, 5-е -релакс, 6-е - восстановление запаса сил.
Естественно и очевидно что нам интересно именно 6-е и в каких случаях эта команда выполняется в коде игры. Внимательно смотрим повыше в ассемблерном листинге и находим там это начало функции. Видим чуть ниже условный переход, который не выкидывает сразу же из функции, но полностью скипает другие проверки, в том числе он скипает и восстановление запаса сил. Скорее всего это и есть проверка, находится ли персонаж на 1 месте (в релаксе) или же не находится.
![Начало функции Начало функции](https://habrastorage.org/getpro/habr/upload_files/1ec/099/97a/1ec09997a9fd460adb652e208cdc8d58.png)
Пробуем поменять, чтобы прыжка через этот кусок кода не стало...
![Команды NOP заменили переход Команды NOP заменили переход](https://habrastorage.org/getpro/habr/upload_files/a26/e73/c31/a26e73c31f84991a12dfa075c0bc9acf.png)
И да! Всё получилось, теперь герой регенирирует свой запас сил даже во время каста заклинания. Ну и во время бега, конечно же, тоже.
![Зак скастовал заклинание и отрегенил запас сил уже 2-мя тиками Зак скастовал заклинание и отрегенил запас сил уже 2-мя тиками](https://habrastorage.org/getpro/habr/upload_files/1ba/997/992/1ba997992fc7103d766cf4d5ec26239c.png)
Поменяем значение в game.exe через HxD, чтобы наслаждаться динамичной игрой...
![Убираем условие Убираем условие](https://habrastorage.org/getpro/habr/upload_files/67a/f6c/9d0/67af6c9d05dbf1a1a7f3628afa864949.png)
Но это не всё. Игра за мага, ясное дело, получается в принципе из-за магии. И динамичная игра за мага определяется самими заклинаниями. В игре есть куча неиспользованной магии. Некоторые заклинания вполне рабочие и просто не продаются в магазинах, как например "мертвец" и "зрение мертвеца" (а в аддоне к этой замечательной игре - "Проклятые Земли: Затерянные в Астрале" так наоборот, они продаются, но не продаются "фейерверк" и "телепортация"). Но некоторые заклинания игры суровейшим образом отключены прямо в самом движке.
По адресу 0х0067F870 в памяти игры есть функция, выбирающая 1 из 43 эффектов для используемого заклинания. Наверняка этот скриншот очень многое скажет о сложности этой функции (там всего довольно много)...
![Страшная функция заклинаний в ПЗ, видная через IDA Страшная функция заклинаний в ПЗ, видная через IDA](https://habrastorage.org/getpro/habr/upload_files/b65/441/d97/b65441d97ed0fd900b9b0e0a178573b7.png)
Довольно долго и нудно, но при этом легко и просто я пришла к этому адресу, где жёстко и грубо выпиливаются 3 заклинания ещё на подходе по их номеру.
![3 условных перехода внизу - проверка для заклинаний Link, Possession и Charm 3 условных перехода внизу - проверка для заклинаний Link, Possession и Charm](https://habrastorage.org/getpro/habr/upload_files/f2c/ca3/f52/f2cca3f521b5ebfc82c835c319f191aa.png)
15h - Possession, 18h - Link, 24h - Charm. Теперь это всё надо превратить в NOP чтобы получить доступ к засекреченным заклинаниям! Ухх, как же интригующе!
![Запреты (условные переходы) превращаем в NOP Запреты (условные переходы) превращаем в NOP](https://habrastorage.org/getpro/habr/upload_files/27b/fa3/893/27bfa38936d70f514cf3233c3d9daa85.png)
Итак... Новые заклинания получены! Теперь достаточно ввести в игре в магазине в консоль, нажав на "~", следующие команды:
thingamabob
give 0 money 99999999
give 0 assortment
Теперь, чтобы игра не забаговалась, стоит выйти из магазина, ну и зайти обратно...
Покупаем заклинания за 200 (с розовым дымком и светлым сиянием, это Possession), за 3200 (с собачкой, это Charm) и за 400 (с пьяным мужиком идущим во тьме, это Link) и идём их тестировать!
Начнём с конца... Link делает ровно ничего, у него даже кода нет, только анимация и её завершение, очень полезное заклинание.
![Скорее всего просто не успели написать код заклинания Скорее всего просто не успели написать код заклинания](https://habrastorage.org/getpro/habr/upload_files/c99/b00/675/c99b0067515713cc3d2f3f4d1c371537.png)
Charm подчиняет противника очень странным образом, заклинание явно не имеет полного кода и игра вылетает при попытке подчинить следующего противника.
Possession же - действительно находка!.. Скриншот будет лучше всяких слов.
![Действие Possession Действие Possession](https://habrastorage.org/getpro/habr/upload_files/07f/89c/ba4/07f89cba4f408542445b49bf113a834f.jpg)
Это заклинание позволяет перенести взгляд героя в противника. Сам эффект не очень эффективный, но очень интересный. Если бы оно было на ранних аллодах, а орлиного взора, ночного зрения и ясновидения не было на Гипате и Ингосе (ну или в ПЗ: ЗвА - на Суслангере и Гипате), это заклинание было бы прекрасным и интересным инструментом для шпионажа за патрулями и позициями противников.
Эти изменения я ввела для ПЗ ещё очень давно, а чуть потом мне удалось запихать их и добавить ещё множество новых в специальную библиотеку, которая является одним из самых масштабных дополнений для движка ПЗ, которое я назвала SpellAddon.
Используя внутриигровые скрипты получилось сбрасывать агрессию противников, что в оригинале было невозможным без перезахода на игровую локацию, даже телепортировавшись через всю карту, через горы и реки, противник всё равно находил главного героя и стремился его убить, пока 1 из них не окажется повержен.
Стоит заметить, что всё выше написанное актуально для версии игры 1.06 и на остальных версиях операции не проводились.
Полезные ссылки:
https://evilislandsaddon.forumotion.com - форум на котором можно найти SpellAddon.
https://vk.com/evil.islands - группа в ВК
http://gipat.ru - форум "Город джунов".
http://gipatgroup.org/forum - самый масштабный, но не особо функционирующий форум "GipatGroup". Впрочем, прочитать на нём полезную информацию сейчас возможно.
http://honestgroup.net/forum — форум HonestGroup.
![Избранный явился! Избранный явился!](https://habrastorage.org/getpro/habr/upload_files/2b0/deb/5a0/2b0deb5a0d104c8e7053d123ae0fa521.png)
Всем удачи!