// ==UserScript== // @name Cookie Clicker Ultimate Automation // @name:zh-TW 餅乾點點樂全自動掛機輔助 (Cookie Clicker) // @name:zh-CN 饼干点点乐全自动挂机辅助 (Cookie Clicker) // @namespace http://tampermonkey.net/ // @version 7.5 // @description Automated clicker, auto-buy, auto-harvest, garden manager (Auto Mutation), stock market trader, and HUD overlay. // @description:zh-TW 全功能自動掛機腳本:v7.5 日誌本地化更新 - 建築與升級名稱現在會正確顯示為遊戲當前語言,並去除干擾的 HTML 標籤。 // @description:zh-CN 全功能自动挂机脚本:v7.5 日志本地化更新 - 建筑与升级名称现在会正确显示为游戏当前语言,并去除干扰的 HTML 标签。 // @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 // @downloadURL none // ==/UserScript== (function() { 'use strict'; // ═══════════════════════════════════════════════════════════════ // 1. 核心變量 & 狀態記憶 // ═══════════════════════════════════════════════════════════════ 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); let isStockEnabled = GM_getValue('isStockEnabled', false); let isSEEnabled = GM_getValue('isSEEnabled', false); // v7.1 ~ v7.4 花園相關設定 let isGardenOverlayEnabled = GM_getValue('isGardenOverlayEnabled', false); let isGardenAvoidBuff = GM_getValue('isGardenAvoidBuff', true); let isGardenMutationEnabled = GM_getValue('isGardenMutationEnabled', false); // 統計計數 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; let restartIntervalId = null; let countdownIntervalId = null; let promptCheckIntervalId = null; let buffCheckIntervalId = null; let ahkSignalIntervalId = null; let overlayIntervalId = 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.5 Loaded (Localized Logs)'); const scriptRestarted = localStorage.getItem('cookieScriptRestarted'); if (scriptRestarted) { console.log('🔄 Script restarted automatically.'); localStorage.removeItem('cookieScriptRestarted'); } if (currentX < 0 || currentX > window.innerWidth) currentX = 50; injectCustomStyles(); 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); stockIntervalId = setInterval(autoStock, 3000); overlayIntervalId = setInterval(updateGardenOverlay, 1000); startCountdown(); scheduleAutoRestart(); setTimeout(() => { if (isClickEnabled) startAutoClick(); if (isBuyEnabled) startAutoBuy(); updateAllDisplays(); }, 2000); document.addEventListener('keydown', function(e) { if (e.key === 'F8') { e.preventDefault(); toggleAutoClick(); } }); } function injectCustomStyles() { const style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = ` .cc-overlay-missing { border: 3px dashed #2196f3 !important; box-sizing: border-box; background: rgba(33, 150, 243, 0.1); } .cc-overlay-anomaly { border: 3px solid #ff4444 !important; box-shadow: inset 0 0 15px rgba(255, 0, 0, 0.6) !important; box-sizing: border-box; z-index: 10; } .cc-overlay-new { border: 3px solid #9c27b0 !important; box-shadow: inset 0 0 15px rgba(156, 39, 176, 0.8), 0 0 10px rgba(156, 39, 176, 0.5) !important; box-sizing: border-box; z-index: 12; } .cc-overlay-correct { border: 1px solid rgba(76, 175, 80, 0.4) !important; box-sizing: border-box; } `; document.head.appendChild(style); } // ═══════════════════════════════════════════════════════════════ // 3. 核心功能模組 // ═══════════════════════════════════════════════════════════════ // v7.5 Helper: 清洗名稱 (去除 HTML 標籤) function cleanName(str) { if (!str) return ''; if (typeof str !== 'string') return String(str); // 去除 HTML 標籤 return str.replace(/<[^>]*>/g, '').trim(); } // --- 花園模組 --- function autoGarden() { if (!isGardenEnabled) return; if (typeof Game === 'undefined' || !Game.Objects['Farm'].minigameLoaded) return; const M = Game.Objects['Farm'].minigame; if (!M) return; let isCpsBuffActive = false; if (isGardenAvoidBuff) { for (let i in Game.buffs) { if (Game.buffs[i].multCpS > 1) { isCpsBuffActive = true; break; } } } let skippedLogPrinted = false; 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]; const savedId = savedGardenPlot[y][x]; // 1. 處理已種植的格子 if (tileId > 0) { const plant = M.plantsById[tileId - 1]; const isAnomaly = (savedId !== -1 && tileId !== savedId) || (savedId === -1); const plantName = cleanName(plant.name); // Case A: 符合預期 if (!isAnomaly) { if (tileAge >= 98 && tileAge >= plant.mature) { M.harvest(x, y); } continue; } // Case B: 異常狀態 (變異或雜草) if (isGardenMutationEnabled) { if (plant.unlocked) { M.harvest(x, y); console.log(`🧹 [花園] 鏟除雜物/已知變異 (紅框): ${plantName}`); } else { if (tileAge >= plant.mature) { M.harvest(x, y); console.log(`🎉 [花園] 成功收割新品種種子 (紫框): ${plantName}`); } } } else { if (plant.weed) { M.harvest(x, y); } } continue; } // 2. 自動補種 if (tileId === 0) { if (savedId !== -1 && savedId !== null) { const seed = M.plantsById[savedId - 1]; if (seed && seed.unlocked && M.canPlant(seed)) { if (isGardenAvoidBuff && isCpsBuffActive) { if (!skippedLogPrinted) { console.log('🌻 [花園] 檢測到產量 Buff,暫停補種。'); skippedLogPrinted = true; } continue; } M.useTool(seed.id, x, y); } } } } } } // --- 視覺覆蓋層 --- function updateGardenOverlay() { if (!isGardenOverlayEnabled) 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++) { const tileDiv = document.getElementById(`gardenTile-${x}-${y}`); if (!tileDiv) continue; tileDiv.classList.remove('cc-overlay-missing', 'cc-overlay-anomaly', 'cc-overlay-correct', 'cc-overlay-new'); if (!M.isTileUnlocked(x, y)) continue; const savedId = savedGardenPlot[y][x]; const realId = M.plot[y][x][0]; if (realId === 0 && savedId !== -1) { tileDiv.classList.add('cc-overlay-missing'); } else if (realId !== 0) { const plant = M.plantsById[realId - 1]; const isAnomaly = (savedId !== -1 && realId !== savedId) || (savedId === -1); if (isAnomaly) { if (plant.unlocked) tileDiv.classList.add('cc-overlay-anomaly'); else tileDiv.classList.add('cc-overlay-new'); } else if (realId === savedId) { tileDiv.classList.add('cc-overlay-correct'); } } } } } 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 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(); coords = `${Math.round(rect.left + rect.width / 2)},${Math.round(rect.top + rect.height / 2)}`; } const signal = isWorthClicking ? "⚡ATTACK" : "💤IDLE"; const displayMult = totalMult > 1000 ? (totalMult/1000).toFixed(1) + 'k' : Math.round(totalMult); document.title = `[${signal}|${displayMult}x|${coords}] ${originalTitle}`; } 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); isClickEnabled ? startAutoClick() : stopAutoClick(); } function autoBuy() { if (typeof Game === 'undefined') return; // 誓約 (Elder Pledge) 優先購買 if (Game.Upgrades['Elder Pledge'] && Game.Upgrades['Elder Pledge'].unlocked && Game.Upgrades['Elder Pledge'].bought === 0 && Game.Upgrades['Elder Pledge'].canBuy()) { console.log('🛡️ [AutoBuy] 誓約過期,強制後台購買!'); Game.Upgrades['Elder Pledge'].buy(); nextBuyTime = Date.now() + getBuyInterval(); return; } // 科技研究 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; } } // 升級 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; } } // 建築 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 = "未知建築"; // v7.5 修正:使用 displayName 並去除 HTML if(Game.ObjectsById[buildId]) { buildName = cleanName(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]) { const obj = Game.UpgradesById[id]; // v7.5 修正:優先使用 dname (本地化名稱),然後是 name,並去除 HTML name = cleanName(obj.dname || obj.name); } } catch(e) {} return name; } function selectByStrategy(items, isUpgrade) { let itemsArray = Array.from(items).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' && 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; } // --- 股市模組 --- function autoStock() { if (!isStockEnabled || typeof Game === 'undefined') return; const Bank = Game.Objects['Bank']; if (!Bank || !Bank.minigameLoaded || !Bank.minigame) return; const M = Bank.minigame; for (let i = 0; i < M.goodsById.length; i++) { const good = M.goodsById[i]; const price = M.getGoodPrice(good); const rv = M.getRestingVal(good.id); const goodName = cleanName(good.name); if (price < rv * 0.5) { const maxStock = M.getGoodMaxStock(good); if (good.stock < maxStock && Game.cookies > price) { M.buyGood(good.id, 10000); } } if (price > rv * 1.5) { if (good.stock > 0) { M.sellGood(good.id, 10000); console.log(`📉 [股市] 獲利賣出 ${goodName} @ $${price.toFixed(2)} (RV: ${rv.toFixed(2)})`); } } } } // --- 金餅乾/糖塊/魔法模組 --- function checkGoldenCookie() { if (isGoldenEnabled) { if (Game.canLumps() && Game.lumpCurrentType !== 3 && (Date.now() - Game.lumpT) >= Game.lumpRipeAge) Game.clickLump(); document.querySelectorAll('#shimmers > div.shimmer').forEach(c => c.click()); } if ((isSpellEnabled || isSEEnabled) && Game.Objects['Wizard tower'].minigame) { const M = Game.Objects['Wizard tower'].minigame; // Auto HoF if (isSpellEnabled && M.magic >= M.getSpellCost(M.spells['hand of fate'])) { let shouldCast = false; for (let i in Game.buffs) { if (Game.buffs[i].multCpS > 7 || Game.buffs[i].multClick > 10) { shouldCast = true; break; } if (Game.buffs[i].multCpS === 7 && M.magic >= M.magicM * 0.95) { shouldCast = true; break; } } if (shouldCast) { M.castSpell(M.spells['hand of fate']); console.log('🧙‍♂️ [AutoSpell] 觸發連擊:命運之手'); } } // Auto SE if (isSEEnabled && M.magic >= M.getSpellCost(M.spells['spontaneous edifice'])) { if (M.magic >= M.magicM * 0.95 && Object.keys(Game.buffs).length === 0 && document.querySelectorAll('.shimmer').length === 0) { console.log('🧙‍♂️ [AutoSpell] 閒置期:免費召喚了一座建築 (Spontaneous Edifice)'); M.castSpell(M.spells['spontaneous edifice']); } } } } // --- 彈窗模組 --- function autoConfirmPrompt() { const yesButton = document.querySelector('#promptOption0'); if (yesButton && document.querySelector('#promptContent')) { const txt = document.querySelector('#promptContent').textContent; if (['Warning', 'One Mind', 'revoke', '警告', '不好的结果'].some(k => txt.includes(k))) { console.log('⚠️ [Safe] Auto-confirming prompt:', txt); yesButton.click(); } } } // ═══════════════════════════════════════════════════════════════ // 4. UI 顯示 // ═══════════════════════════════════════════════════════════════ function createControlPanel() { if (controlPanel) return; const panelX = GM_getValue('panelX', window.innerWidth / 2 - 200); const panelY = GM_getValue('panelY', 100); controlPanel = $(` `); makeDraggable(controlPanel, 'panelX', 'panelY', '#panel-header'); $('body').append(controlPanel); bindPanelEvents(); } function createBuffDisplay() { if (buffDisplay) return; buffDisplay = $(` `); makeDraggable(buffDisplay, 'buffX', 'buffY'); $('body').append(buffDisplay); } function updateBuffDisplay() { if (!showBuffMonitor || !buffDisplay) 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 iconUrl = 'img/icons.png'; const iconX = buff.icon[0] * 48; const iconY = buff.icon[1] * 48; 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)'; // v7.5 也順手將 Buff 名稱使用 cleanName 處理,確保一致性 const buffName = cleanName(buff.dname ? buff.dname : buff.name); 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(`
${buffName}
${multDisplay}
剩餘: ${Math.ceil(buff.time / 30)}s
`); } } if (!hasBuff) buffList.append('
無活性效果
'); let summaryHtml = '
'; let effectiveClickPower = totalCpsMult * totalClickMult; if (totalCpsMult !== 1) { let val = totalCpsMult < 1 ? totalCpsMult.toFixed(2) : Math.round(totalCpsMult).toLocaleString(); summaryHtml += `
🏭 總產量: x${val}
`; } if (effectiveClickPower > 1) { let val = Math.round(effectiveClickPower).toLocaleString(); summaryHtml += `
⚡ 點擊倍率: x${val}
`; } if (typeof Game.computedMouseCps !== 'undefined') { let clickVal = Game.computedMouseCps; let formattedClick = typeof Beautify !== 'undefined' ? Beautify(clickVal) : Math.round(clickVal).toLocaleString(); summaryHtml += `
👆 點擊力: +${formattedClick}
`; } summaryHtml += '
'; buffList.append(summaryHtml); } function createCountdownDisplay() { if (countdownDisplay) return; countdownDisplay = $(` `); countdownDisplay.find('#volume-slider-mini').on('input', function() { gameVolume = parseInt($(this).val()); $('#vol-disp').text(gameVolume); setGameVolume(gameVolume); GM_setValue('gameVolume', gameVolume); }); makeDraggable(countdownDisplay, 'countdownX', 'countdownY'); $('body').append(countdownDisplay); } function startCountdown() { if (countdownIntervalId) clearInterval(countdownIntervalId); countdownIntervalId = setInterval(() => { if (!showCountdown || !countdownDisplay) return; const now = Date.now(); $('#txt-rst').text(formatMs(Math.max(0, nextRestartTime - now))); $('#txt-buy').text(isBuyEnabled ? formatMs(Math.max(0, nextBuyTime - now)) : '--:--'); }, 1000); } function createFloatingButton() { if (floatingButton) return; floatingButton = $(` `); floatingButton.click((e) => { e.stopPropagation(); toggleControlPanel(); }); let isD = false; floatingButton.mousedown(() => isD = true); $(document).mousemove((e) => { if(isD) { currentX = e.clientX - 25; currentY = e.clientY - 25; floatingButton.css({left: currentX, top: currentY}); } }).mouseup(() => { if(isD) { isD = false; GM_setValue('buttonX', currentX); GM_setValue('buttonY', currentY); }}); $('body').append(floatingButton); } function toggleControlPanel() { if (!controlPanel) createControlPanel(); controlPanel.is(':visible') ? controlPanel.fadeOut(200) : controlPanel.fadeIn(200); } function makeDraggable(element, keyX, keyY, handleSelector = null) { let isDragging = false, startX = 0, startY = 0; const handle = handleSelector ? element.find(handleSelector) : element; handle.on('mousedown', function(e) { if ($(e.target).is('input, select, button')) return; isDragging = true; startX = e.clientX - parseInt(element.css('left')); startY = e.clientY - parseInt(element.css('top')); }); $(document).on('mousemove', function(e) { if (isDragging) element.css({left: e.clientX - startX + 'px', top: e.clientY - startY + 'px'}); }).on('mouseup', function() { if (isDragging) { isDragging = false; GM_setValue(keyX, parseInt(element.css('left'))); GM_setValue(keyY, parseInt(element.css('top'))); } }); } function bindPanelEvents() { $('#chk-auto-click').change(function() { isClickEnabled = this.checked; GM_setValue('isClickEnabled', isClickEnabled); isClickEnabled ? startAutoClick() : stopAutoClick(); }); $('#chk-auto-buy').change(function() { isBuyEnabled = this.checked; GM_setValue('isBuyEnabled', isBuyEnabled); isBuyEnabled ? startAutoBuy() : stopAutoBuy(); }); $('#chk-auto-golden').change(function() { isGoldenEnabled = this.checked; GM_setValue('isGoldenEnabled', isGoldenEnabled); }); $('#chk-auto-garden').change(function() { isGardenEnabled = this.checked; GM_setValue('isGardenEnabled', isGardenEnabled); }); $('#chk-stock').change(function() { isStockEnabled = this.checked; GM_setValue('isStockEnabled', isStockEnabled); }); $('#chk-se').change(function() { isSEEnabled = this.checked; GM_setValue('isSEEnabled', isSEEnabled); }); $('#chk-garden-overlay').change(function() { isGardenOverlayEnabled = this.checked; GM_setValue('isGardenOverlayEnabled', isGardenOverlayEnabled); if (!isGardenOverlayEnabled) $('.cc-overlay-missing, .cc-overlay-anomaly, .cc-overlay-correct, .cc-overlay-new').removeClass('cc-overlay-missing cc-overlay-anomaly cc-overlay-correct cc-overlay-new'); }); $('#chk-garden-mutation').change(function() { isGardenMutationEnabled = this.checked; GM_setValue('isGardenMutationEnabled', isGardenMutationEnabled); }); $('#chk-garden-smart').change(function() { isGardenAvoidBuff = this.checked; GM_setValue('isGardenAvoidBuff', isGardenAvoidBuff); }); $('#garden-save-btn').click(saveGardenLayout); $('#buy-strategy').change(function() { buyStrategy = $(this).val(); GM_setValue('buyStrategy', buyStrategy); }); $('#chk-spell').change(function() { isSpellEnabled = this.checked; GM_setValue('isSpellEnabled', isSpellEnabled); }); $('#chk-ui-count').change(function() { showCountdown = this.checked; GM_setValue('showCountdown', showCountdown); countdownDisplay.toggle(showCountdown); }); $('#chk-ui-buff').change(function() { showBuffMonitor = this.checked; GM_setValue('showBuffMonitor', showBuffMonitor); buffDisplay.toggle(showBuffMonitor); }); $('#spd-slider').on('input', function() { clickInterval = parseInt($(this).val()); $('#spd-val').text(clickInterval); GM_setValue('clickInterval', clickInterval); if (isClickEnabled) startAutoClick(); }); $('#buy-min, #buy-sec').change(function() { buyIntervalMinutes = parseInt($('#buy-min').val()); buyIntervalSeconds = parseInt($('#buy-sec').val()); GM_setValue('buyIntervalMinutes', buyIntervalMinutes); GM_setValue('buyIntervalSeconds', buyIntervalSeconds); if (isBuyEnabled) startAutoBuy(); }); $('#rst-hr, #rst-min').change(function() { restartIntervalHours = parseInt($('#rst-hr').val()); restartIntervalMinutes = parseInt($('#rst-min').val()); GM_setValue('restartIntervalHours', restartIntervalHours); GM_setValue('restartIntervalMinutes', restartIntervalMinutes); scheduleAutoRestart(); }); $('#btn-force-restart').click(function() { if(confirm('確定要刷新?')) performRestart(); }); } function performRestart() { if (Game.WriteSave) Game.WriteSave(); localStorage.setItem('cookieScriptRestarted', 'true'); setTimeout(() => { GM_openInTab(window.location.href, { active: true, insert: true, setParent: false }); setTimeout(() => window.close(), 1000); }, 500); } function scheduleAutoRestart() { if (restartIntervalId) clearInterval(restartIntervalId); let interval = (restartIntervalHours * 3600 + restartIntervalMinutes * 60 + restartIntervalSeconds) * 1000; if (interval < 60000) interval = 60000; nextRestartTime = Date.now() + interval; restartIntervalId = setInterval(performRestart, interval); } function setGameVolume(v) { try { if (Game.setVolume) Game.setVolume(v); } catch(e) {} } function formatMs(ms) { const s = Math.floor(ms/1000); return `${Math.floor(s/60)}:${s%60<10?'0':''}${s%60}`; } function generateOptions(min, max, sel, unit) { let h=''; for(let i=min; i<=max; i++) h+=``; return h; } function updateAllDisplays() { if (floatingButton) floatingButton.css('filter', isClickEnabled ? 'hue-rotate(0deg)' : 'grayscale(100%)'); } if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', () => setTimeout(init, 1500)); else setTimeout(init, 1500); })();