/** * difficultés au delà de -10 */ const levelDown = [ { level: -11, score: 1, sign: 0, part: 0, epart: 2, etotal: 90 }, { level: -12, score: 1, sign: 0, part: 0, epart: 2, etotal: 70 }, { level: -13, score: 1, sign: 0, part: 0, epart: 2, etotal: 50 }, { level: -14, score: 1, sign: 0, part: 0, epart: 2, etotal: 30 }, { level: -15, score: 1, sign: 0, part: 0, epart: 2, etotal: 10 }, { level: -16, score: 1, sign: 0, part: 0, epart: 0, etotal: 2 } ]; const levelImpossible = { score: 0, sign: 0, part: 0, epart: 0, etotal: 1 }; /** * Table des résultats spéciaux - inutilisée, conservée si on veut afficher la table */ const specialResults = [ { part: 0, epart: 0, etotal: 0, min: 0, max: 0 }, { part: 1, epart: 81, etotal: 92, min: 1, max: 5 }, { part: 2, epart: 82, etotal: 92, min: 6, max: 10 }, { part: 3, epart: 83, etotal: 93, min: 11, max: 15 }, { part: 4, epart: 84, etotal: 93, min: 16, max: 20 }, { part: 5, epart: 85, etotal: 94, min: 21, max: 25 }, { part: 6, epart: 86, etotal: 94, min: 26, max: 30 }, { part: 7, epart: 87, etotal: 95, min: 31, max: 35 }, { part: 8, epart: 88, etotal: 95, min: 36, max: 40 }, { part: 9, epart: 89, etotal: 96, min: 41, max: 45 }, { part: 10, epart: 90, etotal: 96, min: 46, max: 50 }, { part: 11, epart: 91, etotal: 97, min: 51, max: 55 }, { part: 12, epart: 92, etotal: 97, min: 56, max: 60 }, { part: 13, epart: 93, etotal: 98, min: 61, max: 65 }, { part: 14, epart: 94, etotal: 98, min: 65, max: 70 }, { part: 15, epart: 95, etotal: 99, min: 71, max: 75 }, { part: 16, epart: 96, etotal: 99, min: 76, max: 80 }, { part: 17, epart: 97, etotal: 100, min: 81, max: 85 }, { part: 18, epart: 98, etotal: 100, min: 86, max: 90 }, { part: 19, epart: 99, etotal: 100, min: 81, max: 95 }, { part: 20, epart: 100, etotal: 100, min: 96, max: 100 } ]; const reussites = [ { code: "etotal", isPart: false, isSign: false, isSuccess: false, isEPart: true, isETotal: true, tache: -4, qualite: -6, quality: "Echec total", condition: (target, roll) => roll >= target.etotal && roll <= 100 }, { code: "epart", isPart: false, isSign: false, isSuccess: false, isEPart: true, isETotal: false, tache: -2, qualite: -4, quality: "Echec particulier", condition: (target, roll) => (roll >= target.epart && roll < target.etotal) }, { code: "echec", isPart: false, isSign: false, isSuccess: false, isEPart: false, isETotal: false, tache: 0, qualite: -2, quality: "Echec normal", condition: (target, roll) => (roll > target.score && roll < target.etotal) }, { code: "norm", isPart: false, isSign: false, isSuccess: true, isEPart: false, isETotal: false, tache: 1, qualite: 0, quality: "Réussite normale", condition: (target, roll) => (roll > target.sign && roll <= target.score) }, { code: "sign", isPart: false, isSign: true, isSuccess: true, isEPart: false, isETotal: false, tache: 2, qualite: 1, quality: "Réussite significative", condition: (target, roll) => (roll > target.part && roll <= target.sign) }, { code: "part", isPart: true, isSign: true, isSuccess: true, isEPart: false, isETotal: false, tache: 3, qualite: 2, quality: "Réussite Particulière!", condition: (target, roll) => (roll > 0 && roll <= target.part) }, { code: "error", isPart: false, isSign: false, isSuccess: false, isEPart: true, isETotal: true, tache: 0, qualite: 0, quality: "Jet de dés invalide", condition: (target, roll) => (roll <= 0 || roll > 100) } ]; const reussiteSignificative = reussites.find(r => r.code == "sign"); const reussiteNormale = reussites.find(r => r.code == "norm"); const echecNormal = reussites.find(r => r.code == "echec"); export class RdDResolutionTable { static resolutionTable = this.build() /* -------------------------------------------- */ static build() { let table = [] for (var carac = 0; carac <= 30; carac++) { table[carac] = this._computeRow(carac); } return table; } /* -------------------------------------------- */ static roll(carac, difficulte) { return this.rollChances(this.computeChances(carac, difficulte)); } static rollChances(chances) { chances.roll = new Roll("d100").roll().total; mergeObject(chances, this._computeReussite(chances, chances.roll)); return chances; } static computeChances(carac, difficulte) { if (difficulte < -16) { return duplicate(levelImpossible); } if (difficulte < -10) { return duplicate(levelDown.find(levelData => levelData.level == difficulte)); } return duplicate(this.resolutionTable[carac][difficulte + 10]); } static buildXpMessage(rolled, level) { if (rolled.isPart && level < 0) { const xp = Math.abs(level); const xpcarac = Math.floor(xp / 2); const xpcomp = xp - xpcarac; return "
Points d'expérience gagnés ! Carac: " + xpcarac + ", Comp: " + xpcomp; } return ""; } /* -------------------------------------------- */ static _computeReussite(chances, roll) { const reussite = reussites.find(x => x.condition(chances, roll)); if (chances.needSignificative) { if (reussite.isSign) { return reussiteNormale; } if (reussite.isSuccess){ return echecNormal; } } return reussite; } static _computeRow(carac) { let dataRow = [ this._computeCell(-10, Math.max(Math.floor(carac / 4), 1)), this._computeCell(-9, Math.max(Math.floor(carac / 2), 1)) ] for (var diff = -8; diff <= 22; diff++) { dataRow[diff + 10] = this._computeCell(diff, Math.max(Math.floor(carac * (diff + 10) / 2), 1)); } return dataRow; } static _computeCell(niveau, percentage) { return { niveau: niveau, score: percentage, sign: this._reussiteSignificative(percentage), part: this._reussitePart(percentage), epart: this._echecParticulier(percentage), etotal: this._echecTotal(percentage) } } static _reussiteSignificative(score) { return Math.floor(score / 2); } static _reussitePart(score) { return Math.ceil(score / 5); } static _echecParticulier(score) { return Math.ceil(score / 5) + 80; } static _echecTotal(score) { return Math.ceil(score / 10) + 91; } /* -------------------------------------------- */ static buildHTMLTable(caracValue, levelValue, minCarac = 1, maxCarac = 21, minLevel = -10, maxLevel = 11) { return this._buildHTMLTable(caracValue, levelValue, minCarac, maxCarac, minLevel, maxLevel) } /* -------------------------------------------- */ static _buildHTMLTable(caracValue, levelValue, minCarac, maxCarac, minLevel, maxLevel) { minCarac = Math.max(minCarac, 1); maxCarac = Math.min(maxCarac, 30); minLevel = Math.max(minLevel, -10); maxLevel = Math.min(maxLevel, 22); var table = $("") .append(this._buildHTMLHeader(this.resolutionTable[0], minLevel, maxLevel)); for (var carac = minCarac; carac <= maxCarac; carac++) { table.append(this._buildHTMLRow(this.resolutionTable[carac], carac, caracValue, levelValue, minLevel, maxLevel)); } return table; } static _buildHTMLHeader(dataRow, minLevel, maxLevel) { var tr = $(""); for (var difficulte = minLevel; difficulte <= maxLevel; difficulte++) { const niveau = dataRow[difficulte + 10].niveau; const txt = (niveau > 0 ? "+" : "") + niveau; tr.append($(""); for (var difficulte = minLevel; difficulte <= maxLevel; difficulte++) { var td = $("
").text(txt)); } return tr; } static _buildHTMLRow(dataRow, rowIndex, caracValue, levelValue, minLevel, maxLevel) { var tr = $("
"); let score = dataRow[difficulte + 10].score; if (rowIndex == caracValue && levelValue == difficulte) { td.addClass('table-resolution-target'); } else if (difficulte == -8) { td.addClass('table-resolution-carac'); } tr.append(td.text(score)); } return tr; } }