simulateur
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Prochaine révision | Révision précédente | ||
| simulateur [2026/04/29 20:30] – créée nanaki | simulateur [2026/05/20 16:46] (Version actuelle) – nanaki | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| - | < | + | Voici un simulateur en version beta, n' |
| + | |||
| < | < | ||
| < | < | ||
| Ligne 9: | Ligne 11: | ||
| font-family: | font-family: | ||
| background:# | background:# | ||
| - | color:#e0d3a3; | + | color:#7dd3fc; |
| padding: | padding: | ||
| } | } | ||
| - | |||
| h1,h2 { color: | h1,h2 { color: | ||
| - | + | .box { border:1px solid gold; padding: | |
| - | .box { | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | } | + | |
| select { margin:3px; max-width: | select { margin:3px; max-width: | ||
| - | input { margin:3px; width:50px; } | + | input { margin:3px; width:60px; } |
| - | + | .statLine { display: | |
| - | .statLine { | + | .result { background:# |
| - | | + | .small { font-size: |
| - | | + | |
| - | | + | |
| - | } | + | |
| - | + | ||
| - | .result { | + | |
| - | | + | |
| - | | + | |
| - | } | + | |
| </ | </ | ||
| </ | </ | ||
| Ligne 39: | Ligne 26: | ||
| < | < | ||
| - | < | + | <h1>🎲 Simulateur</ |
| <div class=" | <div class=" | ||
| Race : | Race : | ||
| <select id=" | <select id=" | ||
| - | |||
| < | < | ||
| <pre id=" | <pre id=" | ||
| Ligne 57: | Ligne 43: | ||
| <div class=" | <div class=" | ||
| < | < | ||
| - | |||
| Tête <select id=" | Tête <select id=" | ||
| Cou <select id=" | Cou <select id=" | ||
| Ligne 66: | Ligne 51: | ||
| Anneau <select id=" | Anneau <select id=" | ||
| Pieds <select id=" | Pieds <select id=" | ||
| - | |||
| <div id=" | <div id=" | ||
| </ | </ | ||
| Ligne 75: | Ligne 59: | ||
| </ | </ | ||
| - | <button onclick=" | + | <div class=" |
| + | < | ||
| + | <div id=" | ||
| + | <div id=" | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | <!-- ================= POUSSEE ================= --> | ||
| + | <div class=" | ||
| + | < | ||
| + | |||
| + | Force assaillant <input id=" | ||
| + | Renforcement <select id=" | ||
| + | |||
| + | Endurance <input id=" | ||
| + | Agilité <input id=" | ||
| + | |||
| + | PV actuels <input id=" | ||
| + | |||
| + | Instabilité <select id=" | ||
| + | Stabilité <select id=" | ||
| + | |||
| + | <pre id=" | ||
| + | </ | ||
| + | |||
| + | <button onclick=" | ||
| + | |||
| + | <button onclick=" | ||
| + | <button onclick=" | ||
| + | <button onclick=" | ||
| <pre id=" | <pre id=" | ||
| Ligne 83: | Ligne 97: | ||
| // ===== RACES ===== | // ===== RACES ===== | ||
| const races = { | const races = { | ||
| - | Elfe: | + | Elfe:{a:2,cc: |
| - | Nain: | + | Nain:{a:2,cc: |
| - | Géant: | + | Géant:{a:2,cc: |
| - | Olympien: | + | Olympien:{a:2,cc: |
| - | HS: | + | HS:{a:2,cc: |
| }; | }; | ||
| // ===== COST ===== | // ===== COST ===== | ||
| const costTable = { | const costTable = { | ||
| + | a: | ||
| cc: | cc: | ||
| f: | f: | ||
| Ligne 107: | Ligne 122: | ||
| // ===== PASSIFS ===== | // ===== PASSIFS ===== | ||
| const skills = [ | const skills = [ | ||
| - | " | + | {name:" |
| - | "Anguille"," | + | {name:"Couverture", |
| + | {name:"Réflexes fulgurants",desc:"85% AGI / 15% CC"}, | ||
| + | {name:"Berserker", | ||
| + | {name:" | ||
| + | {name:" | ||
| ]; | ]; | ||
| - | // ===== ÉQUIPEMENTS | + | // ===== SORTS ===== |
| + | const spells = [ | ||
| + | {name:" | ||
| + | {name:" | ||
| + | |||
| + | {name:" | ||
| + | {name:" | ||
| + | |||
| + | {name:" | ||
| + | |||
| + | {name:" | ||
| + | {name:" | ||
| + | |||
| + | {name:" | ||
| + | {name:" | ||
| + | |||
| + | {name:" | ||
| + | |||
| + | {name:" | ||
| + | |||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | ]; | ||
| + | |||
| + | |||
| const equipments = [ | const equipments = [ | ||
| Ligne 133: | Ligne 179: | ||
| {name:" | {name:" | ||
| {name:" | {name:" | ||
| + | |||
| + | /* ===== NOUVEAUX COMMUNS ===== */ | ||
| + | |||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| /* ================= ELFES ================= */ | /* ================= ELFES ================= */ | ||
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| + | |||
| + | // spécifique elfe | ||
| + | {name:" | ||
| /* ================= NAINS ================= */ | /* ================= NAINS ================= */ | ||
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| + | |||
| + | // spécifiques nains | ||
| + | {name:" | ||
| + | {name:" | ||
| /* ================= GÉANTS ================= */ | /* ================= GÉANTS ================= */ | ||
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| {name:" | {name:" | ||
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| + | |||
| + | // spécifique géant | ||
| + | {name:" | ||
| /* ================= HS ================= */ | /* ================= HS ================= */ | ||
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| + | |||
| + | // spécifiques HS | ||
| + | {name:" | ||
| + | {name:" | ||
| /* ================= OLYMPIENS ================= */ | /* ================= OLYMPIENS ================= */ | ||
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| - | {name:" | + | {name:" |
| + | |||
| + | // spécifique olympien | ||
| + | {name:" | ||
| /* ================= ANNEAUX ================= */ | /* ================= ANNEAUX ================= */ | ||
| Ligne 206: | Ligne 276: | ||
| ]; | ]; | ||
| - | |||
| - | |||
| - | |||
| Ligne 216: | Ligne 283: | ||
| const baseDiv = document.getElementById(" | const baseDiv = document.getElementById(" | ||
| - | // races | ||
| for(let r in races){ | for(let r in races){ | ||
| raceSelect.innerHTML += `< | raceSelect.innerHTML += `< | ||
| Ligne 222: | Ligne 288: | ||
| // stats UI | // stats UI | ||
| - | const statOrder = [" | + | for(let s in costTable){ |
| - | const statNames = { | + | |
| - | cc:" | + | |
| - | agi:" | + | |
| - | p:" | + | |
| - | mvt:" | + | |
| - | }; | + | |
| - | + | ||
| - | statOrder.forEach(s=>{ | + | |
| statsDiv.innerHTML += ` | statsDiv.innerHTML += ` | ||
| <div class=" | <div class=" | ||
| - | < | + | < |
| <input type=" | <input type=" | ||
| </ | </ | ||
| - | }); | + | } |
| // passifs | // passifs | ||
| skills.forEach(s=> | skills.forEach(s=> | ||
| - | document.getElementById(" | + | document.getElementById(" |
| + | < | ||
| + | <input type=" | ||
| + | <b>${s.name}</ | ||
| + | <span class=" | ||
| + | </ | ||
| + | }); | ||
| + | |||
| + | |||
| + | // affichage sorts | ||
| + | spells.forEach(s=> | ||
| + | document.getElementById(" | ||
| + | < | ||
| + | <input type=" | ||
| + | < | ||
| + | <span class=" | ||
| + | </ | ||
| }); | }); | ||
| Ligne 247: | Ligne 321: | ||
| baseDiv.textContent = JSON.stringify(races[raceSelect.value], | baseDiv.textContent = JSON.stringify(races[raceSelect.value], | ||
| } | } | ||
| - | |||
| raceSelect.addEventListener(" | raceSelect.addEventListener(" | ||
| displayBase(); | displayBase(); | ||
| Ligne 253: | Ligne 326: | ||
| // ===== COST ===== | // ===== COST ===== | ||
| function calcCost(b, | function calcCost(b, | ||
| - | let total=0, last=b; | + | let total=0, |
| for(let i=1; | for(let i=1; | ||
| if(i===1) last=b; | if(i===1) last=b; | ||
| Ligne 261: | Ligne 334: | ||
| } | } | ||
| return total; | return total; | ||
| + | } | ||
| + | |||
| + | function updateCost(){ | ||
| + | let total=0; | ||
| + | for(let s in costTable){ | ||
| + | let v=+document.getElementById(s).value||0; | ||
| + | let [b, | ||
| + | total+=calcCost(b, | ||
| + | } | ||
| + | document.getElementById(" | ||
| } | } | ||
| // ===== SLOTS ===== | // ===== SLOTS ===== | ||
| - | const head = document.getElementById(" | + | const slots = { |
| - | const neck = document.getElementById(" | + | head:head,neck:neck,cape:cape,rightHand:rightHand, |
| - | const cape = document.getElementById(" | + | leftHand:leftHand,body:body,ring:ring,feet:feet |
| - | const rightHand | + | }; |
| - | const leftHand | + | |
| - | const body = document.getElementById(" | + | |
| - | const ring = document.getElementById(" | + | |
| - | const feet = document.getElementById(" | + | |
| - | // reset slots | ||
| function resetSlots(){ | function resetSlots(){ | ||
| - | [head, | + | Object.values(slots).forEach(s=>s.innerHTML="<option value='' |
| - | sel.innerHTML = `<option value="" | + | |
| - | }); | + | |
| } | } | ||
| - | // remplir équipements | ||
| function fillEquip(){ | function fillEquip(){ | ||
| - | let r = raceSelect.value; | + | let r=raceSelect.value; |
| equipments.forEach((e, | equipments.forEach((e, | ||
| + | if(e.race!==" | ||
| - | if(e.race !== "all" | + | if(e.slot==="weapon"||e.slot===" |
| + | if(e.slot===" | ||
| + | if(e.slot===" | ||
| + | if(e.slot===" | ||
| + | if(e.slot===" | ||
| + | if(e.slot===" | ||
| + | if(e.slot===" | ||
| + | if(e.slot===" | ||
| + | }); | ||
| + | } | ||
| - | // main droite | + | raceSelect.addEventListener("change",()=>{ |
| - | if(e.slot==="weapon" | + | resetSlots(); |
| - | rightHand.innerHTML += `<option value=" | + | fillEquip(); |
| + | autoCalculate(); | ||
| + | }); | ||
| - | // main gauche | + | resetSlots(); |
| - | if(e.slot===" | + | fillEquip(); |
| - | leftHand.innerHTML += `<option value=" | + | |
| - | // corps | + | // ===== BONUS ===== |
| - | if(e.slot==="body") | + | function displayStats(select, |
| - | body.innerHTML | + | let v=select.value; |
| + | let el=document.getElementById(id); | ||
| + | if(v==="" | ||
| + | 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; | ||
| + | } | ||
| - | // tête | + | const slotToStatId |
| - | if(e.slot==="head") | + | head:"headStats", |
| - | head.innerHTML += `<option value="${i}"> | + | neck:"neckStats", |
| + | cape:" | ||
| + | rightHand:" | ||
| + | leftHand:" | ||
| + | body:" | ||
| + | ring:" | ||
| + | feet:" | ||
| + | }; | ||
| - | // cou | + | Object.entries(slots).forEach(([k, |
| - | if(e.slot===" | + | s.addEventListener("change",()=>{ |
| - | neck.innerHTML += `<option value="${i}">${e.name}</ | + | displayStats(s, |
| + | checkLimit(); | ||
| + | autoCalculate(); | ||
| + | }); | ||
| + | }); | ||
| - | // dos | + | // ===== LIMIT ===== |
| - | if(e.slot==="cape") | + | function checkLimit(){ |
| - | cape.innerHTML += `< | + | let count=0; |
| + | Object.entries(slots).forEach(([k, | ||
| + | if(k!=="ring"&&s.value!=="" | ||
| + | }); | ||
| - | // pieds | + | if(count> |
| - | if(e.slot==="feet") | + | limitWarn.innerText=" |
| - | feet.innerHTML += `<option value="${i}">${e.name}</ | + | Object.entries(slots).forEach(([k, |
| + | if(k!==" | ||
| + | }); | ||
| + | }else{ | ||
| + | limitWarn.innerText="" | ||
| + | Object.values(slots).forEach(s=>s.disabled=false); | ||
| + | } | ||
| + | } | ||
| - | // anneau | + | // ===== CALCUL ===== |
| - | if(e.slot===" | + | |
| - | ring.innerHTML += `<option value=" | + | |
| + | function calculate(){ | ||
| + | |||
| + | let activeSpells = [...document.querySelectorAll(" | ||
| + | |||
| + | 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]}; | ||
| + | |||
| + | // stats investies | ||
| + | for(let s in costTable){ | ||
| + | let v=+document.getElementById(s).value||0; | ||
| + | char[s]=(char[s]||0)+v; | ||
| } | } | ||
| - | head.addEventListener(" | + | // equip |
| - | neck.addEventListener(" | + | Object.values(slots).forEach(sel=>{ |
| - | cape.addEventListener(" | + | if(sel.value==="" |
| - | rightHand.addEventListener(" | + | let e=equipments[sel.value]; |
| - | leftHand.addEventListener(" | + | for(let s in e.stats){ |
| - | body.addEventListener(" | + | char[s]=(char[s]||0)+e.stats[s]; |
| - | ring.addEventListener(" | + | } |
| - | feet.addEventListener(" | + | }); |
| - | // update race | + | // ===== DÉS ===== |
| - | raceSelect.addEventListener("change", ()=>{ | + | let ccDice = char.cc * 2; |
| - | resetSlots(); | + | let ctDice = char.ct * 2; |
| - | fillEquip(); | + | let fmDice = char.fm * 2; |
| + | let agiDice = char.agi * 2; | ||
| + | |||
| + | // ===== VALEURS FINALES ===== | ||
| + | let finalCC = ccDice + bestDex; | ||
| + | let finalCT = ctDice + bestDex; | ||
| + | let finalFM = fmDice + bestDex; | ||
| + | |||
| + | |||
| + | // ===== CT DISTANCE ===== | ||
| + | function getCTDistance(baseCT, | ||
| + | if(distance <= 2) return baseCT; | ||
| + | return baseCT - (distance - 2) * 3; | ||
| + | } | ||
| + | |||
| + | let ct1 = getCTDistance(finalCT, | ||
| + | let ct2 = getCTDistance(finalCT, | ||
| + | let ct3 = getCTDistance(finalCT, | ||
| + | let ct4 = getCTDistance(finalCT, | ||
| + | |||
| + | |||
| + | // ===== ESQUIVE ===== | ||
| + | |||
| + | let checked = [...document.querySelectorAll(".skill: | ||
| + | |||
| + | // ===== ESQUIVE CAC ===== | ||
| + | // 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(" | ||
| + | esquiveStat = Math.floor(char.agi * 0.85 + char.cc * 0.15); | ||
| + | } | ||
| + | else if(checked.includes(" | ||
| + | esquiveStat = Math.floor(char.cc * 0.85 + char.agi * 0.15); | ||
| + | } | ||
| + | else{ | ||
| + | esquiveStat = Math.max(esquiveA, | ||
| + | } | ||
| + | |||
| + | // conversion en jet | ||
| + | let esquiveTir = esquiveStat * 2; | ||
| + | |||
| + | // protection (UNE seule fois) | ||
| + | esquiveTir += bestProt; | ||
| + | |||
| + | // bonus passifs | ||
| + | if(checked.includes(" | ||
| + | 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 | ||
| + | |||
| + | sorts += `Niveau ${lvl} → Seuil ${seuil} | Jet ${jetFM} ${reussite}\n`; | ||
| + | } | ||
| + | |||
| + | // ===== AFFICHAGE ===== | ||
| + | document.getElementById(" | ||
| + | "Bonus actifs → Dex: " | ||
| + | |||
| + | result.textContent = | ||
| + | |||
| + | "===== PERSONNAGE =====\n" | ||
| + | "Race : " | ||
| + | |||
| + | " | ||
| + | JSON.stringify(char, | ||
| + | |||
| + | " | ||
| + | "\n⚔ CC : jet moyen " | ||
| + | " | ||
| + | "\n✨ FM : jet moyen " | ||
| + | |||
| + | " | ||
| + | " | ||
| + | " | ||
| + | "\n✨ Esquive FM : " | ||
| + | |||
| + | " | ||
| + | " | ||
| + | "\n1 case : " | ||
| + | "\n2 cases : " | ||
| + | "\n3 cases : " | ||
| + | "\n4 cases : " | ||
| + | |||
| + | " | ||
| + | "Jet FM : " | ||
| + | sorts; | ||
| + | } | ||
| + | |||
| + | |||
| + | // ===== AUTO ===== | ||
| + | function autoCalculate(){ | ||
| + | updateCost(); | ||
| + | calculate(); | ||
| + | } | ||
| + | |||
| + | // events stats | ||
| + | document.querySelectorAll("# | ||
| + | i.addEventListener(" | ||
| }); | }); | ||
| - | // init | + | document.querySelectorAll(" |
| + | s.addEventListener(" | ||
| + | }); | ||
| + | |||
| + | |||
| + | // passifs | ||
| + | document.querySelectorAll(" | ||
| + | s.addEventListener(" | ||
| + | }); | ||
| + | |||
| + | |||
| + | |||
| + | // ===== RESET ===== | ||
| + | function resetAll(){ | ||
| + | |||
| + | document.querySelectorAll("# | ||
| + | document.querySelectorAll(" | ||
| + | |||
| + | Object.values(slots).forEach(s=> | ||
| + | s.value=""; | ||
| + | s.disabled=false; | ||
| + | }); | ||
| + | |||
| + | document.querySelectorAll(" | ||
| resetSlots(); | resetSlots(); | ||
| fillEquip(); | fillEquip(); | ||
| + | displayBase(); | ||
| + | checkLimit(); | ||
| + | autoCalculate(); | ||
| + | } | ||
| + | // init | ||
| + | autoCalculate(); | ||
| - | // ===== AFFICHAGE BONUS ÉQUIPEMENT ===== | ||
| - | function displayStats(select, | ||
| - | let id = select.value; | ||
| - | let target = document.getElementById(targetId); | ||
| - | if(id==="" | ||
| - | target.innerHTML = ""; | ||
| - | return; | ||
| - | } | ||
| - | let item = equipments[id]; | + | // ===== POUSSEE ===== |
| + | function calculatePush(){ | ||
| - | | + | let F=+pushF.value; |
| + | let buff=+pushBuff.value; | ||
| - | for(let stat in item.stats){ | + | let E=+pushE.value; |
| - | let val = item.stats[stat]; | + | let agi=+pushAgi.value; |
| + | let pv=+pushPV.value; | ||
| - | if(val > 0){ | + | let instability=+pushDebuff.value; |
| - | txt += `+${val} ${stat.toUpperCase()} `; | + | let stability=+pushStab.value; |
| - | } else { | + | |
| - | txt += `<span style="color:# | + | let attaque=F+buff; |
| + | let defense=Math.max(E+4,agi)+(pv/ | ||
| + | |||
| + | pushResult.textContent= | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | } | ||
| + | |||
| + | // ===== EVENTS ===== | ||
| + | document.querySelectorAll(" | ||
| + | updateCost(); | ||
| + | })); | ||
| + | |||
| + | document.querySelectorAll(" | ||
| + | updateCost(); | ||
| + | })); | ||
| + | |||
| + | |||
| + | // ===== INIT ===== | ||
| + | updateCost(); | ||
| + | calculate(); | ||
| + | calculatePush(); | ||
| + | |||
| + | |||
| + | // ===================================== | ||
| + | // ENCODE / DECODE | ||
| + | // ===================================== | ||
| + | |||
| + | function encodeBuild(data){ | ||
| + | | ||
| + | } | ||
| + | |||
| + | function decodeBuild(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; | ||
| } | } | ||
| - | } | ||
| - | txt += "</span>"; | + | |
| + | Object.entries(slots).forEach(([k, | ||
| + | data.equip[k] = s.value; | ||
| + | }); | ||
| - | if(item.magicBlock){ | + | // passifs |
| - | | + | |
| - | } | + | data.skills.push(s.dataset.name); |
| + | }); | ||
| - | target.innerHTML | + | // sorts |
| + | document.querySelectorAll(" | ||
| + | data.spells.push({ | ||
| + | dex: +s.dataset.dex, | ||
| + | prot: +s.dataset.prot | ||
| + | }); | ||
| + | }); | ||
| + | |||
| + | return data; | ||
| } | } | ||
| + | // ===================================== | ||
| + | // APPLY BUILD | ||
| + | // ===================================== | ||
| - | // ===== CALCUL ===== | + | function |
| - | function | + | |
| - | let char = {...races[raceSelect.value]}; | + | // race |
| - | let totalPI | + | |
| - | // stats | + | // recharge équipements race |
| - | for(let s in costTable){ | + | resetSlots(); |
| - | let v = +document.getElementById(s).value || 0; | + | fillEquip(); |
| - | char[s]+=v; | + | |
| - | let [b,m1,m2]=costTable[s]; | + | |
| - | totalPI | + | for(let s in costTable){ |
| + | document.getElementById(s).value | ||
| + | data.stats? | ||
| + | } | ||
| + | |||
| + | // équipements | ||
| + | Object.entries(slots).forEach(([k,s])=>{ | ||
| + | s.value = data.equip? | ||
| + | }); | ||
| + | |||
| + | // refresh affichage bonus équipements | ||
| + | Object.entries(slots).forEach(([k,s])=>{ | ||
| + | displayStats(s, slotToStatId[k]); | ||
| + | }); | ||
| + | |||
| + | |||
| + | // passifs | ||
| + | document.querySelectorAll(" | ||
| + | s.checked = | ||
| + | data.skills? | ||
| + | }); | ||
| + | |||
| + | // sorts | ||
| + | document.querySelectorAll(" | ||
| + | |||
| + | s.checked = data.spells? | ||
| + | sp.dex == +s.dataset.dex && | ||
| + | sp.prot | ||
| + | ); | ||
| + | |||
| + | }); | ||
| + | |||
| + | displayBase(); | ||
| + | checkLimit(); | ||
| + | autoCalculate(); | ||
| } | } | ||
| - | // résumé | + | // ===================================== |
| - | let esquive | + | // EXPORT |
| + | // ===================================== | ||
| - | result.textContent = | + | function exportBuild(){ |
| - | JSON.stringify(char,null,2) | + | |
| - | + " | + | let data = getBuildData(); |
| - | + "\n⚔ CC : " | + | |
| - | + " | + | let code = encodeBuild(data); |
| - | + "\n✨ FM : " | + | |
| - | + " | + | |
| + | prompt(" | ||
| } | } | ||
| - | </script> | + | // ===================================== |
| + | // IMPORT | ||
| + | // ===================================== | ||
| + | function importBuild(codeInput){ | ||
| + | |||
| + | let code = codeInput; | ||
| + | |||
| + | if(!code){ | ||
| + | code = prompt(" | ||
| + | } | ||
| + | |||
| + | if(!code) return; | ||
| + | |||
| + | try{ | ||
| + | |||
| + | code = code.trim(); | ||
| + | |||
| + | let data = decodeBuild(code); | ||
| + | |||
| + | applyBuild(data); | ||
| + | |||
| + | alert(" | ||
| + | |||
| + | }catch(e){ | ||
| + | |||
| + | console.log(e); | ||
| + | |||
| + | alert(" | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // ===================================== | ||
| + | // LIEN PARTAGE | ||
| + | // ===================================== | ||
| + | |||
| + | function copyLink(){ | ||
| + | |||
| + | let data = getBuildData(); | ||
| + | |||
| + | let code = encodeBuild(data); | ||
| + | |||
| + | let url = | ||
| + | window.location.origin + | ||
| + | window.location.pathname + | ||
| + | "? | ||
| + | |||
| + | navigator.clipboard.writeText(url).then(()=> | ||
| + | |||
| + | alert(" | ||
| + | |||
| + | }).catch(()=> | ||
| + | |||
| + | prompt(" | ||
| + | |||
| + | }); | ||
| + | } | ||
| + | |||
| + | // ===================================== | ||
| + | // AUTO LOAD URL | ||
| + | // ===================================== | ||
| + | |||
| + | (function(){ | ||
| + | |||
| + | try{ | ||
| + | |||
| + | let params = | ||
| + | new URLSearchParams(window.location.search); | ||
| + | |||
| + | let code = params.get(" | ||
| + | |||
| + | if(!code) return; | ||
| + | |||
| + | let data = decodeBuild(code); | ||
| + | |||
| + | applyBuild(data); | ||
| + | |||
| + | console.log(" | ||
| + | |||
| + | }catch(e){ | ||
| + | |||
| + | console.log(" | ||
| + | |||
| + | } | ||
| + | |||
| + | })(); | ||
| + | |||
| + | </ | ||
| </ | </ | ||
| </ | </ | ||
simulateur.1777487437.txt.gz · Dernière modification : 2026/04/29 20:30 de nanaki
