Automate Arcanum

Automates the game arcanum by allowing autoclicking and autocasting

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey 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 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         Automate Arcanum
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Automates the game arcanum by allowing autoclicking and autocasting
// @author       You
// @match        https://mathiashjelm.gitlab.io/arcanum/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=galaxy.click
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
    const customStyles = `
  .timeInput {
    width: 6rem;
    background-color: #181818;
    border-color: #646464;
    color: #D7DADC;
    text-align: center;
    padding: var(--sm-gap);
    margin: var(--sm-gap);
  }
  .checkbox {
    position: relative;
    display: inline-block;
    width: 1.25em;
    height: 1.25em;
    background-color: transparent;
    border: 1px solid #000;
  }
  .autoCheck {
    margin-left: -1.75em;
    margin-top: 1.35em;
  }
  .quickslotTimer {
    width: 3rem;
    background-color: #181818;
    border-color: #646464;
    color: #D7DADC;
    text-align: center;
    padding: var(--sm-gap);
    margin: var(--sm-gap);
    height: 2rem;
  }
  .quickbar {
  flex-direction: column;
  flex-wrap: wrap;
   justify-content: center;
   align-items: center;
  }
`;
    const loadClass = "load-message"
    let hasLoaded = false;
    let actionInterval = 0;
    let autocastInterval = 0;
    let offMain = false;
    let intervalId;
    let autoKey;
    let quickslotTimers = [];

    function beginAutoAction() {
        clearInterval(intervalId);
        intervalId = setInterval(function() {
            const button = document.querySelector(`[data-key="${autoKey}"]`);
            if (button) {
                button.click();
                console.log(`Timer is currently ${actionInterval} and it is clicking ${autoKey}`);
            }
        }, actionInterval);
    }

    function stopAutoAction() {
        clearInterval(intervalId);
    }

    function beginAutoQuickslot(timer, index) {
        clearInterval(quickslotTimers[index]);
        quickslotTimers[index] = setInterval(function() {
            const quickslot = document.querySelector(`#slot${index}`);
            if (quickslot && quickslot.checked) {
                const quickslot = document.getElementsByClassName("quickslot")[index];
                quickslot.children[0].click();
                console.log(`Clicking the quickslot number ${parseInt(index+1)}`)
            }
        }, timer * 1000);
    }

    function stopAutoQuickSlot(index) {
        clearInterval(quickslotTimers[index]);
    }

    function checkOnlyOne(id, n){
        const checkboxes = document.getElementsByName(n);
        Array.prototype.forEach.call(checkboxes,function(e){
            if (e != id) {
                e.checked = false;
            }
        });
    }

    function pageUpdate() {

        const taskList = document.querySelector(".task-list")
        if (hasLoaded) {
            console.log("Page updated, checking if changes need to be made..");
        }

        let buttons = taskList.querySelectorAll(".task-btn");
        let filteredBtns = Array.from(buttons).filter(button => !button.classList.contains("locked"));
        let lockedBtns = Array.from(buttons).filter(button => button.classList.contains("locked"));
        let i = 0;
        let quickslots = document.querySelector(".quickbar").querySelectorAll(".quickslot").forEach(quickslot => {
            if (document.getElementById("slot"+i)) {
                return
            }

            const checkbox = document.createElement("input");
            checkbox.setAttribute("type", "checkbox");
            checkbox.setAttribute("name", "quickslot");
            checkbox.classList.add("quickCheck");
            checkbox.classList.add("checkbox");
            checkbox.id = "slot"+i;
            checkbox.addEventListener("change", function () {
                const checkboxIndex = parseInt(this.id.replace("slot", ""));
                if (this.checked) {
                    beginAutoQuickslot(document.getElementById("timer"+checkboxIndex).value, checkboxIndex);
                } else {
                    stopAutoQuickSlot(checkboxIndex, checkboxIndex);
                }
            });

            const timer = document.createElement("input");
            timer.setAttribute("placeholder", "(s)");
            timer.addEventListener("input", function(e) {
                const inputValue = e.target.value;
                const cleanedValue = inputValue
                .replace(/[^0-9]+/g, '') // Remove non-numeric and non-dot characters
                .replace(/(\..*?)\..*/g, '$1') // Remove multiple dots
                .replace(/^0[^.]/, '0'); // Remove leading zero before a non-dot character

                if (inputValue !== cleanedValue) {
                    // If the value was changed, update the input field
                    e.target.value = cleanedValue;
                }

                if (e.target.id == "actionTimer") {
                    actionInterval = e.target.value;
                    beginAutoAction();
                }

                if (document.querySelector(`#slot${e.target.id.replace("timer", "")}`).checked) {
                    console.log(`The current timer value is ${e.target.value}`);
                    beginAutoQuickslot(e.target.value, e.target.id.replace("timer", ""));
                }
            });
            timer.classList.add("quickslotTimer")
            timer.setAttribute("type", "text");
            timer.id = `timer${i}`;

            quickslot.insertAdjacentElement("afterend", timer);
            quickslot.insertAdjacentElement('beforeend', checkbox);
            i++;
        });

        filteredBtns.forEach(button => {
            const dataKey = button.getAttribute("data-key")
            if (document.getElementById(dataKey)) {
                return
            }
            const checkbox = document.createElement("input");
            checkbox.setAttribute("type", "checkbox");
            checkbox.setAttribute("name", "task");
            checkbox.classList.add("autoCheck");
            checkbox.classList.add("checkbox");
            checkbox.addEventListener("change", function() {
                if (this.checked && actionInterval != 0) {
                    autoKey = dataKey;
                    beginAutoAction();
                } else {
                    stopAutoAction();
                }
            });
            checkbox.id = dataKey
            button.insertAdjacentElement('afterend', checkbox);
        });

        lockedBtns.forEach(button => {
            const dataKey = button.getAttribute("data-key");
            const checkbox = document.getElementById(dataKey);
            if (checkbox) {
                checkbox.parentNode.removeChild(checkbox);
            }
        });
    }

    function handleDivAppeared(mutationsList) {
        for (const mutation of mutationsList) {
            if(mutation.type === "childList") {
                const addedNodes = Array.from(mutation.addedNodes);
                for (const addedNode of addedNodes) {
                    if (addedNode.classList && addedNode.classList.contains("main-tasks")) {
                        if (document.querySelector(".main-tasks")) {
                            offMain = false;
                            pageUpdate();
                        }
                    }
                }

            }
        }

    }

    function handleDivDisappeared(mutationsList) {
        for (const mutation of mutationsList) {
            if (mutation.type === 'childList') {
                const removedNodes = Array.from(mutation.removedNodes);
                for (const removedNode of removedNodes) {
                    if (removedNode.classList && removedNode.classList.contains("main-task")){
                        offMain = true;
                    }
                    if (removedNode.classList && removedNode.classList.contains(loadClass)) {
                        // Save loaded, run script
                        console.log(`Page loaded, beginning automation.`);
                        // Inject the custom CSS styles into the page
                        GM_addStyle(customStyles);
                        hasLoaded = true;
                        const timer = document.createElement("input");
                        timer.classList.add("timeInput");
                        timer.setAttribute("type", "text");
                        timer.id = "actionTimer";
                        const label = document.createElement("label");
                        label.setAttribute("for", "actionTimer")
                        label.innerHTML="Action interval (ms):"
                        document.querySelector(".load-opts").appendChild(timer);
                        document.querySelector(".load-opts").insertBefore(label, document.getElementById("actionTimer"));
                        timer.addEventListener("input", function(e) {
                            const inputValue = e.target.value;
                            const cleanedValue = inputValue
                            .replace(/[^0-9]+/g, '') // Remove non-numeric and non-dot characters
                            .replace(/(\..*?)\..*/g, '$1') // Remove multiple dots
                            .replace(/^0[^.]/, '0'); // Remove leading zero before a non-dot character

                            if (inputValue !== cleanedValue) {
                                // If the value was changed, update the input field
                                e.target.value = cleanedValue;
                            }

                            if (e.target.id == "actionTimer") {
                                actionInterval = e.target.value;
                                beginAutoAction();
                            }
                        });

                        pageUpdate();

                        startClassObserver();
                    }
                }
            }
        }
    }

    function startClassObserver() {
        const classObserver = new MutationObserver((mutationsList, classObserver) => {
            // Handle class attribute changes here
            pageUpdate();
        });

        const classConfig = { attributes: true, attributeFilter: ['class'] };

        // Start observing class attribute changes
        classObserver.observe(document, classConfig);
    }

    // Create a MutationObserver that watches for changes in the DOM
    const observer = new MutationObserver(handleDivDisappeared);
    const observer2 = new MutationObserver(handleDivAppeared);
    const config = { childList: true, subtree: true };

    // Start observing the DOM
    observer.observe(document, config);
    observer2.observe(document, config);

    document.addEventListener("click", function(e) {
        if(e.target.classList.contains("autoCheck")){
            checkOnlyOne(e.target, e.target.getAttribute("name"));
        }
    });

})();