Tutorial de Scripting para BDSP
Introducción
¡Hola! Soy Blup. Este año he descubierto las posibilidades del ROM hacking de BDSP, una base relativamente reciente y poco conocida hasta ahora.
He estado trabajando, aprendiendo e investigando intensamente sobre esta nueva base.
En este tiempo, he traducido el ROM hack Pokémon Luminescent Platinum al español, también he creado múltiples parches como un parche de accesibilidad para ayudar a jugadores ciegos a disfrutar del juego, otro para restaurar los equipos originales de BDSP y Platino, un parche que añade un Centro Pokémon portátil en forma de objeto, y mucho más.
Todo mi trabajo se puede encontrar en Nexus Mods: https://next.nexusmods.com/profile/Blupblurp/mods?gameId=5055
Actualmente colaboro como scripter para el próximo proyecto de Team Lumi: Pokémon Re:Illuminated Platinum.
He decidido crear una serie de tutoriales para demostrar que es mucho más sencillo de lo que puede parecer obtener resultados increíbles al hacer un ROM hack utilizando un juego de octava generación como es BDSP, y la gran cantidad de posibilidades que ofrece esta base, que en mi opinión está prácticamente a la par con el ROM hacking de GBA (salvo en temas de 3D, por supuesto).
Mi intención es expandir este tutorial progresivamente hasta cubrir todo lo que he aprendido. Se agradece cualquier recomendación y se aceptan sugerencias sobre aspectos del scripting que puedan interesar más a la comunidad.
Más adelante también crearé otro tutorial para enseñar cómo editar la información del juego (entrenadores, objetos, Pokémon, movimientos... ¡todo lo que podáis imaginar!), pero he decidido empezar con el scripting, ya que considero que es lo más interesante.
Muchas gracias a Team Lumi por enseñarme la mayoría de lo que he aprendido.
Índice del tutorial
Introducción al Scripting
Los scripts son los encargados de gestionar el diálogo en el juego, los eventos, el movimiento de NPCs, las batallas contra entrenadores y mucho más.
El sistema de scripting de BDSP es muy similar al de Pokémon Platino para Nintendo DS. Además, utiliza un lenguaje propietario que es bastante sencillo de aprender.
Podéis encontrar más documentación e información sobre los comandos en:
Cómo preparar el entorno de desarrollo
Configurando VS Code con las extensiones para ev_as
Clona mi fork de ev-as y sigue las instrucciones para configurarlo en: https://github.com/BlupBlurp/multi-language-ev-as
Si no tienes Git instalado, puedes simplemente descargar el código en este enlace: https://github.com/BlupBlurp/multi-language-ev-as/archive/refs/heads/main.zip
La carpeta del proyecto debería quedar de la siguiente forma:
Obteniendo el archivo ev_script
Este tutorial asume que el usuario ya posee su propia copia de Brilliant Diamond o Shining Pearl, junto con la actualización 1.3.0.
Puedes omitir este paso si quieres usar Luminescent Platinum (https://www.nexusmods.com/pokemonbdsp/mods/1) (muy recomendado) como base para tu proyecto en lugar de BDSP vanilla.
Extraer scripts
En la consola, ejecuta
Mueve todos estos archivos a la carpeta "scripts".
Compilar scripts
Una vez hayas terminado tus cambios o quieras testear, utiliza
Estructura y sintaxis de un script
Dentro de cada archivo encontraréis múltiples funciones (también llamadas scripts, aunque puede resultar confuso llamar tanto a los archivos como a su contenido por el mismo nombre). Todas siguen la misma estructura:

Convenciones de nomenclatura
Puedes elegir el nombre que quieras para tus funciones, siempre y cuando sean únicos EN TODO EL PROYECTO.
Dos funciones no pueden llamarse de la misma forma, incluso aunque formen parte de archivos distintos, ya que el juego trata todo como un mismo archivo.
Normalmente se utilizan las siguientes reglas:
Scripts de cada mapa
Los distintos archivos están nombrados usando el identificador del mapa al que están asociados. Podéis encontrar una lista de todos los mapas y sus identificadores en: https://luminescent.team/rom-hacking/dictionary/zones (en la última columna llamada "Zone code").
Los map scripts son scripts especiales que se pueden identificar porque su nombre empieza por "sp_" seguido del identificador del mapa. Estos scripts contienen funciones que son llamadas cuando se accede al mapa.
Normalmente encontraréis cuatro tipos:
Scripts especiales
Algunos scripts no están relacionados con un mapa específico. Los más importantes son:
PlaceDatas (NPCs y otras entidades del mapa)
Introducción
PlaceDatas es como se conoce a todas las entidades de un mapa: NPCs, objetos, arbustos de bayas, etc. (conocidos como "Overworlds" en otras bases).
La información de estos objetos se encuentra en los archivos PlaceData de cada mapa, dentro del archivo masterdatas, en:
Extracción de archivos
Para poder extraer los archivos, es necesario usar la herramienta BDSP Repacker, que podéis descargar aquí: https://github.com/Ai0796/BDSP-Repacker
Una vez que hayas realizado los cambios que desees:
Estructura de archivos PlaceData
Los archivos PlaceData siempre se llaman "PlaceData_" seguido del mismo identificador de mapa que se usa en los scripts.
Dentro, lo que nos importa es el array "Data". Aquí se encuentran todos los objetos de ese mapa, todos con las mismas propiedades:

Propiedades principales

Propiedades de movimiento
Propiedades de interacción
Propiedades de rango de interacción
Archivos de área
Algunos mapas están agrupados en "Áreas", en vez de tener archivos PlaceData individuales. Por ejemplo: "PlaceData_A01.json".
Estos archivos contienen múltiples mapas exteriores en uno, y sus objetos se distinguen porque tienen distintos zoneIDs.
Para saber a qué área corresponde cada mapa, podéis consultar la columna "File Path" de la tabla: https://luminescent.team/rom-hacking/dictionary/zones
Flags, inverse flags, sysflags y works
Introducción
En el scripting de BDSP, existen cuatro tipos de variables que nos permiten gestionar el estado del juego:
Flags
Las flags se pueden reconocer por un "#" seguido de un número, por ejemplo
La flag
El resto de flags deberían estar disponibles, pero es importante siempre comprobar que el nuevo número que vayas a utilizar no esté ya en uso.
Cómo verificar si una flag está libre
Comandos para modificar flags
Las inverse flags son flags especiales que están activadas por defecto, en vez de desactivadas. Estas flags están definidas en los scripts
Cómo encontrar las inverse flags
SysFlags
Las SysFlags son flags importantes para los sistemas del juego. Se pueden identificar como
Por ejemplo,
Comandos para modificar SysFlags
Los works pueden contener multitud de valores, y se identifican como
Los works desde 0 hasta 439 son utilizados por el juego.
Works temporales
Algunos works tienen la función de ser utilizados temporalmente, para cuando necesitas conservar un valor dentro de una función para usarlo más tarde, pero no necesitas conservarlo a largo plazo:
Introducción
Una vez has entendido el concepto de works y flags, es hora de introducir algunos de los comandos más importantes para la lógica del scripting.
Estos comandos te permiten:
El comando
El comando
Los comandos
Comparadores disponibles
IF_FLAG
Similar a IFVAL, estos comandos comprueban si una flag está activada (set, on) o desactivada (reset, off), y si es así, saltan o llaman a otro script:
El comando
Cómo utilizarlo
Introducción
Los StopDatas, también conocidos como "triggers" en otras bases, actúan como un rango de tiles invisibles que accionan una función cuando el jugador entra en dicho rango.
Están definidos en los archivos StopData de masterdatas, al igual que los PlaceDatas. Se pueden identificar porque su nombre siempre empieza por "StopData_" seguido del identificador del mapa.

Estructura de archivos StopData
Al igual que los PlaceData, los StopDatas tienen distintas propiedades importantes:
Propiedades principales
Comandos de movimiento y animaciones
Introducción
Las funciones de animación son funciones especiales que permiten modificar el estado del jugador o PlaceDatas. Con estas funciones puedes:
Las funciones de animación siguen reglas específicas:

Cómo utilizar funciones de animación
Llamar a una función de animación
Una vez que hayas creado tu función, puedes llamarla utilizando el comando
Sincronización de animaciones
El comando
Comandos de dirección
Estos comandos cambian la dirección hacia la que mira un PlaceData:
Comandos de movimiento
Estos comandos hacen que el PlaceData se mueva una cantidad específica de tiles:
Añadir sonido a las reacciones
Las reacciones de emoji no tienen sonido por defecto, pero puedes añadirlo:
Comandos avanzados
Existen muchos más comandos de animación, como:
Introducción
Para editar los diálogos del juego o añadir nuevos, se utilizan "comandos de macros". Estos comandos te permiten:
Paso 1: Obtener los archivos
El primer paso es extraer los archivos de idioma del juego:
Una vez hayas realizado cambios en los archivos de idioma, y quieras añadirlos al juego:
Estructura final del proyecto
La estructura debería quedar así:
Comandos de Macros
Una vez que hayas preparado los archivos de idioma, puedes empezar a usar los comandos de macros.
Entendiendo los comandos de diálogo tradicionales
Habrás notado que los scripts utilizan comandos como:
Este comando:
Versión macro
La mayoría de los comandos de diálogo tienen una versión macro que permite editar el texto directamente desde el script:
Funcionamiento de los comandos macro
Para gestionar múltiples líneas, se pueden utilizar secuencias de escape en el texto:
Secuencias disponibles
Herramienta recomendada
Una herramienta esencial para escribir diálogos es BDSP Message Previewer: https://github.com/ProfBlack/BDSP-Message-Previewer/releases
Con esta herramienta puedes:
Ejemplo práctico
Este comando:
Convenciones de nomenclatura
Qué archivo elegir
Los diálogos pueden añadirse a cualquier archivo, pero para mantener organización:
Reglas para identificadores
Para elegir un nuevo identificador, sigue estas reglas:
Todas las funciones que utilizan diálogos suelen seguir la misma estructura:
1. Comandos de inicio
Comienzan por uno de estos comandos:
2. Comandos de diálogo
3. Comando de finalización
Otros comandos de macro útiles
Opciones múltiples
Diálogos simples
Los comandos de macro permiten utilizar variables llamadas "tags" que reciben información del script y la reflejan en el diálogo.
¿Qué permiten los tags?
Ejemplo práctico
En este ejemplo,
Introducción
¡Hola! Soy Blup. Este año he descubierto las posibilidades del ROM hacking de BDSP, una base relativamente reciente y poco conocida hasta ahora.
He estado trabajando, aprendiendo e investigando intensamente sobre esta nueva base.
En este tiempo, he traducido el ROM hack Pokémon Luminescent Platinum al español, también he creado múltiples parches como un parche de accesibilidad para ayudar a jugadores ciegos a disfrutar del juego, otro para restaurar los equipos originales de BDSP y Platino, un parche que añade un Centro Pokémon portátil en forma de objeto, y mucho más.
Todo mi trabajo se puede encontrar en Nexus Mods: https://next.nexusmods.com/profile/Blupblurp/mods?gameId=5055
Actualmente colaboro como scripter para el próximo proyecto de Team Lumi: Pokémon Re:Illuminated Platinum.
He decidido crear una serie de tutoriales para demostrar que es mucho más sencillo de lo que puede parecer obtener resultados increíbles al hacer un ROM hack utilizando un juego de octava generación como es BDSP, y la gran cantidad de posibilidades que ofrece esta base, que en mi opinión está prácticamente a la par con el ROM hacking de GBA (salvo en temas de 3D, por supuesto).
Mi intención es expandir este tutorial progresivamente hasta cubrir todo lo que he aprendido. Se agradece cualquier recomendación y se aceptan sugerencias sobre aspectos del scripting que puedan interesar más a la comunidad.
Más adelante también crearé otro tutorial para enseñar cómo editar la información del juego (entrenadores, objetos, Pokémon, movimientos... ¡todo lo que podáis imaginar!), pero he decidido empezar con el scripting, ya que considero que es lo más interesante.
Para contactar conmigo, podéis comentar en este post o uniros a mi servidor de Discord sobre modding de BDSP, donde puedo resolver cualquier duda y publico actualizaciones sobre mis parches: https://discord.gg/5Qwz85EvC3
Muchas gracias a Team Lumi por enseñarme la mayoría de lo que he aprendido.
Índice del tutorial
- Introducción
- Cómo preparar el entorno de desarrollo
- Entendiendo los distintos archivos y la estructura de los scripts
- PlaceDatas (Overworlds)
- Flags, inverse flags, sysflags y works
- Control de flujo: JUMP, CALL, IFVAL, IF_FLAG, SWITCH
- StopDatas (Triggers)
- Comandos de movimiento y animaciones
- Comandos de Macros y archivos de idioma
- Map Warps
- Lista completa de comandos
- ...
Introducción al Scripting
Los scripts son los encargados de gestionar el diálogo en el juego, los eventos, el movimiento de NPCs, las batallas contra entrenadores y mucho más.
El sistema de scripting de BDSP es muy similar al de Pokémon Platino para Nintendo DS. Además, utiliza un lenguaje propietario que es bastante sencillo de aprender.
Podéis encontrar más documentación e información sobre los comandos en:
Cómo preparar el entorno de desarrollo
Configurando VS Code con las extensiones para ev_as
- Descarga VS Code
- Busca "BDSP Tools" en las extensiones e instálalo
Clona mi fork de ev-as y sigue las instrucciones para configurarlo en: https://github.com/BlupBlurp/multi-language-ev-as
Si no tienes Git instalado, puedes simplemente descargar el código en este enlace: https://github.com/BlupBlurp/multi-language-ev-as/archive/refs/heads/main.zip
La carpeta del proyecto debería quedar de la siguiente forma:
Código:
├───bin
├───Dpr
├───parsed
├───scripts
└───src
└───ev_as.py
└───ev_parse.py
Este tutorial asume que el usuario ya posee su propia copia de Brilliant Diamond o Shining Pearl, junto con la actualización 1.3.0.
Puedes omitir este paso si quieres usar Luminescent Platinum (https://www.nexusmods.com/pokemonbdsp/mods/1) (muy recomendado) como base para tu proyecto en lugar de BDSP vanilla.
- Crea una carpeta llamada "romfs"
- Ve a Ryujinx, haz clic derecho en el juego
- En la parte inferior, pulsa en "Extract Data > RomFS"
- Elige la carpeta que acabas de crear como destino
romfs\Data\StreamingAssets\AssetAssistant\Dpr y copia el archivo ev_script a la carpeta "Dpr" de tu proyecto.Extraer scripts
En la consola, ejecuta
python scr/ev_parse.py. Esto debería extraer todos los archivos de scripts a la carpeta "parsed".Mueve todos estos archivos a la carpeta "scripts".
Compilar scripts
Una vez hayas terminado tus cambios o quieras testear, utiliza
python scr/ev_as.py. Esto debería crear un nuevo archivo ev_script dentro de la carpeta "bin".- Si has usado Lumi como base, reemplaza el archivo
ev_scriptque usaste originalmente por este, y tus cambios aparecerán en el juego. - Si has usado BDSP vanilla como base, deberás crear tu propia carpeta para tu mod, utilizando la misma ruta:
romfs\Data\StreamingAssets\AssetAssistant\Dpr
Entendiendo los distintos archivos y la estructura de los scriptsMuy recomendable para cualquier proyecto serio: usar Git y GitHub.
Estructura y sintaxis de un script
Dentro de cada archivo encontraréis múltiples funciones (también llamadas scripts, aunque puede resultar confuso llamar tanto a los archivos como a su contenido por el mismo nombre). Todas siguen la misma estructura:
- Un nombre (también conocido como label) marcado en azul que identifica la función
- Comandos (es importante que cada función siempre acabe con `_END()` o `_RET()`. Explicación más adelante.)
- Comentarios. Siempre comienzan por ";", y no afecta el código. Útiles para documentar los scripts.

Convenciones de nomenclatura
Puedes elegir el nombre que quieras para tus funciones, siempre y cuando sean únicos EN TODO EL PROYECTO.
Dos funciones no pueden llamarse de la misma forma, incluso aunque formen parte de archivos distintos, ya que el juego trata todo como un mismo archivo.
Normalmente se utilizan las siguientes reglas:
- Los nombres siempre empiezan por "ev_" (a excepción de animaciones, stopdatas o map scripts, que se tratarán más adelante)
- Seguido del identificador del mapa (el mismo que el nombre del archivo)
- Finalmente una palabra o varias para identificar qué hace la función
- Todo separado con guiones bajos "_"
Scripts de cada mapa
Los distintos archivos están nombrados usando el identificador del mapa al que están asociados. Podéis encontrar una lista de todos los mapas y sus identificadores en: https://luminescent.team/rom-hacking/dictionary/zones (en la última columna llamada "Zone code").
Map scriptsTip: Puedes usar "Ctrl + P" en VS Code para buscar archivos rápidamente.
Los map scripts son scripts especiales que se pueden identificar porque su nombre empieza por "sp_" seguido del identificador del mapa. Estos scripts contienen funciones que son llamadas cuando se accede al mapa.
Normalmente encontraréis cuatro tipos:
- INIT
- OBJ
- SCENE
- FLAG
Scripts especiales
Algunos scripts no están relacionados con un mapa específico. Los más importantes son:
- common_scr: Contiene funciones que son llamadas por distintos scripts, utilizado para evitar repetir funciones comunes en cada script
- door: Contiene las funciones que se ejecutan cuando el jugador entra por una puerta
- init_scr: Este script se ejecuta al empezar una nueva partida
PlaceDatas (NPCs y otras entidades del mapa)
Introducción
PlaceDatas es como se conoce a todas las entidades de un mapa: NPCs, objetos, arbustos de bayas, etc. (conocidos como "Overworlds" en otras bases).
La información de estos objetos se encuentra en los archivos PlaceData de cada mapa, dentro del archivo masterdatas, en:
\romfs\Data\StreamingAssets\AssetAssistant\DprExtracción de archivos
Para poder extraer los archivos, es necesario usar la herramienta BDSP Repacker, que podéis descargar aquí: https://github.com/Ai0796/BDSP-Repacker
- Coloca el archivo masterdatas en "AssetFolder"
- Usa "unpack.exe"
- Dentro de la carpeta AssetFolder debería aparecer una nueva carpeta llamada "masterdatas_Export"
- Copia esta carpeta a la carpeta de tu proyecto
Una vez que hayas realizado los cambios que desees:
- Copia de nuevo la carpeta "masterdatas_export"
- Llévala a la carpeta AssetFolder de BDSP repacker
- Reemplaza los archivos cuando te lo indique
- Ejecuta "Repack.exe"
- En la carpeta "EditedAssets" verás un nuevo archivo masterdatas que puedes colocar en tu mod
Estructura de archivos PlaceData
Los archivos PlaceData siempre se llaman "PlaceData_" seguido del mismo identificador de mapa que se usa en los scripts.
Dentro, lo que nos importa es el array "Data". Aquí se encuentran todos los objetos de ese mapa, todos con las mismas propiedades:

Propiedades principales
- ID: Nombre del objeto, debe ser único, en mayúsculas. Normalmente empieza con el nombre del mapa, seguido de una palabra descriptiva
- zoneID: Número del mapa en el que se encuentra el objeto, corresponde a la primera columna de la tabla de zonas
- TrainerID: Identificador del entrenador, si el NPC es un entrenador. Si no, siempre es 0 (solo se usa para entrenadores que pueden empezar una batalla al verte, no para batallas scripteadas como líderes de gimnasio)
- ObjectGraphicIndex (OGI): Determina el modelo que se usará para la entidad (personaje, Pokémon, Pokéball, etc.)
Para utilizar modelos de Pokémon, se usa:numeroDex/00/00. Los ceros hacen referencia a la forma del Pokémon (si tiene formas alternativas, su género, si es shiny, etc. Por ejemplo, "1510000" sería Mew.
Podeis encontrar una lista en: https://bdsp-modding.wiki/index.php/Visuals#Object_Graphics - ColorIndex: Algunos ObjectGraphicIndex pueden tener variantes, como distintos colores de piel o pelo. Si se usa -1, copiará al jugador
- Position: La posición del objeto en el mapa. 0,0 es siempre arriba a la izquierda
- HeightLayer: La posición Z del objeto. Importante, por ejemplo, si se encuentra encima de una montaña
- HeightIgnore: Cuando es 1, te permite interactuar con el objeto aunque no esté a tu misma altura
- Size: Normalmente es siempre 0,0. Solo se pueden modificar estos valores si el OGI es un Pokémon u otro AssetBundle
- Rotation: La rotación del objeto (imagen debajo mostrando el ángulo de cada dirección)

Propiedades de movimiento
- MoveLimit: Algunos MoveCodes permiten al NPC andar por sí mismo; estos valores limitan cuánto puede moverse en cada dirección
- MoveCode: Determina cómo el objeto se va a mover
Código:
MV_DMY = 0 MV_RTLUDR = 29
MV_PLAYER = 1 MV_RTUDRL = 30
MV_DIR_RND = 2 MV_RTRLUD = 31
MV_RND = 3 MV_RTDRLU = 32
MV_RND_V = 4 MV_RTRUDL = 33
MV_RND_H = 5 MV_RTUDLR = 34
MV_RND_UL = 6 MV_RTLRUD = 35
MV_RND_UR = 7 MV_RTDLRU = 36
MV_RND_DL = 8 MV_RTUL = 37
MV_RND_DR = 9 MV_RTDR = 38
MV_RND_UDL = 10 MV_RTLD = 39
MV_RND_UDR = 11 MV_RTRU = 40
MV_RND_ULR = 12 MV_RTUR = 41
MV_RND_DLR = 13 MV_RTDL = 42
MV_UP = 14 MV_RTLU = 43
MV_DOWN = 15 MV_RTRD = 44
MV_LEFT = 16 MV_RND_UD = 45
MV_RIGHT = 17 MV_RND_LR = 46
MV_SPIN_L = 18 MV_SEED = 47
MV_SPIN_R = 19 MV_PAIR = 48
MV_RT2 = 20 MV_REWAR = 49
MV_RTURLD = 21 MV_TR_PAIR = 50
MV_RTRLDU = 22 MV_HIDE_SNOW = 51
MV_RTDURL = 23 MV_HIDE_SAND = 52
MV_RTLDUR = 24 MV_HIDE_GRND = 53
MV_RTULRD = 25 MV_HIDE_KUSA = 54
MV_RTLRDU = 26 MV_CODE_MAX = 55
MV_RTDULR = 27 MV_CODE_NOT = 255
MV_RTRDUL = 28
- MoveParam0, MoveParam1, MoveParam2: Algunos MoveCodes utilizan estos parámetros. Por ejemplo, los entrenadores necesitan un MoveCode de 14-17 y MoveParam0 indica a cuántos tiles de distancia pueden ver al jugador
Propiedades de interacción
- TalkLabel: La función que se ejecutará cuando el jugador interactúe con el objeto
- ContactLabel: La función que se ejecutará cuando el jugador choque contra el objeto
- Work: Este valor es 4000 si el objeto es siempre visible. Otros valores de flags pueden ser usados para hacer que el objeto aparezca solo en determinadas ocasiones, o hacerlo desaparecer al final de un evento. Más información en el apartado de flags
- Dowsing: Si el valor es 1 o 2, determina a qué distancia se puede detectar un objeto oculto
- LoadFirst: Da prioridad al PlaceData para cargarse antes que otros. Normalmente 0
- DoNotLoad: Siempre 4000
Propiedades de rango de interacción
- TalkToRange: Distancia desde la que se puede interactuar con un objeto. Siempre se añade 0.25 a la cantidad de tiles. Normalmente 1.25
- TalkToSize: Utilizando valores superiores a 1, expande la cantidad de tiles que forman el área desde la que se puede interactuar (sin cambiar nada visualmente). Cada tile se podrá interactuar desde la distancia determinada por TalkToRange. Normalmente utilizado en televisiones, que usan un único PlaceData y ocupan dos tiles de ancho
- TalkBit: Indica las direcciones desde las que se puede interactuar con el objeto
Código:
1 (0001): Solo desde arriba
2 (0010): Solo desde abajo
3 (0011): Desde arriba y desde abajo
4 (0100): Solo desde la derecha
5 (0101): Arriba y derecha
6 (0110): Abajo y derecha
7 (0111): Arriba, abajo y derecha
8 (1000): Solo desde la izquierda
9 (1001): Arriba e izquierda
10 (1010): Abajo e izquierda
11 (1011): Arriba, abajo e izquierda
12 (1100): Derecha e izquierda
13 (1101): Arriba, derecha e izquierda
14 (1110): Abajo, derecha e izquierda
15 (1111): Todas las direcciones
Archivos de área
Algunos mapas están agrupados en "Áreas", en vez de tener archivos PlaceData individuales. Por ejemplo: "PlaceData_A01.json".
Estos archivos contienen múltiples mapas exteriores en uno, y sus objetos se distinguen porque tienen distintos zoneIDs.
Para saber a qué área corresponde cada mapa, podéis consultar la columna "File Path" de la tabla: https://luminescent.team/rom-hacking/dictionary/zones
Flags, inverse flags, sysflags y works
Introducción
En el scripting de BDSP, existen cuatro tipos de variables que nos permiten gestionar el estado del juego:
- Flags: Variables booleanas que pueden ser verdadero o falso (set o unset). Usadas en la mayoría de eventos para marcar cuándo un script ha sido completado, o que decisiones ha tomado el jugador.
- Inverse Flags: Igual que las flags, pero están activadas por defecto.
- SysFlags: Flags del sistema, utilizadas para marcar información importante, como si una medalla ha sido obtenida.
- Works: Variables que pueden contener cualquier valor numérico, ya sea decimal o entero, o incluso texto. Utilizadas para guardar información que necesita más complejidad que una flag.
Flags
Las flags se pueden reconocer por un "#" seguido de un número, por ejemplo
#2450. Las flags de la 1 a la 1756 son usadas por el juego y también pueden aparecer utilizando un nombre en vez de un número, por ejemplo #FE_C06R0401_BIGMAN_TALK.La flag
#4000 es especial, ya que es una flag que siempre está desactivada. Se utiliza, por ejemplo, en los PlaceDatas que siempre están visibles.El resto de flags deberían estar disponibles, pero es importante siempre comprobar que el nuevo número que vayas a utilizar no esté ya en uso.
Cómo verificar si una flag está libre
- Utiliza la función de buscar en todo el proyecto de VSCode (Ctrl+Shift+F)
- Busca en todos los scripts si la flag ya está en uso:
#numero - Comprueba también si se utiliza en algún PlaceData:
"Work": numero - Si la búsqueda no devuelve ningún resultado, entonces la flag está libre
- Si aparece solo en los scripts
door.evy/oinit_scr.ev, entonces la flag seguramente sea una inverse flag
Comandos para modificar flags
FLAG_SET(#flag): Activa la flagFLAG_RESET(#flag): Desactiva la flag
Las inverse flags son flags especiales que están activadas por defecto, en vez de desactivadas. Estas flags están definidas en los scripts
door.ev y/o init_scr.ev.Cómo encontrar las inverse flags
- Dirígete a
door.ev - Busca la función
ev_healthcheck_init_inverse_flags - Allí verás todos los números que son inverse flags
- También puedes comprobar
init_scr.ev, pero no siempre son las mismas - Puedes añadir cualquier flag que no esté en la lista y no esté utilizada para convertirla en una inverse flag
SysFlags
Las SysFlags son flags importantes para los sistemas del juego. Se pueden identificar como
$numero o $nombre.Por ejemplo,
$BADGE_ID_C03 guarda la información sobre si la medalla de Ciudad Pirita ha sido obtenida.Comandos para modificar SysFlags
_SET_SYS_FLAG($flag): Activa la sysflag_RESET_SYS_FLAG($flag): Desactiva la sysflag
Los works pueden contener multitud de valores, y se identifican como
@número.Los works desde 0 hasta 439 son utilizados por el juego.
Works temporales
Algunos works tienen la función de ser utilizados temporalmente, para cuando necesitas conservar un valor dentro de una función para usarlo más tarde, pero no necesitas conservarlo a largo plazo:
@LOCALWORK0hasta@LOCALWORK31@SCWK_TEMP0hasta@SCWK_TEMP3@SCWK_ANSWER: Normalmente utilizado en comandos que devuelven un valor
- Utiliza la función de búsqueda de VSCode
- Busca
@numeroen todos los archivos - Busca
"Work": numeroen archivos StopData
_LDWK([USER=45027]@Work[/USER], value): Establece el valor de un work_ADD_WK([USER=45027]@Work[/USER], value): Añade el valor proporcionado al work_SUB_WK([USER=45027]@Work[/USER], value): Resta el valor proporcionado al work
Introducción
Una vez has entendido el concepto de works y flags, es hora de introducir algunos de los comandos más importantes para la lógica del scripting.
Estos comandos te permiten:
- Saltar o llamar a otros scripts
- Comprobar el valor de una flag o work para hacer saltos condicionales
- Crear eventos complejos que cambian en función de las decisiones del jugador, de su progreso, de su posición, etc.
El comando
_JUMP('label-del-script') te permite saltar a otra función.CALLImportante: Cuando se salta a otra función de esta forma, los comandos que se encuentren después de JUMP nunca serán ejecutados, ya que la ejecución ya ha saltado a una función distinta.
El comando
_CALL('label-del-script') llama a otra función. A diferencia de JUMP, cuando todos los comandos de esa función se hayan ejecutado:- Si la función acaba con
_RET()en lugar de_END(), el script volverá a la función original del comando CALL - Seguirá ejecutando los comandos posteriores al CALL
IFVALNota: Si una función utiliza CALL para saltar a otra, y esa otra utiliza JUMP para saltar a una tercera función que acaba en_RET(), la ejecución también volverá a la primera función original donde se encuentra el comando CALL.
Los comandos
_IFVAL_JUMP([USER=45027]@Work[/USER], 'comparador', valor, 'label-del-script') y _IFVAL_CALL permiten comprobar si el valor de un work cumple una condición, y si es así, saltan o llaman a otro script.Comparadores disponibles
- EQ: El valor del work y el segundo valor son iguales
- NE: Los valores son distintos
- GT: El primer valor es mayor que el segundo
- GE: El primer valor es mayor o igual que el segundo
- LT: El primer valor es menor que el segundo
- LE: El primer valor es menor o igual que el segundo
IF_FLAG
Similar a IFVAL, estos comandos comprueban si una flag está activada (set, on) o desactivada (reset, off), y si es así, saltan o llaman a otro script:
_IF_FLAGON_JUMP(#flag, 'label-del-script')_IF_FLAGOFF_JUMP(#flag, 'label-del-script')_IF_FLAGON_CALL(#flag, 'label-del-script')_IF_FLAGOFF_CALL(#flag, 'label-del-script')
El comando
_SWITCH([USER=45027]@Work[/USER]) permite hacer múltiples comprobaciones de igualdad referidas a un mismo work más fácilmente que usando IFVAL.Cómo utilizarlo
- Primero se indica el work con el comando
_SWITCH([USER=45027]@Work[/USER]) - A continuación se utilizan los comandos
_CASE_JUMP(valor, 'label-del-script')y_CASE_CALL(valor, 'label-del-script') - Si el work indicado y el valor son iguales, se saltará o llamará a la función
Introducción
Los StopDatas, también conocidos como "triggers" en otras bases, actúan como un rango de tiles invisibles que accionan una función cuando el jugador entra en dicho rango.
Están definidos en los archivos StopData de masterdatas, al igual que los PlaceDatas. Se pueden identificar porque su nombre siempre empieza por "StopData_" seguido del identificador del mapa.

Estructura de archivos StopData
Al igual que los PlaceData, los StopDatas tienen distintas propiedades importantes:
Propiedades principales
- ID: Nombre único del StopData. Generalmente siempre comienza por "SCRID_POS", seguido del identificador del mapa, y a continuación una palabra descriptiva
- Position: Determina la posición del StopData en el mapa
- HeightLayer: Determina la altura a la que se encuentra en el mapa
- Size: Determina el tamaño del área. Es importante tener en cuenta que el tile inicial se encuentra siempre arriba a la izquierda, por lo que el tamaño se aumenta hacia abajo y hacia la derecha
- ContactLabel: Función que será llamada cuando el jugador entre en el área. A diferencia de las funciones normales, su nombre empieza por "pos_" en vez de "ev_"
- Param: Valor que el work proporcionado deberá tener para que el StopData se active cuando el jugador entra en su rango. Si el valor es cualquier otro, la función no será llamada
- Work: Work (en número) que el StopData comprobará contra el "Param"
Comandos de movimiento y animaciones
Introducción
Las funciones de animación son funciones especiales que permiten modificar el estado del jugador o PlaceDatas. Con estas funciones puedes:
- Mostrar burbujas de emojis sobre los personajes
- Hacer que los NPCs caminen una cantidad específica de tiles
- Reproducir animaciones concretas
- Cambiar la dirección hacia la que mira un personaje
- Y mucho más
Las funciones de animación siguen reglas específicas:
- Siempre empiezan su nombre por
anm_en vez deev_ - Seguido del identificador del mapa y palabras descriptivas
- Siempre acaban con el comando
_ACMD_END(), en vez de_END()
Importante: Los comandos de animación solo pueden ser utilizados dentro de funciones de animación, estos comandos empiezan porAC_. Los comandos normales tampoco funcionarán dentro de funciones de animación.

Cómo utilizar funciones de animación
Llamar a una función de animación
Una vez que hayas creado tu función, puedes llamarla utilizando el comando
_OBJ_ANIME('PlaceData-ID', 'label').- Este comando ejecutará la animación indicada en el PlaceData especificado
- Si deseas que el jugador realice la función, el ID del PlaceData deberá ser
'HERO'
Sincronización de animaciones
El comando
_OBJ_ANIME_WAIT() es muy útil para controlar el flujo:- Pausa la ejecución de la función principal hasta que la función de animación haya terminado
- Diálogos u otras animaciones no ocurren hasta que la primera haya acabado
- Sin este comando, la función principal continuará mientras la animación se ejecuta en paralelo
Comandos de animación principalesNota: Las funciones de animación se ejecutan de forma asíncrona, por lo que es importante usar_OBJ_ANIME_WAIT()cuando necesites sincronización.
Comandos de dirección
Estos comandos cambian la dirección hacia la que mira un PlaceData:
_AC_DIR_U(tiempo): Mirar hacia arriba (Up)_AC_DIR_D(tiempo): Mirar hacia abajo (Down)_AC_DIR_L(tiempo): Mirar hacia la izquierda (Left)_AC_DIR_R(tiempo): Mirar hacia la derecha (Right)
tiempo indica la cantidad de frames que tarda en completar el giro.Comandos de movimiento
Estos comandos hacen que el PlaceData se mueva una cantidad específica de tiles:
_AC_UP(tiles, frames): Moverse hacia arriba_AC_DOWN(tiles, frames): Moverse hacia abajo_AC_LEFT(tiles, frames): Moverse hacia la izquierda_AC_RIGHT(tiles, frames): Moverse hacia la derecha
Comandos de tiempo y esperaImportante: Los comandos de movimiento no cambian la dirección automáticamente. Si mueves a un PlaceData a la derecha sin hacer primero que mire hacia la derecha, se moverá hacia la derecha mientras sigue mirando hacia la dirección anterior.
_AC_WAIT(frames): Espera una cantidad de frames antes de continuar con la ejecución
_AC_MARK_GYOE(): Hace que el PlaceData reaccione con una exclamación y sonido de exclamación_AC_MARK_EMO(id): Hace que el PlaceData reaccione con un emoji específico
_AC_MARK_EMO, puedes encontrar la lista completa de emojis disponibles en: https://luminescent.team/rom-hacking/dictionary/chibi-emotionsAñadir sonido a las reacciones
Las reacciones de emoji no tienen sonido por defecto, pero puedes añadirlo:
- Usa el comando
_PLAY_EMO_SE(id)en la función donde la animación es llamada - NO en la función de animación misma
- Normalmente se coloca entre
_OBJ_ANIMEy_OBJ_ANIME_WAIT
_AC_INDEX_ANIME(id): Reproduce una animación específica del PlaceData_AC_INDEX_ANIME_WAIT(): Hace que la ejecución espere a que la animación termine
Comandos avanzados
Existen muchos más comandos de animación, como:
_AC_WORLD_X/_AC_WORLD_Z: Para hacer que el PlaceData se mueva a una posición específica_AC_HERO_MATCH_X: Para hacer que un PlaceData se mueva hasta coincidir con la posición del jugador- Y muchos otros comandos especializados
Comandos de Macros y archivos de idiomaTip para aprender: La mejor forma de aprender y descubrir nuevos comandos es revisar scripts existentes que hagan cosas similares a lo que estás buscando. Muchos de estos comandos no están completamente documentados, pero puedes encontrar ejemplos prácticos en los scripts del juego.
Introducción
Para editar los diálogos del juego o añadir nuevos, se utilizan "comandos de macros". Estos comandos te permiten:
- Interactuar con los archivos de idioma sin modificarlos manualmente
- Crear y editar diálogos directamente desde los scripts
Paso 1: Obtener los archivos
El primer paso es extraer los archivos de idioma del juego:
- Ve a
romfs\Data\StreamingAssets\AssetAssistant\Message - Copia el idioma que desees:
-"spanish"si quieres desarrollar en español
-"english"si quieres desarrollar en inglés
Paso 2: Extraer con BDSP-RepackerAlternativa para usuarios de Lumi: Si usas Lumi como base en vez de BDSP vanilla, puedes descargar mi parche al español y copiar el archivo "spanish" desde: https://www.nexusmods.com/pokemonbdsp/mods/49
- Lleva el archivo de idioma a la carpeta AssetFolder de BDSP-Repacker
- Al igual que con el archivo masterdatas, ejecuta
unpack.exe - En la carpeta AssetFolder aparecerá una nueva carpeta llamada:
-spanish_Exportoenglish_Export(según el idioma elegido) - Copia esta carpeta y llévala a tu proyecto
Una vez hayas realizado cambios en los archivos de idioma, y quieras añadirlos al juego:
- Lleva la carpeta
spanish_Exportde tu proyecto a la carpeta AssetFolder de BDSP-Repacker - Reemplaza los archivos cuando te lo indique
- Ejecuta
repack.exe - En la carpeta EditedAssets aparecerá tu nuevo archivo
- Copia este archivo y llevale a la misma ruta
romfs\Data\StreamingAssets\AssetAssistant\Messageen tu mod.
Estructura final del proyecto
La estructura debería quedar así:
Código:
├───AssetFolder
└───spanish_Export
└───masterdatas_Export
├───bin
├───Dpr
├───parsed
├───scripts
└───src
Una vez que hayas preparado los archivos de idioma, puedes empezar a usar los comandos de macros.
Entendiendo los comandos de diálogo tradicionales
Habrás notado que los scripts utilizan comandos como:
_TALKMSG('dp_scenario1%66-msg_c03_girl3_02')Este comando:
- Muestra una caja de texto con el diálogo
"66-msg_c03_girl3_02"del archivo"dp_scenario1" - Puedes encontrar el texto buscando el identificador en los archivos JSON exportados
Versión macro
La mayoría de los comandos de diálogo tienen una versión macro que permite editar el texto directamente desde el script:
_MACRO_TALKMSG('archivo', 'identificador', 'texto')Funcionamiento de los comandos macro
- Si el identificador NO existe en el archivo: ev-as creará una nueva entrada con el texto proporcionado
- Si el diálogo YA existe: ev-as reemplazará el texto por el nuevo
Secuencias de escapeConfiguración de idioma: Por defecto, ev-as busca archivos en inglés. Para trabajar en español, usa:python src/ev_as.py --language spanish
Para gestionar múltiples líneas, se pueden utilizar secuencias de escape en el texto:
Secuencias disponibles
\n: Salto de línea\r: Salto de página\f: Desplazamiento de página
Herramienta recomendada
Una herramienta esencial para escribir diálogos es BDSP Message Previewer: https://github.com/ProfBlack/BDSP-Message-Previewer/releases
Con esta herramienta puedes:
- Ver exactamente los límites de cada línea
- Elegir las secuencias de escape correctas
- Copiar el texto formateado para usar en comandos de macro
Ejemplo práctico
_MACRO_TALKMSG('dp_scenario1', 'msg_c03_sergio_01', 'Psss, eh, chico.\n¿Quieres comprar Pokémon Naranja?')Este comando:
- Añade un nuevo diálogo al archivo
'dp_scenario1' - Con el identificador
'msg_c03_sergio_01' - El diálogo quedará separado en dos líneas
Convenciones de nomenclatura
Qué archivo elegir
Los diálogos pueden añadirse a cualquier archivo, pero para mantener organización:
- Usa el mismo archivo que se use en el script en el que estás trabajando
- Si por ejemplo, otros
_TALKMSGusandp_scenario1, úsalo para tus diálogos - Si usan
dp_scenario2, usa ese en su lugar, etc.
Reglas para identificadores
Para elegir un nuevo identificador, sigue estas reglas:
- Empieza todos los identificadores por
msg_ - Después, el identificador del mapa donde estás editando el script
- A continuación, el nombre de la función en la que estás trabajando
- Por último, un número que indica el orden del diálogo:
_01,_02, etc.
Estructura de un diálogoNota: Aunque muchos diálogos del juego empiezan por un número seguido de guión, no es necesario seguir esa convención.
Todas las funciones que utilizan diálogos suelen seguir la misma estructura:
1. Comandos de inicio
Comienzan por uno de estos comandos:
_TALK_OBJ_START(): El jugador y el PlaceData se miran mutuamente_TALK_OBJ_START_LOOK_NONE(): Ni el jugador ni el PlaceData cambian dirección_TALK_OBJ_START_TURN_NOT(): Solo el PlaceData mira al jugador
2. Comandos de diálogo
- Usa comandos como
_TALKMSG, macros o sus variantes - Todos los comandos de diálogo necesitan cerrarse con
_TALK_CLOSE() - Si no se cierran, la caja de texto quedará abierta incluso al pulsar A
- Añade tantos comandos de diálogo como quieras
3. Comando de finalización
- Siempre que hayas iniciado con
_TALK_OBJ_STARTo variantes - Debes acabar con
_TALK_OBJ_END() - Este comando se suele colocar como penúltimo comando, justo antes de
_ENDo_RET
Otros comandos de macro útiles
Opciones múltiples
_MACRO_ADD_CUSTUM_WIN_LABEL('archivo', 'identificador', 'texto', número)- Versión macro de
_ADD_CUSTUM_WIN_LABEL - Añade opciones a un cuadro de opciones (típico "Sí/No")
- Generalmente usa el archivo
dp_options - Tras añadir las opciones que desees, usa
_OPEN_CUSTUM_WIN(@SCWK_ANSWER)para abrir el cuadro - El número elegido se guarda en
@SCWK_ANSWER - Usa comandos de control de flujo como
_IFVALpara actuar según la elección
Diálogos simples
_MACRO_EASY_OBJ_MSG('archivo', 'id', 'texto')- Versión macro de
_EASY_OBJ_MSG - Para funciones con un único comando de diálogo
- Normalmente usado en funciones llamadas desde el TalkLabel de un PlaceData
- Agrupa
_TALK_OBJ_STARTy_TALK_OBJ_ENDen uno - Solo necesitas usar
_EASY_OBJ_MSGy_END
Tags para diálogos dinámicosNota importante: Al extraer scripts con ev-parse, no verás comandos de macro, ya que ev-as los transforma en su contraparte tradicional. Por eso puede ser difícil buscar ejemplos en VSCode.
Los comandos de macro permiten utilizar variables llamadas "tags" que reciben información del script y la reflejan en el diálogo.
¿Qué permiten los tags?
- Mostrar el nombre del jugador
- Mostrar el nombre del rival
- Mostrar nombres de Pokémon
- Y otras variables dinámicas
- Usa
_PLAYER_NAME(número)o_RIVAL_NAME(número)antes del diálogo - Asigna un número (0, 1, 2, etc.)
- En el comando de macro, escribe
{número}donde quieras el nombre
Ejemplo práctico
Código:
_RIVAL_NAME(0)
_MACRO_TALKMSG('dp_scenario1', 'msg_c03_rival_01', 'El nombre del rival es: {0}')
{0} será sustituido por el nombre del rival.Estado de desarrollo: Este es un tema algo complejo, y ev-as aún necesita ser actualizado para simplificar el proceso de añadir tags. La funcionalidad actual es básica, y a veces es necesario realizar cambios manualmente en los archivos de idioma.
Última edición: