Greasy Fork is available in English.

xd2shuffle

Visual larp: Changes ARS to $ everywhere (bets, balance, everything) - keeps numbers the same

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         xd2shuffle
// @namespace    http://tampermonkey.net/
// @version      7.7.8.1
// @description  Visual larp: Changes ARS to $ everywhere (bets, balance, everything) - keeps numbers the same
// @author       fusi | @loficat on tg | codedfusi on github
// @match        *://*.shuffle.com/*
// @grant        none
// @run-at       document-start
// @license      MIT
// ==/UserScript==

(function () {
    const processedTextNodes = new WeakSet();
    const processedImages = new WeakSet();

    // Force update a text node
    function updateTextNode(node) {
        if (node.nodeType !== 3 || !node.nodeValue) return false;
        
        let original = node.nodeValue;
        let newValue = original;
        let changed = false;

        // Replace ARS with $ (case insensitive just in case)
        if (newValue.includes("ARS")) {
            newValue = newValue.replace(/ARS/g, "$");
            changed = true;
        }
        
        // Replace lowercase "ars" if it appears
        if (newValue.includes("ars")) {
            newValue = newValue.replace(/ars/g, "$");
            changed = true;
        }

        // Remove space after the new $
        if (changed) {
            newValue = newValue.replace(/\$\s+/g, '$');
        }

        if (changed && newValue !== original) {
            node.nodeValue = newValue;
            return true;
        }
        return false;
    }

    function processTextNode(node) {
        if (node.nodeType === 3 && node.nodeValue && !processedTextNodes.has(node)) {
            if (updateTextNode(node)) {
                processedTextNodes.add(node);
            }
        }
    }

    function processImageElement(el) {
        if (el.nodeType === 1 && el.hasAttribute("src") && !processedImages.has(el)) {
            const src = el.getAttribute("src");
            if (src && src.includes("/icons/fiat/ARS.svg")) {
                el.setAttribute("src", src.replace("/icons/fiat/ARS.svg", "/icons/fiat/USD.svg"));
                processedImages.add(el);
            }
        }
    }

    function walkAndProcess(root) {
        if (!root) return;

        // Process all text nodes
        const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
        let node;
        while ((node = walker.nextNode())) {
            processTextNode(node);
        }

        // Process all ARS flag images
        const images = root.querySelectorAll('img[src*="/icons/fiat/ARS.svg"]');
        images.forEach(img => processImageElement(img));
    }

    // More aggressive mutation handling
    function onMutation(mutations) {
        let needsFullScan = false;
        
        for (const mutation of mutations) {
            // If attributes changed (like a bet amount updating), scan the target
            if (mutation.type === 'attributes') {
                if (mutation.target.nodeType === 1) {
                    // Re-scan this element and its children
                    walkAndProcess(mutation.target);
                    // Also scan its parent in case the change bubbled
                    if (mutation.target.parentNode) {
                        walkAndProcess(mutation.target.parentNode);
                    }
                }
                needsFullScan = true;
            }
            
            // If child nodes were added, process them
            if (mutation.type === 'childList') {
                for (const addedNode of mutation.addedNodes) {
                    if (addedNode.nodeType === 1) {
                        walkAndProcess(addedNode);
                    } else if (addedNode.nodeType === 3) {
                        processTextNode(addedNode);
                    }
                }
                needsFullScan = true;
            }
            
            // If text itself changed (characterData mutation)
            if (mutation.type === 'characterData') {
                if (mutation.target.nodeType === 3) {
                    // Re-process this text node even if it was processed before
                    const node = mutation.target;
                    if (node.nodeValue && (node.nodeValue.includes("ARS") || node.nodeValue.includes("ars"))) {
                        updateTextNode(node);
                    }
                }
                needsFullScan = true;
            }
        }
        
        // Do a quick partial scan of the body periodically to catch anything missed
        if (needsFullScan) {
            setTimeout(() => {
                // Scan the whole body but skip nodes we've already processed to save performance
                const allTextNodes = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);
                let tn;
                while ((tn = allTextNodes.nextNode())) {
                    if (tn.nodeValue && (tn.nodeValue.includes("ARS") || tn.nodeValue.includes("ars"))) {
                        if (updateTextNode(tn)) {
                            processedTextNodes.add(tn);
                        }
                    }
                }
            }, 100);
        }
    }

    // Start when DOM is ready
    document.addEventListener("DOMContentLoaded", () => {
        walkAndProcess(document.body);

        // Watch for attribute changes (like bet amounts), text changes, AND child lists
        const observer = new MutationObserver(onMutation);
        observer.observe(document.body, {
            childList: true,
            subtree: true,
            attributes: true,      // <-- CRITICAL: catches bet amount updates
            attributeFilter: ['textContent', 'innerHTML', 'value'], // Focus on text-related attributes
            characterData: true    // <-- CRITICAL: catches direct text changes
        });
        
        // Also run every second as a backup (heavy but ensures bets get caught)
        setInterval(() => {
            const allTextNodes = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);
            let tn;
            while ((tn = allTextNodes.nextNode())) {
                if (tn.nodeValue && (tn.nodeValue.includes("ARS") || tn.nodeValue.includes("ars"))) {
                    updateTextNode(tn);
                }
            }
        }, 1000);
    });
})();