Parches
Un parche cambia una parte de un archivo del juego sin sustituirlo entero. Dos mods pueden parchear el mismo archivo y los dos cambios se suman. Si cada uno trajera su copia del archivo, el segundo pisaría al primero.
Valen archivos XML (órdenes, objetos, bonos, definiciones de unidades), INI (constantes, interfaz) y scripts .vs (IA, comportamientos). El archivo tiene que existir en el juego. Ejemplo para copiar: ejemplos/parches-ejemplo.
Dónde va
En tu mod, dentro de patches, con la misma ruta que tiene el archivo en el juego:
mods\mi-mod\
mod.json
patches\data\commands\RBarracks.xml parchea data\commands\RBarracks.xml
patches\data\const.ini parchea data\const.ini
- Cada vez que el juego abre ese archivo, se le aplican los parches de los mods activos. Los originales no se tocan nunca.
- Con varios mods, se aplican del último al primero del orden de carga: el primero tiene la última palabra. Ese orden lo calcula el juego y es el mismo en todos los ordenadores con los mismos mods; la comprobación de multijugador no depende de él.
- Si tu mod trae además su propia copia del archivo (sin
patches), los parches de los demás mods se aplican sobre ella. - Para probar un parche sin crear un mod, ponlo en
<juego>\mod\patches\<ruta>. Se aplica el último, por encima de todos. - Un parche cambia la jugabilidad si el archivo la cambia (
data\..., mapas, unidades). Entonces todos los jugadores tienen que llevar el mismo mod. - Los parches se leen cuando el juego abre cada archivo. Si cambias uno, reinicia el juego.
Ver cómo queda un archivo
Añade esto a imperivm-mod.ini y abre el juego:
[Debug]
Dump=data/commands/RBarracks.xml,data/const.ini
Cada archivo se copia a mod-dump\<ruta> tal como lo lee el juego, con los parches ya aplicados. Para ver el original, usa el perfil Original. Da el nombre exacto de cada archivo, separados por comas, y la línea entera no puede pasar de 1.023 caracteres. Un * solo vuelca todos los archivos que abre el juego: salen miles, úsalo con cuidado.
Parches XML
Un <patch> con operaciones que se aplican en orden:
<patch>
<set select="/commands/cmd[@name='trainRHastatus']" costgold="60" execdelay="3000" unset="costpop"/>
<add select="/commands"><cmd name="miOrden" method="train" .../></add>
<remove select="//cmd[@name='otraOrden']"/>
<replace select="/commands/cmd[@name='trainRArcher']/src"><src obj="RBarracks"/></replace>
</patch>
<set select="…" atributo="valor" …/>: cambia o añade esos atributos en los elementos elegidos.unset="a b"quita atributos.<add select="…">…</add>: añade lo de dentro al final del elemento elegido. Conposition="start"lo pone al principio; con"before"o"after", junto al elemento elegido en vez de dentro.<remove select="…"/>: quita los elementos elegidos.<replace select="…">…</replace>: cambia los elementos elegidos por lo de dentro.
Si lo que buscas puede no existir y no quieres error, pon optional="yes" en la operación.
El selector
Una ruta como las de las carpetas, con condiciones entre corchetes. Escríbela siempre empezando por / o //: el validador da error si no.
| Selector | Elige |
|---|---|
/commands |
el <commands> raíz |
/commands/cmd |
todos los <cmd> dentro de <commands> |
/commands/cmd[@name='trainRHastatus'] |
el <cmd> con ese name |
//cmd[@name='trainRHastatus'] |
ese <cmd>, esté donde esté |
/commands/cmd[@key] |
los <cmd> que tienen atributo key |
/commands/cmd[3] |
el tercer <cmd> |
/commands/cmd[@name='x']/src |
los <src> de ese <cmd> |
//*[@name='x'] |
cualquier elemento con name="x" |
Solo existen estas condiciones: [@a='v'], [@a] y [n]. Puedes poner varias seguidas ([@a='v'][2]). No hay and, contains, text() ni ... Las mayúsculas no cuentan, y los valores van entre comillas simples o dobles.
Reglas
- El parche tiene que ser XML bien formado. En los valores,
&se escribe&y<se escribe<. Si está mal formado no se aplica entero, y el error sale en el registro y en la ficha del mod. - Una operación que falla (un selector que no encuentra nada) se salta y se avisa. Las demás se aplican.
- El parche no cambia la codificación: usa la del archivo del juego (casi siempre ASCII).
- El resultado pierde el sangrado de los atributos (quedan en una línea). El contenido es el mismo.
- Si quitas o renombras algo que usan otros archivos, se rompe. Las IA del juego llaman a las órdenes por su nombre (
trainRScout): quita la orden y la IA fallará.
Parches INI
Un INI con las secciones y claves que quieres cambiar:
; Cambia constantes de jugabilidad
[GamePlay]
DamageAmplify = 250
-TeachingLevel2
; En las listas de nombres sueltos (sin =), + añade una línea si no está
[GameOptions Objects]
+MiBotonNuevo
-RSText
Clave = valorcambia o añade la clave en esa sección.-Clavequita la clave (o la línea que sea exactamente ese texto).+Lineaañade una línea suelta a la sección si no está ya.- Si la sección no existe, se crea al final del archivo.
- Quitar una clave que no existe da error en el registro.
- Los comentarios del final de línea del archivo original (
Clave = 20 ;comentario) se pierden en la línea que cambias.
No pongas comentarios después de una línea del parche. El motor no los quita: -Clave ; texto busca una clave llamada así y falla, [Seccion] ; texto no se reconoce como sección y Clave = 250 ; texto guarda el comentario dentro del valor. Los comentarios van en líneas aparte que empiecen por ;. El validador no avisa de esto.
Parches de scripts
Un parche de un .vs (por ejemplo patches\data\ai\GetTacticScript.vs) es un texto con directivas que empiezan por @ en la primera columna. El código que escribes debajo de cada una se añade al script del juego:
@before nRace = set.GetCentralBuilding.race;
// MOD: mi civilización
if (Mod_TrueRace(set.GetCentralBuilding) == Dacia)
return TS_GaulTactic2;
@after player = set.player;
Mod_Log("GetTacticScript: eligiendo táctica");
Dacia no es una constante del juego: existe si hay una civilización activa con ese nombre (la id de su civs\<id>.json). Ver Civilizaciones.
| Directiva | Dónde pone el código |
|---|---|
@top |
Justo después de la primera línea del script (la de la firma). Solo vale para declarar variables o comentarios. |
@bottom |
Al final del script. |
@before TEXTO |
Antes de la primera línea del script que contiene TEXTO. |
@after TEXTO |
Después de esa línea. |
@replace TEXTO |
En lugar de esa línea. |
@end |
Cierra el bloque anterior. Es opcional: lo que siga hasta la próxima directiva se ignora. |
TEXTOes un trozo de una línea del script, tal cual está escrito (no una expresión regular). Se ancla a la primera línea que lo contiene, así que elige un texto que aparezca una sola vez: si no, tu código acaba en un sitio que no esperabas. Si ninguna línea lo contiene, el error sale en el registro y la directiva se salta.- En los scripts, las variables se declaran todas al principio y el código va después. Un
ifo unreturncon@topqueda antes de las declaraciones y no compila (Unexpected starting token). Pon el código con@beforey la primera línea de código del script. - Los parches de varios mods se suman, así que dos mods pueden cambiar el mismo script (por ejemplo, dos civilizaciones que eligen su táctica en
GetTacticScript.vs). - El script resultante tiene que compilar. Si no, el error sale en
Logs\imperivm\imperivm-mod.logcomoscript: compilation error. - El validador no revisa el código de estos parches, ni las funciones
Mod_*ni la firma.
Si algo no sale
Busca en Logs\imperivm\imperivm-mod.log las líneas con la etiqueta patch: dicen qué archivo se ha parcheado y qué operación falló. Los errores salen también en la ficha del mod. Los de compilación de un parche de script salen como script: compilation error.