您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A modding api for woomy.surge.sh
// ==UserScript== // @name Woomy Modding Api // @namespace http://tampermonkey.net/ // @version 1.8 // @description A modding api for woomy.surge.sh // @author Drako Hyena // @match https://woomy.surge.sh/ // @match https://woomy-arras.netlify.app // @match https://www.woomy-arras.xyz/ // @grant none // @run-at document-start // ==/UserScript== (function() { const version = 1.8 if(window.WMA){ if((!window.WMA.version)||window.WMA.version&&window.WMA.version<version) alert("A script is using an older version of the API. Please disable or update that script or other scripts might not work!") return window.WMA.log(["WoomyModdingApi", "MenuLoading"],"API is already in place") } let movetoTimeout = setTimeout(()=>{},0) // Create the api window.WMA = { version: version, packets: { receive: { subscriptionCount: 0, subscriptions: {}, sub: (funct) => { window.WMA.packets.receive.subscriptions[window.WMA.packets.receive.subscriptionCount] = funct return window.WMA.packets.receive.subscriptionCount++ }, unsub: (id) => { delete window.WMA.packets.receive.subscriptions[id] }, }, send: { subscriptionCount: 0, subscriptions: {}, sub: (funct) => { window.WMA.packets.send.subscriptions[window.WMA.packets.send.subscriptionCount] = funct return window.WMA.packets.send.subscriptionCount++ }, unsub: (id) => { delete window.WMA.packets.send.subscriptions[id] }, } }, entities: { subscriptionCount: 0, subscriptions: {}, sub: (funct) => { window.WMA.entities.subscriptions[window.WMA.entities.subscriptionCount] = funct return window.WMA.entities.subscriptionCount++ }, unsub: (id) => { delete window.WMA.entities.subscriptions[id] }, }, createButton: (name="New Button", otherInfo="off", callback=()=>{})=>{ let button = createButtonEle() button.innerHTML = `<p>${name}</p><p>${otherInfo}</p>` button.onclick = (event) => { callback(button, event) } return button }, refreshInputs: () => { if (!window.WMA.socket) return window.WMA.socket.cmd.set(0, 0); window.WMA.socket.cmd.set(1, 0); window.WMA.socket.cmd.set(2, 0); window.WMA.socket.cmd.set(3, 0); document.getElementById("gameCanvas").focus() }, log: (names=["WoomyModdingAPI"],str="") => { let nameStr = "" for(let name of names){ nameStr += `[${name}]` } console.log(`${nameStr} - ${str}`) }, upgradeStat: (statName) => { switch(statName){ case "Body Damage": window.WMA.socket.talk("x", 0); break; case "Max Health": window.WMA.socket.talk("x", 1); break; case "Bullet Speed": window.WMA.socket.talk("x", 2); break; case "Bullet Health": window.WMA.socket.talk("x", 3); break; case "Bullet Penetration": window.WMA.socket.talk("x", 4); break; case "Bullet Damage": window.WMA.socket.talk("x", 5); break; case "Reload": window.WMA.socket.talk("x", 6); break; case "Movement Speed": window.WMA.socket.talk("x", 7); break; case "Shield Regeneration": window.WMA.socket.talk("x", 8); break; case "Shield Capacity": window.WMA.socket.talk("x", 9); break; } }, move: { up: ()=>{ window.WMA.socket.cmd.set(0, 1); }, down: ()=>{ window.WMA.socket.cmd.set(1, 1); }, left: ()=>{ window.WMA.socket.cmd.set(2, 1); }, right: ()=>{ window.WMA.socket.cmd.set(3, 1); }, to: (x=0, y=0, ms=1000)=>{ if(!window.WMA.yourPlayer.entity) return window.WMA.log(["WoomyModdingAPI","MoveTo/MoveAway"], "No window.WMA.yourPlayer.entity"); window.WMA.move.stop() if(x>window.WMA.yourPlayer.position.x){ window.WMA.move.right() }else if(x<window.WMA.yourPlayer.position.x){ window.WMA.move.left() } if(y<window.WMA.yourPlayer.position.y){ window.WMA.move.up() }else if(y>window.WMA.yourPlayer.position.y){ window.WMA.move.down() } clearTimeout(movetoTimeout) movetoTimeout = setTimeout(()=>{window.WMA.move.stop()}, ms) }, away: (x=0, y=0, ms=1000)=>{ window.WMA.move.to(-x,-y,ms) }, stop: ()=>{ window.WMA.socket.cmd.set(0, 0); window.WMA.socket.cmd.set(1, 0); window.WMA.socket.cmd.set(2, 0); window.WMA.socket.cmd.set(3, 0); } }, yourPlayer: { position: {x:null,y:null}, target: {x:null, y:null}, entity: null, }, socket: null, global: null, loaded: false, loadButtonQueue: [], } // Set up yourPlayer window.WMA.packets.receive.sub((type, data)=>{ if(type!=="u") return; window.WMA.yourPlayer.position = {x:Math.round(data[3]-data[6]), y:Math.round(data[4]-data[7])} }) window.WMA.packets.send.sub((type, data)=>{ if(type!=="C") return window.WMA.yourPlayer.target = {x:data[0], y:data[1]} }) let buffer = 5 window.WMA.entities.sub((entities)=>{ let entity = entities.find(e => e.name&&e.name===window.WMA.global.playerName&&e.x>window.WMA.yourPlayer.position.x-buffer&&e.x<window.WMA.yourPlayer.position.x+buffer&&e.y>window.WMA.yourPlayer.position.y-buffer&&e.y<window.WMA.yourPlayer.position.y+buffer) if(entity) window.WMA.yourPlayer.entity = entity }) // Hook into socket let onmessage = Object.getOwnPropertyDescriptor(window.WebSocket.prototype, 'onmessage') let oldSet = onmessage.set onmessage.set = function(value){ window.WMA.socket = this window.WMA.log(["WoomyModdingAPI","SocketHook"], "Successfully hooked into the socket") return oldSet.apply(this, arguments) } Object.defineProperty(window.WebSocket.prototype, "onmessage", onmessage) // Hook into the receiving packets let decode; Object.defineProperty(Object.prototype, "decode", { get(){ return decode }, set(v){ decode = function(){ let data = v.apply(this, arguments) for(let functName in window.WMA.packets.receive.subscriptions){ let funct = window.WMA.packets.receive.subscriptions[functName] funct(data.shift(), data) } return v.apply(this, arguments) } } }) // Hook into the sending packets let encode; Object.defineProperty(Object.prototype, "encode", { get(){ return encode }, set(v){ encode = function(){ let type = arguments[0].shift() let data = arguments[0] for(let functName in window.WMA.packets.send.subscriptions){ let funct = window.WMA.packets.send.subscriptions[functName] funct(type, data) } arguments[0] = [type].concat(data) return v.apply(this, arguments) } } }) // Hook into global Object.defineProperty(Object.prototype, "message", { get(){ return this._message }, set(value){ if(!window.WMA.global){ window.WMA.global = this window.WMA.global.globalArray = Object.keys(window.WMA.global).map(key=>[key, window.WMA.global[key]]) } this._message = value } }) // Hook into entities let oldSort = Array.prototype.sort Array.prototype.sort = function(){ if(this[0]&&this[0].alpha){ for(let id in window.WMA.entities.subscriptions){ window.WMA.entities.subscriptions[id](this) } } return oldSort.apply(this, arguments) } window.WMA.log(["WoomyModdingAPI","EntityHook"],"Successfully hooked into entities") // Hook into RegExp.test and String.includes to get around the anticheat let oldTest = RegExp.prototype.test RegExp.prototype.test = function(){ if(oldTest.apply(/user-?script|user.js|multibox/i, arguments)) return false return oldTest.apply(this, arguments) } let oldIncludes = String.prototype.includes String.prototype.includes = function(){ if(arguments[0] === "userscript.html") return false return oldIncludes.apply(this, arguments) } // Hook into toString to spoof things let oldToString = Function.prototype.toString Function.prototype.toString = function(){ switch(this){ case Array.prototype.findIndex: return "functionsort(){[native code]}" break; case Function.prototype.toString: return "functiontoString(){[native code]}" break; case RegExp.prototype.test: return "functiontest(){[native code]}" break; case String.prototype.includes: return "functionincludes(){[native code]}" break; } return oldToString.apply(this, arguments) } window.WMA.log(["WoomyModdingAPI","toStringHook"],"Successfully hooked into toString") function createButtonEle(){ let button = document.createElement("button") if(document.getElementsByClassName("modMenu")[0]){ document.getElementsByClassName("modMenu")[0].appendChild(button) }else{ window.WMA.loadButtonQueue.push(button) } return button } // Load things that need to be loaded after the page is in function load(){ // CREATE THE MENU // make the styles var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = `:root { --text-color: rgba(0, 0, 0, 0.75); --main-color: rgba(0, 0, 0, 0.2); --second-color: rgba(0, 0, 0, 0.75); } .modMenu { display: flex; flex-direction: column; flex-wrap: nowrap; align-content: center; align-items: center; justify-content: flex-start; position: absolute; color: var(--text-color); background: var(--main-color); border-style: solid; border-color: var(--main-color); border-width: 2px; padding: 0.2%; margin: 1%; width: 0.5vw; height: 0.5vh; transition: 0.5s; background: var(--second-color); overflow-x: hidden; overflow-y: auto; z-index:110; backdrop-filter: blur(0px); } .modMenu:hover { background: var(--main-color); width: 35vw; height: 50vh; backdrop-filter: blur(10px); } .modMenu > * { color: var(--text-color); max-height: 0; max-width: 0; font-size: 0; opacity: 0; transition: 0.25s; background: var(--main-color); border-style: solid; border-color: var(--main-color); } .modMenu:hover > * { font-size: 15px; opacity: 1; max-width: 100%; max-height: 100%; } .modMenu:hover > p { font-size: 25px; background: none; border-style:none; } .modMenu:hover > button { margin: 2%; } .modMenu:hover > button:hover { transform: scale(1.1); } .modMenu:hover > button:active { transform: scale(1); } ::-webkit-scrollbar { width: 0px; height: 0px; }`; document.getElementsByTagName('head')[0].appendChild(style); // Make the html elements let modMenu = document.createElement("div") modMenu.classList.add("modMenu") modMenu.onclick = () => {window.WMA.refreshInputs()} let title = document.createElement("p") title.innerHTML = "Mod Menu" modMenu.appendChild(title) document.body.appendChild(modMenu) let discordBtn = createButtonEle() discordBtn.innerHTML = `<p>Join the Discord</p><p></p>` discordBtn.onclick = () => { alert("https://discord.gg/zfSvRsJ7") } let refreshSizeBtn = createButtonEle() refreshSizeBtn.innerHTML = `<p>Refresh Size<p><p></p>` refreshSizeBtn.onclick = () => { let gear = document.getElementById("settings-button").getBoundingClientRect(); let modMenu = document.getElementsByClassName("modMenu")[0] modMenu.style.top = `${gear.top+gear.height/2}px` modMenu.style.left = `0px` modMenu.style.zoom = document.getElementById("mainWrapper").style.zoom } refreshSizeBtn.click() for (let button of window.WMA.loadButtonQueue){ document.getElementsByClassName("modMenu")[0].appendChild(button) } for (let funct of window.WMALoadQueue||[]){ funct() } window.WMA.loaded = true; } // LOAD THE MENU let interval = setInterval(()=>{ if(document.getElementById("settings-button")){ clearInterval(interval) load() } },10) })();