Insidie comuni nel modding e nell'analisi dei file
Un promemoria di una sola pagina con le insidie in cui si cade più spesso, sparse nei documenti sui formati di kbot. Se ti trovi davanti a un bug che non ha alcun senso, comincia da qui. Ogni voce rimanda alla spiegazione approfondita nella pagina del formato corrispondente.
Tip
Cerchi "la mia mod non si carica"? La regola del punto e virgola dei TDF (#tdf--fbi--ota, prima voce) è all'origine di più segnalazioni di "rotture silenziose" di tutte le altre insidie messe insieme.
HPI / UFO / CCX / GP3
- I file sciolti nella radice dell'installazione hanno la precedenza su
qualsiasi archivio. Metti
units/MYUNIT.fbisu disco e il motore lo preferirà a qualunque cosa ci sia intotala1.hpi. Il diagramma della stratificazione in hpi.md mostra l'intera pila delle priorità. - Tra gli archivi vince il primo montato, e si montano solo dieci
*.hpi. TA 3.1c montarev31.gp3, poi*.ccx,*.ufoe i primi dieci*.hpiche riesce ad aprire, ogni gruppo in ordine di nome ASCII maiuscolo. Una mod distribuita comezz_mod.hpiviene dopo ogni archivio originale e, in un'installazione che ha già dieci*.hpiche la precedono nell'ordinamento, si monta solo tramite la scansione del CD, sotto tutto il resto. Distribuisci le mod come.ufo. - I puntatori di HPI v1 sono assoluti rispetto all'inizio del file, non
all'inizio della directory. Non sottrarre niente. Il trucco del parser
canonico è allocare un buffer di
DirectorySizebyte e decifrarci dentro la directory all'offsetStart, così i puntatori indicizzano direttamente il buffer. Vedi Albero delle directory. - Il seme della cifratura di HPI v1 avanza con la posizione nel file. Non puoi decifrare un buffer preso da solo: devi sapere da quale offset assoluto del file proviene. Vedi Ricavare la chiave di cifratura.
- Se
DecryptKey == 0, non applicare affatto la cifratura XOR. Alcuni archivi personalizzati sono distribuiti in chiaro; applicare comunque la cifratura rimescola ciò che era già leggibile. - Il checksum dei chunk SQSH è calcolato sui byte cifrati. Verificalo prima di decifrare. Vedi Chunk compressi (SQSH).
- TA: Kingdoms usa HPI v2 (
Version == 0x00020000) con una struttura diversa: niente XOR, un solo chunk SQSH per file. Leggi la sezione HPI v2 di TA: Kingdoms prima di provare il parser v1 su un archivio di TAK. - I salvataggi con il marcatore
BANKsono un'altra cosa: riusano l'involucro HPI, ma il contenuto è lo stato di gioco serializzato, non un filesystem. kbot non li decodifica. - Un
.gp3richiede la patch rev3.1. Dentro è ancora un HPI, ma TA senza patch si rifiuta di montarlo.
TDF / FBI / OTA
- Ogni valore deve terminare con
;. I punti e virgola mancanti uniscono silenziosamente i valori di più righe e producono statistiche completamente sbagliate. È la causa n. 1 dei casi "la mia unità ha punti ferita strani / non ha descrizione / ha il costo sbagliato". - Le chiavi non distinguono tra maiuscole e minuscole, i valori sì.
Side=armfunziona per la maggior parte delle ricerche, ma rompe il codice di qualsiasi mod che confrontiSideper uguaglianza di stringhe. - I valori delle liste sono separati da spazi
(
Category=COMMANDER MOBILE WEAPON), non da virgole. L'eccezione ènumplayers=2,4,6,8,10degli OTA, che usa le virgole. - I booleani sono interi
1/0, nontrue/false. Il motore accetta solo le forme intere. - Nelle mod, non modificare mai
sidedata.tdfper aggiungere unità. Usa invece una registrazione[MENUENTRY]indownload/<UNITNAME>.tdf: lo stesso meccanismo usato da Core Contingency. Vedi TDF:[MENUENTRY]e il tutorial sul modding. Bmcode=0nasconde un'unità dal menu di costruzione anche se tutto il resto è valido. Quasi sempre vuoiBmcode=1.- Un'unità che non compare sotto alcun costruttore non si può costruire, anche se per il resto il suo FBI è valido. È il bug più comune del tipo "la mia nuova unità esiste ma non si può costruire". Vedi il passo 5 del tutorial sul modding.
- La profondità delle sezioni annidate è una convenzione, non una
specifica. Alcuni strumenti presuppongono 2 livelli; i TDF delle armi
arrivano a 3 (
[WEAPON][DAMAGE][category]).
TNT / SCT — terreno delle mappe
WidtheHeightdel TNT sono celle degli attributi da 16 px, non tile e non pixel. Dividi per 2 per il numero di tile; moltiplica per 16 per le dimensioni in pixel. Vedi l'intestazione TNT.SeaLevel == 0NON significa "niente acqua": significa che il valore più piccolo possibile sta sulla soglia, quindi niente è sott'acqua. UsaSeaLevel = 1per le mappe davvero asciutte.- Le parole degli elementi nel TNT piazzano un elemento solo se sono
inferiori al numero di voci della tabella degli elementi.
0xFFFCè una cella vuota (void);0xFFFE(Lava Run, AC02),0xFFFDe qualsiasi altra parola pari o superiore alla dimensione della tabella non piazzano nulla, e la cella resta edificabile. - Il riempimento della minimappa TNT usa l'indice della palette
0x64, e la regione della mappa è dimensionata a partire dalla mappa (lato lungo 252, proporzioni della mappa visibile), non trovata cercando il riempimento. Il gioco legge la minimappa memorizzata solo quando è impostato il bit 0 della parola dell'intestazione a0x2c. Vedi TNT. - I
.tntdi TA: Kingdoms usanoIDVersion == 0x4000invece del0x2000di TA (TA legge anche una struttura più vecchia,0x1020).kbot tnt imageproduce immagini senza senso sui TNT di TAK; il decodificatore dei tile è specifico di TA. Vedi Mappe TA:K. - Le sezioni SCT devono avere entrambe le dimensioni multiple di 4 per essere caricate in TAE. Il formato su disco ammette altre dimensioni, ma l'editor le rifiuta con "section misaligned".
- SCT V2 ha celle delle altezze da 8 byte, V3 da 4 byte. kbot accetta entrambe; le mod costruite con l'editor vedono solo V3.
3DO — modelli
- L'asse verso l'alto è Y, non Z. Importare un 3DO in un motore con Z verso l'alto (Blender, Unreal moderno) senza scambiare gli assi lascia ogni unità sdraiata su un fianco.
- Le primitive senza texture sono invisibili a meno che
IsColored != 0: lo pseudocodicevisible = (texture != "") || (IsColored != 0)copre entrambi i casi. È il bug di rendering dei 3DO più comune. OffsetToSelectionPrimha senso solo sull'oggetto radice; gli oggetti figli devono impostarlo a-1(0xFFFFFFFF).- La scala in virgola fissa è
1 / 65536. Un vertice scritto come0x00010000vale 1,0 unità del mondo; i 16 bit bassi sono la parte frazionaria. - I vertici sono locali all'oggetto, non globali. Due oggetti possono avere array di vertici identici: si tratta di geometria speculare, non di dati condivisi.
COB / BOS — script
- L'opcode di
call-scriptè0x10062000, NON0x10063000come sostengono alcuni documenti precedenti alla 3.1. I vecchi decompilatori che usano0x10063000producono risultati senza senso: vedi il riferimento degli opcode. - I numeri dei pezzi negli opcode sono indici nella tabella dei nomi dei pezzi, non stringhe. Il COB contiene i nomi come pool di stringhe; il runtime usa gli indici per ragioni di velocità.
SET_SIGNAL_MASKregistra solo un interesse: non uccide niente. È l'invio disignal Xa fermare gli script la cui maschera haXimpostato. La regola di lintsignal-never-signalledindividua gli script che impostano una maschera che nessuno segnala mai.- Lo Scriptor di Cavedog sostituisce inline
CURRENT_SPEEDcon il letterale29, rompendo gli script in stileMoveWatcherdopo un round-trip. Il decompilatore di kbot ripristina il nome simbolico; se devi per forza fare un round-trip con Scriptor, metti le parentesi:(get CURRENT_SPEED) > 5. - Gli offset dei salti sono offset in byte relativi a
OffsetToScriptCode, non all'istruzione corrente.JUMP 0x4Csignifica "salta aOffsetToScriptCode + 0x4C". - I numeri di porta di
GET_UNIT_VALUEcambiano tra TA e TA:K. Il catalogo di TA (il decompilatore di kbot etichetta le porte 1–20) è documentato nell'Appendice B.
GAF — animazioni di sprite
- Una sequenza va in loop solo quando il byte basso della sua parola +2 è impostato; con 0 viene riprodotta una volta e si ferma. Tutte le sequenze originali contengono 1, quindi uno strumento che scrive zero congela gli elementi animati.
- I frame in
textures/*.gafeanims/vismasks.gafdevono essere grezzi. Il gioco li legge come semplici array di pixel. - Alcune sequenze sono distribuite con durate dei frame pari a
0; il gioco mostra un frame del genere per un tick. Non "correggerle" con un valore predefinito. - L'indice 0 della palette non è trasparente di per sé. Lo sono solo la chiave di un frame grezzo e i run saltati di un frame compresso.
- Le righe di pixel compresse possono essere più corte di
Width. Il gioco continua a leggere i byte successivi; kbot completa la riga con pixel trasparenti e lo segnala. Nessun file originale ha righe del genere. - Le origini dei livelli sono hotspot: ogni livello di un frame composto viene posizionato in modo che la sua origine cada sull'origine del frame.
anims/terrain.gafeanims/vismasks.gafhannoVersion == 0nell'intestazione. Il gioco ignora la parola di versione.- Il
.tafdi TA: Kingdoms esiste in due varianti. Un.tafcon palette È un GAF: stesso formato su disco, salvo che TAK prende la palette da un.pcxper fazione invece che dalla palette globale di TA. Un.taftruecolor riusa lo stesso contenitore ma memorizza pixel ARGB a 16 bit e non ha bisogno di una palette. A fare fede è il byte del formato del frame (0/1= con palette,4/5= truecolor), non l'estensione: vedi TAF / TSF.
TAF / TSF — animazioni truecolor
.tafha più significati: con palette (da leggere come GAF) oppure truecolor (da leggere conkbot taf). Controlla sempre il byte del formato del frame, mai il nome del file, anche se per convenzione la maggior parte dei file truecolor di TAK porta un suffisso_4444/_1555.- L'esportazione in GIF perde informazioni. Una GIF contiene solo un
ritaglio a 1 bit e 255 colori, quindi l'alfa sfumato di ARGB4444 si
trasforma in bordi netti. Usa APNG (
kbot taf export --format apng) per conservare il vero canale alfa. - Il campo del nome del frame e il byte di flag
0x0Bpossono contenere spazzatura. Conservali tali e quali per un round-trip esatto byte per byte; non normalizzarli. - Un
Delay/Durationpari a0è valido: come nel GAF, un frame da zero tick è guidato dagli eventi (lo usano gli sfondi statici dei menu). Non "correggerlo".
PCX — immagini
- TA ignora
BytesPerLine. I lettori standard scartano il riempimento quandoBytesPerLine > Width; TA 3.1c decodifica esattamenteWidthbyte per riga, quindi nel gioco i file con riempimento risultano sfalsati. ScriviBytesPerLine == Widthe verifica conkbot pcx describe. - TA carica solo la versione 5, e decodifica ogni file come dati a 8 bit su un solo piano.
- I byte letterali con i due bit alti impostati vanno codificati come
run RLE. Un byte isolato di valore
0xC0–0xFFnon è valido come letterale; scrivilo come run di lunghezza 1 (0xC1, 0xFFper un singolo0xFF). Se lo si gestisce male, la decodifica perde la sincronia dopo una riga. - Il gioco prende gli ultimi 768 byte come palette, con o senza il
marcatore
0x0C; i lettori standard hanno bisogno del marcatore.
PAL / ALP / LHT / SHD — palette e tabelle di ricerca
- Il 4° byte di ogni voce NON è l'alfa. È un byte di riempimento
inutilizzato che Cavedog ha sempre impostato a
0x00. Gli strumenti open source per le palette che lo trattano come alfa non riescono a disegnare la palette (alfa=0 → tutto trasparente). - L'indice 0 è nero, non trasparente. Terreno, minimappe e fondali lo disegnano opaco; gli sprite scelgono la propria chiave di trasparenza.
- Un
palette.palvuoto o mancante viene sostituito dapalette.pcx(i suoi ultimi 768 byte); un.palpiù lungo di 1.024 byte viene letto fino al byte 1.024. .alp/.lht/.shdNON sono palette RGB:.alpè una tabella 256×256 e.shd/.lhtsono tabelle 32×256 di indici della palette, e il gioco ignora (e ricostruisce) una tabella di qualsiasi altra dimensione. Disegnarle conkbot pal describemostra immagini senza senso; usa invecekbot pal lookup.- La palette di TA contiene 13 terne RGB duplicate. Se il tuo editor elimina i duplicati all'importazione (alcuni lo fanno), perdi delle voci e la palette diventa silenziosamente di 243 voci.
FNT — font bitmap
Offsets[c] == 0significa "nessun glifo", non "glifo all'offset 0". L'offset 0 cade a metà dell'intestazione: Cavedog riusa lo zero come valore sentinella.- L'ordine dei bit è MSB-first all'interno di ciascun byte. Nei font bitmap moderni è più comune LSB-first; non darlo per scontato.
- Il flusso di bit è continuo tra una riga e l'altra: nessun riempimento alla fine di ogni riga di scansione.
Profili IA
- I file IA di TA: Kingdoms non hanno direttive
plan: solo righeweight/limitisolate. Il parser di kbot apre un plandefaultimplicito; i lettori dovrebbero tollerare il blocco mancante. Vedi TA:K — profili senza plan. - Nessuna validazione, da nessuna parte. Nomi di unità scritti male,
valori di peso sbagliati, righe fuori da un
plan: tutto viene ignorato in silenzio. Il primo segno di un profilo rotto è "l'IA si comporta in modo strano", senza alcun messaggio di log. - Gli alias di categoria (
PLANT,LEVEL3) "esistono" solo se almeno un'unità li dichiara inCategory=. Scrivi per erroreLEVL3e la direttiva non fa nulla, in silenzio.
Suoni
- Un WAV mancante produce silenzio, non un errore. Scrivi male
select1=cmsdel1(lettere invertite) e il motore non riproduce nulla: nessun log, nessun ripiego. - L'estensione
.wavè implicita nei valori dei TDF: non scriverla mai.select1=cmdsel1.wavdiventasounds/cmdsel1.wav.wave non trova nulla.
Particolarità di TA: Kingdoms
- TAK richiede
-disablecavedogverificationcome argomento della riga di comando per caricare la maggior parte dei file modificati. Senza questa opzione il motore rifiuta qualsiasi file il cui hash non compaia nel suo elenco di quelli ammessi. - Nei dati di TAK ci sono 8 codici di fazione, non 4: ARA / TAR / VER / ZON per le quattro fazioni giocabili, più CRE (Creon, Iron Plague), MON (mostri), LIF (fauna selvatica), NPC (personaggi della campagna). Il filtraggio degli elenchi di unità deve gestirli tutti.
- In TAK le armi stanno inline in ogni FBI come sottosezioni
[WEAPON1]–[WEAPON3], non in una directory separataweapons/*.tdf. - I menu di costruzione di TAK sono lineari, non 2×3. Ogni costruttore
ha una directory
canbuild/<builder>/<unit>.tdfcon un singolo blocco[Menu] { Priority = N; }.
Vedi anche
- Tutorial sul modding: una mod di un'unità di TA, dall'inizio alla fine.
- Glossario: le definizioni di tutti i termini comuni ai vari formati citati qui sopra.
- Guida rapida: cinque comandi kbot da provare subito.