MouseHunt Auto Disarm/Swap Bait

Automatically Disarms/Swaps bait when the remaining quantity matches or goes below user input

// ==UserScript==
// @name         MouseHunt Auto Disarm/Swap Bait
// @author       Kane Kiew
// @namespace    https://greasyfork.org/en/users/979741
// @version      2.2
// @description  Automatically Disarms/Swaps bait when the remaining quantity matches or goes below user input
// @match	    http://mousehuntgame.com/*
// @match		https://mousehuntgame.com/*
// @match		http://www.mousehuntgame.com/*
// @match		https://www.mousehuntgame.com/*
// @match       http://www.mousehuntgame.com/camp.php*
// @match       https://www.mousehuntgame.com/camp.php*
// @match		http://apps.facebook.com/mousehunt/*
// @match		https://apps.facebook.com/mousehunt/*
// @icon         https://www.google.com/s2/favicons?domain=mousehuntgame.com
// @grant        none
// @license 	GPL-3.0+; http://www.gnu.org/copyleft/gpl.html
// ==/UserScript==

(function () {
    'use strict';
  // Declare the dropdownDiv variable outside the function scope
  let dropdownDiv;
    // Function to update the selected cheese UI element
    function updateSelectedCheeseUI(selectedBait) {
        selectedCheeseElement.textContent = `Selected Cheese: ${selectedBait}`;
    }
    // Watch for changes in bait quantity using MutationObserver

    const baitQuantityObserver = new MutationObserver(() => {
        console.log('MutationObserver detected a change in bait quantity');
        updateUI();
        checkQuantity();
    });

    // Select the parent element of bait quantity using querySelector

    const baitQuantityParent = document.querySelector('.campPage-trap-baitDetails');

    baitQuantityObserver.observe(baitQuantityParent, { childList: true, subtree: true });

    // Periodically check for changes using requestIdleCallback
    function checkForChanges() {
        if (baitQuantityObserver.takeRecords().length > 0) {
            updateUI();
            checkQuantity();
        }
        requestIdleCallback(checkForChanges);
    }

    requestIdleCallback(checkForChanges);

    function observeDOMChanges() {
        // Create a new mutation observer instance
        const observer = new MutationObserver(function (mutations) {
            mutations.forEach(function (mutation) {
                // Check if the desired element or class name has been added to the DOM
                if (
                    mutation.addedNodes.length > 0 &&
                    (mutation.target.getElementsByClassName(
                        "trapImageView-trapAuraContainer"
                    )[0] &&
                     document.getElementById("mousehuntContainer").className.includes(
                        "PageCamp"
                    ))
                ) {
                    trapChangeListener();
                }
            });
        });

        // Specify the target node and options for the observer
        const targetNode = document.documentElement;
        const config = { childList: true, subtree: true };

        // Start observing the DOM changes
        observer.observe(targetNode, config);
    }

    function trapChangeListener() {
        const originalOpen = XMLHttpRequest.prototype.open;
        XMLHttpRequest.prototype.open = function () {
            this.addEventListener("load", function () {
                if (
                    this.responseURL ===
                    "https://www.mousehuntgame.com/managers/ajax/users/changetrap.php"
                ) {
                    console.log("Mutation Observer detected a change. trapchange");
                    updateUI();
                    checkQuantity();
                } else if (
                    this.responseURL ===
                    "https://www.mousehuntgame.com/managers/ajax/turns/activeturn.php"
                ) {
                    console.log("Intercepted activeturn.php request(horn sounded)");
                    updateUI();
                    checkQuantity();
                } else if (
                    this.responseURL ===
                    "https://www.mousehuntgame.com/managers/ajax/purchases/itempurchase.php"
                    ){
                    console.log("Intercepted itempurchase.php");
                    updateUI();
                    checkQuantity();
                }
            });
            originalOpen.apply(this, arguments);
        };
    }

    // Call the observeDOMChanges function to start observing DOM changes
    observeDOMChanges();

    // Search/dropdown menu and baitlist retrieved by intercepting
    function createDropdown(baitList) {
        dropdownDiv = document.createElement('div');
        dropdownDiv.id = 'bait-dropdown';
        dropdownDiv.style.position = 'fixed';
        dropdownDiv.style.top = '117px';
        dropdownDiv.style.left = '10px';
        dropdownDiv.style.zIndex = '9999';

        const dropdown = $('<select></select>');

        if (baitList.length === 0) {
            const option = document.createElement('option');
            option.value = '';
            option.text = 'No Baits found';
            dropdown.append(option);
        } else {
            const defaultOption = document.createElement('option');
            defaultOption.value = '';
            defaultOption.text = 'Select a bait...';
            dropdown.append(defaultOption);

            baitList.forEach((bait) => {
                const option = document.createElement('option');
                option.value = bait.itemID;
                option.text = `${bait.name} (ID: ${bait.itemID})`;
                dropdown.append(option);
            });
        }

        $(dropdownDiv).append(dropdown);
        document.body.appendChild(dropdownDiv);

        // Initialize Select2
        dropdown.select2();

        // Add event listener to Select2 dropdown
        dropdown.on('change', function (e) {
            const selectedBaitID = parseInt(e.target.value);
            localStorage.setItem('selectedBaitID', selectedBaitID);
            const selectedBait = e.target.selectedOptions[0].text;
            localStorage.setItem('selectedBait', selectedBait);
            console.log('Selected bait ID:', selectedBaitID);
            console.log('Selected bait:', selectedBait);
            checkQuantity(selectedBaitID);
            updateSelectedCheeseUI(selectedBait);
        });
    }

    function processTrapComponents(components) {
        const baitList = components
        .filter((component) => component.classification === 'bait')
        .map((component) => ({
            itemID: component.item_id,
            name: component.name,
        }))
        .sort((a, b) => a.name.localeCompare(b.name)); // Sort by name

        // Remove existing dropdown if it exists
        const existingDropdown = document.getElementById('bait-dropdown');
        if (existingDropdown) {
            existingDropdown.remove();
        }

        createDropdown(baitList);
        updateUI();
    }

    function retrieveTrapComponents() {
        const xhr = new XMLHttpRequest();
        xhr.addEventListener('load', function () {
            if (xhr.status === 200) {
                let data;
                try {
                    data = JSON.parse(xhr.responseText).components;
                    if (data && data.length > 0) {
                        processTrapComponents(data);
                    } else {
                        console.log('Invalid components array data from gettrapcomponents.php');
                        setTimeout(retrieveTrapComponents, 5000); // Retry after 5 seconds
                    }
                } catch (error) {
                    console.log('Failed to process server response for gettrapcomponents.php');
                    console.error(error.stack);
                    setTimeout(retrieveTrapComponents, 5000); // Retry after 5 seconds
                }
            } else {
                console.log('Error retrieving trap components from gettrapcomponents.php');
                setTimeout(retrieveTrapComponents, 5000); // Retry after 5 seconds
            }
        });
        xhr.open('GET', 'https://www.mousehuntgame.com/managers/ajax/users/gettrapcomponents.php');
        xhr.send();
    }

    const storedBaitList = localStorage.getItem('baitList');
    if (storedBaitList) {
        const baitList = JSON.parse(storedBaitList);
        createDropdown(baitList);
    } else {
        createDropdown([]);
    }

    // Get bait quantity from the page
    function getBaitQuantity() {
        const hudBaitQuantity = document.querySelector('.campPage-trap-baitDetails .campPage-trap-baitQuantity');
        if (hudBaitQuantity !== null) {
            const quantityText = hudBaitQuantity.innerText.replace(/,/g, ''); // Remove commas from quantity text
            return parseInt(quantityText);
        } else {
            return 0;
        }
    }

    // Create UI elements
    const createUIElements = () => {
        const createUIElement = (left, top, text) => {
            const element = document.createElement('div');
            element.style.position = 'fixed';
            element.style.left = left;
            element.style.top = top;
            element.style.backgroundColor = '#fff';
            element.style.padding = '5px';
            element.style.zIndex = '9999';
            element.textContent = text;
            document.body.appendChild(element);
            return element;
        };

        return {
            // Create selected cheese UI element
            selectedCheeseElement: createUIElement('10px', '92px', 'Selected Cheese: Not Set'),
            targetQuantityElement: createUIElement('10px', '10px', 'Target Quantity: Not Set(Click me to set)'),
            baitQuantityElement: createUIElement('10px', '35px', 'Bait Quantity: 0'),
        };
    };

    const { targetQuantityElement, baitQuantityElement, selectedCheeseElement } = createUIElements();

    // Update selected cheese UI element based on the stored value in local storage
    const storedSelectedBait = localStorage.getItem('selectedBait');
    if (storedSelectedBait) {
        updateSelectedCheeseUI(storedSelectedBait);
    } else {
        updateSelectedCheeseUI('Not Set');
    }

    // Create toggle switch UI element
    const toggleSwitchElement = document.createElement('div');
    toggleSwitchElement.style.position = 'fixed';
    toggleSwitchElement.style.width = '80px';
    toggleSwitchElement.style.height = '10px';
    toggleSwitchElement.style.left = '10px';
    toggleSwitchElement.style.top = '60px';
    toggleSwitchElement.style.backgroundColor = '#fff';
    toggleSwitchElement.style.padding = '10px';
    toggleSwitchElement.style.zIndex = '9999';
    toggleSwitchElement.style.display = 'flex';
    toggleSwitchElement.style.alignItems = 'center';
    toggleSwitchElement.style.justifyContent = 'space-between';
    document.body.appendChild(toggleSwitchElement);

    const sliderLabelElement = document.createElement('div');
    sliderLabelElement.style.fontWeight = 'bold';
    sliderLabelElement.style.marginLeft = '5px';
    toggleSwitchElement.appendChild(sliderLabelElement);

    const sliderElement = document.createElement('div');
    sliderElement.style.position = 'relative';
    sliderElement.style.width = '10px';
    sliderElement.style.height = '15px';
    sliderElement.style.backgroundColor = '#ccc';
    sliderElement.style.borderRadius = '5px';
    sliderElement.style.cursor = 'pointer';
    sliderElement.style.transition = 'top 0.3s ease-in-out';
    toggleSwitchElement.appendChild(sliderElement);

    // Update target quantity UI
    const updateTargetQuantityUI = () => {
        targetQuantity = parseInt(localStorage.getItem('targetQuantity'));
        if (targetQuantity === null || targetQuantity === 0) {
            targetQuantityElement.textContent = 'Target Quantity: Not Set(Click me to set)';
        } else {
            targetQuantityElement.textContent = `Target Quantity: ${targetQuantity}`;
        }
    };

    // Update bait quantity UI
    const updateBaitQuantityUI = () => {
        const baitQuantity = getBaitQuantity();
        baitQuantityElement.textContent = `Bait Quantity: ${baitQuantity}`;
    };

    // Update toggle switch UI
    const updateToggleSwitchUI = () => {
        localStorage.setItem('isDisarmSelected', isDisarmSelected.toString());
        if (isDisarmSelected) {
            sliderElement.style.top = '-7px';
            sliderLabelElement.textContent = 'Disarm';
        } else {
            sliderElement.style.top = '6px';
            sliderLabelElement.textContent = 'Swap Bait';
        }
    };

    // Update UI elements
// Update UI elements
const updateUI = () => {
  updateSelectedCheeseUI(localStorage.getItem('selectedBait'));
  updateTargetQuantityUI();
  updateBaitQuantityUI();
  updateToggleSwitchUI();
    if (isDisarmSelected) {
      selectedCheeseElement.style.display = 'none';
      dropdownDiv.style.display = 'none';
    } else {
      selectedCheeseElement.style.display = 'block';
      if (!isDisarmSelected) {
        dropdownDiv.style.display = 'block';
      }
    }
  };

    // Check if the action should be performed based on target quantity
    const checkQuantity = () => {
        const selectedBaitID = parseInt(localStorage.getItem('selectedBaitID'));
        const baitQuantity = getBaitQuantity();
        if (targetQuantity !== null && targetQuantity !== 0 && baitQuantity !== 0 && targetQuantity >= baitQuantity) {
            if (isDisarmSelected) {
                hg.utils.TrapControl.disarmBait().go();
                targetQuantity = 0;
                localStorage.setItem('targetQuantity', targetQuantity);
                updateUI();
            } else {
                hg.utils.TrapControl.armItem(selectedBaitID, 'bait');
                hg.utils.TrapControl.go();
                targetQuantity = 0;
                localStorage.setItem('targetQuantity', targetQuantity);
                updateUI();
            }
        }
    };

    // Prompt user to input the remaining bait quantity
    const updatePrompt = () => {
        targetQuantity = prompt('Enter the remaining bait quantity:');
        localStorage.setItem('targetQuantity', targetQuantity);
        updateUI();
        checkQuantity();
    };

    // Add event listener to target quantity element
    targetQuantityElement.addEventListener('click', updatePrompt);

// Update UI when the toggle switch is clicked
toggleSwitchElement.addEventListener('click', () => {
  isDisarmSelected = !isDisarmSelected;
  updateUI();
  checkQuantity();
});


    // Retrieve trap components and process them
    retrieveTrapComponents();

    // Initialize target quantity, isDisarmSelected, and update UI
    let targetQuantity = parseInt(localStorage.getItem('targetQuantity'));
    if (isNaN(targetQuantity)) {
        targetQuantity = 0;
    }
// Initialize isDisarmSelected and update UI
let isDisarmSelected = localStorage.getItem('isDisarmSelected') === 'true';
updateUI();
})();