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

Prochaine révision
Révision précédente
brouillon3 [2026/04/18 22:01] – créée 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>
  
-<tr class="Communs"> +<div class="box"> 
-<td class="race-Communs">Communs</td><td>Arcanes précises</td><td>Sort</td><td>Offensif</td+<h3>Équipement (3 max + 1 anneau)</h3> 
-<td>6 MP</td><td>+4 au toucher</td><td>Autre</td><td>min 2</td+Tête <select id="head"></select> <span id="headStats"></span><br> 
-<td>Bonus de +4 pour toucher</td><td>/</td><td>50 pos</td+Cou <select id="neck"></select> <span id="neckStats"></span><br
-</tr>+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>
  
-<tr class="Communs"> +<div class="box"> 
-<td class="race-Communs">Communs</td><td>Arcanes violentes</td><td>Sort</td><td>Offensif</td+<h3>Passifs</h3
-<td>6 MP</td><td>-6 au toucher, +5 dégâts</td><td>Autre</td><td>min 2</td> +<div id="skills"></div
-<td>Malus de -6 pour toucher, bonus +5 dégâts</td><td>/</td><td>50 pos</td+</div>
-</tr>+
  
-<tr class="Communs"> +<div class="box"> 
-<td class="race-Communs">Communs</td><td>Aveuglement</td><td>Sort</td><td>Malédiction</td+<h3>Sorts actifs</h3
-<td>4 MP</td><td>-1 P</td><td>Autre</td><td>min 2</td+<div id="spells"></div
-<td>Aveuglement (x1)</td><td>non cumulable</td><td>50 pos</td+<div id="spellBonus" class="small"></div
-</tr>+</div>
  
-<tr class="Communs"> 
-<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"> 
-<td class="race-Communs">Communs</td><td>Épuisement arcanique</td><td>Sort</td><td>Malédiction</td> 
-<td>4 MP</td><td>Essoufflement (X/3)</td><td>Autre</td><td>min 2</td> 
-<td>Jet de FM pur. Essoufflement (X/3)</td><td>Effet immédiat. Cumul possible.</td><td>50 pos</td> 
-</tr> 
  
-<tr class="Communs"+<!-- ================= POUSSEE ================= --
-<td class="race-Communs">Communs</td><td>Maladresse</td><td>Sort</td><td>Malédiction</td+<div class="box"> 
-<td>4 MP</td><td>Maladresse (x2)</td><td>Autre</td><td>min 2</td> +<h3>Simulateur de poussée</h3>
-<td>Maladresse (x2)</td><td>non cumulable</td><td>50 pos</td> +
-</tr>+
  
-<tr class="Communs"> +Force assaillant <input id="pushF" type="number" value="10"> 
-<td class="race-Communs">Communs</td><td>Peau de granit</td><td>Sort</td><td>Bénédiction</td> +Renforcement <select id="pushBuff"><option value="0">0</option><option value="6">+6</option></select><br>
-<td>4 MP</td><td>Protection (x2)</td><td>Autre / Soi-même</td><td>max 1</td> +
-<td>Protection (x2)</td><td>non cumulable</td><td>50 pos</td> +
-</tr>+
  
-<tr class="Communs"+Endurance <input id="pushEtype="number" value="5"
-<td class="race-Communs">Communs</td><td>Restauration mineure</td><td>Sort</td><td>Bénédiction</td> +Agilité <input id="pushAgi" type="number" value="5"><br>
-<td>6 MP</td><td>-malus</td><td>Autre / Soi-même</td><td>max 1</td+
-<td>Enlève points de Malus</td><td>Effet immédiat, cumul possible</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>Vulnérabilité</td><td>Sort</td><td>Malédiction</td> +
-<td>6 MP</td><td>Vulnérabilité (x2)</td><td>Autre</td><td>min 2</td> +
-<td>Vulnérabilité (x2)</td><td>non cumulable</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>Enchevêtrement</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>6 MP</td><td>+1 dégât, Ralentissement (1D2)</td><td>Autre</td><td>min 2</td> +
-<td>Ralentissement (1D2)</td><td>non cumulable</td><td>100 pos</td> +
-</tr>+
  
-<!-- ================= RACES ================= -->+<pre id="pushResult" class="result"></pre> 
 +</div>
  
 +<button onclick="resetAll()">Reset</button>
  
-<tr class="HS"> +<button onclick="exportBuild()">📤 Export</button
-<td class="race-HS">HS</td><td>Dard</td><td>Sort</td><td>Offensif</td+<button onclick="importBuild()">📥 Import</button
-<td>3 PM</td><td>+1</td><td>Autre</td><td>min 2</td> +<button onclick="copyLink()">🔗 Lien</button>
-<td>Projette un dard sur l'adversaire.</td><td>/</td><td>100 po</td> +
-</tr>+
  
-<tr class="HS"+<pre id="result" class="result"></pre>
-<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 po</td> +
-</tr>+
  
-<tr class="HS"> +<script>
-<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 po</td> +
-</tr>+
  
 +// ===== RACES =====
 +const races = {
 +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},
 +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},
 +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="HS"> +// ===== COST ====
-<td class="race-HS">HS</td><td>Arme Vivante *</td><td>Sort</td><td>Offensif</td> +const costTable { 
-<td>12 PM</td><td>+M</td><td>Autre</td><td>max 1</td> +a:[800,200,100], 
-<td>Ajoute des dégâts magiques à une attaque avec une arme composée de bois (pétrifié ou non). La caractéristique de touche pour ce sort est la CC.</td><td>/</td><td>300 po</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="HS"> +// ===== PASSIFS ===== 
-<td class="race-HS">HS</td><td>Taillade illusoire</td><td>Sort</td><td>Offensif</td> +const skills = [ 
-<td>10 PM</td><td>+6</td><td>Autre</td><td>max 3</td> +{name:"Fulgurance",desc:"+1 toucher au cac + 1 esquive tous les 5 mouvements"}, 
-<td>Des crocs et des griffes spectraux assaillent votre adversaire de toute part.</td><td>/</td><td>300 po</td> +{name:"Couverture",desc:"85% CC 15% AGI"}, 
-</tr>+{name:"Réflexes fulgurants",desc:"85% AGI 15% CC"}, 
 +{name:"Berserker",desc:"+1 toucher au cac tous les 10 pv perdus"}, 
 +{name:"Griffes",desc:"+3 dégâts au poings"}, 
 +{name:"Anguille",desc:"Avantage esquive"} 
 +];
  
-<tr class="Elfe"> +// ===== SORTS ===== 
-<td class="race-Elfe">Elfe</td><td>Aiguillon</td><td>Sort</td><td>Offensif</td> +const spells = [ 
-<td>4 PM</td><td>+3</td><td>Autre</td><td>min 2</td> +{name:"Peau de granit",dex:0,prot:2}, 
-<td>Projette un aiguillon sur l’adversaire.</td><td>/</td><td>100 po</td> +{name:"Coup précis",dex:2,prot:0},
-</tr>+
  
-<tr class="Elfe"> +{name:"Maladresse",dex:-2,prot:0}, 
-<td class="race-Elfe">Elfe</td><td>Flèche Aquatique</td><td>Sort</td><td>Offensif</td> +{name:"Vulnérabilité",dex:0,prot:-2},
-<td>5 PM</td><td>+3 + effet Eau</td><td>Autre</td><td>min 2</td> +
-<td> Projette une flèche composée d'eau sur l'adversaire.</td><td>effet non cumulable</td><td>100 po</td> +
-</tr>+
  
-<tr class="Elfe"+{name:"Puissance de la nature",dex:2,prot:2},
-<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 po</td> +
-</tr>+
  
-<tr class="Elfe"> +{name:"Aide",dex:4,prot:0}, 
-<td class="race-Elfe">Elfe</td><td>Trait Béni *</td><td>Sort</td><td>Offensif</td> +{name:"Malchance",dex:-4,prot:0},
-<td>12 PM</td><td>+M</td><td>Autre</td><td>min 2</td> +
-<td>Ajoute des dégâts magiques lors d'une attaque au tir. La caractéristique de touche pour ce sort est la CT. L'attaquant fait en dégâts F+M et la cible encaisse avec E+M.</td><td>/</td><td>300 po</td> +
-</tr>+
  
-<tr class="Elfe"> +{name:"Fatigue",dex:0,prot:-4}, 
-<td class="race-Elfe">Elfe</td><td>Glaciation</td><td>Sort</td><td>Offensif</td> +{name:"Réflexes accrus",dex:0,prot:4},
-<td>8 PM</td><td>+6</td><td>Autre</td><td>max 2</td> +
-<td>Vous devenez froids comme l'hiver et propagez cette froideur à un ennemi proche.</td><td>/</td><td>300 po</td> +
-</tr>+
  
-<tr class="Géant"+{name:"Bénédiction",dex:4,prot:4},
-<td class="race-Géant">Géant</td><td>Aiguillon</td><td>Sort</td><td>Offensif</td> +
-<td>PM</td><td>+3</td><td>Autre</td><td>min 2</td> +
-<td>Projette un aiguillon sur l’adversaire.</td><td>/</td><td>100 po</td> +
-</tr>+
  
-<tr class="Géant"+{name:"Puissance du lutin capricieux",dex:-4,prot:-4},
-<td class="race-Géant">Géant</td><td>Boule de Magma</td><td>Sort</td><td>Offensif</td> +
-<td>7 PM</td><td>+3 + effet Feu</td><td>Autre</td><td>min 2</td> +
-<td>Lance une boule de lave en fusion sur l'adversairequi prend feu.</td><td>effet non cumulable</td><td>100 po</td> +
-</tr>+
  
-<tr class="Géant"> +{name:"Exténuation",dex:0,prot:-8}, 
-<td class="race-Géant">Géant</td><td>Régénération</td><td>Sort</td><td>Bénédiction</td> +{name:"Sauvegarde",dex:0,prot:8}, 
-<td>6 PM</td><td></td><td>Autre</td><td>max 1</td> +{name:"Guigne",dex:-8,prot:0}, 
-<td>Régénère la santé d'une cible au corps à corps. La cible est soignée à la hauteur de la R du lanceur. inflige poison au lanceur.</td><td>/</td><td>100 po</td> +{name:"Virtuose",dex:8,prot:0} 
-</tr>+];
  
-<tr class="Géant"> 
-<td class="race-Géant">Géant</td><td>Météore *</td><td>Sort</td><td>Offensif</td> 
-<td>12 PM</td><td>+M + effet Feu</td><td>Autre</td><td>min 2</td> 
-<td>Ajoute des dégâts magiques et de feu à une attaque au jet de pierre. La caractéristique de touche pour ce sort est la CT. Une pierre doit être équipée pour lancer le sort. L'attaquant fait en dégâts F+M et la cible encaisse avec E+M.</td><td>effet non cumulable</td><td>300 po</td> 
-</tr> 
  
-<tr class="Géant"> 
-<td class="race-Géant">Géant</td><td>Souffle des cimes</td><td>Sort</td><td>Offensif</td> 
-<td>8 PM</td><td>+6</td><td>Autre</td><td>max 2</td> 
-<td>Imprégné de la puissance de l'orage, vous rugissez un flot de foudre sur votre adversaire.</td><td>/</td><td>300 po</td> 
-</tr> 
  
 +const equipments = [
  
-<tr class="Nain"> +/* ================= COMMUNS ================= */
-<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 sur l’adversaire.</td><td>/</td><td>100 po</td> +
-</tr>+
  
-<tr class="Nain"> +{name:"Arc",race:"all",slot:"weapon2h",stats:{cc:-1,ct:1}}, 
-<td class="race-Nain">Nain</td><td>Poings de Pierre</td><td>Sort</td><td>Offensif</td> +{name:"Armure matelassée",race:"all",slot:"body",stats:{e:1,agi:-2}}, 
-<td>8 PM</td><td>+8</td><td>Autre</td><td>max 1</td> +{name:"Bâton de marche",race:"all",slot:"weapon",stats:{mvt:1}}, 
-<td>Vos poings deviennent durs comme de la roche millénaireque vous abattez sur vos ennemis.</td><td>/</td><td>300 po</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}},
  
 +/* ===== NOUVEAUX COMMUNS ===== */
  
-<tr class="Olympien"> +{name:"Torche",race:"all",slot:"weapon",stats:{cc:-2,f:-2}}, 
-<td class="race-Olympien">Olympien</td><td>Lame Volante</td><td>Sort</td><td>Offensif</td> +{name:"Hache de jet",race:"all",slot:"weapon",stats:{ct:1}}, 
-<td>4 PM</td><td>+3</td><td>Autre</td><td>min 2</td> +{name:"Pierre Noire",race:"all",slot:"weapon",stats:{f:1,cc:-1}}, 
-<td>Projette une lame magique sur l'adversaire.</td><td>/</td><td>100 po</td> +{name:"Main-gauche offensive",race:"all",slot:"offhand",stats:{cc:2,f:-1}},
-</tr>+
  
-<tr class="Olympien"> +/* ================= ELFES ================= */
-<td class="race-Olympien">Olympien</td><td>Imposition des Mains</td><td>Sort</td><td>Bénédiction</td> +
-<td>7 PM</td><td>+3</td><td>Autre</td><td>max 1</td> +
-<td>Toucher magique pour soigner un blessé.</td><td>/</td><td>100 po</td> +
-</tr>+
  
-<tr class="Olympien"> +{name:"Bâton du Pèlerin",race:"all",slot:"weapon",stats:{mvt:1,fm:1}}, 
-<td class="race-Olympien">Olympien</td><td>Lame Bénie *</td><td>Sort</td><td>Offensif</td> +{name:"Bottes Tâlroval",race:"all",slot:"feet",stats:{mvt:2}}, 
-<td>12 PM</td><td>+M</td><td>Autre</td><td>max 1</td> +{name:"Cuirasse",race:"all",slot:"body",stats:{e:1,r:2}}, 
-<td>Ajoute des dégâts magiques lors d'une attaque de mêlée. La caractéristique de touche pour ce sort 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> +{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="Olympien"> +// spécifique elfe 
-<td class="race-Olympien">Olympien</td><td>Soumission divine</td><td>Sort</td><td>Offensif</td> +{name:"Arc Elfique",race:"Elfe",slot:"weapon2h",stats:{ct:2,cc:-1}},
-<td>8 PM</td><td>+6</td><td>Autre</td><td>max 2</td> +
-<td>Vous vous approchez de votre cible et déferlez un torrent d'énergie divine dans sa direction.</td><td>/</td><td>300 po</td> +
-</tr>+
  
-</tbody> +/* ================= NAINS ================= */
-</table> +
-</div>+
  
-<script> +{name:"Cotte de mailles",race:"all",slot:"body",stats:{e:2,agi:-4}}, 
-// Script pour le premier tableau +{name:"Labrys",race:"all",slot:"weapon",stats:{cc:1,f:1}}, 
-const select1 = document.getElementById("raceSelect1"); +{name:"Marteau de guerre",race:"all",slot:"weapon2h",stats:{f:2,cc:-1}}, 
-const rows1 = document.querySelectorAll("#competencesTable1 tbody tr");+{name:"Targe renforcée naine",race:"all",slot:"offhand",stats:{cc:1,pv:10}}, 
 +{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}},
  
-select1.addEventListener("change", () => +// spécifiques nains 
-  const chosenRace = select1.value; +{name:"Bâton d'archimage",race:"Nain",slot:"weapon2h",stats:{m:2,fm:-1}}, 
-  rows1.forEach(row => { +{name:"Hache runique",race:"Nain",slot:"weapon",stats:{cc:1,f:2}},
-    const isCommun = row.classList.contains("Communs"); +
-    const isRace = row.classList.contains(chosenRace); +
-    row.style.display = (chosenRace === "Toutes" || isCommun || isRace) ? "" : "none"+
-  }); +
-}); +
-</script>+
  
-<hr>+/* ================= GÉANTS ================= */
  
-<!-- ================= TABLEAU 2 : Sorts ================= --> +{name:"Bouclier Clipeus",race:"all",slot:"offhand",stats:{e:1,pv:10}}, 
-<h3>Gestion des compétences — Techniques Corps à corps</h3> +{name:"Masse d'arme",race:"all",slot:"weapon",stats:{cc:1,f:1}}, 
-<label for="raceSelect2">Choisir une race :</label> +{name:"Hallebarde de pierre",race:"all",slot:"weapon",stats:{cc:2,f:-1}}, 
-<select id="raceSelect2"+{name:"Bâton de shaman",race:"Géant",slot:"weapon2h",stats:{fm:2,pv:-5}}, 
-  <option value="Toutes">Toutes</option> +{name:"Javelot lourd",race:"all",slot:"weapon",stats:{f:2,ct:-1,cc:-1}}, 
-  <option value="Communs">Communs</option> +{name:"Broigne",race:"all",slot:"body",stats:{e:2,f:-1}}, 
-  <option value="Nain">Nain</option> +{name:"Fétiche de shaman",race:"all",slot:"offhand",stats:{r:2,pm:5}}, 
-  <option value="Géant">Géant</option> +{name:"Bottes incandescentes",race:"all",slot:"feet",stats:{mvt:1,r:1,pv:5}}, 
-  <option value="Olympien">Olympien</option> +{name:"Médaillon hanté",race:"all",slot:"neck",stats:{cc:1,ct:1}},
-  <option value="HS">HS</option> +
-  <option value="Elfe">Elfe</option> +
-</select>+
  
-<div class="table-container"+// spécifique géant 
-<table id="competencesTable2"+{name:"Peau de granit manifiée",race:"Géant",slot:"body",stats:{m:1,rm:2,agi:-2}},
-<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 ===== --> +/* ================= HS ================= */
-      <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âts. Jet de CC pur. Essouflement(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 ===== --> +{name:"Bâton de sage",race:"all",slot:"weapon2h",stats:{m:1,agi:1}}, 
-          <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> +{name:"Orbe de mana",race:"all",slot:"weapon2h",stats:{m:1,rm:1}}, 
-      <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> +{name:"Cape de mage",race:"all",slot:"cape",stats:{fm:1,rm:1}}, 
-      <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> +{name:"Armure de fourrure",race:"all",slot:"body",stats:{e:2,rm:-3}}, 
-      <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éedéplace immédiatement le personnage au contact de la cible et lui inflige des dégâts magiques. Pour ce sortla 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>+{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}},
  
-    <!-- ===== GÉANTS ===== --> +// spécifiques HS 
-    <tr class="Géant"> +{name:"Manteau de feuillage",race:"HS",slot:"body",stats:{e:1,agi:2}}, 
-      <td class="race-Géant">Géant</td><td>Uppercut</td><td>Technique</td><td>Contact</td> +{name:"Bottes griffues",race:"HS",slot:"feet",stats:{cc:1,f:1,pv:5}},
-      <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"> +/* ================= OLYMPIENS ================= */
-      <td class="race-Géant">Géant</td><td>Leurre</td><td>Technique</td><td>Contact</td> +
-      <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 ===== --> +{name:"Armure hoplitique",race:"all",slot:"body",stats:{e:1,m:1}}, 
-    <tr class="Olympien"> +{name:"Bouclier Ancile",race:"all",slot:"offhand",stats:{e:1}}, 
-      <td class="race-Olympien">Olympien</td><td>Désarmement</td><td>Technique</td><td>Contact</td> +{name:"Diadème",race:"all",slot:"head",stats:{r:1,rm:2}}, 
-      <td>7 PM</td><td>+4</td><td>Autre</td><td>max 1</td> +{name:"Pilum",race:"all",slot:"weapon",stats:{ct:1,f:1,cc:-1}}, 
-      <td>Désarme l'adversaire ( % de chance que l'adversaire lâche son arme au sol).</td><td>/</td><td>200 po</td> +{name:"Spatha",race:"all",slot:"weapon",stats:{cc:1,f:1}}, 
-    </tr>+{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="Olympien"+// spécifique olympien 
-      <td class="race-Olympien">Olympien</td><td>Parade</td><td>Technique</td><td>Contact</td> +{name:"Lorica",race:"Olympien",slot:"body",stats:{e:2,agi:-2}},
-      <td>7 PM</td><td></td><td>Soi-même</td><td>0</td> +
-      <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> +
-    </tr>+
  
-    <!-- ===== HS ===== --> +/* ================= ANNEAUX ================= */
-    <tr class="HS"> +
-      <td class="race-HS">HS</td><td>Griffes</td><td>Technique</td><td>Contact</td> +
-      <td>6 PM</td><td>+3 + poison + poison magique</td><td>Autre</td><td>max 1</td> +
-      <td>Inflige poison + poison magique.</td><td>/</td><td>200 po</td> +
-    </tr>+
  
-    <!-- ===== ELFES ===== --> +{name:"Anneau Caprice",race:"all",slot:"ring",stats:{fm:1}}, 
-    <tr class="Elfe"> +{name:"Anneau Férocité",race:"all",slot:"ring",stats:{f:1}}, 
-      <td class="race-Elfe">Elfe</td><td>Frappe vicieuse</td><td>Technique</td><td>Contact</td> +{name:"Anneau Horizon",race:"all",slot:"ring",stats:{p:1}}, 
-      <td>7 PM</td><td>+2</td><td>Autre</td><td>max 1</td> +{name:"Anneau Prétention",race:"all",slot:"ring",stats:{ct:1}}, 
-      <td>Ignore la pièce d'armure de tronc de l'adversaire.</td><td>/</td><td>200 po</td> +{name:"Anneau Souplesse",race:"all",slot:"ring",stats:{agi:1}}, 
-    </tr>+{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="Elfe"> +];
-      <td class="race-Elfe">Elfe</td><td>Pas de côté</td><td>Technique</td><td>Contact</td> +
-      <td>7 PM + 1 Mvt</td><td></td><td>Soi-même</td><td>0</td> +
-      <td>Esquive la prochaine attaque physique en se déplaçant aléatoirement d'une case.</td><td>/</td><td>200 po</td> +
-    </tr>+
  
-  </tbody> 
-</table> 
-</div> 
  
-<script> +// ===== INIT ===== 
-// Script pour le second tableau +const raceSelect = document.getElementById("race"); 
-const select2 = document.getElementById("raceSelect2"); +const statsDiv = document.getElementById("stats"); 
-const rows2 = document.querySelectorAll("#competencesTable2 tbody tr");+const baseDiv = document.getElementById("baseStats");
  
-select2.addEventListener("change", () => { +for(let r in races){ 
-  const chosenRace select2.value; +raceSelect.innerHTML += `<option>${r}</option>`; 
-  rows2.forEach(row => { +
-    const isCommun = row.classList.contains("Communs")+ 
-    const isRace = row.classList.contains(chosenRace); +// stats UI 
-    row.style.display = (chosenRace === "Toutes|| isCommun || isRace) ? "" "none"; +for(let s in costTable)
-  });+statsDiv.innerHTML +
 +<div class="statLine"> 
 +<span>${s}</span> 
 +<input type="number" id="${s}" value="0" min="0"> 
 +</div>`
 +
 + 
 +// passifs 
 +skills.forEach(s=>{ 
 +document.getElementById("skills").innerHTML += ` 
 +<label> 
 +<input type="checkboxclass="skilldata-name="${s.name}"> 
 +<b>${s.name}</b><br> 
 +<span class="small">${s.desc}</span> 
 +</label><br>`;
 }); });
-</script> 
  
  
-<hr>+// affichage sorts 
 +spells.forEach(s=>
 +document.getElementById("spells").innerHTML += ` 
 +<label> 
 +<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>`; 
 +});
  
-<!-- ================= TABLEAU 3 : Techniques Distance ================= --> +// base stats 
-<h3>Gestion des compétences — Techniques Distance</h3> +function displayBase(){ 
-<label for="raceSelect3">Choisir une race :</label> +baseDiv.textContent JSON.stringify(races[raceSelect.value],null,2); 
-<select id="raceSelect3"> +} 
-  <option value="Toutes">Toutes</option> +raceSelect.addEventListener("change", displayBase); 
-  <option value="Communs">Communs</option> +displayBase();
-  <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"> +// ===== COST ===== 
-<table id="competencesTable3"> +function calcCost(b,m1,m2,n){ 
-<thead> +let total=0,last=b; 
-<tr> +for(let i=1;i<=n;i++){ 
-<th>Race</th><th>Nom</th><th>Type</th><th>Catégorie</th> +if(i===1) last=b; 
-<th>Coût</th><th>Bonus / Malus</th><th>Cible</th><th>Portée</th> +else if(i<=3) last+=m1; 
-<th>Description</th><th>Cumulable</th><th>Prix</th> +else last+=m2; 
-</tr> +total+=last; 
-</thead> +} 
-<tbody>+return total; 
 +}
  
-<!-- ================= COMMUNS ================= -->+function updateCost(){ 
 +let total=0; 
 +for(let s in costTable){ 
 +let v=+document.getElementById(s).value||0; 
 +let [b,m1,m2]=costTable[s]; 
 +total+=calcCost(b,m1,m2,v); 
 +
 +document.getElementById("cost").innerHTML="💰 PI : "+total; 
 +}
  
-<tr class="Communs"> +// ===== SLOTS ====
-<td class="race-Communs">Communs</td><td>Tir épuisant</td><td>Technique</td><td>Tir munitions</td> +const slots { 
-<td>/</td><td>Essoufflement (X/3)</td><td>Autre</td><td>min 2</td> +head:head,neck:neck,cape:cape,rightHand:rightHand, 
-<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> +leftHand:leftHand,body:body,ring:ring,feet:feet 
-</tr>+};
  
 +function resetSlots(){
 +Object.values(slots).forEach(s=>s.innerHTML="<option value=''>--</option>");
 +}
  
-<tr class="Communs"> +function fillEquip(){ 
-<td class="race-Communs">Communs</td><td>Tir précis </td><td>Technique</td><td>Distance</td> +let r=raceSelect.value;
-<td>2 MP</td><td>+4 au toucher, -3 dégâts</td><td>Autre</td><td>min 2</td> +
-<td>Bonus +4 au toucher, Malus de 3 aux dégâts </td><td>/</td><td>50 pos</td> +
-</tr>+
  
-<tr class="Communs"+equipments.forEach((e,i)=>{ 
-<td class="race-Communs">Communs</td><td>Tir violent</td><td>Technique</td><td>Distance</td> +if(e.race!=="all"&&e.race!==r) return;
-<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"+if(e.slot==="weapon"||e.slot==="weapon2h") rightHand.innerHTML+=`<option value="${i}">${e.name}</option>`; 
-<td class="race-Communs">Communs</td><td>Tir à la cheville</td><td>Technique</td><td>Tir munitions</td+if(e.slot==="offhand") leftHand.innerHTML+=`<option value="${i}">${e.name}</option>`; 
-<td>6 MP</td><td>Ralentissement(x1D2)</td><td>Autre</td><td>min 2</td+if(e.slot==="body") body.innerHTML+=`<option value="${i}">${e.name}</option>`; 
-<td>Avec une arme à munitions, si la cible est touchée Ralentissement(x1D2 </td><td>Non cumulable</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="Communs"+raceSelect.addEventListener("change",()=>{ 
-<td class="race-Communs">Communs</td><td>Tir handicapant</td><td>Technique</td><td>Distance</td+resetSlots(); 
-<td>4 MP</td><td>Vulnérabilité (xX)</td><td>Autre</td><td>min 2</td> +fillEquip(); 
-<td>Ne fait pas de dégâts. Jet de CT pur. Vulné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> +autoCalculate(); 
-</tr>+});
  
-<tr class="Communs"> +resetSlots(); 
-<td class="race-Communs">Communs</td><td>Jet infusé</td><td>Technique</td><td>Jet</td> +fillEquip();
-<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>+
  
 +// ===== BONUS =====
 +function displayStats(select,id){
 +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;
 +}
  
-  </tbody> +const slotToStatId = { 
-</table> +head:"headStats", 
-</div>+neck:"neckStats", 
 +cape:"capeStats", 
 +rightHand:"rightStats", 
 +leftHand:"leftStats", 
 +body:"bodyStats", 
 +ring:"ringStats", 
 +feet:"feetStats" 
 +};
  
-<script+Object.entries(slots).forEach(([k,s])=>{ 
-// Script pour le troisieme tableau +s.addEventListener("change",()=>{ 
-const select3 = document.getElementById("raceSelect3"); +displayStats(s, slotToStatId[k]); 
-const rows3 = document.querySelectorAll("#competencesTable3 tbody tr");+checkLimit(); 
 +autoCalculate(); 
 +}); 
 +});
  
-select3.addEventListener("change", () => +// ===== LIMIT ===== 
-  const chosenRace select3.value+function checkLimit(){ 
-  rows3.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> 
  
 +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);
 +}
 +}
  
-<hr>+// ===== CALCUL =====
  
-<!-- ================= TABLEAU 4 : Furtivité ================= --> +function calculate(){
-<h3>Gestion des compétences — Techniques Furtivité</h3> +
-<label for="raceSelect4">Choisir une race :</label> +
-<select id="raceSelect4"> +
-  <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"+let activeSpells [...document.querySelectorAll(".spell:checked")];
-<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>+
  
 +let bestDex = 0;
 +let bestProt = 0;
  
 +activeSpells.forEach(s=>{
 +let d = +s.dataset.dex;
 +let p = +s.dataset.prot;
  
 +if(Math.abs(d) > Math.abs(bestDex)) bestDex = d;
 +if(Math.abs(p) > Math.abs(bestProt)) bestProt = p;
 +});
  
- <!-- ================= COMMUNS ================= -->+let char={...races[raceSelect.value]};
  
- <tr class="Communs"> +// stats investies 
- <td class="race-Communs">Communs</td><td>Exploration</td><td>Technique</td><td>Personnel</td> +for(let s in costTable){ 
- <td>Toutes les A restantes </td><td>+X P</td><td>Soi-même</td><td>/</td> +let v=+document.getElementById(s).value||0; 
- <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> +char[s]=(char[s]||0)+v; 
- </tr>+}
  
 +// equip
 +Object.values(slots).forEach(sel=>{
 +if(sel.value==="") return;
 +let e=equipments[sel.value];
 +for(let s in e.stats){
 +char[s]=(char[s]||0)+e.stats[s];
 +}
 +});
  
- <tr class="Communs"> +// ===== DÉS ===== 
- <td class="race-Communs">Communs</td><td>Discrétion</td><td>Technique</td><td>Personnel</td> +let ccDice char.cc * 2; 
- <td>X MP, Y Mvt </td><td></td><td>Soi-même</td><td>/</td> +let ctDice char.ct * 2
- <td>Le personnage n'apparaîtra pas sur la carte générale jusqu'à son prochain tour. X2*(Furtivité+1)1/2*(Furtivité+1) (voir sous le tableau)</td><td>/</td><td>200 pos</td> +let fmDice = char.fm 2; 
- </tr>+let agiDice = char.agi * 2;
  
- <tr class="Communs"> +// ===== VALEURS FINALES ===== 
- <td class="race-Communs">Communs</td><td>Camouflage (Olympien)</td><td>Technique</td><td>Personnel</td> +let finalCC ccDice + bestDex; 
- <td>X MP, Y Mvt</td><td>/</td><td>Soi-même</td><td>/</td> +let finalCT ctDice bestDex; 
- <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> +let finalFM fmDice bestDex;
- </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. 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 (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> 
  
 +// ===== CT DISTANCE =====
 +function getCTDistance(baseCT, distance){
 +if(distance <= 2) return baseCT;
 +return baseCT - (distance - 2) * 3;
 +}
  
-  </tbody> +let ct1 = getCTDistance(finalCT,1); 
-</table> +let ct2 = getCTDistance(finalCT,2); 
-</div>+let ct3 = getCTDistance(finalCT,3); 
 +let ct4 = getCTDistance(finalCT,4);
  
-<script> 
-// Script pour le quatrieme tableau 
-const select4 = document.getElementById("raceSelect4"); 
-const rows4 = document.querySelectorAll("#competencesTable4 tbody tr"); 
  
-select4.addEventListener("change", () => { +// ===== ESQUIVE ===== 
-  const chosenRace select4.value+ 
-  rows3.forEach(row =+let checked = [...document.querySelectorAll(".skill:checked")].map(e=>e.dataset.name); 
-    const isCommun row.classList.contains("Communs"); + 
-    const isRace row.classList.contains(chosenRace); +// ===== ESQUIVE CAC ===== 
-    row.style.display = (chosenRace === "Toutes" || isCommun || isRace"" : "none"; +// règle : meilleur entre CC et AGI (dés), puis conversion jet + protection 
-  });+ 
 +let esquiveCAC = Math.max(ccDice, agiDice)
 + 
 +// conversion en jet + protection 
 +esquiveCAC = esquiveCAC + bestProt; 
 + 
 + 
 +// ===== ESQUIVE TIR ===== 
 +// règle : 
 +// max entre : 
 +// (3/4 CC + 1/4 AGI) 
 +// (1/4 CC + 3/4 AGI) 
 +// arrondi inférieur → dés → ×2 → + protection 
 + 
 +let esquiveA = Math.floor(char.cc * 0.75 + char.agi * 0.25); 
 +let esquiveB Math.floor(char.cc * 0.25 + char.agi * 0.75); 
 + 
 +// passifs qui remplacent le calcul 
 +let esquiveStat; 
 + 
 +if(checked.includes("Réflexes fulgurants"))
 +    esquiveStat Math.floor(char.agi * 0.85 + char.cc * 0.15); 
 +
 +else if(checked.includes("Couverture")){ 
 +    esquiveStat Math.floor(char.cc * 0.85 + char.agi * 0.15); 
 +
 +else{ 
 +    esquiveStat = Math.max(esquiveA, esquiveB); 
 +
 + 
 +// conversion en jet 
 +let esquiveTir = esquiveStat * 2; 
 + 
 +// protection (UNE seule fois) 
 +esquiveTir += bestProt; 
 + 
 +// bonus passifs 
 +if(checked.includes("Fulgurance")) 
 +    esquiveTir +1; 
 + 
 + 
 +// ===== ESQUIVE MAGIQUE ===== 
 +// règle : FM en jet + protection 
 + 
 +let esquiveFM = fmDice + bestProt; 
 + 
 +// ===== MAGIE ===== 
 +let jetFM = finalFM; 
 + 
 +let sorts = ""; 
 +for(let lvl=1; lvl<=5; lvl++){ 
 +    let seuil 6 + 6 * lvl; 
 +    let reussite = jetFM >= seuil ? ": "❌"; 
 + 
 +    sorts += `Niveau ${lvl} → Seuil ${seuil} Jet ${jetFM} ${reussite}\n`; 
 +
 + 
 +// ===== AFFICHAGE ===== 
 +document.getElementById("spellBonus").innerText = 
 +"Bonus actifs → Dex: "+bestDex+" Protection: "+bestProt; 
 + 
 +result.textContent = 
 + 
 +"===== PERSONNAGE =====\n"
 +"Race : "+raceSelect.value+ 
 + 
 +"\n\n===== STATS =====\n"
 +JSON.stringify(char,null,2)
 + 
 +"\n\n===== JET OFFENSIF =====\n"
 +"\n⚔ CC jet moyen "+ccDice+("+finalCC+")"
 +"\n🎯 CT : jet moyen "+ctDice+" ("+finalCT+")"
 +"\n✨ FM : jet moyen "+fmDice+" ("+finalFM+")"
 + 
 +"\n\n===== JET DEFENSIF =====\n"
 +"\n🛡 Esquive CAC : "+esquiveCAC+ 
 +"\n🏹 Esquive tir : "+esquiveTir+ 
 +"\n✨ Esquive FM : "+esquiveFM+ 
 + 
 +"\n\n===== JET DISTANCE =====\n"
 +"\n🎯 CT distances :"+ 
 +"\n1 case : "+ct1+ 
 +"\n2 cases : "+ct2+ 
 +"\n3 cases : "+ct3+ 
 +"\n4 cases : "+ct4+ 
 + 
 +"\n\n===== MAGIE =====\n"
 +"Jet FM : "+jetFM+"\n\n"
 +sorts
 +} 
 + 
 + 
 +// ===== AUTO ===== 
 +function autoCalculate(){ 
 +updateCost(); 
 +calculate(); 
 +
 + 
 +// events stats 
 +document.querySelectorAll("#stats input").forEach(i=>
 +i.addEventListener("input", autoCalculate);
 }); });
-</script> 
  
 +document.querySelectorAll(".spell").forEach(s=>{
 +s.addEventListener("change", autoCalculate);
 +});
  
-</body> 
-</html> 
  
 +// passifs
 +document.querySelectorAll(".skill").forEach(s=>{
 +s.addEventListener("change", autoCalculate);
 +});
  
  
  
-**Fonctionnement de la carte sur Olympia** :  +// ===== RESET ===== 
->1Tous les joueurs sur Olympia apparaissent en points noirs sur la carte du monde. +function resetAll(){
-+
->2) Dans un rayon de 15 cases autour de sa position, un joueur voit la couleur de la race des  autres personnages. +
-+
->3) Si le personnage se déplace, la couleur se met à jour en fonction de la nouvelle position.+
  
-  +document.querySelectorAll("#stats input").forEach(i=>i.value=0); 
-**Fonctionnement des compétences de discrétion **: +document.querySelectorAll(".spell").forEach(s=>s.checked=false);
->1) Lorsque 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.  +
-+
->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). +
-+
->2) Pour é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 moment) ajoute une charge de l'Effet "Furtivité" pour 48h qui se stack et dont la durée se réinitialise à chaque utilisation de DiscrétionChaque 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)**__.+
  
 +Object.values(slots).forEach(s=>{
 +s.value="";
 +s.disabled=false;
 +});
  
 +document.querySelectorAll(".skill").forEach(s=>s.checked=false);
  
 +resetSlots();
 +fillEquip();
 +displayBase();
 +checkLimit();
 +autoCalculate();
 +}
 +
 +// 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.1776542512.txt.gz · Dernière modification : 2026/04/18 22:01 de nanaki