SDL

Extension du jeu seduis-les.fr

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         SDL
// @version      0.1
// @description  Extension du jeu seduis-les.fr
// @match        *://*.seduis-les.fr/seduire.php?scen=*
// @author       Un Khey Sûr
// @grant        none
// @namespace https://greasyfork.org/users/706973
// ==/UserScript==


let script = [];
let path = [];
let playing = false;
let queueStep = false;

const core = {
    ready: async () => {
        await utils.waitFor(() => {
            const coco = document.getElementById("coco");
            return coco && coco.style && coco.style["background-image"] && coco.style["background-image"] !== "";
        });
    },

    isGameOver: () => {
        const coco = document.getElementById("coco");
        return coco.style["background-image"].includes("go.jpg");
    },

    getGame: () => {
        const title = document.querySelector("body > div:nth-child(7) > table > tbody > tr > td > table:nth-child(4) > tbody > tr:nth-child(1) > td:nth-child(2)").innerHTML.split(":")[1].trim();
        const question = document.querySelector("#txtItem > table:nth-child(1) > tbody > tr > td:nth-child(2) > table.style7 > tbody > tr > td").innerText.trim();
        const table = document.querySelectorAll("#txtItem > table:nth-child(1) > tbody > tr > td:nth-child(2) > table:nth-child(2) > tbody > tr > td > a");
        let answers = [];
        let str = question;

        for (let elem of table) {
            answers.push(elem.innerText.trim());
        }

        answers = answers.sort();

        for (let answer of answers) {
            str += answer;
        }

        answers = answers.sort();

        return {
            title,
            question,
            answers,
            hash: utils.hashCode(str)
        }
    },

    getPath: () => {
        return path;
    },

    play: () => {
        playing = true;
        core.processScript(core.getGame());
    },

    stop: () => {
        queueStep = false;
        playing = false;
    },

    step: () => {
        queueStep = true;
        core.processScript(core.getGame());
    },

    processScript: (game) => {
        let answer = null;
        let i = 0;
        for (let entry of script) {
            i++;
            if (!entry.h || !entry.r || !entry.q) {
                alert("invalid line " + i);
                return;
            }
            if (entry.h === game.hash && entry.q === game.question) {
                answer = entry.r;
                break;
            }
        }

        const table = document.querySelectorAll("#txtItem > table:nth-child(1) > tbody > tr > td:nth-child(2) > table:nth-child(2) > tbody > tr > td > a");
        for (let elem of table) {
            if (answer && elem.innerText.trim() === answer) {
                elem.style["color"] = "green";
                elem.style["font-weight"] = "bold";
            } else {
                elem.style["color"] = "black";
                elem.style["font-weight"] = "normal";
            }
        }


        if (!answer) {
            core.stop();
            const play = document.getElementById("sdl-play");
            const pause = document.getElementById("sdl-pause");
            play.style["display"] = "inline-block";
            pause.style["display"] = "none";
            return;
        };

        if (!playing && !queueStep) return;
        else if (queueStep) queueStep = false;

        core.choose(answer);
    },

    hook: () => {
        const original = window.showText;
        window.showText = async (nb, sco, com, scen) => {
            const prevGame = core.getGame();
            path.push({
                q: prevGame.question,
                r: core.getAnswer(nb, sco, com, scen),
                h: prevGame.hash,
            });

            original(nb, sco, com, scen);

            let game;
            while ((game = core.getGame()).hash === prevGame.hash)
                await utils.sleep(10);

            if (!core.isGameOver()) {
                core.processScript(game);
            }
        };
    },

    setScript: (json) => {
        script = json;
        core.processScript(core.getGame());
    },

    getAnswer: (nb, sco, com, scen) => {
        const table = document.querySelectorAll("#txtItem > table:nth-child(1) > tbody > tr > td:nth-child(2) > table:nth-child(2) > tbody > tr > td > a");
        for (let elem of table) {
            const args = /[^\(]+\(([^\)]+)\)/.exec(elem.getAttribute("onclick"))[1].split(",").map(a => parseInt(a));
            if (args[0] == nb && args[1] == sco && args[2] == com && args[3] == scen)
                return elem.innerText.trim();
        }

        return null;
    },

    getArgs: (answer) => {
        const table = document.querySelectorAll("#txtItem > table:nth-child(1) > tbody > tr > td:nth-child(2) > table:nth-child(2) > tbody > tr > td > a");
        for (let elem of table) {
            if (elem.innerText.trim() === answer)
                return /[^\(]+\(([^\)]+)\)/.exec(elem.getAttribute("onclick"))[1].split(",").map(a => parseInt(a));
        }

        return null;
    },

    choose: (answer) => {
        const args = core.getArgs(answer);
        if (args === null) {
            console.log("can't find arguments for '" + answer + "'");
            return;
        }

        window.showText.apply(null, args);
    }
}

const gui = {

    saveJSON: (data, filename) => {

        if (!data) {
            console.error("No data")
            return;
        }

        if (typeof data === "object") {
            data = JSON.stringify(data, undefined, 4)
        }

        var blob = new Blob([data], {
                type: "text/json"
            }),
            e = document.createEvent("MouseEvents"),
            a = document.createElement("a")

        a.download = filename
        a.href = window.URL.createObjectURL(blob);
        a.dataset.downloadurl = ["text/json", a.download, a.href].join(':')
        e.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
        a.dispatchEvent(e)
    },

    init: () => {
        const parent = document.querySelector("body > div:nth-child(7) > table > tbody > tr > td > table:nth-child(4) > tbody > tr:nth-child(2) > td:nth-child(2)");
        parent.align = "left";
        parent.style["padding-bottom"] = "5px";
        document.head.innerHTML += `
        <style>
            #sdl {
                padding: 2px;
                vertical-align: middle;
            }

            #sdl button {
                cursor: pointer;
                margin-right: 3px;
                margin: 0;
                font-size: 18px;
            }

            #sdl-player {
                vertical-align: middle;
                margin-left: 10px;
            }

            #sdl-pcontainer {
                height: 30px;
                vertical-align: middle;
            }

            #sdl-pcontainer > p {
                margin: 0;
                padding: 0;
                margin-right: 5px;
            }

            #sdl-player, #sdl-player > * {
                display: inline-block;
            }

            #sdl-unload, #sdl-player, #sdl-file, #sdl-pause {
                display: none;
            }

        </style>
        `

        parent.innerHTML = `
        <div id="sdl">
            <button id="sdl-save" title="exporter la progression en fichier script"><svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-cloud-arrow-down-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">  <path fill-rule="evenodd" d="M8 2a5.53 5.53 0 0 0-3.594 1.342c-.766.66-1.321 1.52-1.464 2.383C1.266 6.095 0 7.555 0 9.318 0 11.366 1.708 13 3.781 13h8.906C14.502 13 16 11.57 16 9.773c0-1.636-1.242-2.969-2.834-3.194C12.923 3.999 10.69 2 8 2zm2.354 6.854l-2 2a.5.5 0 0 1-.708 0l-2-2a.5.5 0 1 1 .708-.708L7.5 9.293V5.5a.5.5 0 0 1 1 0v3.793l1.146-1.147a.5.5 0 0 1 .708.708z"/></svg></button>
            <button id="sdl-load" title="importer un fichier script"><svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-cloud-arrow-up-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">  <path fill-rule="evenodd" d="M8 2a5.53 5.53 0 0 0-3.594 1.342c-.766.66-1.321 1.52-1.464 2.383C1.266 6.095 0 7.555 0 9.318 0 11.366 1.708 13 3.781 13h8.906C14.502 13 16 11.57 16 9.773c0-1.636-1.242-2.969-2.834-3.194C12.923 3.999 10.69 2 8 2zm2.354 5.146l-2-2a.5.5 0 0 0-.708 0l-2 2a.5.5 0 1 0 .708.708L7.5 6.707V10.5a.5.5 0 0 0 1 0V6.707l1.146 1.147a.5.5 0 0 0 .708-.708z"/></svg></button>
            <button id="sdl-unload" title="decharger le script"><svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-cloud-slash" fill="currentColor" xmlns="http://www.w3.org/2000/svg">  <path fill-rule="evenodd" d="M3.112 5.112a3.125 3.125 0 0 0-.17.613C1.266 6.095 0 7.555 0 9.318 0 11.366 1.708 13 3.781 13H11l-1-1H3.781C2.231 12 1 10.785 1 9.318c0-1.365 1.064-2.513 2.46-2.666l.446-.05v-.447c0-.075.006-.152.018-.231l-.812-.812zm2.55-1.45l-.725-.725A5.512 5.512 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773a3.2 3.2 0 0 1-1.516 2.711l-.733-.733C14.498 11.378 15 10.626 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3c-.875 0-1.678.26-2.339.661zm7.984 10.692l-12-12 .708-.708 12 12-.707.707z"/></svg></button>
            <div id="sdl-player">
                <div id="sdl-pcontainer"><p id="sdl-script">sdl_scene2.json</p></div>
                <button id="sdl-play" title="jouer tout"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-play-fill" fill="currentColor"><path d="M11.596 8.697l-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z"/></svg></button>
                <button id="sdl-pause" title="arrêter"><svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-pause-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">  <path d="M5.5 3.5A1.5 1.5 0 0 1 7 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5zm5 0A1.5 1.5 0 0 1 12 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5z"/></svg></button>
                <button id="sdl-step" title="jouer une étape"><svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-skip-end-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">  <path fill-rule="evenodd" d="M12 3.5a.5.5 0 0 1 .5.5v8a.5.5 0 0 1-1 0V4a.5.5 0 0 1 .5-.5z"/>  <path d="M11.596 8.697l-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z"/></svg></button>
            </div>
            <input id="sdl-file" type="file" accept=".json" />
        </div>
        `;

        const reader = new FileReader();

        const scriptLabel = document.getElementById("sdl-script");
        const player = document.getElementById("sdl-player");
        const file = document.getElementById("sdl-file");
        const load = document.getElementById("sdl-load");
        const unload = document.getElementById("sdl-unload");
        const save = document.getElementById("sdl-save");
        const play = document.getElementById("sdl-play");
        const pause = document.getElementById("sdl-pause");
        const step = document.getElementById("sdl-step");

        reader.onload = e => {
            try {
                core.setScript(JSON.parse(e.target.result));
                const split = file.value.split("\\");
                scriptLabel.innerText = split[split.length - 1];

                load.style["display"] = "none";
                unload.style["display"] = "inline-block";
                player.style["display"] = "inline-block";
            } catch (e) {
                alert("can't parse JSON");
                console.error(e);
            }
        }



        file.addEventListener("change", e => {
            reader.readAsText(e.target.files[0]);
        });

        load.addEventListener("click", e => {
            file.click();
        });

        unload.addEventListener("click", e => {
            load.style["display"] = "inline-block";
            unload.style["display"] = "none";
            player.style["display"] = "none";
            core.setScript([]);
            core.stop();
        });

        save.addEventListener("click", e => {
            gui.saveJSON(core.getPath(), "sdl_" + Math.floor(Date.now() / 1000) + ".json");
        });

        play.addEventListener("click", e => {
            play.style["display"] = "none";
            pause.style["display"] = "inline-block";
            core.play();
        });

        pause.addEventListener("click", e => {
            play.style["display"] = "inline-block";
            pause.style["display"] = "none";
            core.stop();
        });

        step.addEventListener("click", e => {
            core.step();
        });
    }



}

const utils = {
    sleep: (ms) => {
        return new Promise(resolve => {
            setTimeout(() => resolve(), ms);
        });
    },

    waitFor: (fnc) => {
        return new Promise(async resolve => {
            for (;;) {
                if (fnc() === true) {
                    resolve();
                    return;
                }
                await utils.sleep(100);
            }
        });
    },

    hashCode: (str) => {
        let hash = 0;
        if (str.length == 0) return hash;
        for (let i = 0; i < str.length; i++) {
            let char = str.charCodeAt(i);
            hash = ((hash << 5) - hash) + char;
            hash = hash & hash;
        }
        return hash;
    }
}


async function run(){
    await core.ready();

    if (core.isGameOver())
        return;

    core.hook();
    gui.init();
}

run();