Escollos habituales al hacer mods y analizar formatos
Fuente: coreprime/kbot @ 0ab97bf · Editar en GitHub
Una chuleta de una sola página con los escollos con los que más gente tropieza de todos los que aparecen repartidos por los documentos de formatos de kbot. Si te topas con un fallo que no tiene ningún sentido, empieza por aquí. Cada punto enlaza con la explicación detallada en la página del formato correspondiente.
Tip
¿Buscas por qué «mi mod no carga»? La regla del punto y coma de TDF (#tdf--fbi--ota, primer punto) explica más casos de «fallo silencioso» que todos los demás escollos juntos.
HPI / UFO / CCX / GP3
- Los archivos sueltos de la raíz de la instalación tienen prioridad
sobre todos los archivos comprimidos. Deja
units/MYUNIT.fbien el disco y el motor lo preferirá a cualquier cosa detotala1.hpi. El diagrama de capas de hpi.md muestra la pila de prioridades completa. - Entre los archivos comprimidos gana el primero que se monta, y solo
se montan diez
*.hpi. TA 3.1c montarev31.gp3, después*.ccx,*.ufoy los diez primeros*.hpique se abran, cada grupo ordenado por nombre en mayúsculas según el orden ASCII. Un mod distribuido comozz_mod.hpiqueda por debajo de todos los archivos comprimidos de la versión comercial y, en una instalación que ya tenga diez*.hpique se ordenen antes que él, solo se monta mediante la exploración del disco, por debajo de todo lo demás. Distribuye los mods como.ufo. - Los punteros de HPI v1 son absolutos respecto al inicio del archivo,
no al del directorio. No restes nada. El truco del analizador de
referencia es reservar un búfer de
DirectorySizebytes y descifrar el directorio en él a partir del desplazamientoStart, para que los punteros indexen el búfer directamente. Consulta Árbol de directorios. - La semilla del cifrado de HPI v1 avanza con la posición en el archivo. No puedes descifrar un búfer de forma aislada: tienes que saber de qué desplazamiento absoluto del archivo procede. Consulta Cómo derivar la clave de cifrado.
- Si
DecryptKey == 0, no apliques el cifrado XOR. Algunos archivos comprimidos personalizados se distribuyen en claro; si aplicas el cifrado igualmente, desordenas lo que ya se podía leer. - La suma de comprobación de los chunks SQSH se calcula sobre los bytes cifrados. Compruébala antes de descifrar. Consulta Chunks comprimidos (SQSH).
- TA: Kingdoms usa HPI v2 (
Version == 0x00020000) con otra disposición: sin XOR y con un solo chunk SQSH por archivo. Lee la sección HPI v2 de TA: Kingdoms antes de probar el analizador de v1 con un archivo comprimido de TAK. - Las partidas guardadas con la marca
BANKson otra cosa: reutilizan el envoltorio HPI, pero el contenido es el estado de la partida serializado, no un sistema de archivos. kbot no las decodifica. .gp3necesita el parche rev3.1. Por dentro sigue siendo HPI, pero TA sin parchear se niega a montarlo.
TDF / FBI / OTA
- Todo valor debe terminar en
;. Si falta un punto y coma, los valores de varias líneas se unen sin avisar y salen estadísticas disparatadas. Es la causa número 1 de «mi unidad tiene unos puntos de vida raros / no tiene descripción / cuesta lo que no debe». - Las claves no distinguen mayúsculas de minúsculas; los valores sí.
Side=armfunciona en la mayoría de las búsquedas, pero rompe cualquier código de mod que compareSidepor igualdad de cadenas. - Los valores de lista van separados por espacios
(
Category=COMMANDER MOBILE WEAPON), no por comas. La excepción es elnumplayers=2,4,6,8,10de OTA, que usa comas. - Los booleanos son los enteros
1/0, notrue/false. El motor solo acepta la forma entera. - En los mods, nunca edites
sidedata.tdfpara añadir unidades. Usa en su lugar un registro[MENUENTRY]endownload/<UNITNAME>.tdf, el mismo mecanismo que usa Core Contingency. Consulta TDF:[MENUENTRY]y el tutorial de modding. Bmcode=0oculta una unidad del menú de construcción aunque todo lo demás sea válido. Casi siempre quieresBmcode=1.- Una unidad que no figura en ningún constructor no se puede construir, aunque su FBI sea válido en todo lo demás. Es el fallo más habitual de «mi unidad nueva existe pero no se puede construir». Consulta el paso 5 del tutorial de modding.
- La profundidad de las secciones anidadas es una convención, no una
especificación. Algunas herramientas suponen 2 niveles; los TDF de
armas llegan a 3 (
[WEAPON][DAMAGE][category]).
TNT / SCT: terreno del mapa
WidthyHeightde un TNT se miden en celdas de atributos de 16 px, no en casillas ni en píxeles. Divide por 2 para obtener el número de casillas; multiplica por 16 para obtener las dimensiones en píxeles. Consulta la cabecera de TNT.SeaLevel == 0NO significa «sin agua»: significa que el menor valor posible está en el umbral, así que nada queda bajo el agua. UsaSeaLevel = 1para los mapas realmente secos.- Las palabras de elemento de un TNT solo colocan un elemento por
debajo del número de entradas de la tabla de elementos.
0xFFFCes una celda vacía;0xFFFE(Lava Run, AC02),0xFFFDy cualquier otra palabra igual o superior al tamaño de la tabla no colocan nada, y en la celda se puede seguir construyendo. - El relleno del minimapa de un TNT usa el índice de la paleta
0x64, y el tamaño de la región del mapa se calcula a partir del mapa (lado más largo de 252, con la proporción del mapa visible), no buscando dónde está el relleno. El juego solo lee el minimapa guardado cuando está activado el bit 0 de la palabra de cabecera en0x2c. Consulta TNT. - Los
.tntde TA: Kingdoms usanIDVersion == 0x4000en lugar del0x2000de TA (TA también lee una disposición más antigua,0x1020).kbot tnt imageproduce basura con los TNT de TAK; el decodificador de casillas es específico de TA. Consulta Mapas de TA:K. - Las secciones SCT tienen que medir un múltiplo de 4 en las dos dimensiones para cargarse en TAE. El formato en disco admite otros tamaños, pero el editor los rechaza con «section misaligned».
- SCT V2 tiene celdas de altura de 8 bytes, y V3 de 4 bytes. kbot acepta las dos; los mods creados con el editor solo ven V3.
3DO: modelos
- El eje vertical es Y, no Z. Si importas un 3DO en un motor con Z hacia arriba (Blender, Unreal moderno) sin intercambiar los ejes, todas las unidades quedan tumbadas de lado.
- Las primitivas sin textura son invisibles salvo que
IsColored != 0: el pseudocódigovisible = (texture != "") || (IsColored != 0)cubre los dos casos. Es el fallo más habitual al renderizar 3DO. OffsetToSelectionPrimsolo tiene sentido en el objeto raíz; los objetos hijos deben ponerlo a-1(0xFFFFFFFF).- La escala de coma fija es
1 / 65536. Un vértice escrito como0x00010000vale 1,0 unidades del mundo; los 16 bits bajos son la parte fraccionaria. - Los vértices son locales al objeto, no globales. Dos objetos pueden tener arrays de vértices idénticos: eso es geometría reflejada, no datos compartidos.
COB / BOS: scripts
- El opcode de
call-scriptes0x10062000, NO0x10063000como afirman algunos documentos anteriores a la 3.1. Los descompiladores antiguos que usan0x10063000producen disparates: consulta la referencia de opcodes. - Los números de pieza de los opcodes son índices en la tabla de nombres de piezas, no cadenas. El COB lleva los nombres en un pool de cadenas; en tiempo de ejecución se usan índices por velocidad.
SET_SIGNAL_MASKsolo registra interés: no mata nada. Lo que detiene los scripts cuya máscara tieneXactivada es enviarsignal X. La regla de lintsignal-never-signalleddetecta los scripts que fijan una máscara a la que nadie envía nunca una señal.- El Scriptor de Cavedog sustituye
CURRENT_SPEEDpor el literal29, lo que rompe los scripts al estilo deMoveWatchertras un viaje de ida y vuelta. El descompilador de kbot restaura el nombre simbólico; si tienes que hacer el viaje de ida y vuelta con Scriptor, pon paréntesis:(get CURRENT_SPEED) > 5. - Los desplazamientos de salto son desplazamientos en bytes relativos
a
OffsetToScriptCode, no a la instrucción actual.JUMP 0x4Csignifica «saltar aOffsetToScriptCode + 0x4C». - Los números de puerto de
GET_UNIT_VALUEvarían entre TA y TA:K. El catálogo de TA (el descompilador de kbot etiqueta los puertos 1–20) está documentado en el apéndice B.
GAF: animaciones de sprites
- Una secuencia solo se repite en bucle cuando el byte bajo de su palabra +2 no es cero; con 0 se reproduce una vez y se detiene. Todas las secuencias originales guardan 1, así que una herramienta que escriba cero congela los elementos animados.
- Los fotogramas de
textures/*.gafyanims/vismasks.gafdeben ir sin comprimir. El juego los lee como arrays de píxeles simples. - Algunas secuencias se distribuyen con fotogramas de duración
0; el juego muestra un fotograma así durante un tick. No los «corrijas» con un valor por defecto. - El índice 0 de la paleta no es transparente por sí mismo. Solo lo son el color clave de un fotograma sin comprimir y los tramos de salto de uno comprimido.
- Las filas de píxeles comprimidas pueden ser más cortas que
Width. El juego sigue leyendo los bytes siguientes; kbot completa la fila con píxeles transparentes y avisa. Ningún archivo original tiene filas así. - Los orígenes de las capas son hotspots: cada capa de un fotograma compuesto se coloca de forma que su origen caiga sobre el origen del fotograma.
anims/terrain.gafyanims/vismasks.gaftienenVersion == 0en su cabecera. El juego ignora la palabra de versión.- Los
.tafde TA: Kingdoms son de dos clases. Un.tafcon paleta ES un GAF, con el mismo formato en disco, salvo que TAK toma la paleta de un.pcxpor bando en lugar de la paleta global de TA. Un.taftruecolor reutiliza el mismo contenedor, pero guarda píxeles ARGB de 16 bits y no necesita paleta. Lo que manda es el byte de formato del fotograma (0/1= con paleta,4/5= truecolor), no la extensión: consulta TAF / TSF.
TAF / TSF: animaciones truecolor
.taftiene dos significados: con paleta (se lee como GAF) o truecolor (se lee conkbot taf). Comprueba siempre el byte de formato del fotograma, nunca el nombre del archivo, aunque por convención la mayoría de los archivos truecolor de TAK lleven un sufijo_4444/_1555.- La exportación a GIF pierde información. GIF solo admite un
recorte de 1 bit y 255 colores, así que el alfa suave de ARGB4444 se
convierte en bordes duros. Usa APNG (
kbot taf export --format apng) para conservar el canal alfa real. - El campo de nombre del fotograma y el byte de flags
0x0Bpueden contener basura. Consérvalos tal cual para un viaje de ida y vuelta exacto byte a byte; no los normalices. - Un
Delay/Durationde0es válido: como en GAF, un fotograma de cero ticks lo controlan los eventos (los fondos de menú estáticos lo usan). No lo «corrijas».
PCX: imágenes
- TA ignora
BytesPerLine. Los lectores estándar descartan el relleno cuandoBytesPerLine > Width; TA 3.1c decodifica exactamenteWidthbytes por fila, así que los archivos con relleno se desplazan en el juego. EscribeBytesPerLine == Widthy compruébalo conkbot pcx describe. - TA solo carga la versión 5, y decodifica todos los archivos como datos de 8 bits en un solo plano.
- Los bytes literales con los dos bits altos activados tienen que
escaparse con RLE. Un byte suelto con valor
0xC0–0xFFno es válido como literal; escríbelo como un tramo de longitud 1 (0xC1, 0xFFpara un solo0xFF). Si no se trata bien, la decodificación se desincroniza al cabo de una fila. - El juego toma los 768 bytes finales como paleta, tengan o no la marca
0x0C; los lectores estándar necesitan la marca.
PAL / ALP / LHT / SHD: paletas y tablas de consulta
- El 4.º byte de cada entrada NO es alfa. Es un byte de relleno sin
uso que Cavedog siempre ponía a
0x00. Las herramientas de paletas de código abierto que lo tratan como alfa no consiguen renderizar la paleta (alfa=0 → todo transparente). - El índice 0 es negro, no transparente. El terreno, los minimapas y los fondos lo dibujan opaco; los sprites eligen su propio color clave transparente.
- Un
palette.palvacío o ausente se sustituye porpalette.pcx(sus últimos 768 bytes); de un.palde más de 1024 bytes se lee hasta el byte 1024. .alp/.lht/.shdNO son paletas RGB:.alpes una tabla de 256×256 y.shd/.lhtson tablas de 32×256 de índices de la paleta, y el juego ignora (y reconstruye) una tabla de cualquier otro tamaño. Renderizarlas conkbot pal describemuestra basura; usakbot pal lookupen su lugar.- La paleta de TA tiene 13 tripletes RGB duplicados. Si tu editor elimina duplicados al importar (algunos lo hacen), pierdes entradas y la paleta pasa sin avisar a tener 243 entradas.
FNT: fuentes de mapa de bits
Offsets[c] == 0significa «sin glifo», no «glifo en el desplazamiento 0». El desplazamiento 0 cae en mitad de la cabecera: Cavedog reutiliza el cero como valor centinela.- El orden de los bits es MSB primero dentro de cada byte. En las fuentes de mapa de bits modernas es más habitual LSB primero; no lo des por hecho.
- El flujo de bits es continuo entre filas: no hay relleno al final de cada línea de barrido.
Perfiles de IA
- Los archivos de IA de TA: Kingdoms no tienen directivas
plan: solo líneasweight/limitsueltas. El analizador de kbot abre un plandefaultimplícito; los lectores deberían tolerar que falte el bloque. Consulta Perfiles sin plan de TA:K. - No hay validación en ninguna parte. Nombres de unidad mal escritos,
valores de peso rotos, líneas fuera de
plan: todo se ignora sin avisar. La primera señal de un perfil roto es que «la IA se comporta de forma rara», sin ningún mensaje en el registro. - Los alias de categoría (
PLANT,LEVEL3) solo «existen» si al menos una unidad los declara enCategory=. Escribe malLEVL3y la directiva no hará nada, sin avisar.
Sonidos
- Un WAV que falta no suena, pero no da error. Escribe mal
select1=cmsdel1(letras cambiadas de sitio) y el motor no reproduce nada: ni registro ni sonido de reserva. - La extensión
.wavestá implícita en los valores TDF: no la escribas nunca.select1=cmdsel1.wavse convierte ensounds/cmdsel1.wav.wavy no encuentra nada.
Particularidades de TA: Kingdoms
- TAK necesita
-disablecavedogverificationcomo argumento de línea de comandos para cargar la mayoría de los archivos modificados. Sin esa opción, el motor rechaza todo aquello cuyo hash no esté en su lista de permitidos. - TAK tiene 8 códigos de bando en los datos, no 4: ARA / TAR / VER / ZON para los cuatro bandos jugables, más CRE (Creon, Iron Plague), MON (monstruos), LIF (fauna) y NPC (personajes de la campaña). El filtrado de listas de unidades tiene que tenerlos todos en cuenta.
- Las armas de TAK van en línea dentro de cada FBI como subsecciones
[WEAPON1]–[WEAPON3], no en un directorioweapons/*.tdfaparte. - Los menús de construcción de TAK son lineales, no de 2×3. Cada
constructor tiene un directorio
canbuild/<builder>/<unit>.tdfcon un único bloque[Menu] { Priority = N; }.
Véase también
- Tutorial de modding: recorrido completo para crear un mod de unidad de TA.
- Glosario: definiciones de todos los términos comunes a varios formatos que aparecen arriba.
- Inicio rápido: cinco comandos de kbot para empezar.