Roll

Faire des jets avec prise en compte des stats via des compétences

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name        Roll
// @namespace   InGame
// @author      Odul, MockingJay
// @match       https://www.dreadcast.net/Main
// @version     1.2
// @grant       none
// @description Faire des jets avec prise en compte des stats via des compétences
// ==/UserScript==

// Alias de commandes, utiliser le format suivant:
// alias: "commande",
const aliases = {
    for: "force",
    agi: "agilite",
    res: "resistance",
    per: "perception",
    fur: "furtivite",
    fufu: "furtivite",
    info: "informatique",
    inf: "informatique",
    med: "medecine",
    inge: "ingenierie",
    ing: "ingenierie",
}

// Pour ajouter des formules personnalisées:
// - Le nom doit être en minuscules, sans accents si espaces, underscores autorisés
// - Les coefficients sont dans l'ordre: force, agilité, résistance, perception, furtivité, informatique, médecine, ingénierie
const formulas = {
    force: [1, 0, 0, 0, 0, 0, 0, 0],
    agilite: [0, 1, 0, 0, 0, 0, 0, 0],
    resistance: [0, 0, 1, 0, 0, 0, 0, 0],
    perception: [0, 0, 0, 1, 0, 0, 0, 0],
    furtivite: [0, 0, 0, 0, 1, 0, 0, 0],
    informatique: [0, 0, 0, 0, 0, 1, 0, 0],
    medecine: [0, 0, 0, 0, 0, 0, 1, 0],
    ingenierie: [0, 0, 0, 0, 0, 0, 0, 1],
    dpasse: [1, 2, 0, 1, 0, 0, 0, 0],
    drecep: [1, 1, 0, 2, 0, 0, 0, 0],
    dplaque: [3, 1, 0, 0, 0, 0, 0, 0],
    dfeinte: [1, 1, 0, 1, 0, 0, 0, 0],
    dinter: [0, 1, 0, 1, 0, 0, 0, 0],
    dtir: [1, 1, 0, 0, 0, 0, 0, 0],
    darret: [1, 0, 0, 3, 0, 0, 0, 0],
    hack: [0, 1, 0, 0, 0, 16, 0, 3],
    programmation: [0, 0, 0, 0, 0, 9, 0, 1],
    diag_meca: [0, 0, 0, 2, 0, 1, 0, 2],
    cablage: [0, 0, 0, 0, 0, 3, 0, 7],
    assemblage: [0, 0, 0, 1, 0, 0, 0, 4],
    desassemblage: [1, 0, 0, 0, 0, 0, 0, 4],
    reparation: [1, 0, 0, 0, 0, 0, 0, 4],
    soudure: [1, 0, 0, 3, 0, 0, 0, 6],
    crochetage: [0, 1, 0, 0, 0, 0, 0, 3],
    desamorcer: [0, 1, 0, 3, 0, 0, 0, 16],
    diag_medical: [0, 0, 0, 1, 0, 0, 4, 0],
    chirurgie: [0, 1, 0, 1, 0, 0, 3, 0],
    massage_cardiaque: [3, 0, 0, 0, 0, 0, 7, 0],
    perfusion: [0, 1, 0, 2, 0, 0, 2, 0],
    desinfecter: [0, 3, 0, 0, 0, 0, 2, 0],
    garot: [1, 0, 0, 0, 0, 0, 1, 0],
    tir: [0, 1, 0, 4, 0, 0, 0, 0],
    parade: [0, 4, 0, 1, 0, 0, 0, 0],
    esquive: [1, 9, 0, 0, 0, 0, 0, 0],
    liberation: [4, 5, 0, 0, 0, 0, 0, 1],
    immobilisation: [1, 0, 1, 0, 0, 0, 0, 0],
    equilibre: [0, 4, 1, 0, 0, 0, 0, 0],
    volonte: [4, 2, 9, 1, 1, 1, 1, 1],
    blessure: [0, 1, 9, 0, 0, 0, 0, 0],
    enfoncer: [7, 0, 3, 0, 0, 0, 0, 0],
    mensonge: [0, 3, 0, 0, 5, 0, 2, 0],
    dmensonge: [0, 3, 0, 5, 0, 0, 2, 0],
    maquillage: [0, 8, 0, 2, 0, 0, 0, 0],
    musique: [0, 3, 0, 2, 0, 0, 0, 0],
    accorder: [0, 0, 0, 2, 0, 0, 0, 3],
    fee_lation: [0, 6, 0, 1, 0, 0, 4, 0],
    orgasme: [0, 1, 1, 0, 0, 0, 0, 0],
    skype: [0, 0, 0, 0, 0, 0, 2, 0],
    fee_niasse: [0, 1, 1, 0, 0, 0, 0, 0],
    overflow: [1, 1, 1, 1, 1, 1, 1, 1],
}

// CORE FNS //

const getStats = function() {
    let stats = [];

    for (let i = 1; i <= 8; i++) {
        stats.push(parseInt($('#statistiques .infos .stat_' + i + '_entier').text()));
    }

    return stats;
}

const computeValue = function(skillName){
    if (!formulas[skillName]) {
        return null;
    }

    const stats = getStats();
    const totalWeight = formulas[skillName].reduce(((total, weight) => total + weight), 0);
    const skillPoints = stats.reduce(((total, stat, i) => total + stat * formulas[skillName][i]), 0);

    return 100 - Math.floor((skillPoints / totalWeight) / 6);
}

const retrieveValue = function(facesde, comp, diff)
{
    const ligne = $("#chatContent > .msg.hrp > em").last().text();

    if (!ligne) {
        return;
    }

    if (ligne.includes($("txt_pseudo").text() + " lance 1 dé de " + facesde + " et fait")) {
        let result = parseInt(ligne.substring(ligne.indexOf("et fait") + 7).trim()) + (100 - facesde);
        let threshold = 0;

        switch(diff) {
            case "f":
            case "facile":
                threshold = 25;
                diff = "facile";
                break;
            case "m":
            case "moyen":
                threshold = 50;
                diff = "moyen";
                break;
            case "d":
            case "difficile":
                threshold = 75;
                diff = "difficile";
                break;
            default:
                threshold = parseInt(diff) || 0;
        }

        let textResult = "";

        if (!threshold) {
            textResult += "/me [couleur=jaune]fait "+ result +" à son jet de " + comp + "[/couleur]";
        }
        else if (["facile", "moyen", "difficile"].includes(diff)) {
            textResult += result >= threshold ?
                "/me [couleur=vert]réussit[/couleur] " :
            "/me [couleur=rouge]rate[/couleur] ";
            textResult += "[couleur=jaune]un jet " + diff + " de " + comp + " et fait " + result + "[/couleur]";
        }
        else {
            textResult += result >= threshold ?
                "/me [couleur=vert]réussit[/couleur] " :
            "/me [couleur=rouge]rate[/couleur] ";
            textResult += "[couleur=jaune]un jet de " + comp + " en faisant " + result + " contre un seuil de " + threshold + "[/couleur]";
        }

        $("#chatForm .text_chat").val(textResult);
        nav.getChat().send();
    }

}

const jetDes = function(e) {
    let value = $("#chatForm .text_chat").val();

    if (!value.match(/^\/roll [a-zA-Z]+/)) {
        return; // Ne traiter que l'envoi de /roll avec commande (ignore également les XdY)
    }

    value = value.replace(/[àâ]/g, "a").replace(/[éèê]/g, "e").replace(/[î]/g, "i").replace(/[ô]/g, "o").replace(/[ûù]/g, "u");
    // Essayer d'ignorer les accents

    let comp = value.trim().split(" ")[1].toLowerCase();
    const diff = value.trim().split(" ")[2];

    comp = aliases[comp] || comp;
    const facesde = computeValue(comp);

    if (facesde) {
        value = '/roll 1d' + facesde;
        setTimeout(function() {
            retrieveValue(facesde, comp, diff)
        }, 500);
    }
    else {
        e.preventDefault(); // Empêche l'envoi d'un roll mal écrit
    }

    $("#chatForm .text_chat").val(value);
}

// GUI //

$("body").append(`<style>
#rollPanel {
	position: absolute;
	right: -220px;
	bottom: 20px;
	z-index: 999999;
	display: flex;
}

#rollPanel button, #rollPanel input, #rollPanel select {
	background-color: #8ab6e4;
}

#rollToggle {
	background-color: #6ea0d3;
	height: fit-content;
}

#rollToggle button {
	height: 50px;
	width: 50px;
}

#rollOptions {
	background-color: #6ea0d3;
	padding: 10px;
	width: 200px;
}

#rollOptions label, #rollHasThreshold {
	vertical-align: middle;
}

#rollType, #rollThreshold, .rollPresetDiff {
	height: 30px;
}

.rollPresetDiff {
	flex: 1;
}

#rollType {
	max-width: 160px;
}

#rollThreshold {
	-moz-appearance: textfield;
	text-align: center;
}

#rollThreshold::-webkit-outer-spin-button,
#rollThreshold::-webkit-inner-spin-button {
	-webkit-appearance: none;
 	margin: 0;
}

#rollPresetDiffs {
	display: flex;
}

#rollSubmit {
	width: 100%;
    height: 40px;
    font-size: 18px;
}
</style>`);

$("body").append(`
<div id="rollPanel">
  <div id="rollToggle">
    <button>&lt; Roll</button>
  </div>
  <div id="rollOptions">
    <label for="rollType">Test:</label>

    <select name="rollType" id="rollType">
        <option value="">Standard (1d100)</option>
    </select>

    <br><br>

    <input type="checkbox" name="rollHasThreshold" id="rollHasThreshold">
    <label for="rollHasThreshold">Seuil de réussite</label>
    <input type="number" name="rollThreshold" id="rollThreshold" min="0" max="100" value="0" disabled>

    <br><br>

    <div id="rollPresetDiffs">
      <button id="rollSetEasy" class="rollPresetDiff" value="25" disabled>Facile</button>
      <button id="rollSetMedium" class="rollPresetDiff" value="50" disabled>Moyen</button>
      <button id="rollSetHard" class="rollPresetDiff" value="75" disabled>Difficile</button>
    </div>

    <br>

    <button id="rollSubmit">Lancer</button>
  </div>
</div>
`);

for (let formula in formulas) {
    $("#rollType").append(`<option value="${formula}">${formula}</option>`);
}

let showGUI = false;

$("#rollToggle button").click(function() {
    if (showGUI) {
        $("#rollPanel").css("right", "-220px");
        $("#rollToggle button").text("< Roll");
        showGUI = false;
    }
    else {
        $("#rollPanel").css("right", "0px");
        $("#rollToggle button").text("> Roll");
        showGUI = true;
    }
});

$("#rollHasThreshold").change(function() {
    if ($("#rollHasThreshold").attr("checked")) {
        $(".rollPresetDiff, #rollThreshold").prop("disabled", false);
        $("#rollThreshold").select();
    }
    else {
        $(".rollPresetDiff, #rollThreshold").prop("disabled", true);
    }
});

$(".rollPresetDiff").click(function() {
    $("#rollThreshold").val($(this).attr("value")).select();
});

$("#rollSubmit").click(function() {

    const rollType = $("#rollType").val();
    let roll = "/roll ";

    if (!rollType) {
        roll += "1d100";
    } else {
        roll += rollType;
        if ($("#rollHasThreshold").attr("checked")) {
            roll += " ";
            const threshold = parseInt($("#rollThreshold").val());
            switch (threshold) {
                case 25:
                    roll += "f";
                break;
                case 50:
                    roll += "m";
                break;
                case 75:
                    roll += "d";
                break;
                default:
                    roll += threshold;
            }
        }
    }

    $("#chatForm .text_chat").val(roll);
    $("#chatForm .text_valider").click();

    $("#rollPanel").css("right", "-220px");
    $("#rollToggle button").text("< Roll");
    showGUI = false;
});


// MAIN //

document.addEventListener('keypress', (e) => {
    if (e.keyCode == 13) {
        jetDes(e);
    }
}, false);

$("#chatForm .text_valider").click(jetDes);

console.log("Script Roll - Actif.");