Ir para conteúdo

gcr_fc

Silver Member
  • Total de Posts

    307
  • Registro em

  • Última visita

  • Dias Ganhos

    33
  • WCoins

    281

Tudo que gcr_fc postou

  1. Basicamente. Toda função compilada vira uma sequência de bytes. Mesmo quando o executável é recompilado, o padrão de bytes do início da função costuma ser muito parecido entre versões. Por exemplo, CPSock::AddMessage sempre começa com algo assim: 55 8B EC 51 56 8B F1 83 3E 00 77 ?? C7 46 ?? 0A 00 00 00 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ constante 0x0A (erro 10) │ │ │ │ │ │ └─ JA (jump if above) = "se > 0, pula" │ │ │ │ │ └─ CMP [ESI], 0 = "buffer vazio?" │ │ │ │ └─ MOV ESI, ECX = salva o ponteiro 'this' │ │ │ └─ PUSH ESI │ │ └─ PUSH ECX │ └─ MOV EBP, ESP ─┐ prólogo padrão de função x86 └─ PUSH EBP ─┘ O ?? são wildcards — bytes que podem mudar entre versões (offsets que o compilador pode realocar), mas o esqueleto da lógica é o mesmo. Para cada função, temos 3 assinaturas ordenadas da mais específica para a mais genérica: v1 (22 bytes, match=100): "55 8B EC 51 56 8B F1 83 3E 00 77 ?? C7 46 ?? 0A 00 00 00 33 C0 5E" - muito específica, quase impossível dar falso positivo v2 (14 bytes, match=70): "55 8B EC ?? 56 8B F1 83 3E 00 77 ?? C7 46" - mais tolerante, aceita variação no prólogo v3 (8 bytes, match=40): "8B F1 83 3E 00 77 ?? C7" - último recurso, só o "núcleo" da lógica A prioridade é sempre a v1, se por acaso não encontrar com a v1, tenta a v2 e assim por diante. Raramente chega na v3. Se o código for recompilado, o addr muda porem o padrão dos bytes continua o mesmo, digamos que a função foi reescrita, isso vai dificultar a analise, porem sabemos que esse tipo de função normalmente tem valores de retornos específicos, como por exemplo - constante 0x0A (erro 10), então seguimos procurando por essas particularidades. BOOL CPSock_New::AddMessage(char* pMsg, int Size, int FixedKeyWord) { if (Sock == INVALID_SOCKET || Sock == 0) { ErrCount = 10; //AQUI return FALSE; } // Bloqueia envio de pacotes de game enquanto DH esta pendente. // Em vez de dropar, enfileira para enviar apos DH completar. if (m_useDynamicKeys && !m_keyExchangeCompleted) { if (m_preDHQueuePos + static_cast<int>(sizeof(int)) + Size < PRE_DH_QUEUE_SIZE) { memcpy(&m_preDHQueue[m_preDHQueuePos], &Size, sizeof(int)); m_preDHQueuePos += sizeof(int); memcpy(&m_preDHQueue[m_preDHQueuePos], pMsg, Size); m_preDHQueuePos += Size; pLog.Info(pLog.Format("Pre-DH queue: buffered %d bytes (total queued: %d)", Size, m_preDHQueuePos), "network"); return TRUE; } pLog.Warning("Pre-DH queue full, packet dropped", "network"); return FALSE; } if (nSendPosition + Size >= SEND_BUFFER_SIZE) { //AQUI ErrCount = 1; m_sendDropCount++; return FALSE; } Comentei ai nesse trecho de código, alguns pontos que podem ser usados para a analise. Nesse novo sistema que implementei, vc ate consegue fazer funcionar, porem como cada sessão que vc iniciar com o servidor tem um conjunto de keys exclusivas, toda vez vc vai ter que capturar, para poder fazer funcionar. Mas digamos que reescreveram a função toda, mudaram tudo e etc... Ai meu amigo, vc analisa o exe novamente e encontra outra vez suahsaushaushau A grosso modo é isso.
  2. Fala pessoal, vou compartilhar com vocês uma ferramenta que vem me ajudando a analisar os packets do WYD_Global na versão atual. Foi desenvolvida com o único intuito de poder acertar as STRUCTS do jogo e ter um padrão sólido. Não vou compartilhar a Source. Porem a ferramenta é 100% funcional e cumpre o objetivo. Funciona em todos os cliente que usam o padrão de CPSock Original com o sistema de criptografia original, salvo os que estejam protegidos por anti injection ou outros tipos de proteção, já que a ferramenta não tem nem uma técnica para bypassar essas proteções. Como o objetivo é o WYD Global e ele não tem nem uma tipo de proteção, não implementei nem um bypass, salvo uma verificação de debugger que existe do WYD.exe original!! Temos a KeyTable Original codada dentro da dll, porem conseguimos gerar um dump da KeyTable do cliente que estamos trabalhando. E podemos carregar uma KeyTable Custom caso seja necessario. Como funciona: a primeira ferramenta é a DLL, que basicamente faz todo o trabalho. Sempre que injetamos a DLL em um cliente ela analisa o exe acha a posição da KeyTable na memoria, gera um WYD_KeyTable_dump.txt que pode ser aberto com o bloco de notas. Em caso de diferença entre a KeyTable Original que esta na DLL e a KeyTable usado no cliente, basta renomearmos WYD_KeyTable_dump.txt para WYD_KeyTable_custom.txt e injetarmos novamente a DLL a KeyTable custom será carregada automaticamente e substitui a codada na DLL. Gera um console com informações em tempo real e exibe os packets que estão sendo analisados (somente o Header no console), podemos analisar packets específicos adicionando os opcodes em WYD_PacketFilter.txt, dentro do arquivo tem toda a descrição de como usar, se o arquivo estiver vazio ou somente com comentarios (;) todos os packets serão logados. Os packets são salvos completamente na raiz do cliente, uma pasta é criada com o nome de PacketLog e dentro dela temos as pasta Send e Recv, que são auto explicativas!! os packets são salvos desencriptados e em .txt podendo serem analisados no próprio bloco de notas por exemplo. Cada arquivo .txt salva ate 200 dumps dos packets, qunaod chega no limite os dados param de ser salvos no arquivo. Podemos configurar essa quantia tbm em WYD_PacketFilter.txt o valor minimo é 1 e o maximo 200. Tudo auto explicativo dentro dos .txt Temos uma segunda ferramenta no pacote que se chama WYDSigGen, ele deve ser colocado na pasta do exe. Basta executar e ele carregara o WYD.exe e fara uma analise do binário procurando pela posição das funções de Recv e Send. Dessa forma gera um arquivo chamado WYD_Signatures.ini nele vai conter informações para que a DLL consiga hookar nos locais corretos, mesmo após uma atualização, por exemplo. Salvo quando o cliente passar por modificações muito grandes, como reestruturação das funções de encode/decode por exemplo. Ai o binário precisa ser analisado novamente para encontrar os offsets e assinaturas das novas funções. A terceira ferramenta é o WYDInjector ele que carrega nossa WYDHook.dll no executável. Inicia o WYD no Global normalmente pelo Launcher, quando o cliente estiver rodando, abra o WYDInjector como administrador e a DLL será carregada automaticamente. ATENÇÃO a WYDHook.dll deve estar na mesma pasta do WYDInjector.exe, nem um dos 2 precisam estar na pasta do cliente. Somente WYD_Signatures.ini, WYD_PacketFilter.txt e WYD_KeyTable_custom.txt (caso queira carregar uma KeyTable custom) devem estar na pasta raiz do cliente que esta sendo analisado. Acho que não esqueci de nada, segue um vídeo em uso... OBS: não vou postar scan dos arquivos pelos seguintes motivos: A DLL nao tem nem um tipo de proteção ou ofuscação. Os executáveis WYDSigGen e WYDInjector, principalmente o WYDInjector modificam coisas em runtime, então obviamente são detectados como vírus, porem são falso positivo. O fórum é voltado a Cheat, temos varias pessoas com muito conhecimento aqui, caso não se sintam seguros em usar, baixem os arquivos e analisem pessoalmente... os .exe tbm nao possuem nem um tipo de proteção ou ofuscação. Podem ser abertos com debuggers e analisados, até mesmo descompilados caso alguém tenha curiosidade. Quem quiser usar, pode usar tranquilamente, não tem nada malicioso ou que possa gerar dano a vocês. Bom é isso e espero que seja útil para vocês como foi para mim. A ultima compilação foi hoje, vocês estão tendo acesso a versão release. Segue o Link. Caso o antivirus de vocês acuse algo, basta adicionar uma exceção. WYDStudio_GuiCan
  3. assim que der uma folga faço um vídeo, então o DX11 abre varias possibilidades, tem bastante coisa ainda pra polir, porem como estou trabalhando sozinho e levando em paralelo o wydconverter e umas coisas a mais, não evolui tão rápido como eu gostaria hehe. Estou aprendendo ainda a trabalhar com o DX11 preciso fixar alguns conceitos, a parte mais chata é acertar os shaders. Um parte do novo sistema de Crypto Aqui uma parte do Shader para meshs Skinned
  4. então, esse cliente em questão roda todo em DX11, muita coisa foi reescrita e o dimensionamento dos itens na tela foi um deles, pra poder suportar as resoluções wide reescrevemos o código. Consequentemente acabou corrigindo vários outros bugs que aconteciam com a UI como esse de algumas texturas ficarem fora de posição. O cliente suporta resoluções ate 4k sem erros de posicionamento de texturas. Qualquer edição que for feita no Editor de UI fica perfeitamente posicionada ingame. obvio que vc não pode sobrepor componentes, exemplo se puxar o botão das abas pra cima do espaço onde mostra o gold, os botões perdem a função. Todo o sistema de segurança do cliente foi reescrito, cada cliente tem sua tabela de keys que são geradas aleatoriamente a cada nova conexão. entoa não temos mais a keytable como era antes, entre varias outras mudanças que foram implementadas.
  5. Não sei ainda... Pretendo liberar uma versão com mais funcionalidades como o editor de UI e CamAction. segue algumas prints. Exemplo de uso do Editor de UI - Implementação da 4 aba do Cargo Implementação de Editor de Account e Mobs/Npcs
  6. Ninguém tá discutindo quem faz melhor ou pior cara, o único ponto é o foco da comunidade, tudo que tem aqui na área WYD ou foi fruto de Descompilação ou roubo... Vocês sabem disso... Então não adianta reclamar que o fulano pegou o código e postou... Ele não retirou os créditos do Hamilton. Então só acho que não tem motivo pra ele ficar bravo/chateado com isso... Dei uma olhada por cima e o editor é bem legal, realmente uma novidade aí pra comunidade. E realmente tem coisas a melhorar como vc mesmo disse... Não acho que ele deva se preocupar em usarem o código ou coisa assim... Só vai ficar mais careca 🤣🤣🤣
  7. Para de resmunga cara... Vc é um dos que meche em projeto dos outros tbm... Vc realmente acho que ninguém ia olhar??? Fala sério...
  8. gcr_fc

    mesh

    no WYDConverter fica melhor a visualização
  9. gcr_fc

    mesh

    no WYDConverter eu fiz uma área de tutorial e um deles é a criação de novos itens/mobs, veja se te ajuda. copia e crie um .md pode ser no próprio VS que vai ficar bem mais legível. # Guia: Criar Mobs, Objetos e Meshes Novos para o WYD > Passo a passo completo para criar conteudo 3D novo e integrar no cliente WYD. > Cobre mobs (MSH skinned), objetos estaticos (MSA), modelagem, exportacao, > conversao e registro nos arquivos do cliente. --- ## 1. Sistema de Arquivos do WYD ### 1.1 Arquivos 3D por mob | Arquivo | Exemplo | Conteudo | Formato | |---|---|---|---| | `.msh` | `nm010101.msh` | Mesh skinned (vertices, indices, bones, skinning) | Binario 32B header | | `.bon` | `nm01.bon` | Hierarquia do esqueleto (pares parentID/boneID) | Binario 8B por bone | | `.ani` | `nm010101.ani` | Animacao (matrizes 4x4 locais por bone por frame) | Binario 8B header + matrices | | `.wys` | `nm010101.wys` | Textura DXT1 comprimida | Binario WYS | | `.wyt` | `nm010101.wyt` | Textura BGRA raw (formato antigo) | Binario WYT | ### 1.2 Convencao de nomes ``` {prefixo}{PPVV}.ext prefixo = skeleton type (4 chars): nm01, ch01, ch02, tr09, hs01... PP = parte/slot (2 digitos): 01=corpo, 02=helm, 03=armor... VV = visual/variante (2 digitos): 01=base, 02=alt... ``` **Regra critica:** os primeiros 4 caracteres definem o skeleton. Todos os arquivos com mesmo prefixo compartilham o mesmo `.bon` e os mesmos `.ani`. Exemplos: - `nm010101.msh`, `nm010102.msh` → usam `nm01.bon` - `ch010597.msh` → usa `ch01.bon`, slot 05 (luva), visual 97 ### 1.3 Arquivos de registro do cliente Estes arquivos precisam ser editados para o cliente reconhecer mobs novos. | Arquivo | Path | Funcao | Editar quando | |---|---|---|---| | `BoneAni4.txt` | `Mesh\BoneAni4.txt` | Registra skeletons: index, num ANIs, num partes, prefixo | Skeleton NOVO | | `ValidIndex.bin` | `Mesh\ValidIndex.bin` | Mapeia quais ANIs existem para cada skeleton | Skeleton NOVO | | `MeshTextureList.bin` | `Mesh\MeshTextureList.bin` | Tabela de texturas de meshes (nome → index) | Textura NOVA | | `MeshList.txt` | `Mesh\MeshList.txt` | Registra objetos estaticos MSA: index → path | MSA NOVO | | `AniSound4.txt` | `AniSound4.txt` | Tabela de animacoes/velocidades/sons por skeleton type | Skeleton NOVO | | `ItemList.bin` | Server-side | Define nClass do mob → mapeia para skeleton via `BASE_DefineSkinMeshType` | Mob NOVO | | `Basedef.cpp` | Compilado no .exe | `BASE_DefineSkinMeshType(nClass)` → nBoneAniIndex (hardcoded switch) | Skeleton NOVO (recompilacao) | **Para mob com skeleton EXISTENTE:** nenhum destes arquivos precisa ser editado. Basta colocar o MSH + WYS na pasta `Mesh\` com o prefixo correto. **Para mob com skeleton NOVO:** todos os arquivos acima precisam ser editados. --- ## 2. Formatos Binarios Detalhados ### 2.1 MSH (Mesh Skinned) ``` Header (32 bytes): [00] DWORD dwParentID — ID do bone pai (0xFFFFFFFF = root) [04] DWORD dwMeshID — ID do bone deste mesh [08] DWORD dwFVF — Flexible Vertex Format (D3D9) [0C] DWORD sizeVertex — Bytes por vertice [10] DWORD numFaceInfluence — Numero de face influences [14] DWORD numPalette — Numero de bones na palette [18] DWORD vertexCount — Numero de vertices [1C] DWORD faceCount — Numero de INDICES (nao faces!) Bones (se numPalette > 0): XMFLOAT4X4[numPalette] — Offset matrices (64 bytes cada) DWORD[numPalette] — Bone IDs (4 bytes cada) Vertices: Layout depende do FVF. Tipico para skinned: Position XYZ (12B) + BlendWeights (4-12B) + PackedBoneIndices (4B) + Normal (12B) + UV (8B) Indices: uint16[faceCount] — Index buffer 16-bit ``` ### 2.2 BON (Bone Hierarchy) ``` Arquivo = array de pares (8 bytes cada): [parentID: DWORD] [boneID: DWORD] parentID = 0xFFFFFFFF ou 0 → root (sem pai) parentID = N → bone filho de bone N Tamanho total = numBones * 8 bytes ``` Exemplo para esqueleto com 5 bones: ``` [0xFFFFFFFF] [0] — Bone 0 e root [0] [1] — Bone 1 filho de Bone 0 [0] [2] — Bone 2 filho de Bone 0 [1] [3] — Bone 3 filho de Bone 1 [1] [4] — Bone 4 filho de Bone 1 ``` ### 2.3 ANI (Animation) ``` Header (8 bytes): [00] DWORD numTicks — Numero de keyframes (frames de animacao) [04] DWORD numBones — Numero de bones no skeleton Dados: Para cada tick (0..numTicks-1): XMFLOAT4X4[numBones] — Matriz LOCAL de cada bone neste frame (64 bytes cada) Tamanho total = 8 + (numTicks * numBones * 64) bytes ``` As matrizes sao LOCAL (relativas ao pai na hierarquia BON). O cliente propaga pela hierarquia para obter as combined (world) matrices: `combined[bone] = local[bone] * combined[parent]` ### 2.4 BoneAni4.txt ``` Formato texto, uma linha por skeleton: {index} {numAniTypes} {numParts} {szAniName} Campos: index — Indice no array m_BoneAnimationList (0-99) numAniTypes — Quantos ANIs diferentes este skeleton tem numParts — Quantos slots de equipamento (1 para mobs simples, 7 para players) szAniName — Prefixo completo com path (ex: mesh\nm01, mesh\ch01) ``` Exemplo: ``` 0 38 7 mesh\ch01 <- personagem masculino, 38 animacoes, 7 partes 1 37 7 mesh\ch02 <- personagem feminino 2 1 1 mesh\hs01 <- cavalo, 1 animacao, 1 parte 3 2 1 mesh\nm01 <- mob tipo 1, 2 animacoes, 1 parte ... ``` ### 2.5 ValidIndex.bin ``` Array binario fixo: stValidAniList[100][186] stValidAniList = struct { int nI; } — 4 bytes Tamanho total = 100 * 186 * 4 = 74.400 bytes Indexacao: m_stValidAniList[skeletonIndex][aniSlot].nI = aniFileIndex O cliente usa nI+1 para montar o nome do ANI: sprintf(szTemp, "%s%04d.ani", szAniName, m_stValidAniList[nCount][nFI].nI + 1) Exemplo: m_stValidAniList[3][0].nI = 0 → mesh\nm010001.ani (idle) m_stValidAniList[3][1].nI = 1 → mesh\nm010002.ani (walk) m_stValidAniList[3][2].nI = 100 → mesh\nm010101.ani (arma 01, idle) ``` Codificacao dos 4 digitos do ANI: ``` XXYY onde: XX = tipo de arma (weapon): nArrayIndex / 100 - 1 YY = tipo de acao (motion): nArrayIndex % 100 - 1 Exemplos (nI+1 → arquivo): 0001 → arma 0, acao 0 (idle) 0002 → arma 0, acao 1 (walk) 0003 → arma 0, acao 2 (run) 0004 → arma 0, acao 3 (attack1) 0101 → arma 1, acao 0 (idle com espada) ``` ### 2.6 MeshList.txt ``` Formato texto, uma linha por objeto estatico: {index} {path_relativo} Campos: index — Indice no array m_stCommonMesh (0-3047) path_relativo — Caminho do MSA relativo ao diretorio do cliente ``` Exemplo: ``` 0 mesh\cas001.msa 1 mesh\cas002.msa 50 mesh\tree01.msa 100 mesh\sword01.msa ``` O engine chama `GetCommonMesh(dwObjType)` onde dwObjType = index. Mapas (.trn) referenciam objetos pelo dwObjType. ### 2.7 MeshTextureList.bin ``` Array binario fixo de stTextureListInfo (264 bytes cada): char szFileName[255] — path relativo da textura (ex: "mesh\nm010101.wys") char cAlpha — tipo de alpha: 'N'=none, 'A'=alpha, 'a'=1bit, 'C'=compressed DWORD dwLastUsedTime — runtime (ignorar, preencher com 0) DWORD dwShowTime — runtime (ignorar, preencher com 0) Tamanho por versao: TMProject classico: 2048 slots = 540.672 bytes WYD Global: 6096 slots = 1.609.344 bytes ``` O cliente busca textura por nome (`GetModelTextureIndex`): percorre TODOS os slots comparando `szFileName` com o nome calculado pelo `TMSkinMesh`. Se nao encontra, o mesh **NAO CARREGA** (retorna erro). **Para adicionar textura nova:** 1. Encontrar um slot vazio (szFileName[0] == '\0') 2. Preencher szFileName com path relativo (ex: `mesh\xx010101.wys`) 3. Preencher cAlpha com 'N' (sem alpha) ou 'A' (com alpha) 4. dwLastUsedTime e dwShowTime = 0 ### 2.8 AniSound4.txt ``` Formato texto. Uma secao por skeleton type (MAX_ANI_TYPE = 60 skeletons). Cada secao tem 56 linhas (MAX_ANI_MOTION), uma por tipo de acao. Para skeleton types 0 e 1 (players): {nomeAcao} {ani0} {speed0} {ani1} {speed1} {ani2} {speed2} {ani3} {speed3} {sound} Para skeleton types 2+ (mobs/NPCs): {nomeAcao} {aniIndex} {speed} {sound} Campos: nomeAcao — label (ex: "IDLE", "WALK", "ATK1") — ignorado pelo parser aniIndex — indice na lista de animacoes do skeleton (posicao no array concatenado) speed — velocidade da animacao (ticks por frame) sound — indice do som a tocar ``` Controla qual animacao tocar para cada acao do mob (idle, walk, attack, death, etc.) e a velocidade de reproducao. Se o skeleton novo for um mob simples, basta preencher as acoes basicas (idle=0, walk=1, attack=2, death=3). ### 2.9 Fluxo de resolucao no cliente ``` Servidor envia pacote com mob → nClass (tipo do mob) ↓ BASE_DefineSkinMeshType(nClass) → nBoneAniIndex (switch hardcoded em Basedef.cpp) ↓ BoneAni4.txt[nBoneAniIndex] → szAniName (ex: "mesh\nm01"), numParts, numAniTypes ↓ Skeleton: szAniName + ".bon" → mesh\nm01.bon Mesh: szAniName + PPVV + ".msh" → mesh\nm010101.msh Textura: szAniName + PPVV + ".wys" → mesh\nm010101.wys → GetModelTextureIndex(texName) → busca em MeshTextureList.bin Animacao: ValidIndex.bin[nBoneAniIndex][slot] → nI+1 → mesh\nm010001.ani → AniSound4.txt[nBoneAniIndex] → mapeia acao → indice de animacao ``` ### 2.10 STRUCT_ITEMLIST (ItemList.bin) ``` Struct STRUCT_ITEMLIST — 120 bytes por item: char Name[64] — Nome do item short nIndexMesh — Indice visual do mesh short nIndexTexture — Indice visual da textura short nIndexVisualEffect — Efeito visual (brilho, aura) short nReqLvl — Nivel minimo short nReqStr / nReqInt / — Requisitos de atributo nReqDex / nReqCon STRUCT_STATICEFFECT stEffect[12] — 12 efeitos estaticos (4 bytes cada) int nPrice — Preco do item short nUnique — Tipo de raridade short nPos — Bitmask de slots onde pode equipar short nExtra — Dados extras short nGrade — Grau/rank do item ``` **nIndexMesh e nIndexTexture** sao os campos que conectam o item ao mesh visual. O significado muda COMPLETAMENTE dependendo do tipo de item: **ARMAS E ESCUDOS (slots 6 e 7 — MSA):** nIndexMesh = indice DIRETO no MeshList.txt O cliente chama: GetCommonMesh(nIndexMesh) → LoadMsa(MeshList[nIndexMesh]) Nenhuma formula intermediaria. Se a arma esta no index 500 do MeshList, nIndexMesh = 500. nIndexTexture = preenche LOOK_INFO.SkinX mas NAO e usado para renderizar a arma 3D. A textura da arma vem do nome embeddado no MSA → MeshTextureList. Na pratica, para armas, nIndexTexture = 0. **EQUIPAMENTOS SKINNED (slots 0-5 — MSH):** nIndexMesh = variante visual usada na FORMULA do nome do MSH: sprintf("%s%02d%02d.msh", szAniName, slot+1, nIndexMesh + offset + 1) NAO e um indice de MeshList. E um numero de variante (0, 1, 2...). Exemplo: nIndexMesh=5 no slot coat → ch010306.msh (prefixo + slot03 + visual06) nIndexTexture = modificador de textura na FORMULA do nome da WYS: sprintf("%s%02d%02d.wys", szAniName, slot+1, (nIndexTexture & 0xFFF) + nIndexMesh + offset + 1) Permite usar texturas diferentes para o mesmo mesh visual. Exemplo: nIndexMesh=5, nIndexTexture=2 + 1 → ch010308.wys **MONTARIAS (slot 14 — MSH skinned, skeleton proprio):** O item de montaria fica em Equip[14]. sIndex do item → transformado (sIndex - 2045, com overrides hardcoded) → sIndex final usado como indice no g_pItemList: nIndexMesh = g_pItemList[sIndex].nIndexMesh → Mesh0 (variante visual) nIndexTexture = g_pItemList[sIndex].nIndexTexture → Skin0 (variante textura) nClass (efeito 18) → BASE_DefineSkinMeshType(nClass) → skeleton da montaria Funciona igual a equipamentos skinned: nIndexMesh e variante visual, NAO indice do MeshList. Vem do ItemList.bin. **nPos** — bitmask de slots de equipamento: ``` Bit 0 (0x01) = Slot 0: Face/Corpo Bit 1 (0x02) = Slot 1: Helm (elmo) Bit 2 (0x04) = Slot 2: Coat (armadura) Bit 3 (0x08) = Slot 3: Pants (calca) Bit 4 (0x10) = Slot 4: Gloves (luva) Bit 5 (0x20) = Slot 5: Boots (bota) Bit 6 (0x40) = Slot 6: Left (mao esq/escudo) Bit 7 (0x80) = Slot 7: Right (mao dir/arma) ``` **nClass (efeito 18)** — tipo de classe que determina o skeleton: Usado por `BASE_DefineSkinMeshType(nClass)` para mobs e montarias. Para players: nClass 1/4 = masculino (ch01), 2/8 = feminino (ch02). Para mobs: nClass 16-74 mapeiam para indices 2-57 no BoneAni4.txt. ### 2.11 Fluxo visual de armas ``` Item no Equip[7] (mao direita) ou Equip[6] (mao esquerda) ↓ g_pItemList[sIndex].nIndexMesh → nIndexMesh ↓ GetCommonMesh(nIndexMesh) ← DIRETO, sem formula intermediaria! ↓ MeshList.txt[nIndexMesh] → path do MSA (ex: mesh\wp001.msa) ↓ TMMesh::LoadMsa(path) → carrega MSA ↓ Textura: nome embeddado no MSA → GetModelTextureIndex → MeshTextureList.bin ``` ### 2.12 Fluxo visual de equipamentos (armaduras, helmos, etc.) ``` Item no Equip[0-5] (face, helm, coat, pants, gloves, boots) ↓ g_pItemList[sIndex].nIndexMesh → LOOK_INFO.MeshX (variante) g_pItemList[sIndex].nIndexTexture → LOOK_INFO.SkinX (textura mod) ↓ TMSkinMesh monta nome do arquivo: Mesh: sprintf("%s%02d%02d.msh", szAniName, slot+1, MeshX + offset + 1) Tex: sprintf("%s%02d%02d.wys", szAniName, slot+1, (SkinX & 0xFFF) + MeshX + offset + 1) ↓ Exemplo: ch01, slot 3 (coat), nIndexMesh=5, nIndexTexture=0 Mesh: ch010306.msh Tex: ch010306.wys ``` --- ## 3. Restricoes Tecnicas do Cliente ### 3.1 MSH (Skinned Meshes) | Item | Limite | Origem | |---|---|---| | Bones por mesh | 40 max | `safePalette = min(n, 40)` em CMesh | | Influences por vertice | 4 max | FVF XYZB1-B4 + LASTBETA_UBYTE4 | | Vertices por mesh | 65535 max | Indices 16-bit no MSH | | Textura por mesh | 1 | MSH nao tem attribute ranges | | Textura dimensao | Potencia de 2 | DXT1 | | Coordenadas | Z-Up | Nativo WYD | | UV | V=0 no topo (D3D) | Nativo WYD e 3ds Max | | Skeletons registrados | 100 max | MAX_BONE_ANIMATION_LIST | | ANIs por skeleton | 186 max | Array fixo ValidAniList | | Bones por skeleton | Sem limite hard | Limitado pela RAM | ### 3.2 MSA (Static Meshes) | Item | Limite | Origem | |---|---|---| | Vertices por mesh | 65535 max | Indices 16-bit | | Materiais por mesh | 32 max | dwAttCount no header | | Texturas por material | 1 | Uma WYS por attribute range | | Textura dimensao | Potencia de 2 | DXT1 | | Coordenadas | Z-Up | Nativo WYD | | UV | V=0 no topo (D3D) | Nativo WYD | | Objetos em MeshList | 3048 max | MAX_COMMON_MESH | | FVF suportados | 274 (normal) ou 322 (diffuse) | Engine hardcoded | --- ## 4. Workflow: Novo Mob com Skeleton Existente **Cenario:** criar um mob novo que reutiliza o esqueleto e animacoes de um mob existente. Este e o caminho mais rapido e seguro. ### Passo 1 — Exportar mob de referencia No WYDConverter, abrir o MSH do mob que quer reusar (ex: `nm010101.msh`). Exportar como FBX (target 3ds Max). O FBX contem: - Geometria do mob original - Esqueleto completo com bone IDs - Animacao do ANI companion - Textura companion como PNG ### Passo 2 — Importar no 3ds Max Importar o FBX. O mesh aparece: - Z-Up (nativo do Max e do WYD — sem conversao) - Escala amplificada (conversor aplica x100 para edicao confortavel) - Bones com nomes `Bone_000`, `Bone_001`, etc. **NAO mover, rotacionar ou escalar o Armature.** A posicao dos bones e o bind pose que as animacoes existentes esperam. ### Passo 3 — Modelar - Deletar a geometria do mob original (so poligonos, NAO os bones) - Modelar o novo mob ao redor do esqueleto existente - Manter o mesh alinhado com os bones na posicao de bind Regras: - Apenas triangulos (sem quads/n-gons) - Max 65535 vertices - 1 material/textura por mesh - Polycount razoavel (~500-3000 tris para mobs) ### Passo 4 — Skinning - Aplicar Skin modifier no mesh - Adicionar os bones do esqueleto importado - Pintar weights: max 4 influences por vertice - Weights devem somar 1.0 - Todo vertice deve ter pelo menos 1 bone com peso > 0 ### Passo 5 — UV e Textura - UV Unwrap no Max (UV convention D3D: V=0 topo — default do Max) - Textura PNG/TGA em potencia de 2 (256x256 ou 512x512) - O WYDConverter converte para WYS automaticamente ### Passo 6 — Exportar FBX File → Export → FBX: - Formato: FBX Binary - Eixos: Z-Up (default Max) - Smoothing Groups: ON - Skin/Deformers: ON - Embed Media: OFF ### Passo 7 — Converter No WYDConverter: 1. Abrir o FBX exportado 2. Converter para MSH 3. Nomear: `nm010199.msh` (mesmo prefixo, numero livre) 4. Converter textura PNG → WYS: `nm010199.wys` 5. Copiar para `Mesh\` do cliente ### Passo 8 — Testar O cliente carrega automaticamente: - `nm010199.msh` — mesh novo - `nm01.bon` — hierarquia (ja existe) - `nm010001.ani` etc — animacoes (ja existem) - `nm010199.wys` — textura nova Nenhuma edicao de BoneAni4.txt ou ValidIndex.bin necessaria (mesmo skeleton). --- ## 5. Workflow: Mob com Skeleton e Animacoes Novas **Cenario:** criar um mob completamente novo com esqueleto e animacoes proprias. Requer ferramentas adicionais e edicao de arquivos de registro. ### Passo 1 — Modelar e Riggar no 3ds Max - Modelar o mob - Criar esqueleto com bones (usar nomes `Bone_000`, `Bone_001`, etc.) - Bone 0 deve ser o root - Max 40 bones - Skin modifier com max 4 influences ### Passo 2 — Criar Animacoes No 3ds Max, criar as animacoes necessarias: - Idle (parado) - Walk (andando) - Run (correndo) - Attack (atacando) - Death (morrendo) - etc. Cada animacao sera exportada como um FBX separado (ou ranges no mesmo FBX). ### Passo 3 — Exportar Exportar cada animacao como arquivo separado com mesh + skeleton + animation. Formatos suportados: - **FBX Binary** (3ds Max, Maya, Blender via plugin) - **GLB/GLTF** (Blender nativo, qualquer DCC moderno) ### Passo 4 — Converter Usar o WYDConverter para gerar: | De | Para | Ferramenta | Status | |---|---|---|---| | FBX mesh | `.msh` | MSHEncoder (FBX→MSH) | ✅ Funciona | | GLB/GLTF mesh | `.msh` | MSHEncoder (GLTF→MSH) | ✅ Funciona | | FBX skeleton | `.bon` | **BONEncoder (FBX)** | ❌ NAO EXISTE | | GLB/GLTF skeleton | `.bon` | **BONEncoder (GLTF)** | ❌ NAO EXISTE | | FBX animation | `.ani` | **ANIEncoder (FBX)** | ❌ NAO EXISTE | | GLB/GLTF animation | `.ani` | **ANIEncoder (GLTF)** | ❌ NAO EXISTE | | PNG textura | `.wys` | WYSEncoder | ✅ Funciona | ### Passo 5 — Registrar no cliente Para um skeleton completamente novo, TODOS estes arquivos precisam ser editados: #### 5.1 Editar BoneAni4.txt Adicionar uma linha para o novo skeleton: ``` {novoIndex} {numAnis} {numParts} mesh\{prefixo} ``` Exemplo: adicionar mob `xx01` com 3 animacoes, 1 parte: ``` 50 3 1 mesh\xx01 ``` O index (50) deve ser um slot livre no array (0-99). #### 5.2 Editar ValidIndex.bin Adicionar as entradas para mapear os ANIs do novo skeleton: ``` m_stValidAniList[50][0].nI = 0 → mesh\xx010001.ani (idle) m_stValidAniList[50][1].nI = 1 → mesh\xx010002.ani (walk) m_stValidAniList[50][2].nI = 2 → mesh\xx010003.ani (attack) ``` O ValidIndex.bin e um array binario fixo de 74400 bytes. Offset para skeleton index N = N * 186 * 4 bytes. Cada slot = 4 bytes (int). #### 5.3 Editar MeshTextureList.bin Adicionar a textura do novo mob em um slot vazio: ``` Slot livre → szFileName = "mesh\xx010101.wys", cAlpha = 'N' ``` **CRITICO:** sem esta entrada, o cliente NAO encontra a textura e o mesh nao carrega. O `GetModelTextureIndex` faz busca linear por nome — se nao encontra, retorna -1, e o CMesh aborta o carregamento. Para encontrar slots vazios: qualquer entrada com `szFileName[0] == '\0'`. Cada slot tem 264 bytes. Para editar diretamente no binario: ``` Offset = slotIndex * 264 [+0..+254] = szFileName (null-terminated, zero-padded) [+255] = cAlpha ('N' ou 'A') [+256..+259] = dwLastUsedTime (0) [+260..+263] = dwShowTime (0) ``` #### 5.4 Editar AniSound4.txt Adicionar uma secao para o novo skeleton type. A posicao na lista corresponde ao nBoneAniIndex. Para mob simples (56 linhas, formato `{nome} {aniIdx} {speed} {sound}`): ``` TYPE50 IDLE 0 30 0 WALK 1 30 0 RUN 1 20 0 ATK1 2 25 0 ATK2 2 25 0 DEATH 2 30 0 ... (preencher restante com 0 0 0) ``` #### 5.5 Editar BASE_DefineSkinMeshType (recompilacao) Em `Basedef.cpp`, a funcao `BASE_DefineSkinMeshType(nClass)` e um switch hardcoded que mapeia o nClass do item/mob → nBoneAniIndex. Para adicionar um novo mob com nClass=75: ```cpp case 75: return 50; // nosso novo skeleton xx01, index 50 no BoneAni4.txt ``` **Isto requer recompilacao do cliente.** Nao ha como evitar — o mapeamento e hardcoded no executavel. #### 5.6 Registrar no servidor (ItemList) O servidor define o `nClass` de cada mob/NPC no `ItemList.bin` ou na tabela de mobs. O nClass e o que o cliente recebe no pacote e usa para chamar `BASE_DefineSkinMeshType`. #### 5.7 Colocar arquivos ``` Mesh\xx01.bon — hierarquia Mesh\xx010001.ani — idle Mesh\xx010002.ani — walk Mesh\xx010003.ani — attack Mesh\xx010101.msh — mesh Mesh\xx010101.wys — textura ``` --- ## 6. Plano de Implementacao: Encoders Faltantes ### 6.1 BONEncoder (FBX/GLTF/GLB → BON) **Complexidade:** Baixa (formato trivial: pares de DWORDs) **Input:** FBX ou GLTF/GLB com skeleton **Output:** arquivo .bon **Algoritmo (FBX path):** 1. Percorrer todos os FbxNode com FbxSkeleton attribute 2. Para cada bone, extrair o boneID do nome (`Bone_XXX` → XXX) 3. Para cada bone, determinar o parentID: - Root: parentID = 0xFFFFFFFF - Outros: parentID = boneID do pai 4. Escrever pares [parentID, boneID] em ordem (root primeiro, BFS) **Algoritmo (GLTF/GLB path):** 1. Carregar documento GLTF com glTF SDK 2. Ler `doc.skins[0].jointIds` — lista de nodes que sao joints 3. Para cada joint node, extrair boneID do nome (`Bone_XXX` → XXX) 4. Para cada joint, determinar parentID pela hierarquia de nodes: - Se parent node nao esta em jointIds → root (0xFFFFFFFF) - Senao → boneID do parent node 5. Escrever pares [parentID, boneID] **Arquivos a criar:** - `Conversores/BON/BONEncoder.h` — declaracao - `Conversores/BON/BONEncoder.cpp` — `FromFBX()` e `FromGLTF()` + `SaveBON()` compartilhado **Estimativa:** ~120 linhas de codigo, 2-3 horas. ### 6.2 ANIEncoder (FBX/GLTF/GLB → ANI) **Complexidade:** Media (precisa avaliar animacao por frame e extrair matrizes locais) **Input:** FBX ou GLTF/GLB com skeleton + animation **Output:** arquivo .ani **Algoritmo (FBX path):** 1. Ler o FBX com FBX SDK 2. Determinar numBones (do skeleton) e numTicks (do animation stack) 3. Para cada tick (frame): a. Setar o tempo: `FbxTime::SetFrame(tick, eFrames30)` b. Para cada bone (por boneID, 0..numBones-1): - Avaliar `node->EvaluateLocalTransform(time)` → FbxAMatrix - Converter FbxAMatrix para XMFLOAT4X4 - Se o FBX veio do WYDConverter: reverter anchor correction e scale - Se e novo conteudo: usar local transforms direto c. Gravar as numBones matrizes para este tick 4. Escrever header (numTicks, numBones) + todas as matrizes **Algoritmo (GLTF/GLB path):** 1. Carregar documento GLTF com glTF SDK 2. Ler `doc.animations[0]` — channels e samplers 3. Determinar numTicks pelo max timestamp / (1/30) + 1 4. Para cada tick: a. Calcular tempo: `t = tick / 30.0f` b. Para cada bone: - Interpolar TRS dos samplers (translation, rotation, scale) no tempo t - Rotation: quaternion → matrix (GLTF usa quaternions nativamente) - Compor local matrix: S * R * T - Converter Y-Up → Z-Up (GLTF e Y-Up, ANI e Z-Up) c. Gravar as numBones matrizes 5. Escrever header + matrizes **Cuidados comuns:** - As matrizes no ANI sao LOCAL (relativas ao pai), nao world - FBX: `EvaluateLocalTransform` ja retorna local - GLTF: channels ja sao local (por spec) - FBX Z-Up (nosso export) = WYD Z-Up → sem conversao - GLTF Y-Up → precisa converter para Z-Up: conjugar cada local matrix - Scale: matrizes ANI sao puras (rotacao + translacao) - Normalizar rotation columns para magnitude 1.0 antes de salvar - Frame rate: WYD usa 30fps - GLTF: samplers podem ter interpolacao LINEAR ou STEP - LINEAR: interpolar entre keyframes - STEP: usar valor anterior **Arquivos a criar:** - `Conversores/ANI/ANIEncoder.h` — declaracao - `Conversores/ANI/ANIEncoder.cpp` — `FromFBX()`, `FromGLTF()` + `SaveANI()` compartilhado **Estimativa:** ~350 linhas de codigo, 5-8 horas. ### 6.3 ValidIndexEditor (editor de ValidIndex.bin) **Complexidade:** Baixa (array binario fixo, UI simples) **Funcionalidade:** - Carregar ValidIndex.bin (74400 bytes) - Mostrar grid: skeleton index × ani slot → nI value - Editar nI values - Salvar ValidIndex.bin **Integracao:** nova tab ou dialog no WYDConverter. **Estimativa:** ~150 linhas, 2-3 horas. ### 6.4 BoneAni4Editor (editor de BoneAni4.txt) **Complexidade:** Baixa (texto simples, UI simples) **Funcionalidade:** - Carregar BoneAni4.txt - Mostrar tabela: index, numAniTypes, numParts, szAniName - Adicionar/remover/editar linhas - Salvar BoneAni4.txt **Integracao:** mesma tab do ValidIndexEditor. **Estimativa:** ~100 linhas, 1-2 horas. ### 6.5 MeshTextureListEditor (editor de MeshTextureList.bin) **Complexidade:** Baixa (array binario fixo, ja temos decoder) **Funcionalidade:** - Carregar MeshTextureList.bin (auto-detecta classico 2048 vs Global 6096 slots) - Mostrar tabela: index, szFileName, cAlpha - Busca por nome (filtro) - Adicionar textura em slot vazio (auto-encontrar proximo livre) - Editar/remover entradas - Salvar MeshTextureList.bin **Nota:** Ja temos `MeshTextureListDecoder` com `LoadBIN`, `SaveBIN`, `LoadTXT`, `SaveTXT`. O editor so precisa de UI — a logica de I/O ja existe. **Integracao:** tab no DataEditor do WYDConverter. **Estimativa:** ~120 linhas (UI apenas), 2-3 horas. ### 6.6 AniSound4Editor (editor de AniSound4.txt) **Complexidade:** Baixa (texto formatado, parser simples) **Funcionalidade:** - Carregar AniSound4.txt - Mostrar: skeleton type → 56 linhas (acao, aniIndex, speed, sound) - Editar valores por celula - Duplicar secao de skeleton existente (template para novo mob) - Salvar AniSound4.txt **Integracao:** mesma tab dos editores de registro. **Estimativa:** ~150 linhas, 2-3 horas. ### 6.7 Ordem de Implementacao ``` Fase 1 — BONEncoder FBX + GLTF/GLB (2-3h) Permite: criar hierarquia de skeleton novo de qualquer formato Dependencias: nenhuma Teste: exportar mob existente MSH→FBX→BON e MSH→GLB→BON, comparar com original Fase 2 — ANIEncoder FBX (3-5h) Permite: criar animacoes novas a partir de FBX Dependencias: nenhuma Teste: exportar mob existente MSH+ANI→FBX→ANI, comparar com original Fase 3 — ANIEncoder GLTF/GLB (3-5h) Permite: criar animacoes novas a partir de GLTF/GLB Dependencias: SaveANI() da Fase 2 Teste: exportar mob existente MSH+ANI→GLB→ANI, comparar com original Nota: GLTF usa quaternions + timestamps flutuantes (vs FBX Euler + frames fixos) Precisa: interpolacao de samplers, quat→matrix, Y-Up→Z-Up Fase 4 — Editores de registro (5-8h) 4a. BoneAni4Editor (1-2h) — ja temos parser 4b. ValidIndexEditor (2-3h) — binario fixo 4c. MeshTextureListEditor (2-3h) — ja temos LoadBIN/SaveBIN 4d. AniSound4Editor (2-3h) — parser texto Permite: registrar skeleton, animacoes, texturas e sons Teste: adicionar entradas, verificar que cliente carrega Fase 5 — Workflow integrado (3-4h) Batch: FBX/GLB → MSH + BON + ANI + WYS em um click Auto-registro: adiciona entradas nos 4 arquivos de registro UI: wizard "Novo Mob" no WYDConverter Validacao: checar limites (40 bones, 65535 verts, etc.) Suporte: arrastar FBX ou GLB, detectar conteudo automaticamente ``` **Total estimado: 18-27 horas de desenvolvimento.** --- ## 7. Checklist Final ### Para mob com skeleton existente: - [ ] Exportar mob de referencia como FBX ou GLB - [ ] Modelar novo mesh no DCC ao redor do skeleton - [ ] Skin com max 4 influences, weights somam 1.0 - [ ] UV unwrap, textura potencia de 2 - [ ] Exportar FBX Binary Z-Up ou GLB - [ ] Converter FBX/GLB → MSH no WYDConverter - [ ] Converter textura → WYS - [ ] Adicionar textura nova em MeshTextureList.bin (se textura nova) - [ ] Copiar MSH + WYS para Mesh\ do cliente - [ ] Testar in-game ### Para mob com skeleton novo: - [ ] Tudo acima + - [ ] Criar skeleton com bones `Bone_000` a `Bone_NNN` - [ ] Criar animacoes (idle, walk, attack, death) - [ ] Exportar FBX ou GLB por animacao - [ ] Gerar BON via BONEncoder (FBX ou GLTF) - [ ] Gerar ANIs via ANIEncoder (FBX ou GLTF) - [ ] Editar BoneAni4.txt (adicionar linha com index, numAnis, numParts, prefixo) - [ ] Editar ValidIndex.bin (mapear slots → nI para cada ANI) - [ ] Editar MeshTextureList.bin (adicionar textura em slot vazio) - [ ] Editar AniSound4.txt (adicionar secao com aniIndex/speed/sound por acao) - [ ] Editar BASE_DefineSkinMeshType em Basedef.cpp (nClass → nBoneAniIndex) - [ ] Registrar mob no servidor (ItemList: nClass + LOOK_INFO) - [ ] Copiar BON + ANIs + MSH + WYS para Mesh\ do cliente - [ ] Testar in-game --- ## 8. Criar Objetos Estaticos Novos (MSA) Objetos MSA sao meshes estaticos SEM bones nem animacao. Usados para: - Construcoes (casas, torres, portais, altares) - Decoracoes de cenario (arvores, pedras, caixas, barris) - Armas e itens de chao (espadas, escudos, pocoes) - Efeitos estaticos (circulos, plataformas) ### 8.1 Diferenca entre MSH e MSA | Aspecto | MSH (Skinned) | MSA (Static) | |---|---|---| | Bones/Skeleton | Sim (max 40) | Nao | | Animacao | Sim (.ani + .bon) | Nao | | Skinning/Weights | Sim (max 4 por vertice) | Nao | | Multi-material | Nao (1 textura) | Sim (1-32 attribute ranges) | | Diffuse color | Nao (FVF 274) | Opcional (FVF 322) | | Uso tipico | Personagens, mobs, montarias | Cenario, itens, armas | ### 8.2 Sistema de registro MSA MSA sao registrados via **MeshList.txt** — uma tabela texto simples: ``` {index} {path_relativo} Exemplo: 0 mesh\cas001.msa 1 mesh\cas002.msa 2 mesh\tree01.msa ... ``` O index e o `dwObjType` que o engine usa para referenciar o objeto. `GetCommonMesh(dwObjType)` busca o path no MeshList e chama `LoadMsa()`. As texturas sao resolvidas de 2 formas: 1. Nome embeddado no MSA (campo de 11 bytes por attribute range) 2. Busca em MeshTextureList.bin por `mesh\{nomeBase}.wys` ### 8.3 Formatos de vertice MSA (FVF) | FVF | Hex | Layout | Bytes | Uso | |---|---|---|---|---| | 274 | 0x112 | Position(12) + Normal(12) + UV(8) | 32 | Maioria dos objetos | | 322 | 0x142 | Position(12) + Diffuse(4) + UV(8) | 24 | Objetos com vertex color | **CRITICO:** o FVF deve ser preservado no round-trip. Converter um MSA de FVF 322 para FVF 274 QUEBRA a renderizacao no cliente (o engine trata 322 de forma especial). ### 8.4 Workflow: Criar MSA Novo #### Passo 1 — Modelar Crie o objeto no 3ds Max ou Blender: - Apenas geometria (sem bones, sem skeleton) - Triangulos apenas (sem quads/n-gons) - Max 65.535 vertices - Escala: 1 unidade = proporcional ao mundo WYD (exporte um objeto existente como referencia) #### Passo 2 — Multi-material (opcional) MSA suporta ate 32 materiais/texturas por mesh: - Atribua materiais diferentes a grupos de faces - Cada material pode ter sua propria textura - Os attribute ranges sao preservados no round-trip Para objetos simples, 1 material e suficiente. #### Passo 3 — UV e Textura - UV Unwrap normal - Textura PNG ou TGA em potencia de 2 (256x256, 512x512) - Para multi-material: 1 textura por material - O WYDConverter converte PNG → WYS #### Passo 4 — Exportar No 3ds Max: File > Export > FBX Binary, Z-Up, Smoothing Groups ON No Blender: File > Export > glTF 2.0 (.glb), +Y Up, Apply Modifiers ON **NAO precisa** incluir Skin/Deformers (MSA e estatico). #### Passo 5 — Converter no WYDConverter 1. Abrir o FBX ou GLB no WYDConverter 2. Dropdown "MSA" > "FBX -> MSA" (ou "GLB -> MSA") 3. Nomear: `cas999.msa` (ou qualquer nome livre) 4. Converter textura: PNG -> WYS: `cas999.wys` #### Passo 6 — Registrar **MeshList.txt** — adicionar linha: ``` {indexLivre} mesh\cas999.msa ``` O index deve ser um slot livre (0-3047, MAX_COMMON_MESH = 3048). **MeshTextureList.bin** — adicionar textura: ``` Slot vazio → szFileName = "mesh\cas999.wys", cAlpha = 'N' ``` Para multi-material, adicionar CADA textura separadamente. #### Passo 7 — Colocar e testar ``` Mesh\cas999.msa ← mesh estatico Mesh\cas999.wys ← textura ``` O engine carrega via `GetCommonMesh(index)` quando o terreno ou objeto referencia o `dwObjType` correspondente ao index. Para testar: colocar o objeto em um mapa editando o .trn (terrain file) com o index do MeshList.txt. ### 8.5 Checklist MSA - [ ] Modelar objeto (sem bones, triangulos apenas) - [ ] UV unwrap, textura potencia de 2 - [ ] Exportar FBX ou GLB (sem skeleton) - [ ] Converter FBX/GLB → MSA no WYDConverter - [ ] Converter textura → WYS - [ ] Adicionar textura em MeshTextureList.bin - [ ] Adicionar entrada em MeshList.txt (index + path) - [ ] Copiar MSA + WYS para Mesh\ do cliente - [ ] Testar no mapa (colocar objeto no .trn)
  10. nao, a informação dos mobs na cena sao definidos na demoX.bin cada uma pode ter ate 50 ids, no caso 50 mobs na cena. O editor trabalha com eles tbm.
  11. as 2 coisas, os arquivos do global foram feitos com analise binaria com auxilio da IA e descompilação com o IDA. Os da TMProject tem tudo nela, então só pegar as structs e analisar o código que esta lá. estou usando a source do repositório do Eric como base. Creio que deva ser a mais próxima do cliente original, salvo engano. Na verdade a parte mais complicada é o conversor de meshs, principalmente as .msh tem 5 tipos de padrões diferentes nos arquivos e montar o .fbx com bones e animações funcionais é bem complicado. A vantagem é que vc pode criar meshs do 0 no 3ds/blender e converter com o app e o WYD aceita corretamente. Mas já tem umas 80 horas de trabalho só no conversor.
  12. Implementado Editor de UI do cliente, conseguimos trabalhar com todos os paineis originais, conseguimos criar novos paineis e etc. as texturas que são configuradas nos Scenes podem ser editadas logos por exemplo, as texturas que são carregadas dinamicamente pelo cliente podem ser reposicionadas pelo editor e são carregadas corretamente quando roda o cliente. vai da imaginação, pode modificar inventario, guarda carga e tudo mais... LoginScene.bin FieldScene2.bin Inicio da implementação de um editor de CamAction onde podera ser editado a visão da camera, o caminho que a camera faz, formas de visualização e etc.
  13. Suporte ao 3DsMax. MSH->FBX_3Ds
  14. e entao eu peguei do cliente atual do global, mas ja que a parte do directx foi toda reescrita e roda no DX11, resolvi ja dar uma modificada hehe, ficou legal, tem 12 opcoes de cor de fogos e mais umas porpurinices kkkk
  15. Esta sendo feito para o cliente em DX11 porem pode ser implementado na TMProject original. Gif
  16. caraca, top em ficou bacana no navegador. O meu deu uma boa avançada tbm, dei uma reduzida no ritmo por causa do trabalho, esse mês está uma loucura a oficina.
  17. pois é cara muito mais fácil de implementar o glb/gltf do que o fbx, o fbx fiz via ascii muita frescura, qualquer coisinha fora já não importava, para acertar tudo e carregar bones e animações foram umas boas horas, já o glb/gltf foi muito mais fácil. essas 2 ultimas imagens ai são gifs só clicar nelas e vc vai ver os 2 formatos rodando animados no blender o astaroth é fbx com bones e animações e o pogobol é glb tbm com bones e animações. ainda estou procurando um forma de resolver o posicionamento dos modelos 3d no blender, pq algumas meshs tem rotação de 90 no eixo y e algumas não, logo umas carregam na posição digamos correta e outras ficam deitadas, nada que atrapalhe para editar... porem visualmente fica estranho o modelo 3d deitado kk.
  18. Segue um print de um .FBX convertido do .MSH ag010101 convertido com o app e carregado no blender 5.0 .FBX convertido do .MSH bd010101 .ani no blender agora suportamos GLB/GLTF
  19. não conheço esse formato, vou dar uma pesquisada a respeito para ver a viabilidade de implementar. segue um exemplo de um .msa convertido no app e aberto no blender, aqui foi convertido para .obj
  20. seu problema sao os caracteres chineses no caminho do arquivo veja nas propiredade do lado direito. o app nao reconhece os caracteres chineses é funcional e para os outros formatos tbm. o app ja esta mais avançado, estou trabalhando em um editor de mapas, ainda esta bem cru, mas aos poucos vai avançando
  21. oxi como assim ate que enfim?? tendi nada uU
  22. opa no momento nao. rapaz ainda não pensei em venda. Então por enquanto não tem como comprar.
  23. gcr_fc

    WYD_Converter

    Fala pessoal blz. Bom comentei em outro tópico que estava fazendo um conversor de arquivos do WYD. Estou fazendo para o meu projeto, porem esta ficando bem interessante e vou compartilhar com vocês para terem uma ideia do que a ferramenta será capaz. Usa DirectX 11. Conseguimos trabalhar com todos os arquivos do cliente. .MSH .MSA .WYS .WYT .BON .ANI .TRN e etc. Temos o modo de pré-visualização conseguimos ver além da meshs as animações e etc., Se temos um .MSH que possui um .BON e um .ANI associados quando carregamos o .MSH ele puxa automaticamente todos os outros arquivos correspondentes. Logo podemos dar play e ver a animação na preview. Podemos avançar ou retroceder frame a frame e etc. Todos os arquivos carregados ficam na aba da esquerda vc pode ver um a um clicando neles. O mesmo acontece quando carregamos uma .TRN todos os arquivos relacionados são carregados junto, logo conseguimos ver um a um selecionando na esquerda. A aba a direita do preview é a aba de propriedades e fornece informações importantes sobre os arquivos carregados. Conseguimos trabalhar com as meshs de qualquer cliente, na versão que vou postar para vocês não trabalha com as meshs do MYTH. Ainda temos alguma limitações com meshs novas do Global, pois não mapeei todas ainda, então algumas inda ficam transparentes, ou na visualização do .TRN ficam pretas. Na aba Conversores de dados conseguimos trabalhar com alguns arquivos legais como EnvTextureList ainda não trabalhamos com a Env do Global, mas esta em desenvolvimento. Temos Conversores de ItemList e SkillData aqui conseguimos trabalhar com arquivos da TMProject e do Global tanto leitura quando conversão BIN <--> CSV. Temos um Editor de ServerList.bin e trabalhamos com arquivos da TMProject e do Global basta carregar editar e salvar. Temos um Conversor de AttributeMap DAT <--> CSV logo converte para .CSV edita e converte novamente para .DAT A versão completa que tem os conversores de meshs todos habilitados, nessa versão da pra ver exatamente quais os arquivos suportados. Ainda temos um erros de encode nas mensagens do app e estou corrigindo aos poucos, pois são só estéticos. seguem algumas prints segue o scan - teve um apontamento, porem falso positivo, o app não tem assinatura digital então acusa... podem usar tranquilamente que não tem nada malicioso. VirusTotal Download GuiCan Acho que é isso, caso encontrem algum bug que não citei favor reportarem. A sim estava me esquecendo, no roda pé do app mostra as teclas de atalho.
×
×
  • Criar Novo...

Informação Importante

Nós fazemos uso de cookies no seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies , caso contrário, vamos supor que você está bem para continuar.