Theresmore自动点击工具

解放你的双手自动自动点击工具

  1. // ==UserScript==
  2. // @name Theresmore自动点击工具
  3. // @namespace Theresmore自动点击工具
  4. // @match https://theresmoregame.g8hh.com/
  5. // @grant none
  6. // @version 1.1
  7. // @author zty
  8. // @description 解放你的双手自动自动点击工具
  9. // @license MIT
  10. // ==/UserScript==
  11. ; (function () {
  12. const timeout = 1000 * 10 // 10秒点一次
  13. const minFood = 2 // 食物最小值
  14.  
  15. let blackList = initBlackList() // 部分只能建造一个的建筑需要跳过
  16. const houseList = ['房屋', '市政厅', '宅邸', '住宅区', '发展部', '定居点大厅'] // 会减少食物的建筑
  17. function initBlackList() {
  18. return ['雕像', '心灵神殿', '战争神殿', '月明之夜', '光荣退休']
  19. }
  20. var css = `
  21. #auto_update_btn {
  22. position: fixed;
  23. right: 0;
  24. bottom: 64px;
  25. background: #1d1e20;
  26. border-radius: 50%;
  27. height: 32px;
  28. width: 32px;
  29. display: flex;
  30. align-items: center;
  31. justify-content: center;
  32. text-align: center;
  33. font-size: 14px;
  34. border: 2px solid white;
  35. z-index: 100;
  36. color: white;
  37. cursor: pointer;
  38. }
  39. `
  40. /*添加样式*/
  41. function addStyle(css) {
  42. if (!css) return
  43. var head = document.querySelector('head')
  44. var style = document.createElement('style')
  45. style.type = 'text/css'
  46. style.innerHTML = css
  47. head.appendChild(style)
  48. }
  49.  
  50. /*生成自动升级建筑的按钮*/
  51. function createBtn() {
  52. var btn = document.createElement('div')
  53. btn.title = '开'
  54. var span = document.createElement('span')
  55. span.innerText = '开'
  56. btn.appendChild(span)
  57. btn.id = 'auto_update_btn'
  58. document.body.appendChild(btn)
  59.  
  60. /*初始化事件*/
  61. // 点击按钮启动定时器
  62. btn.addEventListener('click', function () {
  63. toggleBtnStatus()
  64. toggleBtnText()
  65. })
  66. }
  67.  
  68. // 切换文字
  69. function toggleBtnText() {
  70. const node = document.querySelector('#auto_update_btn')
  71. const text = node.innerText
  72. node.innerText = text === '开' ? '关' : '开'
  73. }
  74.  
  75.  
  76. // 自动升级建筑
  77. function autoBuild() {
  78. const tabListNode = document
  79. .querySelector('#main-tabs')
  80. .querySelector(`div[role=tablist]`)
  81. const tabNode = tabListNode.childNodes[0]
  82. const flag = tabNode && tabNode.getAttribute('aria-selected') === 'true'
  83. if (!flag) {
  84. console.log('没找到容器,即将切换到“建造”页')
  85. // 自动切换到建造tab页
  86. tabNode && tabNode.click()
  87. } else {
  88. const id = tabNode.getAttribute('aria-controls')
  89. const containerNode = document.getElementById(id)
  90. const list = containerNode.querySelectorAll(`button.btn`)
  91. const subTabNodes = containerNode.querySelector(`div[role=tablist]`)
  92. let isAllUpdatedInThisTab = false
  93. // judgeFood() // 食物小于${minFood}时不建造房屋
  94. for (const [i, node] of list.entries()) {
  95. let hasClick = false
  96. if (
  97. !node.classList.value.includes('btn-off') &&
  98. !blackList.some((word) => node.textContent.includes(word))
  99. ) {
  100. console.log(`${new Date().toLocaleString()}建造:`, node.textContent)
  101. node.click()
  102. hasClick = true
  103. return true
  104. }
  105. isAllUpdatedInThisTab = i === list.length - 1 && !hasClick
  106. }
  107. return false
  108. // console.log('当前页是否全部升级:', isAllUpdatedInThisTab)
  109. // if (isAllUpdatedInThisTab && subTabNodes) {
  110. // // 如果当前页全部升级了,切换到另一个建筑页,按顺序往后切换,如果当前是最后一个tab,则切换回第一个tab
  111. // const currentSubTab = subTabNodes.querySelector(
  112. // `button[aria-selected=true]`
  113. // ) // 当前选中的子tab页
  114. // const nextTab = currentSubTab.nextElementSibling
  115. // if (nextTab) {
  116. // console.log(`切换到${nextTab.textContent}`)
  117. // nextTab.click()
  118. // } else {
  119. // const target = subTabNodes.childNodes[0]
  120. // console.log(`切换到${target.textContent}`)
  121. // target.click()
  122. // }
  123. // }
  124. }
  125. }
  126.  
  127. // 自动研究
  128. function autoResearch() {
  129. const tabListNode = document
  130. .querySelector('#main-tabs')
  131. .querySelector(`div[role=tablist]`)
  132. const tabNode = tabListNode.childNodes[1]
  133.  
  134.  
  135. const flag = tabNode && tabNode.getAttribute('aria-selected') === 'true'
  136. if (!flag) {
  137. console.log('没找到容器,即将切换到“研究”页')
  138. tabNode && tabNode.click()
  139. } else {
  140. const id = tabNode.getAttribute('aria-controls')
  141. const containerNode = document.getElementById(id)
  142. const list = containerNode.querySelectorAll(`button.btn`)
  143. const subTabNodes = containerNode.querySelector(`div[role=tablist]`)
  144. let isAllUpdatedInThisTab = false
  145. for (const [i, node] of list.entries()) {
  146. let hasClick = false
  147. if (
  148. !node.classList.value.includes('btn-off') &&
  149. !blackList.some((word) => node.textContent.includes(word))
  150. ) {
  151. console.log(`${new Date().toLocaleString()}研究:`, node.textContent)
  152. node.click()
  153. hasClick = true
  154. return true
  155. }
  156. isAllUpdatedInThisTab = i === list.length - 1 && !hasClick
  157. }
  158.  
  159. }
  160. return false
  161. }
  162.  
  163. // 自动调整工人
  164. function autoTuneWorker() {
  165. const tabListNode = document
  166. .querySelector('#main-tabs')
  167. .querySelector(`div[role=tablist]`)
  168. const tabNode = tabListNode.childNodes[2]
  169.  
  170. var list = document.querySelector('table').querySelectorAll('tr')
  171. var rscRatioMap = new Map();
  172.  
  173. for (var node of list) {
  174. var name = node.childNodes[0].innerText
  175. var dataStrs = node.childNodes[1].innerText.split('/')
  176. var cur = Number(dataStrs[0].replace(',', ''))
  177. var cap = Number(dataStrs[1].replace(',', ''))
  178. var ratio = cur / cap
  179. rscRatioMap.set(name, ratio)
  180. // console.log('资源情况:', name, ratio)
  181. }
  182. // avoid humen resource occupied by professor.
  183. rscRatioMap.set('研究点', 1)
  184.  
  185. const id = tabNode.getAttribute('aria-controls')
  186. const containerNode = document.getElementById(id)
  187. list = containerNode.querySelectorAll(`div.sub-container div.p-4`)
  188. var maxIdx = 0
  189. var maxVal = 0
  190. var minIdx = 0
  191. var minVal = 1
  192. for (const [i, node] of list.entries()) {
  193. var div1 = node.querySelector('div.flex-1')
  194. name = div1.querySelector('h5').innerText
  195.  
  196. var rscNameTds = div1.querySelectorAll('td.text-left')
  197. var rscSpeedTds = div1.querySelectorAll('td.text-right')
  198. var minRatio = 1
  199. for (let index = 0; index < rscNameTds.length; index++) {
  200. var rscName = rscNameTds[index].innerText
  201. var rscSpeed = rscSpeedTds[index].innerText
  202. if (rscSpeed.includes('-')) {
  203. continue
  204. }
  205. var ratio = rscRatioMap.get(rscName) || 0
  206. if (ratio < minRatio) {
  207. minRatio = ratio
  208. }
  209.  
  210. }
  211.  
  212. dataStrs = node.querySelector('div.relative input').getAttribute('value').split('/')
  213. cur = Number(dataStrs[0].trim())
  214. cap = Number(dataStrs[1].trim())
  215.  
  216. var maxPermit = name == '农民' ? judgeFood() : true
  217. // var minPermit = name == '农民' ? !judgeFood() : true
  218.  
  219. if (minRatio > maxVal && cur > 0 && maxPermit) {
  220. maxIdx = i
  221. maxVal = minRatio
  222. }
  223. if (minRatio < minVal && cur < cap) {
  224. minIdx = i
  225. minVal = minRatio
  226. }
  227. }
  228. // ensure food wont run out.
  229. if (rscRatioMap.get('食物') < 0.2) {
  230. minIdx = 0
  231. }
  232.  
  233. node = list[maxIdx]
  234. name = node.querySelector('div.flex-1').querySelector('h5').innerText
  235. var lessBtn = node.querySelector('div.relative').querySelectorAll('button.rounded-none')[0]
  236.  
  237. lessBtn.click()
  238. console.log('减少人力:', name)
  239.  
  240. node = list[minIdx]
  241. name = node.querySelector('div.flex-1').querySelector('h5').innerText
  242. var moreBtn = node.querySelector('div.relative').querySelectorAll('button.rounded-none')[1]
  243. setTimeout(() => {
  244. console.log('增加人力1:', name)
  245. moreBtn.click()
  246. }, 500)
  247. setTimeout(() => {
  248. console.log('增加人力2:', name)
  249. moreBtn.click()
  250. }, 1000)
  251. return true
  252. }
  253.  
  254.  
  255. // 自动祈祷
  256. function autoMagic() {
  257. const tabListNode = document
  258. .querySelector('#main-tabs')
  259. .querySelector(`div[role=tablist]`)
  260. const tabNode = tabListNode.childNodes[3]
  261.  
  262.  
  263. var flag = tabNode && tabNode.getAttribute('aria-selected') === 'true'
  264. if (!flag) {
  265. console.log('没找到容器,即将切换到“魔法”页')
  266. tabNode && tabNode.click()
  267. } else {
  268. const id = tabNode.getAttribute('aria-controls')
  269. const containerNode = document.getElementById(id)
  270. const subTabNodes = containerNode.querySelector(`div[role=tablist]`)
  271. const prayNode = subTabNodes.childNodes[1]
  272. flag = prayNode && prayNode.getAttribute('aria-selected') === 'true'
  273. if (!flag) {
  274. prayNode && prayNode.click()
  275. return
  276. }
  277.  
  278. const list = containerNode.querySelectorAll(`button.btn`)
  279. let isAllUpdatedInThisTab = false
  280. for (const [i, node] of list.entries()) {
  281. let hasClick = false
  282. if (
  283. !node.classList.value.includes('btn-off') &&
  284. !blackList.some((word) => node.textContent.includes(word))
  285. ) {
  286. console.log(`${new Date().toLocaleString()}祈祷:`, node.textContent)
  287. node.click()
  288. hasClick = true
  289. return true
  290. }
  291. isAllUpdatedInThisTab = i === list.length - 1 && !hasClick
  292. }
  293.  
  294. }
  295. return false
  296. }
  297.  
  298.  
  299. let buildingInterval = null
  300. let mode = 0
  301. let maxMode = 3
  302. let checkTime = 0
  303.  
  304.  
  305. function checkTab() {
  306. const tabListNode = document
  307. .querySelector('#main-tabs')
  308. .querySelector(`div[role=tablist]`)
  309. if (tabListNode.childNodes.length <= mode) {
  310. mode = 0
  311. return false
  312. }
  313. if (maxMode == 3 && tabListNode.childNodes.length >= 6) {
  314. // open autoMagic
  315. maxMode = 4
  316. }
  317. const tabNode = tabListNode.childNodes[mode]
  318.  
  319. const flag = tabNode && tabNode.getAttribute('aria-selected') === 'true'
  320. if (!flag && checkTime < 12) {
  321. console.log('需要切换到tab:' + mode)
  322. checkTime += 1
  323. return true
  324. }
  325. checkTime = 0
  326. return false
  327. }
  328.  
  329. function switchTab() {
  330. const tabListNode = document
  331. .querySelector('#main-tabs')
  332. .querySelector(`div[role=tablist]`)
  333. if (tabListNode.childNodes.length <= mode) {
  334. mode = 0
  335. return false
  336. }
  337. const tabNode = tabListNode.childNodes[mode]
  338.  
  339. const flag = tabNode && tabNode.getAttribute('aria-selected') === 'true'
  340. if (!flag) {
  341. console.log('切换到tab:' + mode)
  342. tabNode && tabNode.click()
  343. }
  344. }
  345.  
  346. let modeMaxSkipTimes = new Map()
  347. let modeSkipTimes = new Map()
  348.  
  349. function autoHelpler() {
  350. closeDialog()
  351. if (checkTab()) return
  352. let rst = false
  353. switch (mode) {
  354. case 0:
  355. rst = autoBuild()
  356. break;
  357. case 1:
  358. rst = autoResearch()
  359. break;
  360. case 2:
  361. rst = autoTuneWorker()
  362. break;
  363. case 3:
  364. rst = autoMagic()
  365. break;
  366. default:
  367. break;
  368. }
  369.  
  370. var maxSkipTime = modeMaxSkipTimes.get(mode) || 0
  371. if (rst) {
  372. modeMaxSkipTimes.set(mode, Math.max(0, maxSkipTime - 1))
  373. } else {
  374. modeMaxSkipTimes.set(mode, Math.min(10, maxSkipTime + 1))
  375. console.log('设置模式跳过', mode, modeMaxSkipTimes.get(mode))
  376. }
  377.  
  378. setTimeout(() => {
  379. if (checkTab()) return
  380. while (true) {
  381. mode += 1
  382. mode %= maxMode
  383. var maxSkipTime = modeMaxSkipTimes.get(mode) || 0
  384. var skipTime = modeSkipTimes.get(mode) || 0
  385. if (skipTime < maxSkipTime) {
  386. modeSkipTimes.set(mode, skipTime + 1)
  387. } else {
  388. modeSkipTimes.set(mode, 0)
  389. break
  390. }
  391. }
  392. switchTab()
  393. }, timeout / 2);
  394. }
  395.  
  396. // 开启自动升级建筑定时器
  397. function handleAutoUpdateStart() {
  398. buildingInterval = setInterval(autoHelpler, timeout)
  399. }
  400. // 清除自动升级建筑定时器
  401. function handleAutoUpdateClear() {
  402. buildingInterval = clearInterval(buildingInterval)
  403. }
  404. // 切换自动升级建筑定时器状态
  405. function toggleBtnStatus() {
  406. if (buildingInterval) {
  407. console.log('~~~~关闭定时器~~~~')
  408. handleAutoUpdateClear()
  409. } else {
  410. console.log('~~~~开启定时器~~~~')
  411. handleAutoUpdateStart()
  412. }
  413. }
  414. // 判断食物数量
  415. // function judgeFood() {
  416. // var list = document.querySelector('table').querySelectorAll('tr')
  417. // for (var node of list) {
  418. // if (!node.innerText.includes('食物')) continue
  419. // // 获取食物速度
  420. // var val = Number(node.childNodes[2].innerText.split('/')[0])
  421. // if (val < minFood) {
  422. // blackList.push(...houseList)
  423. // } else {
  424. // blackList = initBlackList()
  425. // }
  426. // }
  427. // }
  428.  
  429. function judgeFood() {
  430. var list = document.querySelector('table').querySelectorAll('tr')
  431. for (var node of list) {
  432. if (!node.innerText.includes('食物')) continue
  433. // 获取食物速度
  434. var val = Number(node.childNodes[2].innerText.split('/')[0])
  435. return val > minFood
  436. }
  437. }
  438.  
  439. // 关闭dialog
  440. function closeDialog() {
  441. const dialogNode = document.querySelector('#headlessui-portal-root')
  442. dialogNode && dialogNode.querySelector('.sr-only').parentNode.click()
  443. }
  444.  
  445. createBtn()
  446. addStyle(css)
  447. })()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址