// ==UserScript== // @name Cookie Clicker Ultimate Automation // @name:zh-TW 餅乾點點樂全自動掛機輔助 (Cookie Clicker) // @name:zh-CN 饼干点点乐全自动挂机辅助 (Cookie Clicker) // @namespace http://tampermonkey.net/ // @version 7.0 // @description Automated clicker, auto-buy, auto-harvest, garden manager, stock market trader, and HUD overlay. // @description:zh-TW 全功能自動掛機腳本:自動點擊、智慧購買、自動收成糖塊、花園自動補種、股市自動交易、閒置魔法。 // @description:zh-CN 全功能自动挂机脚本:自动点击、智慧购买、自动收成糖块、花园自动补种、股市自动交易、闲置魔法。 // @author You // @match https://wws.justnainai.com/* // @match https://orteil.dashnet.org/cookieclicker/* // @icon https://orteil.dashnet.org/cookieclicker/img/favicon.ico // @grant GM_setValue // @grant GM_getValue // @grant GM_openInTab // @require https://code.jquery.com/jquery-3.6.0.min.js // @license MIT // @homepage https://greasyfork.org/zh-CN/scripts/557692-cookie-clicker-ultimate-automation // @homepageURL https://greasyfork.org/zh-CN/scripts/557692-cookie-clicker-ultimate-automation // @supportURL https://greasyfork.org/zh-CN/scripts/557692-cookie-clicker-ultimate-automation/feedback // @downloadURL none // ==/UserScript== (function() { 'use strict'; // ═══════════════════════════════════════════════════════════════ // 1. 核心變量 & 狀態記憶 // ═══════════════════════════════════════════════════════════════ // v6.x 基礎功能 let isClickEnabled = GM_getValue('isClickEnabled', false); let isBuyEnabled = GM_getValue('isBuyEnabled', false); let isGoldenEnabled = GM_getValue('isGoldenEnabled', false); let isSpellEnabled = GM_getValue('isSpellEnabled', true); // 基礎連擊魔法 let isGardenEnabled = GM_getValue('isGardenEnabled', false); let isResearchEnabled = GM_getValue('isResearchEnabled', true); // v7.0 新增功能 let isStockEnabled = GM_getValue('isStockEnabled', false); // 股市開關 let isSEEnabled = GM_getValue('isSEEnabled', false); // 閒置建築魔法 (Spontaneous Edifice) // 統計計數 let clickCount = 0; let buyUpgradeCount = 0; let buyBuildingCount = 0; let goldenCookieCount = 0; // Interval IDs let intervalId = null; let buyIntervalId = null; let goldenCheckIntervalId = null; let gardenIntervalId = null; let stockIntervalId = null; // v7.0 let restartIntervalId = null; let countdownIntervalId = null; let promptCheckIntervalId = null; let buffCheckIntervalId = null; let ahkSignalIntervalId = null; // 時間控制 let nextRestartTime = 0; let nextBuyTime = 0; // 設定參數 let gameVolume = GM_getValue('gameVolume', 50); let clickInterval = GM_getValue('clickInterval', 50); let buyStrategy = GM_getValue('buyStrategy', 'expensive'); // 購買間隔 let buyIntervalHours = GM_getValue('buyIntervalHours', 0); let buyIntervalMinutes = GM_getValue('buyIntervalMinutes', 3); let buyIntervalSeconds = GM_getValue('buyIntervalSeconds', 0); // 重啟間隔 let restartIntervalHours = GM_getValue('restartIntervalHours', 1); let restartIntervalMinutes = GM_getValue('restartIntervalMinutes', 0); let restartIntervalSeconds = GM_getValue('restartIntervalSeconds', 0); const MAX_WIZARD_TOWERS = 800; // 花園陣型記憶 let savedGardenPlot = GM_getValue('savedGardenPlot', Array(6).fill().map(() => Array(6).fill(-1))); // UI 位置 let showCountdown = GM_getValue('showCountdown', true); let showBuffMonitor = GM_getValue('showBuffMonitor', true); let countdownX = GM_getValue('countdownX', window.innerWidth - 170); let countdownY = GM_getValue('countdownY', 10); let buffX = GM_getValue('buffX', window.innerWidth - 340); let buffY = GM_getValue('buffY', 150); let currentX = GM_getValue('buttonX', 50); let currentY = GM_getValue('buttonY', 50); // DOM 元素引用 let countdownDisplay = null; let buffDisplay = null; let controlPanel = null; let floatingButton = null; const targetSelector = '#bigCookie'; let originalTitle = document.title; // ═══════════════════════════════════════════════════════════════ // 2. 初始化流程 // ═══════════════════════════════════════════════════════════════ function init() { console.log('🍪 Cookie Clicker Ultimate Automation v7.0 Loaded'); const scriptRestarted = localStorage.getItem('cookieScriptRestarted'); if (scriptRestarted) { console.log('🔄 Script restarted automatically.'); localStorage.removeItem('cookieScriptRestarted'); } if (currentX < 0 || currentX > window.innerWidth) currentX = 50; createFloatingButton(); createControlPanel(); createCountdownDisplay(); createBuffDisplay(); setGameVolume(gameVolume); // 啟動各模組循環 goldenCheckIntervalId = setInterval(checkGoldenCookie, 1000); // 含魔法檢查 promptCheckIntervalId = setInterval(autoConfirmPrompt, 1000); buffCheckIntervalId = setInterval(updateBuffDisplay, 500); ahkSignalIntervalId = setInterval(updateTitleForAHK, 1000); gardenIntervalId = setInterval(autoGarden, 2500); // v7.0 股市循環 (3秒一次即可,股市tick為60秒) stockIntervalId = setInterval(autoStock, 3000); startCountdown(); scheduleAutoRestart(); setTimeout(() => { if (isClickEnabled) startAutoClick(); if (isBuyEnabled) startAutoBuy(); updateAllDisplays(); }, 2000); document.addEventListener('keydown', function(e) { if (e.key === 'F8') { e.preventDefault(); toggleAutoClick(); } }); } // ═══════════════════════════════════════════════════════════════ // 3. AHK 通訊協議 (v6.5 Logic) // ═══════════════════════════════════════════════════════════════ function updateTitleForAHK() { if (typeof Game === 'undefined') return; let totalMult = 1; let isWorthClicking = false; if (Game.buffs) { for (let i in Game.buffs) { const buff = Game.buffs[i]; if (buff.multCpS > 0) totalMult *= buff.multCpS; if (buff.multClick > 0) totalMult *= buff.multClick; if (buff.multClick > 1 || buff.multCpS > 7) { isWorthClicking = true; } } } let coords = "0,0"; const bigCookie = document.querySelector('#bigCookie'); if (bigCookie) { const rect = bigCookie.getBoundingClientRect(); const cx = Math.round(rect.left + rect.width / 2); const cy = Math.round(rect.top + rect.height / 2); coords = `${cx},${cy}`; } const signal = isWorthClicking ? "⚡ATTACK" : "💤IDLE"; const displayMult = totalMult > 1000 ? (totalMult/1000).toFixed(1) + 'k' : Math.round(totalMult); document.title = `[${signal}|${displayMult}x|${coords}] ${originalTitle}`; } // ═══════════════════════════════════════════════════════════════ // 4. 核心功能模組 (Click, Garden, Buy) // ═══════════════════════════════════════════════════════════════ // --- 點擊模組 --- function autoClick() { const element = document.querySelector(targetSelector); if (element) { element.click(); clickCount++; } } function startAutoClick() { if (intervalId) clearInterval(intervalId); intervalId = setInterval(autoClick, clickInterval); isClickEnabled = true; updateAllDisplays(); } function stopAutoClick() { if (intervalId) clearInterval(intervalId); isClickEnabled = false; updateAllDisplays(); } function toggleAutoClick() { isClickEnabled = !isClickEnabled; GM_setValue('isClickEnabled', isClickEnabled); if (isClickEnabled) startAutoClick(); else stopAutoClick(); } // --- 花園模組 --- function autoGarden() { if (!isGardenEnabled) return; if (typeof Game === 'undefined' || !Game.Objects['Farm'].minigameLoaded) return; const M = Game.Objects['Farm'].minigame; if (!M) return; for (let y = 0; y < 6; y++) { for (let x = 0; x < 6; x++) { if (!M.isTileUnlocked(x, y)) continue; const tile = M.plot[y][x]; const tileId = tile[0]; const tileAge = tile[1]; if (tileId > 0) { const plant = M.plantsById[tileId - 1]; if (plant.weed || plant.key === 'crumbspore') { M.harvest(x, y); continue; } if (tileAge >= 98 && tileAge >= plant.mature) { M.harvest(x, y); continue; } } if (tileId === 0) { const targetPlantId = savedGardenPlot[y][x]; if (targetPlantId !== -1 && targetPlantId !== null) { const seed = M.plantsById[targetPlantId - 1]; if (seed && seed.unlocked && M.canPlant(seed)) { M.useTool(seed.id, x, y); } } } } } } function saveGardenLayout() { if (typeof Game === 'undefined' || !Game.Objects['Farm'].minigame) { alert('花園尚未解鎖或載入!'); return; } const M = Game.Objects['Farm'].minigame; let newLayout = []; for (let y = 0; y < 6; y++) { let row = []; for (let x = 0; x < 6; x++) { if (M.isTileUnlocked(x, y)) { const tile = M.plot[y][x]; row.push(tile[0] === 0 ? -1 : tile[0]); } else { row.push(-1); } } newLayout.push(row); } savedGardenPlot = newLayout; GM_setValue('savedGardenPlot', savedGardenPlot); const btn = $('#garden-save-btn'); const originalText = btn.text(); btn.text('✅ 已儲存!').css('background', '#4caf50'); setTimeout(() => btn.text(originalText).css('background', '#2196f3'), 1500); } // --- 購買模組 --- function autoBuy() { if (typeof Game === 'undefined') return; // 0. 誓約絕對優先 if (Game.Upgrades['Elder Pledge']) { const pledge = Game.Upgrades['Elder Pledge']; if (pledge.unlocked && pledge.bought === 0 && pledge.canBuy()) { console.log('🛡️ [AutoBuy] 誓約過期,強制後台購買!'); pledge.buy(); nextBuyTime = Date.now() + getBuyInterval(); return; } } // 1. 科技 if (isResearchEnabled) { const research = document.querySelectorAll('#techUpgrades .crate.upgrade.enabled'); if (research.length > 0) { const item = research[0]; console.log(`🛒 [購買-科技] 研究: ${getUpgradeName(item)}`); item.click(); nextBuyTime = Date.now() + getBuyInterval(); return; } } // 2. 升級 const upgradesList = document.querySelectorAll('#upgrades .crate.upgrade.enabled'); if (upgradesList.length > 0) { const selected = selectByStrategy(upgradesList, true); if (selected) { console.log(`🛒 [購買-升級] 購買: ${getUpgradeName(selected)}`); selected.click(); buyUpgradeCount++; nextBuyTime = Date.now() + getBuyInterval(); return; } } // 3. 建築 const buildings = document.querySelectorAll('.product.unlocked.enabled'); if (buildings.length > 0) { const selected = selectByStrategy(buildings, false); if (selected) { const buildId = selected.id.replace('product', ''); let buildName = "未知建築"; if(Game.ObjectsById[buildId]) buildName = Game.ObjectsById[buildId].displayName; console.log(`🛒 [購買-建築] 建造: ${buildName}`); selected.click(); buyBuildingCount++; nextBuyTime = Date.now() + getBuyInterval(); } } } function getUpgradeName(element) { let name = "未知物品"; try { const id = element.getAttribute('data-id'); if (id && Game.UpgradesById[id]) name = `${Game.UpgradesById[id].name}`; } catch(e) {} return name; } function selectByStrategy(items, isUpgrade) { if (!items || items.length === 0) return null; let itemsArray = Array.from(items); itemsArray = itemsArray.filter(item => { const id = item.getAttribute('data-id'); if (isUpgrade && id === '84') return false; if (!isUpgrade) { const bId = item.id.replace('product', ''); if (Game.ObjectsById[bId] && Game.ObjectsById[bId].name === 'Wizard tower') { if (Game.ObjectsById[bId].amount >= MAX_WIZARD_TOWERS) return false; } } return true; }); if (itemsArray.length === 0) return null; if (buyStrategy === 'random') return itemsArray[Math.floor(Math.random() * itemsArray.length)]; if (buyStrategy === 'cheapest') return itemsArray[0]; return itemsArray[itemsArray.length - 1]; } function startAutoBuy() { if (buyIntervalId) clearInterval(buyIntervalId); const interval = getBuyInterval(); buyIntervalId = setInterval(autoBuy, interval); nextBuyTime = Date.now() + interval; autoBuy(); } function stopAutoBuy() { if (buyIntervalId) clearInterval(buyIntervalId); nextBuyTime = 0; } function getBuyInterval() { return (buyIntervalHours * 3600 + buyIntervalMinutes * 60 + buyIntervalSeconds) * 1000; } // ═══════════════════════════════════════════════════════════════ // 5. 股市模組 (v7.0 New) // ═══════════════════════════════════════════════════════════════ function autoStock() { if (!isStockEnabled) return; if (typeof Game === 'undefined') return; const Bank = Game.Objects['Bank']; if (!Bank || !Bank.minigameLoaded || !Bank.minigame) return; const M = Bank.minigame; // 遍歷所有股票 (ID 0-15) for (let i = 0; i < M.goodsById.length; i++) { const good = M.goodsById[i]; const price = M.getGoodPrice(good); // 獲取靜止價值 (Resting Value) const rv = M.getRestingVal(good.id); // 策略:低買高賣 (考慮 20% Overhead) // 買入閾值:低於 RV 的 50% // 賣出閾值:高於 RV 的 150% (50% profit margin) // 1. 買入邏輯 if (price < rv * 0.5) { // 檢查是否還有庫存空間與現金 const maxStock = M.getGoodMaxStock(good); if (good.stock < maxStock && Game.cookies > price) { // 10000 代表買最大值 M.buyGood(good.id, 10000); // console.log(`📈 [股市] 買入 ${good.name} @ $${price.toFixed(2)} (RV: ${rv.toFixed(2)})`); } } // 2. 賣出邏輯 if (price > rv * 1.5) { if (good.stock > 0) { M.sellGood(good.id, 10000); // 賣出所有 console.log(`📉 [股市] 獲利賣出 ${good.name} @ $${price.toFixed(2)} (RV: ${rv.toFixed(2)})`); } } } } // ═══════════════════════════════════════════════════════════════ // 6. 金餅乾/糖塊/魔法模組 (v7.0 Updated) // ═══════════════════════════════════════════════════════════════ function checkGoldenCookie() { if (isGoldenEnabled) { autoHarvestLump(); const goldenCookies = document.querySelectorAll('#shimmers > div.shimmer'); if (goldenCookies.length > 0) { goldenCookies.forEach(cookie => cookie.click()); goldenCookieCount++; } } // 魔法控制 (基礎與進階) if (isSpellEnabled || isSEEnabled) { autoCastSpell(); } } function autoHarvestLump() { if (typeof Game === 'undefined') return; if (Game.canLumps()) { if (Game.lumpCurrentType === 3) return; let age = Date.now() - Game.lumpT; if (age >= Game.lumpRipeAge) { Game.clickLump(); } } } function autoCastSpell() { if (typeof Game === 'undefined' || !Game.Objects['Wizard tower'].minigame) return; const M = Game.Objects['Wizard tower'].minigame; const spellHoF = M.spells['hand of fate']; const spellSE = M.spells['spontaneous edifice']; // --- 優先級 1: 命運之手 (Hand of Fate) --- // 只有在開啟基礎魔法開關時執行 if (isSpellEnabled && M.magic >= M.getSpellCost(spellHoF)) { let shouldCast = false; for (let i in Game.buffs) { const buff = Game.buffs[i]; if (buff.multCpS > 7 || buff.multClick > 10) { shouldCast = true; break; } if (buff.multCpS === 7 && M.magic >= M.magicM * 0.95) { shouldCast = true; break; } } if (shouldCast) { M.castSpell(spellHoF); console.log('🧙♂️ [AutoSpell] 觸發連擊:命運之手'); return; // 施法後直接結束,避免同時施放兩個魔法 } } // --- 優先級 2: 憑空建築 (Spontaneous Edifice) --- // v7.0 新增:閒置期免費獲取建築 if (isSEEnabled && M.magic >= M.getSpellCost(spellSE)) { // 條件 A: 魔力接近全滿 (避免影響 HoF 回魔) if (M.magic < M.magicM * 0.95) return; // 條件 B: 場上沒有 Buff (確保不是連擊準備期) if (Object.keys(Game.buffs).length > 0) return; // 條件 C: 場上沒有金餅乾 if (document.querySelectorAll('.shimmer').length > 0) return; // 施法 console.log('🧙♂️ [AutoSpell] 閒置期:免費召喚了一座建築 (Spontaneous Edifice)'); M.castSpell(spellSE); } } // ═══════════════════════════════════════════════════════════════ // 7. 彈窗確認 // ═══════════════════════════════════════════════════════════════ function autoConfirmPrompt() { const promptBox = document.querySelector('#prompt'); if (!promptBox) return; const isVisible = promptBox.style.display !== 'none' && promptBox.offsetHeight > 0; if (isVisible) { const promptContent = document.querySelector('#promptContent'); const yesButton = document.querySelector('#promptOption0'); if (promptContent && yesButton) { const txt = promptContent.textContent; // 中英雙語關鍵字 const keywords = ['Warning', 'One Mind', 'revoke', '警告', '不好的结果']; if (keywords.some(k => txt.includes(k))) { console.log('⚠️ [Safe] Auto-confirming prompt:', txt); yesButton.click(); } } } } // ═══════════════════════════════════════════════════════════════ // 8. UI 顯示與管理 // ═══════════════════════════════════════════════════════════════ function createBuffDisplay() { if (buffDisplay) return; buffDisplay = $(`
`); makeDraggable(buffDisplay, 'buffX', 'buffY'); $('body').append(buffDisplay); } function updateBuffDisplay() { if (!showBuffMonitor || !buffDisplay) return; if (typeof Game === 'undefined') return; const buffList = $('#buff-list-content'); buffList.empty(); let totalCpsMult = 1; let totalClickMult = 1; let hasBuff = false; if (Game.buffs) { for (let i in Game.buffs) { hasBuff = true; const buff = Game.buffs[i]; if (buff.multCpS > 0) totalCpsMult *= buff.multCpS; if (buff.multClick > 0) totalClickMult *= buff.multClick; const timeLeft = Math.ceil(buff.time / 30); const iconX = buff.icon[0] * 48; const iconY = buff.icon[1] * 48; const iconUrl = 'img/icons.png'; const isPowerful = buff.multCpS > 50 || buff.multClick > 10; const textColor = isPowerful ? '#ff4444' : 'white'; const bgColor = isPowerful ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.2)'; let multDisplay = ''; if (buff.multCpS > 0 && buff.multCpS !== 1) multDisplay = `產量 x${Math.round(buff.multCpS*10)/10}`; if (buff.multClick > 0 && buff.multClick !== 1) { if(multDisplay) multDisplay += ', '; multDisplay += `點擊 x${Math.round(buff.multClick)}`; } buffList.append(`