brouillon3
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| brouillon3 [2026/04/19 12:02] – nanaki | brouillon3 [2026/05/12 13:53] (Version actuelle) – nanaki | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| - | ===== Liste des Sorts ===== | + | Voici un simulateur en version beta, n' |
| - | Un complément d' | ||
| < | < | ||
| < | < | ||
| <meta charset=" | <meta charset=" | ||
| - | < | + | < |
| - | < | + | |
| - | body { font-family: | + | |
| - | h3 { text-align: center; } | + | |
| - | .table-container { width: 100%; overflow-x: auto; margin-top: 10px; } | + | |
| - | table { width: 100%; border-collapse: | + | |
| - | th, td { padding: 8px; border: 1px solid #ccc; text-align: left; } | + | |
| - | th { background: #f2f2f2; } | + | |
| - | tbody tr: | + | |
| - | tbody tr: | + | |
| - | /* Couleurs par race */ | + | < |
| - | td.race-Communs | + | body { |
| - | td.race-Nain | + | font-family: |
| - | td.race-Géant | + | background:# |
| - | td.race-Olympien | + | |
| - | td.race-HS { color: | + | padding: |
| - | td.race-Elfe | + | } |
| + | h1,h2 { color:gold;} | ||
| + | .box { border:1px solid gold; padding: | ||
| + | select { margin:3px; max-width: | ||
| + | input { margin:3px; width:60px; } | ||
| + | .statLine { display: | ||
| + | .result | ||
| + | .small { font-size: | ||
| </ | </ | ||
| </ | </ | ||
| + | |||
| < | < | ||
| - | <!-- ================= TABLEAU 1 : sorts ================= --> | + | <h1>🎲 Simulateur</h1> |
| - | < | + | |
| - | <label for=" | + | |
| - | <select id=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | </select> | + | |
| - | <div class=" | + | <div class=" |
| - | <table id="competencesTable1"> | + | Race : |
| - | <thead> | + | <select |
| - | <tr> | + | <h3>Stats de base</h3> |
| - | < | + | <pre id=" |
| - | <th>Coût (PM)</th>< | + | </div> |
| - | < | + | |
| - | </ | + | |
| - | </ | + | |
| - | <tbody> | + | |
| - | <!-- ================= COMMUNS ================= --> | + | <div class=" |
| + | < | ||
| + | <div id=" | ||
| + | <div id=" | ||
| + | </div> | ||
| + | <div class=" | ||
| + | < | ||
| + | Tête <select id=" | ||
| + | Cou <select id=" | ||
| + | Dos <select id=" | ||
| + | Main droite <select id=" | ||
| + | Main gauche <select id=" | ||
| + | Corps <select id=" | ||
| + | Anneau <select id=" | ||
| + | Pieds <select id=" | ||
| + | <div id=" | ||
| + | </ | ||
| - | <tr class=" | + | <div class=" |
| - | <td class=" | + | <h3>Passifs</h3> |
| - | <td>6 MP</ | + | <div id=" |
| - | < | + | </div> |
| - | </tr> | + | |
| - | <tr class=" | + | <div class=" |
| - | <td class=" | + | <h3>Sorts actifs</h3> |
| - | <td>6 MP</td>< | + | <div id=" |
| - | <td>Bonus de +4 pour toucher</ | + | <div id=" |
| - | </tr> | + | </div> |
| - | <tr class=" | ||
| - | <td class=" | ||
| - | <td>6 MP</ | ||
| - | < | ||
| - | </tr> | ||
| - | <tr class=" | ||
| - | <td class=" | ||
| - | <td>4 MP</ | ||
| - | < | ||
| - | </tr> | ||
| - | <tr class=" | + | <!-- ================= POUSSEE ================= --> |
| - | <td class=" | + | <div class=" |
| - | <td>4 MP</ | + | <h3>Simulateur de poussée</h3> |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | Force assaillant |
| - | <td class="race-Communs">Communs</ | + | Renforcement |
| - | <td>4 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | Endurance |
| - | <td class="race-Communs">Communs</ | + | Agilité |
| - | <td>4 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | PV actuels |
| - | <td class="race-Communs"> | + | |
| - | <td>4 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | Instabilité |
| - | <td class="race-Communs">Communs</td><td>Restauration mineure</td>< | + | Stabilité |
| - | <td>6 MP</td>< | + | |
| - | <td>Réduit les malus</td>< | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | <pre id="pushResult" class=" |
| - | < | + | </div> |
| - | <td>6 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | <button onclick="resetAll()">Reset</button> |
| - | <td class=" | + | |
| - | <td>6 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | <button onclick="exportBuild()">📤 Export</ |
| - | <td class="race-Communs">Communs</td>< | + | <button onclick="importBuild()">📥 Import</button> |
| - | <td>8 MP</ | + | <button onclick=" |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | <pre id="result" class=" |
| - | < | + | |
| - | <td>8 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | <script> |
| - | <td class=" | + | |
| - | <td>6 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | // ===== RACES ===== |
| - | <td class=" | + | const races = { |
| - | <td>6 MP</ | + | Elfe: |
| - | < | + | Nain:{a:2, |
| - | </tr> | + | Géant: |
| + | Olympien: | ||
| + | HS: | ||
| + | }; | ||
| - | <tr class=" | + | // ===== COST ===== |
| - | <td class=" | + | const costTable |
| - | < | + | a: |
| - | < | + | cc: |
| - | </tr> | + | f: |
| + | agi: | ||
| + | m: | ||
| + | fm: | ||
| + | p: | ||
| + | pv:[4,2,1], | ||
| + | pm: | ||
| + | mvt:[100,50,30], | ||
| + | r: | ||
| + | rm: | ||
| + | }; | ||
| - | <tr class="Communs"> | + | // ===== PASSIFS ===== |
| - | <td class="race-Communs"> | + | const skills = [ |
| - | <td>6 MP</ | + | {name:"Fulgurance", |
| - | < | + | {name:"Couverture", |
| - | </tr> | + | {name:" |
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | ]; | ||
| - | <tr class="Communs"> | + | // ===== SORTS ===== |
| - | <td class="race-Communs"> | + | const spells = [ |
| - | <td>4 MP</ | + | {name:"Peau de granit", |
| - | < | + | {name:"Coup précis",dex:2,prot:0}, |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | {name:"Maladresse", |
| - | <td class="race-Communs"> | + | {name:"Vulnérabilité", |
| - | <td>8 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | {name:"Puissance de la nature", |
| - | <td class=" | + | |
| - | <td>4 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | {name:"Aide", |
| - | <td class="race-Communs"> | + | {name:"Malchance",dex:-4,prot:0}, |
| - | <td>6 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | {name:"Fatigue", |
| - | <td class="race-Communs"> | + | {name:"Réflexes accrus", |
| - | <td>6 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | {name:"Bénédiction",dex: |
| - | <td class=" | + | |
| - | <td>0 MP, 5 PV, 2 Mvt</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | {name:"Puissance du lutin capricieux",dex:-4,prot:-4}, |
| - | <td class=" | + | |
| - | <td>2 MP, 1 Mvt</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | {name:"Exténuation", |
| - | <td class="race-Communs"> | + | {name:"Sauvegarde", |
| - | <td>8 MP</ | + | {name:" |
| - | < | + | {name:" |
| - | </tr> | + | ]; |
| - | <tr class=" | ||
| - | <td class=" | ||
| - | < | ||
| - | < | ||
| - | </tr> | ||
| - | <tr class=" | ||
| - | <td class=" | ||
| - | <td>8 MP</ | ||
| - | < | ||
| - | </tr> | ||
| - | <tr class=" | + | const equipments |
| - | <td class=" | + | |
| - | <td>4 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | /* ================= COMMUNS ================= */ |
| - | <td class=" | + | |
| - | <td>8 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | {name:"Arc", |
| - | <td class="race-Communs"> | + | {name:"Armure matelassée", |
| - | < | + | {name:"Bâton de marche", |
| - | < | + | {name:" |
| - | </tr> | + | {name:" |
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| - | <tr class=" | + | /* ===== NOUVEAUX COMMUNS ===== */ |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | {name:"Torche", |
| - | <td class="race-Communs"> | + | {name:"Hache de jet",race:"all", |
| - | < | + | {name:" |
| - | < | + | {name:" |
| - | </tr> | + | |
| - | <tr class=" | + | /* ================= ELFES ================= */ |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | {name:"Bâton du Pèlerin", |
| - | <td class="race-Communs"> | + | {name:"Bottes Tâlroval", |
| - | < | + | {name:" |
| - | < | + | {name:" |
| - | </tr> | + | {name:" |
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| - | <tr class="Communs"> | + | // spécifique elfe |
| - | <td class="race-Communs"> | + | {name:"Arc Elfique",race:"Elfe", |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | /* ================= NAINS ================= */ |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | {name:"Cotte de mailles", |
| - | <td class="race-Communs"> | + | {name:"Labrys", |
| - | < | + | {name:" |
| - | < | + | {name:" |
| - | </tr> | + | {name:" |
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| - | <tr class="Communs"> | + | // spécifiques nains |
| - | <td class="race-Communs"> | + | {name:"Bâton d' |
| - | < | + | {name:"Hache runique", |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | /* ================= GÉANTS ================= */ |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | {name:"Bouclier Clipeus", |
| - | <td class="race-Communs"> | + | {name:"Masse d' |
| - | < | + | {name:" |
| - | < | + | {name:"Bâton de shaman", |
| - | </tr> | + | {name:" |
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| - | <tr class="Communs"> | + | // spécifique géant |
| - | <td class="race-Communs"> | + | {name:"Peau de granit manifiée",race:" |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | /* ================= HS ================= */ |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <!-- ================= RACES ================= --> | + | {name:" |
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | // spécifiques HS | ||
| + | {name:" | ||
| + | {name:" | ||
| - | <tr class=" | + | /* ================= OLYMPIENS ================= */ |
| - | <td class=" | + | |
| - | <td>4 PM</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="HS"> | + | {name:"Armure hoplitique", |
| - | <td class="race-HS"> | + | {name:"Bouclier Ancile", |
| - | <td>6 PM</ | + | {name:" |
| - | < | + | {name:" |
| - | </tr> | + | {name:" |
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| + | // spécifique olympien | ||
| + | {name:" | ||
| - | <tr class=" | + | /* ================= ANNEAUX ================= */ |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="HS"> | + | {name:"Anneau Caprice", |
| - | <td class="race-HS"> | + | {name:"Anneau Férocité", |
| - | < | + | {name:" |
| - | < | + | {name:" |
| - | </tr> | + | {name:" |
| + | {name:" | ||
| + | {name:" | ||
| + | {name:" | ||
| - | <tr class=" | + | ]; |
| - | <td class=" | + | |
| - | <td>4 PM</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | ||
| - | <td class=" | ||
| - | <td>5 PM</ | ||
| - | <td> Projette une flèche composée d'eau sur l' | ||
| - | </tr> | ||
| - | <tr class=" | + | // ===== INIT ===== |
| - | <td class="race-Elfe"> | + | const raceSelect |
| - | <td>6 PM</ | + | const statsDiv = document.getElementById(" |
| - | < | + | const baseDiv = document.getElementById(" |
| - | </tr> | + | |
| - | <tr class=" | + | for(let r in races){ |
| - | <td class=" | + | raceSelect.innerHTML |
| - | < | + | } |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | // stats UI |
| - | <td class=" | + | for(let s in costTable){ |
| - | <td>8 PM</ | + | statsDiv.innerHTML += ` |
| - | < | + | <div class=" |
| - | </tr> | + | <span>${s}</span> |
| + | <input type=" | ||
| + | </div>`; | ||
| + | } | ||
| - | <tr class="Géant"> | + | // passifs |
| - | <td class=" | + | skills.forEach(s=>{ |
| - | <td>4 PM</td><td> | + | document.getElementById("skills").innerHTML += ` |
| - | <td>Projette un aiguillon sur l’adversaire.</td><td>/</td><td>100 po</td> | + | <label> |
| - | </tr> | + | <input type=" |
| + | <b>${s.name}</b><br> | ||
| + | <span class=" | ||
| + | </label><br>`; | ||
| + | }); | ||
| - | <tr class=" | ||
| - | <td class=" | ||
| - | <td>7 PM</ | ||
| - | < | ||
| - | </tr> | ||
| - | <tr class="Géant"> | + | // affichage sorts |
| - | <td class=" | + | spells.forEach(s=>{ |
| - | <td>6 PM</td>< | + | document.getElementById("spells").innerHTML += ` |
| - | <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> | + | <label> |
| - | </tr> | + | <input type=" |
| + | <b>${s.name}</b> | ||
| + | <span class=" | ||
| + | </label><br>`; | ||
| + | }); | ||
| - | <tr class=" | + | // base stats |
| - | <td class=" | + | function displayBase(){ |
| - | < | + | baseDiv.textContent = JSON.stringify(races[raceSelect.value], |
| - | < | + | } |
| - | </tr> | + | raceSelect.addEventListener(" |
| + | displayBase(); | ||
| - | <tr class=" | + | // ===== COST ===== |
| - | <td class=" | + | function calcCost(b, |
| - | <td>8 PM</ | + | let total=0,last=b; |
| - | < | + | 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; | ||
| + | } | ||
| + | function updateCost(){ | ||
| + | let total=0; | ||
| + | for(let s in costTable){ | ||
| + | let v=+document.getElementById(s).value||0; | ||
| + | let [b, | ||
| + | total+=calcCost(b, | ||
| + | } | ||
| + | document.getElementById(" | ||
| + | } | ||
| - | <tr class=" | + | // ===== SLOTS ===== |
| - | <td class=" | + | const slots = { |
| - | <td>4 PM</ | + | head: |
| - | < | + | leftHand: |
| - | </tr> | + | }; |
| - | <tr class=" | + | function resetSlots(){ |
| - | <td class="race-Nain"> | + | Object.values(slots).forEach(s=>s.innerHTML="<option value='' |
| - | <td>8 PM</ | + | } |
| - | < | + | |
| - | </tr> | + | |
| + | function fillEquip(){ | ||
| + | let r=raceSelect.value; | ||
| - | <tr class=" | + | equipments.forEach((e, |
| - | <td class="race-Olympien"> | + | if(e.race!=="all"&&e.race!==r) return; |
| - | <td>4 PM</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Olympien"> | + | if(e.slot==="weapon"||e.slot===" |
| - | <td class="race-Olympien">Olympien</td><td>Imposition des Mains</td><td>Sort</td><td>Bénédiction</td> | + | if(e.slot===" |
| - | <td>7 PM</td>< | + | if(e.slot===" |
| - | <td>Toucher magique pour soigner un blessé.</td>< | + | if(e.slot===" |
| - | </tr> | + | if(e.slot===" |
| + | if(e.slot===" | ||
| + | if(e.slot===" | ||
| + | if(e.slot===" | ||
| + | }); | ||
| + | } | ||
| - | <tr class="Olympien"> | + | raceSelect.addEventListener("change",()=>{ |
| - | <td class=" | + | resetSlots(); |
| - | < | + | fillEquip(); |
| - | < | + | autoCalculate(); |
| - | </tr> | + | }); |
| - | <tr class=" | + | resetSlots(); |
| - | <td class=" | + | fillEquip(); |
| - | <td>8 PM</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | </tbody> | + | // ===== BONUS ===== |
| - | </table> | + | function displayStats(select, |
| - | </div> | + | 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; | ||
| + | } | ||
| + | const slotToStatId = { | ||
| + | head:" | ||
| + | neck:" | ||
| + | cape:" | ||
| + | rightHand:" | ||
| + | leftHand:" | ||
| + | body:" | ||
| + | ring:" | ||
| + | feet:" | ||
| + | }; | ||
| - | <script> | + | Object.entries(slots).forEach(([k, |
| - | // Script pour le premier tableau | + | s.addEventListener("change",()=>{ |
| - | const select1 = document.getElementById("raceSelect1"); | + | displayStats(s, |
| - | const rows1 = document.querySelectorAll("# | + | checkLimit(); |
| + | autoCalculate(); | ||
| + | }); | ||
| + | }); | ||
| - | select1.addEventListener(" | + | // ===== LIMIT ===== |
| - | const chosenRace | + | function checkLimit(){ |
| - | rows1.forEach(row => { | + | let count=0; |
| - | const isCommun | + | Object.entries(slots).forEach(([k,s])=>{ |
| - | const isRace = row.classList.contains(chosenRace); | + | if(k!=="ring"&&s.value!=="" |
| - | row.style.display = (chosenRace === "Toutes" | + | |
| - | }); | + | |
| }); | }); | ||
| - | </ | ||
| - | <hr> | + | if(count>=3){ |
| + | limitWarn.innerText=" | ||
| + | Object.entries(slots).forEach(([k, | ||
| + | if(k!==" | ||
| + | }); | ||
| + | }else{ | ||
| + | limitWarn.innerText=""; | ||
| + | Object.values(slots).forEach(s=> | ||
| + | } | ||
| + | } | ||
| - | < | + | // ===== CALCUL |
| - | < | + | |
| - | <label for=" | + | |
| - | <select id=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | </ | + | |
| - | <div class=" | + | function calculate(){ |
| - | <table id=" | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | </ | + | |
| - | < | + | |
| - | < | + | let activeSpells |
| - | <tr class=" | + | |
| - | <tr class=" | + | |
| - | <tr class=" | + | |
| - | <tr class=" | + | |
| - | <tr class="Communs">< | + | |
| - | <tr class="Communs">< | + | |
| - | <tr class=" | + | |
| - | <td class=" | + | |
| - | <td>1 Mvt</ | + | |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | let bestDex |
| - | <td class=" | + | let bestProt |
| - | <td>5 Mvt, 0A</ | + | |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | activeSpells.forEach(s=>{ |
| - | <td class=" | + | let d = +s.dataset.dex; |
| - | <td>2 MP</ | + | let p = +s.dataset.prot; |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | if(Math.abs(d) |
| - | <td class=" | + | if(Math.abs(p) |
| - | <td>4 MP</ | + | }); |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | let char={...races[raceSelect.value]}; |
| - | <td class=" | + | |
| - | <td>2 PV</ | + | |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | // stats investies |
| - | <td class=" | + | for(let s in costTable){ |
| - | <td>4 MP</ | + | let v=+document.getElementById(s).value||0; |
| - | < | + | char[s]=(char[s]||0)+v; |
| - | < | + | } |
| - | </tr> | + | |
| - | <!-- ===== NAINS ===== --> | + | // equip |
| - | <tr class=" | + | Object.values(slots).forEach(sel=>{ |
| - | < | + | if(sel.value==="" |
| - | < | + | let e=equipments[sel.value]; |
| - | < | + | for(let s in e.stats){ |
| + | char[s]=(char[s]||0)+e.stats[s]; | ||
| + | } | ||
| + | }); | ||
| - | < | + | // ===== DÉS ===== |
| - | < | + | let ccDice |
| - | < | + | let ctDice |
| - | < | + | let fmDice = char.fm * 2; |
| - | < | + | let agiDice = char.agi * 2; |
| - | </tr> | + | |
| - | <tr class=" | + | // ===== VALEURS FINALES ===== |
| - | < | + | let finalCC |
| - | < | + | let finalCT = ctDice + bestDex; |
| - | < | + | let finalFM = fmDice + bestDex; |
| - | </tr> | + | |
| - | <!-- ===== OLYMPIENS ===== --> | ||
| - | <tr class=" | ||
| - | <td class=" | ||
| - | <td>7 PM</ | ||
| - | < | ||
| - | </tr> | ||
| - | <tr class=" | + | // ===== CT DISTANCE ===== |
| - | <td class=" | + | function getCTDistance(baseCT, |
| - | < | + | if(distance |
| - | < | + | return baseCT |
| - | </ | + | } |
| - | < | + | let ct1 = getCTDistance(finalCT, |
| - | < | + | let ct2 = getCTDistance(finalCT, |
| - | < | + | let ct3 = getCTDistance(finalCT, |
| - | <td>6 PM</ | + | let ct4 = getCTDistance(finalCT, |
| - | < | + | |
| - | </tr> | + | |
| - | <!-- ===== ELFES ===== --> | ||
| - | <tr class=" | ||
| - | <td class=" | ||
| - | <td>7 PM</ | ||
| - | < | ||
| - | </tr> | ||
| - | <tr class=" | + | // ===== ESQUIVE |
| - | <td class=" | + | |
| - | <td>7 PM + 1 Mvt</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | + | ||
| - | + | ||
| - | < | + | |
| - | <tr class="Communs"> | + | let checked |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | <td>2 comp. Avancées</ | + | |
| - | </tr> | + | |
| - | <tr class=" | + | // ===== ESQUIVE CAC ===== |
| - | <td class=" | + | // règle : meilleur entre CC et AGI (dés), puis conversion jet + protection |
| - | <td>/</td>< | + | |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | < | + | let esquiveCAC |
| - | <tr class=" | + | // conversion en jet + protection |
| - | <td class=" | + | esquiveCAC = esquiveCAC |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <!-- ===== HS ===== --> | ||
| - | <tr class=" | + | // ===== ESQUIVE TIR ===== |
| - | <td class=" | + | // règle : |
| - | <td>/</td>< | + | // max entre : |
| - | < | + | // (3/4 CC + 1/4 AGI) |
| - | <td>/</td>< | + | // (1/4 CC + 3/4 AGI) |
| - | </tr> | + | // arrondi inférieur → dés → ×2 → + protection |
| - | < | + | let esquiveA |
| + | let esquiveB | ||
| - | <tr class=" | + | // passifs qui remplacent le calcul |
| - | <td class=" | + | let esquiveStat; |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | </ | + | if(checked.includes(" |
| - | </ | + | |
| - | </ | + | } |
| + | else if(checked.includes(" | ||
| + | esquiveStat = Math.floor(char.cc * 0.85 + char.agi * 0.15); | ||
| + | } | ||
| + | else{ | ||
| + | esquiveStat = Math.max(esquiveA, | ||
| + | } | ||
| - | < | + | // conversion en jet |
| - | // Script pour le second tableau | + | let esquiveTir |
| - | const select2 = document.getElementById(" | + | |
| - | const rows2 = document.querySelectorAll("# | + | |
| - | select2.addEventListener(" | + | // protection |
| - | const chosenRace | + | esquiveTir += bestProt; |
| - | rows2.forEach(row => { | + | |
| - | const isCommun = row.classList.contains(" | + | |
| - | const isRace = row.classList.contains(chosenRace); | + | |
| - | row.style.display = (chosenRace === " | + | |
| - | }); | + | |
| - | }); | + | |
| - | </ | + | |
| + | // bonus passifs | ||
| + | if(checked.includes(" | ||
| + | esquiveTir += 1; | ||
| - | <hr> | ||
| - | < | + | // ===== ESQUIVE MAGIQUE |
| - | < | + | // règle |
| - | <label for=" | + | |
| - | <select id=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | </ | + | |
| - | <div class=" | + | let esquiveFM |
| - | <table id=" | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | </ | + | |
| - | < | + | |
| - | < | + | // ===== MAGIE ===== |
| + | let jetFM = finalFM; | ||
| - | <tr class="Communs"> | + | let sorts = "" |
| - | <td class=" | + | for(let lvl=1; lvl<=5; lvl++){ |
| - | < | + | let seuil = 6 + 6 * lvl; |
| - | < | + | let reussite = jetFM >= seuil ? " |
| - | </tr> | + | |
| + | sorts += `Niveau ${lvl} → Seuil ${seuil} | Jet ${jetFM} ${reussite}\n`; | ||
| + | } | ||
| - | <tr class="Communs"> | + | // ===== AFFICHAGE ===== |
| - | <td class="race-Communs"> | + | document.getElementById("spellBonus").innerText = |
| - | <td>2 MP</ | + | "Bonus actifs → Dex: "+bestDex+" | Protection: " |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | result.textContent |
| - | <td class=" | + | |
| - | <td>2 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | "===== PERSONNAGE =====\n"+ |
| - | <td class="race-Communs"> | + | "Race : "+raceSelect.value+ |
| - | <td>6 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | "\n\n===== STATS =====\n"+ |
| - | <td class="race-Communs"> | + | JSON.stringify(char,null,2)+ |
| - | <td>4 MP</ | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | " |
| - | <td class="race-Communs"> | + | "\n⚔ CC : jet moyen "+ccDice+" |
| - | < | + | " |
| - | < | + | "\n✨ FM : jet moyen " |
| - | </tr> | + | |
| + | " | ||
| + | " | ||
| + | " | ||
| + | "\n✨ Esquive FM : " | ||
| - | <tr class="Communs"> | + | " |
| - | <td class="race-Communs"> | + | "\n🎯 CT distances :"+ |
| - | <td>2 MP</ | + | "\n1 case : "+ct1+ |
| - | < | + | "\n2 cases : "+ct2+ |
| - | < | + | "\n3 cases : "+ct3+ |
| - | </tr> | + | "\n4 cases : "+ct4+ |
| - | <tr class="Communs"> | + | " |
| - | <td class="race-Communs"> | + | " |
| - | <td>2 MP</ | + | sorts; |
| - | < | + | } |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | ||
| - | <td class=" | ||
| - | <td>2 MP</ | ||
| - | < | ||
| - | < | ||
| - | </tr> | ||
| - | <tr class=" | + | // ===== AUTO ===== |
| - | <td class=" | + | function autoCalculate(){ |
| - | <td>4 MP, 1 Mvt</ | + | updateCost(); |
| - | < | + | calculate(); |
| - | < | + | } |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | // events stats |
| - | <td class="race-Communs"> | + | document.querySelectorAll("#stats input").forEach(i=>{ |
| - | < | + | i.addEventListener("input", autoCalculate); |
| - | < | + | }); |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class="Communs"> | + | document.querySelectorAll(".spell").forEach(s=>{ |
| - | <td class="race-Communs"> | + | s.addEventListener("change", autoCalculate); |
| - | < | + | }); |
| - | < | + | |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | ||
| - | <td class=" | ||
| - | < | ||
| - | < | ||
| - | < | ||
| - | </tr> | ||
| + | // passifs | ||
| + | document.querySelectorAll(" | ||
| + | s.addEventListener(" | ||
| + | }); | ||
| - | </ | ||
| - | </ | ||
| - | </ | ||
| - | < | ||
| - | // Script pour le troisieme tableau | ||
| - | const select3 = document.getElementById(" | ||
| - | const rows3 = document.querySelectorAll("# | ||
| - | select3.addEventListener("change", () => { | + | // ===== RESET ===== |
| - | const chosenRace = select3.value; | + | function resetAll(){ |
| - | rows3.forEach(row => { | + | |
| - | const isCommun = row.classList.contains(" | + | document.querySelectorAll("#stats input").forEach(i=>i.value=0); |
| - | const isRace = row.classList.contains(chosenRace); | + | document.querySelectorAll(" |
| - | row.style.display = (chosenRace === "Toutes" | + | |
| - | }); | + | Object.values(slots).forEach(s=>{ |
| + | s.value=""; | ||
| + | s.disabled=false; | ||
| }); | }); | ||
| - | </ | ||
| + | document.querySelectorAll(" | ||
| - | <hr> | + | resetSlots(); |
| + | fillEquip(); | ||
| + | displayBase(); | ||
| + | checkLimit(); | ||
| + | autoCalculate(); | ||
| + | } | ||
| - | <!-- ================= TABLEAU 4 : Furtivité ================= --> | + | // init |
| - | < | + | autoCalculate(); |
| - | <label for=" | + | |
| - | <select id=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | </ | + | |
| - | <div class=" | ||
| - | <table id=" | ||
| - | < | ||
| - | <tr> | ||
| - | < | ||
| - | < | ||
| - | < | ||
| - | </tr> | ||
| - | </ | ||
| - | < | ||
| + | // ===== POUSSEE ===== | ||
| + | function calculatePush(){ | ||
| + | let F=+pushF.value; | ||
| + | let buff=+pushBuff.value; | ||
| - | < | + | let E=+pushE.value; |
| + | let agi=+pushAgi.value; | ||
| + | let pv=+pushPV.value; | ||
| - | <tr class=" | + | let instability=+pushDebuff.value; |
| - | <td class=" | + | let stability=+pushStab.value; |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| + | let attaque=F+buff; | ||
| + | let defense=Math.max(E+4, | ||
| - | <tr class="Communs"> | + | pushResult.textContent= |
| - | <td class="race-Communs"> | + | "Attaque: |
| - | < | + | "\nDéfense: |
| - | < | + | " |
| - | </ | + | } |
| - | <tr class="Communs"> | + | // ===== EVENTS ===== |
| - | <td class="race-Communs"> | + | document.querySelectorAll("input").forEach(i=>i.addEventListener("input",()=>{ |
| - | <td>X MP, Y Mvt, 1A</ | + | updateCost(); calculate(); calculatePush(); |
| - | < | + | })); |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | document.querySelectorAll("select").forEach(i=>i.addEventListener("change", |
| - | <td class=" | + | updateCost(); calculate(); calculatePush(); |
| - | < | + | })); |
| - | < | + | |
| - | </ | + | |
| - | + | ||
| - | <tr class="Communs"> | + | |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | + | ||
| - | <tr class=" | + | |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | + | ||
| - | <tr class="Communs"> | + | |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | + | ||
| - | <tr class=" | + | |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | </ | ||
| - | </ | ||
| - | </ | ||
| + | // ===== INIT ===== | ||
| + | updateCost(); | ||
| + | calculate(); | ||
| + | calculatePush(); | ||
| - | </ | ||
| - | </ | ||
| - | </ | ||
| - | < | + | // ===================================== |
| - | // Script pour le quatrieme tableau | + | // ENCODE / DECODE |
| - | const select4 | + | // ===================================== |
| - | const rows4 = document.querySelectorAll("# | + | |
| - | select4.addEventListener(" | + | function encodeBuild(data){ |
| - | const chosenRace = select4.value; | + | |
| - | rows3.forEach(row => { | + | } |
| - | | + | |
| - | const isRace = row.classList.contains(chosenRace); | + | |
| - | row.style.display = (chosenRace === " | + | |
| - | }); | + | |
| - | }); | + | |
| - | </ | + | |
| + | function decodeBuild(code){ | ||
| + | return JSON.parse(decodeURIComponent(code)); | ||
| + | } | ||
| - | </body> | + | // ===================================== |
| - | </html> | + | // BUILD DATA |
| + | // ===================================== | ||
| + | function getBuildData(){ | ||
| + | let data = { | ||
| + | race: raceSelect.value, | ||
| + | stats: {}, | ||
| + | equip: {}, | ||
| + | skills: [], | ||
| + | spells: [] | ||
| + | }; | ||
| - | <hr> | + | // stats |
| + | for(let s in costTable){ | ||
| + | data.stats[s] = +document.getElementById(s).value || 0; | ||
| + | } | ||
| - | <!-- ================= TABLEAU 5 : Survie ================= --> | + | |
| - | < | + | |
| - | <label for=" | + | |
| - | <select id=" | + | }); |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | <option value=" | + | |
| - | </ | + | |
| - | <div class="table-container"> | + | // passifs |
| - | <table id=" | + | document.querySelectorAll(".skill: |
| - | < | + | |
| - | < | + | }); |
| - | < | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | </ | + | |
| - | < | + | |
| + | // sorts | ||
| + | document.querySelectorAll(" | ||
| + | data.spells.push({ | ||
| + | dex: +s.dataset.dex, | ||
| + | prot: +s.dataset.prot | ||
| + | }); | ||
| + | }); | ||
| + | return data; | ||
| + | } | ||
| + | // ===================================== | ||
| + | // APPLY BUILD | ||
| + | // ===================================== | ||
| - | <!-- ================= COMMUNS ================= --> | + | function applyBuild(data){ |
| - | <tr class=" | + | // race |
| - | <td class="race-Communs"> | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| + | // recharge équipements race | ||
| + | resetSlots(); | ||
| + | fillEquip(); | ||
| - | <tr class=" | + | |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | } |
| - | <tr class=" | + | |
| - | <td class=" | + | |
| - | <td>X MP, Y Mvt, 1A</ | + | |
| - | < | + | }); |
| - | < | + | |
| - | </tr> | + | |
| - | <tr class=" | + | |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | data.skills?.includes(s.dataset.name); |
| - | </ | + | }); |
| - | + | ||
| - | <tr class="Communs"> | + | |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | + | ||
| - | <tr class=" | + | |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | + | ||
| - | <tr class=" | + | |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | + | ||
| - | <tr class=" | + | |
| - | <td class=" | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | </tbody> | + | |
| - | </table> | + | |
| - | </div> | + | |
| + | s.checked = data.spells? | ||
| + | sp.dex == +s.dataset.dex && | ||
| + | sp.prot == +s.dataset.prot | ||
| + | ); | ||
| - | < | + | }); |
| - | // Script pour le cinquième tableau | + | |
| - | const select5 = document.getElementById(" | + | |
| - | const rows5 = document.querySelectorAll("# | + | |
| - | select4.addEventListener(" | + | displayBase(); |
| - | const chosenRace = select5.value; | + | |
| - | rows3.forEach(row => { | + | |
| - | | + | } |
| - | | + | |
| - | | + | |
| - | | + | |
| - | }); | + | |
| - | </ | + | |
| + | // ===================================== | ||
| + | // EXPORT | ||
| + | // ===================================== | ||
| - | </ | + | function exportBuild(){ |
| - | </ | + | |
| + | let data = getBuildData(); | ||
| + | let code = encodeBuild(data); | ||
| + | prompt(" | ||
| + | } | ||
| - | **Fonctionnement de la carte sur Olympia** : | + | // ===================================== |
| - | >1) Tous les joueurs sur Olympia apparaissent en points noirs sur la carte du monde. | + | // IMPORT |
| - | > | + | // ===================================== |
| - | >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. | + | |
| - | + | function importBuild(codeInput){ | |
| - | **Fonctionnement des compétences de discrétion **: | + | |
| - | >1) Lorsque le personnage utilise la compétence " | + | |
| - | > | + | |
| - | >Lors de son prochain tour, pour être de nouveau invisible sur la carte du monde, le joueur devra relancer la compétence " | + | |
| - | > | + | |
| - | >2) Pour éviter que ce soit trop simple de rester furtif, le coût augmente à mesure du nombre d' | + | |
| - | > | + | |
| - | >3) Utiliser une compétence de discrétion (Discrétion pour le moment) ajoute une charge de l' | + | |
| - | > | + | |
| - | >4) Pour réinitialiser le coût des compétences de discrétion, | + | |
| - | > | + | |
| - | >5)Avec la compétence Discrétion, | + | |
| + | 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(" | ||
| + | |||
| + | } | ||
| + | |||
| + | })(); | ||
| + | |||
| + | </ | ||
| + | </ | ||
| + | </ | ||
brouillon3.1776592929.txt.gz · Dernière modification : 2026/04/19 12:02 de nanaki
