您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Easily traverse the world of Sploop.io with Waypoints!
// ==UserScript== // @name Waypoints [Sploop.io] // @name:zh 航点 [Sploop.io] // @name:tr Yolu Göstergeleri [Sploop.io] // @name:ru Точки маршрута [Sploop.io] // @name:vi Điểm chỉ đường [Sploop.io] // @name:ar علامات الطريق [Sploop.io] // @description Easily traverse the world of Sploop.io with Waypoints! // @description:zh 轻松通过航点在Sploop.io世界中穿行! // @description:tr Kolayca Sploop.io dünyasında yol göstergeleri ile gezin! // @description:ru Легко путешествуйте по миру Sploop.io с помощью точек маршрута! // @description:vi Dễ dàng di chuyển trong thế giới Sploop.io với các điểm chỉ đường! // @description:ar اجتاز عالم Sploop.io بسهولة باستخدام علامات الطريق! // @version 2.0.0 // @author Hori + viper // @match https://sploop.io/ // @icon https://i.ibb.co/ym4LXJF7/Waypoints-3-removebg-preview.png // @grant none // @run-at document-start // @license MIT // @namespace https://gf.qytechs.cn/users/1441649 // ==/UserScript== /** * Authors: horizion, viper * * Menu Keybind : ESCAPE * * (!) - You are able to modify the script in any way, as long as it abides by the in-game rules. * (!) - Contact Horizion if the script does not work. * * Discord: horizon2025.#0000 | <@880415818142347297> * * Official Sploop.io Discord Server: https://discord.com/invite/CYadgpyv78 */ (function () { "use strict"; const win = window; const log = console.log; const version = `2.0.0`; const ARROW_DISTANCE_FROM_PLAYER = 210; const COLORS = [ "red", "orange", "yellow", "green", "dark_blue", "light_blue", "purple", "violet", "pink", "rose", ]; const MARKER_IMAGES = [ "https://i.ibb.co/20h3vpRG/map-cross-red.png", "https://i.ibb.co/VWZCzbgK/map-cross-orange.png", "https://i.ibb.co/x8jT4J4x/map-cross-yellow.png", "https://i.ibb.co/dstqTPQP/map-cross-darkgreen.png", "https://i.ibb.co/dsSZtg0Q/map-cross-darkblue.png", "https://i.ibb.co/4RPBRMH7/map-cross-lightblue.png", "https://i.ibb.co/84KYxdNd/map-cross-purple.png", "https://i.ibb.co/8LJ4FbbW/map-cross-indigo.png", "https://i.ibb.co/bgNv5NB7/map-cross-pink.png", "https://i.ibb.co/5WMsX1f1/map-cross-main.png", ]; const ARROW_IMAGES = [ "https://i.ibb.co/chgGndnF/arrow-red.png", "https://i.ibb.co/LdkChynd/arrow-orange.png", "https://i.ibb.co/v6x76XN6/arrow-yellow.png", "https://i.ibb.co/2YYvqNHj/arrow-darkgreen.png", "https://i.ibb.co/6RrD7MvR/arrow-darkblue.png", "https://i.ibb.co/9kqtG2k4/arrow-lightblue.png", "https://i.ibb.co/ZzjZhK0g/arrow-purple.png", "https://i.ibb.co/sdgDvP0Y/arrow-indigo.png", "https://i.ibb.co/yFFq6jBN/arrow-pink.png", "https://i.ibb.co/zT2rYdFT/arrow-main.png", ]; const MARKER_COLOR_IMAGES = { red: "https://i.ibb.co/ksRyM6FY/circle-red.png", orange: "https://i.ibb.co/4gNKXnp6/circle-orange.png", yellow: "https://i.ibb.co/60rHrBWP/circle-yellow.png", green: "https://i.ibb.co/kVGgcVKT/circle-green.png", dark_blue: "https://i.ibb.co/9mbLDCLq/circle-darkblue.png", light_blue: "https://i.ibb.co/LhNv7JXx/circle-lightblue.png", purple: "https://i.ibb.co/WvddsXyk/circle-purple.png", violet: "https://i.ibb.co/PZKjyN2g/circle-indigo.png", pink: "https://i.ibb.co/bf2LzgM/circle-pink.png", rose: "https://i.ibb.co/0pMvXrMS/circle-main.png", }; let waypointID = 0; let waypoints = []; let cards = []; win.showWaypointArrows = 1; //** Styling DOM */ const style = document.createElement("style"); style.type = "text/css"; style.textContent = ` :root { --main: #de5978; --secondary: rgb(43, 37, 37, 1); } button:focus { border: none; outline: none; } input:focus { outline: none; border: none; } /* Making scroll bar more pro */ ::-webkit-scrollbar { width: 7px; } ::-webkit-scrollbar-thumb { background-color: var(--main); border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-top-left-radius: 0; border-bottom-left-radius: 0; } ::-webkit-scrollbar-track { background-color: var(--secondary); border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-top-left-radius: 0; border-bottom-left-radius: 0; } /* Main menu styling */ #wayMenu { display: none; position: fixed; top: 160px; left: 293px; z-index: 99999; padding: 20px; background: var(--secondary); border-radius: 10px; max-height: 60%; overflow-y: auto; width: 400px; border: 1.5px solid var(--main); } .wayHeader { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .wayTitle { font-size: 20px; color: var(--main); } .version { font-size: 15px; color: rgba(100, 100, 100,1); } .wayArrowToggle { display: flex; align-items: center; gap: 5px; opacity: 0; transition: all 0.3s ease-in-out; pointer-events: none; } .wayArrowToggle i { color: var(--main); font-size: 18px; } .switch { position: relative; display: inline-block; width: 40px; height: 20px; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: rgb(41, 41, 41); transition: 0.3s; border-radius: 20px; border: 1px solid rgb(112, 53, 74); } .slider:before { position: absolute; content: ""; height: 14px; width: 14px; left: 3px; background-color: var(--main); bottom: 3px; transition: 0.3s; border-radius: 50%; } input:checked + .slider { background-color: rgba(187, 75, 101,0.6); } input:checked + .slider:before { transform: translateX(20px); } .wayCreateNewButton { margin-top: 25px; border: none; color: white; width: 250px; text-align: center; border-radius: 10px; padding: 7px; background: var(--main); font-size: 18px; cursor: pointer; font-weight: 990; height:35px; transition: transform 0.4s ease; border: 1px solid var(--secondary); } .wayCreateNewButton:hover { transform: translateY(-1px); } .wayCreateNewButton:disabled { background:rgb(187, 75, 101); color:rgba(156, 156, 156, 0.99); cursor: not-allowed; opacity: 0.85; transform: none; } .wayNotFound { text-align: center; display: block; font-size: 15px; color: white; margin-top: 20px; } .wayCreate { text-align: center; } /* popup styling */ #wayPopMenu { display: block; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 25px; background: var(--secondary); border-radius: 10px; max-height: 50%; overflow-y: auto; text-align: center; } .popupHeader { position: absolute; top: 0; right: 8px; margin-bottom: 8px; } .closePopup { font-size: 24px; font-weight: bold; cursor: pointer; color: #fff; } .popupHeader:hover { transform: translateY(-1px); } #markerName { border-radius: 10px; height:35px; text-align: center; font-size: 16px; border: none; width: 200px; } #wayColors { padding: 7px; height:35px; width: 200px; border: none; border-radius: 10px; font-size: 16px; margin-bottom: 16px; background: #fff; color: #333; -webkit-appearance: none; -moz-appearance: none; appearance: none; text-align: center; font-weight: 800; cursor: pointer; } .wayCreateButton { border: none; color: white; width: 200px; text-align: center; border-radius: 10px; padding: 7px; background: var(--main); cursor: pointer; font-weight: 560; font-size: 16px; height:35px; transition: transform 0.4s ease; } .wayCreateButton:focus{ border:none; } .wayCreateButton:hover { transform: translateY(-1px); } /* Card Styling */ .card { display: flex; align-items: center; background:rgb(41, 41, 41); border-radius: 10px; padding: 10px; margin-top: 10px; color: white; border: 1px solid rgb(112, 53, 74); } .card img { width: 22px; height: 22px; margin-right: 10px; border-radius: 50%; } .card .card-name { flex: 4; font-size: 16px; margin-right: 10px; max-width: 145px; } .card .card-coords { flex: 3; font-size: 16px; margin-right: 10px; color: rgba(100, 100, 100,1); } .card .card-remove { background: #e43939; border: none; color: white; padding: 5px 10px; border-radius: 5px; cursor: pointer; } .card .card-remove:hover { transform: translateY(-1px); } #trash:hover { cursor: pointer; } `; document.head.appendChild(style); //** Main */ document.addEventListener("DOMContentLoaded", () => { log( `%cWaypoints %cVersion ${version}\n%cCreators: %cviper + Hori`, "font-size: 90px; font-weight: 900; color: #de5978;", "font-size: 20px; color: gray;", "font-size: 20px; font-weight: 900; color:rgb(255, 255, 255); margin-top: 8px; margin-bottom: 10px;", "font-size: 20px; color:rgb(235, 187, 97); margin-top: 8px; margin-bottom: 10px;" ); const wayMenu = document.createElement("div"); wayMenu.id = "wayMenu"; wayMenu.innerHTML = ` <div class="wayHeader"> <span class="wayTitle">Waypoints <span class="version">- v${version}</span></span> <div class="wayArrowToggle"> <i class="fa-solid fa-location-arrow"></i> <label class="switch"> <input type="checkbox" id="waypointToggle" checked> <span class="slider"></span> </label> </div> </div> <div class="wayContent"> <div id="wayNotFound" class="wayNotFound"> No Waypoints Found <i class="fa-solid fa-magnifying-glass"></i> </div> </div> <div class="wayCreate"> <button id="wayCreateNewButton" class="wayCreateNewButton" disabled>+</button> </div> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css" integrity="sha512-SzlrxWUlpfuzQ+pcUCosxcglQRNAq/DZjVsC0lE40xsADsfeQoEypE+enwcOiGjk/bSuGGKHEyjSoQ1zVisanQ==" crossorigin="anonymous" referrerpolicy="no-referrer" /> `; document.body.append(wayMenu); let isDragging = false, displayToggled = false, offsetX, offsetY; wayMenu.addEventListener("mousedown", function (event) { isDragging = true; offsetX = event.clientX - wayMenu.getBoundingClientRect().left; offsetY = event.clientY - wayMenu.getBoundingClientRect().top; }); document.addEventListener("mousemove", function (event) { if (isDragging) { const newX = event.clientX - offsetX; const newY = event.clientY - offsetY; wayMenu.style.left = newX + "px"; wayMenu.style.top = newY + "px"; } }); document.addEventListener("mouseup", () => { isDragging = false; }); document .getElementById("wayCreateNewButton") .addEventListener("click", () => { if (!document.getElementById("wayPopMenu")) { createPopup(); } }); document.addEventListener("keydown", (event) => { if (event.key === "Escape" && !isChatWrapperVisible()) { wayMenu.style.display = displayToggled ? "none" : "block"; displayToggled = !displayToggled; } }); document .getElementById("waypointToggle") .addEventListener("change", function () { if (this.checked) { win.showWaypointArrows = 1; } else { win.showWaypointArrows = 0; } }); const observer = new MutationObserver(() => { updateCreateButton(); }); const homepage = document.getElementById("homepage"); if (homepage) { observer.observe(homepage, { attributes: true, attributeFilter: ["style"], }); } }); const addWaypoint = new Proxy(waypoints, { set(target, property, value, receiver) { const result = Reflect.set(target, property, value, receiver); if (!isNaN(property)) { createCard(value); } return result; }, }); function createPopup() { let wayPopMenu = document.createElement("div"); wayPopMenu.id = "wayPopMenu"; wayPopMenu.innerHTML = ` <div class="popupHeader"> <span id="closePopup" class="closePopup">x</span> </div> <div class="inputContainer"> <input type="text" id="markerName"placeholder="New Waypoint" maxLength="13"><br><br> </div> <div class="wayColor"> <select name="colors" id="wayColors"> <option value="0">Red</option> <option value="1">Orange</option> <option value="2">Yellow</option> <option value="3">Green</option> <option value="4">Dark Blue</option> <option value="5">Light Blue</option> <option value="6">Purple</option> <option value="7">Violet</option> <option value="8">Pink</option> <option value="9">Rose</option> </select> </div> <div class="wayCreate"> <button id="createButton" class="wayCreateButton">Create</button> </div> `; document.body.appendChild(wayPopMenu); document .getElementById("markerName") .addEventListener("keydown", function (event) { event.stopPropagation(); }); document.getElementById("closePopup").addEventListener("click", () => { wayPopMenu.remove(); }); document .getElementById("createButton") .addEventListener("click", getOption); } function createCard(waypoint) { cards.push({ name: waypoint.name, id: waypoint.id, }); const card = document.createElement("div"); card.className = "card"; card.innerHTML = ` <img src="${MARKER_COLOR_IMAGES[waypoint.color]}" alt="color"> <div class="card-name">${waypoint.name}</div> <div class="card-coords">[${Math.round(waypoint.x)},${Math.round(waypoint.y)}]</div> <button class="card-remove"><i class="fa-solid fa-trash" id="trash"></i></button> `; document.querySelector(".wayContent").appendChild(card); updateArrowToggleAlpha(); const removeButton = card.querySelector(".card-remove"); removeButton.addEventListener("click", function () { const waypointIndex = waypoints.findIndex( (way) => way.id === waypoint.id ); if (waypointIndex > -1) { waypoints.splice(waypointIndex, 1); } const cardIndex = cards.findIndex( (card) => card.id === waypoint.id ); if (cardIndex > -1) { cards.splice(cardIndex, 1); } card.remove(); if (cards.length === 0) { document.getElementById("wayNotFound").style.display = "block"; } updateArrowToggleAlpha(); }); } function createWaypoint(name, color) { const chosenMarker = MARKER_IMAGES[color]; const chosenArrow = ARROW_IMAGES[color]; const markerImg = createImage(chosenMarker); const arrowImg = createImage(chosenArrow); const newWaypoint = { name, id: waypointID++, arrow: arrowImg, marker: markerImg, x: win.coords.x, y: win.coords.y, color: COLORS[color], }; addWaypoint.push(newWaypoint); } function getOption() { const markerName = document.getElementById("markerName").value; const wayColor = document.getElementById("wayColors"); const color = wayColor.value; if (markerName !== "") { createWaypoint(markerName, color); document.getElementById("wayNotFound").style.display = "none"; document.getElementById("wayPopMenu").remove(); } } function updateCreateButton() { const button = document.getElementById("wayCreateNewButton"); const homepage = document.getElementById("homepage"); if (homepage && homepage.style.display === "flex") { button.disabled = true; } else { button.disabled = false; } } function updateArrowToggleAlpha() { const toggle = document.querySelector(".wayArrowToggle"); if (toggle) { toggle.style.opacity = cards.length === 0 ? "0" : "1"; toggle.style.pointerEvents = cards.length === 0 ? "none" : "auto"; } } function createImage(URL) { const image = new Image(); image.src = URL; return image; } function isChatWrapperVisible() { return ( document.getElementById("chat-wrapper").style.display === "block" ); } //** Draw Waypoints, Arrows, Names */ class Drawing { arrows(context, arrow, angle, x, y) { context.save(); context.globalAlpha = 0.52; context.translate(x, y); context.rotate(angle); context.drawImage(arrow, -25 / 2, -25 / 2, 25, 25); context.restore(); } name(context, waypoint) { const x = waypoint.x; const y = waypoint.y - 42; context.font = "24px Baloo Paaji"; context.textAlign = "center"; context.lineWidth = 8; context.strokeStyle = "#414141"; context.lineJoin = "round"; context.strokeText(waypoint.name, x, y); context.fillStyle = "white"; context.fillText(waypoint.name, x, y); } waypoint(context, waypoint) { context.drawImage( waypoint.marker, waypoint.x - 70 / 2, waypoint.y - 70 / 2, 70, 70 ); } } const Draw = new Drawing(); win.draw = (context) => { waypoints.forEach((waypoint) => { const distance = Math.hypot( waypoint.x - win.coords.x, waypoint.y - win.coords.y ); if (distance < 1200) { Draw.waypoint(context, waypoint); Draw.name(context, waypoint); } if (win.showWaypointArrows && distance > 450) { const angle = Math.atan2( waypoint.y - win.coords.y, waypoint.x - win.coords.x ); let radius = ARROW_DISTANCE_FROM_PLAYER; const x = win.coords.x + Math.cos(angle) * radius; const y = win.coords.y + Math.sin(angle) * radius; Draw.arrows(context, waypoint.arrow, angle, x, y); } }); }; //** Hooking onto the game */ const TYPEOF = (value) => Object.prototype.toString.call(value).slice(8, -1).toLowerCase(); const NumberSystem = [ { radix: 2, prefix: "0b0*", }, { radix: 8, prefix: "0+", }, { radix: 10, prefix: "", }, { radix: 16, prefix: "0x0*", }, ]; class Regex { constructor(code, unicode, namespace) { if (!namespace) namespace = "new_script_" + Math.random().toString(36).substr(2, 8); this.code = code; this.COPY_CODE = code; this.unicode = unicode || false; this.hooks = {}; this.namespace = namespace; this.totalHooks = 0; } static parseValue(value) { try { return Function(`return (${value})`)(); } catch (err) { return null; } } isRegexp(value) { return TYPEOF(value) === "regexp"; } generateNumberSystem(int) { const template = NumberSystem.map( ({ prefix, radix }) => prefix + int.toString(radix) ); return `(?:${template.join("|")})`; } parseVariables(regex) { regex = regex.replace(/\{VAR\}/g, "(?:let|var|const)"); regex = regex.replace(/\{QUOTE\}/g, "['\"`]"); regex = regex.replace(/ARGS\{(\d+)\}/g, (...args) => { let count = Number(args[1]), arr = []; while (count--) arr.push("\\w+"); return arr.join("\\s*,\\s*"); }); regex = regex.replace(/NUMBER\{(\d+)\}/g, (...args) => { const int = Number(args[1]); return this.generateNumberSystem(int); }); return regex; } _hookName(name) { return `${this.namespace}:${name}`; } format(name, inputRegex, flags) { this.totalHooks++; let regex = ""; if (Array.isArray(inputRegex)) { regex = inputRegex .map((exp) => (this.isRegexp(exp) ? exp.source : exp)) .join("\\s*"); } else if (this.isRegexp(inputRegex)) { regex = inputRegex.source; } regex = this.parseVariables(regex); if (this.unicode) { regex = regex.replace(/\\w/g, "(?:[^\\x00-\\x7F-]|\\$|\\w)"); } const expression = new RegExp( regex.replace(/\{INSERT\}/, ""), flags ); return regex.includes("{INSERT}") ? new RegExp(regex, flags) : expression; } template(type, name, regex, substr) { const hookName = this._hookName(name); const expression = new RegExp( `(${this.format(hookName, regex).source})` ); const match = this.code.match(expression) || []; this.code = this.code.replace( expression, type === 0 ? "$1" + substr : substr + "$1" ); this.hooks[hookName] = { expression, match }; return match; } logHooks() { log( "%cApplied Hooks:", "font-weight: bold; font-size: 24px; color:rgb(255, 255, 255); margin-top: 20px;" ); let index = 1; for (const hookName in this.hooks) { const hook = this.hooks[hookName]; const matches = Array.isArray(hook.match) ? hook.match : [hook.match]; const status = matches && matches.length > 0 ? "successful" : "unsuccessful"; const style = matches && matches.length > 0 ? "color:rgb(134, 204, 125); font-size: 14px;" : "color:rgb(221, 94, 113); font-size: 14px;"; log(`%c${index}. ${hookName} | ${status}`, style); index++; } log( "%c-----------------", "font-weight: bold; color: gray; margin-bottom: 5px; margin-top: 20px;" ); } match(name, regex, flags) { const hookName = this._hookName(name); const expression = this.format(hookName, regex, flags); const match = this.code.match(expression) || []; this.hooks[hookName] = { expression, match }; return match; } replace(name, regex, substr, flags) { const hookName = this._hookName(name); const expression = this.format(hookName, regex, flags); const preMatch = this.code.match(expression) || []; this.code = this.code.replace(expression, substr); this.hooks[hookName] = { expression, match: preMatch, replaced: preMatch.length > 0, }; return this.code.match(expression) || []; } append(name, regex, substr) { return this.template(0, name, regex, substr); } prepend(name, regex, substr) { return this.template(1, name, regex, substr); } } const applyHooks = (code) => { const namespace = `waypoints_v${version}`; const Hook = new Regex(window.HOOKED_CODE || code, true, namespace); window.COPY_CODE = (Hook.COPY_CODE.match( /^(\(function \w+\(\w+\)\{.+)\(.+?\);$/ ) || [])[1]; // log(Hook.COPY_CODE); if (!window.HOOKED_CODE) Hook.append( "EXTERNAL fix", /\(function (\w+)\(\w+\)\{/, "let $2 = eval(`(() => ${COPY_CODE})()`); delete window.COPY_CODE;" ); Hook.replace("LOADER", /Loading Sploop.io/, `Loading...`); Hook.append( "COORDS", /,this\.\w{2}=0\},this\.\w{2}=\w+\((\w),(\w),\w\)\{/, `window.coords = { x: $2, y: $3 };` ); Hook.prepend("DRAW",/\w=\w\[\w\(\)\.\w+\],\w=\w.{7,8};for\(let \w=\d;\w\W\w;\w\+\+\)!\(\w\[\w\]\.\w+&\w\(\)\.\w+\)&&\w+\(\w\[\w\],(\w),\w\);/,"/*55306335646D457A5457645A4D3070735756685362467044516D6C6C553046335A555657616D4649546C5A50626B70365756453950513D3D*/window.draw($2);"); // log(Hook.code); window.HOOKED_CODE = Hook.code; Hook.logHooks(); return Hook.code; }; window.eval = new Proxy(window.eval, { apply(target, _this, args) { const code = args[0]; if (code.length > 1e5) { args[0] = applyHooks(code); window.eval = target; target.apply(_this, args); return; } return target.apply(_this, args); }, }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址