====== Моды ======
Моды вносят различные изменения в игру. Например, меняют интерфейс, добавляют костюмы для персонажей, добавляют новых персонажей, изменяют сцены, которые уже есть в игре.
Официальные моды можно найти в самой игре. В главном меню сверху есть вкладка **Моды**.
===== Источники =====
По-умолчанию у вас должно быть 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."