FPS unlocker

Mope.io fps unlocker

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         FPS unlocker
// @namespace    http://tampermonkey.net/
// @version      2
// @description  Mope.io fps unlocker
// @author       Jerry || Discord: w5b
// @match        https://mope.io/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=mope.io
// @grant        unsafeWindow
// ==/UserScript==

const jerryPack = () => {
  let jerryData;
  loadStorage();
  checkForUpdate();
  const offsets = {
    fpsLimiter: jerryData.fpsLimit || "_0x39d3c4",
  };
  function checkForUpdate() {
    if (!jerryData.gameVersion || jerryData.gameVersion < $config.gameVersion) {
      jerryData.gameVersion = $config.gameVersion;

      fetch("https://mope.io/client.js")
        .then((res) => res.text())
        .then((text) => {
          const fpsLimitRegex = /requestAnimationFrame\(([^)]+)\)/;
          var fpsLimitOffset = text.match(fpsLimitRegex);
          if (fpsLimitOffset) {
            jerryData.fpsLimit = fpsLimitOffset[1];
          } else {
            console.dir("Regex match not found in the fetched content.");
          }
        })
        .catch((error) => {
          console.dir("Error fetching the client.js:", error);
        });
    }
  }

  function loadStorage() {
    try {
      jerryData = JSON.parse(localStorage.jerryDATA);
    } catch (error) {
      jerryData = {};
    }
  }

  function replaceAllFunctions() {
    unsafeWindow[offsets.fpsLimiter] = newFpsLimit;
  }

  let frameCount = 0,
    lastFrameTime = null,
    averageFPS = 0;

  function updateFPS(currentTime) {
    frameCount += 1;

    if (currentTime - lastFrameTime > 1000) {
      lastFrameTime = currentTime;
      averageFPS = frameCount;
      frameCount = 0;

      $bus["emit"]($bus["EVENTS"]["UI_SET_FPS"], averageFPS);
    }
  }

  let lastTime = 0;
  let targetFPS = jerryData.jerryFPS || 60;
  let timePerFrame = 1000 / targetFPS;

  function newFpsLimit(timestamp) {
    const elapsedTime = timestamp - lastTime;
    if (elapsedTime < timePerFrame) {
      requestAnimationFrame(unsafeWindow[offsets.fpsLimiter]);
      return;
    }
    updateFPS(timestamp);
    lastTime = timestamp;
    lastFrameTime === null && (lastFrameTime = timestamp);
    _0x2bcf6c(timestamp);
    requestAnimationFrame(newFpsLimit);
  }

  function handleFpsSlider() {
    const fpsSlider = document.getElementById("slider-fps");
    const sliderValue = document.getElementById("sliderValue");
    fpsSlider.value = jerryData.jerryFPS;
    sliderValue.innerHTML = fpsSlider.value;
    fpsSlider.addEventListener("input", function () {
      sliderValue.innerHTML = this.value;
      targetFPS = this.value;
      timePerFrame = 1000 / targetFPS;
    });
  }

  window.onbeforeunload = function () {
    const fpsSlider = document.getElementById("slider-fps");
    jerryData.jerryFPS = fpsSlider.value;
    localStorage.jerryDATA = JSON.stringify(jerryData);
  };

  document.addEventListener("keydown", (e) => {
    switch (e.key) {
      case "p":
        const mainContainer = document.getElementById("main-container");
        const currentDisplay = mainContainer.style.display;
        currentDisplay == "none"
          ? (mainContainer.style.display = "flex")
          : (mainContainer.style.display = "none");
        break;
    }
  });

  replaceAllFunctions();

  function injectHTML() {
    const htmlCode = `
      <!-- Paste your HTML code here -->
      <div id="main-container">
        <h1>FPS Unlocker</h1>
        <div class="slider-container">
          <input type="range" min="10" max="360" value="60" class="slider" id="slider-fps">
          <div id="slider-header-container">
          <p id="header-fps">FPS:  </p>
          <span contenteditable id="sliderValue">60</span>
          </div>
        </div>
        <div id="credits-container">
        <button id="credits-button">Join Discord</button>
        </div>
        </div>
    `;

    const div = document.createElement("div");
    div.innerHTML = htmlCode;

    document.body.appendChild(div);

    const sliderValue = document.getElementById("sliderValue");

    sliderValue.addEventListener("keydown", function (event) {
      if (event.key === "Enter") {
        this.blur();
        event.preventDefault();
      }
    });

    sliderValue.addEventListener("blur", function () {
      let newValue = parseInt(this.textContent);

      if (!isNaN(newValue)) {
        const fpsSlider = document.getElementById("slider-fps");

        newValue = Math.min(
          Math.max(newValue, parseInt(fpsSlider.min)),
          parseInt(fpsSlider.max)
        );

        this.textContent = newValue;
        fpsSlider.value = newValue;
      }
    });

    const mainContainer = document.getElementById("main-container");
    makeDraggable(mainContainer);

    document.getElementById("credits-button").addEventListener("click", function() {
      window.open("https://discord.gg/NSyHaFG8Uv", "_blank");
    });
  }

  function makeDraggable(element) {
    let offsetX, offsetY;
    let isDragging = false;

    element.addEventListener("mousedown", function (e) {
      const rect = element.getBoundingClientRect();
      const mainContainer = document.getElementById("main-container");

      if (e.target == mainContainer) {
        e.preventDefault();
        isDragging = true;

        function moveElement(e) {
          if (!isDragging) return;
          element.style.position = "absolute";
          element.style.left = e.clientX + "px";
          element.style.top = e.clientY + "px";
        }

        function stopDragging() {
          isDragging = false;
          document.removeEventListener("mousemove", moveElement);
          document.removeEventListener("mouseup", stopDragging);
        }

        document.addEventListener("mousemove", moveElement);
        document.addEventListener("mouseup", stopDragging);
      }
    });
  }

  function injectCSS() {
    const style = document.createElement("style");
    style.textContent = `
      h1 {
        color: white;
        margin: 20px;
        text-shadow: 1px 1px 1px black;
        font-family: sans-serif
      }

      #main-container {
        background-color: rgba(0, 0, 0, 0.7);
        border-radius: 2%;
        width: 23vw;
        height: 20vh;
        position: absolute;
        top: 20%;
        left: 80%;
        transform: translate(-50%, -50%);
        display: flex;
        align-items: center;
        flex-direction: column;
        z-index: 999
      }

      .slider-container {
        display: flex;
        flex-direction: column;
        justify-content: center;
        width: 100%;
        align-items: center;
      }

      #main-container p,span {
        color: white;
        font-weight: bold;
        text-shadow: 1px 1px 1px black;
        font-family: sans-serif
      }

      .slider {
        width: 70%;
        background-color: rgba(0, 0, 0, 0.2);
        height: 50%;
        -webkit-appearance: none;
        appearance: none;
        border-radius: 16px;
        overflow: hidden;
        border-radius: 16px;
      }

      .slider::-webkit-slider-thumb {
        -webkit-appearance: none;
        appearance: none;
        width: 25px;
        height: 25px;
        background-color: #fff;
        border-radius: 50%;
        box-shadow: -407px 0 0 400px black;
        transition: 0.2s ease-in-out;
      }

      .slider::-moz-range-thumb {
        -webkit-appearance: none;
        appearance: none;
        width: 25px;
        height: 25px;
        background-color: #fff;
        border-radius: 50%;
        box-shadow: -407px 0 0 400px black;
        transition: 0.2s ease-in-out;
      }

      #slider-header-container {
        display: flex;
        flex-direction: row;
        justify-content: center;
        align-items:center;
      }

      #sliderValue {
        margin: 5px;
      }

      #credits-container {
        display: flex;
        position: absolute;
        justify-content: flex-end;
        align-items: center;
        right: 10px;
        width: 100%;
        height: 30px;
        bottom: 10px;
        }
        #credits-button {
          text-decoration: none;
          color: white;
          padding: 5px;
          background-color: transparent;
          border-radius: 5px;
          border: none;
          font-weight: bolder;
          font-family: sans-serif;
          cursor: pointer;
          font-size: 15px;
          text-shadow: 1px 1px 1px black;
          }

          #credits-button:hover {
            font-size: 16px;
            transition: font-size 0.1s ease-out
          }
    `;
    document.head.appendChild(style);
  }

  injectHTML();
  injectCSS();
  handleFpsSlider();
};
const initInterval = setInterval(() => {
  if (document.querySelector("head > script:nth-child(55)")) {
    clearInterval(initInterval);
    jerryPack();
  }
}, 100);