Skip to content

Interactuar con el framework de submods

Slytharbez edited this page Jul 23, 2026 · 1 revision

💻 Interactuar con el framework de submods

Warning

El framework de submods está actualmente bajo una gran renovación debido a la migración a Python 3 de MAS. Los submods de estilo antiguo se volverán incompatibles en el futuro, por lo que se desaconseja la creación de submods complejos usando el estilo antiguo por ahora. ⚠️

El framework de submods permite registrar submods (pequeñas modificaciones personalizadas para MAS) con dependencias y tener scripts de actualización para diferentes versiones, facilitando que tus modificaciones se mantengan compatibles con las actualizaciones de MAS. 🔌

Adicionalmente, ofrece varias utilidades de desarrollo:

  • Utility para enganchar (plug) funciones en etiquetas (labels) u otras funciones.
  • Utility para importar paquetes de Python desde una ruta de archivos.
  • Utility para cargar módulos de Ren'Py de forma dinámica.

📁 Definir un submod

📂 Estructura de archivos

  • Para que MAS pueda detectar y cargar tu submod, debes definirlo explícitamente.
  • Todos los submods deben colocarse dentro del directorio game/submods/ (o game/Submods/). Se permiten subcarpetas.
  • Ejemplos válidos:
    • game/submods/Mi Submod - Mas Trajes/
    • game/submods/Mi Pack/Mi Submod - Mas Dialogos/

Important

Recuerda: Los scripts de los submods deben tener extensión .rpym y/o .rpymc. Los archivos .rpy / .rpyc no son compatibles y serán ignorados por el framework de submods. Los submods pueden incluir recursos de otros tipos: .png, .jpeg, .py, .txt, etc.

📄 Archivo de cabecera (Header)

En la carpeta raíz de tu submod, debes colocar un archivo de cabecera obligatorio llamado header.json (el nombre y la extensión importan). Utiliza el formato JSON estándar.

💻 Archivo de cabecera básico:
{
    "header_version": 1,
    "author": "Nombre Autor",
    "name": "Submod de Ejemplo",
    "version": "0.0.3",
    "modules": [
        "main"
    ]
}
💻 Archivo de cabecera avanzado:
{
    "header_version": 1,
    "author": "Nombre Autor",
    "name": "Submod de Ejemplo",
    "version": "0.0.3",
    "modules": [
        "main"
    ],
    "description": "Esta es una descripción de ejemplo.",
    "dependencies": {
        "Otro Submod": ["0.0.8", "0.1.5"]
    },
    "settings_pane": "pantalla_ajustes_ejemplo",
    "version_updates": {
        "autor_submodejemplo_v0_0_1": "autor_submodejemplo_v0_0_2"
    },
    "coauthors": ["Nombre Coautor"],
    "priority": 0
}

📌 Campos del archivo de cabecera:

  • header_version: (int) Versión del esquema de submods de MAS. Por ahora manténlo en 1. (Requerido)
  • author: (string) Nombre del creador del submod. Procura que sea único. (Requerido)
  • name: (string) Nombre identificador del submod. Debe ser único. (Requerido)
  • version: (string) Versión del submod, representada por 3 enteros separados por un punto (versionamiento semántico, ej. "1.0.0"). (Requerido)
  • modules: (list) Módulos del submod. Son archivos .rpym/.rpymc ubicados en el directorio del submod (ej. "main" corresponde a main.rpym en la raíz, "utils/logging" corresponde a logging.rpym dentro de utils/). (Requerido)
  • description: (string) Explicación breve de las características de tu submod.
  • dependencies: (object) Permite definir si tu submod requiere de otro submod instalado para funcionar. Formato: "nombre_dependencia": ["version_min", "version_max"].
  • settings_pane: (string) Pantalla (screen) que se mostrará en el menú de submods del juego (Esc > Submods) debajo del nombre de tu submod.
  • version_updates: (object) Define las etiquetas (labels) de Ren'Py que se ejecutarán en cadena como scripts de migración cuando el usuario actualice tu submod. Las etiquetas deben tener el formato autor_nombresubmod_vversion (ej. nombreautor_nombresubmod_v0_0_1).
  • coauthors: (list) Lista de coautores del submod.
  • priority: (int) Prioridad de carga del submod. Por defecto es 0. Admite valores enteros de -999 a 999. Las prioridades más bajas se cargan primero.

⛓️ Añadir dependencias

Si tu submod requiere de otro (por ejemplo, Submod Requerido), añade la clave y su rango de versiones al diccionario de dependencies. Si no hay rangos específicos de versión requeridos, puedes pasar null.

  • Ejemplo:
    "dependencies": {
        "Otro Submod": ["0.0.8", "0.1.5"],
        "Submod Requerido": [null, null]
    }

Si una dependencia falla, MAS se saltará la carga de tu submod y guardará el fallo en el archivo de registro submod_log.log.

⚙️ Añadir un panel de configuración

Para crear un panel de configuración, define una pantalla (screen) en Ren'Py que contenga las opciones e interactivos de tu submod. Vincula esta pantalla al campo settings_pane de tu header.json.

screen pantalla_ajustes_ejemplo():
    vbox:
        box_wrap False
        xfill True
        xmaximum 1000

        hbox:
            style_prefix "check"
            box_wrap False

            textbutton _("Ajuste #1") action NullAction()
            textbutton _("Ajuste #2") action NullAction()

Para mostrar descripciones (tooltips) informativas en el menú de submods de forma dinámica al pasar el cursor, puedes acceder a la pantalla principal de submods de esta manera:

screen pantalla_ajustes_ejemplo():
    python:
        submods_screen = store.renpy.get_screen("submods", "screens")
        _tooltip = submods_screen.scope.get("tooltip", None) if submods_screen else None

    vbox:
        box_wrap False
        xfill True
        xmaximum 1000

        hbox:
            style_prefix "check"
            box_wrap False

            if _tooltip:
                textbutton _("Ajuste #1"):
                    action NullAction()
                    hovered SetField(_tooltip, "value", "Descripción emergente al pasar el cursor.")
                    unhovered SetField(_tooltip, "value", _tooltip.default)
            else:
                textbutton _("Ajuste #1"):
                    action NullAction()

🔄 Crear scripts de actualización

Las etiquetas de actualización del submod se ejecutan automáticamente en el nivel de init 10 y deben estructurarse de la siguiente manera:

  • Los espacios en el autor y nombre del submod se reemplazan por guiones bajos.
  • Todos los caracteres se convierten a minúsculas.
  • Los puntos en el número de versión se reemplazan por guiones bajos.
  • La etiqueta debe aceptar un parámetro llamado version que define para qué versión es la actualización.
label monika_after_story_example_submod_v0_0_1(version="v0_0_1"):
    return

label monika_after_story_example_submod_v0_0_2(version="v0_0_2"):
    # Realiza aquí los cambios de base de datos o migración
    return

Para comprobar programáticamente si otro submod está instalado, puedes utilizar la función:
mas_submod_utils.isSubmodInstalled(name, version=None)

🔌 Uso de plugins de función (Function Plugins)

Los plugins de función permiten registrar funciones que se "engancharán" automáticamente al inicio de cualquier etiqueta (label) de Ren'Py sin necesidad de sobreescribir el archivo original. 🔗

📝 Registrar funciones

Los parámetros para registrar un plugin son:

  • key: La etiqueta (label) o función (como string) en la que deseas engancharte.
  • _function: Puntero a la función que deseas ejecutar.
  • args: Argumentos a suministrar a la función (por defecto []).
  • auto_error_handling: Si es True (por defecto), el framework capturará cualquier error y lo registrará en mas_log.log evitando que el juego se caiga.
  • priority: Orden de prioridad de ejecución (las prioridades más bajas se ejecutan antes).

1. Método decorador (Recomendado)

init python:
    @store.mas_submod_utils.functionplugin("ch30_minute")
    def mi_funcion_enganchada():
        renpy.say(m, "¡Te amo mucho!")

2. Registro manual ( registerFunction )

init python:
    store.mas_submod_utils.registerFunction("ch30_minute", mi_funcion_enganchada)

🏷️ Añadir argumentos

Para pasar argumentos a tu función, defínelos como una lista en args:

init python:
    def mi_funcion_con_argumentos(quien, frase):
        renpy.say(quien, frase)

    store.mas_submod_utils.registerFunction(
        "ch30_minute",
        mi_funcion_con_argumentos,
        args=[m, "¡Te amo mucho!"]
    )

⚙️ APIs de utilidades adicionales:

  • store.mas_submod_utils.getArgs(key, _function): Obtiene los argumentos de un plugin registrado.
  • store.mas_submod_utils.setArgs(key, _function, args=[]): Cambia los argumentos de un plugin registrado.
  • store.mas_submod_utils.unregisterFunction(key, _function): Desregistra un plugin de función.

🌎 Variables globales añadidas por el framework:

  • store.mas_submod_utils.current_label: Almacena la etiqueta (label) actual en ejecución.
  • store.mas_submod_utils.last_label: Almacena la etiqueta anterior.

Clone this wiki locally