Création d’un ruleset FG – Partie 1 – Les bases

Organisation des fichiers du ruleset

Renommez dans un dossier votre fichier « CoreRPG.pak » en « CoreRPG.zip », décompressez-le, et nous allons le parcourir rapidement. 

Base.xml

Les rulesets sont composés d’un fichier base.xml, qui va référencer dans l’ordre tous les fichiers XML supplémentaires nécessaires à son bon fonctionnement, ainsi que les scripts Lua, les images graphiques (PNG, JPG), polices (TTF, FGF (plus nécessaires dans FGU)) et les tokens (PNG, JPG).

Tous les rulesets doivent avoir un fichier base.xml à la racine. En ouvrant avec Notepad++ ou VSC le fichier base.xml, vous verrez qu’il est composé des balises suivantes : 

Le fichier base.xml est composé des balises suivantes :

  • La balise root, qu’on retrouvera dans tous les fichiers XML et qui ici définit le numéro de version, de release et l’icône du ruleset (« logo.png », c’est cette image qu’il va falloir remplacer par le logo de celui que vous codez)
<root version="3.0" release="4" logo="logo.png">
  • Entre des balises « description », des éléments descriptifs (pas besoin de décrire je suppose)
    <!-- Attributes -->
    <description>
        <text>Core RPG</text>
        <author>SmiteWorks USA, LLC</author>
        <website>https://www.fantasygrounds.com</website>
    </description>
  • Puis des fichiers inclus qui vont composer les éléments du rulesets. Vous noterez au tout début l’inclusion d’abord de « gamelements.xml », des éléments graphiques, des chaines de caractères (« strings »), des templates puis des scripts lua avant les différents éléments XML. Cela a un sens : ils sont mis dans l’ordre de chargement (vous savez quand vous attendez une plombe que tout soit chargé ;]). Nous reviendrons sur certains de ces fichiers plus tard.

Format des fichiers XML 

Des fichiers XML supplémentaires sont donc définis dans le ruleset ; et appelés en utilisant la balise enfant « includefile » avec un attribut « source » dont la valeur est définie par le chemin d’accès du fichier XML à partir du dossier racine. 

Format des scripts Lua 

Pour inclure du lua (et donc de l’automatisation fine), 2 méthodes : 

  • Les fichiers Lua script peuvent être définis à l’aide de la balise enfant « script ». Si l’attribut « file » est spécifié, le chemin complet du fichier script doit être indiqué. Si la balise script est définie comme un enfant de l’élément « root » d’un fichier XML, alors elle est considérée comme un script « global » et nécessite un attribut « name ». Par exemple, dans le dossier fichier « campaign/campaign_chars.xml » à la ligne 38, dans l’élément « cahrselect_host » (relatif à la sélection des PJ pour les joueurs), un script est inclus pour appliquer des automatisations : 
<script file="campaign/scripts/charselect_host_list.lua" />
  • Le code de script Lua peut être inclus entre les balises de script (c’est-à-dire un bloc directement inclus dans les fichiers XML), ou un fichier de script peut être spécifié à l’aide d’un attribut « file ». Les balises de script peuvent également être définies pour une windowclass, un modèle ou une définition de contrôle de fenêtre au sein d’une classe de fenêtre. Voici un exemple simple, la création d’un dés customl en utilisant le template « customdie » dans le fichier « gamelements.xml » :
   <customdie name="d3">
        <model>d6</model>
        <menuicon>customdice</menuicon>
        <script>
            function onValue(result)
                return math.ceil(result/2);
            end
        </script>
    </customdie>

Un peu de graphisme

FG prend en charge la plupart des formats de fichiers d’images graphiques courants, mais PNG est le plus couramment utilisé, en raison du besoin de transparence que doit supporter l’actif graphique.

Les balises suivantes définissent les actifs graphiques : font, framedef et icon. Pour des exemples, c’est dans « graphics/ » et « strings ».

Tokens

Tous les fichiers graphiques qui sont inclus dans le sous-dossier « tokens » d’un ensemble de règles sont automatiquement ajoutés au sac de jetons GM en tant qu’actifs de jetons avec la même structure de dossiers que celle du sous-dossier « tokens ».

Normalisation des emplacements 

A la racine, vous trouverez les fichiers base.xml, license.html et logo.png, ainsi qu’un fichier gameelements.xml pour les paramètres globaux et les définitions d’assets et de dés. Dans le fichier « gamelements.xml » de CoreRPG, vous verrez qu’il y a beaucoup de type de dés custom défini, que vous pouvez utiliser via le chat, mais que vous pouvez également appeler dans les fiches de persos (on en parlera au prochain « chapitre ») 

Ensuite, vous allez trouver des sous-dossiers pour organiser les différents éléments du rulesets dans l’interface de fantasy grounds :

  • Campaign : Templates et fenêtres pour les “objets” relatifs à la campagne. Typiquement, c’est là qu’on va retrouver les fiches pour les PJs, les PNJs, les items, etc
  • Common : Les templates qui vont être partagés entre tous les éléments
  • Ct : Tout ce qui est relatif au combat tracker. Notez la présence de fichiers différenciés pour le combat tracker côté serveur (ct_host.xml) et côté client (ct_client.xml)
  • Desktop : tout ce qui va être relatif aux éléments du « bureau » de l’interface (la tour, le panel de modification, les dés, le chat, la liste des PJ etc)
  • Graphics : Tout ce qui a trait au graphisme, divisés en sous dossiers par types (buttons, decals, fonts, frames, icons, portraits, radial, sidebar, tabs et toolbar)
  • Ps : Tout ce qui est relatif au party sheet 
  • Ref : Templates et objets relatifs au manuel (ce que vous trouverez typiquement dans la partie « library »)
  • Scripts : Les scripts globaux. Grossièrement toute la partie « automatisation » générale du ruleset se trouvera ici : les jets de dés globaux et identifiables, le traitement des attributs, etc. On verra qu’une facilité est de créer des sortes d’objets relatifs à chaque élément du ruleset afin de pouvoir y faire globalement appel dans les éléments qui le composent accessibles via l’interface graphique. Par exemple on créé une classe « AttributeManager », on lui assigne des fonctions, et dans un script à portée locale, on va pouvoir faire appel à ces classes globales quand on veut manipuler les attributs (que ce soit en lecture ou en écriture). 
  • Strings : Les chaînes de caractères qui composent le ruleset. 
  • Tokens : bon c’est explicite, les tokens 
  • Utility : Templates et fenêtrage des éléments utilitaires. On y trouvera pèle-mêle le calendrier, la section modificateur, la fenêtre des effets préprogrammés etc etc

S’il existe des fichiers de script liés à des éléments de ces dossiers, un sous-dossier appelé scripts est généralement inclus dans chacun des sous-dossiers ci-dessus. Par exemple, une combobox (une liste quoi déroulante quoi) relative aux items sera placée dans « campaign/scripts/combobox_items.lua ». En effet, sa portée est locale, le script sera probablement appelé dans le fichier XML relatif aux items, et donc afin de bien différencier rapidement et à l’œil nu les éléments, on devrait respecter cette structure afin de rendre nos créations lisibles par tous, et surtout par ceux qui veulent les améliorer 😀

Assets graphiques rapidos

Pour les icones, boutons, strings, polices, trucs comme ça, leur nature est assez explicite, je vais donc faire l’impasse.

Frame

Les frames (cadres en français) sont des éléments graphiques qui dessinent une image de fond rectangulaire. Ils sont généralement utilisés comme graphiques d’arrière-plan de fenêtre et de contrôle qui sont capables de s’adapter à la taille de l’élément.

Les frames sont construits à partir de sections rectangulaires qui comprennent les coins, les bords et le centre du cadre. Ce type d’asset graphique est divisé en 9 tranches.

Les frame sont définis à l’aide de la balise « framedef », qui spécifie l’image à utiliser et l’emplacement des sections sur ce cadre. 

Chaque définition de section comprend quatre nombres, séparés par des virgules. Les nombres sont mesurés en pixels et leur signification est :

  • Le décalage horizontal en pixels, basé sur le zéro, du coin supérieur gauche de la section
  • Le décalage vertical de zéro pixel du coin supérieur gauche de la section
  • La largeur de la section
  • La hauteur de la section

Si certaines sections sont omises, elles sont supposées être vides. Les sections vides sont ignorées lors de la construction de cadres. De plus, les sections peuvent également être définies à l’aide de la balise offset où les décalages gauche, supérieur, droit et inférieur sont appliqués automatiquement au graphique du cadre pour créer les sections.

Vous allez vite trouver ça relou 😀

Voici un exemple de frame, les onglets : 

    <framedef name="tabs">
        <bitmap file="graphics/tabs/tabs.png" />
        <topleft rect="0,0,18,73" />
        <left rect="0,73,18,335" />
        <bottomleft rect="0,408,18,86" />
    </framedef>

Ne vous en faites pas, on en fait peu en fait, car il y a déjà des modèles définis et utilisables simplement dans le fichier « graphics/graphic_frames.xml », qu’on va pouvoir utiliser si on a besoin de construire une fenêtre ou un élément dans une déjà existante. Mais bon c’est bien de voir comment c’est foutu.

Les dés

Les ressources « dés » sont utilisées par le système pour manipuler les dés 3D sur le bureau, et pour générer des jets de dés personnalisés (avec une formule généralement).

Dés intégrés

Il existe sept types de dés 3D intégrés de base :

  • d4 = dé à quatre faces
  • d6 = dé à six faces
  • d8 = dé à huit faces
  • d10 = dé à dix faces
  • d12 = dé à douze faces
  • d20 = dé à vingt faces
  • dF = dé FATE, qui renvoie des valeurs de -1, 0 ou 1 (c’est à prendre en compte pour le moment ou vous allez en manipuler)

Si l’un de ces dés est défini à l’aide de la balise « die », les modèles 3D de ces dés sont automatiquement ajoutés au bureau de la campagne lors du chargement dans le cadre de ce jeu de règles. Ce qui veut dire que vous pouvez vous passer de certains dés si votre ruleset n’en a pas besoin. Typiquement, pour COPS j’ai besoin de d10 et de d6, je vire les autres.

Chacun des dés utilisés doit être associé à un emplacement par défaut sur le bureau (balise « position »), ainsi qu’à une icône de ressource qui représente l’image affichée pour les résultats de lancement dans la fenêtre de discussion (balise « icon »). Ceci est fait avec la balise « die », par exemple pour le d4 dans « gameelements.xml » du CoreRPG : 

    <die name="d4">
        <icon>d4icon</icon>
        <position>370,-68</position>
    </die>

Dés personnalisés

Les dés personnalisés sont des types de dés basés sur l’un des dés intégrés, avec la possibilité d’attribuer des valeurs personnalisées au résultat du dé. Le dé intégré sur lequel le dé personnalisé est basé sera utilisé comme modèle 3D pour le lancement (désolé, les fans de DCC RPG). 

Les dés personnalisés n’apparaissent pas sur le bureau de campagne, et l’option de lancer le dé personnalisé se trouve dans le menu du clic droit du dé intégré associé.

Une fonction de script doit être associée à un dé personnalisé. La fonction de script reçoit le résultat du dé intégré lancé et peut appliquer des modifications au résultat avant qu’il ne soit transmis pour un traitement ultérieur.

L’exemple ci-dessous définit un d3 (dé à trois faces), générant une valeur de 1 à 3, en divisant le résultat d’un d6 par deux.

    <customdie name="d3">
        <model>d6</model>
        <menuicon>customdice</menuicon>
        <script>
            function onValue(result)
                return math.ceil(result/2);
            end
        </script>
    </customdie>

Dans la balise script, on voit une fonction lua évènementielle (puisqu’elle va intervenir au moment du résultat du lancement du dé intégré, et qu’elle est donc déclenchée par un évènement). 

Le d100 qui pue

Il existe un autre type de matrice 3D intégrée qui n’a pas besoin d’être défini, le d100 :

d100 = matrice de dixième de centile, renvoie une valeur de 00 à 90.

Le dé de dix centiles n’est pas placé sur le bureau comme les autres dés de base, mais une option d100 est automatiquement ajoutée comme menu de clic droit pour le dé de base d10 (si défini).  De plus, lorsqu’un dé de dix centiles est sélectionné, un d10 sera également ajouté à la liste des dés de base. Le d100 est toujours disponible, et n’a pas besoin d’être défini.

Les dés percentiles dans Fantasy Grounds ont une convention légèrement différente de celle de la plupart des RPG. Le dé d100 et le d10 sont toujours ajoutés ensemble. Ainsi, un 00 sur le dé d100, et un 10 sur le dé d10, donneront une valeur de 10 (00+10) ; et un 90 sur le dé d100 et un 10 sur le dé d10, donneront une valeur de 100 (90+10). 

Bref on aime ou pas mais du coup c’est vachement contre-intuitif quand on regarde les dés dans le chat et qu’on voit le résultat. Après on s’habitue, mais bon, ils se sont pas foulé.

Interface

Toute l’interface utilisateur  d’un ruleset est définie à l’aide de « windowclass ». Les fenêtres sont des instances spécifiques des objets XML « windowclass ». Elles se comportent comme des conteneurs pour les contrôles. Ces « contrôles » sont les unités individuelles de l’interface utilisateur qui mettent en œuvre des fonctionnalités, telles que les champs numériques, les barre de défilement et les icônes de statut.

Les fenêtres peuvent également être intégrées dans d’autres fenêtres à l’aide de contrôles de fenêtres conteneurs (objets XML « subwindow ») et de listes de fenêtres (objets XML « windowlist »). C’est ce qui permettra d’obtenir des éléments dynamiques (comme l’inventaire d’un PJ) et statiques (les onglets de votre fiche de perso, par exemple).

Toute l’interface graphique de FG est composée de « windowclass », dont le « layout » est spécifié par des décalages de pixels (partant du coin supérieur gauche de l’espace défini). 

Les fenêtres sont disposées par rapport à la table virtuelle FG, tandis que les « controls » sont disposées par rapport à l’instance de fenêtre qui les contient.

L’affichage du ruleset est défini à l’aide de « panels » et de la « frame » délimitant le bureau. 

Windowclass

L’apparence et les fonctionnalités de chaque fenêtre sont déterminées par une windowclass, soit un objet XML qui va permettre de définir comment va être construite la fenêtre. Les windowclass ne sont pas exclusives, et plusieurs fenêtres existantes peuvent partager la même « windowclass ».

On y énumère également les contrôles que contiennent les fenêtres qui seront créés par-dessus, et on peut y intégrer une balise script. 

L’exemple ci-dessous se trouve dans le fichier « common/template_combobox.xml » de CoreRPG :

   <windowclass name="comboxbox_item">
        <script file="common/scripts/combobox_item.lua" />
        <sheetdata>
            <hnc name="Order" />
            <hsc name="Value" />
 
            <simplestring name="Text">
                <anchored position="insidetop" height="20" />
                <readonly />
                <script>
                    function onClickDown()
                        return true;
                    end
 
                    function onClickRelease()
                        window.clicked();
                    end
                </script>
            </simplestring>
        </sheetdata>
    </windowclass>

On note qu’un script est intégré au fonctionnement de l’objet « combobox_item », puis que deux éléments de type « hnc » et « hsc » (pour « hidden number control » et « hidden string control ») sont intégrés dans un sous ensemble « sheetdata », qui contient les données proposées par la windowclass. 

Rassurez-vous tout ça est bien abscons, mais ça se décantera en codant. 

Fenêtrage

Toutes les fenêtre sont identifiées par une combinaison unique de deux paramètres : la windowclass, et le chemin d’accès à la base de données des fenêtres (on reviendra sur la base de données un peu plus tard).

Cette référence à la base de données permet d’ouvrir des fenêtres du même type dans des contextes différents (typiquement l’inventaire de PJ1 et l’inventaire de PJ2) sans perdre les données (puisqu’elles sont inscrites dans la base de données). 

Notez qu’on peut créer des fenêtres sans référence à la base données, amis qu’il faut bine comprendre qu’elles seront remises à zéro à chaque fermeture.

Certains contrôles sont également des éléments « fenêtre » si je puis dire :

  • Un contrôle de fenêtre conteneur (subwindow) contient une fenêtre unique,
  • un contrôle de liste de fenêtres (windowlist) peut contenir zéro ou plusieurs fenêtres. 

Ces fenêtres sont appelées fenêtres intégrées. Elles contiennent les mêmes définitions que les fenêtres de niveau supérieur, mais ne contiennent généralement pas de limites de taille.

Les fenêtres peuvent être créées à l’aide d’éléments « windowreferencecontrol » (des liens quoi), à partir d’objets du tableau de bord ou par script (quand vous générez une rencontre aléatoire par exemple, à partir d’une table). Les fenêtres incorporées sont automatiquement créées par l’élément « windowcontrol » de référence.

Dans les scripts, les fenêtres sont conceptualisées via les objets « windowinstance », qui peuvent être étendus en utilisant le bloc script de l’élément « windowclass ». 

Contrôles et section « Sheetdata »

Contrôles 

Les contrôles sont des éléments de l’interface utilisateur contenus dans les fenêtres, et sont les possibilités d’interaction réelles pour l’utilisateur. 

Il existe plusieurs types de contrôles : 

  • Contrôles de valeur :  contiennent une valeur d’un type spécifique : nombre, chaîne de caractères, texte formaté, jeu de dés, jeton, lien de fenêtre ou image. Il existe des types de contrôle spécifiques pour chaque type de valeur.
  • Contrôles utilitaires : fournissent des moyens d’organiser ou de naviguer dans l’interface. Par exemple : sous-fenêtre, liste de fenêtres, barre de défilement, défilement et boutons.
  • Contrôle de bouton : Peut être utilisé soit comme un contrôle de valeur numérique (en définissant plusieurs états, typiquement l’inspiration dans le ruleset 5e la meilleur édition je veux pas le savoir, en passant la valeur d’inspiration à 1), soit comme un contrôle à logique utilitaire (passer en fenêtre minimisée).
  • Contrôle générique : Contrôle de base qui ne peut spécifier qu’une icône.

De nouvelles fonctionnalités et définitions peuvent être définies pour les contrôles en étendant leur fonctionnement par le biais de scripts. 

On reparlera de tout ça dans une semaine avec la partie dédiée au scripting.

Sheetdata

Les contrôles sont définis dans la section « sheetdata » d’un élément XML « windowclass ».  Ils sont disposés et dessinés en commençant par l’entrée la plus haute dans la définition des données de la feuille. 

Cela signifie que lorsque l’on utilise des ancrages (voir ci-dessous), les contrôles faisant office d’ancrages doivent toujours être spécifiés en premier. Lorsque les zones de contrôle se chevauchent, celles définies plus tard seront dessinées en haut. Tous les contrôles doivent avoir une position. 

En plus des informations de positionnement, ils ont des balises supplémentaires partagées par tous les contrôles de fenêtre pour définir l’arrière-plan, les infobulles, etc.  On en parle plus la semaine prochaine, pour voir quoi faire avec les blocs scripts.

En effet, la plupart des types de contrôles personnalisés peuvent être créés en combinaison avec un bloc script et un template approprié. Un exemple de template s’appuyant sur un contrôle pour en créer un nouveau et en y assignant un script : 

     <template name="number">
        <numberfield>
            <noreset />
            <script file="common/scripts/number.lua" />
        </numberfield>
      </template>

Positionnement

Il existe deux méthodes de base pour définir la position d’une commande dans une fenêtre : 

  • La position de la commande peut être donnée sous forme de coordonnées de base en pixels. 
  • Ls bords du contrôle peuvent être ancrés pour suivre les bords d’un autre contrôle ou de la fenêtre elle-même.

Statique

Le format de base des coordonnées de position statique est constitué de quatre nombres entiers positifs, mesurés en pixels.

  • Coordonnée X (position horizontale du bord gauche)
  • Coordonnée Y (position verticale du bord supérieur)
  • Largeur du contrôle
  • Hauteur du contrôle

L’exemple suivant créerait un contrôle de 150 pixels de large et 200 pixels de haut, placé à 15 pixels du bord gauche de la fenêtre et à 30 pixels du haut.

 <bounds>15,30,150,200</bounds>

Une configuration un peu plus complexe implique des coordonnées négatives. L’un ou l’autre des quatre nombres peut être annulé, avec les résultats suivants, respectivement :

  • La coordonnée X du bord gauche du contrôle est calculée à partir du bord droit de la fenêtre
  • La coordonnée Y du bord supérieur du contrôle est calculée à partir du bord inférieur de la fenêtre
  • La largeur du contrôle est automatiquement ajustée de manière à ce que le bord droit du contrôle corresponde au nombre de pixels spécifié à partir du bord droit de la fenêtre
  • La hauteur du contrôle est automatiquement ajustée de manière à ce que le bord inférieur du contrôle corresponde au nombre de pixels spécifié à partir du bord inférieur de la fenêtre

L’exemple suivant crée un contrôle dont le bord gauche est à 15 pixels du bord gauche de la fenêtre, et le bord droit à 15 pixels du bord droit de la fenêtre. La largeur serait égale à la largeur de la fenêtre moins 30 pixels. Le bord supérieur serait à 40 pixels du bas de la fenêtre. La hauteur du contrôle serait de 25 pixels, car le bord inférieur serait calculé à 15 pixels du bas de la fenêtre.

 <limites>15,-40,-15,-15</limites>

Ancrage

Lorsque l’on utilise le schéma de positionnement ancré, les bords de la commande sont liés à d’autres commandes de la fenêtre ou aux bords de la fenêtre. La largeur et la hauteur des contrôles peuvent être explicitement spécifiées ou calculées à partir des bords. 

En raison de la nature verbeuse des définitions d’ancrage, une notation sténographique définissant certaines des configurations les plus courantes est fournie à titre de commodité.

Il est également possible d’omettre l’ancrage sur les bords opposés ou la définition de la largeur/hauteur, de dimensionner dynamiquement un contrôle en fonction de son contenu, comme un contrôle de chaîne de caractères s’agrandissant pour s’adapter au texte. 

Dans ce cas, il est souvent recommandé de n’omettre qu’un seul bord (généralement à droite ou en bas) pour obtenir les meilleurs résultats.

Pour définir les ancres, utilisez la balise « anchored ».

Les bords sont ancrés en spécifiant une balise emboîtée « gauche », « haut », « droite » ou « bas ». 

Chaque ancre de bord peut contenir trois enfants :

  • balise ou attribut « parent » : contient une valeur de chaîne identifiant le nom du contrôle auquel le bord est ancré. Si cette balise est omise ou la valeur vide, l’ancrage se fera sur les bords de la fenêtre.
  • balise ou attribut « anchor » : Identifie le bord de la cible à partir duquel la position est calculée. Si cette balise est omise, le bord correspondant sera utilisé (c’est-à-dire les ancres gauches au bord gauche du parent)
  • balise ou attribut « offset » : Contient une valeur numérique par laquelle le bord est ajusté après les calculs d’ancrage. Une valeur positive indique un décalage vers la droite ou vers le bas, une valeur négative vers la gauche ou vers le haut.
  • Une largeur ou une hauteur explicite peut être définie pour un contrôle ancré en spécifiant des attributs « width » et/ou « height » pour la balise « anchored », ou en définissant une balise enfant « size » avec des enfants ou des attributs « width » et/ou « height ».

Il existe également une construction spéciale permettant d’empiler un nombre quelconque de contrôles sur un contrôle d’ancrage, de sorte que tous les contrôles ancrés évitent les chevauchements. 

Pour ce faire, une quatrième balise ou attribut appelé « relation » peut être spécifié à l’intérieur des différentes balises d’ancrage.

Si la valeur de ce paramètre est « absolute » (la valeur par défaut), les contrôles sont placés comme décrit ci-dessus.  Une valeur de « relative » fera en sorte que le contrôle soit ancré à l’emplacement du dernier contrôle « relative » qui était ancré au contrôle parent. 

Le prochain contrôle « relative » successif recevra un emplacement ajusté en fonction du contrôle actuel. Une valeur de « current » fera en sorte que le contrôle soit ancré à l’emplacement du dernier contrôle « relative », comme pour le contrôle « relative ». Cette valeur n’ajustera cependant pas la position du prochain contrôle « relative » ou « current », et est utile pour créer des lignes ou des colonnes « empilées ».

Certains schémas d’ancrage peuvent également être mis en place en utilisant une notation sténographique. Pour utiliser la notation abrégée, trois balises sont placées sous la balise <anchored> :

  • balise ou attribut « to » : Indique le nom du contrôle auquel s’ancrer. Si elle est spécifiée, toutes les ancres spécifiques utiliseront cette valeur comme attribut parent à moins qu’elle ne soit remplacée.
  • balise ou attribut « position » : Définit la position par rapport au contrôle parent (« relative » ou « absolute »)
  • balise ou attribut « offset » : Contient deux nombres entiers, séparés par une virgule. Ils définissent respectivement le décalage horizontal et vertical appliqué au positionnement. Ces nombres sont traités de telle sorte qu’ils augmentent la distance entre les deux contrôles, de sorte que la direction réelle varie en fonction de la position. Pour les positions de bord (insidetop, above, left, etc.), un décalage positif rendra le contrôle ancré plus grand que la cible ancrée, alors qu’un décalage négatif le rendra plus petit.

La notation sténographique peut être combinée avec les ancres standard, les ancres standard ayant la priorité sur la forme sténographique. 

Je remets le petit schéma : 

Il est souhaitable de définir explicitement la largeur et/ou la hauteur, ou de spécifier un ancrage supplémentaire en utilisant le schéma d’ancrage standard.

Dans le fichier campaign/record_parcel.xml, voici comment est balisée la frame « frame_parcel » qui contient les éléments permettant de définir un trésor (parcel), et sa première colonne « # » :

            <frame_parcel name="coinframe">
                <anchored to="contentframe" width="165">
                    <top />
                    <left />
                    <bottom />
                </anchored>
            </frame_parcel>
            <label>
                <anchored to="coinframe" position="insidetopleft" offset="0,-5" width="55" />
                <static>#</static>
                <center />
            </label>

La balise “anchored” contient le nom du frame  (« contentframe ») auquel est ancré l’élément « frame_parcel »  nommé « coinframe », et sa largeur (165). Ensuite, on définit les bords haut, gauche et bas pour placer l’ancrage balises « top » « left » et « bottom ». 

En dessous de l’élément « label » est lui ancré à « coinframe », sa position est nommée «explicitement « insidetopleft », et on spécifie un offset de décalage (0 soit aucun pour le bord gauche, 5 pixel vers l’intérieur de la zone). 

Widgets

Les widgets sont des éléments graphiques qui peuvent être ajoutés à n’importe quel contrôle, pour mettre en œuvre des fonctionnalités personnalisées ou servir d’indicateurs. 

Ils ne sont pas directement définissables en XML et nécessitent une implémentation de script. 

Deux types de widgets sont disponibles : les widgets texte et les widgets bitmap.

  • Les widgets texte (textwidget) contiennent une chaîne de caractères et une police à utiliser pour afficher le texte. Pour les widgets qui contiennent une chaîne de caractères définissable par l’utilisateur, il est recommandé de fixer la largeur maximale autorisée. Le contenu du widget texte qui entraîne le dépassement de la largeur maximale est tronqué et précédé de trois points (« … »).
  • Les widgets bitmap (interface bitmapwidget) peuvent contenir des icônes graphiques.

Chaque widget peut éventuellement être associé à un asset frame. Le cadre est dessiné en tant qu’arrière-plan du widget, sous le contenu réel du widget.

On en reparlera dans la section sur le scripting

Panel

Les éléments qui apparaissent automatiquement sur la table lors du premier chargement d’une campagne sont mis en œuvre à l’aide de « panel »(panneaux). 

Un panneau est une référence à une classe de fenêtre et à des informations sur la disposition de la table.

Chaque panneau contient une fenêtre, toujours créée sans source de données. La « windowclass » utilisée pour le panneau ne doit pas contenir de contraintes de positionnement ou de taille. Par ailleurs, la fenêtre fonctionne de manière similaire aux fenêtres classiques et peut contenir toutes les mêmes fonctionnalités. 

Les panneaux sont positionnés par rapport au plateau de la table ou à d’autres panneaux de la même manière que les commandes sont disposées dans une fenêtre.

Les définitions des panneaux peuvent contenir un attribut de mode définissant s’ils sont créés en mode « host » (GM), « client » (joueur) ou « local » (gestion des personnages). Ces modes peuvent être combinés en donnant plusieurs valeurs à l’attribut, séparés par une virgule (modes= « host,client »). 

L’omission de l’attribut « mode » entraînera la création du panneau dans tous les modes. Des panneaux de même nom avec des spécifications de mode différentes peuvent contenir des contenus différents.

Par exemple, le panel « modifierstack » (le truc avec les modificateurs), dont vous trouverez le code dans « desktop/desktop_panels.xml ». Il est attaché au bas du bureau, de la gauche de 5 pixel, décalé du bas de 100 pixels et ayant une hauteur de 64 pixels pour une largeur de 57 pixels, et visible par les PJ et le GM, mais pas dans la gestion local des personnages : 

    <panel name="modifierstack" modes="host,client">
        <class>modifierstack</class>
        <bounds>5,-100,64,57</bounds>
        <dynamic />
        <locked />
    </panel>

Base de données 

Introduction

La base de données de la campagne est l’endroit où sont stockées toutes les informations de la concernant les personnages, les aventures, les monstres et les autres PNJ. Elle est sauvegardée lorsqu’une session est fermée et chargée lorsqu’une session est démarrée. 

Chaque campagne a sa propre base de données. Les données sont physiquement stockées sous forme XML dans le fichier « db.xml » du dossier de la campagne.

Structure du fichier

C’est dépendant de la campagne, mais typiquement pour CoreRPG, on a les éléments suivants : 

  • charsheet = données PJ
  • notes = données des notes
  • encounter = Données des scénario
  • storytemplate = Données des modèles de scénario
  • image = Données d’image et de carte
  • quest = Données de quête
  • npc = données des NPC
  • battle = données de rencontre (c’est-à-dire groupes de PNJ)
  • battlerandom = Données de rencontre aléatoire
  • item = Données des items (équipement)
  • treasureparcels = Données sur les trésors (groupes d’items en gros)
  • tables = Données des tables
  • modifiers= données du panneau des modificateurs
  • effects = données sur les effets
  • library = Données de la bibliothèque 

En outre, la norme pour les modules CoreRPG consiste à spécifier le chemin de « référence » en lecture seule. Ainsi, les chemins des objets de données (record dans leur jargon) CoreRPG standard pour les données en lecture seule sont :

  • reference.encounters = données du scénario
  • reference.storytemplates = Données des templates de scénario
  • reference.quests = Données des quêtes
  • reference.images = Données d’images et de cartes
  • reference.npcs = données des PNJ
  • reference.battles = données des rencontres (c’est-à-dire groupes de PNJ)
  • reference.battlerandoms = Données des rencontres aléatoire
  • reference.items = Données des items
  • reference.treasureparcels = Données des trésors (parcels)
  • reference.tables = Données des tables

Enfin, il existe des chemins standard pour stocker les données des outils :

  • combattracker = données du combattracker
  • partysheet = Données du partysheet
  • calendrier = Données du calendrier
  • export = Données d’exportation
  • options = Données sur les options

Interaction avec l’interface

Un chemin d’accès à la base de données peut être attribué à chaque fenêtre. De nombreuses « windowclass » utilisées pour construire des fenêtres dans un ensemble de règles supposent qu’un chemin de base de données leur est attribué lorsqu’elles sont ouvertes (comme les fenêtre de PNJ, par exemples). 

Tous les contrôles de fenêtre dans une fenêtre peuvent être liés ou non à une base de données. S’ils le sont et font partie d’une fenêtre qui a un chemin de base de données, ils s’attacheront aux nœuds de base de données enfants avec le même nom que le contrôle sous le chemin de base de données de la fenêtre. 

Si le nœud de base de données enfant n’existe pas, alors le contrôle de fenêtre lié à la base de données créera un nouveau nœud de base de données enfant avec le même nom. 

En gros si j’ai charactersheet-0001 (mon premier PJ, et que je colle un contrôle « name, j’aurai la création d’un nœud « charactersheet-0001.name »

Les types de contrôle de fenêtre existent pour tous les types de données de base de données correspondants (chaîne, nombre, texte formaté, dés, image, jeton, référence de fenêtre)

Parcours de la base de données

Lorsque l’on référence un nœud de base de données spécifique au sein d’un ensemble de règles, celui-ci utilise une chaîne de chemin d’accès à la base de données (parfois appelée chaîne d’identification de nœud de base de données dans les documents API).

Selon le contexte dans lequel les chemins de la base de données sont utilisés, ils peuvent être absolus ou relatifs : 

  • Les contextes de chemins de base de données absolus recherchent le nœud spécifié sous la racine de la base de données. Les utilisations les plus courantes des contextes de chemins de base de données absolus sont les chemins de base de données spécifiés pour les classes de fenêtres et les contrôles de listes de fenêtres. 
  • Les contextes de chemin de base de données relatif recherchent le chemin relatif comme un sous-chemin sous le chemin de base de données actuel (qui dépend du contexte). Un exemple courant de contexte de chemin de base de données relatif est le chemin de base de données pour un contrôle de fenêtre, qui essaie de trouver le noeud nommé sous le chemin de base de données de la fenêtre.

Les contextes de chemin absolu peuvent avoir un chemin de base de données sous lequel une recherche de chemin de base de données relatif pourrait être effectuée. Dans ce cas, un point au début de l’identificateur provoquera une recherche relative à la place. Un exemple de cela est le chemin de la base de données de contrôle de la liste des fenêtres. Si un point est inclus au début d’un contexte de chemin de base de données relatif, il sera le même que s’il était défini sans.

L’ajout d’autres caractères point après le premier au début de l’identificateur entraînera un nombre correspondant de pas vers le haut dans l’arborescence. Les étapes plus profondes de l’arborescence peuvent être spécifiées en séparant les noms de nœuds successifs par le caractère point.

Par exemple, dans le fichier « campaign/record_encounter.xml », dans la windowclass « battle_npcmaplimnk », un bloc script est défini afin d’exécuter une action évènementielle quand on commence à glisser le token du PNJ vers une carte : 

            <tokencontrol name="token">
                <bounds>2,2,24,24</bounds>
                <readonly />
                <script>
                    function onDragStart(draginfo)
                        local _,sRecord = DB.getValue(window.getDatabaseNode(), "...link");
                        local nSpace,_ = CombatManager.getNPCSpaceReach(DB.findNode(sRecord));
                        TokenManager.setDragTokenUnits(nSpace);
                    end
                    
                    function onDragEnd(draginfo)
                        TokenManager.endDragTokenWithUnits();
                        
                        local _,dropref = draginfo.getTokenData();
                        window.setLink(dropref);
                        return true;
                    end
                </script>
            </tokencontrol>

L’appel à la fonction DB.getValue() fait appel à un chemin pour retrouver le lien du pnj en passant en arguments à la fonction window.getDatabaseNode() (qui retourne l’endroit de l’arborescence de la base de données de l’objet courant) et y adjoint la chaîne de caractère « …link », qui remonte dans l’arborescence et de deux crans (probablement de la valeur npclist.id-0001.token à npclist.id-0001) avant de redescendre vers l’élément « link » (donc ici npclist.id-0001.link). Pour vous montrer la tête du truc, voici une rencontre dans la bdd : 

                <npclist>
                    <id-00004>
                        <count type="number">1</count>
                        <link type="windowreference">
                            <class>npc</class>
                            <recordname>npc.id-00058</recordname>
                        </link>
                        <maplink>
                            <id-00001>
                                <imageref type="windowreference">
                                    <class />
                                    <recordname />
                                </imageref>
                                <imagex type="number">0</imagex>
                                <imagey type="number">0</imagey>
                            </id-00001>
                        </maplink>
                        <name type="string">Baston de fifou</name>
                        <token type="token">campaign/images/DMG/Tokens/lol.png</token>
                    </id-00004>
                </npclist>

En jaune poussin, les éléments auquel on a accédé durant l’exécution du code lors du début du glissage du NPC de mon token.

Base de données d’un module 

Pour différencier la base de données de la campagne des bases de données de modules, une syntaxe spéciale pour les chemins d’accès à la base de données est utilisée. Tout d’abord, les chaînes de chemin de la base de données des modules sont formées exactement comme ci-dessus (en spécifiant le chemin dans la base de données des modules). Ensuite, le chemin est préfixé par le caractère at (« @ ») et suivi du nom complet du module.

Exemples  

  • charsheet.id-00005.inventorylist.id-00001.name : Chemin absolu, Pointe vers le nom (name) du premier item (id-00001) dans l’inventaire (inventorylist) de la fiche du PJ n°5 (charsheet.id-00005). Notez que ce PJ est le 5ème PJ créé et pas le PJ du 5ème joueur à table.
  • ac.totals.general : Chemin relatif. Nombre. Indique le score total général de la CA à partir d’un nœud de base de données de feuilles PJ. Le chemin absolu serait « charsheet.id-000N.ac.totals.general ».
  • .inventorylist : Chemin absolu, avec priorité relative. De type Windowlist (d’où la dénomination, qui doit être clair pour manipuler le code (mais qui est « arbitraire »). Pointe vers le nœud de la base de données d’inventaire à partir d’un nœud de base de données de feuille PJ, par exemple. Pour accéder à cette « Windowlist », le chemin absolu serait « charsheet.id-000N.ac.inventorylist ».
  • …spellset.set1.levels.level0.dc : Chemin relatif. Nombre. Étant donné le nœud de base de données actuel, remontez de deux niveaux, puis suivez le sous-chemin « spellset.set1.levels.level0.dc ».
  • reference.classes.fighter@3.5E Ruleset : Cheminement absolu du module. Pointe vers l’entrée de la classe de guerrier dans la base de données du module « 3.5E Basic Rules ».

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Prêt pour partir à l' aventure ?

Proposer ou Trouver une partie sans difficulté

Handcrafted with for Gamers © 2021  •  Armadon Theme by Themosaurus. All related content, characters, names and materials that could be part of an existing work, are the exclusive property of their authors.