TheresMore Modifier(修改器)

Theresmore修改资源、自动恢复资源、时间加速、军队强化和自动升级建筑等功能,反馈交流摸鱼加群279398607

当前为 2024-07-12 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         TheresMore Modifier(修改器)
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Theresmore修改资源、自动恢复资源、时间加速、军队强化和自动升级建筑等功能,反馈交流摸鱼加群279398607
// @author       Keith
// @match        https://theresmoregame.g8hh.com.cn/*
// @grant        none
// @license MIT
// ==/UserScript==

/*
 * 详细功能说明:
 * 1. 修改资源:允许玩家设置、增加或减少各种游戏资源,包括普通资源、声望点和特殊资源。
 * 2. 自动恢复资源:提供自动恢复资源的选项,可以在特定的时间间隔内自动增加资源。
 * 3. 时间加速:允许玩家加速游戏时间,使游戏运行速度提高。
 * 4. 军队强化:提供军队加速和在进攻失败时不损失部队的功能。
 * 5. 自动升级建筑:自动点击建筑进行升级,并判断是否需要切换到下一个建筑标签页。
 */

(function () {
  'use strict';

  const ids = {
    resources: [
      'research', 'food', 'wood', 'stone', 'gold', 'tools', 'copper', 'iron',
      'cow', 'horse', 'luck', 'mana', 'building_material', 'faith', 'supplies',
      'crystal', 'steel', 'saltpetre', 'natronite'
    ],
    prestige: ['legacy'],
    special: ['relic', 'coin', 'tome_wisdom', 'gem', 'titan_gift']
  };

  // 引入 Google Fonts
  const link = document.createElement('link');
  link.href = 'https://fonts.googleapis.com/css2?family=Cinzel:wght@700&display=swap';
  link.rel = 'stylesheet';
  document.head.appendChild(link);

  // UI 样式
  const style = `
        #mod-ui {
            position: fixed;
            top: 10px;
            right: 10px;
            background: #000;
            color: #ddd;
            border: 1px solid #333;
            padding: 10px;
            z-index: 10000;
            width: 320px;
            box-shadow: 0 0 10px rgba(0,0,0,0.4);
            font-family: Arial, sans-serif;
        }
         #mod-ui h3 {
            margin: 10 0 10px 0;
            font-size: 18px;
            color: #d4af37;
            cursor: move;
            font-family: 'Cinzel', serif;
            text-shadow: 1px 1px 2px #000;
        }
        #mod-ui h4 {
            margin: 10px 0 5px 0;
            font-size: 14px;
            color: #ccc;
        }
        #mod-ui input, #mod-ui select {
            width: 100%;
            margin-bottom: 10px;
            padding: 5px;
            box-sizing: border-box;
            background-color: #222;
            color: #ddd;
            border: 1px solid #333;
        }
        #mod-ui button {
            padding: 5px 10px;
            width: 100%;
            background-color: #004499;
            color: #ddd;
            border: none;
            cursor: pointer;
            box-sizing: border-box;
            margin-bottom: 10px;
        }
        #mod-ui button.toggle-btn {
            position: absolute;
            top: 10px;
            right: 10px;
            width: 30px;
            height: 30px;
            background-color: #1d1e20;
            border: none;
            border-radius: 30%;
            cursor: pointer;
            z-index: 10001;
        }
        #mod-ui button.toggle-btn:hover {
            background-color: #333;
        }
        #mod-ui button:hover {
            background-color: #002266;
        }
        #mod-ui .auto-recover-container {
            display: flex;
            align-items: center;
            margin-top: 5px;
            margin-bottom: 10px;
        }
        #mod-ui .auto-recover-container label {
            color: #ddd;
            white-space: nowrap;
            padding: 5px 0px;
            margin-right: 5px;
            display: inline-flex;
            align-items: center;
        }
        #mod-ui .auto-recover-container input[type="checkbox"] {
            margin: 0;
            margin-left: 15px;
        }
        #auto_update_btn, #speed_on_btn, #army_on_btn {
            background: #1d1e20;
            border-radius: 10%;
            height: 32px;
            width: 120px;
            text-align: center;
            border: 2px solid white;
            color: white;
            cursor: pointer;
            margin-top: 10px;
        }
    `;

    // 在文档中插入样式
    const styleElement = document.createElement('style');
    styleElement.innerText = style;
    document.head.appendChild(styleElement);

    // 创建 UI 元素
    const uiElement = document.createElement('div');
    uiElement.id = 'mod-ui';
    uiElement.innerHTML = `
        <h3>TheresMore Modifier</h3>
        <button id="togglebtn" class="toggle-btn">▲</button>
        <div id="mod-ui-content">
            <h4>修改资源</h4>
            <select id="resource-type">
                <option value="resources">普通资源</option>
                <option value="prestige">声望点</option>
                <option value="special">特殊资源</option>
            </select>
            <input type="number" id="amount-input" placeholder="输入数量" />
            <select id="operation-type">
                <option value="set">设置</option>
                <option value="add">增加</option>
                <option value="subtract">减少</option>
            </select>
            <button id="apply-btn">应用</button>
            <div class="auto-recover-container">
                <label for="auto-recover-checkbox">自动恢复资源
                    <input type="checkbox" id="auto-recover-checkbox" />
                </label>
            </div>
            <input type="number" id="auto-recover-interval" placeholder="恢复间隔(毫秒)" disabled />

            <h4>调速功能</h4>
            <button id="toggleSpeed">开启时间加速</button>
            <button id="toggleArmyStrength">开启军队强化</button>
            <button id="toggleAutoUpdate">开启自动升级</button>
        </div>
    `;
    document.body.appendChild(uiElement);


  // 拖动功能
  let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  uiElement.querySelector('h3').onmousedown = dragMouseDown;

  function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    uiElement.style.top = (uiElement.offsetTop - pos2) + "px";
    uiElement.style.left = (uiElement.offsetLeft - pos1) + "px";
  }

  function closeDragElement() {
    document.onmouseup = null;
    document.onmousemove = null;
  }

  // 获取游戏数据
  function getGameData() {
    const rootElement = document.getElementById('root');
    if (!rootElement) {
      console.error('无法找到 React 根元素。');
      return null;
    }

    const reactKey = Object.keys(rootElement).find(key => key.startsWith('__reactContainer$'));
    if (reactKey) {
      const container = rootElement[reactKey];
      return container?.stateNode?.current?.child?.memoizedProps?.MainStore;
    }
    return null;
  }

  // 修改资源数据
  function modifyResources(type, amount = 1000000000, operation = 'add') {
    const gameData = getGameData();
    if (!gameData || !gameData.run || !gameData.run.resources) {
      console.error('游戏数据不可用或结构不正确。');
      return;
    }

    const resources = gameData.run.resources;
    if (!ids[type]) {
      console.error(`无效的类型:${type}`);
      return;
    }

    console.log('Attempting to modify resources:', type, amount, operation);

    resources.forEach(resource => {
      console.log('Checking resource:', resource.id, resource.value);
      if (ids[type].includes(resource.id)) {
        switch (operation) {
          case 'set':
            resource.value = amount;
            break;
          case 'add':
            resource.value = (resource.value ?? 0) + amount;
            break;
          case 'subtract':
            resource.value = Math.max((resource.value ?? 0) - amount, 0);
            break;
          default:
            console.error(`Invalid operation: ${operation}`);
            break;
        }
        console.log('Modified resource:', resource.id, 'New value:', resource.value);
      }
    });

    console.log(`${type} modification complete.`);
  }
    // 更新 UI 显示
    function updateUI() {
        const gameData = getGameData();
        if (!gameData || !gameData.run || !gameData.run.resources) {
            console.error('游戏数据不可用或结构不正确。');
            return;
        }

        const resources = gameData.run.resources;

        // Update resource values in UI
        ids.resources.forEach(resourceId => {
            const resource = resources.find(res => res.id === resourceId);
            if (resource) {
                const resourceElement = document.getElementById(`resource-${resourceId}`);
                if (resourceElement) {
                    resourceElement.textContent = `${resource.name}: ${resource.value}`;
                }
            }
        });

        // Update prestige points in UI
        ids.prestige.forEach(prestigeId => {
            const prestige = resources.find(res => res.id === prestigeId);
            if (prestige) {
                const prestigeElement = document.getElementById(`resource-${prestigeId}`);
                if (prestigeElement) {
                    prestigeElement.textContent = `${prestige.name}: ${prestige.value}`;
                }
            }
        });

        // Update special resources in UI
        ids.special.forEach(specialId => {
            const special = resources.find(res => res.id === specialId);
            if (special) {
                const specialElement = document.getElementById(`resource-${specialId}`);
                if (specialElement) {
                    specialElement.textContent = `${special.name}: ${special.value}`;
                }
            }
        });
    }
  // 自动恢复资源
  let autoRecoverInterval;
  let lastRecoverInterval = 2000; // 默认恢复间隔为 2000 毫秒

  function startAutoRecover(type, interval) {
    if (autoRecoverInterval) {
        clearInterval(autoRecoverInterval);
    }
    autoRecoverInterval = setInterval(() => {
      modifyResources(type, 1000000000, 'add');
      console.log(`自动恢复 ${type} 资源`);
    }, interval);
  }

  function stopAutoRecover() {
    if (autoRecoverInterval) {
      clearInterval(autoRecoverInterval);
      autoRecoverInterval = null;
    }
  }

  // 界面元素与事件绑定
  document.getElementById('apply-btn').addEventListener('click', () => {
    const type = document.getElementById('resource-type').value;
    const amount = Number(document.getElementById('amount-input').value);
    const operation = document.getElementById('operation-type').value;
    modifyResources(type, amount, operation);
  });

  document.getElementById('auto-recover-checkbox').addEventListener('change', (e) => {
    const isChecked = e.target.checked;
    const intervalInput = document.getElementById('auto-recover-interval');
    intervalInput.disabled = !isChecked;

    if (isChecked) {
      const interval = Number(intervalInput.value) || lastRecoverInterval;
      lastRecoverInterval = interval;
      startAutoRecover(document.getElementById('resource-type').value, interval);
    } else {
      stopAutoRecover();
    }
  });

  // 创建按钮图标
const upIcon = `<svg width="12" height="12" viewBox="0 0 24 24"><path fill="none" stroke="#ddd" stroke-width="4" d="M4 16l8-8 8 8"/></svg>`;
const downIcon = `<svg width="12" height="12" viewBox="0 0 24 24"><path fill="none" stroke="#ddd" stroke-width="4" d="M4 8l8 8 8-8"/></svg>`;


  // 修改按钮事件处理
  const togglebtn = document.getElementById('togglebtn');
  togglebtn.innerHTML = upIcon;
  togglebtn.addEventListener('click', () => {
    const modContent = document.querySelector('#mod-ui-content');

    if (modContent.style.display === 'none') {
      modContent.style.display = 'block';
      togglebtn.innerHTML = upIcon;
    } else {
      modContent.style.display = 'none';
      togglebtn.innerHTML = downIcon;
    }
    updateUI();
  });


  document.getElementById('auto-recover-interval').addEventListener('change', (e) => {
    const interval = Number(e.target.value) || 2000;
    if (document.getElementById('auto-recover-checkbox').checked) {
      lastRecoverInterval = interval;
      startAutoRecover(document.getElementById('resource-type').value, interval);
    }
  });

  // 时间加速功能
  const 超级加速等级 = 10;
  let speedIsOn = false;
  let firstSpeedChanger = true;
  let game;
  let older_game = game
  let older_window_game = window.game
  function SpeedChanger(btnId, openString, closeString) {
    if (firstSpeedChanger) {
      firstSpeedChanger = false;
      performance.older_performance_now = performance.now;
    }

    if (!speedIsOn) {
      performance.now = () => {
        return performance.older_performance_now() * 超级加速等级;
      };
      let timer = setInterval(() => {
        if (document.querySelector("#main-tabs")) {
          clearInterval(timer);
          game = Object.values(document.querySelector("#main-tabs"))[1].children._owner.stateNode.props.MainStore;
          window.game = game;
        }
      }, 100);
      speedIsOn = true;
      toggleBtnText(btnId, closeString);
    } else {
      // 平滑
      let disTime = performance.now() - performance.older_performance_now();
      performance.now = () => {
        return performance.older_performance_now() + disTime;
      };
      window.game = older_window_game;
      let timer = setInterval(() => {
        if (document.querySelector("#main-tabs")) {
          clearInterval(timer);
          game = Object.values(document.querySelector("#main-tabs"))[1].children._owner.stateNode.props.MainStore;
          window.game = game;
        }
      }, 100);
      speedIsOn = false;
      toggleBtnText(btnId, openString);
    }
  }

  function toggleBtnText(btnId, text) {
    const button = document.getElementById(btnId);
    if (button) {
      button.textContent = text;
    }
  }

  document.getElementById('toggleSpeed').addEventListener('click', () => {
    SpeedChanger('toggleSpeed', '开启时间加速', '关闭时间加速');
  });


  // 军队强化功能
  let armyStrengthOn = false;
  let enableArmySpeed = true;
  let enableNoLossOnFail = true;

  function toggleArmyStrength() {
    armyStrengthOn = !armyStrengthOn;
    const button = document.getElementById('toggleArmyStrength');
    button.textContent = armyStrengthOn ? '关闭军队强化' : '开启军队强化';

    if (armyStrengthOn) {
      if (enableArmySpeed) {
        game.ArmyStore.waitTime /= 超级加速等级;
        console.log('军队加速已开启');
      }
      if (enableNoLossOnFail) {
        game.ArmyStore.realDestroyArmy = game.ArmyStore.destroyArmy;
        game.ArmyStore.destroyArmy = function (...args) {
          if (!(args[2] == 'army' && args[3] != !0)) {
            return this.realDestroyArmy(...args);
          }
        };
        console.log('进攻失败不损失部队已开启');
      }
    } else {
      game.ArmyStore.waitTime *= 1;
      game.ArmyStore.destroyArmy = game.ArmyStore.realDestroyArmy;
      console.log('军队强化已关闭');
    }
  }

  document.getElementById('toggleArmyStrength').addEventListener('click', toggleArmyStrength);

      document.getElementById('toggleAutoUpdate').addEventListener('click', () => {
    autoUpdateChanger('toggleAutoUpdate', '开启自动升级', '关闭自动升级');
  });

  // 自动升级功能的实现代码
  let autoUpdate = false;
  let autoUpdateTimer;
  var blackList = getListOfOnce();
  const 自动升级间隔 = 1000 * 2;
  const 最小食物增长 = 5;

  const houseList = ['房屋', '市政厅', '宅邸', '住宅区', '发展部', '定居点大厅']; // 会减少食物的建筑
  function getListOfOnce() {
    return ['雕像', '神殿'];
  }

  function autoUpdateChanger(btnId, openString, closeString) {
    const button = document.getElementById(btnId);
    if (autoUpdate) {
      console.log('关闭自动升级');
      clearInterval(autoUpdateTimer);
      autoUpdate = false;
      button.textContent = openString;
    } else {
      console.log('开启自动升级');
      autoUpdateTimer = setInterval(autoClickBuilding, 自动升级间隔);
      autoUpdate = true;
      button.textContent = closeString;
    }
  }

  function autoClickBuilding() {
    closeDialog();
    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();
      console.log('正在寻找可升级建筑');
      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, ' , MaggotScheduler running.');
          node.click();
          hasClick = true;
          break;
        }
        isAllUpdatedInThisTab = i === list.length - 1 && !hasClick;
      }

      console.log(isAllUpdatedInThisTab ? '当前页已经全部升级' : '当前页还有可升级', ' , MaggotScheduler running.');
      if (isAllUpdatedInThisTab && subTabNodes) {
        // 如果当前页全部升级了,尝试切换到下一个 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 closeDialog() {
    const dialogNode = document.querySelector('#headlessui-portal-root');
    dialogNode && dialogNode.querySelector('.sr-only').parentNode.click();
  }

  // 食物判断
  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 < 最小食物增长) {
        blackList.push(...houseList);
      } else {
        blackList = getListOfOnce();
      }
    }
  }
})();