// ==UserScript== // @name Cookie Clicker Ultimate Automation // @name:zh-TW 餅乾點點樂全自動掛機輔助 (Cookie Clicker) // @name:zh-CN 饼干点点乐全自动挂机辅助 (Cookie Clicker) // @namespace http://tampermonkey.net/ // @version 8.8.9 // @description Automated clicker, auto-buy, auto-harvest, garden manager (5 slots), stock market, season manager, Santa evolver, Smart Sugar Lump harvester, Dragon Aura management, and the new Gambler feature. // @description:zh-TW 全功能自動掛機腳本 v8.8.9 Feature: Garden Editor UX Overhaul & Group Renaming // @author You & AI Architect // @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== /* 變更日誌 (Changelog): v8.8.9 Editor UX Overhaul (2025): - [UI] GardenGrid: 重構編輯器工具列,新增「儲存」、「清空」、「放棄」按鈕,明確區分編輯/預覽狀態。 - [UI] GardenGrid: 群組選單旁新增「✏️」按鈕,支援群組重新命名。 - [Logic] Garden: 實作藍圖編輯器的「儲存」邏輯,直接寫入 GardenProfiles 並刷新視圖。 - [Logic] Garden: 優化 Input 輸入行為,支援清除為空值 (視為-1) 及數字格式自動修正 (01 -> 1)。 v8.8.9 Evolution Protocol (2025): - [UI] GardenGrid: 新增未解鎖種子的視覺回饋。當藍圖包含未解鎖種子時,格子將顯示灰色鎖頭圖示 (🔒)。 - [UI] Styles: 新增 .cc-dashboard-locked 樣式。 - [Logic] Garden: 再次確認同步播種與單獨播種邏輯,確保嚴格忽略未解鎖的植物。 v8.8.9 Blueprint Editor (2025): - [UI] GardenGrid: 實作「編輯模式」,允許用戶手動輸入 ID (0-33) 規劃陣型。 - [UI] Layout: 重組花園預覽面板,新增群組切換下拉選單。 - [Logic] Garden: 存檔邏輯升級,編輯模式下儲存 Input 數值,非編輯模式儲存實際花園狀態。 - [Safety] Garden: 編輯模式期間,自動阻斷花園的自動種植/鏟除邏輯。 v8.8.9 Data Structure Refactor (2025): - [Core] Config: 引入 GardenProfiles 資料結構,支援群組化存檔管理。 - [Migration] Logic: 實作 v8.8.9 自動遷移邏輯,將舊版存檔無縫轉換為新版 Profile 結構。 */ (function() { 'use strict'; // ═══════════════════════════════════════════════════════════════ // 0. 全域配置與狀態 (Configuration & State) // ═══════════════════════════════════════════════════════════════ const Config = { // 開關狀態 Flags: { GlobalMasterSwitch: GM_getValue('isGlobalMasterSwitchEnabled', true), Click: GM_getValue('isClickEnabled', true), Buy: GM_getValue('isBuyEnabled', true), Golden: GM_getValue('isGoldenEnabled', true), Spell: GM_getValue('isSpellEnabled', true), Garden: GM_getValue('isGardenEnabled', true), Research: GM_getValue('isResearchEnabled', true), AutoWrinkler: GM_getValue('isAutoWrinklerEnabled', true), Stock: GM_getValue('isStockEnabled', true), SE: GM_getValue('isSEEnabled', true), Season: GM_getValue('isSeasonEnabled', true), Santa: GM_getValue('isSantaEnabled', true), DragonAura: GM_getValue('isDragonAuraEnabled', true), GardenOverlay: GM_getValue('isGardenOverlayEnabled', true), GardenAvoidBuff: GM_getValue('isGardenAvoidBuff', true), GardenMutation: GM_getValue('isGardenMutationEnabled', false), SyncPlanting: GM_getValue('isSyncPlantingEnabled', false), SavingMode: GM_getValue('isSavingModeEnabled', false), SavingReplant: GM_getValue('isSavingReplantEnabled', true), AutoPledge: GM_getValue('isAutoPledgeEnabled', true), ShowCountdown: GM_getValue('showCountdown', true), ShowBuffMonitor: GM_getValue('showBuffMonitor', true), ShowGardenProtection: GM_getValue('showGardenProtection', true), SpendingLocked: GM_getValue('spendingLocked', false), GodzamokCombo: GM_getValue('isGodzamokComboEnabled', false), ShowGardenGrid: GM_getValue('isShowGardenGrid', false) }, // 參數 Settings: { Volume: GM_getValue('gameVolume', 50), ClickInterval: GM_getValue('clickInterval', 10), BuyStrategy: GM_getValue('buyStrategy', 'expensive'), BuyIntervalMs: (GM_getValue('buyIntervalHours', 0) * 3600 + GM_getValue('buyIntervalMinutes', 0) * 60 + GM_getValue('buyIntervalSeconds', 10)) * 1000, RestartIntervalMs: (GM_getValue('restartIntervalHours', 1) * 3600 + GM_getValue('restartIntervalMinutes', 0) * 60 + GM_getValue('restartIntervalSeconds', 0)) * 1000, MaxWizardTowers: 800, SugarLumpGoal: 100, SpellCooldownSuccess: 60000, SpellCooldownFail: 60000, GardenBufferTime: 5000, GodzamokMinMult: 1000, GodzamokSellAmount: 100, GodzamokTargetBuilding: 'Farm', GodzamokCooldown: 15000, GodzamokBuyBackTime: 11000, GodzamokBuyback: GM_getValue('godzamokBuyback', 400), GodzamokHotkey: GM_getValue('godzamokHotkey', '^+F9'), GodzamokBuyHotkey: GM_getValue('godzamokBuyHotkey', 'F10') }, // 記憶 Memory: { // [v8.8.9] Config & Memory 變更: 新增 GardenProfiles GardenProfiles: null, // 由 Core.init 填充 SavedGardenPlot: Array(6).fill().map(() => Array(6).fill(-1)), // 剪貼簿 (不變) // Legacy keys preserved to avoid reference errors during migration logic GardenSavedPlots: GM_getValue('gardenSavedPlots', ['', '', '', '', '']), GardenSelectedSlot: GM_getValue('gardenSelectedSlot', 0), GardenSlotNames: GM_getValue('gardenSlotNames', ['Layout 1', 'Layout 2', 'Layout 3', 'Layout 4', 'Layout 5']), PanelX: GM_getValue('panelX', window.innerWidth / 2 - 200), PanelY: GM_getValue('panelY', 100), BuffX: GM_getValue('buffX', window.innerWidth - 340), BuffY: GM_getValue('buffY', 150), CountdownX: GM_getValue('countdownX', window.innerWidth - 170), CountdownY: GM_getValue('countdownY', 10), ButtonX: GM_getValue('buttonX', 50), ButtonY: GM_getValue('buttonY', 50), GardenProtectionX: GM_getValue('gardenProtectionX', 10), GardenProtectionY: GM_getValue('gardenProtectionY', 10), ActionLogX: GM_getValue('actionLogX', window.innerWidth - 420), ActionLogY: GM_getValue('actionLogY', window.innerHeight - 350), GardenGridX: GM_getValue('gardenGridX', 100), GardenGridY: GM_getValue('gardenGridY', 100), LastActiveTab: GM_getValue('lastActiveTab', 'core'), GardenLeftExpanded: GM_getValue('gardenLeftExpanded', false), GardenRightExpanded: GM_getValue('gardenRightExpanded', false), LogFontSize: GM_getValue('logFontSize', 12), LogOpacity: GM_getValue('logOpacity', 0.95), SavedSpendingStates: GM_getValue('savedSpendingStates', { Buy: true, Garden: true, Research: true, Stock: true }), GardenProtectionMinimized: GM_getValue('gardenProtectionMinimized', false), LastBuffEndTime: GM_getValue('lastBuffEndTime', 0), SavingModeExpanded: GM_getValue('savingModeExpanded', false) } }; // 運行時計時器與緩存 const Runtime = { Cache: { BigCookie: null }, Timers: { NextBuy: 0, NextRestart: 0, NextGarden: 0, NextStock: 0, NextSeasonCheck: 0, NextGodzamokCombo: 0, GardenWarmup: 0, SeasonBusy: 0 }, Stats: { ClickCount: 0, BuyUpgradeCount: 0, BuyBuildingCount: 0 }, GodzamokState: { isActive: false, soldAmount: 0, originalBuyState: true, // [v8.8.8] 戒嚴協議狀態 mutationRestoreTimer: null, wasMutationEnabled: false }, GodzamokTacticalState: { status: 'IDLE', // Enum: 'IDLE', 'COOLDOWN' lock: false, // 防止重複觸發的鎖 reloadTimer: null // [New v8.8.8.2] 用於存儲自動買回的計時器ID }, DragonState: { isBursting: false, lastSwitchTime: 0, currentPhase: 'IDLE' }, ModuleFailCount: {}, OriginalTitle: document.title, SeasonState: { CurrentStage: 0, Roadmap: [ { id: 'valentines', name: 'Valentines', target: 'Normal' }, { id: 'christmas', name: 'Christmas', target: 'MaxSanta' }, { id: 'easter', name: 'Easter', target: 'Normal' }, { id: 'halloween', name: 'Halloween', target: 'Normal' } ], isFarming: false }, WarmupForceShown: false }; // ═══════════════════════════════════════════════════════════════ // Logger 模組 // ═══════════════════════════════════════════════════════════════ const Logger = { log: function(module, message) { const formatted = `[${module}] ${message}`; console.log(`ℹ️ ${formatted}`); if (UI.ActionLog && UI.ActionLog.append) UI.ActionLog.append(formatted, 'info'); }, warn: function(module, message) { const formatted = `[${module}] ${message}`; console.warn(`⚠️ ${formatted}`); if (UI.ActionLog && UI.ActionLog.append) UI.ActionLog.append(formatted, 'warn'); }, error: function(module, message, error) { const formatted = `[${module}] ${message}`; console.error(`❌ ${formatted}`, error || ''); if (UI.ActionLog && UI.ActionLog.append) UI.ActionLog.append(formatted, 'error'); if (typeof Game !== 'undefined' && Game.Notify) { Game.Notify('腳本錯誤', `${module}: ${message}`, [10, 6], 10); } }, success: function(module, message) { const formatted = `[${module}] ${message}`; console.log(`%c✅ ${formatted}`, 'color: #4caf50; font-weight: bold;'); if (UI.ActionLog && UI.ActionLog.append) UI.ActionLog.append(formatted, 'success'); }, critical: function(module, message) { const formatted = `[${module}] ⚠️ CRITICAL: ${message}`; console.error(`%c❌ ${formatted}`, 'color: #ff0000; font-weight: bold; background: #000; padding: 2px 5px;'); if (UI.ActionLog && UI.ActionLog.append) UI.ActionLog.append(formatted, 'error'); if (typeof Game !== 'undefined' && Game.Notify) { Game.Notify('功能已停用', `${module}: ${message}`, [10, 6], 10); } } }; // ═══════════════════════════════════════════════════════════════ // 1. UI 模組 // ═══════════════════════════════════════════════════════════════ const UI = { Elements: { Panel: null, FloatingBtn: null, Countdown: null, BuffMonitor: null }, _lastBuffSnapshot: null, getLocalizedPlantName: function(gridId) { if (!gridId || gridId === 0) return ''; const plantId = gridId - 1; if (typeof Game === 'undefined' || !Game.Objects['Farm'].minigame) return ''; const plant = Game.Objects['Farm'].minigame.plantsById[plantId]; return plant ? plant.name : ''; }, updateAllLayoutSelectors: function() { const selectors = [$('#gardenLayoutSelect'), $('#gardenLayoutSelectGrid')]; const groupSelector = $('#gardenGroupSelect'); const profiles = Config.Memory.GardenProfiles; if (!profiles) return; // Safety const activeGroup = profiles.activeGroup; const group = profiles.groups[activeGroup]; const plots = group.slots; const names = group.slotNames; const selected = Config.Memory.GardenSelectedSlot; // Update Group Select if (groupSelector.length) { groupSelector.empty(); profiles.groups.forEach((g, idx) => { const opt = $('