Outils pour utilisateurs

Outils du site


reg

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

reg [2026/10/06 11:23] – créée nanakireg [2026/10/06 11:28] (Version actuelle) – nanaki
Ligne 1: Ligne 1:
 +Les compétences sont organisées en 5 grandes branches, formant un véritable arbre de progression :
 +
 +• Magie (Sort)
 +• Corps à corps (CAC)
 +• Distance (DIS)
 +• Survie (SUR)
 +• Furtivité (FUR)
 +
 +Chaque compétence appartient à une branche et possède des caractéristiques spécifiques détaillées dans le tableau ci-dessous.
 +
 +—
 +
 +Lecture du tableau :
 +
 +• Race : Com (Commun), Elfes, Nains, Géants, HS, Olymp (Olympien)
 +
 +• Catégorie : correspond à la branche (Sort, CAC, Distance, Survie, Furtivité)
 +
 +• Nom : nom de la compétence
 +
 +• Coût : ressources nécessaires à l’activation (PM, PV, Mouvement). Le coût minimum est toujours minimum 1 pa, si c'est 0 pa c'est indiqué dans le cout.
 +
 +• Type :
 +
 +Technique (T)
 +Passif (P): ne demande pas de coût pour activation, s'active en fonction de la condition d'activation
 +Les Sorts
 +• Effet : description et puissance de la compétence
 +
 +• Portée : distance d’utilisation
 +
 +• Niveau : de 1 à 5 influence le coût ( voire plus bas)
 +augmente le seuil FM pour les sorts défensifs et de soin ( voir Combat partie sorts défensifs)
 +
 +—
 +
 +Règles générales :
 +
 +• Vous disposez d’un maximum de 15 points de compétences
 +
 +• Les passifs coûtent uniquement de l’or et ne nécessitent aucune activation
 +
 +• Coût en or selon le niveau :
 +
 +Niveau 1 : 50 pos
 +Niveau 2 : 100 pos
 +Niveau 3 : 200 pos
 +Niveau 4 : 300 pos
 +Niveau 5 : 300 pos
 +—
 +
 +Utilisation du tableau :
 +
 +Vous pouvez filtrer les compétences pour affiner votre recherche :
 +
 +• Par catégorie → afficher une branche spécifique
 +• Par effet → uniquement pour les sorts (offensif, défensif, malédiction)
 +• Par type → techniques ou passifs
 +
 +—
 +
 +Note d’affichage :
 +Le tableau s'affiche en entier sur les PC. Pour les mobiles, il y a la possibilité de scroller, ainsi que de changer le paramètre d'affichage. Sous Chrome et Edge, cliquer sur les trois points en haut à droite de l'écran puis Version ordinateur.
 +
 +—
 +
 +Les compétences barrés sont celles qu'on ne peut plus acheter , si vous les connaissiez avant la mise à jour, elles restent dans votre liste de compétences mais si vous l'oubliez, impossible de la racheter.
 +
 +Concernant les sorts, il y a un code couleur:
 +Offensif : fond et barre sur le coté gauche du tableau : rouge clair
 +Défensif et soin: fond et barre sur le coté gauche du tableau : vert clair
 +Malédiction: fond et barre sur le coté gauche du tableau : violet clair
 +
 +Attention, pour lancer un sort defensifs et sorts de soins. Il faut faire un jet minimum.
 +Voici le calcul:
 +
 +**Seuil minimal pour réussir les Bénédictions et sorts défensifs : 6 x (Niveau du sort +1).
 +**
 +
 +C'est à dire pour lancer un sort defensifs niveau 5 ( exemple virtuose), je dois faire un jet de 36 minimum.
 +
 +Voici la liste complète des compétences :
 +
 +
 +
 +
 +<html>
 +<head>
 +<meta charset="UTF-8">
 +<meta name="viewport" content="width=device-width, initial-scale=1.0">
 +
 +<title>Tableau de compétences</title>
 +
 +<style>
 +body {
 +    font-family: Arial, sans-serif;
 +    margin: 10px;
 +}
 +
 +.controls {
 +    margin-bottom: 10px;
 +    display: flex;
 +    flex-wrap: wrap;
 +    gap: 8px;
 +    align-items: center;
 +}
 +
 +.controls label {
 +    font-weight: bold;
 +}
 +
 +.controls select,
 +.controls input {
 +    padding: 5px;
 +}
 +
 +#points {
 +    font-weight: bold;
 +    font-size: 18px;
 +}
 +
 +#warning {
 +    margin: 8px 0;
 +    padding: 8px;
 +    background: #fff5cc;
 +    border: 1px solid #e6c84f;
 +    display: none;
 +}
 +
 +/* Tableau */
 +
 +.table-container {
 +    width: 100%;
 +    overflow-x: auto;
 +}
 +
 +table {
 +    border-collapse: collapse;
 +    width: 100%;
 +    font-size: 13px;
 +    table-layout: fixed;
 +}
 +
 +td,
 +th {
 +    border: 1px solid #ccc;
 +    padding: 5px;
 +    overflow: hidden;
 +    text-overflow: ellipsis;
 +    white-space: nowrap;
 +}
 +
 +th {
 +    background: #f2f2f2;
 +    cursor: pointer;
 +}
 +
 +/* tailles colonnes */
 +
 +th:nth-child(1) { width: 50px; }
 +th:nth-child(2) { width: 40px; }
 +th:nth-child(3) { width: 55px; }
 +th:nth-child(4) { width: 130px; }
 +th:nth-child(5) { width: 80px; }
 +th:nth-child(6) { width: 60px; }
 +th:nth-child(7) { width: 80px; }
 +th:nth-child(8) { width: 120px; }
 +th:nth-child(9) { width: 30px; }
 +
 +/* Texte multi-lignes */
 +
 +td:nth-child(4),
 +td:nth-child(7) {
 +    white-space: normal;
 +    word-break: break-word;
 +}
 +
 +/* Catégories */
 +
 +.sort {
 +    background: #fff5e5;
 +}
 +
 +.cac {
 +    background: #ffe5e5;
 +}
 +
 +.tir {
 +    background: #e5f0ff;
 +}
 +
 +.survie {
 +    background: #e5fff5;
 +}
 +
 +.furtivite {
 +    background: #f5e5ff;
 +}
 +
 +.Passif_Mana {
 +    background: #fffbe5;
 +}
 +
 +/* Effets */
 +
 +.offensif {
 +    border-left: 4px solid #ff4d4d;
 +}
 +
 +.defensif {
 +    border-left: 4px solid #4d79ff;
 +}
 +
 +.soin {
 +    border-left: 4px solid #4d79ff;
 +}
 +
 +.malediction {
 +    border-left: 4px solid #9933ff;
 +}
 +
 +/* Couleurs des sorts */
 +
 +.sort.offensif {
 +    background: #ffe5e5;
 +}
 +
 +.sort.defensif {
 +    background: #e5f0ff;
 +}
 +
 +.sort.malediction {
 +    background: #f3e5ff;
 +}
 +
 +/* Passifs */
 +
 +.P {
 +    background: #e5ffe5 !important;
 +}
 +
 +/* Compétence bloquée */
 +
 +tr.skill-locked {
 +    opacity: 0.45;
 +}
 +
 +tr.skill-locked td:first-child {
 +    position: relative;
 +}
 +
 +tr.skill-locked .skill {
 +    cursor: not-allowed;
 +}
 +
 +/* Compétences Mana répétables */
 +
 +.repeatable-cell {
 +    white-space: nowrap !important;
 +}
 +
 +.repeat-controls {
 +    display: inline-flex;
 +    align-items: center;
 +    gap: 3px;
 +}
 +
 +.repeat-count {
 +    min-width: 18px;
 +    display: inline-block;
 +    text-align: center;
 +    font-weight: bold;
 +}
 +
 +.repeat-btn {
 +    width: 20px;
 +    height: 20px;
 +    padding: 0;
 +    line-height: 18px;
 +    cursor: pointer;
 +    border: 1px solid #aaa;
 +    background: #eee;
 +    border-radius: 3px;
 +}
 +
 +.repeat-btn:hover {
 +    background: #ddd;
 +}
 +
 +.repeat-btn:disabled {
 +    opacity: 0.4;
 +    cursor: not-allowed;
 +}
 +
 +/* Sorts verrouillés par manque de capacité */
 +
 +tr.spell-locked {
 +    opacity: 0.45;
 +}
 +
 +.spell-capacity {
 +    font-size: 12px;
 +    margin-left: 5px;
 +}
 +
 +.reset-container {
 +    margin-bottom: 10px;
 +}
 +
 +#resetTable {
 +    padding: 6px 12px;
 +    cursor: pointer;
 +}
 +
 +/* Mobile */
 +
 +@media (max-width: 768px) {
 +    table {
 +        min-width: 950px;
 +    }
 +}
 +</style>
 +</head>
 +
 +<body>
 +
 +<div class="controls">
 +
 +    <span>
 +        Points utilisés :
 +        <span id="points">0</span> / 15
 +    </span>
 +
 +    <label for="search">Recherche :</label>
 +    <input
 +        type="text"
 +        id="search"
 +        placeholder="Rechercher..."
 +    >
 +
 +    <label for="filterCat">Arbre :</label>
 +    <select id="filterCat">
 +        <option value="all">Tous</option>
 +        <option value="sort">Sorts</option>
 +        <option value="cac">CAC</option>
 +        <option value="dis">Distance</option>
 +        <option value="survie">Survie</option>
 +        <option value="furtivite">Furtivité</option>
 +        <option value="mana">Mana</option>
 +    </select>
 +
 +    <label for="filterEffect">Effet :</label>
 +    <select id="filterEffect">
 +        <option value="all">Tous</option>
 +        <option value="offensif">Offensif</option>
 +        <option value="defensif">Défensif</option>
 +        <option value="soin">Soin</option>
 +        <option value="malediction">Malédiction</option>
 +    </select>
 +
 +    <label for="filterType">Type :</label>
 +    <select id="filterType">
 +        <option value="all">Tous</option>
 +        <option value="S">Sort</option>
 +        <option value="T">Technique</option>
 +        <option value="P">Passif</option>
 +    </select>
 +
 +</div>
 +
 +<div id="warning"></div>
 +
 +<div class="reset-container">
 +    <button id="resetTable" type="button">
 +        Réinitialiser
 +    </button>
 +</div>
 +
 +<div class="table-container">
 +
 +<table id="skills">
 +
 +<thead>
 +<tr>
 +    <th></th>
 +    <th onclick="sortTable(1)">Race</th>
 +    <th onclick="sortTable(2)">Catégorie</th>
 +    <th onclick="sortTable(3)">Nom</th>
 +    <th onclick="sortTable(4)">Coût</th>
 +    <th onclick="sortTable(5)">Type</th>
 +    <th onclick="sortTable(6)">Effet</th>
 +    <th onclick="sortTable(7)">Portée</th>
 +    <th onclick="sortTable(8)">Niv</th>
 +</tr>
 +</thead>
 +
 +<tbody>
 +
 +<!-- ===================================================== -->
 +<!-- ========================= MANA ====================== -->
 +<!-- ===================================================== -->
 +
 +<tr class="Passif_Mana P" data-cat="mana" data-type="P" data-niv="1"
 +    data-repeatable="true" data-repeat-name="Apprenti">
 +<td class="repeatable-cell">
 +    <div class="repeat-controls">
 +        <button class="repeat-btn minus" type="button">−</button>
 +        <span class="repeat-count">0</span>
 +        <button class="repeat-btn plus" type="button">+</button>
 +    </div>
 +</td>
 +<td>com</td><td>Mana</td><td>Apprenti</td><td>/</td><td>P</td>
 +<td>+3 sorts de niveau 1 par acquisition</td><td>/</td><td>1</td>
 +</tr>
 +
 +<tr class="Passif_Mana P" data-cat="mana" data-type="P" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Mana</td><td>Méditation arcanique</td><td>/</td><td>P</td>
 +<td>Ajoute RM/8 PM par action dépensée lors d'un Repos</td><td>/</td><td>1</td>
 +</tr>
 +
 +<tr class="Passif_Mana P" data-cat="mana" data-type="P" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Mana</td><td>Méditation somatique</td><td>/</td><td>P</td>
 +<td>Ajoute R/8 PM par action dépensée lors d'un Repos</td><td>/</td><td>1</td>
 +</tr>
 +
 +<tr class="Passif_Mana P" data-cat="mana" data-type="P" data-niv="2"
 +    data-repeatable="true" data-repeat-name="Disciple">
 +<td class="repeatable-cell">
 +    <div class="repeat-controls">
 +        <button class="repeat-btn minus" type="button">−</button>
 +        <span class="repeat-count">0</span>
 +        <button class="repeat-btn plus" type="button">+</button>
 +    </div>
 +</td>
 +<td>com</td><td>Mana</td><td>Disciple</td><td>/</td><td>P</td>
 +<td>+3 sorts de niveau 2 par acquisition</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="Passif_Mana P" data-cat="mana" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>Elfe</td><td>Mana</td><td>Pouvoir titanique</td><td>/</td><td>P</td>
 +<td>+1 pour toucher offensivement à la magie par effet sur lui</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="Passif_Mana P" data-cat="mana" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>Géant</td><td>Mana</td><td>Voie de l'Air</td><td>/</td><td>P</td>
 +<td>+6 pour toucher avec des Malédictions</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="Passif_Mana P" data-cat="mana" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>Nain</td><td>Mana</td><td>Récupération runique</td><td>/</td><td>P</td>
 +<td>Récupère en plus Pui/4 PM par action lors d'un Repos</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="Passif_Mana P" data-cat="mana" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>HS</td><td>Mana</td><td>Retrait</td><td>/</td><td>P</td>
 +<td>Réduit de 4 le seuil du jet de FM de distance</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="Passif_Mana P" data-cat="mana" data-type="P" data-niv="3"
 +    data-repeatable="true" data-repeat-name="Mage">
 +<td class="repeatable-cell">
 +    <div class="repeat-controls">
 +        <button class="repeat-btn minus" type="button">−</button>
 +        <span class="repeat-count">0</span>
 +        <button class="repeat-btn plus" type="button">+</button>
 +    </div>
 +</td>
 +<td>com</td><td>Mana</td><td>Mage</td><td>/</td><td>P</td>
 +<td>+3 sorts de niveau 3 par acquisition</td><td>/</td><td>3</td>
 +</tr>
 +
 +<tr class="Passif_Mana P" data-cat="mana" data-type="P" data-niv="4"
 +    data-repeatable="true" data-repeat-name="Grand Mage">
 +<td class="repeatable-cell">
 +    <div class="repeat-controls">
 +        <button class="repeat-btn minus" type="button">−</button>
 +        <span class="repeat-count">0</span>
 +        <button class="repeat-btn plus" type="button">+</button>
 +    </div>
 +</td>
 +<td>com</td><td>Mana</td><td>Grand Mage</td><td>/</td><td>P</td>
 +<td>+3 sorts de niveau 4 par acquisition</td><td>/</td><td>4</td>
 +</tr>
 +
 +<tr class="Passif_Mana P" data-cat="mana" data-type="P" data-niv="4"
 +    data-repeatable="true" data-repeat-name="Archimage">
 +<td class="repeatable-cell">
 +    <div class="repeat-controls">
 +        <button class="repeat-btn minus" type="button">−</button>
 +        <span class="repeat-count">0</span>
 +        <button class="repeat-btn plus" type="button">+</button>
 +    </div>
 +</td>
 +<td>com</td><td>Mana</td><td>Archimage</td><td>/</td><td>P</td>
 +<td>+2 sorts de niveau 5 par acquisition</td><td>/</td><td>4</td>
 +</tr>
 +
 +<tr class="Passif_Mana P" data-cat="mana" data-type="P" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Mana</td><td>Focus mental</td><td>/</td><td>P</td>
 +<td>Le personnage a l'avantage quand il lance un sort</td><td>/</td><td>4</td>
 +</tr>
 +
 +<!-- ===================================================== -->
 +<!-- ======================== SORTS ======================= -->
 +<!-- ===================================================== -->
 +
 +<!-- Niveau 1 -->
 +
 +<tr class="sort offensif"
 +    data-cat="sort"
 +    data-effect="offensif"
 +    data-type="S"
 +    data-niv="1">
 +<td><input type="checkbox" class="skill spell"></td>
 +<td>com</td><td>Sort</td><td>Arcane ajustée</td><td>6 PM</td><td>S</td>
 +<td>+3 dégâts, "Avantage" sur le lancer</td><td>min 2</td><td>1</td>
 +</tr>
 +
 +<tr class="sort offensif"
 +    data-cat="sort"
 +    data-effect="offensif"
 +    data-type="S"
 +    data-niv="1">
 +<td><input type="checkbox" class="skill spell"></td>
 +<td>com</td><td>Sort</td><td>Arcanes précises</td><td>6 PM</td><td>S</td>
 +<td>+4 toucher</td><td>min 2</td><td>1</td>
 +</tr>
 +
 +<tr class="sort offensif"
 +    data-cat="sort"
 +    data-effect="offensif"
 +    data-type="S"
 +    data-niv="1">
 +<td><input type="checkbox" class="skill spell"></td>
 +<td>com</td><td>Sort</td><td>Arcanes violentes</td><td>6 PM</td><td>S</td>
 +<td>-6 toucher +5 dégâts</td><td>min 2</td><td>1</td>
 +</tr>
 +
 +<tr class="sort offensif"
 +    data-cat="sort"
 +    data-effect="offensif"
 +    data-type="S"
 +    data-niv="1">
 +<td><input type="checkbox" class="skill spell"></td>
 +<td>com</td><td>Sort</td><td>Aveuglement</td><td>4 PM</td><td>S</td>
 +<td>"Aveuglement" (x1)</td><td>min 2</td><td>1</td>
 +</tr>
 +
 +<tr class="sort defensif"
 +    data-cat="sort"
 +    data-effect="defensif"
 +    data-type="S"
 +    data-niv="1">
 +<td><input type="checkbox" class="skill spell"></td>
 +<td>com</td><td>Sort</td><td>Coup précis</td><td>4 PM</td><td>S</td>
 +<td>"Dextérité" (x2)</td><td>soi-même / max 1</td><td>1</td>
 +</tr>
 +
 +<tr class="sort offensif"
 +    data-cat="sort"
 +    data-effect="offensif"
 +    data-type="S"
 +    data-niv="1">
 +<td><input type="checkbox" class="skill spell"></td>
 +<td>com</td><td>Sort</td><td>Dard</td><td>3 PM</td><td>S</td>
 +<td>+1 dégât</td><td>min 2</td><td>1</td>
 +</tr>
 +
 +<tr class="sort offensif"
 +    data-cat="sort"
 +    data-effect="offensif"
 +    data-type="S"
 +    data-niv="1">
 +<td><input type="checkbox" class="skill spell"></td>
 +<td>com</td><td>Sort</td><td>Epuisement arcanique</td><td>4 PM</td><td>S</td>
 +<td>"Essoufflement" (X/3), 0 dégât. X = différence des jets</td><td>min 2</td><td>1</td>
 +</tr>
 +
 +<tr class="sort malediction"
 +    data-cat="sort"
 +    data-effect="malediction"
 +    data-type="S"
 +    data-niv="1">
 +<td><input type="checkbox" class="skill spell"></td>
 +<td>com</td><td>Sort</td><td>Maladresse</td><td>4 PM</td><td>S</td>
 +<td>"Maladresse" (x2)</td><td>min 2</td><td>1</td>
 +</tr>
 +
 +<tr class="sort defensif"
 +    data-cat="sort"
 +    data-effect="defensif"
 +    data-type="S"
 +    data-niv="1">
 +<td><input type="checkbox" class="skill spell"></td>
 +<td>com</td><td>Sort</td><td>Peau de granit</td><td>4 PM</td><td>S</td>
 +<td>"Protection" (x2)</td><td>soi-même / max 1</td><td>1</td>
 +</tr>
 +
 +<tr class="sort soin"
 +    data-cat="sort"
 +    data-effect="soin"
 +    data-type="S"
 +    data-niv="1">
 +<td><input type="checkbox" class="skill spell"></td>
 +<td>com</td><td>Sort</td><td>Restauration mineure</td><td>6 PM</td><td>S</td>
 +<td>"Restauration" (5)</td><td>soi-même / max 1</td><td>1</td>
 +</tr>
 +
 +<tr class="sort malediction"
 +    data-cat="sort"
 +    data-effect="malediction"
 +    data-type="S"
 +    data-niv="1">
 +<td><input type="checkbox" class="skill spell"></td>
 +<td>com</td><td>Sort</td><td>Vulnérabilité</td><td>6 PM</td><td>S</td>
 +<td>"Vulnérabilité" (x2)</td><td>min 2</td><td>1</td>
 +</tr>
 <!-- Niveau 2 --> <!-- Niveau 2 -->
  
Ligne 228: Ligne 852:
 </tr> </tr>
  
 +
 +
 +<!-- ===================================================== -->
 +<!-- ========================= CAC ======================= -->
 +<!-- ===================================================== -->
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Attaque précise</td><td>2 PM</td><td>T</td>
 +<td>+4 toucher, -3 dégâts</td><td>max 1</td><td>1</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Attaque violente</td><td>4 PM</td><td>T</td>
 +<td>-6 toucher, +2 dégâts</td><td>max 1</td><td>1</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Coup ajusté</td><td>2 PM</td><td>T</td>
 +<td>"Avantage"</td><td>max 1</td><td>1</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Coup d'épaule</td><td>5 Mvt, 0 PA</td><td>T</td>
 +<td>-4 toucher, -3 dommage</td><td>max 1</td><td>1</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Epuisement</td><td>/</td><td>T</td>
 +<td>"Jet pur". 0 dégât. "Essoufflement" (X/2)</td><td>max 1</td><td>1</td>
 +</tr>
 +
 +<tr class="cac P" data-cat="cac" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>Géant</td><td>CAC</td><td>Berserker</td><td>/</td><td>P</td>
 +<td>+1 CC offensif tous les 10 PV perdus</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Bousculade</td><td>1 Mvt</td><td>T</td>
 +<td>"Bouscule". 0 dégât.</td><td>max 1</td><td>2</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Croc-en-jambe</td><td>6 PM</td><td>T</td>
 +<td>"Ralentissement" (x2D2)</td><td>max 1</td><td>2</td>
 +</tr>
 +
 +<tr class="cac P" data-cat="cac" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>HS</td><td>CAC</td><td>Griffes</td><td>/</td><td>P</td>
 +<td>+3 dégâts aux poings</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="cac P" data-cat="cac" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>Elfe</td><td>CAC</td><td>Fulgurance</td><td>/</td><td>P</td>
 +<td>+1 toucher au CàC + 1 esquive tous les 5 mouvements</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Manchette</td><td>2 PM</td><td>T</td>
 +<td>"Jet pur". 0 dégât. "Maladresse" (X/2)</td><td>max 1</td><td>2</td>
 +</tr>
 +
 +<tr class="cac P" data-cat="cac" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>Olymp</td><td>CAC</td><td>Guerrier béni</td><td>/</td><td>P</td>
 +<td>+1 toucher CàC et +1 Esquive par effet sur lui</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="cac P" data-cat="cac" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>Nain</td><td>CAC</td><td>Maître-lame</td><td>/</td><td>P</td>
 +<td>-2 aux coûts en PM des attaques/techniques basées sur CC, min 1, -4 pour Saut d'attaque</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="3">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Arme infusée</td><td>8 PM</td><td>T</td>
 +<td>+(Pui/3) dégâts</td><td>max 1</td><td>3</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="3">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Attaque drainante</td><td>4 PM</td><td>T</td>
 +<td>"Drain"</td><td>max 1</td><td>3</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="3">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Attaque siphonnante</td><td>2 PV</td><td>T</td>
 +<td>"Siphon"</td><td>max 1</td><td>3</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="3">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Frappe à la tempe</td><td>4 PM</td><td>T</td>
 +<td>"Dommages mentaux" (6)</td><td>max 1</td><td>3</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="3">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Coup de grâce</td><td>6 PM</td><td>T</td>
 +<td>+X dégâts. X = PV cible manquants / 25</td><td>max 1</td><td>3</td>
 +</tr>
 +
 +<tr class="cac P" data-cat="cac" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Brute</td><td>/</td><td>P</td>
 +<td>+2 F pour les calculs de Pousse</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="cac offensif" data-cat="cac" data-type="T" data-niv="3">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Saut d'attaquee</td><td>12 PM, 1 Mvt</td><td>T</td>
 +<td>Déplacement immédiat au contact puis attaque avec malus</td><td>min 2, indirect</td><td>3</td>
 +</tr>
 +
 +<tr class="cac P" data-cat="cac" data-type="P" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Duelliste</td><td>/</td><td>P</td>
 +<td>Avantage sur les attaques au CC</td><td>/</td><td>4</td>
 +</tr>
 +
 +<tr class="cac P" data-cat="cac" data-type="P" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>CAC</td><td>Maître bretteur</td><td>/</td><td>P</td>
 +<td>Malus +1 au CC sur la cible si la frappe passe</td><td>/</td><td>4</td>
 +</tr>
 +
 +
 +<!-- ===================================================== -->
 +<!-- ======================= DISTANCE ==================== -->
 +<!-- ===================================================== -->
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Arme improvisée</td><td>2 PM</td><td>T</td>
 +<td>-4 touche, -2 dégâts. Pas besoin d'arme équipée</td><td>min 2</td><td>1</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Bout portant</td><td>2 PM</td><td>T</td>
 +<td>Tir au contact, -8 touche</td><td>max 1</td><td>1</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Tir ajusté</td><td>2 PM</td><td>T</td>
 +<td>"Avantage"</td><td>min 2</td><td>1</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Tir épuisant</td><td>/</td><td>T</td>
 +<td>"Jet pur". 0 dégât. "Essoufflement" (X/3)</td><td>min 2</td><td>1</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Tir précis</td><td>2 PM</td><td>T</td>
 +<td>+4 toucher, -3 dégâts</td><td>min 2</td><td>1</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Tir violent</td><td>2 PM</td><td>T</td>
 +<td>-6 toucher, +2 dégâts</td><td>min 2</td><td>1</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Jet de sable</td><td>4 PM, 1 Mvt</td><td>T</td>
 +<td>"Aveuglement" (x2), 0 dégât, sans arme équipée</td><td>max 1</td><td>2</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Tir à la cheville</td><td>6 PM</td><td>T</td>
 +<td>"Ralentissement" (x1D2)</td><td>min 2</td><td>2</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Tir handicapant</td><td>4 PM</td><td>T</td>
 +<td>"Jet pur". "Vulnérabilité" (X/3)</td><td>min 2</td><td>2</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Tir puissant</td><td>1 Mvt, 2 PM</td><td>T</td>
 +<td>Repousse la cible de 1 case sous condition de Force</td><td>min 2</td><td>2</td>
 +</tr>
 +
 +<tr class="tir P" data-cat="dis" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>Géant</td><td>Distance</td><td>Voie de l'Eau</td><td>/</td><td>P</td>
 +<td>-3 aux coûts en PM des techniques ≥ 8 PM avec armes de Jet</td><td>min 2</td><td>2</td>
 +</tr>
 +
 +<tr class="tir P" data-cat="dis" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>Elfe</td><td>Distance</td><td>Maître archer</td><td>/</td><td>P</td>
 +<td>+1 dégât sur les tirs avec arme à munition tous les 7 Mvt max</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="3">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Jet infusé</td><td>10 PM</td><td>T</td>
 +<td>+(Pui/3) dégâts</td><td>min 2</td><td>3</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Harponnage</td><td>1 Mvt, 8 PM</td><td>T</td>
 +<td>Attire la cible d'une case vers le lanceur sous condition de Force</td><td>min 2</td><td>2</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Jet brutal</td><td>8 PM</td><td>T</td>
 +<td>Ignore les malus de distance aux dégâts</td><td>min 2</td><td>2</td>
 +</tr>
 +
 +<tr class="tir offensif" data-cat="dis" data-type="T" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Opportunisme</td><td>8 PM</td><td>T</td>
 +<td>+X dégâts. X = Malus cible / 5</td><td>min 2</td><td>2</td>
 +</tr>
 +
 +<tr class="tir P" data-cat="dis" data-type="P" data-niv="3">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Musculeux</td><td>/</td><td>P</td>
 +<td>+2 F pour le calcul de Pousse</td><td>/</td><td>3</td>
 +</tr>
 +
 +<tr class="tir P" data-cat="dis" data-type="P" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Escarmoucheur</td><td>/</td><td>P</td>
 +<td>Malus augmenté de 1 sur la cible avec une arme de tir</td><td>/</td><td>4</td>
 +</tr>
 +
 +<tr class="tir P" data-cat="dis" data-type="P" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Lanceur</td><td>/</td><td>P</td>
 +<td>Avantage sur la CT avec une arme de jet</td><td>/</td><td>4</td>
 +</tr>
 +
 +<tr class="tir P" data-cat="dis" data-type="P" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Distance</td><td>Tireur d'élite</td><td>/</td><td>P</td>
 +<td>Avantage sur la CT avec une arme de tir</td><td>/</td><td>4</td>
 +</tr>
 +
 +
 +<!-- ===================================================== -->
 +<!-- ======================== SURVIE ===================== -->
 +<!-- ===================================================== -->
 +
 +<tr class="survie defensif" data-cat="survie" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Encaisser</td><td>6 PM</td><td>T</td>
 +<td>Donne Encaisse jusqu'au prochain tour</td><td>soi-même</td><td>1</td>
 +</tr>
 +
 +<tr class="survie defensif" data-cat="survie" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Parade</td><td>8 PM</td><td>T</td>
 +<td>Esquive automatiquement la prochaine attaque/technique CàC qui touche</td><td>soi-même</td><td>1</td>
 +</tr>
 +
 +<tr class="survie defensif" data-cat="survie" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Dissipation</td><td>8 PM</td><td>T</td>
 +<td>Esquive automatiquement le prochain Sort qui touche</td><td>soi-même</td><td>1</td>
 +</tr>
 +
 +<tr class="survie defensif" data-cat="survie" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Pas de côté</td><td>8 PM</td><td>T</td>
 +<td>Esquive automatiquement le prochain tir qui touche</td><td>soi-même</td><td>1</td>
 +</tr>
 +
 +<tr class="survie P" data-cat="survie" data-type="P" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Récupération arcanique</td><td>/</td><td>P</td>
 +<td>Ajoute RM/8 PV par action dépensée lors d'un Repos</td><td>/</td><td>1</td>
 +</tr>
 +
 +<tr class="survie P" data-cat="survie" data-type="P" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Récupération somatique</td><td>/</td><td>P</td>
 +<td>Ajoute R/8 PV par action dépensée lors d'un Repos</td><td>/</td><td>1</td>
 +</tr>
 +
 +<tr class="survie P" data-cat="survie" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Encaisser</td><td>/</td><td>P</td>
 +<td>Bénéficie des effets "Encaisse" à 25 PV ou moins</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="survie P" data-cat="survie" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Inébranlable</td><td>/</td><td>P</td>
 +<td>Considéré comme ayant Stabilité (+2)</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="survie P" data-cat="survie" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Rétablissement rapide</td><td>/</td><td>P</td>
 +<td>Ajoute R/5 Malus par action lors d'un Repos</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="survie defensif" data-cat="survie" data-type="T" data-niv="3">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Dédoublement</td><td>10 PM</td><td>T</td>
 +<td>Esquive automatiquement la prochaine action offensive qui touche</td><td>soi-même</td><td>3</td>
 +</tr>
 +
 +<tr class="survie P" data-cat="survie" data-type="P" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Anguille</td><td>/</td><td>P</td>
 +<td>"Avantage" pour les esquives</td><td>/</td><td>4</td>
 +</tr>
 +
 +<tr class="survie P" data-cat="survie" data-type="P" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Couverture</td><td>/</td><td>P</td>
 +<td>Esquive les tirs 85% CC et 15% Agi avec bouclier</td><td>/</td><td>4</td>
 +</tr>
 +
 +<tr class="survie P" data-cat="survie" data-type="P" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Inépuisable</td><td>/</td><td>P</td>
 +<td>Malus réduits sur les actions au CàC</td><td>/</td><td>4</td>
 +</tr>
 +
 +<tr class="survie P" data-cat="survie" data-type="P" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Réflexes fulgurants</td><td>/</td><td>P</td>
 +<td>Esquive les tirs 85% Agi et 15% CC</td><td>/</td><td>4</td>
 +</tr>
 +
 +<tr class="survie P" data-cat="survie" data-type="P" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Survie</td><td>Volonté de fer</td><td>/</td><td>P</td>
 +<td>"Avantage" pour contrer les sorts</td><td>/</td><td>4</td>
 +</tr>
 +
 +
 +
 +<!-- ===================================================== -->
 +<!-- ====================== FURTIVITE ==================== -->
 +<!-- ===================================================== -->
 +
 +<tr class="furtivite" data-cat="furtivite" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Furtivité</td><td>Exploration</td><td>Toutes les A restantes</td><td>T</td>
 +<td>+X (P)</td><td>Soi-même</td><td>1</td>
 +</tr>
 +
 +<tr class="furtivite" data-cat="furtivite" data-type="T" data-niv="1">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Furtivité</td><td>Pas léger</td><td>X PM, Y Mvt</td><td>T</td>
 +<td>X = 4×(Furtivité+1), Y = 1×(Furtivité+1). Aucune trace de pas</td><td>Soi-même</td><td>1</td>
 +</tr>
 +
 +<tr class="furtivite P" data-cat="furtivite" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Furtivité</td><td>Oeil perçant</td><td>/</td><td>P</td>
 +<td>Voit à +5 cases sur la carte générale</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="furtivite P" data-cat="furtivite" data-type="P" data-niv="2">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Furtivité</td><td>Pickpocket</td><td>/</td><td>P</td>
 +<td>Vole 2× plus de PO</td><td>/</td><td>2</td>
 +</tr>
 +
 +<tr class="furtivite" data-cat="furtivite" data-type="T" data-niv="3">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Furtivité</td><td>Discrétion</td><td>X PM, Y Mvt</td><td>T</td>
 +<td>X = 4×(Furtivité+1), Y = 1×(Furtivité+1). Invisible sur la carte globale</td><td>Soi-même</td><td>3</td>
 +</tr>
 +
 +<tr class="furtivite P" data-cat="furtivite" data-type="P" data-niv="3">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Furtivité</td><td>Oeil d'aigle</td><td>/</td><td>P</td>
 +<td>Voit à +5 cases sur la carte générale</td><td>/</td><td>3</td>
 +</tr>
 +
 +<tr class="furtivite" data-cat="furtivite" data-type="T" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Furtivité</td><td>Camouflage (Olympien)</td><td>X PM, Y Mvt</td><td>T</td>
 +<td>Apparence Olympien</td><td>Soi-même</td><td>4</td>
 +</tr>
 +
 +<tr class="furtivite" data-cat="furtivite" data-type="T" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Furtivité</td><td>Camouflage (Elfe)</td><td>X PM, Y Mvt</td><td>T</td>
 +<td>Apparence Elfe</td><td>Soi-même</td><td>4</td>
 +</tr>
 +
 +<tr class="furtivite" data-cat="furtivite" data-type="T" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Furtivité</td><td>Camouflage (HS)</td><td>X PM, Y Mvt</td><td>T</td>
 +<td>Apparence HS</td><td>Soi-même</td><td>4</td>
 +</tr>
 +
 +<tr class="furtivite" data-cat="furtivite" data-type="T" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Furtivité</td><td>Camouflage (Géant)</td><td>X PM, Y Mvt</td><td>T</td>
 +<td>Apparence Géant</td><td>Soi-même</td><td>4</td>
 +</tr>
 +
 +<tr class="furtivite" data-cat="furtivite" data-type="T" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Furtivité</td><td>Camouflage (Nain)</td><td>X PM, Y Mvt</td><td>T</td>
 +<td>Apparence Nain</td><td>Soi-même</td><td>4</td>
 +</tr>
 +
 +<tr class="furtivite P" data-cat="furtivite" data-type="P" data-niv="4">
 +<td><input type="checkbox" class="skill"></td>
 +<td>com</td><td>Furtivité</td><td>Oeil ultime</td><td>/</td><td>P</td>
 +<td>Voit à +5 cases sur la carte générale</td><td>/</td><td>4</td>
 +</tr>
 +
 +</tbody>
 +</table>
 +
 +</div>
 +
 +
 +<script>
 +
 +
 +/* =========================================================
 +   CONFIGURATION
 +========================================================= */
 +
 +const MAX_POINTS = 15;
 +
 +const points = document.getElementById("points");
 +const warning = document.getElementById("warning");
 +
 +const search = document.getElementById("search");
 +const filterCat = document.getElementById("filterCat");
 +const filterEffect = document.getElementById("filterEffect");
 +const filterType = document.getElementById("filterType");
 +
 +const table = document.getElementById("skills");
 +const tbody = table.querySelector("tbody");
 +
 +function resetTable() {
 +
 +    // Décocher toutes les compétences normales
 +    tbody.querySelectorAll(".skill").forEach(cb => {
 +        cb.checked = false;
 +    });
 +
 +    // Remettre toutes les compétences répétables à 0
 +    tbody.querySelectorAll(
 +        'tr[data-repeatable="true"] .repeat-count'
 +    ).forEach(counter => {
 +        counter.innerText = "0";
 +    });
 +
 +    // Effacer le message éventuel
 +    hideWarning();
 +
 +    // Remettre les filtres à leur état initial
 +    search.value = "";
 +    filterCat.value = "all";
 +    filterEffect.value = "all";
 +    filterType.value = "all";
 +
 +    updateAll();
 +}
 +
 +/* =========================================================
 +   OUTILS
 +========================================================= */
 +
 +/*
 + * Retourne toutes les lignes de compétences d'un arbre.
 + * Les sorts ne sont pas considérés comme une partie de l'arbre
 + * Mana pour les prérequis de niveau.
 + */
 +function getTreeRows(tree) {
 +
 +    return Array.from(
 +        tbody.querySelectorAll(
 +            `tr[data-cat="${tree}"]`
 +        )
 +    );
 +}
 +
 +
 +/*
 + * Nombre d'acquisitions d'une compétence.
 + *
 + * Pour une compétence normale :
 + *   0 ou 1
 + *
 + * Pour les compétences Mana répétables :
 + *   0, 1, 2, 3...
 + */
 +function getSkillCount(row) {
 +
 +    if (row.dataset.repeatable === "true") {
 +
 +        const counter = row.querySelector(".repeat-count");
 +
 +        return counter
 +            ? parseInt(counter.innerText, 10) || 0
 +            : 0;
 +    }
 +
 +    const checkbox = row.querySelector(".skill");
 +
 +    return checkbox && checkbox.checked ? 1 : 0;
 +}
 +
 +
 +/*
 + * Nombre total de points dépensés.
 + *
 + * Les sorts ne coûtent pas de point.
 + */
 +function getUsedPoints() {
 +
 +    let total = 0;
 +
 +    tbody.querySelectorAll("tr").forEach(row => {
 +
 +        const cat = row.dataset.cat;
 +
 +        if (cat === "sort") {
 +            return;
 +        }
 +
 +        total += getSkillCount(row);
 +    });
 +
 +    return total;
 +}
 +
 +
 +/*
 + * Nombre de compétences connues à un niveau donné
 + * dans un arbre.
 + *
 + * Une acquisition répétée compte comme une compétence
 + * supplémentaire.
 + */
 +function countLevel(tree, level) {
 +
 +    let total = 0;
 +
 +    getTreeRows(tree).forEach(row => {
 +
 +        if (parseInt(row.dataset.niv, 10) !== level) {
 +            return;
 +        }
 +
 +        total += getSkillCount(row);
 +    });
 +
 +    return total;
 +}
 +
 +
 +/*
 + * Nombre de niveaux 4 déjà acquis dans chaque arbre.
 + */
 +function hasLevel4(tree) {
 +
 +    return countLevel(tree, 4) > 0;
 +}
 +
 +
 +/*
 + * Vérifie si un niveau est accessible dans son arbre.
 + */
 +function levelRequirementMet(tree, level) {
 +
 +    if (level <= 1) {
 +        return true;
 +    }
 +
 +    if (level === 2) {
 +        return countLevel(tree, 1) >= 1;
 +    }
 +
 +    if (level === 3) {
 +        return countLevel(tree, 2) >= 2;
 +    }
 +
 +    if (level === 4) {
 +        return countLevel(tree, 3) >= 2;
 +    }
 +
 +    return true;
 +}
 +
 +
 +/*
 + * Vérifie la règle :
 + *
 + * une fois un niveau 4 pris dans un arbre,
 + * aucun niveau 4 ne peut être pris dans un autre arbre.
 + *
 + * Plusieurs niveaux 4 restent possibles dans le même arbre.
 + */
 +function level4Allowed(tree) {
 +
 +    if (!hasLevel4(tree)) {
 +
 +        const anotherTreeHasLevel4 =
 +            ["cac", "dis", "survie", "furtivite", "mana"]
 +            .some(otherTree =>
 +                otherTree !== tree &&
 +                hasLevel4(otherTree)
 +            );
 +
 +        if (anotherTreeHasLevel4) {
 +            return false;
 +        }
 +    }
 +
 +    return true;
 +}
 +
 +
 +/*
 + * Vérifie si une compétence normale peut être apprise.
 + */
 +function canLearn(row) {
 +
 +    const tree = row.dataset.cat;
 +    const level = parseInt(row.dataset.niv, 10);
 +
 +    if (tree === "sort") {
 +        return true;
 +    }
 +
 +    if (!levelRequirementMet(tree, level)) {
 +        return false;
 +    }
 +
 +    if (level === 4 && !level4Allowed(tree)) {
 +        return false;
 +    }
 +
 +    return true;
 +}
 +
 +
 +/* =========================================================
 +   MESSAGE DE BLOCAGE
 +========================================================= */
 +
 +function getLockReason(row) {
 +
 +    const tree = row.dataset.cat;
 +    const level = parseInt(row.dataset.niv, 10);
 +
 +    if (level === 1) {
 +        return "";
 +    }
 +
 +    if (level === 2 && countLevel(tree, 1) < 1) {
 +        return "Niveau 2 : il faut connaître au moins 1 compétence de niveau 1 dans cet arbre.";
 +    }
 +
 +    if (level === 3 && countLevel(tree, 2) < 2) {
 +        return "Niveau 3 : il faut connaître au moins 2 compétences de niveau 2 dans cet arbre.";
 +    }
 +
 +    if (level === 4) {
 +
 +        if (countLevel(tree, 3) < 2) {
 +            return "Niveau 4 : il faut connaître au moins 2 compétences de niveau 3 dans cet arbre.";
 +        }
 +
 +        if (!level4Allowed(tree)) {
 +            return "Un niveau 4 est déjà appris dans un autre arbre.";
 +        }
 +    }
 +
 +    return "";
 +}
 +
 +
 +/* =========================================================
 +   GESTION DES COMPETENCES NORMALES
 +========================================================= */
 +
 +function setupNormalSkills() {
 +
 +    tbody.querySelectorAll(
 +        'tr:not([data-repeatable="true"]) .skill'
 +    ).forEach(cb => {
 +
 +        cb.addEventListener("change", function() {
 +
 +            if (this.checked) {
 +
 +                const row = this.closest("tr");
 +
 +                if (!canLearn(row)) {
 +
 +                    this.checked = false;
 +
 +                    showWarning(
 +                        getLockReason(row)
 +                    );
 +
 +                    updateAll();
 +                    return;
 +                }
 +
 +                if (getUsedPoints() > MAX_POINTS) {
 +
 +                    this.checked = false;
 +
 +                    showWarning(
 +                        "Vous ne pouvez pas dépasser " +
 +                        MAX_POINTS +
 +                        " points de compétences."
 +                    );
 +
 +                    updateAll();
 +                    return;
 +                }
 +            }
 +
 +            hideWarning();
 +            updateAll();
 +        });
 +    });
 +}
 +
 +
 +/* =========================================================
 +   GESTION DES COMPETENCES MANA REPETABLES
 +========================================================= */
 +
 +function setupRepeatableSkills() {
 +
 +    tbody.querySelectorAll(
 +        'tr[data-repeatable="true"]'
 +    ).forEach(row => {
 +
 +        const plus = row.querySelector(".plus");
 +        const minus = row.querySelector(".minus");
 +
 +        plus.addEventListener("click", function() {
 +
 +            const current = getSkillCount(row);
 +
 +            /*
 +             * Vérification du prérequis de niveau.
 +             *
 +             * Important :
 +             * pour une compétence répétable, une nouvelle
 +             * acquisition doit également respecter les
 +             * prérequis de son niveau.
 +             */
 +            if (!levelRequirementMet(
 +                row.dataset.cat,
 +                parseInt(row.dataset.niv, 10)
 +            )) {
 +
 +                showWarning(
 +                    getLockReason(row)
 +                );
 +
 +                return;
 +            }
 +
 +            /*
 +             * Pour les niveaux 4 :
 +             * même règle que pour les autres compétences.
 +             */
 +            if (
 +                parseInt(row.dataset.niv, 10) === 4 &&
 +                !level4Allowed(row.dataset.cat)
 +            ) {
 +
 +                showWarning(
 +                    "Un niveau 4 est déjà appris dans un autre arbre."
 +                );
 +
 +                return;
 +            }
 +
 +            /*
 +             * Vérification du nombre maximal de points.
 +             */
 +            if (getUsedPoints() >= MAX_POINTS) {
 +
 +                showWarning(
 +                    "Vous ne pouvez pas dépasser " +
 +                    MAX_POINTS +
 +                    " points de compétences."
 +                );
 +
 +                return;
 +            }
 +
 +            row.querySelector(".repeat-count").innerText =
 +                current + 1;
 +
 +            hideWarning();
 +            updateAll();
 +        });
 +
 +
 +        minus.addEventListener("click", function() {
 +
 +            const current = getSkillCount(row);
 +
 +            if (current <= 0) {
 +                return;
 +            }
 +
 +            row.querySelector(".repeat-count").innerText =
 +                current - 1;
 +
 +            hideWarning();
 +            updateAll();
 +        });
 +
 +    });
 +}
 +
 +
 +/* =========================================================
 +   MANA → CAPACITE DE SORTS
 +========================================================= */
 +
 +const spellCapacity = {
 +    1: "Apprenti",
 +    2: "Disciple",
 +    3: "Mage",
 +    4: "Grand Mage",
 +    5: "Archimage"
 +};
 +
 +
 +/*
 + * Nombre de places de sorts disponibles pour un niveau.
 + */
 +function getSpellCapacity(level) {
 +
 +    const requiredSkill = spellCapacity[level];
 +
 +    if (!requiredSkill) {
 +        return 0;
 +    }
 +
 +    const row = Array.from(
 +        tbody.querySelectorAll(
 +            'tr[data-repeatable="true"]'
 +        )
 +    ).find(r =>
 +        r.dataset.repeatName === requiredSkill
 +    );
 +
 +    if (!row) {
 +        return 0;
 +    }
 +
 +    const acquisitions = getSkillCount(row);
 +
 +    if (level === 5) {
 +        return acquisitions * 2;
 +    }
 +
 +    return acquisitions * 3;
 +}
 +
 +
 +/*
 + * Nombre de sorts effectivement sélectionnés
 + * pour un niveau donné.
 + */
 +function getSelectedSpells(level) {
 +
 +    return Array.from(
 +        tbody.querySelectorAll(
 +            `tr[data-cat="sort"][data-niv="${level}"]`
 +        )
 +    ).filter(row => {
 +
 +        const checkbox = row.querySelector(".skill");
 +
 +        return checkbox && checkbox.checked;
 +
 +    }).length;
 +}
 +
 +
 +/*
 + * Vérifie si un sort peut être sélectionné.
 + */
 +function canLearnSpell(row) {
 +
 +    const level = parseInt(row.dataset.niv, 10);
 +
 +    const capacity = getSpellCapacity(level);
 +    const selected = getSelectedSpells(level);
 +
 +    return selected <= capacity;
 +}
 +
 +
 +/*
 + * Configure les cases des sorts.
 + */
 +function setupSpells() {
 +
 +    tbody.querySelectorAll(
 +        'tr[data-cat="sort"] .skill'
 +    ).forEach(cb => {
 +
 +        cb.addEventListener("change", function() {
 +
 +            const row = this.closest("tr");
 +
 +            if (!this.checked) {
 +
 +                updateAll();
 +                return;
 +            }
 +
 +            if (!canLearnSpell(row)) {
 +
 +                this.checked = false;
 +
 +                const level =
 +                    parseInt(row.dataset.niv, 10);
 +
 +                const capacity =
 +                    getSpellCapacity(level);
 +
 +                if (capacity === 0) {
 +
 +                    showWarning(
 +                        "Vous ne possédez pas la compétence Mana nécessaire pour apprendre des sorts de niveau " +
 +                        level +
 +                        "."
 +                    );
 +
 +                } else {
 +
 +                    showWarning(
 +                        "Vous avez atteint votre capacité de sorts de niveau " +
 +                        level +
 +                        " (" +
 +                        capacity +
 +                        " sort(s))."
 +                    );
 +                }
 +
 +                updateAll();
 +                return;
 +            }
 +
 +            hideWarning();
 +            updateAll();
 +        });
 +    });
 +}
 +
 +
 +/* =========================================================
 +   MISE A JOUR VISUELLE
 +========================================================= */
 +
 +function updatePoints() {
 +
 +    points.innerText = getUsedPoints();
 +
 +    if (getUsedPoints() >= MAX_POINTS) {
 +        points.style.color = "red";
 +    } else {
 +        points.style.color = "";
 +    }
 +}
 +
 +
 +/*
 + * Ajoute / retire l'état verrouillé sur les compétences.
 + */
 +function updateLocks() {
 +
 +    tbody.querySelectorAll("tr").forEach(row => {
 +
 +        /*
 +         * Les sorts sont gérés séparément par updateSpellRows().
 +         */
 +        if (row.dataset.cat === "sort") {
 +            return;
 +        }
 +
 +        const level = parseInt(row.dataset.niv, 10);
 +        const tree = row.dataset.cat;
 +
 +        /*
 +         * Les compétences Mana répétables sont gérées
 +         * uniquement avec leurs boutons + / -.
 +         */
 +        if (row.dataset.repeatable === "true") {
 +
 +            let locked = false;
 +
 +            if (!levelRequirementMet(tree, level)) {
 +                locked = true;
 +            }
 +
 +            if (
 +                level === 4 &&
 +                !level4Allowed(tree)
 +            ) {
 +                locked = true;
 +            }
 +
 +            row.classList.toggle(
 +                "skill-locked",
 +                locked
 +            );
 +
 +            return;
 +        }
 +
 +        /*
 +         * Compétences normales
 +         */
 +        const locked =
 +            !levelRequirementMet(tree, level) ||
 +            (
 +                level === 4 &&
 +                !level4Allowed(tree)
 +            );
 +
 +        row.classList.toggle(
 +            "skill-locked",
 +            locked
 +        );
 +
 +        const checkbox = row.querySelector(".skill");
 +
 +        if (checkbox) {
 +
 +            /*
 +             * Une compétence déjà sélectionnée doit toujours
 +             * pouvoir être décochée, même si on est à 15 points.
 +             */
 +            checkbox.disabled =
 +                locked ||
 +                (
 +                    !checkbox.checked &&
 +                    getUsedPoints() >= MAX_POINTS
 +                );
 +        }
 +    });
 +}
 +
 +
 +/*
 + * Mise à jour de l'affichage des compteurs Mana.
 + */
 +function updateRepeatButtons() {
 +
 +    tbody.querySelectorAll(
 +        'tr[data-repeatable="true"]'
 +    ).forEach(row => {
 +
 +        const count = getSkillCount(row);
 +
 +        const minus = row.querySelector(".minus");
 +        const plus = row.querySelector(".plus");
 +
 +        /*
 +         * Le bouton - est disponible dès qu'au moins
 +         * une acquisition existe.
 +         */
 +        minus.disabled = count <= 0;
 +
 +        /*
 +         * Le bouton + dépend :
 +         * - du nombre maximal de points
 +         * - du prérequis de niveau
 +         * - de la règle des niveaux 4
 +         */
 +        const tree = row.dataset.cat;
 +        const level = parseInt(row.dataset.niv, 10);
 +
 +        let canAdd = true;
 +
 +        if (getUsedPoints() >= MAX_POINTS) {
 +            canAdd = false;
 +        }
 +
 +        if (!levelRequirementMet(tree, level)) {
 +            canAdd = false;
 +        }
 +
 +        if (
 +            level === 4 &&
 +            !level4Allowed(tree)
 +        ) {
 +            canAdd = false;
 +        }
 +
 +        plus.disabled = !canAdd;
 +    });
 +}
 +
 +
 +/*
 + * Affichage de la capacité de sorts.
 + */
 +function updateSpellRows() {
 +
 +    tbody.querySelectorAll(
 +        'tr[data-cat="sort"]'
 +    ).forEach(row => {
 +
 +        const level =
 +            parseInt(row.dataset.niv, 10);
 +
 +        const capacity =
 +            getSpellCapacity(level);
 +
 +        const selected =
 +            getSelectedSpells(level);
 +
 +        const checkbox =
 +            row.querySelector(".skill");
 +
 +        const locked =
 +            capacity === 0 ||
 +            (
 +                !checkbox.checked &&
 +                selected >= capacity
 +            );
 +
 +        row.classList.toggle(
 +            "spell-locked",
 +            locked
 +        );
 +
 +        checkbox.disabled =
 +            locked && !checkbox.checked;
 +
 +        /*
 +         * Affiche la capacité sur la première cellule
 +         * uniquement si nécessaire.
 +         */
 +        let info =
 +            row.querySelector(".spell-capacity");
 +
 +        if (!info) {
 +
 +            info = document.createElement("span");
 +
 +            info.className =
 +                "spell-capacity";
 +
 +            row.cells[0].appendChild(info);
 +        }
 +
 +        info.innerText =
 +            capacity > 0
 +                ? `(${selected}/${capacity})`
 +                : "(0)";
 +    });
 +}
 +
 +
 +/* =========================================================
 +   MESSAGES
 +========================================================= */
 +
 +function showWarning(message) {
 +
 +    warning.innerText = message;
 +    warning.style.display = "block";
 +}
 +
 +function hideWarning() {
 +
 +    warning.innerText = "";
 +    warning.style.display = "none";
 +}
 +
 +
 +/* =========================================================
 +   FILTRES
 +========================================================= */
 +
 +function filter() {
 +
 +    const cat = filterCat.value;
 +    const eff = filterEffect.value;
 +    const type = filterType.value;
 +    const s = search.value.toLowerCase();
 +
 +    tbody.querySelectorAll("tr").forEach(row => {
 +
 +        const txt =
 +            row.innerText.toLowerCase();
 +
 +        /*
 +         * Les sorts appartiennent à leur propre filtre
 +         * "Sorts".
 +         */
 +        const rowCat = row.dataset.cat || "";
 +
 +        const categoryOK =
 +            cat === "all" ||
 +            rowCat === cat;
 +
 +        const effectOK =
 +            eff === "all"
 +                ? true
 +                : (
 +                    rowCat === "sort" &&
 +                    (row.dataset.effect || "") === eff
 +                );
 +
 +        const typeOK =
 +            type === "all" ||
 +            (row.dataset.type || "") === type;
 +
 +        const searchOK =
 +            txt.includes(s);
 +
 +        row.style.display =
 +            categoryOK &&
 +            effectOK &&
 +            typeOK &&
 +            searchOK
 +                ? ""
 +                : "none";
 +    });
 +}
 +
 +filterCat.onchange = filter;
 +filterEffect.onchange = filter;
 +filterType.onchange = filter;
 +search.oninput = filter;
 +
 +
 +/* =========================================================
 +   TRI
 +========================================================= */
 +
 +function sortTable(n) {
 +
 +    const rows =
 +        Array.from(
 +            tbody.querySelectorAll("tr")
 +        );
 +
 +    const asc =
 +        document.body.dataset.sort !== "asc";
 +
 +    rows.sort((a, b) => {
 +
 +        let x =
 +            a.cells[n].innerText.toLowerCase();
 +
 +        let y =
 +            b.cells[n].innerText.toLowerCase();
 +
 +        return asc
 +            ? x.localeCompare(
 +                y,
 +                undefined,
 +                { numeric: true }
 +            )
 +            : y.localeCompare(
 +                x,
 +                undefined,
 +                { numeric: true }
 +            );
 +    });
 +
 +    document.body.dataset.sort =
 +        asc ? "asc" : "desc";
 +
 +    rows.forEach(row =>
 +        tbody.appendChild(row)
 +    );
 +
 +    /*
 +     * Le tri ne doit pas casser les états.
 +     */
 +    updateAll();
 +}
 +
 +
 +/* =========================================================
 +   MISE A JOUR GENERALE
 +========================================================= */
 +
 +function updateAll() {
 +
 +    updatePoints();
 +    updateLocks();
 +    updateRepeatButtons();
 +    updateSpellRows();
 +    filter();
 +}
 +
 +
 +/* =========================================================
 +   INITIALISATION
 +========================================================= */
 +
 +setupNormalSkills();
 +setupRepeatableSkills();
 +setupSpells();
 +
 +document.getElementById("resetTable")
 +    .addEventListener("click", resetTable);
 +
 +updateAll();
 +
 +</script>
 +
 +</body>
 +</html>
reg.1791278630.txt.gz · Dernière modification : 2026/10/06 11:23 de nanaki