// ==UserScript== // @name Theresmore自动点击工具 // @namespace Theresmore自动点击工具 // @match https://theresmoregame.g8hh.com/ // @grant none // @version 1.1 // @author zty // @description 解放你的双手自动自动点击工具 // @license MIT // @downloadURL none // ==/UserScript== ; (function () { const timeout = 1000 * 10 // 10秒点一次 const minFood = 2 // 食物最小值 let blackList = initBlackList() // 部分只能建造一个的建筑需要跳过 const houseList = ['房屋', '市政厅', '宅邸', '住宅区', '发展部', '定居点大厅'] // 会减少食物的建筑 function initBlackList() { return ['雕像', '心灵神殿', '战争神殿', '月明之夜', '光荣退休'] } var css = ` #auto_update_btn { position: fixed; right: 0; bottom: 64px; background: #1d1e20; border-radius: 50%; height: 32px; width: 32px; display: flex; align-items: center; justify-content: center; text-align: center; font-size: 14px; border: 2px solid white; z-index: 100; color: white; cursor: pointer; } ` /*添加样式*/ function addStyle(css) { if (!css) return var head = document.querySelector('head') var style = document.createElement('style') style.type = 'text/css' style.innerHTML = css head.appendChild(style) } /*生成自动升级建筑的按钮*/ function createBtn() { var btn = document.createElement('div') btn.title = '开' var span = document.createElement('span') span.innerText = '开' btn.appendChild(span) btn.id = 'auto_update_btn' document.body.appendChild(btn) /*初始化事件*/ // 点击按钮启动定时器 btn.addEventListener('click', function () { toggleBtnStatus() toggleBtnText() }) } // 切换文字 function toggleBtnText() { const node = document.querySelector('#auto_update_btn') const text = node.innerText node.innerText = text === '开' ? '关' : '开' } // 自动升级建筑 function autoBuild() { const tabListNode = document .querySelector('#main-tabs') .querySelector(`div[role=tablist]`) const tabNode = tabListNode.childNodes[0] const flag = tabNode && tabNode.getAttribute('aria-selected') === 'true' if (!flag) { console.log('没找到容器,即将切换到“建造”页') // 自动切换到建造tab页 tabNode && tabNode.click() } else { const id = tabNode.getAttribute('aria-controls') const containerNode = document.getElementById(id) const list = containerNode.querySelectorAll(`button.btn`) const subTabNodes = containerNode.querySelector(`div[role=tablist]`) let isAllUpdatedInThisTab = false // judgeFood() // 食物小于${minFood}时不建造房屋 for (const [i, node] of list.entries()) { let hasClick = false if ( !node.classList.value.includes('btn-off') && !blackList.some((word) => node.textContent.includes(word)) ) { console.log(`${new Date().toLocaleString()}建造:`, node.textContent) node.click() hasClick = true return true } isAllUpdatedInThisTab = i === list.length - 1 && !hasClick } return false // console.log('当前页是否全部升级:', isAllUpdatedInThisTab) // if (isAllUpdatedInThisTab && subTabNodes) { // // 如果当前页全部升级了,切换到另一个建筑页,按顺序往后切换,如果当前是最后一个tab,则切换回第一个tab // const currentSubTab = subTabNodes.querySelector( // `button[aria-selected=true]` // ) // 当前选中的子tab页 // const nextTab = currentSubTab.nextElementSibling // if (nextTab) { // console.log(`切换到${nextTab.textContent}`) // nextTab.click() // } else { // const target = subTabNodes.childNodes[0] // console.log(`切换到${target.textContent}`) // target.click() // } // } } } // 自动研究 function autoResearch() { const tabListNode = document .querySelector('#main-tabs') .querySelector(`div[role=tablist]`) const tabNode = tabListNode.childNodes[1] const flag = tabNode && tabNode.getAttribute('aria-selected') === 'true' if (!flag) { console.log('没找到容器,即将切换到“研究”页') tabNode && tabNode.click() } else { const id = tabNode.getAttribute('aria-controls') const containerNode = document.getElementById(id) const list = containerNode.querySelectorAll(`button.btn`) const subTabNodes = containerNode.querySelector(`div[role=tablist]`) let isAllUpdatedInThisTab = false for (const [i, node] of list.entries()) { let hasClick = false if ( !node.classList.value.includes('btn-off') && !blackList.some((word) => node.textContent.includes(word)) ) { console.log(`${new Date().toLocaleString()}研究:`, node.textContent) node.click() hasClick = true return true } isAllUpdatedInThisTab = i === list.length - 1 && !hasClick } } return false } // 自动调整工人 function autoTuneWorker() { const tabListNode = document .querySelector('#main-tabs') .querySelector(`div[role=tablist]`) const tabNode = tabListNode.childNodes[2] var list = document.querySelector('table').querySelectorAll('tr') var rscRatioMap = new Map(); for (var node of list) { var name = node.childNodes[0].innerText var dataStrs = node.childNodes[1].innerText.split('/') var cur = Number(dataStrs[0].replace(',', '')) var cap = Number(dataStrs[1].replace(',', '')) var ratio = cur / cap rscRatioMap.set(name, ratio) // console.log('资源情况:', name, ratio) } // avoid humen resource occupied by professor. rscRatioMap.set('研究点', 1) const id = tabNode.getAttribute('aria-controls') const containerNode = document.getElementById(id) list = containerNode.querySelectorAll(`div.sub-container div.p-4`) var maxIdx = 0 var maxVal = 0 var minIdx = 0 var minVal = 1 for (const [i, node] of list.entries()) { var div1 = node.querySelector('div.flex-1') name = div1.querySelector('h5').innerText var rscNameTds = div1.querySelectorAll('td.text-left') var rscSpeedTds = div1.querySelectorAll('td.text-right') var minRatio = 1 for (let index = 0; index < rscNameTds.length; index++) { var rscName = rscNameTds[index].innerText var rscSpeed = rscSpeedTds[index].innerText if (rscSpeed.includes('-')) { continue } var ratio = rscRatioMap.get(rscName) || 0 if (ratio < minRatio) { minRatio = ratio } } dataStrs = node.querySelector('div.relative input').getAttribute('value').split('/') cur = Number(dataStrs[0].trim()) cap = Number(dataStrs[1].trim()) var maxPermit = name == '农民' ? judgeFood() : true // var minPermit = name == '农民' ? !judgeFood() : true if (minRatio > maxVal && cur > 0 && maxPermit) { maxIdx = i maxVal = minRatio } if (minRatio < minVal && cur < cap) { minIdx = i minVal = minRatio } } // ensure food wont run out. if (rscRatioMap.get('食物') < 0.2) { minIdx = 0 } node = list[maxIdx] name = node.querySelector('div.flex-1').querySelector('h5').innerText var lessBtn = node.querySelector('div.relative').querySelectorAll('button.rounded-none')[0] lessBtn.click() console.log('减少人力:', name) node = list[minIdx] name = node.querySelector('div.flex-1').querySelector('h5').innerText var moreBtn = node.querySelector('div.relative').querySelectorAll('button.rounded-none')[1] setTimeout(() => { console.log('增加人力1:', name) moreBtn.click() }, 500) setTimeout(() => { console.log('增加人力2:', name) moreBtn.click() }, 1000) return true } // 自动祈祷 function autoMagic() { const tabListNode = document .querySelector('#main-tabs') .querySelector(`div[role=tablist]`) const tabNode = tabListNode.childNodes[3] var flag = tabNode && tabNode.getAttribute('aria-selected') === 'true' if (!flag) { console.log('没找到容器,即将切换到“魔法”页') tabNode && tabNode.click() } else { const id = tabNode.getAttribute('aria-controls') const containerNode = document.getElementById(id) const subTabNodes = containerNode.querySelector(`div[role=tablist]`) const prayNode = subTabNodes.childNodes[1] flag = prayNode && prayNode.getAttribute('aria-selected') === 'true' if (!flag) { prayNode && prayNode.click() return } const list = containerNode.querySelectorAll(`button.btn`) let isAllUpdatedInThisTab = false for (const [i, node] of list.entries()) { let hasClick = false if ( !node.classList.value.includes('btn-off') && !blackList.some((word) => node.textContent.includes(word)) ) { console.log(`${new Date().toLocaleString()}祈祷:`, node.textContent) node.click() hasClick = true return true } isAllUpdatedInThisTab = i === list.length - 1 && !hasClick } } return false } let buildingInterval = null let mode = 0 let maxMode = 3 let checkTime = 0 function checkTab() { const tabListNode = document .querySelector('#main-tabs') .querySelector(`div[role=tablist]`) if (tabListNode.childNodes.length <= mode) { mode = 0 return false } if (maxMode == 3 && tabListNode.childNodes.length >= 6) { // open autoMagic maxMode = 4 } const tabNode = tabListNode.childNodes[mode] const flag = tabNode && tabNode.getAttribute('aria-selected') === 'true' if (!flag && checkTime < 12) { console.log('需要切换到tab:' + mode) checkTime += 1 return true } checkTime = 0 return false } function switchTab() { const tabListNode = document .querySelector('#main-tabs') .querySelector(`div[role=tablist]`) if (tabListNode.childNodes.length <= mode) { mode = 0 return false } const tabNode = tabListNode.childNodes[mode] const flag = tabNode && tabNode.getAttribute('aria-selected') === 'true' if (!flag) { console.log('切换到tab:' + mode) tabNode && tabNode.click() } } let modeMaxSkipTimes = new Map() let modeSkipTimes = new Map() function autoHelpler() { closeDialog() if (checkTab()) return let rst = false switch (mode) { case 0: rst = autoBuild() break; case 1: rst = autoResearch() break; case 2: rst = autoTuneWorker() break; case 3: rst = autoMagic() break; default: break; } var maxSkipTime = modeMaxSkipTimes.get(mode) || 0 if (rst) { modeMaxSkipTimes.set(mode, Math.max(0, maxSkipTime - 1)) } else { modeMaxSkipTimes.set(mode, Math.min(10, maxSkipTime + 1)) console.log('设置模式跳过', mode, modeMaxSkipTimes.get(mode)) } setTimeout(() => { if (checkTab()) return while (true) { mode += 1 mode %= maxMode var maxSkipTime = modeMaxSkipTimes.get(mode) || 0 var skipTime = modeSkipTimes.get(mode) || 0 if (skipTime < maxSkipTime) { modeSkipTimes.set(mode, skipTime + 1) } else { modeSkipTimes.set(mode, 0) break } } switchTab() }, timeout / 2); } // 开启自动升级建筑定时器 function handleAutoUpdateStart() { buildingInterval = setInterval(autoHelpler, timeout) } // 清除自动升级建筑定时器 function handleAutoUpdateClear() { buildingInterval = clearInterval(buildingInterval) } // 切换自动升级建筑定时器状态 function toggleBtnStatus() { if (buildingInterval) { console.log('~~~~关闭定时器~~~~') handleAutoUpdateClear() } else { console.log('~~~~开启定时器~~~~') handleAutoUpdateStart() } } // 判断食物数量 // function judgeFood() { // var list = document.querySelector('table').querySelectorAll('tr') // for (var node of list) { // if (!node.innerText.includes('食物')) continue // // 获取食物速度 // var val = Number(node.childNodes[2].innerText.split('/')[0]) // if (val < minFood) { // blackList.push(...houseList) // } else { // blackList = initBlackList() // } // } // } function judgeFood() { var list = document.querySelector('table').querySelectorAll('tr') for (var node of list) { if (!node.innerText.includes('食物')) continue // 获取食物速度 var val = Number(node.childNodes[2].innerText.split('/')[0]) return val > minFood } } // 关闭dialog function closeDialog() { const dialogNode = document.querySelector('#headlessui-portal-root') dialogNode && dialogNode.querySelector('.sr-only').parentNode.click() } createBtn() addStyle(css) })()