Overview
И опять всем доброго дня или ночи! В своём первом руководстве о нашей игре (“Основы игры простым языком для непосвящённых”, https://steamcommunity.com/sharedfiles/filedetails/?id=1953949665 ) я давал сохранения для разных вариантов игры. А теперь, как я считаю, пришла пора разобраться, как вообще работают сохранения и можно ли делать что-то с их файлами.
1. Как ко мне пришла идея этого руководства
В обновлении v2020.8.a.1 разработчики добавили Мастерскую Steam (сохранив при этом возможность установки модов старым способом через папку ИМЯ ПОЛЬЗОВАТЕЛЯAppDataLocalLowWeather FactoryCultist Simulatormods). Мне приглянулся там один из модов на «наследие» (вариант старта игры), The Veteran от superjw2, но там был некоторый забавный нюансик. Как написал в комментариях автор мода, для доступа к новому старту понадобилось оказаться арестованным. Я включил одно из имеющихся сохранений и попытался подставиться под улики. Но… Усталый детектив внезапно словил аутизм в терминальной стадии и всё никак не желал создавать изобличающие улики из предварительных, хотя я постоянно подкидывал ему свежие карты дурной славы. В мод я так и не поиграл, зато понял, что нужно разобраться с форматом сохранений и понять, что и как там прописывается, чтобы была возможность подключить мод самостоятельно в качестве варианта старта.
2. Где находятся сохранения
Все сохранения записываются в директорию [ИМЯ ПОЛЬЗОВАТЕЛЯ]AppDataLocalLowWeather FactoryCultist Simulator, в неё можно попасть как с помощью Проводника Windows, так и с помощью кнопки «открыть файл сохранения» с меню настроек в самой игре. Начав игру, видим приветствие и начальную ситуацию на столе:
Затем тут же сохранившись и выйдя в главное меню, открываем директорию для сохранений. Видим следующее:
Папка «mods» пустая, папка «Unity» содержит файлы движка игры (они нам не интересны), файлы «config.ini» и «Player.log» тоже, а вот последний файл, «save.txt» и является объектом нашего интереса. Открываем его.
Примечание №1: кому как, а я предпочитаю для просмотра файлов конфигурации использовать Notepad++ из-за удобства отображения структуры текста. В дальнейшем скриншоты будут именно из этой программы.
3. Разбор формата
Мой файл занимает объём 62 килобайта и содержит много строк. Но не будем пугаться, а попытаемся вникнуть, что это за текст.
Кажется, что всё страшно и запутанно… Но давайте вглядимся внимательнее. Текст состоит из строк, сгруппированных под общими заголовками. Это код javascript, содержащий списки элементов, задействованных в игре в данный момент. Да, так сохранение и устроено. Когда мы жмём в игре кнопку «сохранить и выйти», она запоминает текущее состояние (в том числе и для отдельных карт) и записывает всё это добро в такой вот файл в виде этих групп строк, каждая из этих групп отвечает за отдельный записанный элемент (карту), а заголовок объединяет элементы одного вида. Насколько я понял, заголовки имеют такие роли:
«elementStacks»: имеющиеся на столе карты;
«decks»: карты, ещё не вышедшие на стол;
«metainfo»: версия игры;
«characterDetails»: глобальные сведения о сохранении (имя героя, доступное «наследие», сведения о прошлом «пути»);
«situations»: имеющиеся на столе действия и состояния.
Давайте проверим нашу гипотезу. Поиграем совсем чуть-чуть, чтобы ситуация на столе немного изменилась. Снова сохраняемся и выходим, вновь открываем файл сохранения…
Бинго! Вот ситуация в самой игре:
А вот изменившееся содержание файла сохранения:
Отлично! Выходит, что мы можем отслеживать в этом файле всё, что происходит в игре! А можем ли мы изменять этот файл? Конечно же, это же просто текст! Но делать надо это аккуратно, чтобы ничего не сломать. Итак, кажется, я начинаю догадываться, за что отвечает каждая строка под каждым заголовком. Вот, например, свойства карт заголовка «elementStacks»:
Длинный набор букв и цифр: видимо, это уникальный идентификатор карты, трогать его не будем;
«lifetimeRemaining»: скорее всего, это таймер до исчезновения карты, значение 0 показывает, что карта всегда присутствует на столе;
«lastTablePosX»: расположение карты (координата по оси Х);
«markedForConsumption»: как я понял, это параметр для поглощения карты ячейкой со значком свечки. True – исчезнет, False – останется. По умолчанию стоит «False»;
«elementId»: название карты (какое здесь стоит, та карта и будет на столе);
«lastTablePosY»: расположение карты (координата по оси Y);
«quantity»: количество экземпляров карты. Всё точно соответствует ситуации: по одной карте здоровья и змоций, две карты средств.
Под заголовком «decks» содержатся списки ещё не вышедших карт, отсортированных по разным критериям (охотники, награды за экспедиции и т. д.). Эта часть файла самая большая, нам она пока не нужна. Идём дальше.
«metainfo»: сведения о версии игры. Пропускаем, трогать не будем, а то вдруг сохранение поломается, и игра в нынешней версии не сможет его прочесть.
«characterDetails»: сведения о сохранении. Пожалуй, это самое главное. Разберём.
«executions»: по-моему, это информация о выполненных начальных условиях – запись о исполненной «чёрной работе», полученном действии сна, полученном «наследстве»;
«name»: имя «героя» игрока;
«profession»: название «наследия» на языке локализации;
«pastLevers»: играя сам, я уже прошёл три вознесения (Лампады, Кузни и Чаши) и догадался, что обозначает эта группа. Это карты, унаследованные из прошлого прохождения:
«LastPersonKilled»: последний убитый персонаж;
«LastHeadquarters»: последняя имевшаяся штаб-квартира культа;
«LastCult»: последний культ;
«LastTool»: последний полученный инструмент;
«LastFollower»: последний полученный последователь;
«LastBook»: последняя полученная книга;
«LastDesire»: последнее желание;
«LastSignificantPainting»: последняя особая картина;
«LastCharacterName»: имя «героя» игрока из последней игры.
«futureLevers»: то же самое, но будет записано по итогам текущей игры. Изначально этим параметрам соответствуют некоторые значения, но потом они могут быть перезаписаны;
Примечание №2: как можно заметить из содержания файла сохранения, значения многих параметров являются техническими обозначениями чего-либо, чаще всего карт. Какое обозначение чему соответствует, можно посмотреть на сайте [link], введя интересующее обозначение в строку поиска. Вообще это очень полезный ресурс, позволяющий разобраться во многих деталях игры, по умолчанию скрытых от игрока.
«activeLegacy»: «наследие», по которому мы играем в этом сохранении.
Перейдём к группе элементов «situations». Это действия и состояния. В целом там всё похоже на описание карт, но есть и другие важные параметры:
«recipeId»: использующийся «рецепт», т. е., занята ли ячейка действия или состояния чем-либо. Значение «NULL» обозначает, что действие или состояние свободны, и в него можно класть карты;
«state»: обозначает, запущен ли какой-то процесс или нет. Значение «Unstarted» соответствует неактивному состоянию (его можно начать), а значение «Ongoing» соответствует уже идущему процессу;
«situationWindowOpen»: обозначает, открыто ли окно действия или состояния. Значение по умолчанию – «False» (закрыто);
«situationWindowX» и «situationWindowZ»: по аналогии с картами показывают положение области действия или состояния на столе;
«situationOutputNotes»: текст описания в окне действия или состояния (цифры обозначают части текста, которые можно перематывать стрелками);
«title» (под цифрой 1): описание состояния на языке локализации;
«title» (отдельно): заголовок состояния на языке локализации;
«verbId»: техническое обозначение состояния;
«situationWindowY»: координаты окна состояния;
«completioncount»: параметр завершения какого-либо процесса. 1 – есть завершённый процесс, ожидающий забора карт, 0 – никакой процесс ещё не завершён.
Параметр «timeRemaining» здесь отвечает не за срок существования карты, а за длительность того или иного процесса. Как можно видеть на скриншотах игры и файла сохранения, значение 29.7 соответствует времени, которое осталось до завершения процесса получения карты «наследство» из действия «изучение». В данном случае значение 0 в других действиях показывает, что никакие процессы с таймером не запущены.
4. Редактирование файла
Так, что обозначает тот или иной параметр, мы разобрались. А теперь давайте попробуем что-нибудь поменять.
Примечание №3: настоятельно рекомендую перед экспериментами сделать отдельную резервную копию файла сохранения. Автосохранение всего лишь перезаписывает один и тот же файл под разными названиями, оно не гарантирует корректность чтения этого файла после ручных изменений.
Примечание №4: нарушать структуру файла крайне нежелательно, иначе он точно поломается. Уникальный номер элемента (из цифр и букв) трогать тоже лучше не надо.
Начнём с простого. Попробуем изменить количество карт эмоций, например, сделать 7 штук вместо одной:
У нас получилось! Теперь попробуем поменять расположение карт средств. Допустим, я меняю параметры «lastTablePosX» с -45 на 0 и «lastTablePosY» с -130 на 0…
Нет. Ничего не получается. Впрочем, это не так уж и важно. Теперь попробуем что-нибудь удалить, например, действие работы. Вырезаем кусок файла, описывающий это действие (не забываем о резервной копии!). И…
Хм… сработало! Конечно, на работу завязано множество важных действий, без неё нормально играть не получится. Но это всего лишь эксперимент! Возвращаем удалённое действие на место, убеждаемся, что в итоге ничего не поломалось.
А теперь приступим к самому интересному – добавлению карт и действий/состояний. Иначе для чего мы это всё затевали? Залезаем на уже упомянутый выше сайт и пробуем вписать в файл сохранения… Франжиклав! Почему бы ради эксперимента и не понаглеть немного?
Разумеется, как писать тот многоциферный и многобуквенный код, мы не знаем, вполне вероятно, что он генерируется случайно. Попробуем вписать в файл сохранения уже известные параметры карты, ориентируясь на её описание на странице [link] . При этом в качестве значения для параметра «elementId» пишется непосредственно техническое обозначение нужной карты в заглавии страницы.
И… файл сломался, так как нет того самого длинного кода. Видимо, он определяет и наличие карты, и её расположение. Да уж, разработчики предусмотрели это, не дали нам запустить свои шаловливые ручки куда не следует. Неужели ничего нельзя делать, кроме изменения количества элементов и их удаления? Хм… А если внаглую скопировать один из кодов и вставить для новой карты? О, а в его начале и в значениях координат одни и те же цифры! А если написать координаты и в коде тоже? Ну-ка…
Получилось!!! Кстати, параллельно мы отследили, как выглядит уже завершившийся рецепт. Приятное с полезным:
А состояние так получится разместить? Давайте сделаем «слежку», карты дурной славы и «суд» (мне всё-таки хочется попробовать тот мод поскорее):
Отлично! Я специально разложил карты по столу, чтобы показать, что они появились в нужном мне количестве. При этом я заменил Франжиклав на дурную славу в нужном количестве штук, просто поменяв значение параметра «elementId» и изменив число для параметра «quantity». Стоп… Ещё один нюанс…
А можно ли изменить ход идущего процесса? А что, момент подходящий:
Делаем резервную копию сохранения ещё разок, открываем окно работы в «Гловер и Гловер». Затем открываем файл сохранения и обращаем внимание на то, что появились ещё две подгруппы:
«situationStoredElements»: карты, которые появятся при окончании процесса;
«ongoingSlotElements»: карта, занятая процессом;
Код полностью соответствует тому, что мы видим в игре: в конторе мы используем разум (подгруппа «ongoingSlotElements» со значением “reason” в параметре “elementId”) и получим две карты средств и карту работы обратно ((подгруппа «situationStoredElements» со значениями “funds” и “gloverandglover_difficultbossa_job” в параметре “elementId” для каждой такой карты). Теперь дерзнём поменять обычные средства на бронзовые спинтрии, например, пусть нам платят получше!
Всё прошло как по маслу! Выходит, что мы можем менять что угодно и как угодно? Определённо да, главное – понимать, что и как делать, чтобы файл сохранения не сломался.
Ладно, продолжим то, что хотели, откатив сохранение. И разумеется, меня после всех этих мероприятий по поиску улик благополучно отправили на нары:
Файл сохранения при этом радикально изменился:
Мы видим, что появились новые параметры:
«availablelegacies»: доступные варианты игры;
«currentending»: полученный финал игры;
«defunctCharacterDetails»: изменённые данные о сохранении.
Также изменился подраздел «futureLevers», вот так:
«LastCult»: «cultsecrethistories_1» (культ Тайных Историй, я выбрал его перед самым арестом);
«LastTool»: «toolknockf» (начитеренный Франжиклав);
«LastFollower»: «neville_b»: последователь Невилл, пришедший ко мне при создании культа.
Примечание №5: видимо, последняя карта для наследования между вариантами игры отслеживается автоматически и заменяется лишь следующей картой того же типа. Франжиклав остался записанным в инструменты несмотря на то, что я принудительно заменил его другой картой.
Та-ак… Если доступные варианты игры записываются отдельно, то можно ли прописать их самому? Конечно можно, главное – файл не сломать. По-видимому, первое из одинаковых слов обозначает сам вариант, а второе – картинку для него. Порывшись на сайте [link], я нашёл все варианты игры, которые можно записать в файл сохранения:
“aspirant”: “aspirant” – искатель;
“physician”: “physician” – медик;
“detective”: “detective” – детектив;
“brightyoungthing”: “brightyoungthing” – юное дарование;
“apostlelantern”: “apostlelantern” – продолжение пути Лампады;
“apostleforge”: “apostleforge” – продолжение пути Кузни;
“apostlegrail”: “apostlegrail” – продолжение пути Чаши;
“dancer”: “dancer” – танцовщица;
“ghoul”: “ghoul” – медиум;
“priest”: “priest” – жрец;
“exile:” “exile” – изгнанник.
Примечание №6: возможные варианты игры надо записывать по три и через запятую в конце строки, кроме последней.
Допустим, я хочу поменять предложенные варианты на другие, и пишу вместо них понравившиеся:
Да! Получилось! И… кажется, я всё-таки что-то сломал, несмотря на все меры предосторожности… Хотя ладно, таковы реалии сурового русского моддинга… Смиритесь…
P. S. в тот мод я так и не поиграл, хотя вроде выполнил условия его разблокировки. Видимо, он так и не подключился, загрузка из мастерской не работает как надо. Ну да ладно. Зато разобрался, как устроены сохранения.
шаблон файла сохранения для редактирования стартовых вариантов игры
{
“availablelegacies”: {
“вариант1”: “вариант1”,
“вариант2”: “вариант2”,
“вариант3”: “вариант3”
},
“metainfo”: {
“VERSIONNUMBER”: “2021.1.b.2”
},
“currentending”: “arrest”,
“defunctCharacterDetails”: {
“name”: “[впишите имя]”,
“futureLevers”: {
“LastPersonKilled”: “neville_a”,
“LastHeadquarters”: “hq.temporary”,
“LastCult”: “cultlantern_1”,
“LastTool”: “toolknockf”,
“LastFollower”: “neville_a”,
“LastBook”: “textbookvaksanskrit”,
“LastDesire”: “ascensionenlightmenta”,
“LastSignificantPainting”: “paintingmansus”,
“LastCharacterName”: “J. N. Sinombre”
},
}
}
5. Заключение
Надеюсь, вам была полезна эта информация, пусть и перегруженная выкладками из кода. Напомню только, что всё надо делать аккуратно и не забывать делать резервные копии редактируемых файлов. И да, я догадался, как включить тот мод на новый вариант игры. Скорее всего, придётся установить этот мод вручную, подсмотреть в его файлах, как называется вариант игры, и подставить это название в файл сохранения на момент окончания игры. С другими модами на варианты игры придётся поступать аналогичным образом.
Спасибо за внимание. Буду рад дополнениям, замечаниям и предложениям в комментариях.