Greasy Fork 支持简体中文。

TheresMore Modifier(修改器)

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

// ==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();
      }
    }
  }
})();