Outils pour utilisateurs

Outils du site


brouillon3

Différences

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

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
brouillon3 [2026/04/18 22:06] nanakibrouillon3 [2026/05/12 13:53] (Version actuelle) nanaki
Ligne 1: Ligne 1:
-===== Liste des Sorts =====+Voici un simulateur en version beta, n'hésitez pas à faire vos remarques sur le discord ou le forum.
  
-Un complément d'information sur certains sorts a été ajouté après le tableau de sorts. 
  
 <html> <html>
 <head> <head>
 <meta charset="UTF-8"> <meta charset="UTF-8">
-<title>Compétences — Techniques & Sorts</title> +<title>Simulateur RPG</title>
-<style> +
-body { font-family: Arial, sans-serif; margin: 10px; } +
-h3 { text-align: center; } +
-.table-container { width: 100%; overflow-x: auto; margin-top: 10px; } +
-table { width: 100%; border-collapse: collapse; min-width: 1200px; } +
-th, td { padding: 8px; border: 1px solid #ccc; text-align: left; } +
-th { background: #f2f2f2; } +
-tbody tr:nth-child(odd) { background: #fafafa; } +
-tbody tr:nth-child(even) { background: #ffffff; }+
  
-/* Couleurs par race */ +<style> 
-td.race-Communs { color: #555; } +body { 
-td.race-Nain { color: red; } +  font-family: Arial; 
-td.race-Géant colorsaddlebrown; } +  background:#0b1a13; 
-td.race-Olympien colordarkorange; } +  color:#7dd3fc; 
-td.race-HS { color: darkgreen; } +  padding:10px; 
-td.race-Elfe { color: green; }+
 +h1,h2 { color:gold;} 
 +.box border:1px solid gold; padding:10px; margin-bottom:10px; } 
 +select { margin:3px; max-width:150px;
 +input margin:3px; width:60px; } 
 +.statLine { display:flex; justify-content:space-between; max-width:260px;
 +.result background:#000; color:#00ffcc; padding:10px; white-space:pre-wrap; } 
 +.small font-size:12px; color:#aaa; }
 </style> </style>
 </head> </head>
 +
 <body> <body>
  
-<!-- ================= TABLEAU 1 : sorts ================= --> +<h1>🎲 Simulateur</h1>
-<h3>Gestion des compétences — sorts</h3> +
-<label for="raceSelect1">Choisir une race :</label> +
-<select id="raceSelect1"> +
-  <option value="Toutes">Toutes</option> +
-  <option value="Communs">Communs</option> +
-  <option value="Nain">Nain</option> +
-  <option value="Géant">Géant</option> +
-  <option value="Olympien">Olympien</option> +
-  <option value="HS">HS</option> +
-  <option value="Elfe">Elfe</option> +
-</select>+
  
-<div class="table-container"> +<div class="box"> 
-<table id="competencesTable1"> +Race : 
-<thead+<select id="race"></select
-<tr> +<h3>Stats de base</h3
-<th>Race</th><th>Nom de la compétence</th><th>Type</th><th>Catégorie</th+<pre id="baseStats"></pre
-<th>Coût (PM)</th><th>Bonus / Malus</th><th>Cible</th><th>Portée</th+</div>
-<th>Description</th><th>Cumulable</th><th>Prix</th> +
-</tr> +
-</thead> +
-  <tbody>+
  
-<!-- ================= COMMUNS ================= -->+<div class="box"> 
 +<h3>Améliorations</h3> 
 +<div id="stats"></div> 
 +<div id="cost"></div> 
 +</div>
  
-Un complément d'information sur certains sorts a été ajouté après le tableau de sorts.+<div class="box"> 
 +<h3>Équipement (3 max + 1 anneau)</h3> 
 +Tête <select id="head"></select> <span id="headStats"></span><br> 
 +Cou <select id="neck"></select> <span id="neckStats"></span><br> 
 +Dos <select id="cape"></select> <span id="capeStats"></span><br> 
 +Main droite <select id="rightHand"></select> <span id="rightStats"></span><br> 
 +Main gauche <select id="leftHand"></select> <span id="leftStats"></span><br> 
 +Corps <select id="body"></select> <span id="bodyStats"></span><br> 
 +Anneau <select id="ring"></select> <span id="ringStats"></span><br> 
 +Pieds <select id="feet"></select> <span id="feetStats"></span> 
 +<div id="limitWarn" style="color:red;"></div> 
 +</div>
  
-<html+<div class="box"
-<head+<h3>Passifs</h3
-<meta charset="UTF-8"> +<div id="skills"></div
-<title>Compétences — Techniques & Sorts</title+</div>
-<style> +
-body { font-family: Arial, sans-serif; margin: 10px; } +
-h3 { text-align: center; } +
-.table-container { width: 100%; overflow-x: auto; margin-top: 10px; } +
-table { width: 100%; border-collapse: collapse; min-width: 1200px; } +
-th, td { padding: 8px; border: 1px solid #ccc; text-align: left; } +
-th { background: #f2f2f2; } +
-tbody tr:nth-child(odd) { background: #fafafa; } +
-tbody tr:nth-child(even) { background: #ffffff; }+
  
-/* Couleurs par race */ +<div class="box"> 
-td.race-Communs { color: #555; } +<h3>Sorts actifs</h3> 
-td.race-Nain { color: red; } +<div id="spells"></div
-td.race-Géant { color: saddlebrown;+<div id="spellBonus" class="small"></div
-td.race-Olympien { color: darkorange; } +</div>
-td.race-HS { color: darkgreen; } +
-td.race-Elfe { color: green; } +
-</style+
-</head+
-<body>+
  
-<!-- ================= TABLEAU 1 : sorts ================= --> 
-<h3>Gestion des compétences — sorts</h3> 
-<label for="raceSelect1">Choisir une race :</label> 
-<select id="raceSelect1"> 
-  <option value="Toutes">Toutes</option> 
-  <option value="Communs">Communs</option> 
-  <option value="Nain">Nain</option> 
-  <option value="Géant">Géant</option> 
-  <option value="Olympien">Olympien</option> 
-  <option value="HS">HS</option> 
-  <option value="Elfe">Elfe</option> 
-</select> 
  
-<div class="table-container"> 
-<table id="competencesTable1"> 
-<thead> 
-<tr> 
-<th>Race</th><th>Nom de la compétence</th><th>Type</th><th>Catégorie</th> 
-<th>Coût (PM)</th><th>Bonus / Malus</th><th>Cible</th><th>Portée</th> 
-<th>Description</th><th>Cumulable</th><th>Prix</th> 
-</tr> 
-</thead> 
-  <tbody> 
  
-<!-- ================= COMMUNS ================= -->+<!-- ================= POUSSEE ================= --
 +<div class="box"> 
 +<h3>Simulateur de poussée</h3>
  
 +Force assaillant <input id="pushF" type="number" value="10">
 +Renforcement <select id="pushBuff"><option value="0">0</option><option value="6">+6</option></select><br>
  
-<tr class="Communs"> +Endurance <input id="pushE" type="number" value="5"> 
-<td class="race-Communs">Communs</td><td>Arcane ajustée</td><td>Sort</td><td>Offensif</td> +Agilité <input id="pushAgi" type="number" value="5"><br>
-<td>6 MP</td><td>Avantage au toucher</td><td>Autre</td><td>min 2</td> +
-<td>Donne l’avantage au toucher</td><td>/</td><td>50 pos</td> +
-</tr>+
  
-<tr class="Communs"+PV actuels <input id="pushPVtype="number" value="50"><br>
-<td class="race-Communs">Communs</td><td>Arcanes précises</td><td>Sort</td><td>Offensif</td> +
-<td>6 MP</td><td>+4 au toucher</td><td>Autre</td><td>min 2</td> +
-<td>Bonus de +4 pour toucher</td><td>/</td><td>50 pos</td> +
-</tr>+
  
-<tr class="Communs"> +Instabilité <select id="pushDebuff"><option value="0">0</option><option value="-6">-6</option></select> 
-<td class="race-Communs">Communs</td><td>Arcanes violentes</td><td>Sort</td><td>Offensif</td> +Stabilité <select id="pushStab"><option value="0">0</option><option value="6">+6</option><option value="12">+12</option><option value="18">+18</option></select>
-<td>MP</td><td>-6 au toucher, +5 dégâts</td><td>Autre</td><td>min 2</td> +
-<td>Malus de -6 pour toucher, bonus +5 dégâts</td><td>/</td><td>50 pos</td> +
-</tr>+
  
-<tr class="Communs"+<pre id="pushResult" class="result"></pre
-<td class="race-Communs">Communs</td><td>Aveuglement</td><td>Sort</td><td>Malédiction</td> +</div>
-<td>4 MP</td><td>-1 P</td><td>Autre</td><td>min 2</td> +
-<td>Aveuglement (x1)</td><td>non cumulable</td><td>50 pos</td+
-</tr>+
  
-<tr class="Communs"> +<button onclick="resetAll()">Reset</button>
-<td class="race-Communs">Communs</td><td>Coup précis</td><td>Sort</td><td>Bénédiction</td> +
-<td>4 MP</td><td>Dextérité (x2)</td><td>Autre / Soi-même</td><td>max 1</td> +
-<td>Dextérité (x2)</td><td>non cumulable</td><td>50 pos</td> +
-</tr>+
  
-<tr class="Communs"> +<button onclick="exportBuild()">📤 Export</button
-<td class="race-Communs">Communs</td><td>Épuisement arcanique</td><td>Sort</td><td>Malédiction</td+<button onclick="importBuild()">📥 Import</button
-<td>4 MP</td><td>Essoufflement (X/3)</td><td>Autre</td><td>min 2</td> +<button onclick="copyLink()">🔗 Lien</button>
-<td>Réduction d’endurance</td><td>/</td><td>50 pos</td> +
-</tr>+
  
-<tr class="Communs"+<pre id="result" class="result"></pre>
-<td class="race-Communs">Communs</td><td>Maladresse</td><td>Sort</td><td>Malédiction</td> +
-<td>4 MP</td><td>Maladresse (x2)</td><td>Autre</td><td>min 2</td> +
-<td>Réduit la précision</td><td>non cumulable</td><td>50 pos</td> +
-</tr>+
  
-<tr class="Communs"> +<script>
-<td class="race-Communs">Communs</td><td>Peau de granit</td><td>Sort</td><td>Bénédiction</td> +
-<td>4 MP</td><td>Protection (x2)</td><td>Autre / Soi-même</td><td>max 1</td> +
-<td>Renforce la défense</td><td>non cumulable</td><td>50 pos</td> +
-</tr>+
  
-<tr class="Communs"> +// ===== RACES ====
-<td class="race-Communs">Communs</td><td>Restauration mineure</td><td>Sort</td><td>Bénédiction</td> +const races { 
-<td>6 MP</td><td>-malus</td><td>Autre / Soi-même</td><td>max 1</td> +Elfe:{a:2,cc:9,ct:10,f:9,e:4,agi:9,p:5,mvt:5,pv:55,pm:30,r:4,rm:6,fm:8,m:6}, 
-<td>Réduit les malus</td><td>/</td><td>50 pos</td> +Nain:{a:2,cc:11,ct:8,f:11,e:6,agi:6,p:4,mvt:4,pv:50,pm:15,r:5,rm:4,fm:10,m:3}, 
-</tr>+Géant:{a:2,cc:9,ct:10,f:12,e:4,agi:7,p:4,mvt:5,pv:65,pm:20,r:5,rm:5,fm:6,m:5}, 
 +Olympien:{a:2,cc:10,ct:9,f:10,e:5,agi:8,p:4,mvt:5,pv:60,pm:30,r:5,rm:6,fm:7,m:5}, 
 +HS:{a:2,cc:8,ct:9,f:7,e:3,agi:11,p:5,mvt:6,pv:45,pm:40,r:3,rm:7,fm:9,m:5} 
 +};
  
-<tr class="Communs"> +// ===== COST ====
-<td class="race-Communs">Communs</td><td>Vulnérabilité</td><td>Sort</td><td>Malédiction</td> +const costTable { 
-<td>6 MP</td><td>Vulnérabilité (x2)</td><td>Autre</td><td>min 2</td> +a:[800,200,100], 
-<td>Augmente les dégâts subis</td><td>non cumulable</td><td>50 pos</td> +cc:[100,50,30], ct:[110,50,30], 
-</tr>+f:[120,55,30], e:[120,55,30], 
 +agi:[95,45,25], 
 +m:[110,55,35], 
 +fm:[100,50,30], 
 +p:[110,85,78], 
 +pv:[4,2,1], 
 +pm:[5,3,1], 
 +mvt:[100,50,30], 
 +r:[40,30,15], 
 +rm:[50,40,20] 
 +};
  
-<tr class="Communs"> +// ===== PASSIFS ===== 
-<td class="race-Communs">Communs</td><td>Agressivité</td><td>Sort</td><td>Bénédiction</td> +const skills = [ 
-<td>6 MP</td><td>Agressivité (x1)</td><td>Autre Soi-même</td><td>max 1</td> +{name:"Fulgurance",desc:"+1 toucher au cac + 1 esquive tous les 5 mouvements"}, 
-<td>Augmente l’agressivité</td><td>non cumulable</td><td>100 pos</td> +{name:"Couverture",desc:"85% CC 15% AGI"}, 
-</tr>+{name:"Réflexes fulgurants",desc:"85% AGI 15% CC"}, 
 +{name:"Berserker",desc:"+toucher au cac tous les 10 pv perdus"}, 
 +{name:"Griffes",desc:"+3 dégâts au poings"}, 
 +{name:"Anguille",desc:"Avantage esquive"
 +];
  
-<tr class="Communs"> +// ===== SORTS ===== 
-<td class="race-Communs">Communs</td><td>Armure</td><td>Sort</td><td>Bénédiction</td> +const spells = [ 
-<td>8 MP</td><td>Armure (x1)</td><td>Autre / Soi-même</td><td>max 1</td> +{name:"Peau de granit",dex:0,prot:2}, 
-<td>Renforce la défense</td><td>non cumulable</td><td>100 pos</td> +{name:"Coup précis",dex:2,prot:0},
-</tr>+
  
-<tr class="Communs"> +{name:"Maladresse",dex:-2,prot:0}, 
-<td class="race-Communs">Communs</td><td>Colère de la nature</td><td>Sort</td><td>Malédiction</td> +{name:"Vulnérabilité",dex:0,prot:-2},
-<td>8 MP</td><td>Maladresse (x2)Vulnérabilité (x2)</td><td>Autre</td><td>min 2</td> +
-<td>Affaiblissement combiné</td><td>cumulable</td><td>100 pos</td> +
-</tr>+
  
-<tr class="Communs"+{name:"Puissance de la nature",dex:2,prot:2},
-<td class="race-Communs">Communs</td><td>Drain</td><td>Sort</td><td>Offensif</td> +
-<td>6 MP</td><td>Vol de PV</td><td>Autre</td><td>min 2</td> +
-<td>Récupère une partie des dégâts</td><td>/</td><td>100 pos</td> +
-</tr>+
  
-<tr class="Communs"> +{name:"Aide",dex:4,prot:0}, 
-<td class="race-Communs">Communs</td><td>Faiblesse</td><td>Sort</td><td>Malédiction</td> +{name:"Malchance",dex:-4,prot:0},
-<td>6 MP</td><td>Faiblesse (x1)</td><td>Autre</td><td>min 2</td> +
-<td>Réduit les capacités</td><td>non cumulable</td><td>100 pos</td> +
-</tr>+
  
-<tr class="Communs"> +{name:"Fatigue",dex:0,prot:-4}, 
-<td class="race-Communs">Communs</td><td>Fragilité</td><td>Sort</td><td>Malédiction</td> +{name:"Réflexes accrus",dex:0,prot:4},
-<td>10 MP</td><td>Fragilité (x1)</td><td>Autre</td><td>min 2</td> +
-<td>Augmente les dégâts subis</td><td>non cumulable</td><td>100 pos</td> +
-</tr>+
  
-<tr class="Communs"+{name:"Bénédiction",dex:4,prot:4},
-<td class="race-Communs">Communs</td><td>Instabilité</td><td>Sort</td><td>Malédiction</td> +
-<td>6 MP</td><td>Instabilité (x6)</td><td>Autre</td><td>min 2</td> +
-<td>Effet instable</td><td>cumulable</td><td>100 pos</td> +
-</tr>+
  
-<tr class="Communs"+{name:"Puissance du lutin capricieux",dex:-4,prot:-4},
-<td class="race-Communs">Communs</td><td>Migraine</td><td>Sort</td><td>Malédiction</td> +
-<td>MP</td><td>Dégâts mentaux</td><td>Autre</td><td>min 2</td> +
-<td>Inflige des dégâts mentaux</td><td>/</td><td>100 pos</td> +
-</tr>+
  
-<tr class="Communs"> +{name:"Exténuation",dex:0,prot:-8}, 
-<td class="race-Communs">Communs</td><td>Puissance de la nature</td><td>Sort</td><td>Bénédiction</td> +{name:"Sauvegarde",dex:0,prot:8}, 
-<td>MP</td><td>Dextérité + Protection</td><td>Autre / Soi-même</td><td>/</td> +{name:"Guigne",dex:-8,prot:0}, 
-<td>Boost multiple</td><td>cumulable</td><td>100 pos</td> +{name:"Virtuose",dex:8,prot:0} 
-</tr>+];
  
-<tr class="Communs"> 
-<td class="race-Communs">Communs</td><td>Régénération</td><td>Sort</td><td>Bénédiction</td> 
-<td>4 MP</td><td>Soin (R/2)</td><td>Autre / Soi-même</td><td>/</td> 
-<td>Soins basés sur R</td><td>/</td><td>100 pos</td> 
-</tr> 
  
-<tr class="Communs"> 
-<td class="race-Communs">Communs</td><td>Renforcement</td><td>Sort</td><td>Bénédiction</td> 
-<td>6 MP</td><td>Renforcement (x6)</td><td>Autre / Soi-même</td><td>/</td> 
-<td>Boost global</td><td>cumulable</td><td>100 pos</td> 
-</tr> 
  
-<tr class="Communs"> +const equipments [
-<td class="race-Communs">Communs</td><td>Restauration</td><td>Sort</td><td>Bénédiction</td> +
-<td>6 MP</td><td>Restauration (R/2)</td><td>Autre / Soi-même</td><td>/</td> +
-<td>Restaure selon R</td><td>/</td><td>100 pos</td> +
-</tr>+
  
-<tr class="Communs"> +/* ================= COMMUNS ================= */
-<td class="race-Communs">Communs</td><td>Siphon</td><td>Sort</td><td>Offensif</td> +
-<td>0 MP, 5 PV, 2 Mvt</td><td>Vol de PM</td><td>Autre</td><td>min 2</td> +
-<td>Convertit dégâts en PM</td><td>/</td><td>100 pos</td> +
-</tr>+
  
-<tr class="Communs"> +{name:"Arc",race:"all",slot:"weapon2h",stats:{cc:-1,ct:1}}, 
-<td class="race-Communs">Communs</td><td>Stabilisation</td><td>Sort</td><td>Bénédiction</td> +{name:"Armure matelassée",race:"all",slot:"body",stats:{e:1,agi:-2}}, 
-<td>MP, 1 Mvt</td><td>Stabilité +6</td><td>Autre / Soi-même</td><td>/</td> +{name:"Bâton de marche",race:"all",slot:"weapon",stats:{mvt:1}}, 
-<td>Stabilise</td><td>/</td><td>100 pos</td> +{name:"Bottes de marche",race:"all",slot:"feet",stats:{mvt:1}}, 
-</tr>+{name:"Bouclier Parma",race:"all",slot:"offhand",stats:{e:1,agi:-2}}, 
 +{name:"Fustibale",race:"all",slot:"weapon",stats:{cc:-2,ct:1}}, 
 +{name:"Gladius",race:"all",slot:"weapon",stats:{cc:1}}, 
 +{name:"Sceptre",race:"all",slot:"weapon",stats:{fm:1}}, 
 +{name:"Lance",race:"all",slot:"weapon",stats:{ct:1,cc:-1}}, 
 +{name:"Targe",race:"all",slot:"offhand",stats:{cc:1,agi:-1}}, 
 +{name:"Visière",race:"all",slot:"head",stats:{p:1,cc:-1,fm:-1}}, 
 +{name:"Cape de chasse",race:"all",slot:"cape",stats:{ct:1}}, 
 +{name:"Collier tressé",race:"all",slot:"neck",stats:{pv:5,pm:5}}, 
 +{name:"Couronne d'Adonis",race:"all",slot:"head",stats:{rm:1}}, 
 +{name:"Ceinture",race:"all",slot:"body",stats:{r:1}}, 
 +{name:"Arc long",race:"all",slot:"weapon2h",stats:{ct:2,f:-1,cc:-2}}, 
 +{name:"Targe renforcée",race:"all",slot:"offhand",stats:{cc:1,pv:10}},
  
-<tr class="Communs"> +/* ===== NOUVEAUX COMMUNS ===== */
-<td class="race-Communs">Communs</td><td>Aide</td><td>Sort</td><td>Bénédiction</td> +
-<td>8 MP</td><td>Dextérité (x4)</td><td>Autre / Soi-même</td><td>/</td> +
-<td>Boost fort</td><td>non cumulable</td><td>200 pos</td> +
-</tr>+
  
-<tr class="Communs"> +{name:"Torche",race:"all",slot:"weapon",stats:{cc:-2,f:-2}}, 
-<td class="race-Communs">Communs</td><td>Fatigue</td><td>Sort</td><td>Malédiction</td> +{name:"Hache de jet",race:"all",slot:"weapon",stats:{ct:1}}, 
-<td>12 MP</td><td>Vulnérabilité (x4)</td><td>Autre</td><td>min 2</td> +{name:"Pierre Noire",race:"all",slot:"weapon",stats:{f:1,cc:-1}}, 
-<td>Affaiblissement fort</td><td>non cumulable</td><td>200 pos</td> +{name:"Main-gauche offensive",race:"all",slot:"offhand",stats:{cc:2,f:-1}},
-</tr>+
  
-<tr class="Communs"> +/* ================= ELFES ================= */
-<td class="race-Communs">Communs</td><td>Malchance</td><td>Sort</td><td>Malédiction</td> +
-<td>8 MP</td><td>Maladresse (x4)</td><td>Autre</td><td>min 2</td> +
-<td>Réduit précision</td><td>non cumulable</td><td>200 pos</td> +
-</tr>+
  
-<tr class="Communs"> +{name:"Bâton du Pèlerin",race:"all",slot:"weapon",stats:{mvt:1,fm:1}}, 
-<td class="race-Communs">Communs</td><td>Récupération</td><td>Sort</td><td>Bénédiction</td> +{name:"Bottes Tâlroval",race:"all",slot:"feet",stats:{mvt:2}}, 
-<td>4 MP</td><td>Soin (R/2)</td><td>Autre</td><td>max 1</td> +{name:"Cuirasse",race:"all",slot:"body",stats:{e:1,r:2}}, 
-<td>Soigne</td><td>non cumulable</td><td>200 pos</td> +{name:"Lance de garde Sylvestre",race:"all",slot:"weapon",stats:{cc:1,f:1}}, 
-</tr>+{name:"Sceptre de mage",race:"all",slot:"weapon2h",stats:{m:1,fm:1}}, 
 +{name:"Arc Ensorcelé",race:"all",slot:"weapon2h",stats:{ct:1,rm:2,cc:-1}}, 
 +{name:"Armure de garde Sylvestre",race:"all",slot:"body",stats:{e:2,mvt:-1},magicBlock:true}, 
 +{name:"Toge de feuillage",race:"all",slot:"body",stats:{fm:1,agi:1,pv:5}}, 
 +{name:"Marque Forestière",race:"all",slot:"neck",stats:{pm:10,r:1}}, 
 +{name:"Capuche du chasseur",race:"all",slot:"head",stats:{ct:1,r:1}},
  
-<tr class="Communs"> +// spécifique elfe 
-<td class="race-Communs">Communs</td><td>Réflexes accrus</td><td>Sort</td><td>Bénédiction</td> +{name:"Arc Elfique",race:"Elfe",slot:"weapon2h",stats:{ct:2,cc:-1}},
-<td>8 MP</td><td>Protection (x4)</td><td>Autre / Soi-même</td><td>max 1</td> +
-<td>Boost défense</td><td>non cumulable</td><td>200 pos</td> +
-</tr>+
  
-<tr class="Communs"> +/* ================= NAINS ================= */
-<td class="race-Communs">Communs</td><td>Régénération accélérée</td><td>Sort</td><td>Bénédiction</td> +
-<td>10 MP</td><td>Soin (R)</td><td>Autre / Soi-même</td><td>max 1</td> +
-<td>Soins puissants</td><td>non cumulable</td><td>200 pos</td> +
-</tr>+
  
-<tr class="Communs"> +{name:"Cotte de mailles",race:"all",slot:"body",stats:{e:2,agi:-4}}, 
-<td class="race-Communs">Communs</td><td>Restauration majeure</td><td>Sort</td><td>Bénédiction</td> +{name:"Labrys",race:"all",slot:"weapon",stats:{cc:1,f:1}}, 
-<td>12 MP</td><td>Restauration (R)</td><td>Autre / Soi-même</td><td>/</td> +{name:"Marteau de guerre",race:"all",slot:"weapon2h",stats:{f:2,cc:-1}}, 
-<td>Restaure complètement</td><td>/</td><td>200 pos</td> +{name:"Targe renforcée naine",race:"all",slot:"offhand",stats:{cc:1,pv:10}}, 
-</tr>+{name:"Armure runique",race:"all",slot:"body",stats:{e:1,pm:8}}, 
 +{name:"Cape dorée",race:"all",slot:"cape",stats:{m:1,fm:1},magicBlock:true}, 
 +{name:"Solerets",race:"all",slot:"feet",stats:{mvt:1,pm:5,pv:5}}, 
 +{name:"Casque grossissant",race:"all",slot:"head",stats:{ct:2,p:-1}},
  
-<tr class="Communs"> +// spécifiques nains 
-<td class="race-Communs">Communs</td><td>Anémie</td><td>Sort</td><td>Malédiction</td> +{name:"Bâton d'archimage",race:"Nain",slot:"weapon2h",stats:{m:2,fm:-1}}, 
-<td>12 MP</td><td>Faiblesse (x2)</td><td>Autre</td><td>max 1</td> +{name:"Hache runique",race:"Nain",slot:"weapon",stats:{cc:1,f:2}},
-<td>Affaiblissement sévère</td><td>non cumulable</td><td>300 pos</td> +
-</tr>+
  
-<tr class="Communs"> +/* ================= GÉANTS ================= */
-<td class="race-Communs">Communs</td><td>Bénédiction</td><td>Sort</td><td>Bénédiction</td> +
-<td>15 MP</td><td>Protection + Dextérité (x4)</td><td>Autre / Soi-même</td><td>max 1</td> +
-<td>Boost complet</td><td>non cumulable</td><td>300 pos</td> +
-</tr>+
  
-<tr class="Communs"> +{name:"Bouclier Clipeus",race:"all",slot:"offhand",stats:{e:1,pv:10}}, 
-<td class="race-Communs">Communs</td><td>Cuirasse</td><td>Sort</td><td>Bénédiction</td> +{name:"Masse d'arme",race:"all",slot:"weapon",stats:{cc:1,f:1}}, 
-<td>15 MP</td><td>Armure (x2)</td><td>Autre / Soi-même</td><td>max 1</td> +{name:"Hallebarde de pierre",race:"all",slot:"weapon",stats:{cc:2,f:-1}}, 
-<td>Défense élevée</td><td>non cumulable</td><td>300 pos</td> +{name:"Bâton de shaman",race:"Géant",slot:"weapon2h",stats:{fm:2,pv:-5}}, 
-</tr>+{name:"Javelot lourd",race:"all",slot:"weapon",stats:{f:2,ct:-1,cc:-1}}, 
 +{name:"Broigne",race:"all",slot:"body",stats:{e:2,f:-1}}, 
 +{name:"Fétiche de shaman",race:"all",slot:"offhand",stats:{r:2,pm:5}}, 
 +{name:"Bottes incandescentes",race:"all",slot:"feet",stats:{mvt:1,r:1,pv:5}}, 
 +{name:"Médaillon hanté",race:"all",slot:"neck",stats:{cc:1,ct:1}},
  
-<tr class="Communs"> +// spécifique géant 
-<td class="race-Communs">Communs</td><td>Férocité</td><td>Sort</td><td>Bénédiction</td> +{name:"Peau de granit manifiée",race:"Géant",slot:"body",stats:{m:1,rm:2,agi:-2}},
-<td>12 MP</td><td>Agressivité (x2)</td><td>Autre / Soi-même</td><td>max 1</td> +
-<td>Offensive renforcée</td><td>non cumulable</td><td>300 pos</td> +
-</tr>+
  
-<tr class="Communs"> +/* ================= HS ================= */
-<td class="race-Communs">Communs</td><td>Friabilité</td><td>Sort</td><td>Malédiction</td> +
-<td>20 MP</td><td>Fragilité (x2)</td><td>Autre</td><td>min 2</td> +
-<td>Extrêmement fragile</td><td>non cumulable</td><td>300 pos</td> +
-</tr>+
  
-<tr class="Communs"> +{name:"Bâton de sage",race:"all",slot:"weapon2h",stats:{m:1,agi:1}}, 
-<td class="race-Communs">Communs</td><td>Puissance du lutin capricieux</td><td>Sort</td><td>Malédiction</td> +{name:"Orbe de mana",race:"all",slot:"weapon2h",stats:{m:1,rm:1}}, 
-<td>20 MP</td><td>Maladresse + Vulnérabilité (x4)</td><td>Autre</td><td>min 2</td> +{name:"Cape de mage",race:"all",slot:"cape",stats:{fm:1,rm:1}}, 
-<td>Double malédiction</td><td>non cumulable</td><td>300 pos</td> +{name:"Armure de fourrure",race:"all",slot:"body",stats:{e:2,rm:-3}}, 
-</tr>+{name:"Ceste",race:"all",slot:"weapon",stats:{f:1,cc:1}}, 
 +{name:"Collier d'apaisement",race:"all",slot:"neck",stats:{pv:10,pm:5}}, 
 +{name:"Bottes de voleur",race:"all",slot:"feet",stats:{mvt:1,agi:1}}, 
 +{name:"Sarbacane",race:"all",slot:"weapon",stats:{ct:1,f:10,cc:-1}}, 
 +{name:"Bouclier en lianes",race:"all",slot:"offhand",stats:{cc:1,agi:1}},
  
-<tr class="Communs"> +// spécifiques HS 
-<td class="race-Communs">Communs</td><td>Récupération supérieure</td><td>Sort</td><td>Bénédiction</td> +{name:"Manteau de feuillage",race:"HS",slot:"body",stats:{e:1,agi:2}}, 
-<td>10 MP</td><td>Soin (R)</td><td>Autre / Soi-même</td><td>max 1</td> +{name:"Bottes griffues",race:"HS",slot:"feet",stats:{cc:1,f:1,pv:5}},
-<td>Soins complets</td><td>non cumulable</td><td>300 pos</td> +
-</tr>+
  
-<tr class="Communs"> +/* ================= OLYMPIENS ================= */
-<td class="race-Communs">Communs</td><td>Exténuation</td><td>Sort</td><td>Malédiction</td> +
-<td>25 MP</td><td>Vulnérabilité (x8)</td><td>Autre</td><td>min 2</td> +
-<td>Vulnérabilité (x8)</td><td>/</td><td>300 pos</td> +
-</tr>+
  
-<tr class="Communs"> +{name:"Armure hoplitique",race:"all",slot:"body",stats:{e:1,m:1}}, 
-<td class="race-Communs">Communs</td><td>Guigne</td><td>Sort</td><td>Malédiction</td> +{name:"Bouclier Ancile",race:"all",slot:"offhand",stats:{e:1}}, 
-<td>20 MP</td><td>Maladresse (x8)</td><td>Autre</td><td>min 2</td> +{name:"Diadème",race:"all",slot:"head",stats:{r:1,rm:2}}, 
-<td>Maladresse (x8)</td><td>/</td><td>300 pos</td> +{name:"Pilum",race:"all",slot:"weapon",stats:{ct:1,f:1,cc:-1}}, 
-</tr>+{name:"Spatha",race:"all",slot:"weapon",stats:{cc:1,f:1}}, 
 +{name:"Sceptre de puissance",race:"all",slot:"weapon",stats:{m:1,pm:8}}, 
 +{name:"Lame Sainte",race:"all",slot:"weapon",stats:{cc:1,m:1}}, 
 +{name:"Tiare d'Oracle",race:"all",slot:"head",stats:{fm:1,p:1}}, 
 +{name:"Cnémides",race:"all",slot:"feet",stats:{mvt:1,rm:1,r:1}},
  
-<tr class="Communs"> +// spécifique olympien 
-<td class="race-Communs">Communs</td><td>Sauvegarde</td><td>Sort</td><td>Bénédiction</td> +{name:"Lorica",race:"Olympien",slot:"body",stats:{e:2,agi:-2}},
-<td>20 MP</td><td>Protection (x8)</td><td>Autre / Soi-même</td><td>max 1</td> +
-<td>Protection (x8)</td><td>/</td><td>300 pos</td> +
-</tr>+
  
-<tr class="Communs"> +/* ================= ANNEAUX ================= */
-<td class="race-Communs">Communs</td><td>Virtuose</td><td>Sort</td><td>Bénédiction</td> +
-<td>20 MP</td><td>Dextérité (x8)</td><td>Autre / Soi-même</td><td>max 1</td> +
-<td>Dextérité (x8)</td><td>/</td><td>300 pos</td> +
-</tr>+
  
-<!-- ================= SORTS RACIAUX ================= -->+{name:"Anneau Caprice",race:"all",slot:"ring",stats:{fm:1}}, 
 +{name:"Anneau Férocité",race:"all",slot:"ring",stats:{f:1}}, 
 +{name:"Anneau Horizon",race:"all",slot:"ring",stats:{p:1}}, 
 +{name:"Anneau Prétention",race:"all",slot:"ring",stats:{ct:1}}, 
 +{name:"Anneau Souplesse",race:"all",slot:"ring",stats:{agi:1}}, 
 +{name:"Anneau Tenacité",race:"all",slot:"ring",stats:{e:1}}, 
 +{name:"Anneau Puissance",race:"all",slot:"ring",stats:{m:1}}, 
 +{name:"Anneau Finesse",race:"all",slot:"ring",stats:{cc:1}}
  
-<tr class="race-HS"> +];
-<td class="race-HS">HS</td><td>Aiguillon</td><td>Sort</td><td>Offensif</td> +
-<td>4 PM</td><td>+3</td><td>Autre</td><td>min 2</td> +
-<td>Projette un aiguillon sur l’adversaire.</td><td>/</td><td>100 pos</td> +
-</tr>+
  
-<tr class="race-HS"> 
-<td class="race-HS">HS</td><td>Flux Vital</td><td>Sort</td><td>Bénédiction</td> 
-<td>6 PM</td><td></td><td>Soi-même</td><td>0</td> 
-<td>Puise dans la régénération magique pour se soigner.</td><td>/</td><td>100 pos</td> 
-</tr> 
  
-<tr class="race-HS"> +// ===== INIT ===== 
-<td class="race-HS">HS</td><td>Arme Vivante *</td><td>Sort</td><td>Offensif</td> +const raceSelect = document.getElementById("race"); 
-<td>12 PM</td><td>+M</td><td>Autre</td><td>max 1</td> +const statsDiv document.getElementById("stats"); 
-<td>Ajoute des dégâts magiques à une attaque avec une arme composée de bois.</td><td>/</td><td>300 pos</td> +const baseDiv = document.getElementById("baseStats");
-</tr>+
  
-<tr class="race-HS"> +for(let r in races){ 
-<td class="race-HS">HS</td><td>Taillade illusoire</td><td>Sort</td><td>Offensif</td+raceSelect.innerHTML +`<option>${r}</option>`; 
-<td>10 PM</td><td>+6</td><td>Autre</td><td>max 3</td> +}
-<td>Des crocs et des griffes spectraux attaquent l’adversaire.</td><td>/</td><td>300 pos</td> +
-</tr>+
  
-<!-- Elfe --> +// stats UI 
-<tr class="race-Elfe"> +for(let s in costTable){ 
-<td class="race-Elfe">Elfe</td><td>Aiguillon</td><td>Sort</td><td>Offensif</td+statsDiv.innerHTML +` 
-<td>4 PM</td><td>+3</td><td>Autre</td><td>min 2</td+<div class="statLine"> 
-<td>Projette un aiguillon sur l’adversaire.</td><td>/</td><td>100 pos</td+<span>${s}</span
-</tr>+<input type="number" id="${s}" value="0" min="0"
 +</div>`; 
 +}
  
-<tr class="race-Elfe"> +// passifs 
-<td class="race-Elfe">Elfe</td><td>Flèche Aquatique</td><td>Sort</td><td>Offensif</td+skills.forEach(s=>{ 
-<td>5 PM</td><td>+3 + effet Eau</td><td>Autre</td><td>min 2</td+document.getElementById("skills").innerHTML += ` 
-<td>Projette une flèche d’eau.</td><td>/</td><td>100 pos</td+<label
-</tr>+<input type="checkbox" class="skill" data-name="${s.name}"> 
 +<b>${s.name}</b><br
 +<span class="small">${s.desc}</span> 
 +</label><br>`; 
 +});
  
-<tr class="race-Elfe"> 
-<td class="race-Elfe">Elfe</td><td>Lien de Vie</td><td>Sort</td><td>Bénédiction</td> 
-<td>6 PM</td><td></td><td>Autre</td><td>max 1</td> 
-<td>Soigne via régénération magique.</td><td>/</td><td>100 pos</td> 
-</tr> 
  
-<tr class="race-Elfe"> +// affichage sorts 
-<td class="race-Elfe">Elfe</td><td>Trait Béni *</td><td>Sort</td><td>Offensif</td+spells.forEach(s=>{ 
-<td>12 PM</td><td>+M</td><td>Autre</td><td>min 2</td+document.getElementById("spells").innerHTML += ` 
-<td>Ajoute des dégâts magiques au tir.</td><td>/</td><td>300 pos</td+<label
-</tr>+<input type="checkbox" class="spell" data-dex="${s.dex}" data-prot="${s.prot}"> 
 +<b>${s.name}</b>  
 +<span class="small">(Dex ${s.dex>=0?"+":""}${s.dex} | Prot ${s.prot>=0?"+":""}${s.prot})</span
 +</label><br>`; 
 +});
  
-<tr class="race-Elfe"> +// base stats 
-<td class="race-Elfe">Elfe</td><td>Glaciation</td><td>Sort</td><td>Offensif</td> +function displayBase(){ 
-<td>8 PM</td><td>+6</td><td>Autre</td><td>max 2</td> +baseDiv.textContent = JSON.stringify(races[raceSelect.value],null,2); 
-<td>Attaque de froid.</td><td>/</td><td>300 pos</td> +
-</tr>+raceSelect.addEventListener("change", displayBase); 
 +displayBase();
  
-<tr class="race-Géant"> +// ===== COST ====
-<td class="race-Géant">Géant</td><td>Régénération</td><td>Sort</td><td>Bénédiction</td> +function calcCost(b,m1,m2,n){ 
-<td>6 PM</td><td></td><td>Autre</td><td>max 1</td> +let total=0,last=b; 
-<td>Soigne la cible.</td><td>/</td><td>100 pos</td> +for(let i=1;i<=n;i++){ 
-</tr>+if(i===1) last=b; 
 +else if(i<=3) last+=m1; 
 +else last+=m2; 
 +total+=last; 
 +
 +return total; 
 +}
  
-<tr class="race-Géant"> +function updateCost(){ 
-<td class="race-Géant">Géant</td><td>Météore *</td><td>Sort</td><td>Offensif</td> +let total=0; 
-<td>12 PM</td><td>+M + feu</td><td>Autre</td><td>min 2</td> +for(let s in costTable){ 
-<td>Attaque de pierre enflammée.</td><td>/</td><td>300 pos</td> +let v=+document.getElementById(s).value||0; 
-</tr>+let [b,m1,m2]=costTable[s]; 
 +total+=calcCost(b,m1,m2,v); 
 +
 +document.getElementById("cost").innerHTML="💰 PI : "+total; 
 +}
  
-<tr class="race-Géant"> +// ===== SLOTS ====
-<td class="race-Géant">Géant</td><td>Souffle des cimes</td><td>Sort</td><td>Offensif</td> +const slots { 
-<td>8 PM</td><td>+6</td><td>Autre</td><td>max 2</td> +head:head,neck:neck,cape:cape,rightHand:rightHand, 
-<td>Foudre déchaînée.</td><td>/</td><td>300 pos</td> +leftHand:leftHand,body:body,ring:ring,feet:feet 
-</tr>+};
  
-<!-- Nain --> +function resetSlots(){ 
-<tr class="race-Nain"> +Object.values(slots).forEach(s=>s.innerHTML="<option value=''>--</option>"); 
-<td class="race-Nain">Nain</td><td>Pic de Pierre</td><td>Sort</td><td>Offensif</td+}
-<td>4 PM</td><td>+3</td><td>Autre</td><td>min 2</td> +
-<td>Projette un pic de pierre.</td><td>/</td><td>100 pos</td> +
-</tr>+
  
-<tr class="race-Nain"> +function fillEquip(){ 
-<td class="race-Nain">Nain</td><td>Poings de Pierre</td><td>Sort</td><td>Offensif</td> +let r=raceSelect.value;
-<td>8 PM</td><td>+8</td><td>Autre</td><td>max 1</td> +
-<td>Poings de roche.</td><td>/</td><td>300 pos</td> +
-</tr>+
  
-<!-- Olympien --+equipments.forEach((e,i)=>{ 
-<tr class="race-Olympien"> +if(e.race!=="all"&&e.race!==r) return;
-<td class="race-Olympien">Olympien</td><td>Lame Volante</td><td>Sort</td><td>Offensif</td> +
-<td>4 PM</td><td>+3</td><td>Autre</td><td>min 2</td> +
-<td>Lame magique.</td><td>/</td><td>100 pos</td> +
-</tr>+
  
-<tr class="race-Olympien"+if(e.slot==="weapon"||e.slot==="weapon2h") rightHand.innerHTML+=`<option value="${i}">${e.name}</option>`; 
-<td class="race-Olympien">Olympien</td><td>Imposition des Mains</td><td>Sort</td><td>Bénédiction</td+if(e.slot==="offhand") leftHand.innerHTML+=`<option value="${i}">${e.name}</option>`; 
-<td>7 PM</td><td>+3</td><td>Autre</td><td>max 1</td+if(e.slot==="body") body.innerHTML+=`<option value="${i}">${e.name}</option>`; 
-<td>Soigne une cible.</td><td>/</td><td>100 pos</td+if(e.slot==="head") head.innerHTML+=`<option value="${i}">${e.name}</option>`; 
-</tr>+if(e.slot==="neck") neck.innerHTML+=`<option value="${i}">${e.name}</option>`; 
 +if(e.slot==="cape") cape.innerHTML+=`<option value="${i}">${e.name}</option>`; 
 +if(e.slot==="feet") feet.innerHTML+=`<option value="${i}">${e.name}</option>`; 
 +if(e.slot==="ring") ring.innerHTML+=`<option value="${i}">${e.name}</option>`; 
 +}); 
 +}
  
-<tr class="race-Olympien"+raceSelect.addEventListener("change",()=>{ 
-<td class="race-Olympien">Olympien</td><td>Lame Bénie *</td><td>Sort</td><td>Offensif</td+resetSlots(); 
-<td>12 PM</td><td>+M</td><td>Autre</td><td>max 1</td> +fillEquip(); 
-<td>Attaque magique de mêlée.</td><td>/</td><td>300 pos</td> +autoCalculate(); 
-</tr>+});
  
-<tr class="race-Olympien"> +resetSlots(); 
-<td class="race-Olympien">Olympien</td><td>Soumission divine</td><td>Sort</td><td>Offensif</td> +fillEquip();
-<td>8 PM</td><td>+6</td><td>Autre</td><td>max 2</td> +
-<td>Énergie divine.</td><td>/</td><td>300 pos</td> +
-</tr>+
  
-</tbody> +// ===== BONUS ===== 
-</table> +function displayStats(select,id){ 
-</div>+let v=select.value; 
 +let el=document.getElementById(id); 
 +if(v===""){el.innerHTML="";return;
 +let e=equipments[v]; 
 +let txt=""; 
 +for(let s in e.stats){ 
 +let val=e.stats[s]; 
 +txt+=val>0?`+${val} ${s} `:`${val} ${s} `; 
 +
 +el.innerHTML=txt; 
 +}
  
 +const slotToStatId = {
 +head:"headStats",
 +neck:"neckStats",
 +cape:"capeStats",
 +rightHand:"rightStats",
 +leftHand:"leftStats",
 +body:"bodyStats",
 +ring:"ringStats",
 +feet:"feetStats"
 +};
  
-<script+Object.entries(slots).forEach(([k,s])=>{ 
-// Script pour le premier tableau +s.addEventListener("change",()=>{ 
-const select1 = document.getElementById("raceSelect1"); +displayStats(s, slotToStatId[k]); 
-const rows1 = document.querySelectorAll("#competencesTable1 tbody tr");+checkLimit(); 
 +autoCalculate(); 
 +}); 
 +});
  
-select1.addEventListener("change", () => +// ===== LIMIT ===== 
-  const chosenRace select1.value+function checkLimit(){ 
-  rows1.forEach(row => { +let count=0
-    const isCommun row.classList.contains("Communs"); +Object.entries(slots).forEach(([k,s])=>{ 
-    const isRace = row.classList.contains(chosenRace); +if(k!=="ring"&&s.value!==""count++;
-    row.style.display = (chosenRace === "Toutes|| isCommun || isRace) ? "" : "none"; +
-  });+
 }); });
-</script> 
  
-<hr>+if(count>=3){ 
 +limitWarn.innerText="Limite atteinte"; 
 +Object.entries(slots).forEach(([k,s])=>
 +if(k!=="ring"&&s.value==="") s.disabled=true; 
 +}); 
 +}else{ 
 +limitWarn.innerText=""; 
 +Object.values(slots).forEach(s=>s.disabled=false); 
 +
 +}
  
-<!-- ================= TABLEAU 2 : Sorts ================= --> +// ===== CALCUL =====
-<h3>Gestion des compétences — Techniques Corps à corps</h3> +
-<label for="raceSelect2">Choisir une race :</label> +
-<select id="raceSelect2"> +
-  <option value="Toutes">Toutes</option> +
-  <option value="Communs">Communs</option> +
-  <option value="Nain">Nain</option> +
-  <option value="Géant">Géant</option> +
-  <option value="Olympien">Olympien</option> +
-  <option value="HS">HS</option> +
-  <option value="Elfe">Elfe</option> +
-</select>+
  
-<div class="table-container"> +function calculate(){
-<table id="competencesTable2"> +
-<thead> +
-<tr> +
-<th>Race</th><th>Nom</th><th>Type</th><th>Catégorie</th> +
-<th>Coût</th><th>Bonus / Malus</th><th>Cible</th><th>Portée</th> +
-<th>Description</th><th>Cumulable</th><th>Prix</th> +
-</tr> +
-</thead> +
-<tbody>+
  
-    <!-- ===== COMMUNS ===== --> +let activeSpells [...document.querySelectorAll(".spell:checked")];
-      <tr class="Communs"><td class="race-Communs">Communs</td><td>Epuisement</td><td>Technique</td><td>Contact</td><td>/</td><td><span style="color: red;">Essouflement(X/2)</span></td><td>Autre</td><td>max 1</td><td>Ne fait pas de dégâtsJet de CC purEssouflement(X/2) où X est la différence des jets de dés.</td><td>effet immédiat, gain immédiat des malus, pas de statut, cumul possible</td><td>50 pos</td></tr> +
-      <tr class="Communs"><td class="race-Communs">Communs</td><td>Attaque précise</td><td>Technique</td><td>Contact</td><td>2 PM</td><td>+4 toucher, -3 dégâts</td><td>Autre</td><td>max 1</td><td>Bonus de +4 pour toucher, -3 dégâts.</td><td>/</td><td>50 pos</td></tr> +
-      <tr class="Communs"><td class="race-Communs">Communs</td><td>Attaque violente</td><td>Technique</td><td>Contact</td><td>4 PM</td><td>-6 toucher, +3 dégâts</td><td>Autre</td><td>max 1</td><td>Malus de -6 pour toucher, +3 dégâts.</td><td>/</td><td>50 pos</td></tr> +
-      <tr class="Communs"><td class="race-Communs">Communs</td><td>Croc-en-jambe</td><td>Technique</td><td>Contact</td><td>6 PM</td><td>Ralentissement(x2D2)</td><td>Autre</td><td>max 1</td><td>Ralentissement(x2D2)</td><td>non cumulable</td><td>100 pos</td></tr> +
-      <tr class="Communs"><td class="race-Communs">Communs</td><td>Manchette</td><td>Technique</td><td>Contact</td><td>2 PM</td><td>Maladresse(xX/2)</td><td>Autre</td><td>max 1</td><td>Ne fait pas de dégâts. Jet de CC pur. Si l'attaque touche, la cible aura Maladresse(xX/2) où X est la différence des jets de dés</td><td>non cumulable</td><td>100 pos</td></tr> +
-      <tr class="Communs"><td class="race-Communs">Communs</td><td>Arme infusée</td><td>Technique</td><td>Contact</td><td>8 PM</td><td>M/3</td><td>Autre</td><td>max 1</td><td>Bonus de +M/3 dégâts.</td><td>/</td><td>200 pos</td></tr>+
  
-    <!-- ===== NAINS ===== --> +let bestDex 0; 
-          <tr class="Nain"><td class="race-Nain">Nain</td><td>Assomoir</td><td>Technique</td><td>Contact</td><td>7 PM</td><td>+4</td><td>Autre</td><td>max 1</td><td>Ignore le casque (chance de critique). Jet basé sur CC.</td>/<td></td><td>200 po</td></tr> +let bestProt = 0;
-      <tr class="Nain"><td class="race-Nain">Nain</td><td>Barbier</td><td>Technique</td><td>Contact</td><td>8 PM</td><td></td><td>Autre</td><td>max 1</td><td>Soigne une cible au corps à corps ( la statistique utilisée pour le soin est l'agilité du lanceur)</td><td>/</td><td>100 po</td></tr> +
-      <tr class="Nain"><td class="race-Nain">Nain</td><td>Clé de bras</td><td>Technique</td><td>Contact</td><td>7 PM</td><td></td><td>Soi-même</td><td>0</td><td>Pare la prochaine attaque de mếlée et immobilise l'adversaire (uniquement à Mains nues).</td><td>/</td><td>200 po</td></tr> +
-      <tr class="Nain"><td class="race-Nain">Nain</td><td>Attaque Sautée</td><td>Technique</td><td>Contact</td><td>12 PM</td><td>+M</td><td>Autre</td><td>min 2</td><td>Avec une arme de mêlée, déplace immédiatement le personnage au contact de la cible et lui inflige des dégâts magiques. Pour ce sort, la carac de touche est la CC. L'attaquant fait en dégâts F+M et la cible encaisse avec E+M. </td><td>/</td><td>300 po</td></tr>+
  
-    <!-- ===== GÉANTS ===== --+activeSpells.forEach(s=>{ 
-    <tr class="Géant"> +let d +s.dataset.dex; 
-      <td class="race-Géant">Géant</td><td>Uppercut</td><td>Technique</td><td>Contact</td> +let p = +s.dataset.prot;
-      <td>8 PM</td><td>+3 dégâts (coup critique automatique)</td><td>Autre</td><td>max 1</td> +
-      <td>Inflige un coup critique automatique à une cible au contact : +3 dégâts sur la cible.</td><td>/</td><td>200 po</td> +
-    </tr>+
  
-    <tr class="Géant"> +if(Math.abs(d) Math.abs(bestDex)) bestDex d; 
-      <td class="race-Géant">Géant</td><td>Leurre</td><td>Technique</td><td>Contact</td> +if(Math.abs(p) Math.abs(bestProt)) bestProt = p; 
-      <td>8 PM</td><td></td><td>Soi-même</td><td>0</td> +});
-      <td>Leurre la prochaine attaque magique de l'adversaire.</td><td>/</td><td>200 po</td> +
-    </tr>+
  
-    <!-- ===== OLYMPIENS ===== --> +let char={...races[raceSelect.value]};
-    <tr class="Olympien"> +
-      <td class="race-Olympien">Olympien</td><td>Désarmement</td><td>Technique</td><td>Contact</td> +
-      <td>7 PM</td><td>+4</td><td>Autre</td><td>max 1</td> +
-      <td>Désarme l'adversaire ( % de chance que l'adversaire lâche son arme au sol).</td><td>/</td><td>200 po</td> +
-    </tr>+
  
-    <tr class="Olympien"> +// stats investies 
-      <td class="race-Olympien">Olympien</td><td>Parade</td><td>Technique</td><td>Contact</td> +for(let s in costTable){ 
-      <td>7 PM</td><td></td><td>Soi-même</td><td>0</td> +let v=+document.getElementById(s).value||0; 
-      <td>Pare la prochaine attaque de mêlée de l'adversaire (nécessite une arme de mêlée).</td><td>/</td><td>200 po</td> +char[s]=(char[s]||0)+v; 
-    </tr>+}
  
-    <!-- ===== HS ===== --> +// equip 
-    <tr class="HS"> +Object.values(slots).forEach(sel=>{ 
-      <td class="race-HS">HS</td><td>Griffes</td><td>Technique</td><td>Contact</td> +if(sel.value==="") return; 
-      <td>6 PM</td><td>+3 + poison + poison magique</td><td>Autre</td><td>max 1</td> +let e=equipments[sel.value]; 
-      <td>Inflige poison poison magique.</td><td>/</td><td>200 po</td> +for(let s in e.stats){ 
-    </tr>+char[s]=(char[s]||0)+e.stats[s]; 
 +
 +});
  
-    <!-- ===== ELFES ===== --> +// ===== DÉS ===== 
-    <tr class="Elfe"> +let ccDice char.cc * 2; 
-      <td class="race-Elfe">Elfe</td><td>Frappe vicieuse</td><td>Technique</td><td>Contact</td> +let ctDice char.ct * 2; 
-      <td>7 PM</td><td>+2</td><td>Autre</td><td>max 1</td> +let fmDice = char.fm * 2; 
-      <td>Ignore la pièce d'armure de tronc de l'adversaire.</td><td>/</td><td>200 po</td> +let agiDice = char.agi * 2;
-    </tr>+
  
-    <tr class="Elfe"> +// ===== VALEURS FINALES ====
-      <td class="race-Elfe">Elfe</td><td>Pas de côté</td><td>Technique</td><td>Contact</td> +let finalCC ccDice + bestDex; 
-      <td>7 PM 1 Mvt</td><td></td><td>Soi-même</td><td>0</td> +let finalCT = ctDice bestDex; 
-      <td>Esquive la prochaine attaque physique en se déplaçant aléatoirement d'une case.</td><td>/</td><td>200 po</td> +let finalFM = fmDice + bestDex;
-    </tr>+
  
-  </tbody> 
-</table> 
-</div> 
  
-<script> +// ===== CT DISTANCE ===== 
-// Script pour le second tableau +function getCTDistance(baseCT, distance){ 
-const select2 document.getElementById("raceSelect2"); +if(distance <2) return baseCT; 
-const rows2 document.querySelectorAll("#competencesTable2 tbody tr");+return baseCT - (distance - 2* 3; 
 +}
  
-select2.addEventListener("change"(=> { +let ct1 = getCTDistance(finalCT,1); 
-  const chosenRace = select2.value+let ct2 getCTDistance(finalCT,2); 
-  rows2.forEach(row => { +let ct3 getCTDistance(finalCT,3); 
-    const isCommun = row.classList.contains("Communs"); +let ct4 getCTDistance(finalCT,4);
-    const isRace row.classList.contains(chosenRace); +
-    row.style.display = (chosenRace === "Toutes" || isCommun || isRace? "" : "none"; +
-  }); +
-}); +
-</script>+
  
  
-<hr>+// ===== ESQUIVE =====
  
-<!-- ================= TABLEAU 3 : Techniques Distance ================= --> +let checked [...document.querySelectorAll(".skill:checked")].map(e=>e.dataset.name);
-<h3>Gestion des compétences — Techniques Distance</h3> +
-<label for="raceSelect3">Choisir une race :</label> +
-<select id="raceSelect3"> +
-  <option value="Toutes">Toutes</option> +
-  <option value="Communs">Communs</option> +
-  <option value="Nain">Nain</option> +
-  <option value="Géant">Géant</option> +
-  <option value="Olympien">Olympien</option> +
-  <option value="HS">HS</option> +
-  <option value="Elfe">Elfe</option> +
-</select>+
  
-<div class="table-container"> +// ===== ESQUIVE CAC ===== 
-<table id="competencesTable3"> +// règle : meilleur entre CC et AGI (dés), puis conversion jet + protection
-<thead> +
-<tr> +
-<th>Race</th><th>Nom</th><th>Type</th><th>Catégorie</th> +
-<th>Coût</th><th>Bonus / Malus</th><th>Cible</th><th>Portée</th> +
-<th>Description</th><th>Cumulable</th><th>Prix</th> +
-</tr> +
-</thead> +
-<tbody>+
  
-<!-- ================= COMMUNS ================= -->+let esquiveCAC Math.max(ccDice, agiDice);
  
-<tr class="Communs"> +// conversion en jet + protection 
-<td class="race-Communs">Communs</td><td>Tir épuisant</td><td>Technique</td><td>Tir munitions</td> +esquiveCAC = esquiveCAC + bestProt;
-<td>/</td><td>Essoufflement (X/3)</td><td>Autre</td><td>min 2</td> +
-<td>Ne fait pas de dégâts. Jet de CT pur. Essouflement(X/3) où X est la différence des jets de dés</td><td>Effet immédiat. Cumul possible.</td><td>50 pos</td> +
-</tr>+
  
  
-<tr class="Communs"> +// ===== ESQUIVE TIR ===== 
-<td class="race-Communs">Communs</td><td>Tir précis </td><td>Technique</td><td>Distance</td> +// règle : 
-<td>2 MP</td><td>+4 au toucher, -3 dégâts</td><td>Autre</td><td>min 2</td> +// max entre : 
-<td>Bonus +au toucher, Malus de aux dégâts </td><td>/</td><td>50 pos</td> +// (3/4 CC 1/AGI) 
-</tr>+// (1/4 CC + 3/4 AGI) 
 +// arrondi inférieur → dés → ×2 → + protection
  
-<tr class="Communs"> +let esquiveA Math.floor(char.cc * 0.75 + char.agi * 0.25); 
-<td class="race-Communs">Communs</td><td>Tir violent</td><td>Technique</td><td>Distance</td> +let esquiveB Math.floor(char.cc * 0.25 char.agi * 0.75);
-<td>2 MP</td><td>-6 au toucher, +2 dégâts</td><td>Autre</td><td>min 2</td> +
-<td>Malus de -6 pour toucher, bonus +2 dégâts</td><td>/</td><td>50 pos</td> +
-</tr>+
  
-<tr class="Communs"> +// passifs qui remplacent le calcul 
-<td class="race-Communs">Communs</td><td>Tir à la cheville</td><td>Technique</td><td>Tir munitions</td> +let esquiveStat;
-<td>6 MP</td><td>Ralentissement(x1D2)</td><td>Autre</td><td>min 2</td> +
-<td>Avec une arme à munitions, si la cible est touchée Ralentissement(x1D2)  </td><td>Non cumulable</td><td>100 pos</td> +
-</tr>+
  
-<tr class="Communs"> +if(checked.includes("Réflexes fulgurants")){ 
-<td class="race-Communs">Communs</td><td>Tir handicapant</td><td>Technique</td><td>Distance</td> +    esquiveStat Math.floor(char.agi * 0.85 + char.cc * 0.15); 
-<td>4 MP</td><td>Vulnérabilité (xX)</td><td>Autre</td><td>min 2</td> +
-<td>Ne fait pas de dégâts. Jet de CT purVulnérabilité (xXoù X est la différence entre le jet d'attaque et de défense /3</td><td>Non cumulable</td><td>100 pos</td> +else if(checked.includes("Couverture")){ 
-</tr>+    esquiveStat = Math.floor(char.cc * 0.85 + char.agi * 0.15); 
 +
 +else{ 
 +    esquiveStat = Math.max(esquiveA, esquiveB); 
 +}
  
-<tr class="Communs"> +// conversion en jet 
-<td class="race-Communs">Communs</td><td>Jet infusé</td><td>Technique</td><td>Jet</td> +let esquiveTir = esquiveStat * 2;
-<td>10 MP</td><td>M/3</td><td>Autre</td><td>min 2</td> +
-<td>Avec une arme de jet, +M/3 dmg</td><td>/</td><td>200 pos</td> +
-</tr>+
  
 +// protection (UNE seule fois)
 +esquiveTir += bestProt;
  
-  </tbody> +// bonus passifs 
-</table> +if(checked.includes("Fulgurance")) 
-</div>+    esquiveTir += 1;
  
-<script> 
-// Script pour le troisieme tableau 
-const select3 = document.getElementById("raceSelect3"); 
-const rows3 = document.querySelectorAll("#competencesTable3 tbody tr"); 
  
-select3.addEventListener("change", () => { +// ===== ESQUIVE MAGIQUE ===== 
-  const chosenRace select3.value; +// règle : FM en jet + protection
-  rows3.forEach(row => { +
-    const isCommun row.classList.contains("Communs"); +
-    const isRace row.classList.contains(chosenRace); +
-    row.style.display (chosenRace === "Toutes" || isCommun || isRace) ? "" : "none"; +
-  }); +
-}); +
-</script>+
  
 +let esquiveFM = fmDice + bestProt;
  
-<hr>+// ===== MAGIE ===== 
 +let jetFM = finalFM;
  
-<!-- ================= TABLEAU 4 : Furtivité ================= --> +let sorts = ""; 
-<h3>Gestion des compétences — Techniques Furtivité</h3> +for(let lvl=1; lvl<=5; lvl++){ 
-<label for="raceSelect4">Choisir une race :</label> +    let seuil 6 + 6 * lvl; 
-<select id="raceSelect4"> +    let reussite jetFM >= seuil ? """;
-  <option value="Toutes">Toutes</option> +
-  <option value="Communs">Communs</option> +
-  <option value="Nain">Nain</option> +
-  <option value="Géant">Géant</option> +
-  <option value="Olympien">Olympien</option> +
-  <option value="HS">HS</option> +
-  <option value="Elfe">Elfe</option> +
-</select>+
  
-<div class="table-container"> +    sorts +`Niveau ${lvl} → Seuil ${seuil} | Jet ${jetFM} ${reussite}\n`; 
-<table id="competencesTable4"> +}
-<thead> +
-<tr> +
-<th>Race</th><th>Nom</th><th>Type</th><th>Catégorie</th> +
-<th>Coût</th><th>Bonus / Malus</th><th>Cible</th><th>Portée</th> +
-<th>Description</th><th>Cumulable</th><th>Prix</th> +
-</tr> +
-</thead> +
-<tbody>+
  
 +// ===== AFFICHAGE =====
 +document.getElementById("spellBonus").innerText =
 +"Bonus actifs → Dex: "+bestDex+" | Protection: "+bestProt;
  
 +result.textContent =
  
 +"===== PERSONNAGE =====\n"+
 +"Race : "+raceSelect.value+
  
- <!-- ================= COMMUNS ================= -->+"\n\n===== STATS =====\n"+ 
 +JSON.stringify(char,null,2)+
  
- <tr class="Communs"> +"\n\n===== JET OFFENSIF =====\n"+ 
- <td class="race-Communs">Communs</td><td>Exploration</td><td>Technique</td><td>Personnel</td> +"\n⚔ CC : jet moyen "+ccDice+" ("+finalCC+")"+ 
- <td>Toutes les A restantes </td><td>+X P</td><td>Soi-même</td><td>/</td> +"\n🎯 CT : jet moyen "+ctDice+" ("+finalCT+")"+ 
- <td>Le personnage gagne Acuité visuelle (xoù x est le nombre d'actions dépensées jusqu'au prochain tour</td><td>/</td><td>50 pos</td> +"\n✨ FM : jet moyen "+fmDice+" ("+finalFM+")"+
- </tr>+
  
 +"\n\n===== JET DEFENSIF =====\n"+
 +"\n🛡 Esquive CAC : "+esquiveCAC+
 +"\n🏹 Esquive tir : "+esquiveTir+
 +"\n✨ Esquive FM : "+esquiveFM+
  
- <tr class="Communs"> +"\n\n===== JET DISTANCE =====\n"
- <td class="race-Communs">Communs</td><td>Discrétion</td><td>Technique</td><td>Personnel</td> +"\n🎯 CT distances :"+ 
- <td>X MP, Y Mvt </td><td></td><td>Soi-même</td><td>/</td> +"\n1 case : "+ct1+ 
- <td>Le personnage n'apparaîtra pas sur la carte générale jusqu'à son prochain tour. X= 2*(Furtivité+1). Y = 1/2*(Furtivité+1) (voir sous le tableau)</td><td>/</td><td>200 pos</td> +"\n2 cases : "+ct2+ 
- </tr>+"\n3 cases : "+ct3
 +"\n4 cases : "+ct4+
  
- <tr class="Communs"> +"\n\n===== MAGIE =====\n"+ 
- <td class="race-Communs">Communs</td><td>Camouflage (Olympien)</td><td>Technique</td><td>Personnel</td> +"Jet FM : "+jetFM+"\n\n"+ 
- <td>X MP, Y Mvt</td><td>/</td><td>Soi-même</td><td>/</td> +sorts; 
- <td>Apparaît sur la carte générale avec la Race choisie (Olympien) jusqu'à son prochain tour. X2*(Furtivité+1). Y 1/2*(Furtivité+1) (voir sous le tableau)</td><td>/</td><td>300 pos</td> +}
- </tr> +
-  +
- <tr class="Communs"> +
- <td class="race-Communs">Communs</td><td>Camouflage (Elfe)</td><td>Technique</td><td>Personnel</td> +
- <td>X MP, Y Mvt</td><td>/</td><td>Soi-même</td><td>/</td> +
- <td>Apparaît sur la carte générale avec la Race choisie (Elfe) jusqu'à son prochain tour. X2*(Furtivité+1). Y 1/2*(Furtivité+1) (voir sous le tableau)</td><td>/</td><td>300 pos</td> +
- </tr> +
-  +
- <tr class="Communs"> +
- <td class="race-Communs">Communs</td><td>Camouflage (HS)</td><td>Technique</td><td>Personnel</td> +
- <td>X MP, Y Mvt</td><td>/</td><td>Soi-même</td><td>/</td> +
- <td>Apparaît sur la carte générale avec la Race choisie (HS) jusqu'à son prochain tour. X= 2*(Furtivité+1). Y = 1/2*(Furtivité+1) (voir sous le tableau)</td><td>/</td><td>300 pos</td> +
- </tr> +
-  +
- <tr class="Communs"+
- <td class="race-Communs">Communs</td><td>Camouflage (Géant)</td><td>Technique</td><td>Personnel</td> +
- <td>X MP, Y Mvt</td><td>/</td><td>Soi-même</td><td>/</td> +
- <td>Apparaît sur la carte générale avec la Race choisie (Géant) jusqu'à son prochain tour. X= 2*(Furtivité+1). Y = 1/2*(Furtivité+1) (voir sous le tableau)</td><td>/</td><td>300 pos</td> +
- </tr> +
-  +
- <tr class="Communs"> +
- <td class="race-Communs">Communs</td><td>Camouflage (Nain)</td><td>Technique</td><td>Personnel</td> +
- <td>X MP, Y Mvt</td><td>/</td><td>Soi-même</td><td>/</td> +
- <td>Apparaît sur la carte générale avec la Race choisie (Nain) jusqu'à son prochain tour. X= 2*(Furtivité+1). Y = 1/2*(Furtivité+1) (voir sous le tableau)</td><td>/</td><td>300 pos</td> +
- </tr>+
  
-  </tbody> 
-</table> 
-</div> 
  
 +// ===== AUTO =====
 +function autoCalculate(){
 +updateCost();
 +calculate();
 +}
  
-  </tbody> +// events stats 
-</table+document.querySelectorAll("#stats input").forEach(i=>{ 
-</div>+i.addEventListener("input", autoCalculate); 
 +}); 
 + 
 +document.querySelectorAll(".spell").forEach(s=>
 +s.addEventListener("change", autoCalculate); 
 +});
  
-<script> 
-// Script pour le quatrieme tableau 
-const select4 = document.getElementById("raceSelect4"); 
-const rows4 = document.querySelectorAll("#competencesTable4 tbody tr"); 
  
-select4.addEventListener("change", (=> { +// passifs 
-  const chosenRace = select4.value; +document.querySelectorAll(".skill").forEach(s=>{ 
-  rows3.forEach(row => { +s.addEventListener("change", autoCalculate);
-    const isCommun = row.classList.contains("Communs"); +
-    const isRace = row.classList.contains(chosenRace); +
-    row.style.display = (chosenRace === "Toutes" || isCommun || isRace) ? "" : "none"; +
-  });+
 }); });
-</script> 
  
  
-</body> 
-</html> 
  
 +// ===== RESET =====
 +function resetAll(){
  
 +document.querySelectorAll("#stats input").forEach(i=>i.value=0);
 +document.querySelectorAll(".spell").forEach(s=>s.checked=false);
  
 +Object.values(slots).forEach(s=>{
 +s.value="";
 +s.disabled=false;
 +});
  
-**Fonctionnement de la carte sur Olympia** :  +document.querySelectorAll(".skill").forEach(s=>s.checked=false);
->1Tous les joueurs sur Olympia apparaissent en points noirs sur la carte du monde. +
-> +
->2) Dans un rayon de 15 cases autour de sa position, un joueur voit la couleur de la race des  autres personnages. +
-+
->3Si le personnage se déplace, la couleur se met à jour en fonction de la nouvelle position.+
  
-  +resetSlots(); 
-**Fonctionnement des compétences de discrétion **: +fillEquip(); 
->1Lorsque le personnage utilise la compétence "discrétion", il n'apparait plus sur la carte du monde __**jusqu'à sa prochaine activation**__. L'icone Furtivité apparait avec un décompte.  +displayBase(); 
-+checkLimit(); 
->Lors de son prochain tour, pour être de nouveau invisible sur la carte du monde, le joueur devra relancer la compétence "discrétion" (au plus tôt pour apparaitre le moins longtemps possible sur la carte du monde). +autoCalculate(); 
-+}
->2Pour éviter que ce soit trop simple de rester furtif, le coût augmente à mesure du nombre d'utilisations successives le compétence.  +
-+
->3) Utiliser une compétence de discrétion (Discrétion pour le momentajoute une charge de l'Effet "Furtivité" pour 48h qui se stack et dont la durée se réinitialise à chaque utilisation de Discrétion. Chaque charge de "Furtivité" augmente les coûts des compétences de discrétion.  +
-+
->4) Pour réinitialiser le coût des compétences de discrétion, il faut perdre l'effet Furtivité (donc ne pas utiliser de compétence de discrétion pendant 48h+
-+
->5)Avec la compétence Discrétion, __**on est invisible uniquement sur la carte globale et non sur les mini map (ville et sous plans)**__.+
  
 +// init
 +autoCalculate();
  
  
 +
 +// ===== POUSSEE =====
 +function calculatePush(){
 +
 +let F=+pushF.value;
 +let buff=+pushBuff.value;
 +
 +let E=+pushE.value;
 +let agi=+pushAgi.value;
 +let pv=+pushPV.value;
 +
 +let instability=+pushDebuff.value;
 +let stability=+pushStab.value;
 +
 +let attaque=F+buff;
 +let defense=Math.max(E+4,agi)+(pv/10)+instability+stability;
 +
 +pushResult.textContent=
 +"Attaque: "+attaque+
 +"\nDéfense: "+defense.toFixed(1)+
 +"\n"+(attaque>=defense?"✅ PUSH":"❌ FAIL");
 +}
 +
 +// ===== EVENTS =====
 +document.querySelectorAll("input").forEach(i=>i.addEventListener("input",()=>{
 +updateCost(); calculate(); calculatePush();
 +}));
 +
 +document.querySelectorAll("select").forEach(i=>i.addEventListener("change",()=>{
 +updateCost(); calculate(); calculatePush();
 +}));
 +
 +
 +// ===== INIT =====
 +updateCost();
 +calculate();
 +calculatePush();
 +
 +
 +// =====================================
 +// ENCODE / DECODE
 +// =====================================
 +
 +function encodeBuild(data){
 +    return encodeURIComponent(JSON.stringify(data));
 +}
 +
 +function decodeBuild(code){
 +    return JSON.parse(decodeURIComponent(code));
 +}
 +
 +// =====================================
 +// BUILD DATA
 +// =====================================
 +
 +function getBuildData(){
 +
 +    let data = {
 +        race: raceSelect.value,
 +        stats: {},
 +        equip: {},
 +        skills: [],
 +        spells: []
 +    };
 +
 +    // stats
 +    for(let s in costTable){
 +        data.stats[s] = +document.getElementById(s).value || 0;
 +    }
 +
 +    // équipements
 +    Object.entries(slots).forEach(([k,s])=>{
 +        data.equip[k] = s.value;
 +    });
 +
 +    // passifs
 +    document.querySelectorAll(".skill:checked").forEach(s=>{
 +        data.skills.push(s.dataset.name);
 +    });
 +
 +    // sorts
 +    document.querySelectorAll(".spell:checked").forEach(s=>{
 +        data.spells.push({
 +            dex: +s.dataset.dex,
 +            prot: +s.dataset.prot
 +        });
 +    });
 +
 +    return data;
 +}
 +
 +// =====================================
 +// APPLY BUILD
 +// =====================================
 +
 +function applyBuild(data){
 +
 +    // race
 +    raceSelect.value = data.race || "Elfe";
 +
 +    // recharge équipements race
 +    resetSlots();
 +    fillEquip();
 +
 +    // stats
 +    for(let s in costTable){
 +        document.getElementById(s).value =
 +            data.stats?.[s] || 0;
 +    }
 +
 +    // équipements
 +    Object.entries(slots).forEach(([k,s])=>{
 +        s.value = data.equip?.[k] || "";
 +    });
 +
 +    // passifs
 +    document.querySelectorAll(".skill").forEach(s=>{
 +        s.checked =
 +            data.skills?.includes(s.dataset.name);
 +    });
 +
 +    // sorts
 +    document.querySelectorAll(".spell").forEach(s=>{
 +
 +        s.checked = data.spells?.some(sp =>
 +            sp.dex == +s.dataset.dex &&
 +            sp.prot == +s.dataset.prot
 +        );
 +
 +    });
 +
 +    displayBase();
 +    checkLimit();
 +    autoCalculate();
 +}
 +
 +// =====================================
 +// EXPORT
 +// =====================================
 +
 +function exportBuild(){
 +
 +    let data = getBuildData();
 +
 +    let code = encodeBuild(data);
 +
 +    prompt("Copie ton build :", code);
 +}
 +
 +// =====================================
 +// IMPORT
 +// =====================================
 +
 +function importBuild(codeInput){
 +
 +    let code = codeInput;
 +
 +    if(!code){
 +        code = prompt("Colle le code du build :");
 +    }
 +
 +    if(!code) return;
 +
 +    try{
 +
 +        code = code.trim();
 +
 +        let data = decodeBuild(code);
 +
 +        applyBuild(data);
 +
 +        alert("✅ Build importé");
 +
 +    }catch(e){
 +
 +        console.log(e);
 +
 +        alert("❌ Code invalide");
 +    }
 +}
 +
 +// =====================================
 +// LIEN PARTAGE
 +// =====================================
 +
 +function copyLink(){
 +
 +    let data = getBuildData();
 +
 +    let code = encodeBuild(data);
 +
 +    let url =
 +        window.location.origin +
 +        window.location.pathname +
 +        "?id=simulateur&build=" + code;
 +
 +    navigator.clipboard.writeText(url).then(()=>{
 +
 +        alert("🔗 Lien copié !");
 +
 +    }).catch(()=>{
 +
 +        prompt("Copie ce lien :", url);
 +
 +    });
 +}
 +
 +// =====================================
 +// AUTO LOAD URL
 +// =====================================
 +
 +(function(){
 +
 +    try{
 +
 +        let params =
 +            new URLSearchParams(window.location.search);
 +
 +        let code = params.get("build");
 +
 +        if(!code) return;
 +
 +        let data = decodeBuild(code);
 +
 +        applyBuild(data);
 +
 +        console.log("✅ Build URL chargé");
 +
 +    }catch(e){
 +
 +        console.log("Erreur chargement URL", e);
 +
 +    }
 +
 +})();
 +
 +</script>
 +</body>
 +</html>
brouillon3.1776542762.txt.gz · Dernière modification : 2026/04/18 22:06 de nanaki