[CK] Les ESP - Contenu d'un plugin esp - esm

Vous trouverez ici les conseils indispensables pour bien modder et maîtriser les outils de modding des jeux.
Répondre
Avatar du membre
Kesta
Maître de Forge
Maître de Forge
Messages : 1077

Les ESP - Contenu d'un plugin esp - esm

Message par Kesta »

Le topic qui suit est actuellement en cours de rédaction. Il vise à fournir une explication claire et techniquement exacte du contenu d'un plugin, au sens informatique du terme. Le but est de servir de base à la rédaction d'une explication tout aussi exacte est détaillée de ce sujet en anglais pour le guide xEdit du STEP.
Au vu de la complexité du sujet, j'ai préféré pauser les choses au clair en français avant de passer à la langue de Shakespeare. Etant donné que ça pourra toujours servir à quelques-uns des lecteurs locaux, j'utilise ce topic comme "brouillon" plutôt que de garder un vf sur mon PC.
Les contributions / corrections sont les bienvenue, de même que les remarques "ce passage n'est pas super clair". L'esprit est proche de ce que l'on trouvait sur le site du zero avant sa reconversion, pour ceux qui ont eu la chance de connaitre ;)


Introduction :

Le disclaimer en italique fera office d'intro pour le moment ^^ Si vous voulez suivre le guide et tout comprendre rapidement, je vous conseille d'ouvrir TES5Edit et éventuellement le CK en parallèle pour suivre, et ce dès que vous aurez terminé la petite aparté du début sur l'hexadécimal.


Notion de base : Le pourquoi de l'Hexadécimal

Je vais pas vous faire un cours sur le binaire et l'hexadécimal non plus, mais voilà une version simplifiée :
Un ordinateur ne comprend que des "suites de 0 et de 1". Sa mémoire est faite de blocs de mini-interrupteurs. Quand il veut une info, il regarde un de ces blocs, et l'état de chacun de ces interrupteurs : si il voit qu'il y a du courant, il considère que c'est un 1, sinon il considère un 0.
D’où le fait qu'on parle de 0 ou de 1 : Un ordinateur ne détecte en fait que la présence/absence d'électricité. On utilise ces suites de 0 et de 1 pour facilement comprendre et communiquer avec un ordinateur.

"Facilement ? Attends, tu trouve ça facile à comprendre 101000101111101001 ?"

Nan, évidemment, à convertir en base 10 (notre système numérique à nous les humains), c'est pas évident du tout, car il n'y a aucun point de repère. Mais c'est toujours mieux que d'essayer de détecter des signaux électriques à l'aide de tes petits doigts (ou de toute autre partie de ton corps, je ne juge pas)

C'est pourquoi on a "inventé" la base 16, aka l'hexadécimal. Plutôt que d'utiliser seulement 10 chiffres, on en utilise 16. Et parce qu'un informaticien est paresseux par nature, plutôt que d'inventer 6 nouveaux chiffres, ils ont utilisé les 6 première lettres de l'alphabet.

"Attends, c'est pas encore plus compliqué de rajouter encore une troisième façon de compter ?"

Eh bien non, l'hexadécimal est en base 16, et 16 est une puissance de 2 (16 = 2x2x2x2). "Et alors ?" me direz vous. Eh bien ça veux dire qu'on peu très facilement traduire du binaire en hexadécimal (contrairement à la traduction binaire -> base 10 qui est plutôt lourde). En effet, un nombre représenté par 4 données binaires correspond à un chiffre entre 0 et 15... c'est à dire un seul charactère hexadécimal.

"Nan mais c'est pas vraiment plus facile à lire..."

Pas plus facile que notre base 10 habituelle, non c'est sur. Mais infiniment plus qu'une suite de centaines de 0 et de 1. Donc pour tout ce qui touche à l'informatique, on utilise en général de l'hexadécimal pour visualiser une donnée.

Le dernier point important pour avoir les clés pour la suite : Je vous ai dit un peu plus haut qu'un ordinateur regardait un "groupe d'interrupteurs" pour lire une donnée. Ça veut dire que quand il cherche une donnée, il va regarder un nombre d'interrupteur prédéfini pour cette donnée. La taille la plus basique utilisée est de 8 interrupteurs (un nombre entre 0 et 255), ce qu'on appelle un octet. Et que l'on représente par simplement 2 caractères en hexadécimal.
Ça veut dire qu'on représente toujours une donnée avec le même nombre de chiffre, on ne "cache pas" les 0, comme nous avons l'habitude de le faire. Le nombre hexadécimal 0A, c'est le nombre décimal 0A, ce n'est pas "juste A". La différence, c'est que quand vous lisez "0A", vous savez que vous analysez une donnée qui peu avoir une valeur entre "00" et "FF", même si au moment ou vous la lisez, elle vaut "0A".


Les records dans skyrim

Et là, c'est le moment ou vous allez comprendre pourquoi il y avait une introduction complète sur l'hexadécimal...

Vous avez surement déjà utilisé un code console dans skyrim, pour une raison ou pour une autre. Et vous avez tapé un truc avec 8 caractères, du genre 00A15C28 pour appliquer ce code console... "Eh mais attend, ce 00A15C28, ce serait pas un code hexadécimal en fait ?"
Et bien si, bravo, ravi de voir que tu as tout suivi jusqu'ici ;) C'est ce qu'on appelle un FormID dans Skyrim. C'est à dire le nombre hexadécimal qui représente un "objet" du jeu, au sens large (objet pouvant ici signifier potion, PNJ, objet, quête, effet magique, décor, ...)
Bon, vu que le terme objet est pas très parlant, on parle en fait de "form". D’où le fait que le nombre haxadécimal soit un "FormID", c'est l'ID (identifiant) d'une Form !

"Bon, c'est bien beau tout ça, mais y a "record" dans le titre du paragraphe, pourquoi tu nous parle de Form ?"

Bah... parce que c'est plus ou moins la même la même chose. Raison pour laquelle, à partir de maintenant, on ne parlera donc plus que de record, et non de Form ^^


"Mais alors c'est quoi exactement, un record ?"

C'est une "macro-donnée" qui contient d'autres données. Comme une entrée dans une base de donnée. (Par exemple, si on faisait une base de donnée sur la confrérie, l'entrée de chaque "moddeur" pourrait contenir son pseudo, son age, son sexe, et une liste de ses mods).

Les informations les plus critiques d'un record forment ce que l'on appelle le "record header". C'est un peu une information à part des autres, qui permet d'identifier rapidement le record. Sa définition si vous préférez. Le "record header" contient les informations suivantes :
  • Le formID du record (qui est unique pour chacun d'entre eux),
  • Son "type" (j'en reparle juste après), que l'on apelle signature
  • Sa taille
  • Quelques autres informations qui servent à identifier la façon dont a été enregistré le record
A noter que le "record header" n'est pas stocké en tant que tel dans le fichier du jeu. C'est simplement la façon de désigner toutes les informations d'un record autres que ses fields (qui eux, sont stockés dans un tableau de fields). Voir plus loin pour ce qu'est un field.


Les signatures

Oui, les records ont des signatures. Non, ils ne signent pas de chèques. La signature d'un record, c'est ce qui va définir son "type". C'est à dire est-ce que le record désigne un pnj, une arme, une quête, etc...
La signature d'un record est désignée par 4 lettres en majuscules. Il s'agit le plus souvent des 4 premières lettres correspondant au nom anglais du type dont il s'agit. Par exemple, la signature pour les armes et WEAP, weapon signifiant arme en anglais.

Et puis comme avoir une signature c'est cool, eh bien il n'y a pas que les records qui en ont... eh oui, même si les records sont le cœur du contenu d'un plugin, il existe deux autres types d'éléments : Les "groups" / "sub-groups", et les "fields". Comme vous vous en doutez, les groups "contiennent" des records, tandis que les records "contiennent" à leur tour des fields.

Les fields

Les fields ("champ" en français) sont les éléments qui sont enregistrés dans un record. Ils ont également leur propre signature. Le meilleur exemple de field et l'EditorID d'un record. L'EditorID (signature EDID) correspond au nom utilisé dans le CK du record (ce qui est beaucoup plus utile que le "vrai" nom du record quand vous moddez). Le field EDID existe pour TOUS les types de records qui existent. Et c'est le seul point commun... le reste des fields référencés par un record dépend de son type.

A notez que si vous lisez un jour le terme sub-record, il s'agit le plus souvent d'un abus de langage pour désigner un field, voir une partie du field, si ce dernier contient une liste de différents éléments.

Les fields peuvent contenir différents types d'information. L'EDID contient un string (une chaîne de caractère), qui défini le nom de l'editor ID. Un field peut également contenir un "flag" (un élément prédéfini, les fields ne contenant qu'un flag correspondent le plus souvent aux checkbox dans le CK), un nombre entier ou réel, ou bien une référence à un autre record (par exemple, une arme enchantée est un record de type WEAP, avec un field EITM qui désigne le record ENCH correspondant à son enchantement).
Ou encore une liste contenant un mix de tout ça... (oui, ça devient le bordel ^^)

Un point important, les strings peuvent avoir plusieurs rôles, selon le field auquel elle sont associées. L'EDID contient une string toute simple. En revanche, un field DESC, contenant la description d'un objet, peut contenir du texte spécial utilisé pour la mise en forme, ou une balise du style <ChoseSpecial> ou bien <Machin=Truc> qui va permettre de contenir du texte "dynamique" (par exemple, le nom d'un PNJ qui dépend du contexte, ou la valeur d'un variable globale)

Et enfin, même si c'est encore plus à part, c'est extrêmement important : Un string peut désigner le chemin d'accès (path) à une ressources, typiquement un meshe pour le field MODL présent dans la plupart des records correspondant à des objets qui peuvent "apparaître" dans le monde.


Les groups

Comme on peu s'en douter, les groups sont... des groupes ^^ il s'agit en fait de collection de records, c'est à dire des éléments qui vont servir à catégoriser et lister les différents records. Il n'existe qu'un seul "vrai" type de group : ceux avec la signature GRUP. Un group contient par exemple la liste des armes du jeu (c'est à dire la liste des records ayant la signature WEAP). Par contre, il existe des sous-groupes...

Ma compréhension des sub-groups à l'heure actuelle est encore un peu juste pour faire une explication exacte, mais voilà ce qu'on peu en dire :

Un sous-groupe se comporte un peu comme un field, dans le sens ou il "appartient" à un record. En revanche, il ne contient pas une information, mais comme son grand frère, une liste de nouveaux records. C'est très différents des fields qui référencent d'autres records, car les records présents dans un sous-group n'existent que dans ce sous-groupe.

On trouve des sous-groupes dans les CELL et les WRLD : Il s'agit des records définissant des zones de jeu (respectivement, les "cellules", c'est à dire les pièces intérieures, et les "worldspaces", c'est à dire les zones extérieures, la plus grosse étant Tamriel et les plus petites sont par exemple les cités ou le cairn des âmes). Ces sous-groupes listent l'intégralité des records qui sont placés dans la pièce/zone.

Les records contenu dans ces sous-groupes sont un peu différents des autres, étant donné qu'il s'agit essentiellement de références. Ce sont des records qui correspondent aux objets que vous ajoutez dans les cellules depuis le CK, ils référencent donc systématiquement un objet "de base" .Par exemple, un tel record désignant un troll placé dans une cellule aura un field NAME (pas super intuitive cette signature là...) avec pour valeur le record correspondant au troll de base (qui lui est un record à la signature NPC_). Les autres fields définiront sa position dans la cellule, et les éventuelles modifs apportées.
Ces sous-groupes contiennent également les records correspondant aux navmeshes (NAVM) qui contiennent les informations pour que l'IA des NPC sachent ou elle a le droit de marcher ou non, et dans le cas des worldspaces, des records correspondant au landscape (LAND) qui représentent les modifications apportées au terrain.

On trouve également des sous-groupes dans les DIAL, c'est à dire les dialogues, qui références les différentes INFO (aka les "phrases"). Si vous avez déjà édité/créé des dialogues, vous savez de quoi je parle, sinon on va mettre ça de coté, l'architecture des dialogues est quelque chose qui doit être édité exclusivement via le CK, et pas besoin de comprendre tout ça pour l'utiliser ^^

A noter que si vous entendez parler de sub-records, il se peut également que l'on parle également de ces records appartenant à un sous-groupe, et non pas des fields comme je le signalais au paragraphe précédent (d'ou l'intérêt d'éviter cet abus de langage quand faire ce peu).


Et les mods dans tout ça ?

Comme vous l'aurez surement compris si vous avez tout lu, on peut donc résumer qu'un mod avec un plugin (fichier .esp ou .esm) contient des records, qui eux-mêmes contiennent des fields, et sont triés par groups.

De la même façon que les records qui ont un record header, le plugin contient également quelques données qui permettent de l'identifier. C'est le File Header. Et en fait... eh bien c'est un record aussi, avec ses propres fields, et tout un tas de trucs que personne n'a jamais réussi à savoir ce que c'était. On y retrouve aussi le nom de l'auteur, et la liste de ses masters.

En parlant de masters... si on commençait un peu à parler de compatibilité et de tout ce qui vas avec ?


On a vu au début que les records avaient un FormID unique, constitué de 8 charactères hexadécimal. Il y a donc une limite au nombre maximum de records que le jeu peut accepter : FFFFFF, soit plus ou moins... 4,3 milliards de record. Ça va, on a de la marge. Oui mais non... vous avez déjà eu l'impression que tous les records du jeux de base avaient un formID qui correspondait à 00 ? Alors que pour ceux qui appartiennent à un mod, les deux premiers caractères correspondent à la position du mod dans le load order ? Et.. puisque le jeu de base est en fait skyrim.esm, qui a la position 00 dans le load order, les deux premiers caractères seraient en fait complètement liés au load order ?

Eh bien oui ! Bravo arnaud ! Afin d'assurer la compatibilité avec les mods (ou plutôt, avec ses DLCs, et surtout pour pouvoir faire des mises à jour sans avoir à triffouiller le jeu d'origine), Beteshda a en fait limité le nombre de records possibles par plugins à FFFFFF au lieu de FFFFFFFF, soit seulement 16 millions. Ça en fait déjà beaucoup moins, même si ça reste plus qu'assez. Parceque bon, si deux records qui n'avaient rien à voir avaient le même formID dans deux plugins différents (disons, Balgruuf dans skyrim.esm, et un objet dans un mod traduit par sylom dans l'autre), on pourrait avoir des trucs sacrément bizarre... vous vous imaginez débarquer à Fort-Dragon et vous retrouver nez à nez avec un bocal à cerveau ?

Les formIDs ne peuvent donc être attribuées que dans un espace confiné... "MAIS", car il y a un "mais", c'est possible qu'en fait, NON. C'est toute la magie des "masters". Référencer un Master dans un plugin, ça veut revient à lui dire "en fait, t'as aussi le droit d'utiliser des formID qui correspondent à cet autre plugin".

Oui mais bon, dans ce cas on a toujours le même risque... sauf si on interdit à notre plugin de faire ce qu'il veut, et qu'on l'autorise uniquement à modifier des records déjà existant. Et là, tout va bien : On peut modifier un mod depuis un autre mod, ce qui permet de créer un patch. Encore mieux, il est possible d'indiquer dans les fields des records correspondant à notre mod des références à des records appartenant au master. Classe internationale !


Les problèmes d'override

Bon, on a réussi à faire un peu de magie en mettant un master à notre mod... Mais alors, si deux mods ont le même master, et changent les mêmes records, il se passent quoi ?

Eh bien il y en a un qui écrase l'autre, tout simplement. Le monde des records est un monde bien organisé, les priorité est donc donnée au mod qui est placé avec la plus haute priorité dans le load order.
Le point important à bien comprendre, c'est que c'est le record complet qui est écrasé, ça ne marche pas field par field. Donc si un mod modifie une arme pour changer ses statistiques (field DATA) et que l'autre change le son qu'elle fait quand on la dégaine (field NAM9), un seul des deux changements sera conservés, car les deux appartiennent aux même record. Pour avoir les deux changements, il faut créer un patch de compatibilité, qui modifiera une troisième fois ce record, cette fois en incorporant les changements faits par les deux mods.

Il faut savoir que les groups/sub-groups n'ont pas se souci, donc si deux mods ajoutent des objets différents dans la même cellule, vous aurez les objets en provenance des deux mods. Par contre, ce n'est valable que pour le sous-groupe, le reste des fields associés à la cell sera aux couleurs du plugin ayant la plus haute priorité. C'est à dire que si vous avez un mod qui change la couleur de la lumière ambiante dans votre cellule (partie du record XCLL), et qu'un autre plugin vient après dans le load order, juste pour ajouter une épée dans la cell... les changements apportés à la lumière apportés par le premier mod ne prendront pas effet !

Par chance, quelques records spéciaux sont en fait "mélangés" au lancement du jeu. Du coup, pas de problème de compatibilité avec ces derniers ! Mais il s'agit le plus souvent de records que vous ne serez de toute façon pas amenés à éditer à éditer vous même, ils le sont automatiquement quand éditez d'autres trucs dans le CK.
On dit que ces records sont "merged at runtime" (comprendre : fusionnés au lancement). Une liste est dispo ici : http://afkmods.iguanadons.net/index.php ... t-runtime/



Ce sera tout pour le moment, je suis claqué ^^ déso, pas le courage de m'occuper complètement de la mise en forme là tout de suite. Idem pour l'orthographe.


Références importantes :
http://www.uesp.net/wiki/Tes5Mod:Mod_File_Format
http://forum.step-project.com/topic/821 ... /?p=129949
Modifié en dernier par Kesta le 02 oct. 2015, 23:25, modifié 1 fois.
Faites un feu à un homme, il aura chaud un jour.
Mettez le feu à un homme, il aura chaud jusqu'à la fin de sa vie.

Terry Pratchett
Répondre

Retourner vers « Tutoriels et conseils de réalisation »