====== Моды ====== Моды вносят различные изменения в игру. Например, меняют интерфейс, добавляют костюмы для персонажей, добавляют новых персонажей, изменяют сцены, которые уже есть в игре. Официальные моды можно найти в самой игре. В главном меню сверху есть вкладка **Моды**. ===== Источники ===== По-умолчанию у вас должно быть 3 источника модов: **Локальные моды**, **Моды для патронов** и **Official**. * Локальные моды - Это моды, которые уже установлены * Моды для патронов - Официальные источник модов, доступный только патронам. * Official - Официальный источник модов, доступный всем. ==== Список источников ==== * Официальные моды: http://mods.kunoichi-trainer.ninja/official/manifest.json * Переводы игры: http://mods.kunoichi-trainer.ninja/translations/manifest.json * Моды для разработчиков модов: https://bitbucket.org/dinaki/dev-mods/raw/master/manifest.json [[ru:mods:create_source|Как создать свой источник]] ===== Моды ===== ==== Как установить официальный мод ==== - Зайдите в игру - Сверху выберите вкладку **Моды** - Выберите источник модов. Например, Official. - Выберите мод. - Нажмите кнопку **Установить**. - Перезагрузите игру. ==== Как установить сторонний мод ==== - Распакуйте архив с модом в папку с модами. См. [[#где_хранятся_моды|где находится папка с модами]]. ==== Где хранятся моды ==== По-умолчанию, моды находятся в папке ''Kunoichi Trainer/mods''. Папки ''mods'' может не быть. В таком случае её нужно создать вручную. Так же в настройках игры, если пролистать в самый низ, можно указать другой путь до папки с модами. ==== Как отключить мод ==== - Откройте главное меню. - Выберите источник **Локальные моды**. - Выберите мод. - Нажмите **Отключить**. ------- Каждый мод должен находится в отдельной папке, которая называется так же, как и id мода. В папке мода должен быть файл ''manifest.json''. В этом файле должна быть такая же информация, что и в источнике, кроме поля ''file_name''. === Пример === { "id": "mod-id", "name": "Название мода", "version": "1.0", "description": "Описание мода", "game_version": "0.16" } ==== Скрипты ==== Файлы с кодом должны иметь формат **.rpym**, либо **.rpymc**. Это тоже самое, что и **.rpy** и **.rpyc**. Не знаете про .rpy и .rpyc? Смотрите [[https://www.renpy.org/doc/html/language_basics.html#files|документацию RenPy]]. Вы пишите код мода в файлах .rpym, при запуске игры они будут скомпилированы в .rpymc. Файлы могут лежать просто в папке, либо в **.rpa** архиве. ==== Как заменить изображение из игры ==== Для этого необходимо в ''manifest.json'' добавить новый параметр ''merge_folders'', который является массивом строк. В этом параметре указывается список папок, файлы из которых будут распознаваться игрой, как будто они были в самой игре изначально. Чтобы изменить изображение в игре, нужно знать расположение оригинального изображения. В папке, указанной в параметре ''merge_folders'', нужно разместить новое изображение по такому же пути, что и оригинальное изображение. === Пример === Простой мод, который заменяет фон комнаты, в которой игрок появляется в самом начале игры. Оригинальный фон хранится по такому пути: images/bg/beginning_room.webp Структура папок мода: mods └───mod-id │ │ manifest.json │ └───my_folder │ └───images │ └───bg │ └───beginning_room.webp Где ''mod-id/my_folder/images/bg/beginning_room.webp'' - это новое изображение, на которое хотим заменить оригинальное. Содержимое файла ''manifest.json'': { "id": "mod-id", "name": "Название мода", "version": "1.0", "description": "Описание мода", "game_version": "0.16", "merge_folders": ["my_folder"] } Это всё, что нужно, чтобы заменить изображение. ==== Как взаимодействовать с игровыми событиями ==== Для этого необходимо создать класс (в файле **.rpym**), наследующий класс ''Module'' и подписаться на нужные события. См. [[ru:mods:events|Список событий]] Например, модуль, который реагирует на изменение времени суток и смену локации. init python: # У каждого модуля должно быть уникальное название и id class DemoModule(Module): id="demo" subscribe_on_events=["time_update", "change_location"] def on_event(self, event): if event.type == "time_update": if event.is_morning: renpy.notify("Наступило утро") elif event.is_evening: renpy.notify("Наступил вечер") elif event.type == "change_location": renpy.notify("Новая локация: " + event.new_location.id) ==== Как добавить предмет в магазин ==== Для этого, нужно создать переменную от класса [[ru:mods:classes#item|Item]], если это просто предмет, или от класса [[ru:mods:classes#outfit|Outfit]], если это элемент одежды. * Желательно, чтобы название переменной начиналось с ''item_''. * Название предмета должно быть уникальным и не должно повторятся. === Примеры === Добавление обычного предмета в магазин Тен-Тен. init python: item_pen = Item( name=__("Ручка"), cost=5, icon="my_mod_folder/pen.webp", descr=__("Ручка с чернилами."), shop="tenten", ) Добавление одежды в магазин Тен-Тен. init python: item_ino_my_new_costume = Outfit( name=__("Новый костюм для Ино"), cost=100, descr=__("Описание предмета"), char="Ino", lust=10, layer="costume", val="my_new_costume", shop="tenten", ptr=False, icon=KTCharInventoryPreview( char_name="ino", layers=ino_preview_layers + [("costume", "my_new_costume")], crop=ino_costume_inv_preview ), ) Структура папок мода: mods └───mod-id │ │ manifest.json │ │ item.rpym │ └───merge_folder │ └───images │ └───characters │ └───ino │ └───costume │ └───my_new_costume.webp При таком подходе предмет будет в магазине, только если начать новую игру. Чтобы добавить предмет в магазин, если игрок загружает уже существующее сохранение надо использовать [[ru:mods:classes#module|Module]]. См. [[ru:mods#как_взаимодействовать_с_игровыми_событиями|Как взаимодействовать с игровыми событиями]] и [[ru:mods:events#game_loaded|событие game_loaded]]. Получится что-то вроде такого: def on_event(self, event): if event.type == "game_loaded" and not inv_shop.has_item(item_my_item): inv_shop.add(item_my_item) ===== Игровые переменные ===== ==== Время суток ==== if game.time.is_morning: "Сейчас день" elif game.time.is_evening: "Сейчас вечер" $ game.time.set_morning() "Сейчас точно день" $ game.time.set_evening() "Сейчас точно вечер" $ game.time.next_cycle() "Если был день, сейчас вечер. Если был вечер, сейчас день и счетчик дней увеличился." $ game.time.next_day() "Сейчас точно день и счетчик дней увеличился на 1." $ game.time.skip_days(10) "Счетчик дней увеличился на 10."