Greasy Fork

Greasy Fork is available in English.

我的文字修仙全靠刷之随身老爷爷

2024/7/31 10:36:02

当前为 2024-08-06 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        我的文字修仙全靠刷之随身老爷爷
// @namespace   Violentmonkey Scripts
// @match       https://xiuxian.jntm.cool/
// @grant       none
// @version     1.3
// @author      -
// @description 2024/7/31 10:36:02
// @license MIT
// ==/UserScript==
(function () {
  'use strict';

  class Interval {
    constructor(fun, speed) {
      this.fun = fun
      this.speed = speed
      this.id = null
      this.runing = false
    }

    start () {
      console.log('Interval.start()')
      if (this.id) {
        return
      }
      this.runing = true
      this.id = setInterval(this.fun, this.speed)
    }

    stop () {
      console.log('Interval.stop()')
      if (this.id) {
        this.runing = false
        clearInterval(this.id)
        console.log(`Interval.stop()-clearInterval(${this.id})`)
        this.id = null
      }
    }

    isRun () {
      return this.runing
    }

    isNotRun () {
      return !this.isRun()
    }
  }

  class LinkInterval extends Interval {
    #handleBefore
    #handleAfter
    constructor(linkList, speed, one = true, startClickButtonList = [], endClickButtonList = []) {
      super(null, speed)
      const _run = this.#run.bind(this)
      super.fun = _run

      this.startClickButtonList = startClickButtonList
      this.startClickButtonListLength = startClickButtonList.length
      this.startClickButtonListIndex = 0

      this.endClickButtonList = endClickButtonList
      this.endClickButtonListLength = endClickButtonList.length
      this.endClickButtonListIndex = 0

      this.linkList = linkList
      this.linkListLength = linkList.length

      this.one = one
      this.linkListIndex = 0
      this.next = null
      this.#handleBefore = () => { }
      this.#handleAfter = () => { }

      this.excNext = true

      this.cycleCount = 0
    }

    setHandleBefore (fun) {
      this.#handleBefore = fun
      this.#handleBefore = this.#handleBefore.bind(this)
    }

    setHandleAfter (fun) {
      this.#handleAfter = fun
      this.#handleAfter = this.#handleAfter.bind(this)
    }

    start (excNext = true) {
      this.excNext = excNext
      this.startClickButtonListIndex = 0
      this.endClickButtonListIndex = 0
      this.linkListIndex = 0
      this.cycleCount = 0
      super.start()
    }

    stop () {
      if (this.#isExecEndClickButtonList()) {
        this.runing = false
        return
      }
      super.stop()
      if (this.next && super.isRun()) {
        this.next.stop()
      }
    }

    linkNext (next) {
      this.next = next
      return this
    }

    nextInterval () {
      console.log(`执行下一定时器${this.next}`)
      this.stop()
      if (super.isNotRun() && this.next) {
        this.next.start()
      }
    }

    #run () {
      this.#handleBefore(this)
      if (super.isNotRun() && !this.#isExecEndClickButtonList()) {
        super.stop()
        return
      }
      let item = null, linkListlinkListEndIndex = false
      if (super.isRun() && this.#isExecStartClickButtonList()) {
        item = this.startClickButtonList[this.startClickButtonListIndex++]
      } else if (super.isNotRun() && this.#isExecEndClickButtonList()) {
        item = this.endClickButtonList[this.endClickButtonListIndex++]
      } else {
        let curIndex = (this.linkListIndex++) % this.linkListLength
        item = this.linkList[curIndex]
        linkListlinkListEndIndex = curIndex === (this.linkListLength - 1)
        if (linkListlinkListEndIndex) {
          this.cycleCount = this.linkListIndex / this.linkListLength
          console.log(`当前周期:${this.cycleCount}`)
        }
      }
      let cbs = findClickButton(item)
      if (cbs) {
        for (const cb of cbs) {
          console.log(`[${item}]元素点击。`)
          cb.click()
        }
      } else {
        console.warn(`未找到[${item}]元素。`)
      }
      this.#handleAfter(this)
      if (this.one == true && linkListlinkListEndIndex) {
        if (this.excNext) {
          this.nextInterval()
        } else {
          this.stop()
          this.excNext = true
        }
      }
    }

    #isExecStartClickButtonList () {
      return this.startClickButtonListIndex < this.startClickButtonListLength
    }

    #isExecEndClickButtonList () {
      return this.endClickButtonListIndex < this.endClickButtonListLength
    }
  }
  // 总速度
  let speed = 50
  // 出售频率
  let sellFrequency = 256
  // 放宠次数
  let releasePetFrequency = 16
  // 是否放生所有宠物
  let releasePetAll = false
  // 培养次数
  let raisePetFrequency = 16
  // 升级次数
  let upgradeFrequency = 16

  function handleAfter (_this) {
    if (sellFrequency <= 0) {
      return
    }
    if (_this.cycleCount == sellFrequency) {
      _this.nextInterval()
    }
  }
  const commonClickButtonList = ['it>立马撤退', 'it>发起战斗', 'it>回家疗伤', 'it>返回家里']
  // 出售任务
  const sellInterval = new LinkInterval(
    [
      'it>出售装备',
      'body > div.game-container-wrapper > div.game-container > div.index > div:nth-child(7) > div > div.el-dialog__body > div.dialog-footer > button',
      'body > div.game-container-wrapper > div.game-container > div.index > div:nth-child(7) > div > div.el-dialog__header > button'
    ],
    200, true, commonClickButtonList
  )
  // 修炼任务
  const cultivateInterval = new LinkInterval(['it>开始修炼', 'it>继续修炼', 'it>突破境界'], speed, false, [], commonClickButtonList)
  // 探索任务
  const autoInterval = new LinkInterval(['it>探索秘境', 'it>发起战斗', 'it>继续探索'], speed, false, [], commonClickButtonList)
  autoInterval.linkNext(sellInterval)
  autoInterval.setHandleAfter(handleAfter)
  // 抓宠任务
  const petInterval = new LinkInterval(['it>探索秘境', 'it>收服对方', 'it>发起战斗', 'it>继续探索'], speed, false, [], commonClickButtonList)
  petInterval.linkNext(sellInterval)
  petInterval.setHandleAfter(handleAfter)
  // 放宠任务
  const releasePetInterval = new LinkInterval(['#pane-pet > div > span:nth-child(1)', 'it>灵宠放生', 'it>确定放生'], speed, false, ['#tab-pet'])
  releasePetInterval.setHandleAfter((_this) => {
    if (!releasePetAll && _this.cycleCount == releasePetFrequency) {
      _this.stop()
      unDisabled()
    }
  })
  // 培养宠物任务
  const raisePetInterval = new LinkInterval(['it>点击培养', 'it>确定以及肯定'], speed, false,
    ['body > div > div.game-container > div.index > div.index-box > div.equip-box > div:nth-child(3) > span > span.pet'],
    ['#el-drawer__title > button'])
  raisePetInterval.setHandleAfter((_this) => {
    if (_this.cycleCount == raisePetFrequency) {
      _this.stop()
      unDisabled()
    }
  })
  //TODO BOSS任务

  class GroupLinkInterval {
    constructor(speed) {
      this.map = {}
      this.clickButtonList = ['it>点击炼器', 'it>确定以及肯定']
      this.endClickButtonList = ['#el-drawer__title > button']
      this.speed = speed
    }

    add (key, startClickButtonList = []) {
      let interval = new LinkInterval(this.clickButtonList, this.speed, false, startClickButtonList, this.endClickButtonList)
      interval.setHandleAfter((_this) => {
        if (_this.cycleCount == upgradeFrequency) {
          _this.stop()
          unDisabled()
        }
      })
      this.map[key] = interval
    }

    start (key) {
      this.map[key].start()
    }

    setSpeed (speed) {
      this.speed = speed
      for (const key in this.map) {
        this.map[key].speed = this.speed
      }
    }
  }

  setTimeout(() => {
    let groupLinkInterval = new GroupLinkInterval(speed)
    let divBox = document.createElement('div')
    divBox.style = 'margin-bottom: 8px; padding-top: 16px;'
    const note = document.createElement('span')
    note.innerHTML = `<p style='margin: 2px 0; color: #ba0e0e; font-size: 12px;'>请将出售/升级/培养的相关设置选好后在进行使用。</p>
                      <p style='margin: 2px 0; color: #ba0e0e; font-size: 12px;'>出售:不自动出售将出售频率设置为0。</p>
                      <p style='margin: 2px 0; color: #ba0e0e; font-size: 12px;'>升级:启动后无法停止只能刷新页面,请设置合适的升级次数。</p>
                      <p style='margin: 2px 0; color: #ba0e0e; font-size: 12px;'>放宠:放生所有将放宠次数设为-1</p>
                      <p style='margin: 2px 0; color: #ba0e0e; font-size: 12px;'>如果启动后无效果请回到家里在重新启动。</p>`
    divBox.appendChild(note)
    addInput(divBox, '总速度', speed, (event) => {
      raisePetInterval.speed =
        releasePetInterval.speed =
        cultivateInterval.speed =
        autoInterval.speed =
        sellInterval.speed =
        petInterval.speed = speed = Number(event.target.value)
      groupLinkInterval.setSpeed(speed)
    })
    addInput(divBox, '出售频率', sellFrequency, (event) => { sellFrequency = Number(event.target.value) })
    addInput(divBox, '放宠次数', releasePetFrequency, (event) => { releasePetFrequency = Number(event.target.value) })
    addInput(divBox, '升级次数', upgradeFrequency, (event) => { upgradeFrequency = Number(event.target.value) })
    addInput(divBox, '培养次数', raisePetFrequency, (event) => {
      raisePetFrequency = Number(event.target.value)
      releasePetAll = raisePetFrequency < 0
    })
    appendLine(divBox)
    // 出售按钮
    addButton(divBox, '快捷出售', ['el-button'], () => { sellInterval.start(false) })
    // 修炼按钮
    const cultivateButtonText = ['开始修炼', '停止修炼']
    const cultivateButton = addButton(divBox, cultivateButtonText[0], ['el-button'], () => {
      if (cultivateButton.innerText === cultivateButtonText[0]) {
        disabled(cultivateButton)
        cultivateInterval.start()
        cultivateButton.innerText = cultivateButtonText[1]
        return
      }
      cultivateInterval.stop()
      cultivateButton.innerText = cultivateButtonText[0]
      unDisabled()
    })
    // 探索按钮
    const buttonText = ['开始探索', '停止探索']
    const autoButton = addButton(divBox, buttonText[0], ['el-button'], () => {
      if (autoButton.innerText === buttonText[0]) {
        disabled(autoButton)
        autoInterval.start()
        sellInterval.linkNext(autoInterval)
        autoButton.innerText = buttonText[1]
        return
      }
      autoInterval.stop()
      autoButton.innerText = buttonText[0]
      unDisabled()
    })
    // 抓宠按钮
    const petButtonText = ['开始抓宠', '停止抓宠']
    const petButton = addButton(divBox, petButtonText[0], ['el-button'], () => {
      if (petButton.innerText === petButtonText[0]) {
        disabled(petButton)
        petInterval.start()
        sellInterval.linkNext(petInterval)
        petButton.innerText = petButtonText[1]
        return
      }
      petInterval.stop()
      petButton.innerText = petButtonText[0]
      unDisabled()
    })
    // 放宠按钮
    const releasePetButton = addButton(divBox, '放宠', ['el-button'], () => {
      disabled(releasePetButton)
      if (releasePetAll) {
        releasePetFrequency = document.querySelector('#pane-pet > div').children.length
      }
      releasePetInterval.start()
    })
    // 培养按钮
    const raisePetButton = addButton(divBox, '培养宠物', ['el-button'], () => {
      disabled(raisePetButton)
      releasePetFrequency = document.querySelector('#pane-pet > div').children.length
      raisePetInterval.start()
    })
    appendLine(divBox)
    let groupButtonList = [
      { key: '升级神兵', startClickButtonList: ['body > div > div.game-container > div.index > div.index-box > div.equip-box > div:nth-child(1) > span:nth-child(1) > span.el-tag'] },
      { key: '升级护甲', startClickButtonList: ['body > div > div.game-container > div.index > div.index-box > div.equip-box > div:nth-child(1) > span:nth-child(2) > span.el-tag'] },
      { key: '升级灵宝', startClickButtonList: ['body > div > div.game-container > div.index > div.index-box > div.equip-box > div:nth-child(2) > span:nth-child(1) > span.el-tag'] },
      { key: '升级法器', startClickButtonList: ['body > div > div.game-container > div.index > div.index-box > div.equip-box > div:nth-child(2) > span:nth-child(2) > span.el-tag'] }
    ]
    for (const groupButton of groupButtonList) {
      groupLinkInterval.add(groupButton.key, groupButton.startClickButtonList)
      addButton(divBox, groupButton.key, ['el-button'], (event) => {
        disabled(event.target)
        groupLinkInterval.start(groupButton.key)
      })
    }
    const gameBox = document.querySelector('.game-container')
    insertBefore(gameBox, divBox)
  }, 1000)

  function insertBefore (node, newElement) {
    node.insertBefore(newElement, node.firstChild)
  }

  function findClickButton (clickButton) {
    if (clickButton.startsWith('it>')) {
      clickButton = clickButton.replace('it>', '')
      let buttonList = document.querySelectorAll('.el-button')
      for (const node of buttonList) {
        if (node.innerText.replaceAll(' ', '') === clickButton) {
          return [node]
        }
      }
      return null
    }
    return document.querySelectorAll(clickButton)
  }

  function appendLine (divBox) {
    const p = document.createElement('p')
    p.style = 'margin: 2px 0'
    divBox.appendChild(p)
  }

  const buttonList = []
  function addButton (box, name, classNames, onClick) {
    let button = document.createElement("button")
    button.style = 'margin-left: 4px; padding: 10px 10px; margin-top: 6px;'
    button.classList.add(classNames)
    button.innerText = name
    button.addEventListener('click', onClick)
    box.appendChild(button)
    buttonList.push(button)
    return button
  }

  function disabled (button) {
    for (const item of buttonList) {
      item.disabled = true;
      item.style.cursor = "not-allowed"
    }
    button.disabled = false;
    button.style.cursor = "pointer"
  }

  function unDisabled () {
    for (const item of buttonList) {
      item.disabled = false;
      item.style.cursor = "pointer"
    }
  }

  function addInput (box, name, val, onInput) {
    let span = document.createElement("span")
    span.style = 'margin-left: 4px; margin-right: 4px; margin-top: 6px;'
    span.innerHTML = name
    let input = document.createElement("input")
    input.style = 'height: 21px; width: 8%; text-align: center; margin-top: 6px;'
    input.value = val
    input.addEventListener('input', onInput)
    box.appendChild(span)
    box.appendChild(input)
    return input
  }
})();