Outils pour utilisateurs

Outils du site


competence_saison3_full_v2

Différences

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

Lien vers cette vue comparative

Prochaine révision
Révision précédente
competence_saison3_full_v2 [2026/10/21 13:20] – créée nanakicompetence_saison3_full_v2 [2026/10/23 21:12] (Version actuelle) – nanaki
Ligne 86: Ligne 86:
  
 Voici la liste complète des compétences : Voici la liste complète des compétences :
- 
- 
- 
  
 <html> <html>
Ligne 172: Ligne 169:
 th:nth-child(8) { width: 80px; } th:nth-child(8) { width: 80px; }
 th:nth-child(9) { width: 30px; } th:nth-child(9) { width: 30px; }
 +th:nth-child(10) { width: 210px; }
  
 /* Texte multi-lignes */ /* Texte multi-lignes */
  
 td:nth-child(4), td:nth-child(4),
 +td:nth-child(7),
 td:nth-child(8), td:nth-child(8),
-td:nth-child(7) {+td:nth-child(10) {
     white-space: normal;     white-space: normal;
     word-break: break-word;     word-break: break-word;
 +}
 +
 +td:nth-child(10) {
 +    overflow-wrap: anywhere;
 +    text-overflow: clip;
 } }
  
Ligne 398: Ligne 402:
     <th onclick="sortTable(7)">Portée</th>     <th onclick="sortTable(7)">Portée</th>
     <th onclick="sortTable(8)">Niv</th>     <th onclick="sortTable(8)">Niv</th>
 +    <th>Commentaires</th>
 </tr> </tr>
 </thead> </thead>
Ligne 460: Ligne 465:
 <td><input type="checkbox" class="skill"></td> <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>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>+<td>Récupère en plus Pui/3 PM par action lors d'un Repos</td><td>/</td><td>2</td>
 </tr> </tr>
  
Ligne 1004: Ligne 1009:
 <tr class="cac offensif" data-cat="cac" data-type="T" data-niv="3"> <tr class="cac offensif" data-cat="cac" data-type="T" data-niv="3">
 <td><input type="checkbox" class="skill"></td> <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>com</td><td>CAC</td><td>Saut d'attaquee</td><td>15 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>+<td>Déplacement immédiat au contact puis attaque avec malus +0,5F *distance</td><td>min 2, indirect</td><td>3</td>
 </tr> </tr>
  
Ligne 1082: Ligne 1087:
 <td><input type="checkbox" class="skill"></td> <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(jet)</td> <td>com</td><td>Distance</td><td>Tir puissant</td><td>1 Mvt, 2 PM</td><td>T(jet)</td>
-<td>Repousse la cible de 1 case sous condition de Force</td><td>min 2</td><td>2</td>+<td>Repousse la cible de 1 case sous condition de Force et ne fait pas de dégats.</td><td>min 2</td><td>2</td>
 </tr> </tr>
  
Ligne 1350: Ligne 1355:
 const table = document.getElementById("skills"); const table = document.getElementById("skills");
 const tbody = table.querySelector("tbody"); const tbody = table.querySelector("tbody");
 +
 +/* =========================================================
 +   COMMENTAIRES, PREREQUIS ET INCOMPATIBILITES
 +========================================================= */
 +
 +function normaliserNom(nom) {
 +    const valeur = String(nom || "")
 +        .normalize("NFD")
 +        .replace(/[\u0300-\u036f]/g, "")
 +        .toLowerCase()
 +        .replace(/[’'\-]/g, " ")
 +        .replace(/[^a-z0-9 ]/g, "")
 +        .replace(/\s+/g, " ")
 +        .trim();
 +
 +    return valeur;
 +}
 +
 +// Tous les prérequis d'une ligne doivent être sélectionnés.
 +const PREREQUIS = {
 +    "Oeil d'aigle": ["Oeil perçant"],
 +    "Oeil ultime": ["Oeil d'aigle"],
 +    "Colère de la nature": ["Maladresse", "Vulnérabilité"],
 +    "Puissance de la nature": ["Coup précis", "Peau de granit"],
 +    "Aide": ["Coup précis"],
 +    "Fatigue": ["Vulnérabilité"],
 +    "Malchance": ["Maladresse"],
 +    "Réflexes accrus": ["Peau de granit"],
 +    "Régénération accélérée": ["Régénération"],
 +    "Restauration majeure": ["Restauration"],
 +    "Anémie": ["Faiblesse"],
 +    "Bénédiction": ["Réflexes accrus", "Aide"],
 +    "Cuirasse": ["Armure"],
 +    "Férocité": ["Agressivité"],
 +    "Friabilité": ["Fragilité"],
 +    "Puissance du lutin capricieux": ["Malchance", "Fatigue"],
 +    "Récupération supérieure": ["Récupération"],
 +    "Exténuation": ["Fatigue"],
 +    "Guigne": ["Malchance"],
 +    "Sauvegarde": ["Réflexes accrus"],
 +    "Virtuose": ["Aide"]
 +};
 +
 +// Chaque incompatibilité est automatiquement réciproque.
 +const INCOMPATIBILITES = [
 +    ["Fulgurance", "Pouvoir titanique"],
 +    ["Fulgurance", "Maître archer"],
 +    ["Berserker", "Voie de l'air"],
 +    ["Berserker", "Voie de l'eau"],
 +    ["Guerrier béni", "Mage sacré"],
 +    ["Maître-lame", "Récupération runique"],
 +    ["Brute", "Inébranlable"],
 +    ["Duelliste", "Anguille"],
 +    ["Maître bretteur", "Inépuisable"],
 +    ["Maître archer", "Pouvoir titanique"],
 +    ["Voie de l'eau", "Voie de l'air"],
 +    ["Musculeux", "Inébranlable"],
 +    ["Escarmoucheur", "Inépuisable"],
 +    ["Lanceur", "Anguille"],
 +    ["Tireur d'élite", "Anguille"],
 +    ["Méditation arcanique", "Méditation somatique"],
 +    ["Retrait", "Griffes"],
 +    ["Focus mental", "Volonté de fer"],
 +    ["Récupération arcanique", "Récupération somatique"],
 +    ["Couverture", "Réflexes fulgurants"]
 +];
 +
 +function nomCompetence(row) {
 +    return row && row.cells[3] ? row.cells[3].innerText.trim() : "";
 +}
 +
 +function trouverCompetence(nom) {
 +    const cible = normaliserNom(nom);
 +    return Array.from(tbody.querySelectorAll("tr")).find(row =>
 +        normaliserNom(nomCompetence(row)) === cible
 +    ) || null;
 +}
 +
 +// Utilise l'orthographe exacte du nom tel qu'il apparaît dans le tableau.
 +function nomOfficiel(nom) {
 +    const ligne = trouverCompetence(nom);
 +    return ligne ? nomCompetence(ligne) : nom;
 +}
 +
 +function estSelectionnee(row) {
 +    if (!row) return false;
 +    if (row.dataset.repeatable === "true") {
 +        return getSkillCount(row) > 0;
 +    }
 +    const checkbox = row.querySelector(".skill");
 +    return !!checkbox && checkbox.checked;
 +}
 +
 +function prerequisDe(row) {
 +    const nom = nomCompetence(row);
 +    const cle = Object.keys(PREREQUIS).find(
 +        item => normaliserNom(item) === normaliserNom(nom)
 +    );
 +    return cle ? PREREQUIS[cle] : [];
 +}
 +
 +function incompatiblesDe(row) {
 +    const nom = normaliserNom(nomCompetence(row));
 +    const resultat = [];
 +    INCOMPATIBILITES.forEach(([a, b]) => {
 +        if (normaliserNom(a) === nom) resultat.push(b);
 +        else if (normaliserNom(b) === nom) resultat.push(a);
 +    });
 +    return resultat;
 +}
 +
 +function prerequisManquants(row) {
 +    return prerequisDe(row).filter(nom =>
 +        !estSelectionnee(trouverCompetence(nom))
 +    );
 +}
 +
 +function incompatibilitesActives(row) {
 +    return incompatiblesDe(row).filter(nom =>
 +        estSelectionnee(trouverCompetence(nom))
 +    );
 +}
 +
 +function prerequisRespectes(row) {
 +    return prerequisManquants(row).length === 0;
 +}
 +
 +function incompatibilitePresente(row) {
 +    return incompatibilitesActives(row).length > 0;
 +}
 +
 +function raisonRegle(row) {
 +    const manquants = prerequisManquants(row);
 +    if (manquants.length) {
 +        return "Requiert " + manquants.join(" et ") + ".";
 +    }
 +
 +    const incompatibles = incompatibilitesActives(row);
 +    if (incompatibles.length) {
 +        return "Est incompatible avec " + incompatibles.join(" et ") + ".";
 +    }
 +
 +    return "";
 +}
 +
 +function initialiserCommentaires() {
 +    const entete = table.querySelector("thead tr");
 +    if (entete && entete.cells.length === 9) {
 +        const th = document.createElement("th");
 +        th.innerText = "Commentaires";
 +        entete.appendChild(th);
 +    }
 +
 +    tbody.querySelectorAll("tr").forEach(row => {
 +        if (row.cells.length === 9) row.insertCell(-1);
 +        const cellule = row.cells[9];
 +        if (!cellule) return;
 +
 +        const commentaires = [];
 +        const prerequis = prerequisDe(row);
 +        const incompatibles = incompatiblesDe(row);
 +
 +        if (prerequis.length) {
 +            commentaires.push(
 +                "Requiert " + prerequis.map(nomOfficiel).join(" et ")
 +            );
 +        }
 +        if (incompatibles.length) {
 +            commentaires.push(
 +                "Est incompatible avec " + incompatibles.map(nomOfficiel).join(" et ")
 +            );
 +        }
 +
 +        cellule.innerText = commentaires.join(" ; ");
 +        cellule.title = cellule.innerText;
 +    });
 +}
 +
 +// Si un prérequis est retiré, retire aussi les compétences qui en dépendent.
 +function retirerSelectionsInvalides() {
 +    let changement = true;
 +    while (changement) {
 +        changement = false;
 +        tbody.querySelectorAll("tr").forEach(row => {
 +            if (!estSelectionnee(row)) return;
 +            if (!prerequisRespectes(row) || incompatibilitePresente(row)) {
 +                if (row.dataset.repeatable === "true") {
 +                    const compteur = row.querySelector(".repeat-count");
 +                    if (compteur) compteur.innerText = "0";
 +                } else {
 +                    const checkbox = row.querySelector(".skill");
 +                    if (checkbox) checkbox.checked = false;
 +                }
 +                changement = true;
 +            }
 +        });
 +    }
 +}
  
 function resetTable() { function resetTable() {
Ligne 1602: Ligne 1805:
     const tree = row.dataset.cat;     const tree = row.dataset.cat;
     const level = parseInt(row.dataset.niv, 10);     const level = parseInt(row.dataset.niv, 10);
 +
 +    if (!prerequisRespectes(row) || incompatibilitePresente(row)) {
 +        return false;
 +    }
  
     if (tree === "sort") {     if (tree === "sort") {
Ligne 1624: Ligne 1831:
  
 function getLockReason(row) { function getLockReason(row) {
 +
 +    const raison = raisonRegle(row);
 +    if (raison) return raison;
  
     const tree = row.dataset.cat;     const tree = row.dataset.cat;
Ligne 1719: Ligne 1929:
                     return;                     return;
                 }                 }
 +            } else {
 +                retirerSelectionsInvalides();
             }             }
  
Ligne 1753: Ligne 1965:
              * prérequis de son niveau.              * prérequis de son niveau.
              */              */
-            if (!skillRequirementMet(row)) {+            if (!skillRequirementMet(row) || 
 +                !prerequisRespectes(row) || 
 +                incompatibilitePresente(row)) {
  
                 showWarning(                 showWarning(
-                    getLockReason(row)+                    getLockReason(row) || "Cette compétence ne peut pas être acquise."
                 );                 );
  
Ligne 1891: Ligne 2105:
  
     const level = parseInt(row.dataset.niv, 10);     const level = parseInt(row.dataset.niv, 10);
- 
     const capacity = getSpellCapacity(level);     const capacity = getSpellCapacity(level);
     const selected = getSelectedSpells(level);     const selected = getSelectedSpells(level);
  
-    return selected <= capacity;+    return prerequisRespectes(row) && 
 +        !incompatibilitePresente(row) && 
 +        selected <= capacity;
 } }
  
Ligne 1914: Ligne 2129:
             if (!this.checked) {             if (!this.checked) {
  
 +                retirerSelectionsInvalides();
                 updateAll();                 updateAll();
                 return;                 return;
Ligne 1927: Ligne 2143:
                 const capacity =                 const capacity =
                     getSpellCapacity(level);                     getSpellCapacity(level);
 +                const raison = raisonRegle(row);
  
-                if (capacity === 0) {+                if (raison) { 
 +                    showWarning(raison); 
 +                } else if (capacity === 0) {
  
                     showWarning(                     showWarning(
Ligne 1999: Ligne 2218:
             let locked = false;             let locked = false;
  
-            if (!skillRequirementMet(row)) {+            if (!skillRequirementMet(row) || 
 +                !prerequisRespectes(row) || 
 +                incompatibilitePresente(row)) {
                 locked = true;                 locked = true;
             }             }
Ligne 2023: Ligne 2244:
         const locked =         const locked =
             !skillRequirementMet(row) ||             !skillRequirementMet(row) ||
 +            !prerequisRespectes(row) ||
 +            incompatibilitePresente(row) ||
             (             (
                 level === 4 &&                 level === 4 &&
Ligne 2087: Ligne 2310:
         }         }
  
-        if (!skillRequirementMet(row)) {+        if (!skillRequirementMet(row) || 
 +            !prerequisRespectes(row) || 
 +            incompatibilitePresente(row)) {
             canAdd = false;             canAdd = false;
         }         }
Ligne 2126: Ligne 2351:
         const locked =         const locked =
             capacity === 0 ||             capacity === 0 ||
 +            !prerequisRespectes(row) ||
 +            incompatibilitePresente(row) ||
             (             (
                 !checkbox.checked &&                 !checkbox.checked &&
Ligne 2304: Ligne 2531:
    INITIALISATION    INITIALISATION
 ========================================================= */ ========================================================= */
 +
 +initialiserCommentaires();
  
 setupNormalSkills(); setupNormalSkills();
competence_saison3_full_v2.1792581639.txt.gz · Dernière modification : 2026/10/21 13:20 de nanaki