Automate Arcanum

Automates the game arcanum by allowing autoclicking and autocasting

当前为 2023-09-12 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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"));
        }
    });

})();