您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Helper for TheresMoreGame
当前为
// ==UserScript== // @name TheresMoreHelp // @namespace TheresMoreGame.com // @match https://www.theresmoregame.com/play/ // @grant none // @version 1.4 // @description Helper for TheresMoreGame // @license MIT // @run-at document-idle // ==/UserScript== ;(async () => { const cheatsOff = true const sleep = (ms) => new Promise((r) => setTimeout(r, ms)) // https://stackoverflow.com/a/55366435 class NumberParser { constructor(locale) { const format = new Intl.NumberFormat(locale) const parts = format.formatToParts(12345.6) const numerals = Array.from({ length: 10 }).map((_, i) => format.format(i)) const index = new Map(numerals.map((d, i) => [d, i])) this._group = new RegExp(`[${parts.find((d) => d.type === 'group').value}]`, 'g') this._decimal = new RegExp(`[${parts.find((d) => d.type === 'decimal').value}]`) this._numeral = new RegExp(`[${numerals.join('')}]`, 'g') this._index = (d) => index.get(d) } parse(string) { let multiplier = 1 if (string.includes('K')) { multiplier = 1000 } else if (string.includes('M')) { multiplier = 1000000 } return (string = string.replace('K', '').replace('M', '').trim().replace(this._group, '').replace(this._decimal, '.').replace(this._numeral, this._index)) ? +string * multiplier : NaN } } const numberParser = new NumberParser() const formatTime = (timeToFormat) => { const timeValues = { seconds: 0, minutes: 0, hours: 0, days: 0, } let timeShort = '' let timeLong = '' timeValues.seconds = timeToFormat % 60 timeToFormat = (timeToFormat - (timeToFormat % 60)) / 60 timeValues.minutes = timeToFormat % 60 timeToFormat = (timeToFormat - (timeToFormat % 60)) / 60 timeValues.hours = timeToFormat % 24 timeToFormat = (timeToFormat - (timeToFormat % 24)) / 24 timeValues.days = timeToFormat if (timeValues.days) { timeShort += `${timeValues.days}d ` timeLong += `${timeValues.days} days ` } if (timeValues.hours) { timeShort += `${timeValues.hours}h ` timeLong += `${timeValues.hours} hrs ` } if (timeValues.minutes) { timeShort += `${timeValues.minutes}m ` timeLong += `${timeValues.minutes} min ` } if (timeValues.seconds) { timeShort += `${timeValues.seconds}s ` timeLong += `${timeValues.seconds} sec ` } timeShort = timeShort.trim() timeLong = timeLong.trim() return { timeShort, timeLong, timeValues, } } const findResource = (resourceName = 'Gold') => { let resourceFound = false let resourceToFind = { name: resourceName, current: 0, max: 0, speed: 0, ttf: null, ttz: null } const resources = document.querySelectorAll('#root div > div > div > table > tbody > tr > td:nth-child(1) > span') resources.forEach((resource) => { if (resource.textContent.includes(resourceName)) { resourceFound = true const values = resource.parentNode.parentNode.childNodes[1].textContent .split('/') .map((x) => numberParser.parse(x.replace(/[^0-9KM\-,\.]/g, '').trim())) resourceToFind.current = values[0] resourceToFind.max = values[1] resourceToFind.speed = numberParser.parse(resource.parentNode.parentNode.childNodes[2].textContent.replace(/[^0-9KM\-,\.]/g, '').trim()) resourceToFind.ttf = resourceToFind.speed > 0 && resourceToFind.max !== resourceToFind.current ? formatTime(Math.ceil((resourceToFind.max - resourceToFind.current) / resourceToFind.speed)) : null resourceToFind.ttz = resourceToFind.speed < 0 && resourceToFind.current ? formatTime(Math.ceil(resourceToFind.current / (resourceToFind.speed * -1))) : null } }) return resourceFound ? resourceToFind : null } let shouldStopClicking = false window.stopClicking = () => (shouldStopClicking = true) window.generateGold = async () => { window.stopClicking() await sleep(10) shouldStopClicking = false let gold = findResource('Gold') if (gold && gold.current < gold.max) { const buttons = document.querySelectorAll('[id^="headlessui-tabs-tab-"]') let marketplace = false buttons.forEach((button) => { if (button.innerText.includes('Marketplace')) { marketplace = button } }) if (marketplace) { marketplace.click() await sleep(100) const buyHorses = document.querySelector( 'div > div > div.grid.gap-3.grid-cols-fill-240.min-w-full > div:nth-child(8) > div.grid.gap-2.grid-cols-2 > button:nth-child(4)' ) const sellHorses = document.querySelector( 'div > div > div.grid.gap-3.grid-cols-fill-240.min-w-full > div:nth-child(8) > div.grid.gap-2.grid-cols-2 > button:nth-child(3)' ) while (gold && gold.current < gold.max && !shouldStopClicking) { buyHorses.click() await sleep(1) sellHorses.click() await sleep(1) gold = findResource('Gold') } } } shouldStopClicking = false } window.getManualResources = async () => { window.stopClicking() await sleep(10) shouldStopClicking = false const manualResources = ['Food', 'Wood', 'Stone'] const resourcesToClick = [] const buttonsToClick = [] const buttons = document.querySelectorAll( '#root > div.flex.flex-wrap.w-full.mx-auto.p-2 > div.w-full.lg\\:pl-2 > div > div.order-2.flex.flex-wrap.gap-3 > button' ) manualResources.forEach((resourceName) => { const resource = findResource(resourceName) if (resource && resource.current < resource.max) { resourcesToClick.push(resourceName) } }) buttons.forEach((button) => { if (resourcesToClick.includes(button.innerText.trim())) { buttonsToClick.push(button) } }) while (buttonsToClick.length && !shouldStopClicking) { const buttonToClick = buttonsToClick.shift() const resource = findResource(buttonToClick.innerText.trim()) if (resource && resource.current < resource.max) { buttonToClick.click() await sleep(1) buttonsToClick.push(buttonToClick) } } shouldStopClicking = false } const createPanel = () => { if (cheatsOff) return const controlPanel = document.querySelector('div#theresMoreHelpControlPanel') if (!controlPanel) { const controlPanelElement = document.createElement('div') controlPanelElement.id = 'theresMoreHelpControlPanel' controlPanelElement.style.position = 'fixed' controlPanelElement.style.bottom = '20px' controlPanelElement.style.left = '20px' controlPanelElement.style.zIndex = '99999999' controlPanelElement.innerHTML = ` <button onClick="window.stopClicking()" title="Stop auto-clicking">🛑</button> <button onClick="window.getManualResources()" title="Get Manual Resources"><svg viewBox="0 0 24 24" role="presentation" class="icon inline -mt-1 mr-2"><path d="M14.79,10.62L3.5,21.9L2.1,20.5L13.38,9.21L14.79,10.62M19.27,7.73L19.86,7.14L19.07,6.35L19.71,5.71L18.29,4.29L17.65,4.93L16.86,4.14L16.27,4.73C14.53,3.31 12.57,2.17 10.47,1.37L9.64,3.16C11.39,4.08 13,5.19 14.5,6.5L14,7L17,10L17.5,9.5C18.81,11 19.92,12.61 20.84,14.36L22.63,13.53C21.83,11.43 20.69,9.47 19.27,7.73Z" style="fill: currentcolor;"></path></svg></button> <button onClick="window.generateGold()" title="Get Gold From Market"><svg viewBox="0 0 24 24" role="presentation" class="icon inline -mt-1 mr-2"><path d="M1 22L2.5 17H9.5L11 22H1M13 22L14.5 17H21.5L23 22H13M6 15L7.5 10H14.5L16 15H6M23 6.05L19.14 7.14L18.05 11L16.96 7.14L13.1 6.05L16.96 4.96L18.05 1.1L19.14 4.96L23 6.05Z" style="fill: currentcolor;"></path></svg></button> ` document.querySelector('div#root').insertAdjacentElement('afterend', controlPanelElement) } } const calculateTTF = () => { const resourceTrNodes = document.querySelectorAll('#root > div > div:not(#maintabs-container) > div > div > div > table:not(.hidden) > tbody > tr') resourceTrNodes.forEach((row) => { const cells = row.querySelectorAll('td') const resourceName = cells[0].textContent.trim() const resource = findResource(resourceName) let ttf = '' if (resource && resource.current < resource.max && resource.speed) { ttf = resource.ttf ? resource.ttf.timeLong : resource.ttz.timeLong } if (!cells[3]) { const ttfElement = document.createElement('td') ttfElement.className = 'px-3 3xl:px-5 py-3 lg:py-2 3xl:py-3 whitespace-nowrap w-1/3 text-right' ttfElement.textContent = ttf row.appendChild(ttfElement) } else { cells[3].textContent = ttf } }) } const calculateTippyTTF = () => { let potentialResourcesToFillTable = document.querySelectorAll('div.tippy-box > div.tippy-content > div > div > table') if (potentialResourcesToFillTable.length) { potentialResourcesToFillTable = potentialResourcesToFillTable[0] const rows = potentialResourcesToFillTable.querySelectorAll('tr') rows.forEach((row) => { const cells = row.querySelectorAll('td') const resourceName = cells[0].textContent.trim() const resource = findResource(resourceName) if (resource) { let ttf = '✅' const target = numberParser.parse( cells[1].textContent .split(' ') .shift() .replace(/[^0-9KM\-,\.]/g, '') .trim() ) if (target > resource.max || resource.speed <= 0) { ttf = 'never' } else if (target > resource.current) { ttf = formatTime(Math.ceil((target - resource.current) / resource.speed)).timeShort } if (!cells[2]) { const ttfElement = document.createElement('td') ttfElement.className = 'px-4 3xl:py-1 text-right' ttfElement.textContent = ttf row.appendChild(ttfElement) } else { cells[2].textContent = ttf } } }) } } const performRoutineTasks = () => { createPanel() calculateTTF() } const performFastTasks = () => { calculateTippyTTF() } window.setInterval(performRoutineTasks, 1000) window.setInterval(performFastTasks, 100) })()