Todas as páginas de formatos ↓
Tutoriais e referência

Armadilhas comuns na criação de mods e na análise de ficheiros

Fonte: coreprime/kbot @ 0ab97bf · Editar no GitHub

Um resumo de uma página com as armadilhas que mais gente apanham, espalhadas pelos documentos de formatos do kbot. Se está às voltas com um erro que não faz sentido, comece por aqui. Cada ponto tem uma ligação para a explicação mais aprofundada na página do formato correspondente.

Tip

À procura de "o meu mod não carrega"? A regra do ponto e vírgula do TDF (#tdf--fbi--ota, primeiro ponto) explica mais relatos de "avarias silenciosas" do que todas as outras armadilhas juntas.


HPI / UFO / CCX / GP3

  • Os ficheiros soltos na raiz da instalação sobrepõem-se a todos os arquivos. Coloque units/MYUNIT.fbi no disco e o motor prefere-o a qualquer coisa que esteja em totala1.hpi. O diagrama de camadas em hpi.md mostra a pilha de prioridades completa.
  • Entre arquivos, ganha o primeiro a ser montado, e só se montam dez *.hpi. O TA 3.1c monta rev31.gp3, depois *.ccx, *.ufo e os dez primeiros *.hpi que consegue abrir, cada grupo por ordem do nome em maiúsculas ASCII. Um mod distribuído como zz_mod.hpi fica abaixo de todos os arquivos comerciais e, numa instalação que já tenha dez *.hpi ordenados antes dele, só é montado através da leitura do disco, abaixo de tudo. Distribua os mods como .ufo.
  • Os ponteiros do HPI v1 são absolutos em relação ao início do ficheiro, não ao início do diretório. Não subtraia nada. O truque do analisador canónico é alocar um buffer de DirectorySize bytes e decifrar o diretório para dentro dele no deslocamento Start, para que os ponteiros indexem o buffer diretamente. Veja Árvore de diretórios.
  • A semente da cifra do HPI v1 avança com a posição no ficheiro. Não é possível decifrar um buffer isoladamente: é preciso saber de que deslocamento absoluto do ficheiro veio esse buffer. Veja Derivar a chave da cifra.
  • Se DecryptKey == 0, não aplique a cifra XOR. Alguns arquivos personalizados vêm em texto simples; aplicar a cifra na mesma baralha o que já era legível.
  • A soma de verificação dos blocos SQSH é calculada sobre os bytes cifrados. Verifique-a antes de decifrar. Veja Blocos comprimidos (SQSH).
  • O TA: Kingdoms usa HPI v2 (Version == 0x00020000), com uma estrutura diferente: sem XOR, um único bloco SQSH por ficheiro. Leia a secção TA: Kingdoms — HPI v2 antes de experimentar o analisador da v1 num arquivo do TAK.
  • Os jogos guardados com o marcador BANK são outra coisa: reutilizam o invólucro do HPI, mas o conteúdo é o estado serializado do jogo, não um sistema de ficheiros. O kbot não os descodifica.
  • O .gp3 exige o patch rev3.1. Por dentro continua a ser HPI, mas o TA sem o patch recusa-se a montá-lo.

TDF / FBI / OTA

  • Todos os valores têm de terminar em ;. A falta de pontos e vírgulas junta silenciosamente valores de várias linhas e produz atributos completamente errados. É a causa número 1 de "a minha unidade tem pontos de vida estranhos / não tem descrição / tem o custo errado".
  • As chaves não distinguem maiúsculas de minúsculas; os valores distinguem. Side=arm funciona na maioria das pesquisas, mas estraga qualquer código de mod que compare Side por igualdade de cadeias de caracteres.
  • Os valores de lista são separados por espaços (Category=COMMANDER MOBILE WEAPON), não por vírgulas. A exceção é o numplayers=2,4,6,8,10 do OTA, que usa vírgulas.
  • Os booleanos são os inteiros 1/0, não true/false. O motor só aceita as formas inteiras.
  • Num mod, nunca edite o sidedata.tdf para acrescentar unidades. Use antes um registo [MENUENTRY] num download/<UNITNAME>.tdf, o mesmo mecanismo que o Core Contingency usa. Veja TDF: [MENUENTRY] e o tutorial de criação de mods.
  • Bmcode=0 esconde uma unidade do menu de construção, mesmo que tudo o resto esteja válido. Quase sempre, o que se quer é Bmcode=1.
  • Uma unidade que não esteja listada em nenhum construtor não pode ser construída, mesmo que o seu FBI seja válido em tudo o resto. É o erro mais comum de "a minha unidade nova existe mas não se pode construir". Veja o passo 5 do tutorial.
  • A profundidade das secções aninhadas é uma convenção, não uma especificação. Algumas ferramentas assumem 2 níveis; os TDF de armas chegam aos 3 ([WEAPON][DAMAGE][category]).

TNT / SCT — terreno dos mapas

  • O Width e o Height do TNT estão em células de atributos de 16 px, não em mosaicos nem em píxeis. Divida por 2 para obter o número de mosaicos; multiplique por 16 para obter as dimensões em píxeis. Veja Cabeçalho do TNT.
  • SeaLevel == 0 NÃO significa "sem água": significa que o menor valor possível está no limiar, por isso nada fica debaixo de água. Use SeaLevel = 1 para mapas realmente secos.
  • As palavras de elemento do TNT só colocam um elemento quando estão abaixo da contagem da tabela de elementos. 0xFFFC é vazio; 0xFFFE (Lava Run, AC02), 0xFFFD e qualquer outra palavra igual ou superior ao tamanho da tabela não colocam nada, e continua a ser possível construir na célula.
  • O preenchimento do minimapa do TNT usa o índice da paleta 0x64, e a região do mapa é dimensionada a partir do próprio mapa (lado maior com 252, com a proporção do mapa visível), e não encontrada à procura do preenchimento. O jogo só lê o minimapa guardado quando o bit 0 da palavra do cabeçalho em 0x2c está definido. Veja TNT.
  • O .tnt do TA: Kingdoms usa IDVersion == 0x4000 em vez do 0x2000 do TA (o TA também lê uma estrutura mais antiga, 0x1020). O kbot tnt image produz lixo com os TNT do TAK; o descodificador de mosaicos é específico do TA. Veja Mapas do TA:K.
  • As secções SCT têm de ter dimensões múltiplas de 4 para carregarem no TAE. O formato no disco permite outros tamanhos, mas o editor rejeita-os com "section misaligned".
  • O SCT V2 tem células de altura de 8 bytes, o V3 de 4 bytes. O kbot aceita os dois; os mods feitos com o editor só veem o V3.

3DO — modelos

  • O eixo vertical é o Y, não o Z. Importar um 3DO para um motor com o Z para cima (Blender, Unreal moderno) sem trocar os eixos deixa todas as unidades deitadas de lado.
  • As primitivas sem textura são invisíveis a não ser que IsColored != 0: o pseudocódigo visible = (texture != "") || (IsColored != 0) cobre os dois casos. É o erro mais comum ao renderizar um 3DO.
  • OffsetToSelectionPrim só tem significado no objeto raiz; os objetos filhos têm de o pôr a -1 (0xFFFFFFFF).
  • A escala de vírgula fixa é 1 / 65536. Um vértice escrito 0x00010000 = 1.0 unidades do mundo; os 16 bits inferiores são a parte fracionária.
  • Os vértices são locais ao objeto, não globais. Dois objetos podem ter vetores de vértices idênticos: é geometria espelhada, não dados partilhados.

COB / BOS — scripts

  • O opcode de call-script é 0x10062000, NÃO 0x10063000, como afirmam alguns documentos anteriores à 3.1. Os descompiladores antigos que usam 0x10063000 produzem disparates; veja a referência de opcodes.
  • Os números de peça nos opcodes são índices na tabela de nomes das peças, não cadeias de caracteres. O COB traz os nomes num conjunto de nomes; o motor em execução usa índices por ser mais rápido.
  • SET_SIGNAL_MASK só regista interesse: não mata nada. O que para os scripts cuja máscara tem X definido é enviar signal X. A regra de lint signal-never-signalled apanha os scripts que definem uma máscara que nunca ninguém sinaliza.
  • O Scriptor da Cavedog substitui CURRENT_SPEED pelo literal 29, o que estraga os scripts ao estilo de MoveWatcher depois de uma ida e volta. O descompilador do kbot repõe o nome simbólico; se tiver mesmo de fazer a ida e volta pelo Scriptor, use parênteses: (get CURRENT_SPEED) > 5.
  • Os deslocamentos dos saltos são deslocamentos em bytes relativos a OffsetToScriptCode, e não à instrução atual. JUMP 0x4C significa "saltar para OffsetToScriptCode + 0x4C".
  • Os números de porta de GET_UNIT_VALUE variam entre o TA e o TA:K. O catálogo do TA (o descompilador do kbot dá nome às portas 1–20) está documentado no Apêndice B.

GAF — animações de sprites

  • Uma sequência só se repete em ciclo quando o byte inferior da sua palavra +2 está definido; com 0, reproduz-se uma vez e para. Todas as sequências originais guardam 1, por isso uma ferramenta que escreva zero congela os elementos animados.
  • Os fotogramas de textures/*.gaf e anims/vismasks.gaf têm de estar em bruto. O jogo lê-os como simples vetores de píxeis.
  • Algumas sequências vêm com fotogramas de duração 0; o jogo mostra um fotograma assim durante um tick. Não os "corrija" para um valor por omissão.
  • O índice 0 da paleta não é transparente por si só. Só o são a chave de um fotograma em bruto e as séries de salto de um fotograma comprimido.
  • As linhas de píxeis comprimidas podem ser mais curtas do que Width. O jogo continua a ler os bytes seguintes; o kbot completa a linha com píxeis transparentes e avisa. Nenhum ficheiro original tem linhas assim.
  • As origens das camadas são pontos ativos (hotspots): cada camada de um fotograma composto é colocada de forma a que a sua origem coincida com a origem do fotograma.
  • anims/terrain.gaf e anims/vismasks.gaf têm Version == 0 nos cabeçalhos. O jogo ignora a palavra de versão.
  • O .taf do TA: Kingdoms existe em dois tipos. Um .taf com paleta É um GAF: o mesmo formato no disco, só que o TAK vai buscar a paleta a um .pcx de cada lado em vez de usar a paleta global do TA. Um .taf truecolor reutiliza o mesmo contentor, mas guarda píxeis ARGB de 16 bits e não precisa de paleta. O que conta é o byte de formato do fotograma (0/1 = com paleta, 4/5 = truecolor), não a extensão; veja TAF / TSF.

TAF / TSF — animações truecolor

  • O .taf tem dois significados: com paleta (lido como GAF) ou truecolor (lido com kbot taf). Verifique sempre o byte de formato do fotograma, nunca o nome do ficheiro, embora, por convenção, a maioria dos ficheiros truecolor do TAK tenha o sufixo _4444 / _1555.
  • A exportação para GIF perde informação. O GIF só guarda um recorte de 1 bit e 255 cores, por isso o alfa suave do ARGB4444 passa a arestas duras. Use APNG (kbot taf export --format apng) para manter o verdadeiro canal alfa.
  • O campo do nome do fotograma e o byte de flags 0x0B podem conter lixo. Preserve-os tal como estão para uma ida e volta idêntica byte a byte; não os normalize.
  • Um Delay / Duration de 0 é válido: tal como no GAF, um fotograma de zero ticks é comandado por eventos (os fundos de menu estáticos usam-no). Não o "corrija".

PCX — imagens

  • O TA ignora BytesPerLine. Os leitores normais descartam o preenchimento quando BytesPerLine > Width; o TA 3.1c descodifica exatamente Width bytes por linha, por isso os ficheiros com preenchimento aparecem desalinhados no jogo. Escreva BytesPerLine == Width e confirme com kbot pcx describe.
  • O TA só carrega a versão 5 e descodifica todos os ficheiros como dados de 8 bits num único plano.
  • Os bytes literais com os dois bits superiores definidos têm de ser escapados com RLE. Um byte isolado com valor 0xC0–0xFF não é válido como literal; emita-o como uma série de contagem 1 (0xC1, 0xFF para um único 0xFF). Tratar mal este caso dessincroniza a descodificação ao fim de uma linha.
  • O jogo usa os últimos 768 bytes como paleta, com ou sem o marcador 0x0C; os leitores normais precisam do marcador.

PAL / ALP / LHT / SHD — paletas e tabelas de consulta

  • O quarto byte de cada entrada NÃO é alfa. É um byte de preenchimento sem uso que a Cavedog pôs sempre a 0x00. As ferramentas de paletas de código aberto que o tratam como alfa não conseguem renderizar a paleta (alfa=0 → tudo transparente).
  • O índice 0 é preto, não transparente. O terreno, os minimapas e os fundos desenham-no opaco; os sprites escolhem a sua própria chave de transparência.
  • Um palette.pal vazio ou em falta é substituído pelo palette.pcx (os seus últimos 768 bytes); um .pal com mais de 1024 bytes é lido até ao byte 1024.
  • .alp / .lht / .shd NÃO são paletas RGB: o .alp é uma tabela de 256×256 e os .shd / .lht são tabelas de 32×256 com índices da paleta, e o jogo ignora (e reconstrói) uma tabela de qualquer outro tamanho. Renderizá-las com kbot pal describe mostra lixo; use antes kbot pal lookup.
  • A paleta do TA tem 13 triplos RGB duplicados. Se o seu editor eliminar duplicados ao importar (alguns fazem-no), perde entradas e a paleta passa, sem aviso, a ter 243 entradas.

FNT — tipos de letra bitmap

  • Offsets[c] == 0 significa "sem glifo", e não "glifo no deslocamento 0". O deslocamento 0 cai a meio do cabeçalho: a Cavedog reaproveita o zero como sentinela.
  • A ordem dos bits é MSB primeiro dentro de cada byte. LSB primeiro é mais comum nos tipos de letra bitmap modernos; não parta do princípio contrário.
  • O fluxo de bits é contínuo entre linhas: não há preenchimento no fim de cada linha de varrimento.

Perfis de IA

  • Os ficheiros de IA do TA: Kingdoms não têm diretivas plan: só linhas weight/limit soltas. O analisador do kbot abre um plano default implícito; os leitores devem tolerar a falta do bloco. Veja TA:K — perfis sem plan.
  • Não há validação em lado nenhum. Nomes de unidades mal escritos, valores de peso estragados, linhas fora de um plan: tudo é ignorado em silêncio. O primeiro sinal de um perfil estragado é "a IA comporta-se de forma estranha", sem qualquer mensagem no registo.
  • Os aliases de categoria (PLANT, LEVEL3) só "existem" se pelo menos uma unidade os declarar em Category=. Basta escrever LEVL3 por engano para a diretiva não fazer nada, sem aviso.

Sons

  • Um WAV em falta fica em silêncio, não dá erro. Escreva select1=cmsdel1 (com letras trocadas) e o motor não toca nada: nem registo, nem alternativa.
  • A extensão .wav está implícita nos valores TDF: nunca a escreva. select1=cmdsel1.wav passa a sounds/cmdsel1.wav.wav e não encontra nada.

Particularidades do TA: Kingdoms

  • O TAK exige -disablecavedogverification como argumento da linha de comandos para carregar a maior parte dos ficheiros modificados. Sem ele, o motor rejeita tudo aquilo cujo hash não esteja na sua lista de permissões.
  • O TAK tem 8 códigos de lado nos dados, não 4: ARA / TAR / VER / ZON para os quatro lados jogáveis, mais CRE (Creon, Iron Plague), MON (monstros), LIF (vida selvagem) e NPC (personagens da campanha). A filtragem de listas de unidades tem de tratar todos.
  • As armas do TAK estão dentro de cada FBI, como subsecções [WEAPON1]–[WEAPON3], e não numa pasta weapons/*.tdf separada.
  • Os menus de construção do TAK são lineares, não 2×3. Cada construtor tem uma pasta canbuild/<builder>/<unit>.tdf com um único bloco [Menu] { Priority = N; }.

Ver também