您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adjustable key macro for split/feed with customizable keys that save & load automatically, including Big Split Macro (Space → Quad order). Prevents activation while typing.
// ==UserScript== // @name Snay.io Split/Feed Macro // @namespace http://tampermonkey.net/ // @version 3.4 // @description Adjustable key macro for split/feed with customizable keys that save & load automatically, including Big Split Macro (Space → Quad order). Prevents activation while typing. // @author GravityG // @match https://www.snay.io/* // @grant none // ==/UserScript== (function() { 'use strict'; let gameKeys = {}; let intervalId = null; let inputFocused = false; // Track if user is typing // Load saved settings or set defaults let macroSpeed = localStorage.getItem('macroSpeed') ? parseInt(localStorage.getItem('macroSpeed')) : 1000; let macroDelay = localStorage.getItem('macroDelay') ? parseInt(localStorage.getItem('macroDelay')) : 20; function getStoredKey(key, defaultKey) { return localStorage.getItem(key) || defaultKey; } function getUpdatedKeys() { return { macroKey: getStoredKey('macroKey', 'F'), macroActionKey: getStoredKey('macroActionKey', 'E'), quadSplitKey: getStoredKey('quadSplitKey', 'R'), secondaryMacroKey: getStoredKey('secondaryMacroKey', 'G'), bigSplitKey: getStoredKey('bigSplitKey', 'S') }; } let keys = getUpdatedKeys(); function triggerMacro() { if (inputFocused) return; // Prevent activation while typing let macroEventDown = new KeyboardEvent('keydown', { key: keys.macroActionKey, code: `Key${keys.macroActionKey}` }); let quadEventDown = new KeyboardEvent('keydown', { key: keys.quadSplitKey, code: `Key${keys.quadSplitKey}` }); let macroEventUp = new KeyboardEvent('keyup', { key: keys.macroActionKey, code: `Key${keys.macroActionKey}` }); let quadEventUp = new KeyboardEvent('keyup', { key: keys.quadSplitKey, code: `Key${keys.quadSplitKey}` }); window.dispatchEvent(macroEventDown); window.dispatchEvent(quadEventDown); setTimeout(() => { window.dispatchEvent(macroEventUp); window.dispatchEvent(quadEventUp); }, 50); } function triggerSecondaryMacro() { if (inputFocused) return; // Prevent activation while typing let spaceDown = new KeyboardEvent('keydown', { key: " ", code: "Space" }); let spaceUp = new KeyboardEvent('keyup', { key: " ", code: "Space" }); window.dispatchEvent(spaceDown); setTimeout(() => { window.dispatchEvent(spaceUp); setTimeout(triggerMacro, macroDelay); }, 20); } function triggerBigSplitMacro() { if (inputFocused) return; // Prevent activation while typing let spaceDown = new KeyboardEvent('keydown', { key: " ", code: "Space" }); let spaceUp = new KeyboardEvent('keyup', { key: " ", code: "Space" }); let quadDown = new KeyboardEvent('keydown', { key: keys.quadSplitKey, code: `Key${keys.quadSplitKey}` }); let quadUp = new KeyboardEvent('keyup', { key: keys.quadSplitKey, code: `Key${keys.quadSplitKey}` }); // Press Space Bar first window.dispatchEvent(spaceDown); setTimeout(() => { window.dispatchEvent(spaceUp); // After 20ms, press Quad Split setTimeout(() => { window.dispatchEvent(quadDown); setTimeout(() => window.dispatchEvent(quadUp), 50); }, 20); }, 50); } // Prevent macros while typing function preventMacroOnTyping() { document.addEventListener("focusin", (event) => { if (event.target.tagName === "INPUT" || event.target.tagName === "TEXTAREA") { inputFocused = true; // User is typing, disable macros console.log("Macros paused while typing."); } }); document.addEventListener("focusout", () => { inputFocused = false; // User finished typing, re-enable macros console.log("Macros reactivated."); }); } window.addEventListener('keydown', function(event) { keys = getUpdatedKeys(); if (inputFocused) return; // Prevent activation while typing if (event.key.toUpperCase() === keys.macroKey && !gameKeys[keys.macroKey]) { gameKeys[keys.macroKey] = true; event.preventDefault(); triggerMacro(); intervalId = setInterval(triggerMacro, macroSpeed); } if (event.key.toUpperCase() === keys.secondaryMacroKey) { event.preventDefault(); triggerSecondaryMacro(); } if (event.key.toUpperCase() === keys.bigSplitKey) { event.preventDefault(); triggerBigSplitMacro(); } }); window.addEventListener('keyup', function(event) { keys = getUpdatedKeys(); if (event.key.toUpperCase() === keys.macroKey) { gameKeys[keys.macroKey] = false; clearInterval(intervalId); intervalId = null; } }); function waitForModMenu() { const modMenu = document.getElementById('modmenu'); if (modMenu) { createQuickSettings(modMenu); } else { setTimeout(waitForModMenu, 500); } } function createQuickSettings(modMenu) { let settingsContainer = document.createElement('div'); settingsContainer.style.border = "0.1vw solid yellowgreen"; settingsContainer.style.width = "100%"; settingsContainer.innerHTML = ` <li style="display: flex; align-items: center;"> <span style="font-size: 1.5vw; color: white;">Split Macro</span> </li> <li style="display: flex; align-items: center; width: 90%;"> <input type="range" min="0" max="600" value="${macroSpeed}" class="slider" id="feedsplitmacro"> <output id="feedsplitmacroValue">${macroSpeed}</output> </li> <li style="display: flex; align-items: center; margin-top: 10px;"> <span style="font-size: 1.5vw; color: white;">In Split Macro</span> </li> <li style="display: flex; align-items: center; width: 90%;"> <input type="range" min="0" max="300" value="${macroDelay}" class="slider" id="macroDelaySlider"> <output id="macroDelaySliderValue">${macroDelay}</output> </li> ${createKeyButton("Split/Macro Key:", "macroKeyButton", keys.macroKey)} ${createKeyButton("In Split Key:", "secondaryMacroKeyButton", keys.secondaryMacroKey)} ${createKeyButton("Big Split Key:", "bigSplitKeyButton", keys.bigSplitKey)} ${createKeyButton("Macro Action Key:", "macroActionKeyButton", keys.macroActionKey)} ${createKeyButton("Quad Action Key:", "quadSplitKeyButton", keys.quadSplitKey)} `; modMenu.appendChild(settingsContainer); document.getElementById('feedsplitmacro').addEventListener('input', function() { macroSpeed = parseInt(this.value); document.getElementById('feedsplitmacroValue').textContent = macroSpeed; localStorage.setItem('macroSpeed', macroSpeed); }); document.getElementById('macroDelaySlider').addEventListener('input', function() { macroDelay = parseInt(this.value); document.getElementById('macroDelaySliderValue').textContent = macroDelay; localStorage.setItem('macroDelay', macroDelay); }); setupKeybinds(); } function createKeyButton(label, id, key) { return ` <li style="display: flex; align-items: center; width: 90%; margin-top: 10px;"> <span style="font-size: 1.2vw; color: white;">${label}</span> <button id="${id}" style="margin-left: 0.5vw; padding: 0.8vw; font-size: 1.2vw; background: limegreen; color: white; border: none; cursor: pointer; border-radius: 5px;">${key}</button> </li> `; } function setupKeybinds() { ['macroKey', 'macroActionKey', 'quadSplitKey', 'secondaryMacroKey', 'bigSplitKey'].forEach(key => { setupKeyChange(`${key}Button`, key); }); } function setupKeyChange(buttonId, storageKey) { document.getElementById(buttonId).addEventListener('click', function() { this.textContent = "Press a key..."; document.addEventListener('keydown', function setKey(event) { localStorage.setItem(storageKey, event.key.toUpperCase()); document.getElementById(buttonId).textContent = event.key.toUpperCase(); keys = getUpdatedKeys(); document.removeEventListener('keydown', setKey); }); }); } preventMacroOnTyping(); // Call function to prevent macros while typing waitForModMenu(); })();