217 lines
5.6 KiB
JavaScript
217 lines
5.6 KiB
JavaScript
// ==UserScript==
|
|
// @name Evolve Helper
|
|
// @namespace http://tampermonkey.net/
|
|
// @version 2024-12-06
|
|
// @description accerlate and automate
|
|
// @author liooil
|
|
// @match https://pmotschmann.github.io/Evolve/
|
|
// @icon https://www.google.com/s2/favicons?sz=64&domain=github.io
|
|
// @grant none
|
|
// ==/UserScript==
|
|
|
|
let autoIds = getStrSet("autoIds") ?? new Set();
|
|
let vueMethod;
|
|
|
|
let scanTimer = setInterval(scan, getInt("scanInterval") ?? 1000);
|
|
let autoTimer = setInterval(auto, getInt("autoInterval") ?? 100);
|
|
|
|
function scan() {
|
|
const versionLogEl = document.getElementById("versionLog");
|
|
if (versionLogEl) {
|
|
menuBtn(versionLogEl, "scanInterval", "int", 1000, (val) => {
|
|
clearInterval(scanTimer);
|
|
scanTimer = setInterval(scan, val);
|
|
});
|
|
menuBtn(versionLogEl, "autoInterval", "int", 100, (val) => {
|
|
clearInterval(autoTimer);
|
|
autoTimer = setInterval(scan, val);
|
|
});
|
|
menuBtn(versionLogEl, "customSpeed", "int", 1, () => {
|
|
if (!vueMethod._data.s.pause) {
|
|
fromScript = true;
|
|
vueMethod.pause();
|
|
}
|
|
});
|
|
menuBtn(versionLogEl, "autoRun", "bool", true);
|
|
vueMethod = document.getElementById("topBar").__vue__;
|
|
}
|
|
for (const node of document.querySelectorAll("div.action.vb")) {
|
|
autoBtn(node, node.firstChild);
|
|
}
|
|
for (const node of document.querySelectorAll("div.resource.crafted")) {
|
|
if (node.style.display === "none") continue;
|
|
autoBtn(node, node.firstChild);
|
|
}
|
|
for (const node of document.getElementById("market")?.querySelectorAll("div.market-item") ?? []) {
|
|
if (node.style.display === "none") continue;
|
|
for (const type of ['buy', 'sell']) {
|
|
const span = node.querySelector('span.' + type);
|
|
if (!span) continue;
|
|
autoBtn(span, span, node.id + '-' + type);
|
|
}
|
|
}
|
|
}
|
|
|
|
function auto() {
|
|
if (!getBool("autoRun")) return;
|
|
for (const id of autoIds) {
|
|
for (const type of ['buy', 'sell']) {
|
|
if (id.endsWith('-' + type)) {
|
|
const el = document.getElementById(id.slice(0, -type.length - 1));
|
|
if (!el) continue;
|
|
const prev = el.querySelector('span.' + type);
|
|
if (!prev) continue;
|
|
prev.nextElementSibling.click();
|
|
}
|
|
}
|
|
const el = document.getElementById(id);
|
|
if (!el || el.classList.contains("cna")) continue;
|
|
/** @type {HTMLElement} */
|
|
const a = el.querySelector("a.button,a:has(span[data-val='A'])");
|
|
if (a) a.click();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} key
|
|
* @param {number} defaultVal
|
|
*/
|
|
function useInt(key, defaultVal) {
|
|
let text = localStorage.getItem(key);
|
|
let val = text ? parseInt(text) : defaultVal;
|
|
return [
|
|
() => val,
|
|
/** @type {(val: number) => void} */
|
|
(v) => {
|
|
val = v;
|
|
localStorage.setItem(key, v.toString());
|
|
}
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param {string} key
|
|
*/
|
|
function getInt(key) {
|
|
const val = localStorage.getItem(key);
|
|
if (val !== null) return parseFloat(val);
|
|
}
|
|
/**
|
|
* @param {string} key
|
|
* @param {number} val
|
|
*/
|
|
function setInt(key, val) {
|
|
localStorage.setItem(key, val)
|
|
}
|
|
/**
|
|
* @param {string} key
|
|
*/
|
|
function getStrSet(key) {
|
|
const val = localStorage.getItem(key);
|
|
if (val !== null) return new Set(val.split(","));
|
|
}
|
|
/**
|
|
* @param {string} key
|
|
* @param {Set<string>} val
|
|
*/
|
|
function setStrSet(key, val) {
|
|
localStorage.setItem(key, [...val.keys()].join(","))
|
|
}
|
|
/**
|
|
* @param {string} key
|
|
*/
|
|
function getBool(key) {
|
|
const val = localStorage.getItem(key);
|
|
if (val !== null) return val === "true";
|
|
}
|
|
/**
|
|
* @param {string} key
|
|
* @param {boolean} val
|
|
*/
|
|
function setBool(key, val) {
|
|
localStorage.setItem(key, val.toString());
|
|
}
|
|
|
|
/**
|
|
* @param {HTMLElement} nextElementSibling
|
|
* @param {string} id
|
|
* @param {"int" | "bool"} type
|
|
* @param {number} defaultVal
|
|
* @param {(val: number) => void} cb
|
|
*/
|
|
function menuBtn(nextElementSibling, id, type, defaultVal, cb) {
|
|
if (document.getElementById(id)) return;
|
|
const el = document.createElement("span");
|
|
el.id = id;
|
|
el.classList.add("version");
|
|
el.style.cursor = "pointer";
|
|
el.textContent = `${id}=${getInt(id) ?? defaultVal}`;
|
|
el.onclick = () => {
|
|
let val;
|
|
if (type === "bool") {
|
|
val = !(getBool(id) ?? defaultVal);
|
|
setBool(id, val);
|
|
} else {
|
|
let input = prompt(`${id}=`, `${getInt(id) ?? defaultVal}`);
|
|
if (input === null) return;
|
|
val = parseInt(input)
|
|
setInt(id, input);
|
|
}
|
|
el.textContent = `${id}=${val}`;
|
|
cb?.(val);
|
|
}
|
|
nextElementSibling.before(el);
|
|
return el;
|
|
}
|
|
|
|
/**
|
|
* add auto button
|
|
* @param {HTMLElement} root
|
|
* @param {HTMLElement?} parent
|
|
*/
|
|
function autoBtn(root, parent = root, id = root.id) {
|
|
/** @type {HTMLButtonElement} */
|
|
let auto = root.querySelector(".auto");
|
|
if (!auto) {
|
|
auto = parent.appendChild(document.createElement("span"));
|
|
auto.classList.add("auto");
|
|
auto.textContent = "A";
|
|
auto.onclick = (e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
if (autoIds.has(id)) {
|
|
autoIds.delete(id);
|
|
auto.style.color = "gray";
|
|
} else {
|
|
autoIds.add(id);
|
|
auto.style.color = "green";
|
|
}
|
|
setStrSet("autoIds", autoIds);
|
|
}
|
|
}
|
|
if (autoIds.has(id)) {
|
|
auto.style.color = "green";
|
|
} else {
|
|
auto.style.color = "gray";
|
|
}
|
|
}
|
|
|
|
let fromScript = false;
|
|
|
|
const oldPost = Worker.prototype.postMessage;
|
|
Worker.prototype.postMessage = async function (...args) {
|
|
let that = this
|
|
async function hookPost() {
|
|
if (args[0].period) {
|
|
args[0].period = args[0].period / (getInt("customSpeed") ?? 1)
|
|
}
|
|
oldPost.apply(that, args)
|
|
}
|
|
let hookResult = await hookPost()
|
|
if (fromScript) {
|
|
vueMethod.pause()
|
|
fromScript = false
|
|
}
|
|
return hookResult
|
|
}
|