Drawaria The Cauldron of Curses (Halloween)

Unleash chilling spectral hexes and auras to sabotage Drawaria players with true Halloween malice.

// ==UserScript==
// @name         Drawaria The Cauldron of Curses (Halloween)
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  Unleash chilling spectral hexes and auras to sabotage Drawaria players with true Halloween malice.
// @author       SpectralSaboteur
// @match        https://drawaria.online/*
// @match        https://*.drawaria.online/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// @grant        GM_xmlhttpRequest
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    /* ----------  CONFIGURACIÓN DE MALDICIONES Y AURAS  ---------- */

    // Hexes (Armas) de sabotaje espectral
    const HALLOWEEN_HEXES = {
        'Ninguno': '',
        '🧛 Vampire\'s Kiss': 'hex:vampires_kiss',         // Drains color palette (visual effect)
        '👻 Phantom\'s Glitch': 'hex:phantom_glitch',       // Chaotic drawing coordinates
        '🎃 Pumpkin King\'s Seal': 'hex:pumpkin_seal',     // Massive circular orange stamp
        '🕷️ Spider Rain': 'hex:spider_rain',
        '💀 Death Mark': 'hex:death_mark',
        '⚰️ Coffin Drop': 'hex:coffin_drop',
        '🔥 Hellfire Breath': 'hex:hellfire_breath',
        '👁️ Evil Eye Curse': 'hex:evil_eye',
        '⛓️ Chains of Torment': 'hex:chains_torment',
        '🔪 Butcher\'s Block': 'hex:butchers_block',
        '🌑 Dark Vortex': 'hex:dark_vortex',
        '🌕 Lunatic Grin': 'hex:lunatic_grin',
        '🧪 Potion of Chaos': 'hex:potion_chaos',
        '⚡ Lightning Strike': 'hex:lightning_strike',
        '🩸 Blood Splatter': 'hex:blood_splatter'
    };

    // Auras (Efectos) de sabotaje persistente
    const SPECTRAL_AURAS = {
        'Ninguno': '',
        '🛡️ Spectral Ward': 'aura:spectral_ward',          // Green/purple shield (for consistency with original)
        '🌫️ Graveyard Fog': 'aura:graveyard_fog',          // Dims the canvas
        '🧪 Ectoplasmic Slime': 'aura:ectoplasm_slime',    // Shimmering green border
        '💀 Haunting Glare': 'aura:haunting_glare',
        '🕯️ Candlelight Flicker': 'aura:candlelight_flicker',
        '🌀 Poltergeist Spin': 'aura:poltergeist_spin',
        '⭐ Demonic Rune': 'aura:demonic_rune',
        '🌑 Void Distortion': 'aura:void_distortion'
    };

    const DEFAULT_HEX_NAME = 'Ninguno';
    const DEFAULT_AURA_NAME = 'Ninguno';

    /* ----------  CONSTANTES DE EFECTOS  ---------- */
    const EFFECT_DURATION_BASE = 100; // ms base entre frames

    /* ----------  SETUP BÁSICO Y SOCKET  ---------- */
    let socket;
    const canvas = document.getElementById('canvas');
    const ctx = canvas ? canvas.getContext('2d') : null;

    let stopSignal = false;
    let stopBtn;
    let activeEffectInterval = null;

    const originalSend = WebSocket.prototype.send;
    WebSocket.prototype.send = function (...args) {
        if (!socket) socket = this;
        return originalSend.apply(this, args);
    };

    /* ----------  INTERFAZ DE USUARIO (CAULDRON OF CURSES)  ---------- */
    const container = document.createElement('div');
    container.style.cssText = `
        position:fixed; bottom:10px; right:10px; z-index:9999;
        background: radial-gradient(circle at top left, #330033 0%, #000000 100%);
        color:#ffcc00; padding:15px 20px; border-radius:15px;
        font-family: 'Creepster', 'Times New Roman', serif; font-size:14px;
        display:flex; flex-direction:column; gap:12px;
        box-shadow: 0 8px 30px rgba(100,0,100,0.9), inset 0 1px 0 rgba(255,100,255,0.1);
        border: 3px ridge #4b0082; /* Deep Purple/Indigo for spooky border */
        min-width: 320px;
        backdrop-filter: blur(5px);
        transform: rotateZ(1deg); /* Slight tilt for unsettling look */
    `;

    // Custom Font Styling (Optional: Requires loading a spooky font like 'Creepster')
    const fontLink = document.createElement('link');
    fontLink.href = 'https://fonts.googleapis.com/css2?family=Creepster&display=swap';
    fontLink.rel = 'stylesheet';
    document.head.appendChild(fontLink);

    const titleBar = document.createElement('div');
    titleBar.innerHTML = '⚰️ THE CAULDRON OF CURSES ⚰️';
    titleBar.style.cssText = `
        font-weight: bold; font-size: 20px; text-align: center; cursor: grab;
        background: linear-gradient(45deg, #8b0000, #ff00ff, #330033);
        -webkit-background-clip: text; -webkit-text-fill-color: transparent;
        text-shadow: 0 0 10px rgba(255, 0, 0, 0.7), 0 0 20px rgba(255, 100, 255, 0.5);
        margin: -15px -20px 10px -20px; padding: 15px 20px;
        border-bottom: 2px dashed #ff00ff;
        border-radius: 15px 15px 0 0;
        font-family: 'Creepster', cursive;
    `;
    container.appendChild(titleBar);

    const contentDiv = document.createElement('div');
    contentDiv.style.cssText = `display:flex; flex-direction:column; gap:12px;`;
    container.appendChild(contentDiv);

    const spookyInputStyle = `
        flex-grow: 1; padding: 10px 15px; border-radius: 5px;
        border: 2px solid #ff00ff; background: rgba(0, 0, 0, 0.7);
        color: #ffcc00; font-size: 14px; font-family: 'Creepster', monospace;
        transition: all 0.3s ease;
        &:focus { box-shadow: 0 0 15px rgba(255, 0, 255, 0.7); border-color: #ff0000; }
    `;

    function createSpookyRow(parent, labelText, inputElement) {
        const wrapper = document.createElement('div');
        wrapper.style.cssText = `display:flex; align-items:center; gap:12px;`;
        const label = document.createElement('span');
        label.textContent = labelText;
        label.style.cssText = `color: #ffcc00; font-weight: bold; min-width: 120px; text-shadow: 1px 1px 2px #000;`;
        wrapper.appendChild(label);
        wrapper.appendChild(inputElement);
        parent.appendChild(wrapper);
        return { wrapper, label, inputElement };
    }

    // Selector de jugadores (Victim)
    const playerSelect = document.createElement('select');
    playerSelect.style.cssText = spookyInputStyle;
    createSpookyRow(contentDiv, '💀 Victim:', playerSelect);

    // Selector de hexes
    const hexSelect = document.createElement('select');
    hexSelect.style.cssText = spookyInputStyle;
    for (const name in HALLOWEEN_HEXES) {
        const opt = document.createElement('option');
        opt.value = HALLOWEEN_HEXES[name];
        opt.textContent = name;
        hexSelect.appendChild(opt);
    }
    hexSelect.value = HALLOWEEN_HEXES[DEFAULT_HEX_NAME];
    createSpookyRow(contentDiv, '🔮 Hex:', hexSelect);

    // Selector de auras
    const auraSelect = document.createElement('select');
    auraSelect.style.cssText = spookyInputStyle;
    for (const name in SPECTRAL_AURAS) {
        const opt = document.createElement('option');
        opt.value = SPECTRAL_AURAS[name];
        opt.textContent = name;
        auraSelect.appendChild(opt);
    }
    auraSelect.value = SPECTRAL_AURAS[DEFAULT_AURA_NAME];
    createSpookyRow(contentDiv, '👻 Aura:', auraSelect);

    // Auto-reset de selectores
    hexSelect.addEventListener('change', () => {
        if (hexSelect.value !== '') auraSelect.value = SPECTRAL_AURAS['Ninguno'];
    });

    auraSelect.addEventListener('change', () => {
        if (auraSelect.value !== '') hexSelect.value = HALLOWEEN_HEXES['Ninguno'];
    });

    // Nivel de Potencia (Potency Level)
    const potencyInput = document.createElement('input');
    potencyInput.type = 'range';
    potencyInput.min = '1';
    potencyInput.max = '5';
    potencyInput.value = '3';
    potencyInput.style.cssText = `
        flex-grow: 1; accent-color: #ff0000;
        background: linear-gradient(to right, #ffcc00, #ff0000);
    `;

    const potencyLabel = document.createElement('span');
    potencyLabel.textContent = '🧪 Potency Level: (Mischief)';
    potencyLabel.style.cssText = `color: #ffcc00; font-weight: bold; min-width: 120px; text-shadow: 1px 1px 2px #000;`;

    potencyInput.addEventListener('input', () => {
        const levels = { 1: 'Mischief', 2: 'Prank', 3: 'Curse', 4: 'Hex', 5: 'Malice' };
        potencyLabel.textContent = `🧪 Potency Level: (${levels[potencyInput.value]})`;
    });

    const potencyWrapper = document.createElement('div');
    potencyWrapper.style.cssText = `display:flex; align-items:center; gap:12px;`;
    potencyWrapper.appendChild(potencyLabel);
    potencyWrapper.appendChild(potencyInput);
    contentDiv.appendChild(potencyWrapper);


    // Toggle de repetición (Eternal Torment)
    const repeatToggle = document.createElement('input');
    repeatToggle.type = 'checkbox';
    repeatToggle.style.cssText = `transform: scale(1.5); accent-color: #ff00ff;`;
    const repeatLabel = document.createElement('label');
    repeatLabel.textContent = ' ⚰️ Eternal Torment';
    repeatLabel.style.cssText = `color: #ff00ff; font-weight: bold; cursor: pointer; text-shadow: 0 0 5px rgba(255, 0, 255, 0.7);`;
    const repeatWrapper = document.createElement('div');
    repeatWrapper.style.cssText = `display:flex; align-items:center; gap:8px; justify-content: center; margin-top: 10px;`;
    repeatWrapper.appendChild(repeatToggle);
    repeatWrapper.appendChild(repeatLabel);
    contentDiv.appendChild(repeatWrapper);

    // Botón de activación
    const destroyBtn = document.createElement('button');
    destroyBtn.textContent = '🟢 UNLEASH THE HEX! 🟢';
    destroyBtn.disabled = true;
    destroyBtn.style.cssText = `
        padding: 12px 20px; border-radius: 10px; border: 2px solid #00ff00;
        background: linear-gradient(45deg, #008000, #004d00);
        color: white; font-weight: bold; font-size: 18px;
        cursor: pointer; transition: all 0.3s ease;
        box-shadow: 0 4px 15px rgba(0, 255, 0, 0.5);
        text-shadow: 0 0 5px #000;
        font-family: 'Creepster', sans-serif;
        &:hover {
            background: linear-gradient(45deg, #00ff00, #00b300);
            box-shadow: 0 6px 20px rgba(0, 255, 0, 0.8);
            transform: translateY(-2px);
        }
        &:disabled {
            background: #666; cursor: not-allowed; opacity: 0.5;
            box-shadow: none; transform: none;
        }
    `;
    contentDiv.appendChild(destroyBtn);

    // Botón de parada (Vanish Spirit)
    stopBtn = document.createElement('button');
    stopBtn.textContent = '🔥 VANISH SPIRIT 🔥';
    stopBtn.disabled = true;
    stopBtn.style.cssText = `
        margin-top: 8px; padding: 10px 16px; border-radius: 8px; border: 2px solid #ff0000;
        background: linear-gradient(45deg, #8b0000, #4d0000);
        color: white; font-weight: bold; font-size: 16px;
        cursor: pointer; transition: all 0.3s ease;
        box-shadow: 0 4px 10px rgba(255, 0, 0, 0.5);
        font-family: 'Creepster', sans-serif;
        &:hover {
            background: linear-gradient(45deg, #ff0000, #b30000);
            transform: translateY(-1px);
        }
        &:disabled {
            background: #666; cursor: not-allowed; opacity: 0.5;
            transform: none;
        }
    `;
    contentDiv.appendChild(stopBtn);

    document.body.appendChild(container);

    /* ----------  FUNCIONES DE SABOTAJE ESPECTRAL  ---------- */

    // Función base para dibujar/lanzar hex
    function castSpectralLine(x1, y1, x2, y2, color, thickness) {
        x1 = Math.round(x1); y1 = Math.round(y1);
        x2 = Math.round(x2); y2 = Math.round(y2);

        if (ctx && canvas) {
            // Client-side draw (for visual feedback on own screen)
            ctx.strokeStyle = color;
            ctx.lineWidth = thickness;
            ctx.lineCap = 'round';
            ctx.lineJoin = 'round';
            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x2, y2);
            ctx.stroke();
        }

        if (!socket || !canvas) return;

        // Server-side draw command (the actual sabotage)
        const normX1 = (x1 / canvas.width).toFixed(4);
        const normY1 = (y1 / canvas.height).toFixed(4);
        const normX2 = (x2 / canvas.width).toFixed(4);
        const normY2 = (y2 / canvas.height).toFixed(4);
        // Note: The thickness is sent as a *negative* value to Drawaria for thicker lines
        const cmd = `42["drawcmd",0,[${normX1},${normY1},${normX2},${normY2},false,${0 - thickness},"${color}",0,0,{}]]`;
        socket.send(cmd);
    }

    // Obtener coordenadas del jugador víctima
    function getPlayerCoords(playerId) {
        // Find the player's avatar on the canvas
        const avatar = document.querySelector(`.spawnedavatar[data-playerid="${playerId}"]`);
        if (!avatar || !canvas) return null;

        const cRect = canvas.getBoundingClientRect();
        const aRect = avatar.getBoundingClientRect();

        return {
            x: Math.round((aRect.left - cRect.left) + (aRect.width / 2)),
            y: Math.round((aRect.top - cRect.top) + (aRect.height / 2)),
            width: aRect.width,
            height: aRect.height
        };
    }

    /* ----------  HALLOWEEN HEXES  ---------- */

    // 1. Vampire's Kiss (Drains color palette)
    async function vampiresKiss(playerId, potency = 3) {
        if (stopSignal) return;
        console.log(`🧛 Casting Vampire's Kiss on victim ${playerId} (Potency: ${potency})`);

        const target = getPlayerCoords(playerId);
        if (!target) return;

        const drainCount = 10 + (potency * 4);
        const colors = ['#8B0000', '#4B0082', '#000000']; // Deep red, indigo, black

        for (let i = 0; i < drainCount; i++) {
            if (stopSignal) break;

            const startX = target.x + (Math.random() - 0.5) * 100;
            const startY = target.y - 100 + Math.random() * 50;
            const endX = target.x + (Math.random() - 0.5) * 20;
            const endY = target.y + (Math.random() - 0.5) * 10;

            const color = colors[Math.floor(Math.random() * colors.length)];
            const thickness = 2 + Math.random() * potency * 0.5;

            // Draw draining lines converging on the target
            castSpectralLine(startX, startY, endX, endY, color, thickness);

            await new Promise(r => setTimeout(r, 80 - (potency * 10)));
        }
    }

    // 2. Pumpkin King's Seal (Massive circular orange stamp)
    async function pumpkinKingsSeal(playerId, potency = 3) {
        if (stopSignal) return;
        console.log(`🎃 Sealing victim ${playerId} with the Pumpkin King's mark (Potency: ${potency})`);

        const target = getPlayerCoords(playerId);
        if (!target) return;

        const sealCount = 5 + (potency * 3);
        const colors = ['#FF7518', '#FF4500', '#FFA500']; // Pumpkin Orange/Red/Yellow

        for (let i = 0; i < sealCount; i++) {
            if (stopSignal) break;

            const centerX = target.x + (Math.random() - 0.5) * 50;
            const centerY = target.y + (Math.random() - 0.5) * 30;
            const radius = 30 + potency * 15;

            // Draw a massive circle stamp
            for (let angle = 0; angle < 16; angle++) {
                const radians = (angle / 16) * 2 * Math.PI;
                const x = centerX + radius * Math.cos(radians);
                const y = centerY + radius * Math.sin(radians);
                const color = colors[i % colors.length];

                // Draw lines from center to perimeter to simulate a solid circle/stamp
                castSpectralLine(centerX, centerY, x, y, color, 10 + potency);
            }

            await new Promise(r => setTimeout(r, 150 - (potency * 10)));
        }
    }

    // 3. Phantom's Glitch (Chaotic drawing coordinates)
    async function phantomsGlitch(playerId, potency = 3) {
        if (stopSignal) return;
        console.log(`👻 Initiating Phantom's Glitch on victim ${playerId} (Potency: ${potency})`);

        const target = getPlayerCoords(playerId);
        if (!target) return;

        const glitchDuration = 1500 + potency * 500;
        const startTime = Date.now();
        const colors = ['#00FF00', '#00FFFF', '#FF00FF', '#FFFFFF']; // Neon, spectral colors

        while (Date.now() - startTime < glitchDuration) {
            if (stopSignal) break;

            const glitchCount = 5 + potency;
            const maxDisplacement = 50 + potency * 20;

            for (let i = 0; i < glitchCount; i++) {
                const startX = target.x + (Math.random() - 0.5) * maxDisplacement;
                const startY = target.y + (Math.random() - 0.5) * maxDisplacement;
                const endX = startX + (Math.random() - 0.5) * 30;
                const endY = startY + (Math.random() - 0.5) * 30;

                const color = colors[Math.floor(Math.random() * colors.length)];
                const thickness = 1 + Math.random() * potency * 0.5;

                // Draw short, chaotic, glowing lines
                castSpectralLine(startX, startY, endX, endY, color, thickness);
            }

            await new Promise(r => setTimeout(r, 50 - (potency * 5)));
        }
    }

    /* --- Placeholder Hexes (Mapping to existing logic for full menu) --- */
    // Reusing the original mod's structure for the other 12 hexes/auras by mapping them
    // to the three new core functions, adjusted by potency.

    // Helper to map hexes to functions
    const hexFunctionMap = {
        'hex:vampires_kiss': vampiresKiss,
        'hex:phantom_glitch': phantomsGlitch,
        'hex:pumpkin_seal': pumpkinKingsSeal,
        'hex:spider_rain': (id, p) => phantomsGlitch(id, p + 1),
        'hex:death_mark': (id, p) => pumpkinKingsSeal(id, p),
        'hex:coffin_drop': (id, p) => vampiresKiss(id, p * 2),
        'hex:hellfire_breath': (id, p) => pumpkinKingsSeal(id, p * 2),
        'hex:evil_eye': (id, p) => vampiresKiss(id, p + 1),
        'hex:chains_torment': (id, p) => phantomsGlitch(id, p + 1),
        'hex:butchers_block': (id, p) => pumpkinKingsSeal(id, p * 1.5),
        'hex:dark_vortex': (id, p) => phantomsGlitch(id, p * 2),
        'hex:lunatic_grin': (id, p) => vampiresKiss(id, p * 1.5),
        'hex:potion_chaos': (id, p) => phantomsGlitch(id, p * 1.5),
        'hex:lightning_strike': (id, p) => vampiresKiss(id, p),
        'hex:blood_splatter': (id, p) => pumpkinKingsSeal(id, p)
    };

    /* ----------  SPECTRAL AURAS (PERSISTENT EFFECTS)  ---------- */

    // 1. Graveyard Fog (Dims the canvas)
    async function graveyardFog(playerId, potency = 3) {
        if (stopSignal) return;
        console.log(`🌫️ Applying Graveyard Fog to victim ${playerId} (Potency: ${potency})`);

        const target = getPlayerCoords(playerId);
        if (!target || !canvas) return;

        // Draw a large, dark, semi-transparent box over the canvas repeatedly.
        const color = `rgba(0, 0, 0, ${0.1 + potency * 0.05})`; // Increasing darkness
        const thickness = canvas.width / 2; // Make it a large stroke to cover

        // We only cast a single dark line across the whole screen's center
        // to minimize spam, relying on the line thickness to cover the area.
        castSpectralLine(0, canvas.height / 2, canvas.width, canvas.height / 2, color, thickness);
    }

    // 2. Ectoplasmic Slime (Shimmering green border)
    async function ectoplasmicSlime(playerId, potency = 3) {
        if (stopSignal) return;
        console.log(`🧪 Applying Ectoplasmic Slime to canvas (Potency: ${potency})`);

        if (!canvas) return;

        const colors = ['#39ff14', '#00cc00', '#aaffaa']; // Neon green slime
        const thickness = 5 + potency * 2;
        const offset = Math.random() * 5; // Shimmer effect

        // Draw four lines to form a border
        // Top
        castSpectralLine(0 - offset, 0 - offset, canvas.width + offset, 0 - offset, colors[0], thickness);
        // Bottom
        castSpectralLine(0 - offset, canvas.height + offset, canvas.width + offset, canvas.height + offset, colors[1], thickness);
        // Left
        castSpectralLine(0 - offset, 0 - offset, 0 - offset, canvas.height + offset, colors[2], thickness);
        // Right
        castSpectralLine(canvas.width + offset, 0 - offset, canvas.width + offset, canvas.height + offset, colors[0], thickness);
    }

    // Helper to map auras to functions
    const auraFunctionMap = {
        'aura:spectral_ward': (id, p) => ectoplasmicSlime(id, p / 2),
        'aura:graveyard_fog': graveyardFog,
        'aura:ectoplasm_slime': ectoplasmicSlime,
        'aura:haunting_glare': (id, p) => graveyardFog(id, p * 1.5),
        'aura:candlelight_flicker': (id, p) => ectoplasmicSlime(id, p),
        'aura:poltergeist_spin': (id, p) => graveyardFog(id, p),
        'aura:demonic_rune': (id, p) => ectoplasmicSlime(id, p * 1.5),
        'aura:void_distortion': (id, p) => graveyardFog(id, p * 2)
    };

    /* ----------  SISTEMA DE GESTIÓN DE JUGADORES (VICTIMS)  ---------- */

    // (Player list logic remains the same, only renaming labels)
    let lastPlayerList = new Set();
    let isUpdatingList = false;

    function refreshPlayerList() {
        if (isUpdatingList) return;

        const currentPlayers = new Set();
        const playerRows = document.querySelectorAll('.playerlist-row[data-playerid]');

        playerRows.forEach(row => {
            if (row.dataset.self !== 'true' && row.dataset.playerid !== '0') {
                const name = row.querySelector('.playerlist-name a')?.textContent || `Victim ${row.dataset.playerid}`;
                currentPlayers.add(`${row.dataset.playerid}:${name}`);
            }
        });

        const playersChanged = currentPlayers.size !== lastPlayerList.size ||
              ![...currentPlayers].every(player => lastPlayerList.has(player));

        if (!playersChanged) return;

        isUpdatingList = true;
        const previousSelection = playerSelect.value;

        playerSelect.innerHTML = '';

        playerRows.forEach(row => {
            if (row.dataset.self === 'true') return;
            if (row.dataset.playerid === '0') return;
            const name = row.querySelector('.playerlist-name a')?.textContent || `Victim ${row.dataset.playerid}`;
            const opt = document.createElement('option');
            opt.value = row.dataset.playerid;
            opt.textContent = `💀 ${name}`;
            playerSelect.appendChild(opt);
        });

        if (previousSelection) {
            playerSelect.value = previousSelection;
        }

        lastPlayerList = new Set(currentPlayers);
        destroyBtn.disabled = playerSelect.children.length === 0;
        isUpdatingList = false;
    }

    /* ----------  EVENTOS PRINCIPALES  ---------- */

    // Dragging logic (renamed for theme)
    let isDragging = false;
    let offsetX, offsetY;

    titleBar.addEventListener('mousedown', (e) => {
        isDragging = true;
        titleBar.style.cursor = 'grabbing';
        offsetX = e.clientX - container.getBoundingClientRect().left;
        offsetY = e.clientY - container.getBoundingClientRect().top;
    });

    document.addEventListener('mousemove', (e) => {
        if (!isDragging) return;
        let newX = e.clientX - offsetX;
        let newY = e.clientY - offsetY;
        newX = Math.max(0, Math.min(newX, window.innerWidth - container.offsetWidth));
        newY = Math.max(0, Math.min(newY, window.innerHeight - container.offsetHeight));
        container.style.left = newX + 'px';
        container.style.top = newY + 'px';
        container.style.right = 'auto'; // Disable right/bottom styles during drag
        container.style.bottom = 'auto';
    });

    document.addEventListener('mouseup', () => {
        isDragging = false;
        titleBar.style.cursor = 'grab';
    });

    // Botón de parada de emergencia (Vanish Spirit)
    stopBtn.addEventListener('click', () => {
        console.log('🔥 VANISH SPIRIT: Hexes Dispersed.');
        stopSignal = true;

        if (activeEffectInterval) {
            clearInterval(activeEffectInterval);
            activeEffectInterval = null;
        }

        destroyBtn.textContent = '🟢 UNLEASH THE HEX! 🟢';
        destroyBtn.style.background = 'linear-gradient(45deg, #008000, #004d00)';
        destroyBtn.disabled = false;
        stopBtn.disabled = true;
    });

    // Botón principal de sabotaje (Unleash the Hex!)
    destroyBtn.addEventListener('click', async () => {
        const playerId = playerSelect.value;
        if (!playerId) {
            alert('💀 Please select a victim first!');
            return;
        }

        const selectedHex = hexSelect.value;
        const selectedAura = auraSelect.value;
        const potency = parseInt(potencyInput.value);

        // Toggle Continuous/Eternal Torment off if already running
        if (activeEffectInterval) {
            console.log('Stopping Eternal Torment...');
            stopSignal = true;
            clearInterval(activeEffectInterval);
            activeEffectInterval = null;
            destroyBtn.textContent = '🟢 UNLEASH THE HEX! 🟢';
            destroyBtn.style.background = 'linear-gradient(45deg, #008000, #004d00)';
            stopBtn.disabled = true;
            return;
        }

        let actionToExecute = null;

        // Select Hex or Aura
        if (selectedHex && selectedHex.startsWith('hex:')) {
            actionToExecute = hexFunctionMap[selectedHex];
        } else if (selectedAura && selectedAura.startsWith('aura:')) {
            actionToExecute = auraFunctionMap[selectedAura];
        } else {
            alert('🔮 Please select a Hex or Aura to unleash!');
            return;
        }

        if (!actionToExecute) {
            alert('⚠️ Curse not implemented! The spirits refuse.');
            return;
        }

        stopSignal = false;
        destroyBtn.disabled = true;
        stopBtn.disabled = false;

        try {
            if (repeatToggle.checked) {
                destroyBtn.textContent = '💀 END TORMENT 💀';
                destroyBtn.style.background = 'linear-gradient(45deg, #8b0000, #ff0000)';
                destroyBtn.disabled = false;

                console.log('🔥 Initiating Eternal Torment...');

                const continuousTorment = async () => {
                    if (stopSignal || !repeatToggle.checked) {
                        if (activeEffectInterval) clearInterval(activeEffectInterval);
                        activeEffectInterval = null;
                        destroyBtn.textContent = '🟢 UNLEASH THE HEX! 🟢';
                        destroyBtn.style.background = 'linear-gradient(45deg, #008000, #004d00)';
                        stopBtn.disabled = true;
                        return;
                    }

                    try {
                        await actionToExecute(playerId, potency);
                    } catch (error) {
                        console.error('Error during Eternal Torment:', error);
                    }
                };

                await continuousTorment(); // First execution
                if (!stopSignal) {
                    // Repeat at a speed based on potency for non-aura effects
                    const intervalSpeed = selectedHex ? 3000 - (potency * 400) : 500;
                    activeEffectInterval = setInterval(continuousTorment, intervalSpeed);
                }
            } else {
                console.log('💥 Executing One-Shot Curse...');
                await actionToExecute(playerId, potency);
            }
        } finally {
            if (!activeEffectInterval) {
                destroyBtn.disabled = false;
                stopBtn.disabled = true;
            }
        }
    });

    // Observar cambios en la lista de jugadores
    const playerListElement = document.getElementById('playerlist');
    if (playerListElement) {
        new MutationObserver(() => {
            setTimeout(refreshPlayerList, 100);
        }).observe(playerListElement, {
            childList: true,
            subtree: true,
            attributes: true,
            attributeFilter: ['data-playerid']
        });
    }

    // Limpieza al cerrar
    window.addEventListener('beforeunload', () => {
        if (activeEffectInterval) {
            clearInterval(activeEffectInterval);
            activeEffectInterval = null;
        }
        stopSignal = true;
    });

    // Inicialización
    refreshPlayerList();
    potencyLabel.textContent = `🧪 Potency Level: (Curse)`; // Set default label
    console.log('⚰️ The Cauldron of Curses Mod loaded successfully! ⚰️');

})();