Ответ на пост «Желание исполнено в точности как было и написано»2
Как-то пришла ко мне девушка, вроде прилично одетая - футболочка, штанишки, сандалии.
Как потом выяснилось - только эти три предмета одежды/обуви на ней и были.
Как-то пришла ко мне девушка, вроде прилично одетая - футболочка, штанишки, сандалии.
Как потом выяснилось - только эти три предмета одежды/обуви на ней и были.
Оригинальный псто:
Навеяло. Разговор двух подруг:
- Сказала своему что мечтаю проснуться от орального секса.
- И что?
- Он сказал, что намёк понял и хитро улыбнулся. Утром просыпаюсь млять от того, что он мне х*й свой нежно в лицо тычет!!!
В прошлом посте я показал, как у меня с монстров сыплются одни зелёные вещи. В комментариях спросили: как? Рассказываю подробно, с формулами и байтами. Вдруг кому-то пригодится, кто тоже 20 лет не может собрать сет.
Играю в «Гроздья гнева»: это русский мод на Diablo 2 версии 1.09.
Часть 1. Где игра хранит правила.
Всё содержимое Diablo 2 лежит в архивах .mpq, это формат Blizzard. Мод добавляет свой архив, Rus_Grapes_of_Wrath.mpq. Внутри лежат таблицы: оружие, броня, камни, рецепты куба, таблицы дропа.
Первая засада: в моде таблицы лежат только в скомпилированном виде (.bin), без исходных .txt. Это сырые массивы записей фиксированной длины без заголовков полей. У записи брони 564 байта, а что где лежит, не написано.
Как я их расшифровал: в обычном патче игры (patch_d2.mpq) есть и .txt, и .bin для одних и тех же таблиц. Я написал скрипт, который для каждого столбца из .txt перебирает все смещения в .bin и ищет, где значения совпадают во всех строках сразу. Так нашлась карта полей, например для брони:
код предмета: смещение 324;
уровень предмета: 407;
требование силы: 417;
флаг «может выпадать» (spawnable): 448;
максимум ячеек: 453;
требование уровня: 460.
Структура у мода та же, поэтому карта подошла и к его таблицам.
Часть 2. Как игра решает, что выпадет
Когда монстр умирает, игра делает два независимых выбора.
Шаг А: какой предмет. У каждого монстра есть «класс сокровищ» (Treasure Class), например Act 5 (H) H2H A. Это список вариантов с весами: золото, зелья, «экипировка». Есть ещё вес NoDrop, ничего не выпало. Игра делает несколько бросков (Picks) и спускается по вложенным спискам. В конце она попадает в автоматические группы вроде armo63 или weap66, куда игра сама раскладывает все предметы по уровню с шагом 3, и выбирает конкретную базу: «Готический доспех», «Корона» и так далее.
Шаг Б: какого качества. Только теперь игра проверяет качество, строго по очереди: уникальная, сетовая, редкая, магическая, «превосходная», обычная. Каждая проверка (по исследованиям сообщества, Phrozen Keep) выглядит так:
шанс = (Ratio − (ур.монстра − ур.предмета) / Divisor) × 128 шанс = шанс × 100 / (100 + MF_эфф) если шанс < Min, то шанс = Min успех, если random(0..шанс) < 128
Ratio, Divisor и Min берутся из таблицы itemratio. В ней 6 строк: классика или дополнение, обычные, «убер» и классовые вещи. Например, для уникальных в моде стоит Ratio 500, Divisor 6, Min 50.
Отсюда, кстати, видно, почему MF быстро упирается в потолок. Для уникальных он режется по формуле MF × 250 / (MF + 250), для сетов × 500 / (MF + 500). Я собрал персонажа с 570% MF (об этом ниже), а на уникальные это дало реальные +174%. На практике шанс уникальной с предмета поднялся примерно с 0,2% до 0,55%.
Часть 3. Первая попытка и облом
Логичный ход: поставить сетам Ratio = 1, Divisor = 10000, Min = 128. Тогда шанс = 128, и random(0..128) < 128 выполняется всегда. А уникальным, чтобы они не перехватывали проверку (они идут первыми), поставить Ratio 100000 и Min 10 000 000.
Нюанс: числа нельзя брать слишком большими. Внутри игра умножает шанс на 100, и 32-битное число может переполниться. 100000 × 128 × 100 ≈ 1,28 млрд, это ещё влезает.
Результат: падают… белые и синие вещи.
Почему: шаг Б идёт после шага А. Если игра уже выбрала базу, у которой нет сетовой версии, проверка «сет?» проваливается, и вещь становится магической или обычной. А сетовые версии есть далеко не у всех баз.
Часть 4. Решение: подменить выбор базы
Раз качество зависит от базы, нужно сделать так, чтобы игра выбирала только «правильные» базы.
Разобрал таблицу сетов (setitems.bin). В 1.09 одна запись — это целый сет до 6 предметов, коды предметов лежат с шагом 60 байт начиная со смещения 140. В моде 63 сета и 217 баз: 157 брони, 57 оружия, 3 прочих.
Всем остальным предметам брони и оружия обнулил флаг spawnable. Отключено 450 баз, монстры их больше не выбирают.
Подводный камень: игра раскладывает предметы по группам уровней (weap33, armo63…). Если в группе не останется ни одного предмета, игра может упасть. У мода есть несколько «дыр» в уровнях 4–6, 10–12, 28–36 и 43–45, где нет ни одного сетового оружия. В этих группах я оставил обычные базы. Поэтому иногда, особенно на Normal и Nightmare, всё ещё может выпасть обычное или магическое оружие.
Итог: если с монстра падает экипировка, она почти всегда зелёная.
Часть 5. Больше лута
В таблице дропа (treasureclassex.bin, запись 732 байта: имя, Picks, NoDrop, 10 ссылок по 64 байта и 10 весов):
обнулил NoDrop у всех 928 классов сокровищ;
удвоил Picks у 168 классов обычных монстров во всех актах и на всех сложностях, плюс у коров и Совета.
Боссов не трогал: у них бросков и так много, а игра ограничивает число вещей с одного монстра.
Часть 6. Рецепт для дублей
Приятный сюрприз: в 1.09 рецепты куба хранятся в .bin обычным текстом. 7 входов по 32 байта, результат со смещения 236, и разбирает их сама игра при загрузке. Поэтому новый рецепт — это просто новая запись в конце файла:
"any,set,qty=3" → "usetype,set" (уровень предмета 99)
Три любые сетовые вещи дают новую сетовую вещь того же типа, что и первая положенная. Из 3411 рецептов мода нашёлся и родной вариант: сет + совершенный изумруд дают новый сет.
Часть 7. Персонаж-пылесос
Перед всем этим я честно пытался поднять MF. Файл персонажа .d2s я правил вручную. Формат 1.09 такой:
в начале сигнатура 0xAA55AA55, версия 92 и контрольная сумма: циклический сдвиг влево и сложение по всем байтам;
характеристики записаны как 16-битная маска, за которой идут 32-битные значения; здоровье и мана хранятся умноженными на 256;
предметы — это битовые структуры, которые начинаются с JM. Камень в ячейке — отдельный предмет с «местом» = 6, он идёт сразу за вещью-владельцем и не входит в общий счётчик предметов.
В моде камни переделаны (gems.bin, 144 записи вместо 68 в оригинале):
Perfect Topaz в шлеме или броне даёт 30% MF вместо 24% и ещё +60% к золоту;
руна Ist даёт MF даже в оружии и щите;
ячейки разрешены у сапог, перчаток, поясов, амулетов и колец.
Итог: 19 совершенных топазов в 8 вещах, до 570% MF. Только, как мы выяснили выше, для уникальных и сетов это почти ничего не даёт. Поэтому я и полез в таблицы.
Чем пользовался
StormLib (открытая библиотека для .mpq): распаковка и упаковка архивов;
Python: разбор .bin и .d2s, пересчёт контрольной суммы;
Hero Editor от ZonFire99, чтобы посмотреть на результат.
Изменённые файлы не выкладываю: это архивы мода и игры. Но по описанию выше всё повторяется.
Всем добрый вечер.
Мне уже ближе к 40 чем к 30, занимаюсь информационной безопасностью и люблю раз в пару лет перепроходить diablo 2 Гроздья гнева по старой памяти из юности. Все годы что играю очень нравился уровень с коровами и как-то трепетно относился в зеленым вещам. В этом году в очередной раз прошел и понял что не смог собрать ни одного полного сета и решил это исправить в силу своих возможностей.
Покопавшись в файлах нашел что вероятностью выпадения вещей можно редактировать и поднял максимальный шанс падения зеленых на максимум. Теперь есть падает вещь и у неё есть сетовый аналог, то падает именно он, вот так выглядит теперь моя игра.
Находим где мобов побольше, укладываем их, нажимаем кнтрл и радуемся)
p.s. так же можно для уникальных делать.
Спасибо Газпрому за кассы самообслуживания на заправке - теперь никто не уйдёт попить кофе и посрать, оставив машину на колонке.
Зашёл 1 октября, пикаю по полосатому коду на кетчупе - не проходит. Теперь надо по квадратному. И отменить может только продавец. Зову, отменяет. Пикаю по полосатому коду на майонезном соусе - не проходит. Теперь надо по квадратному. И отменить может только продавец. Зову, отменяет.
Пикаю по квадратному коду на кефире Пискарёвского завода - не проходит. Теперь надо по полосатому (временно). Потому что завод атакован и не может передавать актуальные коды в магазины. Зову продавца.
Только он отходит, я автоматически пикаю по квадратному коду на сметане Пискарёвского, хотя и знал уже, что надо по полосатому. Хорошо что продавец недалеко ушёл...
Стою как дурак с хлебом, на нём тоже уже несколько кодов. Какой сканировать - большой вопрос.