PARTE 2: EDITANDO EL MODULE SYSTEM
Como hemos mencionado en el capitulo anterior, trabajaremos con el MS de la siguiente forma:
Editamos uno o más archivos del mod (aquellos que empiezan por module_ y terminan por .py), haciendo los cambios que queramos.
Después de eso, ejecutamos build_module.bat . Esto generará los archivos *.txt de nuestro mod. En caso de que haya errores, aparecerán en la consola.
Si no hay errores, podrás ejecutar tu mod y comprobar los cambios que has realizado. La mayoría de las veces necesitarás comenzar una partida nueva para que los cambios tengan efecto.
2.1.- Personalizando tu mod
Antes de comenzar, vamos a personalizar un poco nuestro mod, para darle un aspecto diferente. Para ello cambiaremos la imagen del mod. Esto se puede hacer con el MS Paint, o con cualquier programa que edite archivos BMP. El archivo en cuestión se llama main.bmp, y se encuentra en la carpeta de tu mod (C:\Archivos de Programa\Mount&Blade\Modules\MiMod). Editando este archivo cambiaremos la imagen que se muestra en el launcher del juego cuando seleccionemos nuestro mod.
También podemos cambiar las imágenes DDS del juego (copiamos la carpeta C:\Archivos de Programa\Mount&Blade\Textures en C:\Archivos de Programa\Mount&Blade\MiMod\Textures). Si las cambiamos podremos ver imágenes distintas cuando juguemos con nuestro mod. El archivo bg2.dds es el fondo estándar de la mayoría de imágenes y el archivo pic_mercenary.dds es el dibujo que aparece en el menú principal del juego. No es algo muy importante, pero así ya sabes que puedes hacer tu mod totalmente distinto a los demás y que tenga imágenes totalmente distintas a las originales…
2.2.- Editando los archivos del Module System
El MS utiliza listas de Python para almacenar el conjunto de códigos del juego (Estas listas comienzan siempre con [, después se incluyen los códigos, separados por comas, y finalmente la lista termina con otro ] ). Abriendo cualquiera de los archivos del MS podrás ver estas listas.
Veamos por ejemplo el archivo module_map_icons.py:
- Código:
map_icons = [
("player",0,"player", avatar_scale, snd_footstep_grass, 0.15, 0.173, 0),
("player_horseman",0,"player_horseman", avatar_scale, snd_gallop, 0.15, 0.173, 0),
("gray_knight",0,"knight_a", avatar_scale, snd_gallop, 0.15, 0.173, 0),
("vaegir_knight",0,"knight_b", avatar_scale, snd_gallop, 0.15, 0.173, 0),
("flagbearer_a",0,"flagbearer_a", avatar_scale, snd_gallop, 0.15, 0.173, 0),
("flagbearer_b",0,"flagbearer_b", avatar_scale, snd_gallop, 0.15, 0.173, 0),
("peasant",0,"peasant_a", avatar_scale,snd_footstep_grass, 0.15, 0.173, 0),
("khergit",0,"khergit_horseman", avatar_scale,snd_gallop, 0.15, 0.173, 0),
#### El archivo continua, pero no copiaremos más.
Aquí vemos como map_icons está declarado como una lista Python, y que cada elemento de esta lista hace referencia a un icono especifico del mapa. En este ejemplo, (“player”,0,”player”,avatar_scale, snd_footstep_grass, 0.15, 0.173, 0), es un objeto. A estos objetos los llamaremos “tuples”. Estos contienen, al igual que las listas, elementos separados por comas (aunque estos empiezan y terminan con paréntesis). La estructura de cada “tuple” esta explicada al comienzo del archivo. Para map_icons, cada “tuple” contiene lo siguiente:
1. Id del icono. Se utiliza para llamarlo desde otros archivos. El prefijo icon_ se añade automáticamente antes de cada id.
2. Flags del icono. Las flags disponibles se encuentran en header_map_icons.py
3. Nombre del mesh utilizado (las meshes se encuentran en la carpeta resources del mod, en formato *.brf
4. Escala.
5. Id del sonido asociado al icono.
6. Posición en el eje x de la bandera.
7. Posición en el eje y de la bandera.
8. Posición en el eje z de la bandera.
Para el primer “tuple”:
- Código:
("player",0,"player",avatar_scale, snd_footstep_grass, 0.15, 0.173, 0),
1. Id del icono = “player”
2. Flags del icono = 0
3. Nombre del mesh utilizado = “player”
4. Escala = 0.2
5. Id del sonido asociado al icono = snd_footstep_grass
6. Posición en el eje x de la bandera = 0.15
7. Posición en el eje y de la bandera = 0.173
8. Posición en el eje z de la bandera = 0
Podemos aprender cómo está construida cada “tuple” del MS viendo únicamente las explicaciones del principio del archivo, y haciéndolas coincidir con cada elemento de las listas.
2.3.- Editando los archivos del Module System
Conociendo la estructura de los “tuples”, podemos empezar añadiendo nuestro propio icono para el mapa. Echemos otro vistazo a la lista
- Código:
map_icons = [
("player",0,"player", avatar_scale, snd_footstep_grass, 0.15, 0.173, 0),
("player_horseman",0,"player_horseman", avatar_scale, snd_gallop, 0.15, 0.173, 0),
("gray_knight",0,"knight_a", avatar_scale, snd_gallop, 0.15, 0.173, 0),
("vaegir_knight",0,"knight_b", avatar_scale, snd_gallop, 0.15, 0.173, 0),
("flagbearer_a",0,"flagbearer_a", avatar_scale, snd_gallop, 0.15, 0.173, 0),
("flagbearer_b",0,"flagbearer_b", avatar_scale, snd_gallop, 0.15, 0.173, 0),
("peasant",0,"peasant_a", avatar_scale,snd_footstep_grass, 0.15, 0.173, 0),
...
("banner_125",0,"map_flag_f20", banner_scale,0),
("banner_126",0,"map_flag_15", banner_scale,0),
]
Cualquier nuevo objeto debe ser añadido dentro de la lista. Como podemos ver, esta lista termina justo debajo de
- Código:
("banner_126",0,"map_flag_15", banner_scale,0),
]
A fin de hacer un hueco para nuestro icono, moveremos nuestro corchete una línea hacia abajo. Una vez hecho esto, podemos comenzar a añadir un nuevo objeto. La manera más fácil de hacer esto es copiando y pegando un objeto ya existente y después editar su contenido. Por ejemplo, copiaremos “town” justo debajo de “banner_126”:
- Código:
("banner_126",0,"map_flag_15", banner_scale,0),
("town",mcn_no_shadow,"map_town_a", 0.35,0),
]
En este ejemplo, hemos copiado ("town",mcn_no_shadow,"map_town_a", 0.35,0).
Ahora demos un nuevo nombre al icono; “new_icon”. Este icono tiene una flag. Estas flags son características que pueden ser activadas y desactivadas incluyéndolas o quitándolas en los lugares adecuados. Por ejemplo, mcn_no_shadow significa que nuestro icono no proyectará ninguna sombra en el suelo.
Quitamos esa flag de nuestro icono. Para ello la sustituimos por un 0, lo que el MS interpretará como que no hay flags asignadas a este icono.
- Código:
("banner_126",0,"map_flag_15", banner_scale,0),
("new_icon",0,"map_town_a", 0.35,0),
]
Tanto el objeto “town” como “new_icon” utilizan la mesh “map_town_a”, lo que significa que utilizan el modelo denominado map_town_a (recogido en un archivo brf en la carpeta resources del mod). Cambiando este campo, el icono puede ser cualquier elemento 3d de la carpeta de resources. Por eso, aunque los iconos se llamen de forma distinta, al aparecer nuestro “new_icon” en el juego, tendrá la misma apariencia que “town”.
Démosle entonces un aspecto distinto a nuestro nuevo icono. Para ello cambiemos “map_town_a” por “city”. Esta mesh no se utiliza en el native, por lo que nuestro icono tendrá una mejor presencia en nuestro mod.
- Código:
("banner_126",0,"map_flag_15", banner_scale,0),
("new_icon",0,"city", 2,0),
]
En este ejemplo, también hemos cambiado la escala del icono, de 0.35 a 2. Eso significa que aparecerá dos veces más grande de lo normal. Esto nos ayudara a seleccionarla cuando la introduzcamos en el juego.
Lo siguiente que haremos será crear un nuevo grupo en module_parties.py que utilice nuestro recién creado icono.
Para hacer esto, tendremos que referenciar el icono desde el archivo module_parties.py.
Antes de continuar, ejecutaremos build_module.bat. Esto nos permitirá saber si la sintaxis es correcta. Es un buen hábito compilar de vez en cuando el MS para evitar que haya errores que luego sean más difíciles de encontrar.
2.4.- Referenciando objetos del juego
Abrimos el archivo module_parties.py de la carpeta del MS. Como en el caso anterior, vemos que también está formado por una lista Python: parties = [ Justo después, se encuentra la declaración de una constante:
(pf_town = pf_is_static|pf_always_visible|pf_show_faction|pf_label_large).
Como podemos ver, la estructura de los “tuples” de module_parties.py es ligeramente diferente a la de module_icons.
Lo primero de todo es que nos quede claro que “parties” engloba a cualquier elemento con el que nos podamos encontrar en un mapa, pueden ser ejércitos o pueblos, ciudades u otras localizaciones que hayamos diseñado. Una de las características de las “parties” es que cuando dos o más de ellas se encuentran se ejecuta un desencadenante (“trigger”).
Veamos un ejemplo de una de estas “parties”:
- Código:
("town_1","Sargoth",icon_town|pf_town,no_menu,pt_none,fac_neutral,0, ai_bhvr_hold,0,(-1.55,66.45),[],170)
Este “tuple” se encarga de localizar la ciudad de Sargoth en el mapa. Todas sus cualidades se encuentran en los campos apropiados del “tuple” (de forma similar a los campos que hemos visto en module_map_icons.py).
Analizándolo a fondo:
1) Id de la party. Se utiliza para referenciarla desde otros archivos
2) Nombre de la party. Esto será el texto que se muestra en el juego. No tiene por qué ser igual que el Id.
3) Flags. La primera flag deberá ser siempre el icono que se utilizará para representarla en el mapa.
4) Menú. Esto no se utiliza en el juego desde la versión v.0.730, por lo que siempre será “no_menu”
5) Party-template. Id de la party template a la que pertenece este objeto. Por defecto utilizaremos pt_none.
6) Facción. Esta puede ser cualquiera de las entradas del archivo module_factions.py
7) Personalidad. Ver en header_parties.py una explicación de este elemento.
8 ) Comportamiento de la IA. Cómo actuará esta party en el mapa.
9) IA-target party. (no estoy seguro de que es)
10) Coordenadas Iniciales. Las coordenadas XY en las que comienza este objeto en el mapa.
11) Lista de tropas acantonadas. Esta lista se divide en tres campos:
11.1) Id de la tropa. Puede ser tanto un héroe como cualquier otro soldado de module_troops.py.
11.2) Numero de tropas acantonadas. Este no varía, el número que pongamos será el número de tropas que tendrá la ciudad.
11.3) Flags. Opcional, podemos usar pmf_is_prisioner para hacer que ese miembro es un prisionero.
12) Orientación de la “party”. Es opcional.
Analizamos ahora la ciudad de Sargoth:
- Código:
("town_1","Sargoth",icon_town|pf_town,no_menu,pt_none,fac_neutral,0, ai_bhvr_hold,0,(-1.55,66.45),[],170)
1) Id de la party. “town_1”
2) Nombre de la party. “Sargoth”
3) Flags. icon_town|pf_town
4) Menú. no_menu
5) Party-template. pt_none
6) Facción. fac_neutral
7) Personalidad. 0
8 ) Comportamiento de la IA. ai_bhvr_hold
9) IA-target party. 0
10) Coordenadas Iniciales. (-1.55,66.45)
11) Lista de tropas acantonadas. [] (none)
12) Orientación de la “party”. 170
Observando el campo 3, podemos ver que Sargoth referencia el icono “town” desde module_icons.py añadiéndole el prefijo icon_. Este prefijo indica al sistema donde tiene que buscar dicha referencia. Para referenciar el archivo module_icons, utilizamos el prefijo icon_, para module_factions, utilizamos fac_, para module_parties, p_... Hay un prefijo para cada archivo del MS (encontrarás la lista al final de este capítulo).
Ahora que sabemos cómo se estructuran las parties, vamos a añadir una nueva hecha por nosotros. Pero antes de hacerlo, debes tener en cuenta un aspecto importante de module_parties.py (y de ciertos archivos más). No debes añadir nuevas ciudades al final de la lista. Normalmente suele haber notas en esos archivos que indican esta peculiaridad, porque si no se modifican correctamente pueden aparecer errores. En module_parties.py, es recomendable que cualquier ciudad que añadas la incluyas entre “town_1” y “castle_1”. Esto está definido en module_constants.py.
Copiamos la entrada "town_1" y la pegamos justo despues de "town_18", pero antes de "castle_1"
- Código:
("town_18","Narra", icon_town_steppe|pf_town, no_menu, pt_none, fac_neutral,0,ai_bhvr_hold,0,(-22.6, -82),[], 135),
## Nueva ciudad
("town_1","Sargoth", icon_town|pf_town, no_menu, pt_none, fac_neutral,0,ai_bhvr_hold,0,(-1.55, 66.45),[], 170),
## Fin Nueva ciudad
# Aztaq_Castle
# Malabadi_Castle
("castle_1","Culmarr_Castle",icon_castle_a|pf_castle, no_menu, pt_none, fac_neutral,0,ai_bhvr_hold,0,(-69.2, 31.3),[],50),
Aprovecho para explicar las anotaciones antes del tuple de "town_1". Estas anotaciones, precedidas del símbolo # permiten encontrar más fácilmente las lineas con las que estamos trabajando, haciendo más fácil la búsqueda. También sirven para explicar lo que hemos hecho, permitiendo a otros modders entender los pasos que hemos llevado a cabo.
Lo que hace el símbolo # es evitar que el MS lea más allá en la linea en la que se encuentra: todo el texto que se encuentre a su derecha no será compilado, por lo que es muy útil para llevar a cabo lo que he dicho anteriormente.
En este ejemplo, cambiaremos "town_1" por "mod_town" y "Sargoth" por "Mod_Town".
Analizamos la nueva ciudad:
1) La nueva ciudad aparecerá en el juego con el nombre de Mod Town.
2) La ciudad utiliza el icono "town", referenciado en el "tuple" como "icon_town", y tiene asignado el flag pf_town, que le otorga las mismas caracteristicas que otras ciudades del juego.
3) Esta ciudad no pertenece a ninguna faccion (Neutral).
4) Si no cambiamos nada, la ciudad aparecerá en la misma posicion que Sargoth, para ello cambiaremos sus coordenadas y algun aspecto más:
- Código:
## Nueva ciudad
("mod_town","Mod_Town", icon_new_icon|pf_town, no_menu, pt_none, fac_neutral,0,ai_bhvr_hold,0,(-1, -1),[], 45),
## Fin Nueva ciudad
Hemos cambiado su posición a las coordenadas [-1,-1], ademas de haberla dado una nueva orientación (45 grados). Además, al cambiar "icon_town" por "icon_new_icon", "Mod Town" tendrá una nueva apariencia.
Guardamos los cambios y compilamos el MS (doble click en build_module.bat). Si hemos hecho todo bien, podremos iniciar nuestro mod y encontraremos la ciudad que hemos creado en el medio del mapa. Hacemos click sobre ella para entrar en la ciudad.
Si no hemos seguido correctamente los pasos, aparecerán errores al compilar. Revisamos de nuevo todos los cambios, y nos aseguramos de que hemos colocado todos los paréntesis y corchetes en el lugar correcto. Estos fallos, las comas mal situadas y algunos errores al escribir los tuples son los fallos más comunes que ocurren cuando trabajamos con el MS, por eso debemos revisar siempre nuestro trabajo.
Cuando entramos en la ciudad vemos que aparece el menú de ciudad, que nos indica que podemos ir a la taberna, al castillo... pero sin embargo, si intentamos cualquiera de esas acciones, apareceremos en lugares que nada tienen que ver con lo que esperábamos. Esto se debe a que no hemos definido completamente todos los aspectos de la ciudad, sino que únicamente la hemos colocado en el mapa. Esta tarea la realizaremos mas tarde, cuando creemos una taberna para una quest. Todo a su debido tiempo.
Como hemos visto, todos los archivos están interrelacionados entre si. Muchos cambios no afectan solamente al archivo que modificamos, si no que cambian aspectos de otros archivos del modulo. Por suerte, la mayoría de los cambios que llevemos a cabo se realizarán modificando 2 o tres archivos como mucho.
Ahora que ya hemos visto por encima como funciona el MS, podremos analizar mas profundamente los demás archivos. Por ello es importante que aprendamos los prefijos necesarios para referenciar los objetos de un archivo desde otro archivo. Estos prefijos están recogidos en los textos de la cabecera de los module_xxx.py.
Lista de Prefijos:
- fac_ module_factions.py
- icon_ module_icons.py
- itm_ module_items.py
- mnu_ module_game_menus.py
- mt_ module_mission_templates.py
- psys_ module_particle_systems.py
- p_ module_parties.py
- pt_ module_party_templates.py
- qst_ module_quests.py
- script_ module_scripts.py
- scn_ module_scenes.py
- spr_ module_scene_props.py
- str_ module_strings.py
- trp_ module_troops.py
- skl_ module_skills.py
Nunca se hacen referencias a module_dialogs.py, por lo que no tiene prefijo propio.
Última edición por Mikeboix el Miér Nov 28, 2012 3:14 pm, editado 1 vez