[Pokeclicker] Farm Plot Editor

Adds edit mode button to farm modal for directly setting berries at Berry stage

目前為 2025-09-19 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name          [Pokeclicker] Farm Plot Editor
// @namespace     Pokeclicker Scripts
// @author        samfp
// @description   Adds edit mode button to farm modal for directly setting berries at Berry stage
// @copyright     https://github.com/Ephenia
// @license       GPL-3.0 License
// @version       1.0.0

// @match         https://www.pokeclicker.com/
// @icon          https://www.google.com/s2/favicons?domain=pokeclicker.com
// @grant         unsafeWindow
// @run-at        document-idle
// ==/UserScript==

function initFarmPlotEditor() {
    let editMode = false;

    function createEditButton() {
        const shovelList = document.getElementById('shovelList');
        if (!shovelList) return;

        const buttonDiv = document.createElement('div');
        buttonDiv.className = 'row justify-content-center py-1';

        const button = document.createElement('button');
        button.id = 'farm-edit-mode-toggle';
        button.className = 'btn btn-block btn-danger';
        button.textContent = 'Edit Mode [OFF]';
        button.onclick = toggleEditMode;

        buttonDiv.appendChild(button);
        shovelList.before(buttonDiv);
    }

    function toggleEditMode() {
        editMode = !editMode;
        console.log('Farm Edit Mode:', editMode ? 'ON' : 'OFF');
        const button = document.getElementById('farm-edit-mode-toggle');
        button.className = `btn btn-block btn-${editMode ? 'success' : 'danger'}`;
        button.textContent = `Edit Mode [${editMode ? 'ON' : 'OFF'}]`;
    }

    function setPlotBerryAtBerryStage(plotIndex, berryType) {
        console.log(`Setting plot ${plotIndex} to berry ${berryType} (${BerryType[berryType]})`);

        if (plotIndex >= App.game.farming.plotList.length) {
            console.log(`Invalid plot index ${plotIndex}, max is ${App.game.farming.plotList.length - 1}`);
            return;
        }

        const plot = App.game.farming.plotList[plotIndex];

        // If plot has a berry, advance to berry stage and harvest
        if (plot.berry !== -1) {
            const berryData = App.game.farming.berryData[plot.berry];
            if (berryData && berryData.growthTime) {
                let targetAge = 0;
                for (let i = 0; i < 4 && i < berryData.growthTime.length; i++) {
                    targetAge += berryData.growthTime[i];
                }
                plot.age = targetAge;
                console.log(`Advanced existing berry to harvest stage`);
            }
            App.game.farming.harvest(plotIndex);
            console.log(`Harvested plot ${plotIndex}`);
        }

        // Plant new berry and advance to berry stage
        App.game.farming.plant(plotIndex, berryType);
        console.log(`Planted ${BerryType[berryType]} at plot ${plotIndex}`);

        const berryData = App.game.farming.berryData[berryType];
        if (berryData && berryData.growthTime) {
            let targetAge = 0;
            for (let i = 0; i < 4 && i < berryData.growthTime.length; i++) {
                targetAge += berryData.growthTime[i];
            }
            plot.age = targetAge;
            console.log(`Advanced to Berry stage (age: ${targetAge})`);
        }
    }

    function addPlotClickListeners() {
        console.log('Starting to look for farm container...');
        const checkForPlots = setInterval(() => {
            const farmContainer = document.querySelector('#farmContainer');
            console.log('Checking for farmContainer:', farmContainer ? 'found' : 'not found');

            // Also try alternative selectors
            const farmView = document.querySelector('#farmView');
            const plotElements = document.querySelectorAll('[data-bind*="plotList"]');
            console.log('farmView:', farmView ? 'found' : 'not found');
            console.log('plot elements found:', plotElements.length);

            if (farmContainer || farmView || plotElements.length > 0) {
                clearInterval(checkForPlots);
                console.log('Farm elements found, adding click listeners');

                const targetElement = farmContainer || farmView || document.body;
                console.log('Adding listener to:', targetElement.id || targetElement.tagName);

                targetElement.addEventListener('click', (e) => {
                    console.log('Click detected, edit mode:', editMode);
                    if (!editMode) return;

                    let target = e.target;
                    console.log('Initial target:', target.tagName, target.className);

                    // Check if we're clicking on a farm plot
                    let isPlotClick = false;
                    for (let i = 0; i < 10 && target; i++) {
                        if (target.hasAttribute('data-bind')) {
                            const dataBind = target.getAttribute('data-bind');
                            if (dataBind.includes('$index()')) {
                                isPlotClick = true;
                                break;
                            }
                        }
                        target = target.parentElement;
                    }

                    if (!isPlotClick) {
                        console.log('Not a plot click, allowing normal behavior');
                        return;
                    }

                    e.preventDefault();
                    e.stopPropagation();
                    console.log('Plot click intercepted');

                    target = e.target;
                    console.log('Initial target:', target.tagName, target.className);

                    // Check multiple levels up
                    for (let i = 0; i < 10 && target; i++) {
                        console.log(`Level ${i}:`, target.tagName, target.getAttribute('data-bind'));
                        if (target.hasAttribute('data-bind')) {
                            const dataBind = target.getAttribute('data-bind');
                            console.log('Found data-bind:', dataBind);

                            // Look for $index() which indicates we're in the foreach loop
                            if (dataBind.includes('$index()')) {
                                // Find the foreach element to get the plot index
                                let foreachElement = target;
                                while (foreachElement && !foreachElement.getAttribute('data-bind')?.includes('foreach: App.game.farming.plotList')) {
                                    foreachElement = foreachElement.parentElement;
                                }

                                if (foreachElement) {
                                    // Get all plot elements and find which one this is
                                    const allPlots = Array.from(foreachElement.children);
                                    console.log(`Total children in foreach: ${allPlots.length}`);
                                    console.log(`Total plots in game: ${App.game.farming.plotList.length}`);

                                    let plotIndex = -1;

                                    // Find the plot container that contains our clicked element
                                    let plotContainer = target;
                                    while (plotContainer && plotContainer.parentElement !== foreachElement) {
                                        plotContainer = plotContainer.parentElement;
                                    }

                                    if (plotContainer) {
                                        plotIndex = allPlots.indexOf(plotContainer);
                                        console.log(`Found plot container at DOM index ${plotIndex}`);

                                        // The DOM might include non-plot elements, so let's count only actual plots
                                        let actualPlotIndex = 0;
                                        for (let j = 0; j < plotIndex; j++) {
                                            if (allPlots[j].querySelector('[data-bind*="$index()"]')) {
                                                actualPlotIndex++;
                                            }
                                        }
                                        plotIndex = actualPlotIndex;
                                        console.log(`Corrected to actual plot index ${plotIndex}`);
                                    }

                                    if (plotIndex >= 0) {
                                        const selectedBerry = FarmController.selectedBerry();
                                        console.log(`Plot ${plotIndex} clicked, selected berry: ${selectedBerry}`);
                                        if (selectedBerry !== undefined) {
                                            setPlotBerryAtBerryStage(plotIndex, selectedBerry);
                                        }
                                        return;
                                    }
                                }
                            }
                        }
                        target = target.parentElement;
                    }
                    console.log('No plot found in click hierarchy');
                }, true);
            }
        }, 1000);
    }

    // Initialize when the game is loaded
    const initInterval = setInterval(() => {
        if (typeof App !== 'undefined' && App.game && App.game.farming && typeof FarmController !== 'undefined') {
            clearInterval(initInterval);
            createEditButton();
            addPlotClickListeners();
        }
    }, 1000);
}

// Auto-start the script
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initFarmPlotEditor);
} else {
    initFarmPlotEditor();
}