Patch
Una patch cambia una parte di un file del gioco senza sostituirlo per intero. Due mod possono patchare lo stesso file e le due modifiche si sommano. Se ognuna portasse la sua copia del file, la seconda sovrascriverebbe la prima.
Vanno bene file XML (comandi, oggetti, bonus, definizioni di unità), INI (costanti, interfaccia) e script .vs (IA, comportamenti). Il file deve esistere nel gioco. Esempio da copiare: esempi/esempio-patch.
Dove va
Nella tua mod, dentro patches, con lo stesso percorso che ha il file nel gioco:
mods\mi-mod\
mod.json
patches\data\commands\RBarracks.xml parchea data\commands\RBarracks.xml
patches\data\const.ini parchea data\const.ini
- Ogni volta che il gioco apre quel file, gli vengono applicate le patch delle mod attive. Gli originali non si toccano mai.
- Con più mod, si applicano dall'ultima alla prima dell'ordine di caricamento: la prima ha l'ultima parola. Quell'ordine lo calcola il gioco ed è lo stesso su tutti i computer con le stesse mod; il controllo del multiplayer non dipende da esso.
- Se la tua mod porta anche una sua copia del file (senza
patches), le patch delle altre mod si applicano su quella. - Per provare una patch senza creare una mod, mettila in
<gioco>\mod\patches\<percorso>. Si applica per ultima, sopra tutte. - Una patch cambia il gameplay se il file lo cambia (
data\..., mappe, unità). Allora tutti i giocatori devono avere la stessa mod. - Le patch si leggono quando il gioco apre ogni file. Se ne cambi una, riavvia il gioco.
Vedere come risulta un file
Aggiungi questo a imperivm-mod.ini e apri il gioco:
[Debug]
Dump=data/commands/RBarracks.xml,data/const.ini
Ogni file viene copiato in mod-dump\<percorso> così come lo legge il gioco, con le patch già applicate. Per vedere l'originale, usa il profilo Originale. Scrivi il nome esatto di ogni file, separati da virgole; la riga intera non può superare i 1.023 caratteri. Un * da solo scarica tutti i file che il gioco apre: ne escono migliaia, usalo con cautela.
Patch XML
Un <patch> con operazioni che si applicano in ordine:
<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 aggiunge quegli attributi negli elementi scelti.unset="a b"toglie attributi.<add select="…">…</add>: aggiunge ciò che contiene in fondo all'elemento scelto. Conposition="start"lo mette all'inizio; con"before"o"after", accanto all'elemento scelto invece che dentro.<remove select="…"/>: toglie gli elementi scelti.<replace select="…">…</replace>: sostituisce gli elementi scelti con ciò che contiene.
Se ciò che cerchi potrebbe non esistere e non vuoi un errore, metti optional="yes" nell'operazione.
Il selettore
Un percorso come quelli delle cartelle, con condizioni tra parentesi quadre. Scrivilo sempre iniziando con / o //: altrimenti il validatore dà errore.
| Selettore | Sceglie |
|---|---|
/commands |
il <commands> radice |
/commands/cmd |
tutti i <cmd> dentro <commands> |
/commands/cmd[@name='trainRHastatus'] |
il <cmd> con quel name |
//cmd[@name='trainRHastatus'] |
quel <cmd>, ovunque sia |
/commands/cmd[@key] |
i <cmd> che hanno l'attributo key |
/commands/cmd[3] |
il terzo <cmd> |
/commands/cmd[@name='x']/src |
i <src> di quel <cmd> |
//*[@name='x'] |
qualsiasi elemento con name="x" |
Esistono solo queste condizioni: [@a='v'], [@a] e [n]. Puoi metterne più di seguito ([@a='v'][2]). Non ci sono and, contains, text() né ... Le maiuscole non contano, e i valori vanno tra apici singoli o doppi.
Regole
- La patch deve essere XML ben formato. Nei valori,
&si scrive&e<si scrive<. Se è malformata non si applica per intero, e l'errore compare nel log e nella scheda della mod. - Un'operazione che fallisce (un selettore che non trova nulla) viene saltata e segnalata. Le altre si applicano.
- La patch non cambia la codifica: usa quella del file del gioco (quasi sempre ASCII).
- Il risultato perde il rientro degli attributi (finiscono su una riga). Il contenuto è lo stesso.
- Se togli o rinomini qualcosa che usano altri file, si rompe. Le IA del gioco richiamano i comandi per nome (
trainRScout): togli il comando e l'IA fallirà.
Patch INI
Un INI con le sezioni e le chiavi che vuoi cambiare:
; Cambia costanti di gameplay
[GamePlay]
DamageAmplify = 250
-TeachingLevel2
; Negli elenchi di nomi singoli (senza =), + aggiunge una riga se non c'è
[GameOptions Objects]
+MiBotonNuevo
-RSText
Clave = valorcambia o aggiunge la chiave in quella sezione.-Clavetoglie la chiave (o la riga che è esattamente quel testo).+Lineaaggiunge una riga singola alla sezione se non c'è già.- Se la sezione non esiste, viene creata in fondo al file.
- Togliere una chiave che non esiste dà errore nel log.
- I commenti a fine riga del file originale (
Clave = 20 ;comentario) si perdono nella riga che cambi.
Non mettere commenti dopo una riga della patch. Il motore non li toglie: -Clave ; texto cerca una chiave con quel nome e fallisce, [Seccion] ; texto non viene riconosciuta come sezione e Clave = 250 ; texto salva il commento dentro il valore. I commenti vanno su righe a parte che iniziano con ;. Il validatore non lo segnala.
Patch di script
La patch di un .vs (per esempio patches\data\ai\GetTacticScript.vs) è un testo con direttive che iniziano con @ in prima colonna. Il codice che scrivi sotto ognuna viene aggiunto allo script del gioco:
@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 non è una costante del gioco: esiste se c'è una civiltà attiva con quel nome (l'id del suo civs\<id>.json). Vedi Civiltà.
| Direttiva | Dove mette il codice |
|---|---|
@top |
Subito dopo la prima riga dello script (quella della firma). Vale solo per dichiarare variabili o commenti. |
@bottom |
In fondo allo script. |
@before TEXTO |
Prima della prima riga dello script che contiene TEXTO. |
@after TEXTO |
Dopo quella riga. |
@replace TEXTO |
Al posto di quella riga. |
@end |
Chiude il blocco precedente. È opzionale: ciò che segue fino alla direttiva successiva viene ignorato. |
TEXTOè un pezzo di una riga dello script, così com'è scritta (non un'espressione regolare). Si aggancia alla prima riga che lo contiene, quindi scegli un testo che compaia una volta sola: altrimenti il tuo codice finisce dove non ti aspettavi. Se nessuna riga lo contiene, l'errore compare nel log e la direttiva viene saltata.- Negli script le variabili si dichiarano tutte all'inizio e il codice viene dopo. Un
ifo unreturncon@topfinisce prima delle dichiarazioni e non compila (Unexpected starting token). Metti il codice con@beforee la prima riga di codice dello script. - Le patch di più mod si sommano, quindi due mod possono cambiare lo stesso script (per esempio, due civiltà che scelgono la loro tattica in
GetTacticScript.vs). - Lo script risultante deve compilare. Altrimenti l'errore compare in
Logs\imperivm\imperivm-mod.logcomescript: compilation error. - Il validatore non controlla il codice di queste patch, né le funzioni
Mod_*né la firma.
Se qualcosa non va
Cerca in Logs\imperivm\imperivm-mod.log le righe con l'etichetta patch: dicono quale file è stato patchato e quale operazione è fallita. Gli errori compaiono anche nella scheda della mod. Quelli di compilazione di una patch di script compaiono come script: compilation error.