Add Multi-Dice Roller Tab to Panel Tabs

Adds a very basic dice tab to the sidebar with various die sizes

// ==UserScript==
// @name         Add Multi-Dice Roller Tab to Panel Tabs
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Adds a very basic dice tab to the sidebar with various die sizes
// @match        https://ogres.app/play/*
// @license MIT
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const MAX_RETRIES = 100;
    const RETRY_INTERVAL_MS = 100;
    let attempts = 0;

    function tryAddDiceTab() {
        const ul = document.querySelector('ul.panel-tabs');
        if (!ul) {
            if (attempts < MAX_RETRIES) {
                attempts++;
                if (attempts % 10 === 0) {
                    console.log(`[DiceTab] Waiting... (attempt ${attempts})`);
                }
                setTimeout(tryAddDiceTab, RETRY_INTERVAL_MS);
                return;
            } else {
                console.warn('[DiceTab] ul.panel-tabs not found after max retries.');
                return;
            }
        }

        console.log('[DiceTab] Found ul.panel-tabs, adding dice tab...');

        const li = document.createElement('li');
        li.className = 'panel-tabs-tab';
        // option 2:
        li.style.cursor = 'pointer';


        const label = document.createElement('label');

        const input = document.createElement('input');
        input.type = 'radio';
        input.name = 'panel';
        input.value = 'dice';

        // SVG DICE
        const svgNS = 'http://www.w3.org/2000/svg';
        const svg = document.createElementNS(svgNS, 'svg');
        svg.setAttribute('width', '16');
        svg.setAttribute('height', '16');
        svg.setAttribute('viewBox', '0 0 16 16');
        svg.setAttribute('fill', 'currentColor');

        const die = document.createElementNS(svgNS, 'rect');
        die.setAttribute('x', '1');
        die.setAttribute('y', '1');
        die.setAttribute('width', '14');
        die.setAttribute('height', '14');
        die.setAttribute('rx', '2');
        die.setAttribute('ry', '2');
        die.setAttribute('stroke', 'currentColor');
        die.setAttribute('fill', 'none');
        svg.appendChild(die);

        const createDot = (cx, cy) => {
            const dot = document.createElementNS(svgNS, 'circle');
            dot.setAttribute('cx', cx);
            dot.setAttribute('cy', cy);
            dot.setAttribute('r', '1.2');
            dot.setAttribute('fill', 'currentColor');
            return dot;
        };

        // D6 face with 6 dots
        const positions = [
            [4, 4], [8, 4], [12, 4],
            [4, 12], [8, 12], [12, 12],
        ];
        positions.forEach(([cx, cy]) => svg.appendChild(createDot(cx, cy)));

        // END SVG DICE


        label.appendChild(input);
        label.appendChild(svg);
        li.appendChild(label);
        //ul.appendChild(li);
        const lastItem = ul.lastElementChild;
        ul.insertBefore(li, lastItem);

        console.log('[DiceTab] Dice tab added. Setting up interaction...');

        input.addEventListener('change', () => {
            if (!input.checked) return;

            console.log('[DiceTab] Dice tab selected — updating .form-body...');
            const panel = document.querySelector('.form-body');
            if (!panel) {
                console.warn('[DiceTab] .form-body not found.');
                return;
            }

            // Setup other tabs to hide dice panel
            const otherTabs = [...ul.querySelectorAll('li.panel-tabs-tab')].filter(el => el !== li);
            otherTabs.forEach(tab => {
                tab.addEventListener('click', () => {
                    const panel = document.querySelector('#form-panel');
                    if (!panel) return;

                    const dicePanel = panel.querySelector('#dice-panel');
                    if (dicePanel) {
                        dicePanel.style.display = 'none';
                    }
                });
            });


            // Hide all direct children of #form-panel
[...panel.children].forEach(child => child.style.display = 'none');

            // Create or show dice panel
let dicePanel = document.querySelector('#dice-panel');
if (!dicePanel) {
    dicePanel = document.createElement('div');
    dicePanel.id = 'dice-panel';
    dicePanel.style.padding = '1em';

    const result = document.createElement('div');
    result.textContent = '🎲 Click a die to roll.';
    result.style.marginTop = '1em';

    // History display
    const historyTitle = document.createElement('div');
    historyTitle.textContent = 'Last 100 rolls:';
    historyTitle.style.marginTop = '1em';
    historyTitle.style.fontWeight = 'bold';

    const historyList = document.createElement('ul');
    historyList.style.paddingLeft = '20px';
    //historyList.style.maxHeight = '120px';
    historyList.style.overflowY = 'auto';
    historyList.style.fontSize = '0.9em';

    // Rolling buffer array
    const rollHistory = [];

    const dice = [4, 6, 8, 10, 12, 20, 100];
    dice.forEach(sides => {
        const btn = document.createElement('button');
        btn.textContent = `d${sides}`;
        btn.style.marginRight = '0.5em';
        btn.addEventListener('click', () => {
            const roll = Math.floor(Math.random() * sides) + 1;
            result.textContent = `🎲 You rolled a ${roll} on a d${sides}`;

            // Add to history
            rollHistory.unshift(`d${sides}: ${roll}`);
            if (rollHistory.length > 100) rollHistory.pop();

            // Update history display
            historyList.innerHTML = '';
            rollHistory.forEach(entry => {
                const li = document.createElement('li');
                li.textContent = entry;
                historyList.appendChild(li);
            });
        });
        dicePanel.appendChild(btn);
    });

    dicePanel.appendChild(result);
    dicePanel.appendChild(historyTitle);
    dicePanel.appendChild(historyList);

    const footer = document.querySelector('.form-footer');
    if (footer) {
        footer.style.visibility = "hidden";
    }

    panel.appendChild(dicePanel);

}

dicePanel.style.display = 'block';


// Show our dice panel
dicePanel.style.display = 'block';

        });
    }

    console.log('[DiceTab] Starting tab insert with retry logic...');
    tryAddDiceTab();
})();