碧可梦

碧可梦散步

// ==UserScript==
// @name         碧可梦
// @namespace    https://github.com/Waaatanuki
// @version      1.0.3
// @description  碧可梦散步
// @author       Waaatanuki
// @license      MIT
// @match        *://*/*
// @icon         https://prd-game-a-granbluefantasy.akamaized.net/favicon.ico
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// ==/UserScript==

(function () {
  'use strict'

  // ⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️配置信息⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️

  const config = {"sort":[0],"cosmetic":["000","000","000"],"size":100,"frameInterval":150}

  // ⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️配置信息⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️⬆️

  const STORAGE_KEY = 'sampoPosition'
  const imgUri = 'https://prd-game-a1-granbluefantasy.akamaized.net/assets/img/sp/vyrnsampo/assets/character/exploring'

  let requestId = null

  // 主容器
  const container = document.createElement('div')
  container.style.position = 'fixed'
  container.style.zIndex = '9999'
  container.style.display = 'flex'
  container.style.alignItems = 'center'
  container.style.justifyContent = 'center'
  container.style.cursor = 'move'

  // 尝试从GM存储加载位置(跨页面共享)
  const savedPosition = GM_getValue(STORAGE_KEY)
  if (savedPosition) {
    const { left, top } = savedPosition
    container.style.left = `${left}px`
    container.style.top = `${top}px`
  }
  else {
    container.style.right = '20px'
    container.style.bottom = '20px'
  }

  const partyInfo = []

  for (let i = 0; i < config.sort.length; i++) {
    const npcId = config.sort[i]

    const npcContainer = document.createElement('div')
    npcContainer.style.position = 'relative'
    npcContainer.style.width = `${config.size}px`
    npcContainer.style.height = `${config.size}px`
    container.appendChild(npcContainer)

    const npcInfo = { id: npcId, element: [] }

    for (let i = 0; i < (npcId === 0 ? 3 : 1); i++) {
      const el = document.createElement('img')
      el.style.position = 'absolute'
      el.style.width = `${config.size}px`
      el.draggable = false
      el.onerror = () => {
        console.log('加载碧可梦失败')
        if (requestId) {
          cancelAnimationFrame(requestId)
          requestId = null
        }
        container.remove()
      }
      npcContainer.appendChild(el)
      npcInfo.element.push(el)
    }
    partyInfo.push(npcInfo)
  }

  let isDragging = false
  let offsetX = 0
  let offsetY = 0

  container.addEventListener('mousedown', (e) => {
    if (e.button !== 0)
      return

    isDragging = true
    const rect = container.getBoundingClientRect()
    offsetX = e.clientX - rect.left
    offsetY = e.clientY - rect.top
  })

  document.addEventListener('mousemove', (e) => {
    if (!isDragging)
      return

    const x = e.clientX - offsetX
    const y = e.clientY - offsetY

    container.style.right = 'auto'
    container.style.bottom = 'auto'
    container.style.left = `${x}px`
    container.style.top = `${y}px`
  })

  document.addEventListener('mouseup', () => {
    if (isDragging) {
      isDragging = false

      const position = {
        left: Number.parseInt(container.style.left),
        top: Number.parseInt(container.style.top),
      }
      GM_setValue(STORAGE_KEY, position)
    }
  })

  document.body.appendChild(container)

  GM_registerMenuCommand('重置位置', () => {
    GM_deleteValue([STORAGE_KEY])
  })

  let currentIndex = 0
  let lastTime = 0

  function animate(timestamp) {
    if (timestamp - lastTime >= config.frameInterval) {
      currentIndex = (currentIndex % 4) + 1
      lastTime = timestamp

      for (const npc of partyInfo) {
        if (npc.id === 0) {
          npc.element.forEach((el, index) => {
            el.src = `${imgUri}/captain/captain_01_0${index + 1}_${config.cosmetic[index]}_0${currentIndex}.png`
          })
        }
        else {
          npc.element.forEach((el) => {
            el.src = `${imgUri}/crew/crew_0${npc.id}_0${currentIndex}.png`
          })
        }
      }
    }

    requestId = requestAnimationFrame(animate)
  }

  requestId = requestAnimationFrame(animate)
})()

QingJ © 2025

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