[Pokeclicker] Farm Plot Editor

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

// ==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
// @license       GPL-3.0 License
// @version       1.0.2

// @homepageURL   https://github.com/Ephenia/Pokeclicker-Scripts/
// @supportURL    https://github.com/Ephenia/Pokeclicker-Scripts/issues

// @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];

        // Step 1: If there is a berry, advance it to berry stage
        if (plot.berry !== -1) {
            const existingBerry = plot.berry;
            console.log(`Found existing berry: ${existingBerry} (${BerryType[existingBerry]})`);
            const existingBerryData = App.game.farming.berryData[existingBerry];
            const existingTargetAge = existingBerryData.growthTime[3];
            console.log(`Existing berry data:`, existingBerryData.growthTime);
            plot.age = existingTargetAge;
            console.log(`Step 1: Advanced existing berry ${BerryType[existingBerry]} to harvest stage (age: ${existingTargetAge})`);

            setTimeout(() => {
                // Step 2: Harvest plot
                App.game.farming.harvest(plotIndex);
                console.log(`Step 2: Harvested plot ${plotIndex}`);

                setTimeout(() => {
                    // Step 3: Plant selected berry
                    App.game.farming.plant(plotIndex, berryType);
                    console.log(`Step 3: Planted ${BerryType[berryType]} at plot ${plotIndex}`);

                    setTimeout(() => {
                        // Step 4: Advance new berry to berry stage
                        const newBerryData = App.game.farming.berryData[berryType];
                        const newTargetAge = newBerryData.growthTime[3];
                        console.log(`New berry data:`, newBerryData.growthTime);
                        plot.age = newTargetAge;
                        console.log(`Step 4: Advanced new berry to Berry stage (age: ${newTargetAge})`);
                    }, 100);
                }, 100);
            }, 100);
        } else {
            // Step 3: Plant selected berry
            App.game.farming.plant(plotIndex, berryType);
            console.log(`Step 3: Planted ${BerryType[berryType]} at plot ${plotIndex}`);

            setTimeout(() => {
                // Step 4: Advance new berry to berry stage
                const newBerryData = App.game.farming.berryData[berryType];
                const newTargetAge = newBerryData.growthTime[3];
                console.log(`New berry data:`, newBerryData.growthTime);
                plot.age = newTargetAge;
                console.log(`Step 4: Advanced new berry to Berry stage (age: ${newTargetAge})`);
            }, 100);
        }
    }

    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();
}