User Tools

Site Tools


mods

Mods

Mods make various changes to the game. For example, they change the interface, add costumes for characters, add new characters, and change scenes that are already in the game.

Official mods can be found in the game itself. In the main menu at the top there is a tab Mods.

Sources

By default you should have 3 mod sources: Local Mods, Patron Mods and Official.

  • Local mods - These are mods that are already installed
  • Patron Mods - Official source of mods available only to Patrons.
  • Official - Official source of mods available to everyone.

List of sources

Mods

How to install an official mod

  1. Start the game
  2. At the top, select the Mods tab.
  3. Select the source of the mods. For example, Official.
  4. Select the mod.
  5. Click the Install button.
  6. Reload the game.

How to install a third-party mod

  1. Unpack the archive with the mod into a folder with mods. See. where the mods folder is located.

Where mods are stored

By default, mods are located in the “Kunoichi Trainer/mods” folder. The “mods” folder may not exist. In this case, it must be created manually.

Also in the game settings, if you scroll to the bottom, you can specify a different path to the folder with mods.

How to disable a mod

  1. Star the game.
  2. At the top, select the Mods tab.
  3. Select the source Local Mods.
  4. Select a mod.
  5. Click Disable.

Each mod should be in a separate folder named the same as the mod's id.

There should be a manifest.json file in the mod folder. This file must contain the same information as in the source, except for the file_name field.

Example

{
    "id": "mod-id",
    "name": "Mod name",
    "version": "1.0",
    "description": "Description of the mod",
    "game_version": "0.16"
}

Scripts

Code files must be in .rpym or .rpymc format. This is the same as .rpy and .rpyc. Don't know about .rpy and .rpyc? See RenPy documentation.

You write mod code in .rpym files, when you start the game they will be compiled into .rpymc.

The files can simply be in a folder, or in a .rpa archive.

How to replace an image from a game

To do this, you need to add a new parameter merge_folders in manifest.json, which is an array of strings. This parameter specifies a list of folders, files from which will be recognized by the game, as if they were in the game itself from the very beginning.

To change the image in the game, you need to know the location of the original image. In folder, specified in the merge_folders parameter, you need to place the new image in the same path as the original image.

Example

A simple mod that replaces the background of the room in which the player appears at the very beginning of the game.

The original background is stored in this path:

images/bg/beginning_room.webp

Mod folder structure:

 mods
└───mod-id
│   │   manifest.json
│   └───my_folder
│       └───images
│           └───bg
│               └───beginning_room.webp

Where mod-id/my_folder/images/bg/beginning_room.webp is the new image we want to replace the original one with.

The content of the manifest.json file is:

{
    "id": "mod-id",
    "name": "Mod name",
    "version": "1.0",
    "description": "Description of the mod",
    "game_version": "0.16",
    "merge_folders": ["my_folder"]
}

That's all it takes to replace the image.

How to interact with game events

To do this, you need to create a class (in the .rpym file) that inherits the Module class and subscribe to the necessary events. See List of events

For example, a module that reacts to a change in the time of day and a change in location.

init python:
    class DemoModule(Module):
        id="demo" # Each module must have a unique id
        subscribe_on_events=["time_update", "change_location"]
 
        def on_event(self, event):
            if event.type == "time_update":
                if event.is_morning:
                    renpy.notify("Morning has come")
                elif event.is_evening:
                    renpy.notify("Evening came")
            elif event.type == "change_location":
                renpy.notify("New location: " + event.new_location.id)

How to add an item to the store

To do this, you need to create a variable from the Item class if it's just an item, or from the Outfit class if it's an item of clothing.

  • It is desirable that the variable name starts with item_.
  • Item name must be unique and must not be repeated.

Examples

Adding a regular item to the Tenten shop.

init python:
  item_pen = Item(
    name=__("Handle"),
    cost=5,
    icon="my_mod_folder/pen.webp",
    descr=__("Pen with ink."),
    shop="tenten",
  )

Adding clothes to the Ten-Ten store.

init python:
  item_ino_my_new_costume = Outfit(
    name=__("New costume for Ino"),
    cost=100,
    descr=__("Item description"),
    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
    ),
  )

Mod folder structure:

mods
└───mod-id
│   │   manifest.json
│   │   item.rpym
│   └───merge_folder
│       └───images
│           └───characters
│               └───ino
│                   └───costume
│                       └───my_new_costume.webp

With this approach, the item will only be in the store if you start a new game. To add an item to the store, if the player is loading an already existing save, use Module. See. How to interact with game events and event game_loaded.

You will get something like this:

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)

Game variables

Time of the Day

if game.time.is_morning:
    "Now is the day"
elif game.time.is_evening:
    "It is evening now"
 
$ game.time.set_morning()
"Now is the day"
$ game.time.set_evening()
"Now it's evening"
 
$ game.time.next_cycle()
"If there was a day, now it is evening. If it was evening, it is now day and the counter of days has increased."
 
$ game.time.next_day()
"It is now exactly a day and the counter of days has increased by 1."
 
$ game.time.skip_days(10)
"The day counter has increased by 10."
mods.txt · Last modified: 2024/01/06 15:01 by superuser