GeoGuessr Force NMPZ

A script that forces NMPZ mode for yourself in GeoGuessr.

// ==UserScript==
// @name         GeoGuessr Force NMPZ
// @name:ja      GeoGuessr 強制NMPZ
// @namespace    http://tampermonkey.net/
// @version      1.00
// @description  A script that forces NMPZ mode for yourself in GeoGuessr.
// @description:ja GeoGuessrで自分だけ強制的にNMPZモードにするスクリプトです。
// @author       sino
// @match        https://www.geoguessr.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com
// @license      MIT
// @run-at       document-start
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// ==/UserScript==

(function() {
    'use strict';

    const STORAGE_KEY = 'nmpz_enabled';
    let menuCommandId = null;
    let isEnabled = GM_getValue(STORAGE_KEY, true);

    function isGamePage() {
        const path = window.location.pathname;
        return path.includes('/game/') ||
               path.includes('/duels/') ||
               path.includes('/team-duels/');
    }

    function preventEvent(e) {
        e.preventDefault();
        e.stopPropagation();
        return false;
    }

    function preventDragAndZoom(e) {
        if (e.type === 'mousemove' || e.type === 'wheel' ||
            e.type === 'touchmove' || e.type === 'drag' || e.type === 'dragstart') {
            e.preventDefault();
            e.stopPropagation();
            return false;
        }
    }

    function preventMovementKeys(e) {
        if (!isEnabled || !isGamePage()) return;

        const activeElement = document.activeElement;
        if (activeElement && (
            activeElement.tagName === 'INPUT' ||
            activeElement.tagName === 'TEXTAREA' ||
            activeElement.isContentEditable
        )) {
            return;
        }

        const key = e.key.toUpperCase();
        if (key === 'N' || key === 'W' || key === 'A' || key === 'S' || key === 'D') {
            e.preventDefault();
            e.stopPropagation();
            return false;
        }
    }

    function disableMovementAndZoom() {
        if (!isGamePage() || !isEnabled) return false;

        const panorama = document.querySelector('div.game_panorama__6X071');
        if (!panorama || panorama.dataset.disableApplied === 'true') {
            return panorama && panorama.dataset.disableApplied === 'true';
        }

        let overlay = document.getElementById('geoguessr-disable-overlay');
        if (overlay) overlay.remove();

        overlay = document.createElement('div');
        overlay.id = 'geoguessr-disable-overlay';
        overlay.style.cssText = `
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 1;
            cursor: pointer;
            background-color: transparent;
            pointer-events: auto;
        `;

        overlay.addEventListener('mousemove', preventDragAndZoom, true);
        overlay.addEventListener('wheel', preventDragAndZoom, true);
        overlay.addEventListener('touchmove', preventDragAndZoom, true);
        overlay.addEventListener('drag', preventDragAndZoom, true);
        overlay.addEventListener('dragstart', preventDragAndZoom, true);
        overlay.addEventListener('contextmenu', preventEvent, true);

        const currentPosition = getComputedStyle(panorama).position;
        if (currentPosition === 'static') {
            panorama.style.position = 'relative';
        }

        panorama.appendChild(overlay);
        panorama.dataset.disableApplied = 'true';

        return true;
    }

    const compassEventHandlers = new WeakMap();

    function disableControls() {
        if (!isGamePage() || !isEnabled) return false;

        let foundAny = false;

        const compassButtons = document.querySelectorAll('button.compass_compass__lRB0J.compass_clickable__Yt4eB[data-qa="compass"]');
        compassButtons.forEach(button => {
            if (!button.dataset.clickDisabled) {
                const handlers = {
                    click: (e) => preventEvent(e),
                    mousedown: (e) => preventEvent(e),
                    mouseup: (e) => preventEvent(e),
                    touchstart: (e) => preventEvent(e),
                    touchend: (e) => preventEvent(e)
                };
                
                compassEventHandlers.set(button, handlers);
                
                button.addEventListener('click', handlers.click, true);
                button.addEventListener('mousedown', handlers.mousedown, true);
                button.addEventListener('mouseup', handlers.mouseup, true);
                button.addEventListener('touchstart', handlers.touchstart, true);
                button.addEventListener('touchend', handlers.touchend, true);
                button.style.pointerEvents = 'none';
                button.dataset.clickDisabled = 'true';
                foundAny = true;
            }
        });

        return foundAny;
    }

    function enableControls() {
        const compassButtons = document.querySelectorAll('button.compass_compass__lRB0J.compass_clickable__Yt4eB[data-qa="compass"]');
        compassButtons.forEach(button => {
            if (button.dataset.clickDisabled) {
                const handlers = compassEventHandlers.get(button);
                if (handlers) {
                    button.removeEventListener('click', handlers.click, true);
                    button.removeEventListener('mousedown', handlers.mousedown, true);
                    button.removeEventListener('mouseup', handlers.mouseup, true);
                    button.removeEventListener('touchstart', handlers.touchstart, true);
                    button.removeEventListener('touchend', handlers.touchend, true);
                    compassEventHandlers.delete(button);
                }
                button.style.pointerEvents = '';
                delete button.dataset.clickDisabled;
            }
        });
    }

    function removeControlGroups() {
        if (!isGamePage() || !isEnabled) return false;

        let foundAny = false;
        const controlGroups = document.querySelectorAll('div.styles_controlGroup__2t2NT');
        controlGroups.forEach(group => {
            if (!group.dataset.removed) {
                group.dataset.removed = 'true';
                group.style.display = 'none';
                foundAny = true;
            }
        });

        const columnTwo = document.querySelectorAll('div.styles_columnTwo__kyT60');
        columnTwo.forEach(col => {
            if (!col.dataset.removed) {
                col.dataset.removed = 'true';
                col.style.display = 'none';
                foundAny = true;
            }
        });

        return foundAny;
    }

    function restoreControlGroups() {
        const controlGroups = document.querySelectorAll('div.styles_controlGroup__2t2NT');
        controlGroups.forEach(group => {
            if (group.dataset.removed) {
                group.style.display = '';
                delete group.dataset.removed;
            }
        });

        const columnTwo = document.querySelectorAll('div.styles_columnTwo__kyT60');
        columnTwo.forEach(col => {
            if (col.dataset.removed) {
                col.style.display = '';
                delete col.dataset.removed;
            }
        });
    }

    function removeTooltips() {
        if (!isGamePage() || !isEnabled) return false;

        let foundAny = false;

        const tooltips = document.querySelectorAll('div.tooltip_tooltip__3D6bz');
        tooltips.forEach(tooltip => {
            if (!tooltip.dataset.removed) {
                tooltip.dataset.removed = 'true';
                tooltip.style.display = 'none';
                foundAny = true;
            }
        });

        return foundAny;
    }

    function restoreTooltips() {
        const tooltips = document.querySelectorAll('div.tooltip_tooltip__3D6bz');
        tooltips.forEach(tooltip => {
            if (tooltip.dataset.removed) {
                tooltip.style.display = '';
                delete tooltip.dataset.removed;
            }
        });
    }

    function removeOverlay() {
        const overlay = document.getElementById('geoguessr-disable-overlay');
        if (overlay) overlay.remove();

        const panoramas = document.querySelectorAll('div.game_panorama__6X071');
        panoramas.forEach(panorama => {
            delete panorama.dataset.disableApplied;
        });
    }

    function enableFeatures() {
        if (isGamePage()) {
            disableMovementAndZoom();
            disableControls();
            removeControlGroups();
            removeTooltips();
        }
    }

    function disableFeatures() {
        removeOverlay();
        enableControls();
        restoreControlGroups();
        restoreTooltips();
    }

    function toggleEnabled() {
        isEnabled = !isEnabled;
        GM_setValue(STORAGE_KEY, isEnabled);

        if (isEnabled) {
            enableFeatures();
        } else {
            disableFeatures();
        }

        updateMenuCommand();
    }

    function updateMenuCommand() {
        if (menuCommandId !== null) {
            GM_unregisterMenuCommand(menuCommandId);
        }

        const status = isEnabled ? 'Enabled ✅' : 'Disabled ❌';
        menuCommandId = GM_registerMenuCommand(`NMPZ Mode: ${status}`, toggleEnabled, {
            autoClose: false
        });
    }

    document.addEventListener('keydown', preventMovementKeys, true);
    document.addEventListener('keyup', preventMovementKeys, true);
    document.addEventListener('keypress', preventMovementKeys, true);

    let currentUrl = window.location.href;
    const urlObserver = new MutationObserver(() => {
        if (currentUrl !== window.location.href) {
            currentUrl = window.location.href;

            if (isGamePage()) {
                removeOverlay();

                let attempts = 0;
                const maxAttempts = 20;
                const intervalId = setInterval(() => {
                    attempts++;
                    if (isEnabled) {
                        disableMovementAndZoom();
                        disableControls();
                        removeControlGroups();
                        removeTooltips();
                    }

                    if (attempts >= maxAttempts) {
                        clearInterval(intervalId);
                    }
                }, 500);
            } else {
                removeOverlay();
            }
        }
    });

    urlObserver.observe(document.body, {
        childList: true,
        subtree: true
    });

    setInterval(() => {
        if (isGamePage() && isEnabled) {
            disableControls();
            removeControlGroups();
            removeTooltips();
        }
    }, 100);

    if (isGamePage()) {
        let attempts = 0;
        const maxAttempts = 20;
        const intervalId = setInterval(() => {
            attempts++;
            if (isEnabled) {
                disableMovementAndZoom();
                disableControls();
                removeControlGroups();
                removeTooltips();
            }

            if (attempts >= maxAttempts) {
                clearInterval(intervalId);
            }
        }, 500);
    }

    updateMenuCommand();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址