Greasy Fork is available in English.

Mobile Shift-Click Toggle

Adds a floating button to toggle Shift+Click for mobile/touch devices

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Mobile Shift-Click Toggle
// @namespace    http://tampermonkey.net/
// @version      1.0.1
// @description  Adds a floating button to toggle Shift+Click for mobile/touch devices
// @author       korphd
// @match        *://*/*
// @license       MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // State of our virtual Shift key
    let isShiftToggled = false;

    // --- 1. THE MAGIC TRICK ---
    // This overrides the browser's default event rules.
    // Whenever the game checks "event.shiftKey", it will read our toggle state instead!
    function overrideShiftKey(prototypeObject) {
        const originalDescriptor = Object.getOwnPropertyDescriptor(prototypeObject, 'shiftKey');
        if (!originalDescriptor) return;

        Object.defineProperty(prototypeObject, 'shiftKey', {
            get: function() {
                // If our button is ON, tell the game Shift is being pressed
                if (isShiftToggled) return true;
                // Otherwise, act normally
                return originalDescriptor.get.call(this);
            },
            configurable: true,
            enumerable: true
        });
    }

    // Apply the trick to Mouse, Pointer, and Touch events
    if (window.MouseEvent) overrideShiftKey(MouseEvent.prototype);
    if (window.PointerEvent) overrideShiftKey(PointerEvent.prototype);
    if (window.KeyboardEvent) overrideShiftKey(KeyboardEvent.prototype);


    // --- 2. THE UI BUTTON ---
    const toggleBtn = document.createElement('button');
    toggleBtn.id = 'mobile-shift-toggle-btn';
    toggleBtn.innerText = 'Shift: OFF';
    
    // Styling the floating button
    toggleBtn.style.cssText = `
        position: fixed;
        bottom: 20px;
        left: 20px; /* Placed on the left so it doesn't overlap your tracker */
        z-index: 999999;
        padding: 12px 18px;
        background-color: rgba(170, 0, 0, 0.4); /* Semi-transparent Red */
        color: white;
        border: 2px solid #fff;
        border-radius: 8px;
        font-family: Arial, sans-serif;
        font-size: 16px;
        font-weight: bold;
        box-shadow: 0 4px 6px rgba(0,0,0,0.5);
        cursor: pointer;
        user-select: none;
    `;

    document.body.appendChild(toggleBtn);

    // --- 3. BUTTON LOGIC ---
    function toggleShift(e) {
        // Prevent the game from registering you clicking the toggle button
        e.preventDefault();
        e.stopPropagation();

        isShiftToggled = !isShiftToggled;

        if (isShiftToggled) {
            toggleBtn.innerText = 'Shift: ON';
            toggleBtn.style.backgroundColor = 'rgba(0, 170, 0, 0.8)'; // Green
            toggleBtn.style.boxShadow = '0 0 15px rgba(0, 255, 0, 0.8)'; // Glow effect
        } else {
            toggleBtn.innerText = 'Shift: OFF';
            toggleBtn.style.backgroundColor = 'rgba(170, 0, 0, 0.8)'; // Red
            toggleBtn.style.boxShadow = '0 4px 6px rgba(0,0,0,0.5)';
        }
    }

    // We use 'pointerdown' instead of 'click' so it responds instantly on touchscreens
    // and intercepts the touch before the game registers it.
    toggleBtn.addEventListener('pointerdown', toggleShift);
    toggleBtn.addEventListener('click', (e) => e.stopPropagation());

})();