您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Enhances Agar.io with custom controls, advanced features, and skin-maker drag-and-drop
// ==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 }); } })();