- // ==UserScript==
- // @name New Jacks Agario Mod
- // @namespace All in one mod, doesnt add cheats.
- // @version 1.1
- // @description Enhances Agar.io with custom controls, advanced features, and skin-maker drag-and-drop
- // @author 𝓝𝑒ⓦ 𝓙ⓐ¢𝓀🕹️
- // @match https://agar.io/*
- // @grant none
- // @license MIT
- // @run-at document-start
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- // Remove background image
- const originalDrawImage = CanvasRenderingContext2D.prototype.drawImage;
- CanvasRenderingContext2D.prototype.drawImage = function (img) {
- if (img && img.src === "https://agar.io/img/background.png") {
- return;
- }
- originalDrawImage.apply(this, arguments);
- };
-
- window.addEventListener('DOMContentLoaded', function() {
- document.documentElement.removeAttribute('style');
- const adDiv = document.querySelector('#agar-io_970x90');
- if (adDiv) {
- adDiv.remove();
- }
- initAgarioMod();
- observeTargetContainer();
- initRussiaToUkraine();
- });
-
- //------------------------------------------------------------------
- // 1) Main Agar.io Mod
- //------------------------------------------------------------------
- function initAgarioMod() {
- const CONFIG = {
- enableMod: true,
- leftMouseAction: 'macroFeed', // "none" | "singleFeed" | "macroFeed" | "split"
- rightMouseAction: 'split',
- singleFeedKey: 'w',
- macroFeedKey: 'm',
- doubleSplitKey: 'd',
- tripleSplitKey: 't',
- quadSplitKey: 'q',
- straightLineKey: 'e',
- zoomOutKey: '-',
- zoomInKey: '=',
- acidModeKey: 'a',
- skinSwitcherKey: 's',
- toggleUIKey: 'h',
- pauseMovementKey: 'p',
- enableGamepad: false,
- enableAcidMode: false,
- enableMinimap: true,
- enableCustomSkin: true,
- customSkinUrl: '',
- feedRate: 50,
- splitDelay: 50,
- gamepadSplit: 0,
- gamepadFeed: 1,
- gamepadDoubleSplit: 2,
- gamepadTripleSplit: 3,
- gamepadAcidMode: 9,
- gamepadStraightLine: 10,
- };
-
- let isMacroFeeding = false;
- let macroFeedInterval = null;
- let gameCanvas = null;
- let startingMousePosition = { x: 0, y: 0 };
- let currentMousePosition = { x: 0, y: 0 };
- let isStraightLineMode = false;
- let originalSkin = '';
- let modUIVisible = false;
- let isPaused = false;
- let connectedGamepads = [];
- let lastGamepadState = {};
- let isRemappingGamepad = false;
- let remappingButton = null;
- let showControlsButton = null;
- let mainOverlay = null;
-
- function initMod() {
- console.log('Initializing New Jacks Agario Mod...');
- createShowControlsButton();
- createMainOverlay();
- setTimeout(findGameCanvas, 2000);
- document.addEventListener('keydown', handleKeyDown);
- document.addEventListener('keyup', handleKeyUp);
- captureOriginalSkin();
- increaseNickLimit();
- console.log('Mod initialized successfully!');
- }
-
- function createShowControlsButton() {
- showControlsButton = document.createElement('button');
- showControlsButton.id = 'show-controls-button';
- showControlsButton.textContent = 'Show Controls';
- showControlsButton.style.cssText = `
- position: fixed;
- top: 10px;
- left: 10px;
- z-index: 99999;
- padding: 5px 10px;
- background-color: #54c800;
- color: #fff;
- border: none;
- border-radius: 5px;
- cursor: pointer;
- font-family: Arial, sans-serif;
- transition: background-color 0.2s ease;
- `;
- showControlsButton.addEventListener('mouseover', () => {
- showControlsButton.style.backgroundColor = '#347f01';
- });
- showControlsButton.addEventListener('mouseout', () => {
- showControlsButton.style.backgroundColor = '#54c800';
- });
- showControlsButton.addEventListener('mousedown', () => {
- showControlsButton.style.backgroundColor = '#347f01';
- });
- showControlsButton.addEventListener('mouseup', () => {
- showControlsButton.style.backgroundColor = '#54c800';
- });
- showControlsButton.onclick = toggleMainOverlay;
- document.body.appendChild(showControlsButton);
- }
-
- function findGameCanvas() {
- const canvases = document.getElementsByTagName('canvas');
- if (canvases.length > 0) {
- for (let i = 0; i < canvases.length; i++) {
- if (canvases[i].width > 500 && canvases[i].height > 500) {
- gameCanvas = canvases[i];
- break;
- }
- }
- if (gameCanvas) {
- console.log('Game canvas found!');
- gameCanvas.addEventListener('mousedown', handleMouseDown);
- gameCanvas.addEventListener('mouseup', handleMouseUp);
- gameCanvas.addEventListener('contextmenu', (e) => e.preventDefault() );
- gameCanvas.addEventListener('mousemove', (e) => {
- currentMousePosition.x = e.clientX;
- currentMousePosition.y = e.clientY;
- if (isStraightLineMode) {
- applyLineConstraint();
- }
- });
- showNotification('Advanced Controls Active! Press H for help or to toggle UI.');
- } else {
- console.log('Game canvas not found, retrying...');
- setTimeout(findGameCanvas, 2000);
- }
- } else {
- console.log('No canvases found, retrying...');
- setTimeout(findGameCanvas, 2000);
- }
- }
-
- function handleMouseDown(e) {
- if (!CONFIG.enableMod) return;
- if (isPaused) return;
- if (e.button === 0) {
- doMouseAction(CONFIG.leftMouseAction, 'down');
- } else if (e.button === 2) {
- doMouseAction(CONFIG.rightMouseAction, 'down');
- }
- }
- function handleMouseUp(e) {
- if (!CONFIG.enableMod) return;
- if (isPaused) return;
- if (e.button === 0) {
- doMouseAction(CONFIG.leftMouseAction, 'up');
- } else if (e.button === 2) {
- doMouseAction(CONFIG.rightMouseAction, 'up');
- }
- }
-
- function doMouseAction(action, phase) {
- if (action === 'none') {
- return;
- }
- else if (action === 'singleFeed') {
- if (phase === 'down') {
- window.core.eject();
- }
- }
- else if (action === 'macroFeed') {
- if (phase === 'down') {
- startMacroFeed();
- } else if (phase === 'up') {
- stopMacroFeed();
- }
- }
- else if (action === 'split') {
- if (phase === 'down') {
- window.core.split();
- }
- }
- }
-
- function handleKeyDown(e) {
- if (e.key.toLowerCase() === CONFIG.toggleUIKey) {
- toggleMainOverlay();
- return;
- }
- if (!CONFIG.enableMod) return;
- if (isPaused) { }
- switch (e.key.toLowerCase()) {
- case CONFIG.singleFeedKey:
- window.core.eject();
- break;
- case CONFIG.macroFeedKey:
- startMacroFeed();
- break;
- case CONFIG.doubleSplitKey:
- performMultiSplit(2);
- break;
- case CONFIG.tripleSplitKey:
- performMultiSplit(3);
- break;
- case CONFIG.quadSplitKey:
- performMultiSplit(4);
- break;
- case CONFIG.straightLineKey:
- toggleStraightLineMode();
- break;
- case CONFIG.zoomOutKey:
- window.core.playerZoom(0.8);
- break;
- case CONFIG.zoomInKey:
- window.core.playerZoom(1.2);
- break;
- case CONFIG.acidModeKey:
- toggleAcidMode();
- break;
- case CONFIG.skinSwitcherKey:
- openSkinSwitcherUI();
- break;
- case CONFIG.pauseMovementKey:
- isPaused = !isPaused;
- showNotification(isPaused ? 'Movement is paused.' : 'Movement unpaused.');
- break;
- }
- }
- function handleKeyUp(e) {
- if (!CONFIG.enableMod) return;
- if (e.key.toLowerCase() === CONFIG.macroFeedKey) {
- stopMacroFeed();
- }
- }
-
- function startMacroFeed() {
- if (isMacroFeeding) return;
- isMacroFeeding = true;
- showNotification('Macro feeding started');
- window.core.eject();
- macroFeedInterval = setInterval(() => {
- window.core.eject();
- }, CONFIG.feedRate);
- }
- function stopMacroFeed() {
- if (!isMacroFeeding) return;
- clearInterval(macroFeedInterval);
- isMacroFeeding = false;
- showNotification('Macro feeding stopped');
- }
-
- function performMultiSplit(count) {
- if (!window.core.playerHasCells || !window.core.playerHasCells()) {
- showNotification('Cannot split when dead');
- return;
- }
- showNotification(`${count}x Split`);
- for (let i = 0; i < count; i++) {
- setTimeout(() => {
- window.core.split();
- }, CONFIG.splitDelay * i);
- }
- }
-
- function toggleStraightLineMode() {
- isStraightLineMode = !isStraightLineMode;
- if (isStraightLineMode) {
- startingMousePosition.x = currentMousePosition.x;
- startingMousePosition.y = currentMousePosition.y;
- showNotification('Straight line mode ON');
- } else {
- showNotification('Straight line mode OFF');
- }
- }
- function applyLineConstraint() {
- if (!isStraightLineMode) return;
- const dx = currentMousePosition.x - startingMousePosition.x;
- const dy = currentMousePosition.y - startingMousePosition.y;
- const angle = Math.atan2(dy, dx);
- const snappedAngle = Math.round(angle / (Math.PI / 4)) * (Math.PI / 4);
- const distance = Math.sqrt(dx*dx + dy*dy);
- const newX = startingMousePosition.x + Math.cos(snappedAngle)*distance;
- const newY = startingMousePosition.y + Math.sin(snappedAngle)*distance;
- window.core.setTarget(newX, newY);
- }
-
- function increaseNickLimit() {
- const updateNickInput = () => {
- const nickInputs = document.querySelectorAll('input[id="nick"], input[placeholder="Nick"], input[maxlength="15"]');
- if (nickInputs.length > 0) {
- nickInputs.forEach(input => {
- input.setAttribute('maxlength', '50');
- });
- showNotification('Nickname limit increased to 50 characters');
- } else {
- setTimeout(updateNickInput, 2000);
- }
- };
- updateNickInput();
- try {
- const observer = new MutationObserver(mutations => {
- for (const mutation of mutations) {
- if (mutation.type === 'childList' && mutation.addedNodes.length) {
- for (const node of mutation.addedNodes) {
- if (node.nodeType === Node.ELEMENT_NODE) {
- const inputs = node.querySelectorAll ?
- node.querySelectorAll('input[id="nick"], input[placeholder="Nick"], input[maxlength="15"]') : [];
- if (
- node.tagName === 'INPUT' &&
- (node.id === 'nick' || node.placeholder === 'Nick' || node.getAttribute('maxlength') === '15')
- ) {
- node.setAttribute('maxlength', '50');
- }
- if (inputs.length > 0) {
- inputs.forEach(input => {
- input.setAttribute('maxlength', '50');
- });
- }
- }
- }
- }
- }
- });
- observer.observe(document.body, { childList: true, subtree: true });
- } catch (e) {
- console.error('Error setting up MutationObserver:', e);
- }
- }
-
- function showNotification(message) {
- let notification = document.getElementById('agario-mod-notification');
- if (!notification) {
- notification = document.createElement('div');
- notification.id = 'agario-mod-notification';
- notification.style.cssText = `
- position: absolute;
- top: 80px;
- left: 50%;
- transform: translateX(-50%);
- background-color: rgba(0, 0, 0, 0.7);
- color: white;
- padding: 10px 20px;
- border-radius: 5px;
- font-family: Arial, sans-serif;
- font-size: 16px;
- z-index: 1000;
- transition: opacity 0.5s;
- pointer-events: none;
- `;
- document.body.appendChild(notification);
- }
- notification.textContent = message;
- notification.style.opacity = '1';
- clearTimeout(notification.fadeTimeout);
- notification.fadeTimeout = setTimeout(() => {
- notification.style.opacity = '0';
- }, 2000);
- }
-
- function captureOriginalSkin() {
- if (window.core) {
- try {
- const observer = new MutationObserver((mutations, obs) => {
- const skinContainer = document.querySelector('#skin-preview');
- if (skinContainer) {
- const skinImg = skinContainer.querySelector('img');
- if (skinImg && skinImg.src) {
- originalSkin = skinImg.src;
- obs.disconnect();
- }
- }
- });
- observer.observe(document.body, { childList: true, subtree: true });
- try {
- const localData = localStorage.getItem('ogarioSettings');
- if (localData) {
- const settings = JSON.parse(localData);
- if (settings && settings.skin) {
- originalSkin = settings.skin;
- }
- }
- } catch (e) {
- console.warn('Failed to get skin from localStorage', e);
- }
- } catch (e) {
- console.warn('Failed to capture original skin', e);
- }
- }
- }
-
- function applyCustomSkin(url) {
- if (!window.core) return;
- try {
- if (!originalSkin) {
- captureOriginalSkin();
- }
- window.core.registerSkin(null, "customskin", url, 0, 0);
- window.core.loadSkin("customskin");
- CONFIG.customSkinUrl = url;
- CONFIG.enableCustomSkin = true;
- showNotification('Custom skin applied');
- } catch (e) {
- showNotification('Failed to apply skin: ' + e.message);
- console.error('Failed to apply skin:', e);
- }
- }
-
- function toggleCustomSkin() {
- CONFIG.enableCustomSkin = !CONFIG.enableCustomSkin;
- if (CONFIG.enableCustomSkin && CONFIG.customSkinUrl) {
- applyCustomSkin(CONFIG.customSkinUrl);
- } else {
- if (window.core) {
- if (originalSkin && originalSkin.startsWith('http')) {
- window.core.registerSkin(null, "originalskin", originalSkin, 0, 0);
- window.core.loadSkin("originalskin");
- showNotification('Restored original skin');
- } else if (originalSkin) {
- window.core.loadSkin(originalSkin);
- showNotification('Restored original skin');
- } else {
- window.core.loadSkin("");
- showNotification('Custom skin disabled');
- }
- }
- }
- }
-
- function loadSkinsFromStorage() {
- let data = localStorage.getItem('myCustomSkins');
- if (!data) return [];
- try {
- return JSON.parse(data);
- } catch(e) {
- console.error('Failed to parse myCustomSkins:', e);
- return [];
- }
- }
- function saveSkinsToStorage(arr) {
- localStorage.setItem('myCustomSkins', JSON.stringify(arr));
- }
-
- function openSkinSwitcherUI() {
- let existing = document.getElementById('skin-switcher-overlay');
- if (existing) {
- existing.style.display = 'flex';
- return;
- }
- const overlay = document.createElement('div');
- overlay.id = 'skin-switcher-overlay';
- overlay.style.cssText = `
- position: fixed;
- top: 10%;
- left: 10%;
- width: 640px;
- max-width: 90%;
- background-color: rgba(255, 255, 255, 0.9);
- border-radius: 8px;
- padding: 20px;
- z-index: 1000000;
- display: flex;
- flex-direction: column;
- box-shadow: 0 0 15px rgba(0,0,0,0.3);
- font-family: Arial, sans-serif;
- `;
- document.body.appendChild(overlay);
- const titleRow = document.createElement('div');
- titleRow.style.cssText = 'width: 100%; display: flex; justify-content: space-between; margin-bottom: 10px;';
- const titleH2 = document.createElement('h2');
- titleH2.textContent = 'Skin Switcher';
- titleH2.style.margin = '0';
- titleRow.appendChild(titleH2);
- const closeBtn = document.createElement('button');
- closeBtn.textContent = 'X';
- closeBtn.style.cssText = `
- background-color: #00d3ff;
- border: 1px solid #ff0000;
- color: #ff0000;
- font-size: 20px;
- font-weight: bold;
- cursor: pointer;
- padding: 0 8px;
- border-radius: 4px;
- transition: background-color 0.2s ease;
- `;
- closeBtn.onclick = () => {
- overlay.style.display = 'none';
- };
- titleRow.appendChild(closeBtn);
- overlay.appendChild(titleRow);
- const previewContainer = document.createElement('div');
- previewContainer.style.cssText = `
- position: relative;
- width: 200px;
- height: 200px;
- border-radius: 50%;
- overflow: hidden;
- margin: 10px auto 0 auto;
- display: flex;
- align-items: center;
- justify-content: center;
- background: #f0f0f0;
- `;
- overlay.appendChild(previewContainer);
- const previewImg = document.createElement('img');
- previewImg.style.cssText = `
- width: 100%;
- height: 100%;
- object-fit: cover;
- `;
- previewContainer.appendChild(previewImg);
- const arrowsContainer = document.createElement('div');
- arrowsContainer.style.cssText = `
- display: flex;
- justify-content: space-between;
- align-items: center;
- width: 200px;
- margin: 10px auto 0 auto;
- `;
- overlay.appendChild(arrowsContainer);
- const leftArrow = document.createElement('button');
- leftArrow.textContent = '◀';
- leftArrow.style.cssText = arrowButtonStyle();
- leftArrow.addEventListener('mouseover', () => {
- leftArrow.style.backgroundColor = '#347f01';
- });
- leftArrow.addEventListener('mouseout', () => {
- leftArrow.style.backgroundColor = '#54c800';
- });
- leftArrow.addEventListener('mousedown', () => {
- leftArrow.style.backgroundColor = '#347f01';
- });
- leftArrow.addEventListener('mouseup', () => {
- leftArrow.style.backgroundColor = '#54c800';
- });
- arrowsContainer.appendChild(leftArrow);
- const rightArrow = document.createElement('button');
- rightArrow.textContent = '▶';
- rightArrow.style.cssText = arrowButtonStyle();
- rightArrow.addEventListener('mouseover', () => {
- rightArrow.style.backgroundColor = '#347f01';
- });
- rightArrow.addEventListener('mouseout', () => {
- rightArrow.style.backgroundColor = '#54c800';
- });
- rightArrow.addEventListener('mousedown', () => {
- rightArrow.style.backgroundColor = '#347f01';
- });
- rightArrow.addEventListener('mouseup', () => {
- rightArrow.style.backgroundColor = '#54c800';
- });
- arrowsContainer.appendChild(rightArrow);
- const skinUrlLabel = document.createElement('div');
- skinUrlLabel.style.cssText = 'margin-top: 10px; text-align: center; font-style: italic; color: #333;';
- overlay.appendChild(skinUrlLabel);
- const urlInput = document.createElement('input');
- urlInput.type = 'text';
- urlInput.placeholder = 'https://i.imgur.com/skin.png';
- urlInput.style.cssText = `
- margin: 10px auto 0 auto;
- width: 80%;
- padding: 5px;
- border: 1px solid #ccc;
- border-radius: 3px;
- display: block;
- `;
- overlay.appendChild(urlInput);
- const buttonsContainer = document.createElement('div');
- buttonsContainer.style.cssText = 'display: flex; justify-content: space-around; margin-top: 10px;';
- overlay.appendChild(buttonsContainer);
- const addSkinBtn = document.createElement('button');
- addSkinBtn.textContent = 'Add Skin';
- addSkinBtn.style.cssText = buttonStyle();
- addSkinBtn.onclick = addSkin;
- buttonsContainer.appendChild(addSkinBtn);
- const useSkinBtn = document.createElement('button');
- useSkinBtn.textContent = 'Use This Skin';
- useSkinBtn.style.cssText = buttonStyle();
- useSkinBtn.onclick = useSkin;
- buttonsContainer.appendChild(useSkinBtn);
- const deleteSkinBtn = document.createElement('button');
- deleteSkinBtn.textContent = 'Delete Skin';
- deleteSkinBtn.style.cssText = `
- padding: 6px 12px;
- border: none;
- border-radius: 4px;
- background-color: #ff0000;
- color: #fff;
- cursor: pointer;
- transition: background-color 0.2s ease;
- `;
- deleteSkinBtn.addEventListener('mouseover', () => {
- deleteSkinBtn.style.backgroundColor = '#cc0000';
- });
- deleteSkinBtn.addEventListener('mouseout', () => {
- deleteSkinBtn.style.backgroundColor = '#ff0000';
- });
- deleteSkinBtn.addEventListener('mousedown', () => {
- deleteSkinBtn.style.backgroundColor = '#cc0000';
- });
- deleteSkinBtn.addEventListener('mouseup', () => {
- deleteSkinBtn.style.backgroundColor = '#ff0000';
- });
- deleteSkinBtn.onclick = deleteSkin;
- buttonsContainer.appendChild(deleteSkinBtn);
- let skins = loadSkinsFromStorage();
- let currentIndex = 0;
- function renderSkins() {
- if (skins.length === 0) {
- currentIndex = 0;
- previewImg.src = '';
- skinUrlLabel.textContent = 'No skins yet';
- } else {
- if (currentIndex >= skins.length) currentIndex = skins.length - 1;
- if (currentIndex < 0) currentIndex = 0;
- previewImg.src = skins[currentIndex];
- skinUrlLabel.textContent = skins[currentIndex];
- }
- }
- leftArrow.onclick = () => {
- if (skins.length > 0) {
- currentIndex = (currentIndex - 1 + skins.length) % skins.length;
- renderSkins();
- }
- };
- rightArrow.onclick = () => {
- if (skins.length > 0) {
- currentIndex = (currentIndex + 1) % skins.length;
- renderSkins();
- }
- };
- function addSkin() {
- const url = urlInput.value.trim();
- if (!url) return;
- skins.push(url);
- saveSkinsToStorage(skins);
- urlInput.value = '';
- currentIndex = skins.length - 1;
- renderSkins();
- }
- function useSkin() {
- if (!skins[currentIndex]) {
- alert('No skin selected!');
- return;
- }
- applyCustomSkin(skins[currentIndex]);
- overlay.style.display = 'none';
- }
- function deleteSkin() {
- if (skins.length === 0) {
- alert('No skins to delete!');
- return;
- }
- if (confirm('Are you sure you want to delete this skin?')) {
- skins.splice(currentIndex, 1);
- saveSkinsToStorage(skins);
- if (currentIndex >= skins.length) {
- currentIndex = skins.length - 1;
- }
- renderSkins();
- }
- }
- function arrowButtonStyle() {
- return `
- font-size: 24px;
- width: 40px;
- height: 40px;
- border-radius: 8px;
- cursor: pointer;
- border: none;
- background: #54c800;
- color: #fff;
- transition: background-color 0.2s ease;
- `;
- }
- function buttonStyle() {
- return `
- padding: 6px 12px;
- border: none;
- border-radius: 4px;
- background-color: #54c800;
- color: #fff;
- cursor: pointer;
- transition: background-color 0.2s ease;
- `;
- }
- renderSkins();
- }
-
- function createMainOverlay() {
- mainOverlay = document.createElement('div');
- mainOverlay.id = 'main-overlay';
- mainOverlay.style.cssText = `
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- width: 700px;
- max-width: 90%;
- background: #fff;
- border-radius: 8px;
- padding: 20px;
- z-index: 999999;
- display: block;
- box-shadow: 0 0 20px rgba(0,0,0,0.5);
- font-family: Arial, sans-serif;
- `;
- document.body.appendChild(mainOverlay);
- const titleBar = document.createElement('div');
- titleBar.style.cssText = 'display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;';
- const h2 = document.createElement('h2');
- h2.textContent = 'Advanced Controls';
- h2.style.margin = '0';
- titleBar.appendChild(h2);
- const closeBtn = document.createElement('button');
- closeBtn.textContent = 'X';
- closeBtn.style.cssText = `
- background-color: #00d3ff;
- border: 1px solid #ff0000;
- color: #ff0000;
- font-size: 18px;
- font-weight: bold;
- cursor: pointer;
- padding: 0 8px;
- border-radius: 4px;
- transition: background-color 0.2s ease;
- `;
- closeBtn.onclick = toggleMainOverlay;
- titleBar.appendChild(closeBtn);
- mainOverlay.appendChild(titleBar);
- const mouseActionsContainer = document.createElement('div');
- mouseActionsContainer.style.cssText = 'display: flex; flex-direction: column; gap: 5px; margin-bottom: 10px;';
- mouseActionsContainer.appendChild(createMouseActionRow('Left Mouse Action', 'leftMouseAction'));
- mouseActionsContainer.appendChild(createMouseActionRow('Right Mouse Action','rightMouseAction'));
- mainOverlay.appendChild(mouseActionsContainer);
- mainOverlay.appendChild(document.createElement('hr'));
- const columnsDiv = document.createElement('div');
- columnsDiv.style.cssText = 'display: flex; gap: 20px; margin-top: 10px;';
- const pcCol = document.createElement('div');
- pcCol.style.cssText = 'flex:1; background: rgba(255,255,255,0.6); padding: 10px; border-radius: 5px;';
- pcCol.innerHTML = '<h3>PC Hotkeys</h3>';
- const pcHotkeysDiv = document.createElement('div');
- pcCol.appendChild(pcHotkeysDiv);
- columnsDiv.appendChild(pcCol);
- const gpCol = document.createElement('div');
- gpCol.style.cssText = 'flex:1; background: rgba(255,255,255,0.6); padding: 10px; border-radius: 5px;';
- gpCol.innerHTML = '<h3>Gamepad</h3>';
- const gpDiv = document.createElement('div');
- gpCol.appendChild(gpDiv);
- columnsDiv.appendChild(gpCol);
- mainOverlay.appendChild(columnsDiv);
- const bottomDiv = document.createElement('div');
- bottomDiv.style.cssText = 'margin-top: 20px; display: flex; flex-wrap: wrap; gap: 10px;';
- const toggleModBtn = document.createElement('button');
- toggleModBtn.textContent = CONFIG.enableMod ? 'Disable Mod' : 'Enable Mod';
- toggleModBtn.style.cssText = buttonStyle();
- toggleModBtn.onclick = () => {
- CONFIG.enableMod = !CONFIG.enableMod;
- toggleModBtn.textContent = CONFIG.enableMod ? 'Disable Mod' : 'Enable Mod';
- if (!CONFIG.enableMod) {
- stopMacroFeed();
- isStraightLineMode = false;
- }
- };
- bottomDiv.appendChild(toggleModBtn);
- const acidBtn = document.createElement('button');
- acidBtn.textContent = CONFIG.enableAcidMode ? 'Acid Mode: ON' : 'Acid Mode: OFF';
- acidBtn.style.cssText = buttonStyle();
- acidBtn.onclick = () => {
- toggleAcidMode();
- acidBtn.textContent = CONFIG.enableAcidMode ? 'Acid Mode: ON' : 'Acid Mode: OFF';
- };
- bottomDiv.appendChild(acidBtn);
- const skinBtn = document.createElement('button');
- skinBtn.textContent = 'Change Skin';
- skinBtn.style.cssText = buttonStyle();
- skinBtn.onclick = openSkinSwitcherUI;
- bottomDiv.appendChild(skinBtn);
- const pauseBtn = document.createElement('button');
- pauseBtn.textContent = 'Pause Movement';
- pauseBtn.style.cssText = buttonStyle();
- pauseBtn.onclick = () => {
- isPaused = !isPaused;
- pauseBtn.textContent = isPaused ? 'Unpause Movement' : 'Pause Movement';
- showNotification(isPaused ? 'Movement is paused.' : 'Movement unpaused.');
- };
- bottomDiv.appendChild(pauseBtn);
- mainOverlay.appendChild(bottomDiv);
- buildPCHotkeysUI(pcHotkeysDiv);
- buildGamepadUI(gpDiv);
- mainOverlay.style.display = 'none';
-
- function createMouseActionRow(label, configKey) {
- const row = document.createElement('div');
- row.style.cssText = 'display: flex; align-items: center; margin-bottom: 5px;';
- const lbl = document.createElement('span');
- lbl.textContent = label + ': ';
- lbl.style.width = '150px';
- row.appendChild(lbl);
- const select = document.createElement('select');
- select.style.cssText = `
- border: 1px solid #777;
- border-radius: 4px;
- padding: 2px 4px;
- `;
- const actions = [
- { value: 'none', text: 'None' },
- { value: 'singleFeed', text: 'Single Feed' },
- { value: 'macroFeed', text: 'Macro Feed' },
- { value: 'split', text: 'Split' }
- ];
- actions.forEach(a => {
- const opt = document.createElement('option');
- opt.value = a.value;
- opt.textContent = a.text;
- select.appendChild(opt);
- });
- select.value = CONFIG[configKey];
- select.onchange = () => {
- CONFIG[configKey] = select.value;
- showNotification(`${label} changed to: ${select.value}`);
- };
- row.appendChild(select);
- return row;
- }
- }
-
- function toggleMainOverlay() {
- modUIVisible = !modUIVisible;
- mainOverlay.style.display = modUIVisible ? 'block' : 'none';
- showControlsButton.textContent = modUIVisible ? 'Hide Controls' : 'Show Controls';
- }
-
- function buttonStyle() {
- return `
- padding: 6px 12px;
- font-size: 14px;
- border: none;
- border-radius: 5px;
- cursor: pointer;
- background-color: #54c800;
- color: #fff;
- transition: background-color 0.2s ease;
- `;
- }
-
- function buildPCHotkeysUI(container) {
- container.appendChild(createHotkeyRow('Single Feed', 'singleFeedKey'));
- container.appendChild(createHotkeyRow('Macro Feed', 'macroFeedKey'));
- container.appendChild(createHotkeyRow('Double Split', 'doubleSplitKey'));
- container.appendChild(createHotkeyRow('Triple Split', 'tripleSplitKey'));
- container.appendChild(createHotkeyRow('Quad Split', 'quadSplitKey'));
- container.appendChild(createHotkeyRow('Straight Line', 'straightLineKey'));
- container.appendChild(createHotkeyRow('Acid Mode', 'acidModeKey'));
- container.appendChild(createHotkeyRow('Skin Switcher', 'skinSwitcherKey'));
- container.appendChild(createHotkeyRow('Toggle UI', 'toggleUIKey'));
- container.appendChild(createHotkeyRow('Zoom Out', 'zoomOutKey'));
- container.appendChild(createHotkeyRow('Zoom In', 'zoomInKey'));
- container.appendChild(createHotkeyRow('Pause Movement', 'pauseMovementKey'));
- }
-
- function createHotkeyRow(label, configKey) {
- const row = document.createElement('div');
- row.style.cssText = 'display: flex; align-items: center; margin-bottom: 5px;';
- const lbl = document.createElement('span');
- lbl.textContent = label + ': ';
- lbl.style.width = '120px';
- row.appendChild(lbl);
- const input = document.createElement('input');
- input.type = 'text';
- input.readOnly = true;
- input.value = CONFIG[configKey];
- input.style.cssText = `
- width: 50px;
- text-align: center;
- border: 1px solid #777;
- border-radius: 3px;
- background-color: #f0f0f0;
- cursor: pointer;
- `;
- row.appendChild(input);
- let waitingForKey = false;
- input.addEventListener('click', () => {
- waitingForKey = true;
- input.value = '???';
- input.focus();
- });
- input.addEventListener('keydown', (evt) => {
- if (!waitingForKey) return;
- evt.preventDefault();
- evt.stopPropagation();
- const newKey = evt.key.toLowerCase();
- CONFIG[configKey] = newKey;
- input.value = newKey;
- waitingForKey = false;
- showNotification(`${label} changed to: ${newKey.toUpperCase()}`);
- });
- return row;
- }
-
- function buildGamepadUI(container) {
- const row = document.createElement('div');
- row.style.marginBottom = '10px';
- const label = document.createElement('label');
- label.textContent = 'Gamepad Enabled: ';
- const cb = document.createElement('input');
- cb.type = 'checkbox';
- cb.checked = CONFIG.enableGamepad;
- cb.style.marginLeft = '5px';
- cb.onchange = () => {
- toggleGamepadMode(cb.checked);
- };
- row.appendChild(label);
- row.appendChild(cb);
- container.appendChild(row);
- container.appendChild(createGamepadRow('Split Button', 'gamepadSplit', CONFIG.gamepadSplit));
- container.appendChild(createGamepadRow('Feed Button', 'gamepadFeed', CONFIG.gamepadFeed));
- container.appendChild(createGamepadRow('Double Split', 'gamepadDoubleSplit', CONFIG.gamepadDoubleSplit));
- container.appendChild(createGamepadRow('Triple Split', 'gamepadTripleSplit', CONFIG.gamepadTripleSplit));
- container.appendChild(createGamepadRow('Acid Mode', 'gamepadAcidMode', CONFIG.gamepadAcidMode));
- container.appendChild(createGamepadRow('Straight Line', 'gamepadStraightLine', CONFIG.gamepadStraightLine));
- }
-
- function createGamepadRow(label, configKey, defaultVal) {
- const row = document.createElement('div');
- row.style.cssText = 'display: flex; align-items: center; margin-bottom: 5px;';
- const lbl = document.createElement('span');
- lbl.textContent = label + ': ';
- lbl.style.width = '120px';
- row.appendChild(lbl);
- const input = document.createElement('input');
- input.type = 'text';
- input.readOnly = true;
- input.value = `Button ${defaultVal}`;
- input.style.cssText = `
- width: 80px;
- text-align: center;
- border: 1px solid #777;
- border-radius: 3px;
- background-color: #54c800;
- color: #fff;
- cursor: pointer;
- transition: background-color 0.2s ease;
- `;
- input.addEventListener('mouseover', () => {
- input.style.backgroundColor = '#347f01';
- });
- input.addEventListener('mouseout', () => {
- input.style.backgroundColor = '#54c800';
- });
- input.addEventListener('mousedown', () => {
- input.style.backgroundColor = '#347f01';
- });
- input.addEventListener('mouseup', () => {
- input.style.backgroundColor = '#54c800';
- });
- input.addEventListener('click', () => {
- input.value = "Press Button...";
- input.style.backgroundColor = '#ffee99';
- isRemappingGamepad = true;
- remappingButton = configKey;
- setTimeout(() => {
- if (input.value === "Press Button...") {
- input.value = `Button ${CONFIG[configKey]}`;
- input.style.backgroundColor = '#f0f0f0';
- isRemappingGamepad = false;
- remappingButton = null;
- }
- }, 5000);
- });
- row.appendChild(input);
- return row;
- }
-
- function setupGamepadSupport() {
- window.addEventListener("gamepadconnected", handleGamepadConnected);
- window.addEventListener("gamepaddisconnected", handleGamepadDisconnected);
- if (CONFIG.enableGamepad) {
- startGamepadPolling();
- }
- }
- function handleGamepadConnected(event) {
- const gamepad = event.gamepad;
- connectedGamepads[gamepad.index] = gamepad;
- console.log(`Gamepad connected at index ${gamepad.index}: ${gamepad.id}`);
- showNotification(`Gamepad connected: ${gamepad.id.split('(')[0]}`);
- if (CONFIG.enableGamepad) {
- startGamepadPolling();
- }
- }
- function handleGamepadDisconnected(event) {
- const gamepad = event.gamepad;
- console.log(`Gamepad disconnected from index ${gamepad.index}: ${gamepad.id}`);
- showNotification('Gamepad disconnected');
- delete connectedGamepads[gamepad.index];
- const hasGamepads = Object.keys(connectedGamepads).length > 0;
- if (!hasGamepads) {
- stopGamepadPolling();
- }
- }
- let gamepadPollingId = null;
- function startGamepadPolling() {
- if (gamepadPollingId === null) {
- gamepadPollingId = setInterval(pollGamepads, 16);
- console.log('Gamepad polling started');
- }
- }
- function stopGamepadPolling() {
- if (gamepadPollingId !== null) {
- clearInterval(gamepadPollingId);
- gamepadPollingId = null;
- console.log('Gamepad polling stopped');
- }
- }
- function toggleGamepadMode(enabled) {
- CONFIG.enableGamepad = enabled;
- if (enabled) {
- startGamepadPolling();
- showNotification('Gamepad mode enabled');
- } else {
- stopGamepadPolling();
- showNotification('Gamepad mode disabled');
- }
- }
- function pollGamepads() {
- if (!CONFIG.enableGamepad) return;
- const gamepads = navigator.getGamepads
- ? navigator.getGamepads()
- : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : []);
- for (let i = 0; i < gamepads.length; i++) {
- const gamepad = gamepads[i];
- if (!gamepad) continue;
- if (!lastGamepadState[gamepad.index]) {
- lastGamepadState[gamepad.index] = {
- buttons: Array(gamepad.buttons.length).fill(false),
- axes: Array(gamepad.axes.length).fill(0)
- };
- }
- for (let j = 0; j < gamepad.buttons.length; j++) {
- const isPressed = gamepad.buttons[j].pressed;
- const wasPressed = lastGamepadState[gamepad.index].buttons[j];
- if (isPressed && !wasPressed) {
- handleGamepadButtonPressed(gamepad.index, j);
- } else if (!isPressed && wasPressed) {
- handleGamepadButtonReleased(gamepad.index, j);
- }
- lastGamepadState[gamepad.index].buttons[j] = isPressed;
- }
- for (let j = 0; j < gamepad.axes.length; j++) {
- const axisValue = gamepad.axes[j];
- const prevAxisValue = lastGamepadState[gamepad.index].axes[j];
- if (Math.abs(axisValue - prevAxisValue) > 0.1) {
- handleGamepadAxisMoved(gamepad.index, j, axisValue);
- }
- lastGamepadState[gamepad.index].axes[j] = axisValue;
- }
- }
- if (isPaused && gameCanvas && window.core) {
- const rect = gameCanvas.getBoundingClientRect();
- const centerX = rect.left + rect.width / 2;
- const centerY = rect.top + rect.height / 2;
- window.core.setTarget(centerX, centerY);
- }
- }
- function handleGamepadButtonPressed(gamepadIndex, buttonIndex) {
- if (isRemappingGamepad) {
- if (remappingButton) {
- CONFIG[remappingButton] = buttonIndex;
- showNotification(`Mapped ${remappingButton} to button ${buttonIndex}`);
- isRemappingGamepad = false;
- const gpInputs = document.querySelectorAll('input[value="Press Button..."]');
- for (let i = 0; i < gpInputs.length; i++) {
- const input = gpInputs[i];
- if (input.style.backgroundColor === 'rgb(255, 238, 153)') {
- input.value = `Button ${buttonIndex}`;
- input.style.backgroundColor = '#f0f0f0';
- break;
- }
- }
- remappingButton = null;
- }
- return;
- }
- if (!window.core || isPaused) return;
- if (buttonIndex === CONFIG.gamepadSplit) {
- window.core.split();
- }
- else if (buttonIndex === CONFIG.gamepadFeed) {
- window.core.eject();
- }
- else if (buttonIndex === CONFIG.gamepadDoubleSplit) {
- performMultiSplit(2);
- }
- else if (buttonIndex === CONFIG.gamepadTripleSplit) {
- performMultiSplit(3);
- }
- else if (buttonIndex === CONFIG.gamepadAcidMode) {
- toggleAcidMode();
- }
- else if (buttonIndex === CONFIG.gamepadStraightLine) {
- toggleStraightLineMode();
- }
- }
- function handleGamepadButtonReleased() { }
- function handleGamepadAxisMoved(gamepadIndex, axisIndex, value) {
- if (isPaused) return;
- if (axisIndex <= 1 && window.core && gameCanvas) {
- const gamepad = navigator.getGamepads()[gamepadIndex];
- const horizontalAxis = gamepad.axes[0];
- const verticalAxis = gamepad.axes[1];
- const deadzone = 0.15;
- let x = Math.abs(horizontalAxis) < deadzone ? 0 : horizontalAxis;
- let y = Math.abs(verticalAxis) < deadzone ? 0 : verticalAxis;
- if (Math.abs(x) > 0.1 || Math.abs(y) > 0.1) {
- const rect = gameCanvas.getBoundingClientRect();
- const centerX = rect.left + rect.width / 2;
- const centerY = rect.top + rect.height / 2;
- const sensitivity = 200;
- const targetX = centerX + (x * sensitivity);
- const targetY = centerY + (y * sensitivity);
- window.core.setTarget(targetX, targetY);
- }
- }
- }
-
- function toggleAcidMode() {
- if (!window.core) return;
- CONFIG.enableAcidMode = !CONFIG.enableAcidMode;
- window.core.setAcid(CONFIG.enableAcidMode);
- const acidButtons = document.querySelectorAll('button');
- for (let i = 0; i < acidButtons.length; i++) {
- if (acidButtons[i].textContent.includes('Acid Mode')) {
- acidButtons[i].textContent = CONFIG.enableAcidMode ? 'Acid Mode: ON' : 'Acid Mode: OFF';
- }
- }
- showNotification(CONFIG.enableAcidMode ? 'Acid mode: ON' : 'Acid mode: OFF');
- }
-
- function checkCoreAccess() {
- if (typeof window.core === 'undefined') {
- console.log('Waiting for core functions to load...');
- setTimeout(checkCoreAccess, 1000);
- return;
- }
- console.log('Core functions found!');
- if (CONFIG.enableMinimap && window.core) {
- window.core.setMinimap(true);
- window.core.minimizeMinimap(false);
- window.core.playersMinimap(true);
- }
- if (CONFIG.enableAcidMode && window.core) {
- window.core.setAcid(true);
- }
- setupGamepadSupport();
- }
-
- initMod();
- checkCoreAccess();
- }
-
- //------------------------------------------------------------------
- // 4) "Skin Maker" with Drag-and-Drop
- //------------------------------------------------------------------
- function convertImageFileToBase64(file) {
- const reader = new FileReader();
- reader.onloadend = function () {
- const base64 = reader.result;
- drawImage(base64);
- };
- reader.readAsDataURL(file);
- }
- function convertImageToBase64(event) {
- const file = event.target.files[0];
- if (file) {
- convertImageFileToBase64(file);
- }
- }
- function drawImage(base64) {
- const canvas = document.getElementById("skin-editor-canvas");
- if (!canvas) {
- console.warn("No skin-editor-canvas found to draw on!");
- return;
- }
- const context = canvas.getContext("2d");
- const image = new Image();
- image.onload = function () {
- canvas.width = 512;
- canvas.height = 512;
- context.drawImage(image, 0, 0, 512, 512);
- context.save();
- };
- image.src = base64;
- }
- function createImageButton() {
- const container = document.createElement("div");
- container.style.position = "relative";
- container.style.display = "inline-block";
- const input = document.createElement("input");
- input.type = "file";
- input.accept = "image/*";
- input.id = "customImageUpload";
- input.style.width = "100%";
- input.style.height = "100%";
- input.style.opacity = "0";
- input.style.position = "absolute";
- input.style.left = "0";
- input.style.top = "0";
- input.style.zIndex = "1";
- const button = document.createElement("button");
- button.textContent = "Upload Image";
- button.style.color = "#fff";
- button.style.backgroundColor = "#54c800";
- button.style.border = "1px solid black";
- button.style.padding = "5px 10px";
- button.style.cursor = "pointer";
- container.appendChild(input);
- container.appendChild(button);
- input.addEventListener("change", convertImageToBase64);
- return container;
- }
- function createDragAndDropZone() {
- const dropZone = document.createElement('div');
- dropZone.id = 'dropZone';
- dropZone.style.border = "2px dashed #ccc";
- dropZone.style.padding = "10px";
- dropZone.style.marginTop = "10px";
- dropZone.style.textAlign = "center";
- dropZone.textContent = "Drag & drop your image file here";
- dropZone.addEventListener("dragover", (e) => {
- e.preventDefault();
- dropZone.style.backgroundColor = "#ddd";
- });
- dropZone.addEventListener("dragleave", (e) => {
- e.preventDefault();
- dropZone.style.backgroundColor = "";
- });
- dropZone.addEventListener("drop", (e) => {
- e.preventDefault();
- dropZone.style.backgroundColor = "";
- const file = e.dataTransfer.files[0];
- if (file && file.type.startsWith("image/")) {
- convertImageFileToBase64(file);
- } else {
- alert("Please drop an image file only!");
- }
- });
- return dropZone;
- }
- function insertImageButtonAndDropZone(container, target) {
- if (target) {
- const newDiv = document.createElement("div");
- newDiv.style.marginTop = "50px";
- newDiv.appendChild(container);
- const dropZone = createDragAndDropZone();
- newDiv.appendChild(dropZone);
- const saveArea = target.querySelector(".save");
- if (saveArea) {
- saveArea.appendChild(newDiv);
- }
- }
- }
- function observeTargetContainer() {
- const observer = new MutationObserver((mutationsList) => {
- for (let mutation of mutationsList) {
- if (mutation.type === 'childList') {
- const target = document.querySelector(".right-tools");
- if (target && target.querySelector(".save")) {
- if (
- !target.querySelector("#customImageUpload") &&
- !target.querySelector("#dropZone")
- ) {
- const button = createImageButton();
- insertImageButtonAndDropZone(button, target);
- }
- }
- }
- }
- });
- observer.observe(document.body, {
- childList: true,
- subtree: true
- });
- }
-
- //------------------------------------------------------------------
- // 5) Russia -> Ukraine Replacement
- //------------------------------------------------------------------
- function initRussiaToUkraine() {
- function replaceText() {
- const options = document.querySelectorAll('option[value="RU-Russia"]');
- options.forEach(option => {
- const text = option.textContent;
- if (text.includes("Russia")) {
- option.textContent = text.replace("Russia", "Ukraine");
- }
- });
- }
- replaceText();
- const observer = new MutationObserver(replaceText);
- observer.observe(document.body, {
- childList: true,
- subtree: true
- });
- }
- })();