Outils pour utilisateurs

Outils du site


brouillon7

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
brouillon7 [2026/05/03 06:54] nanakibrouillon7 [2026/05/04 21:25] (Version actuelle) nanaki
Ligne 1: Ligne 1:
-Fiable+Voici un simulateur en version beta, n'hésitez pas à faire vos remarques sur le discord ou le forum. 
  
 <html> <html>
Ligne 13: Ligne 14:
   padding:10px;   padding:10px;
 } }
-h1,h2 { color:#facc15; } /* JAUNE LISBLE */ +h1,h2 { color:gold;} 
-.box { border:1px solid #facc15; padding:10px; margin-bottom:10px; }+.box { border:1px solid gold; padding:10px; margin-bottom:10px; }
 select { margin:3px; max-width:150px; } select { margin:3px; max-width:150px; }
 input { margin:3px; width:60px; } input { margin:3px; width:60px; }
Ligne 59: Ligne 60:
  
 <div class="box"> <div class="box">
-<h3>Sorts actifs (non cumulables)</h3>+<h3>Sorts actifs</h3>
 <div id="spells"></div> <div id="spells"></div>
 +<div id="spellBonus" class="small"></div>
 </div> </div>
  
 +
 +
 +<!-- ================= POUSSEE ================= -->
 <div class="box"> <div class="box">
 <h3>Simulateur de poussée</h3> <h3>Simulateur de poussée</h3>
  
-Force <input id="pushF" type="number" value="10">+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> Renforcement <select id="pushBuff"><option value="0">0</option><option value="6">+6</option></select><br>
  
Ligne 75: Ligne 80:
  
 Instabilité <select id="pushDebuff"><option value="0">0</option><option value="-6">-6</option></select> Instabilité <select id="pushDebuff"><option value="0">0</option><option value="-6">-6</option></select>
-Stabilité <select id="pushStab"> +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>
-<option value="0">0</option> +
-<option value="6">+6</option> +
-<option value="12">+12</option> +
-<option value="18">+18</option> +
-</select>+
  
 <pre id="pushResult" class="result"></pre> <pre id="pushResult" class="result"></pre>
Ligne 86: Ligne 86:
  
 <button onclick="resetAll()">Reset</button> <button onclick="resetAll()">Reset</button>
 +
 <pre id="result" class="result"></pre> <pre id="result" class="result"></pre>
  
Ligne 124: Ligne 125:
 {name:"Anguille",desc:"Avantage esquive"} {name:"Anguille",desc:"Avantage esquive"}
 ]; ];
 +
 +// ===== SORTS =====
 +const spells = [
 +{name:"Peau de granit",dex:0,prot:2},
 +{name:"Coup précis",dex:2,prot:0},
 +
 +{name:"Maladresse",dex:-2,prot:0},
 +{name:"Vulnérabilité",dex:0,prot:-2},
 +
 +{name:"Puissance de la nature",dex:2,prot:2},
 +
 +{name:"Aide",dex:4,prot:0},
 +{name:"Malchance",dex:-4,prot:0},
 +
 +{name:"Fatigue",dex:0,prot:-4},
 +{name:"Réflexes accrus",dex:0,prot:4},
 +
 +{name:"Bénédiction",dex:4,prot:4},
 +
 +{name:"Puissance du lutin capricieux",dex:-4,prot:-4},
 +
 +{name:"Exténuation",dex:0,prot:-8},
 +{name:"Sauvegarde",dex:0,prot:8},
 +{name:"Guigne",dex:-8,prot:0},
 +{name:"Virtuose",dex:8,prot:0}
 +];
 +
  
  
Ligne 246: Ligne 274:
  
  
-// ===== SORTS ===== +// ===== INIT =====
-const spells = [ +
-{name:"Peau de granit",effects:{protection:2}}, +
-{name:"Coup précis",effects:{dex:2}}, +
-{name:"Maladresse",effects:{maladresse:2}}, +
-{name:"Vulnérabilité",effects:{vulne:2}}, +
-{name:"Puissance de la nature",effects:{dex:2,protection:2}}, +
-{name:"Aide",effects:{dex:4}}, +
-{name:"Malchance",effects:{maladresse:4}}, +
-{name:"Fatigue",effects:{vulne:4}}, +
-{name:"Réflexes accrus",effects:{protection:4}}, +
-{name:"Bénédiction",effects:{dex:4,protection:4}}, +
-{name:"Puissance du lutin capricieux",effects:{maladresse:4,vulne:4}}, +
-{name:"Exténuation",effects:{vulne:8}}, +
-{name:"Sauvegarde",effects:{protection:8}}, +
-{name:"Guigne",effects:{maladresse:8}}, +
-{name:"Virtuose",effects:{dex:8}} +
-]; +
- +
-// ===== INIT UI =====+
 const raceSelect = document.getElementById("race"); const raceSelect = document.getElementById("race");
 const statsDiv = document.getElementById("stats"); const statsDiv = document.getElementById("stats");
Ligne 283: Ligne 292:
 } }
  
-// sorts UI +// passifs 
-spells.forEach((s,i)=>{+skills.forEach(s=>{ 
 +document.getElementById("skills").innerHTML += ` 
 +<label> 
 +<input type="checkbox" class="skill" data-name="${s.name}"> 
 +<b>${s.name}</b><br> 
 +<span class="small">${s.desc}</span> 
 +</label><br>`; 
 +})
 + 
 + 
 +// affichage sorts 
 +spells.forEach(s=>{
 document.getElementById("spells").innerHTML += ` document.getElementById("spells").innerHTML += `
-<label><input type="checkbox" class="spell" data-id="${i}">${s.name}</label><br>`;+<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>`;
 }); });
  
-// ===== BASE =====+// base stats
 function displayBase(){ function displayBase(){
 baseDiv.textContent = JSON.stringify(races[raceSelect.value],null,2); baseDiv.textContent = JSON.stringify(races[raceSelect.value],null,2);
Ligne 315: Ligne 339:
 total+=calcCost(b,m1,m2,v); total+=calcCost(b,m1,m2,v);
 } }
-cost.innerHTML="💰 PI : "+total;+document.getElementById("cost").innerHTML="💰 PI : "+total;
 } }
  
-// ===== SORT EFFECTS ===== +// ===== SLOTS ===== 
-function getSpellEffects(){ +const slots = { 
-let max={dex:0,protection:0,maladresse:0,vulne:0};+head:head,neck:neck,cape:cape,rightHand:rightHand, 
 +leftHand:leftHand,body:body,ring:ring,feet:feet 
 +};
  
-document.querySelectorAll(".spell:checked").forEach(el=>+function resetSlots(){ 
-let e=spells[el.dataset.id].effects; +Object.values(slots).forEach(s=>s.innerHTML="<option value=''>--</option>");
-for(let k in e)+
-if(Math.abs(e[k])>Math.abs(max[k])) max[k]=e[k];+
 } }
 +
 +function fillEquip(){
 +let r=raceSelect.value;
 +
 +equipments.forEach((e,i)=>{
 +if(e.race!=="all"&&e.race!==r) return;
 +
 +if(e.slot==="weapon"||e.slot==="weapon2h") rightHand.innerHTML+=`<option value="${i}">${e.name}</option>`;
 +if(e.slot==="offhand") leftHand.innerHTML+=`<option value="${i}">${e.name}</option>`;
 +if(e.slot==="body") body.innerHTML+=`<option value="${i}">${e.name}</option>`;
 +if(e.slot==="head") head.innerHTML+=`<option value="${i}">${e.name}</option>`;
 +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>`;
 }); });
-return max;+
 + 
 +raceSelect.addEventListener("change",()=>
 +resetSlots(); 
 +fillEquip(); 
 +autoCalculate(); 
 +}); 
 + 
 +resetSlots(); 
 +fillEquip(); 
 + 
 +// ===== 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; 
 +
 + 
 +const slotToStatId = { 
 +head:"headStats", 
 +neck:"neckStats", 
 +cape:"capeStats", 
 +rightHand:"rightStats", 
 +leftHand:"leftStats", 
 +body:"bodyStats", 
 +ring:"ringStats", 
 +feet:"feetStats" 
 +}; 
 + 
 +Object.entries(slots).forEach(([k,s])=>
 +s.addEventListener("change",()=>
 +displayStats(s, slotToStatId[k]); 
 +checkLimit(); 
 +autoCalculate(); 
 +}); 
 +}); 
 + 
 +// ===== LIMIT ===== 
 +function checkLimit(){ 
 +let count=0; 
 +Object.entries(slots).forEach(([k,s])=>
 +if(k!=="ring"&&s.value!=="") count++; 
 +}); 
 + 
 +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); 
 +}
 } }
  
 // ===== CALCUL ===== // ===== CALCUL =====
 +
 function calculate(){ function calculate(){
 +
 +let activeSpells = [...document.querySelectorAll(".spell:checked")];
 +
 +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;
 +});
  
 let char={...races[raceSelect.value]}; let char={...races[raceSelect.value]};
  
-// stats+// stats investies
 for(let s in costTable){ for(let s in costTable){
 let v=+document.getElementById(s).value||0; let v=+document.getElementById(s).value||0;
Ligne 342: Ligne 454:
 } }
  
-// effets +// equip 
-let effects=getSpellEffects();+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]; 
 +
 +});
  
-let ccFinal=char.cc+effects.dex-effects.maladresse+// ===== DÉS ===== 
-let ctFinal=char.ct+effects.dex-effects.maladresse+let ccDice = char.cc * 2
-let fmFinal=char.fm+effects.dex-effects.maladresse;+let ctDice = char.ct * 2
 +let fmDice = char.fm * 2;
  
-// esquive +// ===== VALEURS FINALES ===== 
-let esquive=Math.round(char.agi*0.75+char.cc*0.25)+let finalCC ccDice bestDex
-esquive+=effects.protection-effects.vulne;+let finalCT = ctDice bestDex; 
 +let finalFM fmDice + bestDex;
  
-// magie +// ===== CT DISTANCE ===== 
-let jetFM=fmFinal*2;+function getCTDistance(baseCT, distance){ 
 +if(distance <= 2) return baseCT; 
 +return baseCT - (distance - 2) * 3; 
 +}
  
-let sorts=""+let ct1 getCTDistance(finalCT,1)
-for(let lvl=1;lvl<=5;lvl++){ +let ct2 = getCTDistance(finalCT,2); 
-let seuil=6+6*lvl+let ct3 getCTDistance(finalCT,3); 
-sorts+=`Niveau ${lvl} → ${jetFM>=seuil?"":"❌"}\n`;+let ct4 getCTDistance(finalCT,4); 
 + 
 + 
 + 
 +// ===== ESQUIVE ===== 
 +let checked = [...document.querySelectorAll(".skill:checked")].map(e=>e.dataset.name); 
 + 
 +// CAC = jet CC direct 
 +let esquiveCAC finalCC; 
 + 
 +// ===== ESQUIVE TIR ===== 
 + 
 +// calcul des 2 formules en dés 
 +let esquiveA = Math.floor(char.cc * 0.75 char.agi 0.25)
 +let esquiveB = Math.floor(char.cc * 0.25 char.agi * 0.75); 
 + 
 +// choix du meilleur 
 +let esquiveStat Math.max(esquiveA, esquiveB); 
 + 
 +// ===== PASSIFS ===== 
 + 
 +// remplace complètement le calcul si passif spécifique 
 +if(checked.includes("Réflexes fulgurants")){ 
 +    esquiveStat = Math.floor(char.agi * 0.85 + char.cc * 0.15);
 } }
  
-// affichage +if(checked.includes("Couverture")){ 
-result.textContent=+    esquiveStat = Math.floor(char.cc * 0.85 + char.agi * 0.15); 
 +
 + 
 +// conversion en jet 
 +let esquive = esquiveStat * 2; 
 + 
 +// bonus 
 +if(checked.includes("Fulgurance")) 
 +    esquive += 1; 
 + 
 +// bonus protection 
 +esquive += bestProt; 
 + 
 + 
 +// ===== ESQUIVE MAGIQUE ===== 
 +let esquiveFM = Math.floor(finalFM + 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 = 
 +"===== STATS =====\n"+
 JSON.stringify(char,null,2)+ JSON.stringify(char,null,2)+
-"\nCC:"+ccFinal+ 
-"\nCT:"+ctFinal+"\n\n⚔ CC jet moyen "+ccDice+"  ("+finalCC+")"
-"\nFM:"+fmFinal+"\n🎯 CT jet moyen "+ctDice+"  ("+finalCT+")"
-"\nEsquive:"+esquive+ +"\n✨ FM jet moyen "+fmDice+"  ("+finalFM+")"+ 
-"\n\nMagie:\n"+sorts;+ 
 +"\n\n🛡 Esquive CAC : "+esquiveCAC+ 
 +"\n🏹 Esquive tir : "+esquive+ 
 +"\n✨ Esquive FM : "+esquiveFM+ 
 +"\n🏹 Esquive tir "+esquive+" ("+esquiveStat+" dés)" 
 + 
 +"\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;
 } }
  
-// ===== POUSSEE ===== 
-function calculatePush(){ 
-let atk=+pushF.value+ +pushBuff.value; 
-let def=Math.max(+pushE.value+4,+pushAgi.value) 
-+(+pushPV.value/10) 
-+ +pushDebuff.value 
-+ +pushStab.value; 
  
-pushResult.textContent+// ===== AUTO ====
-"Attaque:"+atk+ +function autoCalculate(){ 
-"\nDéfense:"+def.toFixed(1)+ +updateCost(); 
-"\n"+(atk>=def?"✅ PUSH":"❌ FAIL");+calculate();
 } }
  
-// ===== EVENTS ===== +// events stats 
-document.querySelectorAll("input,select").forEach(e=>{ +document.querySelectorAll("#stats input").forEach(i=>{ 
-e.addEventListener("input",()=>{updateCost();calculate();calculatePush();});+i.addEventListener("input", autoCalculate);
 }); });
 +
 +document.querySelectorAll(".spell").forEach(s=>{
 +s.addEventListener("change", autoCalculate);
 +});
 +
 +
 +// passifs
 +document.querySelectorAll(".skill").forEach(s=>{
 +s.addEventListener("change", autoCalculate);
 +});
 +
 +// ===== SORTS ACTIFS =====
 +
  
 // ===== RESET ===== // ===== RESET =====
 function resetAll(){ function resetAll(){
-document.querySelectorAll("input").forEach(i=>i.value=0);+ 
 +document.querySelectorAll("#stats input").forEach(i=>i.value=0);
 document.querySelectorAll(".spell").forEach(s=>s.checked=false); document.querySelectorAll(".spell").forEach(s=>s.checked=false);
-updateCost();calculate();calculatePush();+ 
 +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 ===== // ===== INIT =====
brouillon7.1777784074.txt.gz · Dernière modification : 2026/05/03 06:54 de nanaki