// ==UserScript==
// @license MIT
// @name Overheaven Line+FPS
// @namespace https://gota.io/
// @version 2.7.0
// @description Mass feed + line macros with FPS uncap and full keyboard support
// @author Overheaven | @kazura667 (Discord)
// @match https://gota.io/web*
// @grant none
// @run-at document-end
// @note If you have any trouble with the script feel free to dm me, if you can't line right use the "Freeze mouse" option. A tutorial have been posted on @Overheaven Gota channel.
// ==/UserScript==
(function() {
'use strict';
if (window.top !== window.self) return;
// ---------- Config ----------
const defaultConfig = {
enabled: true,
removeFpsLimit: true,
fastFeedKey: 'F',
lineUpKey: 'W',
lineDownKey: 'S',
lineLeftKey: 'A',
lineRightKey: 'D',
diagonalUpLeftKey: 'Q',
diagonalUpRightKey: 'E',
diagonalDownLeftKey: 'Z',
diagonalDownRightKey: 'C',
fastFeedSpeed: 50,
lineSpeed: 30
};
let config = loadConfig();
function loadConfig() {
try {
const raw = localStorage.getItem('gota-macros-config');
if (!raw) return { ...defaultConfig };
return { ...defaultConfig, ...JSON.parse(raw) };
} catch {
return { ...defaultConfig };
}
}
function saveConfig() {
localStorage.setItem('gota-macros-config', JSON.stringify(config));
}
// ---------- State ----------
let isFastFeeding = false;
let isDrawingLine = false;
let fastFeedInterval = null;
let lineInterval = null;
let lastMouse = { x: 0, y: 0 };
let panel = null;
let currentLineDirection = null;
let lineModeIndicator = null;
document.addEventListener('mousemove', function(e) {
lastMouse.x = e.clientX;
lastMouse.y = e.clientY;
}, { passive: true });
// ---------- FPS Uncap ----------
if (config.removeFpsLimit) {
const originalRAF = window.requestAnimationFrame;
let lastTime = 0;
window.requestAnimationFrame = function(callback) {
const now = performance.now();
const deltaTime = now - lastTime;
lastTime = now;
return setTimeout(() => {
callback(now);
}, Math.max(0, 8 - deltaTime));
};
const canvas = document.querySelector('canvas');
if (canvas) {
canvas.style.imageRendering = 'pixelated';
canvas.style.animationDuration = '0s';
}
const originalSetTimeout = window.setTimeout;
window.setTimeout = function(callback, delay) {
if (delay < 16) delay = 1;
return originalSetTimeout(callback, delay);
};
}
// ---------- Create Panel First ----------
function createPanel() {
panel = document.createElement('div');
panel.id = 'gota-macros-panel';
panel.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 450px;
max-height: 85vh;
background: rgba(0,0,0,0.95);
color: white;
padding: 25px;
border-radius: 15px;
font-family: Arial, sans-serif;
font-size: 14px;
z-index: 100000;
display: none;
backdrop-filter: blur(10px);
border: 3px solid #f44336;
box-shadow: 0 10px 40px rgba(0,0,0,0.6);
overflow-y: auto;
`;
panel.innerHTML = `
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;">
<h2 style="margin:0;color:#f44336;font-size:22px;text-shadow: 0 2px 4px rgba(0,0,0,0.5);">Overheaven Line+FPS</h2>
<button id="gm-close" style="background:#f44336;border:none;color:#fff;padding:8px 15px;border-radius:8px;cursor:pointer;font-weight:bold;font-size:16px;">✕</button>
</div>
<div style="margin-bottom:20px;">
<label style="display:flex;align-items:center;gap:10px;font-size:16px;">
<input type="checkbox" id="gm-enabled" ${config.enabled ? 'checked' : ''} style="transform:scale(1.3);">
<span style="font-weight:bold;">Enable Macros</span>
</label>
</div>
<div style="margin-bottom:25px;">
<label style="display:flex;align-items:center;gap:10px;font-size:16px;">
<input type="checkbox" id="gm-fps" ${config.removeFpsLimit ? 'checked' : ''} style="transform:scale(1.3);">
<span style="font-weight:bold;">Remove FPS limit (120+ FPS)</span>
</label>
</div>
<div style="border-top:3px solid #f44336;margin:20px 0;padding-top:20px;">
<h3 style="margin:0 0 15px 0;color:#f44336;font-size:18px;text-shadow: 0 1px 2px rgba(0,0,0,0.5);">Mass Feed</h3>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:15px;margin-bottom:20px;">
<div>
<label style="display:block;margin-bottom:8px;font-size:13px;color:#ccc;font-weight:bold;">Key</label>
<input type="text" id="gm-k-fast" value="${config.fastFeedKey}" maxlength="1" style="width:100%;height:36px;text-align:center;border-radius:8px;border:2px solid #f44336;background:#222;color:#fff;font-size:16px;font-weight:bold;">
</div>
<div>
<label style="display:block;margin-bottom:8px;font-size:13px;color:#ccc;font-weight:bold;">Speed (ms)</label>
<input type="number" id="gm-fast-speed" value="${config.fastFeedSpeed}" min="10" max="200" style="width:100%;height:36px;text-align:center;border-radius:8px;border:2px solid #f44336;background:#222;color:#fff;font-size:16px;font-weight:bold;">
</div>
</div>
</div>
<div style="border-top:3px solid #f44336;margin:20px 0;padding-top:20px;">
<h3 style="margin:0 0 15px 0;color:#f44336;font-size:18px;text-shadow: 0 1px 2px rgba(0,0,0,0.5);">Lines</h3>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:20px;">
<div>
<label style="display:block;margin-bottom:5px;font-size:12px;color:#ccc;font-weight:bold;">Up</label>
<input type="text" id="gm-k-up" value="${config.lineUpKey}" maxlength="1" style="width:100%;height:32px;text-align:center;border-radius:6px;border:2px solid #f44336;background:#222;color:#fff;font-size:14px;font-weight:bold;">
</div>
<div>
<label style="display:block;margin-bottom:5px;font-size:12px;color:#ccc;font-weight:bold;">Down</label>
<input type="text" id="gm-k-down" value="${config.lineDownKey}" maxlength="1" style="width:100%;height:32px;text-align:center;border-radius:6px;border:2px solid #f44336;background:#222;color:#fff;font-size:14px;font-weight:bold;">
</div>
<div>
<label style="display:block;margin-bottom:5px;font-size:12px;color:#ccc;font-weight:bold;">Left</label>
<input type="text" id="gm-k-left" value="${config.lineLeftKey}" maxlength="1" style="width:100%;height:32px;text-align:center;border-radius:6px;border:2px solid #f44336;background:#222;color:#fff;font-size:14px;font-weight:bold;">
</div>
<div>
<label style="display:block;margin-bottom:5px;font-size:12px;color:#ccc;font-weight:bold;">Right</label>
<input type="text" id="gm-k-right" value="${config.lineRightKey}" maxlength="1" style="width:100%;height:32px;text-align:center;border-radius:6px;border:2px solid #f44336;background:#222;color:#fff;font-size:14px;font-weight:bold;">
</div>
<div>
<label style="display:block;margin-bottom:5px;font-size:12px;color:#ccc;font-weight:bold;">Up-Left</label>
<input type="text" id="gm-k-upleft" value="${config.diagonalUpLeftKey}" maxlength="1" style="width:100%;height:32px;text-align:center;border-radius:6px;border:2px solid #f44336;background:#222;color:#fff;font-size:14px;font-weight:bold;">
</div>
<div>
<label style="display:block;margin-bottom:5px;font-size:12px;color:#ccc;font-weight:bold;">Up-Right</label>
<input type="text" id="gm-k-upright" value="${config.diagonalUpRightKey}" maxlength="1" style="width:100%;height:32px;text-align:center;border-radius:6px;border:2px solid #f44336;background:#222;color:#fff;font-size:14px;font-weight:bold;">
</div>
<div>
<label style="display:block;margin-bottom:5px;font-size:12px;color:#ccc;font-weight:bold;">Down-Left</label>
<input type="text" id="gm-k-downleft" value="${config.diagonalDownLeftKey}" maxlength="1" style="width:100%;height:32px;text-align:center;border-radius:6px;border:2px solid #f44336;background:#222;color:#fff;font-size:14px;font-weight:bold;">
</div>
<div>
<label style="display:block;margin-bottom:5px;font-size:12px;color:#ccc;font-weight:bold;">Down-Right</label>
<input type="text" id="gm-k-downright" value="${config.diagonalDownRightKey}" maxlength="1" style="width:100%;height:32px;text-align:center;border-radius:6px;border:2px solid #f44336;background:#222;color:#fff;font-size:14px;font-weight:bold;">
</div>
</div>
<div style="margin-top:15px;">
<label style="display:block;margin-bottom:8px;font-size:13px;color:#ccc;font-weight:bold;">Line Speed (ms)</label>
<input type="number" id="gm-line-speed" value="${config.lineSpeed}" min="10" max="100" style="width:140px;height:36px;text-align:center;border-radius:8px;border:2px solid #f44336;background:#222;color:#fff;font-size:16px;font-weight:bold;">
</div>
</div>
<div style="display:flex;justify-content:space-between;gap:15px;margin-top:25px;">
<button id="gm-reset" style="background:#666;border:none;color:#fff;padding:10px 20px;border-radius:8px;cursor:pointer;font-weight:bold;font-size:14px;">Reset</button>
<button id="gm-save" style="background:#f44336;border:none;color:#fff;padding:10px 20px;border-radius:8px;cursor:pointer;font-weight:bold;font-size:14px;">Save & Close</button>
</div>
<div style="margin-top:25px;font-size:13px;color:#aaa;text-align:center;border-top:2px solid #f44336;padding-top:15px;line-height:1.6;">
<div style="font-size:16px;color:#f44336;font-weight:bold;margin-bottom:8px;">
OVERHEAVEN LINE+FPS 🔥
</div>
<div style="font-size:14px;color:#fff;margin-bottom:5px;">
<strong>Created by:</strong> <span style="color:#f44336;font-weight:bold;">Overheaven</span>
</div>
<div style="font-size:14px;color:#fff;margin-bottom:5px;">
<strong>Discord:</strong> <span style="color:#f44336;font-weight:bold;">@kazura667</span>
</div>
<div style="font-size:12px;color:#888;margin-top:10px;">
Press <strong style="color:#f44336;">Ctrl+M</strong> to toggle menu<br>
Supports ALL keyboard keys including numbers!
</div>
</div>
`;
document.body.appendChild(panel);
// Panel event handlers
panel.querySelector('#gm-close').addEventListener('click', () => {
panel.style.display = 'none';
});
// Key input handlers - Support ALL keys including numbers
const keyIds = ['gm-k-fast','gm-k-up','gm-k-down','gm-k-left','gm-k-right','gm-k-upleft','gm-k-upright','gm-k-downleft','gm-k-downright'];
keyIds.forEach(id => {
const input = panel.querySelector('#' + id);
input.addEventListener('keydown', (e) => {
e.preventDefault();
let key = e.key;
// Handle special keys
if (e.key === ' ') key = 'SPACE';
if (e.key === 'Enter') key = 'ENTER';
if (e.key === 'Tab') key = 'TAB';
if (e.key === 'Escape') key = 'ESC';
if (e.key === 'ArrowUp') key = 'UP';
if (e.key === 'ArrowDown') key = 'DOWN';
if (e.key === 'ArrowLeft') key = 'LEFT';
if (e.key === 'ArrowRight') key = 'RIGHT';
if (e.key === 'Shift') key = 'SHIFT';
if (e.key === 'Control') key = 'CTRL';
if (e.key === 'Alt') key = 'ALT';
// Handle function keys
if (e.key.startsWith('F') && e.key.length === 2) key = e.key;
// Handle numbers
if (e.key >= '0' && e.key <= '9') key = e.key;
// Handle letters
if (e.key.length === 1) key = e.key.toUpperCase();
input.value = key;
});
input.addEventListener('input', () => {
input.value = (input.value || '').slice(0,1).toUpperCase();
});
});
panel.querySelector('#gm-save').addEventListener('click', () => {
config.enabled = panel.querySelector('#gm-enabled').checked;
config.removeFpsLimit = panel.querySelector('#gm-fps').checked;
config.fastFeedKey = panel.querySelector('#gm-k-fast').value || defaultConfig.fastFeedKey;
config.fastFeedSpeed = Math.max(10, Math.min(200, parseInt(panel.querySelector('#gm-fast-speed').value) || defaultConfig.fastFeedSpeed));
config.lineUpKey = panel.querySelector('#gm-k-up').value || defaultConfig.lineUpKey;
config.lineDownKey = panel.querySelector('#gm-k-down').value || defaultConfig.lineDownKey;
config.lineLeftKey = panel.querySelector('#gm-k-left').value || defaultConfig.lineLeftKey;
config.lineRightKey = panel.querySelector('#gm-k-right').value || defaultConfig.lineRightKey;
config.diagonalUpLeftKey = panel.querySelector('#gm-k-upleft').value || defaultConfig.diagonalUpLeftKey;
config.diagonalUpRightKey = panel.querySelector('#gm-k-upright').value || defaultConfig.diagonalUpRightKey;
config.diagonalDownLeftKey = panel.querySelector('#gm-k-downleft').value || defaultConfig.diagonalDownLeftKey;
config.diagonalDownRightKey = panel.querySelector('#gm-k-downright').value || defaultConfig.diagonalDownRightKey;
config.lineSpeed = Math.max(10, Math.min(100, parseInt(panel.querySelector('#gm-line-speed').value) || defaultConfig.lineSpeed));
saveConfig();
panel.style.display = 'none';
});
panel.querySelector('#gm-reset').addEventListener('click', () => {
if (confirm('Reset all settings to defaults?')) {
config = { ...defaultConfig };
saveConfig();
location.reload();
}
});
panel.addEventListener('click', (e) => e.stopPropagation());
}
// ---------- In-Game Button (Black & Red) ----------
function createInGameUI() {
const checkForGameUI = setInterval(() => {
const mainBottom = document.querySelector('.main-bottom-left, .main-bottom-right');
if (!mainBottom) return;
clearInterval(checkForGameUI);
const btn = document.createElement('button');
btn.id = 'gota-macros-btn';
btn.className = 'gota-btn bottom-btn';
btn.style.cssText = `
position: relative;
margin: 5px 3px;
float: none;
border-radius: 3px 10px 10px 3px;
white-space: nowrap;
overflow: hidden;
background: linear-gradient(135deg, #000, #333);
border: 2px solid #f44336;
color: #f44336;
font-weight: bold;
text-shadow: 0 1px 2px rgba(0,0,0,0.5);
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
cursor: pointer;
`;
btn.innerHTML = 'Overheaven';
btn.title = 'Click to configure macros (Ctrl+M)';
btn.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('Overheaven button clicked!');
if (panel) {
panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
}
});
mainBottom.appendChild(btn);
console.log('Overheaven button added to game UI');
}, 100);
}
// ---------- Macros ----------
function startFastFeed() {
if (!config.enabled || isFastFeeding) return;
isFastFeeding = true;
console.log('Starting mass feed');
fastFeedInterval = setInterval(() => {
if (!config.enabled) return;
// Use 'w' key for mass ejection (not space for splitting)
const evt = new KeyboardEvent('keydown', { key: 'w', code: 'KeyW', keyCode: 87, which: 87, bubbles: true });
document.dispatchEvent(evt);
}, config.fastFeedSpeed);
}
function stopFastFeed() {
isFastFeeding = false;
if (fastFeedInterval) { clearInterval(fastFeedInterval); fastFeedInterval = null; }
console.log('Stopped mass feed');
}
// ---------- Line Mode Indicator ----------
function showLineModeIndicator(direction) {
hideLineModeIndicator();
lineModeIndicator = document.createElement('div');
lineModeIndicator.id = 'lineModeIndicator';
lineModeIndicator.style.cssText = `
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.9);
color: #f44336;
padding: 10px 20px;
border-radius: 5px;
font-family: Arial, sans-serif;
font-size: 16px;
font-weight: bold;
z-index: 10000;
pointer-events: none;
border: 2px solid #f44336;
`;
lineModeIndicator.textContent = `LINE MODE: ${direction.toUpperCase()}`;
document.body.appendChild(lineModeIndicator);
}
function hideLineModeIndicator() {
if (lineModeIndicator) {
lineModeIndicator.remove();
lineModeIndicator = null;
}
}
// ---------- Line Splitting (FIXED - Based on Agario Train Line Controller approach) ----------
function moveMouse(X, Y) {
const canvas = document.querySelector('canvas');
if (!canvas) return;
// Use the same approach as the working script
const mouseMoveEvent = new MouseEvent('mousemove', {
clientX: X,
clientY: Y,
bubbles: true,
cancelable: true,
view: window
});
canvas.dispatchEvent(mouseMoveEvent);
}
function startLine(direction) {
if (!config.enabled || isDrawingLine) return;
isDrawingLine = true;
currentLineDirection = direction;
console.log('Starting line in direction:', direction);
// Show line mode indicator
showLineModeIndicator(direction);
// Calculate screen dimensions
const screenWidth = window.innerWidth;
const screenHeight = window.innerHeight;
const centerX = screenWidth / 2;
const centerY = screenHeight / 2;
const squareSize = Math.min(screenWidth, screenHeight);
const halfSquareSize = squareSize / 2;
// Calculate target position based on direction (like the working script)
let targetX, targetY;
switch (direction) {
case 'up':
targetX = centerX;
targetY = centerY - halfSquareSize;
break;
case 'down':
targetX = centerX;
targetY = centerY + halfSquareSize;
break;
case 'left':
targetX = centerX - halfSquareSize;
targetY = centerY;
break;
case 'right':
targetX = centerX + halfSquareSize;
targetY = centerY;
break;
case 'upLeft':
targetX = centerX - halfSquareSize;
targetY = centerY - halfSquareSize;
break;
case 'upRight':
targetX = centerX + halfSquareSize;
targetY = centerY - halfSquareSize;
break;
case 'downLeft':
targetX = centerX - halfSquareSize;
targetY = centerY + halfSquareSize;
break;
case 'downRight':
targetX = centerX + halfSquareSize;
targetY = centerY + halfSquareSize;
break;
default:
return;
}
// Move mouse to calculated position
moveMouse(targetX, targetY);
}
function stopLine() {
if (!isDrawingLine) return;
isDrawingLine = false;
currentLineDirection = null;
// Hide line mode indicator
hideLineModeIndicator();
console.log('Stopped line drawing');
}
// ---------- Input handling with chat protection (FIXED) ----------
function isKey(cfgKey, e) {
if (!cfgKey) return false;
// Don't trigger macros when typing in chat
const chatInput = document.querySelector('#chat-input, input[type="text"], textarea');
if (chatInput && chatInput === document.activeElement) {
return false;
}
let key = e.key;
// Handle special keys
if (e.key === ' ') key = 'SPACE';
if (e.key === 'Enter') key = 'ENTER';
if (e.key === 'Tab') key = 'TAB';
if (e.key === 'Escape') key = 'ESC';
if (e.key === 'ArrowUp') key = 'UP';
if (e.key === 'ArrowDown') key = 'DOWN';
if (e.key === 'ArrowLeft') key = 'LEFT';
if (e.key === 'ArrowRight') key = 'RIGHT';
if (e.key === 'Shift') key = 'SHIFT';
if (e.key === 'Control') key = 'CTRL';
if (e.key === 'Alt') key = 'ALT';
// Handle function keys
if (e.key.startsWith('F') && e.key.length === 2) key = e.key;
// Handle numbers and letters
if (e.key.length === 1) key = e.key.toUpperCase();
return key === cfgKey.toUpperCase();
}
document.addEventListener('keydown', function(e) {
if (e.ctrlKey && e.key.toLowerCase() === 'm') {
e.preventDefault();
if (panel) {
panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
}
return;
}
if (!config.enabled) return;
// Check if we should start a new line direction
const lineKeys = {
[config.lineUpKey]: 'up',
[config.lineDownKey]: 'down',
[config.lineLeftKey]: 'left',
[config.lineRightKey]: 'right',
[config.diagonalUpLeftKey]: 'upLeft',
[config.diagonalUpRightKey]: 'upRight',
[config.diagonalDownLeftKey]: 'downLeft',
[config.diagonalDownRightKey]: 'downRight'
};
// Handle fast feed
if (isKey(config.fastFeedKey, e)) {
e.preventDefault();
isFastFeeding ? stopFastFeed() : startFastFeed();
return;
}
// Handle line keys
for (const [key, direction] of Object.entries(lineKeys)) {
if (isKey(key, e)) {
e.preventDefault();
// Hold mode: start line
stopLine(); // Stop any current line first
startLine(direction);
return;
}
}
});
document.addEventListener('keyup', function(e) {
if (!config.enabled) return;
// Only stop if the key matches current direction
const lineKeys = {
[config.lineUpKey]: 'up',
[config.lineDownKey]: 'down',
[config.lineLeftKey]: 'left',
[config.lineRightKey]: 'right',
[config.diagonalUpLeftKey]: 'upLeft',
[config.diagonalUpRightKey]: 'upRight',
[config.diagonalDownLeftKey]: 'downLeft',
[config.diagonalDownRightKey]: 'downRight'
};
for (const [key, direction] of Object.entries(lineKeys)) {
if (isKey(key, e) && currentLineDirection === direction) {
stopLine();
return;
}
}
});
document.addEventListener('click', function(e) {
if (panel && panel.style.display === 'block' && !panel.contains(e.target)) {
panel.style.display = 'none';
}
});
// ---------- Boot ----------
createPanel();
createInGameUI();
console.log(' OVERHEAVEN LINE+FPS loaded! By Overheaven | @kazura667 (Discord) ��');
})();