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.fbino disco e o motor prefere-o a qualquer coisa que esteja emtotala1.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 montarev31.gp3, depois*.ccx,*.ufoe os dez primeiros*.hpique consegue abrir, cada grupo por ordem do nome em maiúsculas ASCII. Um mod distribuído comozz_mod.hpifica abaixo de todos os arquivos comerciais e, numa instalação que já tenha dez*.hpiordenados 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
DirectorySizebytes e decifrar o diretório para dentro dele no deslocamentoStart, 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
BANKsã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
.gp3exige 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=armfunciona na maioria das pesquisas, mas estraga qualquer código de mod que compareSidepor 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 é onumplayers=2,4,6,8,10do OTA, que usa vírgulas. - Os booleanos são os inteiros
1/0, nãotrue/false. O motor só aceita as formas inteiras. - Num mod, nunca edite o
sidedata.tdfpara acrescentar unidades. Use antes um registo[MENUENTRY]numdownload/<UNITNAME>.tdf, o mesmo mecanismo que o Core Contingency usa. Veja TDF:[MENUENTRY]e o tutorial de criação de mods. Bmcode=0esconde 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
Widthe oHeightdo 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 == 0NÃO significa "sem água": significa que o menor valor possível está no limiar, por isso nada fica debaixo de água. UseSeaLevel = 1para 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),0xFFFDe 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 em0x2cestá definido. Veja TNT. - O
.tntdo TA: Kingdoms usaIDVersion == 0x4000em vez do0x2000do TA (o TA também lê uma estrutura mais antiga,0x1020). Okbot tnt imageproduz 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ódigovisible = (texture != "") || (IsColored != 0)cobre os dois casos. É o erro mais comum ao renderizar um 3DO. OffsetToSelectionPrimsó 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 escrito0x00010000= 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ÃO0x10063000, como afirmam alguns documentos anteriores à 3.1. Os descompiladores antigos que usam0x10063000produzem 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_MASKsó regista interesse: não mata nada. O que para os scripts cuja máscara temXdefinido é enviarsignal X. A regra de lintsignal-never-signalledapanha os scripts que definem uma máscara que nunca ninguém sinaliza.- O Scriptor da Cavedog substitui
CURRENT_SPEEDpelo literal29, o que estraga os scripts ao estilo deMoveWatcherdepois 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 0x4Csignifica "saltar paraOffsetToScriptCode + 0x4C". - Os números de porta de
GET_UNIT_VALUEvariam 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/*.gafeanims/vismasks.gaftê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.gafeanims/vismasks.gaftêmVersion == 0nos cabeçalhos. O jogo ignora a palavra de versão.- O
.tafdo TA: Kingdoms existe em dois tipos. Um.tafcom paleta É um GAF: o mesmo formato no disco, só que o TAK vai buscar a paleta a um.pcxde cada lado em vez de usar a paleta global do TA. Um.taftruecolor 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
.taftem dois significados: com paleta (lido como GAF) ou truecolor (lido comkbot 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
0x0Bpodem conter lixo. Preserve-os tal como estão para uma ida e volta idêntica byte a byte; não os normalize. - Um
Delay/Durationde0é 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 quandoBytesPerLine > Width; o TA 3.1c descodifica exatamenteWidthbytes por linha, por isso os ficheiros com preenchimento aparecem desalinhados no jogo. EscrevaBytesPerLine == Widthe confirme comkbot 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–0xFFnão é válido como literal; emita-o como uma série de contagem 1 (0xC1, 0xFFpara um único0xFF). 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.palvazio ou em falta é substituído pelopalette.pcx(os seus últimos 768 bytes); um.palcom mais de 1024 bytes é lido até ao byte 1024. .alp/.lht/.shdNÃO são paletas RGB: o.alpé uma tabela de 256×256 e os.shd/.lhtsão tabelas de 32×256 com índices da paleta, e o jogo ignora (e reconstrói) uma tabela de qualquer outro tamanho. Renderizá-las comkbot pal describemostra lixo; use anteskbot 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] == 0significa "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ó linhasweight/limitsoltas. O analisador do kbot abre um planodefaultimplí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 emCategory=. Basta escreverLEVL3por 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
.wavestá implícita nos valores TDF: nunca a escreva.select1=cmdsel1.wavpassa asounds/cmdsel1.wav.wave não encontra nada.
Particularidades do TA: Kingdoms
- O TAK exige
-disablecavedogverificationcomo 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 pastaweapons/*.tdfseparada. - Os menus de construção do TAK são lineares, não 2×3. Cada
construtor tem uma pasta
canbuild/<builder>/<unit>.tdfcom um único bloco[Menu] { Priority = N; }.
Ver também
- Tutorial de criação de mods — percurso completo de um mod de unidade do TA.
- Glossário — definições de todos os termos comuns aos vários formatos referidos acima.
- Início rápido — cinco comandos do kbot para experimentar primeiro.