The Solar Smash Mod

Unleash unique Solar Smash weapons and effects - each weapon has its own distinct behavior!

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         The Solar Smash Mod
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  Unleash unique Solar Smash weapons and effects - each weapon has its own distinct behavior!
// @author       YouTubeDrawaria
// @match        https://drawaria.online/*
// @match        https://*.drawaria.online/*
// @grant        GM_xmlhttpRequest
// @license      MIT
// @icon https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// ==/UserScript==

(function () {
    'use strict';

    /* ----------  ARMAS ÚNICAS DE SOLAR SMASH  ---------- */

    const SOLAR_WEAPONS = {
        'Ninguno': '',
        '⚡ Rayo Láser': 'weapon:laser_beam', // 1.1 (reordenado)
        '🔮 Rayo de Plasma': 'weapon:plasma_beam', // 1.1 (reordenado)
        '🌠 Lluvia de Meteoritos': 'weapon:meteor_rain', // 1.1
        '☄️ Asteroide Gigante': 'weapon:giant_asteroid', // 1.1
        '🔥 Dragón Espacial': 'weapon:space_dragon', // 1.1
        '🛸 Invasión OVNI': 'weapon:ufo_invasion', // 1.1 (queda como arma, solo batches y 1 ovni)
        '🗡️ Sable Láser Galáctico': 'weapon:galactic_lightsaber', // 1.1
        '🚀 Misil de Antimateria': 'weapon:antimatter_missile', // 1.1
        '🌪️ Vórtice Gravitacional': 'weapon:gravity_vortex', // 1.1 (queda como arma, delays y batches)
        '🌑 Agujero Negro': 'weapon:black_hole' // 1.1 (queda como arma, solo batches)
    };

    const SOLAR_EFFECTS = {
        'Ninguno': '',
        '⚡ Rayo Láser (v1.0)': 'effect:laser_beam_v1_0', // 1.0 (reordenado)
        '🛡️ Escudo Planetario': 'effect:planetary_shield', // 1.1 (delays y batches)
        '🎆 Fuegos Artificiales Solares': 'effect:solar_fireworks', // 1.1
        '❄️ Era de Hielo Instantánea': 'effect:instant_ice_age', // 1.1 (delays y batches)
        '🌋 Erupción Volcánica': 'effect:volcanic_eruption', // 1.1
        '🌀 Anomalía Espacial': 'effect:space_anomaly', // 1.1 (delays y batches)
        '🛸 Invasión OVNI (v1.0)': 'effect:ufo_invasion_v1_0', // 1.0
        '🌪️ Vórtice Gravitacional (v1.0)': 'effect:gravity_vortex_v1_0', // 1.0 (delays y batches)
        '🌑 Agujero Negro (v1.0)': 'effect:black_hole_v1_0' // 1.0 (solo batches)
    };

    /* ----------  SETUP BÁSICO  ---------- */
    let socket;
    const canvas = document.getElementById('canvas');
    const ctx = canvas ? canvas.getContext('2d') : null;
    let stopSignal = false;
    let stopBtn;
    let activeEffectInterval = null;
    let isExecuting = false;

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

    /* ----------  INTERFAZ DE USUARIO  ---------- */
    const container = document.createElement('div');
    container.style.cssText = `
        position:fixed; bottom:10px; right:10px; z-index:9999;
        background:linear-gradient(135deg, #1a1a2e, #16213e, #0f3460);
        color:#fff; padding:15px 20px; border-radius:15px;
        font-family: 'Orbitron', 'Segoe UI', Arial, sans-serif; font-size:13px;
        display:flex; flex-direction:column; gap:12px;
        box-shadow: 0 8px 25px rgba(0,0,0,0.8), inset 0 1px 0 rgba(255,255,255,0.1);
        border: 2px solid #00ffff;
        min-width: 320px;
        backdrop-filter: blur(10px);
        cursor: default;
    `;

    const titleBar = document.createElement('div');
    titleBar.innerHTML = '🌌 THE SOLAR SMASH MOD 🌌';
    titleBar.style.cssText = `
        font-weight: bold; font-size: 16px; text-align: center; cursor: grab;
        background: linear-gradient(45deg, #ff6b35, #f7931e, #ffcc02);
        -webkit-background-clip: text; -webkit-text-fill-color: transparent;
        text-shadow: 0 0 10px rgba(255, 107, 53, 0.5);
        margin: -15px -20px 10px -20px; padding: 15px 20px;
        border-bottom: 2px solid rgba(0, 255, 255, 0.3);
        border-radius: 15px 15px 0 0;
    `;
    container.appendChild(titleBar);

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

    const solarInputStyle = `
        flex-grow: 1; padding: 8px 12px; border-radius: 8px;
        border: 2px solid #00ffff; background: rgba(0, 20, 40, 0.8);
        color: #00ffff; font-size: 13px; font-family: 'Orbitron', monospace;
        transition: all 0.3s ease;
        appearance: none;
        background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%2300ffff%22%20d%3D%22M287%2C197.3L159.2%2C69.5c-3.6-3.6-8.2-5.4-12.8-5.4s-9.2%2C1.8-12.8%2C5.4L5.4%2C197.3c-7.2%2C7.2-7.2%2C18.8%2C0%2C26c3.6%2C3.6%2C8.2%2C5.4%2C12.8%2C5.4s9.2%2C1.8%2C12.8%2C5.4l117%2C117c3.6%2C3.6%2C8.2%2C5.4%2C12.8%2C5.4s9.2%2C1.8%2C12.8%2C5.4l117-117c7.2-7.2%2C7.2-18.8%2C0-26C294.2%2C204.5%2C294.2%2C200.9%2C287%2C197.3z%22%2F%3E%3C%2Fsvg%3E');
        background-repeat: no-repeat;
        background-position: right 8px center;
        background-size: 12px;
        cursor: pointer;
    `;

    function createSolarRow(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: #00ffff; font-weight: bold; min-width: 90px;`;
        wrapper.appendChild(label);
        wrapper.appendChild(inputElement);
        parent.appendChild(wrapper);
        return { wrapper, label, inputElement };
    }

    // Selector de jugadores
    const playerSelect = document.createElement('select');
    playerSelect.style.cssText = solarInputStyle;
    createSolarRow(contentDiv, '🎯 Target:', playerSelect);

    // Selector de armas
    const weaponSelect = document.createElement('select');
    weaponSelect.style.cssText = solarInputStyle;
    for (const name in SOLAR_WEAPONS) {
        const opt = document.createElement('option');
        opt.value = SOLAR_WEAPONS[name];
        opt.textContent = name;
        weaponSelect.appendChild(opt);
    }
    weaponSelect.value = SOLAR_WEAPONS['Ninguno'];
    createSolarRow(contentDiv, '⚔️ Weapon:', weaponSelect);

    // Selector de efectos
    const effectSelect = document.createElement('select');
    effectSelect.style.cssText = solarInputStyle;
    for (const name in SOLAR_EFFECTS) {
        const opt = document.createElement('option');
        opt.value = SOLAR_EFFECTS[name];
        opt.textContent = name;
        effectSelect.appendChild(opt);
    }
    effectSelect.value = SOLAR_EFFECTS['Ninguno'];
    createSolarRow(contentDiv, '✨ Effect:', effectSelect);

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

    effectSelect.addEventListener('change', () => {
        if (effectSelect.value !== '') {
            weaponSelect.value = SOLAR_WEAPONS['Ninguno'];
        }
    });

    // Intensity slider
    const intensitySlider = document.createElement('input');
    intensitySlider.type = 'range';
    intensitySlider.min = '1';
    intensitySlider.max = '5';
    intensitySlider.value = '3';
    intensitySlider.style.cssText = `
        flex-grow: 1; -webkit-appearance: none; height: 6px; border-radius: 5px;
        background: linear-gradient(to right, #00ffff 0%, #ff6b35 100%);
        outline: none;
    `;
    createSolarRow(contentDiv, '⚡ Power:', intensitySlider);

    // Repeat toggle
    const repeatToggle = document.createElement('input');
    repeatToggle.type = 'checkbox';
    repeatToggle.id = 'solarRepeatToggle';
    repeatToggle.style.cssText = `margin-right: 8px; cursor: pointer; transform: scale(1.3);`;
    const repeatLabel = document.createElement('label');
    repeatLabel.htmlFor = 'solarRepeatToggle';
    repeatLabel.textContent = ' 🔄 Repeat Action';
    repeatLabel.style.cssText = `display: flex; align-items: center; cursor: pointer; color: #00ffff;`;
    const repeatWrapper = document.createElement('div');
    repeatWrapper.style.cssText = `display:flex; align-items:center; gap:0;`;
    repeatWrapper.appendChild(repeatToggle);
    repeatWrapper.appendChild(repeatLabel);
    contentDiv.appendChild(repeatWrapper);

    // Botones
    const executeBtn = document.createElement('button');
    executeBtn.textContent = '🚀 EXECUTE SOLAR WEAPON';
    executeBtn.disabled = true;
    executeBtn.style.cssText = `
        padding: 12px 20px; border-radius: 10px; border: none;
        background: linear-gradient(145deg, #ff6b35, #f7931e);
        color: white; font-weight: bold; font-size: 15px;
        cursor: pointer; transition: all 0.3s ease;
        box-shadow: 0 4px 15px rgba(255, 107, 53, 0.4);
        text-transform: uppercase; letter-spacing: 1px;
    `;

    stopBtn = document.createElement('button');
    stopBtn.textContent = '🛑 STOP DESTRUCTION';
    stopBtn.disabled = true;
    stopBtn.style.cssText = `
        margin-top: 8px; padding: 10px 18px; border-radius: 8px; border: none;
        background: linear-gradient(145deg, #ff1744, #d50000);
        color: white; font-weight: bold; font-size: 14px;
        cursor: pointer; transition: all 0.3s ease;
        box-shadow: 0 4px 12px rgba(255, 23, 68, 0.4);
        text-transform: uppercase;
    `;

    contentDiv.appendChild(executeBtn);
    contentDiv.appendChild(stopBtn);
    document.body.appendChild(container);

    /* ----------  FUNCIONES AUXILIARES  ---------- */
    function drawSolarCommand(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) {
            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) return;

        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);
        const cmd = `42["drawcmd",0,[${normX1},${normY1},${normX2},${normY2},false,${0 - thickness},"${color}",0,0,{}]]`;
        socket.send(cmd);
    }

    function getPlayerCoords(playerId) {
        const avatar = document.querySelector(`.spawnedavatar[data-playerid="${playerId}"]`);
        if (!avatar) 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
        };
    }

    /* ----------  ARMAS ÚNICAS (VERSION 1.1) ---------- */

 // 🌠 Lluvia de Meteoritos
async function meteorRain(playerId, intensity = 3) {
    if (stopSignal) return;
    console.log(`🌠 Lluvia de meteoritos iniciada`);

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

    const meteorCount = 20 + (intensity * 8); // Ahora es número de flores
    const colors = ['#ff4500', '#ff6347', '#ffa500']; // Ahora colores de pétalos

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

        // NUEVO: En lugar de meteoros cayendo, flores creciendo desde el centro
        const startX = target.x; // Todas las "flores" nacen del centro
        const startY = target.y;

        // Posición final: patrón radial en lugar de caída
        const flowerAngle = (i / meteorCount) * Math.PI * 2; // Distribución circular
        const flowerDistance = 50 + (i % 4) * 25; // Capas de flores
        const endX = target.x + flowerDistance * Math.cos(flowerAngle);
        const endY = target.y + flowerDistance * Math.sin(flowerAngle) * 0.7; // Aplanado

        const color = colors[Math.floor(Math.random() * colors.length)];

        // NUEVO: Tallo de la flor en lugar de meteorito
        drawSolarCommand(startX, startY, endX, endY, '#ffe99c', 2 + Math.random() * 3);

        // Mini explosión al impactar
        // NUEVO: Pétalos de flor en lugar de chispas de explosión
        for (let spark = 0; spark < 3; spark++) {
            const sparkAngle = (spark / 3) * Math.PI * 2; // Pétalos ordenados
            const sparkDist = 8 + Math.random() * 12; // Tamaño del pétalo
            const sparkX = endX + sparkDist * Math.cos(sparkAngle + flowerAngle);
            const sparkY = endY + sparkDist * Math.sin(sparkAngle + flowerAngle);

            // Dibujar pétalo como línea curvada
            drawSolarCommand(endX, endY, sparkX, sparkY, color, 1);

            // NUEVO: Centro de la flor
            const centerX = endX + 3 * Math.cos(sparkAngle + Math.PI);
            const centerY = endY + 3 * Math.sin(sparkAngle + Math.PI);
            drawSolarCommand(endX, endY, centerX, centerY, '#FFD700', 2);
        }

        // NUEVO: Hojas adicionales para hacer más realista
        if (i % 2 === 0) {
            const leafAngle1 = flowerAngle + Math.PI * 0.3;
            const leafAngle2 = flowerAngle - Math.PI * 0.3;
            const leafDist = flowerDistance * 0.6;

            const leaf1X = target.x + leafDist * Math.cos(leafAngle1);
            const leaf1Y = target.y + leafDist * Math.sin(leafAngle1) * 0.7;
            const leaf2X = target.x + leafDist * Math.cos(leafAngle2);
            const leaf2Y = target.y + leafDist * Math.sin(leafAngle2) * 0.7;

            drawSolarCommand(startX, startY, leaf1X, leaf1Y, '#ffa159', 1);
            drawSolarCommand(startX, startY, leaf2X, leaf2Y, '#ffcd59', 1);
        }

        await new Promise(r => setTimeout(r, 80 + Math.random() * 60));
    }
}


    // ☄️ Asteroide Gigante
    async function giantAsteroid(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`☄️ Asteroide gigante aproximándose`);

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

        const size = 30 + intensity * 10;
        const startX = -100;
        const startY = -100;
        const endX = target.x;
        const endY = target.y;

        // Animación de aproximación
        const steps = 25;
        for (let step = 0; step < steps; step++) {
            if (stopSignal) break;

            const progress = step / steps;
            const currentX = startX + (endX - startX) * progress;
            const currentY = startY + (endY - startY) * progress;
            const currentSize = size * (0.2 + progress * 0.8);

            // Núcleo del asteroide
            drawSolarCommand(currentX - currentSize/2, currentY - currentSize/2,
                           currentX + currentSize/2, currentY + currentSize/2, '#8B4513', currentSize/3);

            // Cola ardiente
            for (let trail = 0; trail < 8; trail++) {
                const trailX = currentX - (progress * 50) - trail * 15;
                const trailY = currentY - (progress * 50) - trail * 15;
                drawSolarCommand(currentX, currentY, trailX, trailY, '#ff4500', 8 - trail);
            }

            await new Promise(r => setTimeout(r, 120));
        }

        // Impacto devastador
        for (let explosion = 0; explosion < 30; explosion++) {
            if (stopSignal) break;
            const angle = Math.random() * Math.PI * 2;
            const distance = Math.random() * (80 + intensity * 20);
            const impactX = endX + distance * Math.cos(angle);
            const impactY = endY + distance * Math.sin(angle);
            const color = ['#ff0000', '#ff4500', '#ffa500'][Math.floor(Math.random() * 3)];
            drawSolarCommand(endX, endY, impactX, impactY, color, 8 + Math.random() * 6);
        }
    }


    // ⚡ Rayo Láser (Version 1.1 - Weapon)
    async function laserBeam(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`⚡ Disparando rayo láser`);

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

        const startX = Math.random() * canvas.width;
        const startY = 0;
        const endX = target.x;
        const endY = target.y;

        // Carga láser
        for (let charge = 0; charge < 10; charge++) {
            if (stopSignal) break;
            const chargeIntensity = charge * 3;
            drawSolarCommand(startX - chargeIntensity, startY, startX + chargeIntensity, startY, '#ff0000', chargeIntensity);
            await new Promise(r => setTimeout(r, 100));
        }

        // Disparo continuo
        const beamDuration = 2000 + intensity * 500;
        const beamStart = Date.now();

        while (Date.now() - beamStart < beamDuration) {
            if (stopSignal) break;

            // Rayo principal
            drawSolarCommand(startX, startY, endX, endY, '#ff0000', 15);
            drawSolarCommand(startX, startY, endX, endY, '#ffffff', 8);

            // Efectos de dispersión
            for (let scatter = 0; scatter < 3; scatter++) {
                const scatterX = endX + (Math.random() - 0.5) * 30;
                const scatterY = endY + (Math.random() - 0.5) * 30;
                drawSolarCommand(endX, endY, scatterX, scatterY, '#ff6600', 4);
            }

            await new Promise(r => setTimeout(r, 50));
        }
    }

    // ⚡ Rayo Láser (Version 1.0 - Effect)
    async function laserBeam_v1_0(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`⚡ Disparando rayo láser a jugador ${playerId} (v1.0)`);

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

        const startX = Math.random() * canvas.width;
        const startY = 0;
        const endX = target.x;
        const endY = target.y;

        const duration = 1000 + intensity * 500;
        const startTime = Date.now();

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

            // Núcleo del láser
            drawSolarCommand(startX, startY, endX, endY, '#00ffff', 6 + intensity);
            drawSolarCommand(startX, startY, endX, endY, '#ffffff', 3 + intensity);

            // Efectos de energía
            for (let i = 0; i < 5; i++) {
                const offsetX = (Math.random() - 0.5) * 10;
                const offsetY = (Math.random() - 0.5) * 10;
                drawSolarCommand(
                    startX + offsetX, startY + offsetY,
                    endX + offsetX, endY + offsetY,
                    '#87ceeb', 1 + Math.random() * 2
                );
            }

            await new Promise(r => setTimeout(r, 50));
        }

        // Impacto final
        await createEnergyImpact(endX, endY, intensity);
    }

    // 🔮 Rayo de Plasma
    async function plasmaBeam(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🔮 Disparando rayo de plasma`);

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

        const startX = Math.random() * canvas.width;
        const startY = 0;
        const endX = target.x;
        const endY = target.y;

        // Carga de plasma
        for (let charge = 0; charge < 8; charge++) {
            if (stopSignal) break;
            const chargeRadius = charge * 5;
            for (let spark = 0; spark < 12; spark++) {
                const angle = (spark / 12) * Math.PI * 2 + charge * 0.5;
                const sparkX = startX + chargeRadius * Math.cos(angle);
                const sparkY = startY + chargeRadius * Math.sin(angle);
                drawSolarCommand(startX, startY, sparkX, sparkY, '#ff00ff', 4 - charge * 0.3);
            }
            await new Promise(r => setTimeout(r, 150));
        }

        // Disparo del plasma
        const beamDuration = 2000;
        const beamStartTime = Date.now();

        while (Date.now() - beamStartTime < beamDuration) {
            if (stopSignal) break;

            // Rayo principal ondulante
            const waveOffset = Math.sin((Date.now() - beamStartTime) * 0.01) * 15;

            // Núcleo del plasma
            drawSolarCommand(startX, startY, endX + waveOffset, endY, '#ff00ff', 12);
            drawSolarCommand(startX, startY, endX + waveOffset, endY, '#ffffff', 6);

            // Descargas laterales
            for (let discharge = 0; discharge < 5; discharge++) {
                const progress = discharge / 5;
                const dischargeX = startX + (endX - startX) * progress + waveOffset * progress;
                const dischargeY = startY + (endY - startY) * progress;
                const sideX = dischargeX + (Math.random() - 0.5) * 40;
                const sideY = dischargeY + (Math.random() - 0.5) * 40;

                drawSolarCommand(dischargeX, dischargeY, sideX, sideY, '#ff00ff', 3);
            }

            await new Promise(r => setTimeout(r, 80));
        }

        // Impacto de plasma
        for (let impact = 0; impact < 15; impact++) {
            if (stopSignal) break;
            const burstAngle = Math.random() * Math.PI * 2;
            const burstDist = Math.random() * 60;
            const burstX = endX + burstDist * Math.cos(burstAngle);
            const burstY = endY + burstDist * Math.sin(burstAngle);
            drawSolarCommand(endX, endY, burstX, burstY, '#ff00ff', 6 - impact * 0.3);
        }
    }

    // 🔥 Dragón Espacial
    async function spaceDragon(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🔥 Invocando dragón espacial`);

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

        let dragonX = -100;
        let dragonY = target.y - 50;
        const dragonSize = 20 + intensity * 8;

        // Vuelo del dragón
        const flightSteps = 60;
        for (let step = 0; step < flightSteps; step++) {
            if (stopSignal) break;

            const nextX = dragonX + (canvas.width + 200) / flightSteps;
            const nextY = dragonY + Math.sin(step * 0.2) * 20;

            // Cuerpo del dragón
            drawSolarCommand(dragonX, dragonY, nextX, nextY, '#8B0000', dragonSize);

            // Alas
            const wingSpan = dragonSize * 1.5;
            const wingAngle = Math.sin(step * 0.5) * 0.5;
            const wingY1 = nextY - wingSpan * Math.cos(wingAngle);
            const wingY2 = nextY + wingSpan * Math.cos(wingAngle);
            drawSolarCommand(nextX, nextY, nextX - wingSpan, wingY1, '#4B0000', dragonSize * 0.3);
            drawSolarCommand(nextX, nextY, nextX - wingSpan, wingY2, '#4B0000', dragonSize * 0.3);

            // Llamas del dragón hacia el objetivo
            if (step > 20 && Math.abs(nextX - target.x) < 100) {
                for (let flame = 0; flame < 8; flame++) {
                    const flameAngle = Math.atan2(target.y - nextY, target.x - nextX) + (Math.random() - 0.5) * 0.5;
                    const flameDist = 30 + Math.random() * 50;
                    const flameX = nextX + flameDist * Math.cos(flameAngle);
                    const flameY = nextY + flameDist * Math.sin(flameAngle);
                    const flameColors = ['#ff4500', '#ff6600', '#ffa500'];
                    drawSolarCommand(nextX, nextY, flameX, flameY, flameColors[flame % 3], 6);
                }
            }

            dragonX = nextX;
            dragonY = nextY;
            await new Promise(r => setTimeout(r, 100));
        }
    }

    // 🌑 Agujero Negro (Version 1.1 - Weapon) - Solo Batches
    async function blackHole(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🌑 Creando agujero negro`);

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

        const centerX = target.x;
        const centerY = target.y;
        const duration = 50 + intensity * 50;
        const startTime = Date.now();

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

            const elapsed = Date.now() - startTime;

            // Horizonte de eventos (negro)
            const eventHorizon = 20 + intensity * 5;
            for (let horizon = 0; horizon < 16; horizon++) {
                const hAngle = (horizon / 16) * Math.PI * 2;
                const hX = centerX + eventHorizon * Math.cos(hAngle);
                const hY = centerY + eventHorizon * Math.sin(hAngle);
                drawSolarCommand(centerX, centerY, hX, hY, '#000000', 8);
            }

            // Disco de acreción
            const accretionLayers = 5;
            for (let layer = 0; layer < accretionLayers; layer++) {
                const layerRadius = eventHorizon + (layer + 1) * (15 + intensity * 3);
                const layerSpeed = elapsed * (0.0001 + layer * 0.00005);
                const layerSegments = 20;

                for (let seg = 0; seg < layerSegments; seg++) {
                    const segAngle = (seg / layerSegments) * Math.PI * 2 + layerSpeed;
                    const nextAngle = ((seg + 1) / layerSegments) * Math.PI * 2 + layerSpeed;

                    const x1 = centerX + layerRadius * Math.cos(segAngle);
                    const y1 = centerY + layerRadius * Math.sin(segAngle) * 0.3;
                    const x2 = centerX + layerRadius * Math.cos(nextAngle);
                    const y2 = centerY + layerRadius * Math.sin(nextAngle) * 0.3;

                    const layerColors = ['#ff6600', '#ff4500', '#ff0000', '#8B0000', '#4B0000'];
                    drawSolarCommand(x1, y1, x2, y2, layerColors[layer], 6 - layer);
                }
            }

// Círculo de materia orbital
const orbitalRadius = 80 + intensity * 20;
const particleCount = 12 + intensity * 4;
for (let particle = 0; particle < particleCount; particle++) {
    const particleAngle = (particle / particleCount) * Math.PI * 2 + elapsed * 0.002;
    const particleX = centerX + orbitalRadius * Math.cos(particleAngle);
    const particleY = centerY + orbitalRadius * Math.sin(particleAngle) * 0.6; // Aplanado para efecto de disco

    // Dibujar partícula como pequeño círculo
    const nextAngle = particleAngle + 0.1;
    const nextX = centerX + orbitalRadius * Math.cos(nextAngle);
    const nextY = centerY + orbitalRadius * Math.sin(nextAngle) * 0.6;

    drawSolarCommand(particleX, particleY, nextX, nextY, '#ffff00', 4);

    // Partículas más pequeñas para mayor densidad
    if (particle % 2 === 0) {
        const smallAngle = particleAngle + Math.PI;
        const smallX = centerX + (orbitalRadius * 0.8) * Math.cos(smallAngle);
        const smallY = centerY + (orbitalRadius * 0.8) * Math.sin(smallAngle) * 0.6;
        const smallNextX = centerX + (orbitalRadius * 0.8) * Math.cos(smallAngle + 0.1);
        const smallNextY = centerY + (orbitalRadius * 0.8) * Math.sin(smallAngle + 0.1) * 0.6;

        drawSolarCommand(smallX, smallY, smallNextX, smallNextY, '#ffa500', 2);
    }
}


            await new Promise(r => setTimeout(r, 100));
        }
    }

    // 🛸 Invasión OVNI (Version 1.1 - Weapon) - Solo Batches y solo 1 OVNI
    async function ufoInvasion(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🛸 Iniciando invasión OVNI`);

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

        const ufos = [];

        // Crear UNA formación de OVNI
        ufos.push({
            x: target.x, // Centered
            y: target.y - 100, // Above target
            angle: 0,
            size: 15 + intensity * 3
        });

        const invasionDuration = 1000;
        const startTime = Date.now();

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

            const elapsed = Date.now() - startTime;

            for (let i = 0; i < ufos.length; i++) { // Este bucle ahora solo se ejecutará una vez para el OVNI único
                const ufo = ufos[i];

                // Movimiento ondulante
                ufo.x += Math.sin(elapsed * 0.003 + i) * 2;
                ufo.y += Math.cos(elapsed * 0.002 + i) * 1;
                ufo.angle += 0.1;

                // Cuerpo del OVNI
                const ufoPoints = 12;
                for (let p = 0; p < ufoPoints; p++) {
                    const pAngle = (p / ufoPoints) * Math.PI * 2 + ufo.angle;
                    const nextAngle = ((p + 1) / ufoPoints) * Math.PI * 2 + ufo.angle;

                    const x1 = ufo.x + ufo.size * Math.cos(pAngle);
                    const y1 = ufo.y + ufo.size * Math.sin(pAngle) * 0.3;
                    const x2 = ufo.x + ufo.size * Math.cos(nextAngle);
                    const y2 = ufo.y + ufo.size * Math.sin(nextAngle) * 0.3;

                    drawSolarCommand(x1, y1, x2, y2, '#c0c0c0', 4);
                }

                // Cúpula
                const domeSize = ufo.size * 0.6;
                for (let d = 0; d < 8; d++) {
                    const dAngle = (d / 8) * Math.PI * 2;
                    const dX = ufo.x + domeSize * Math.cos(dAngle);
                    const dY = ufo.y - 10 + domeSize * Math.sin(dAngle) * 0.5;
                    drawSolarCommand(ufo.x, ufo.y - 10, dX, dY, '#87ceeb', 3);
                }

                // Rayo tractor
                if (Math.random() < 0.3) {
                    const beamWidth = ufo.size * 0.8;
                    for (let beam = 0; beam < 6; beam++) {
                        const beamX = ufo.x + (beam - 3) * (beamWidth / 6);
                        const beamY = target.y + Math.random() * 30;
                        drawSolarCommand(ufo.x, ufo.y + ufo.size * 0.3, beamX, beamY, '#00ff00', 2);
                    }
                }
            }

            await new Promise(r => setTimeout(r, 80));
        }
    }

    // 🗡️ Sable Láser Galáctico
    async function galacticLightsaber(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🗡️ Activando sable láser galáctico`);

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

        const centerX = target.x;
        const centerY = target.y;
        const bladeLength = 60 + intensity * 15;
        const rotations = 3;

        // Activación del sable
        for (let charge = 0; charge < 10; charge++) {
            if (stopSignal) break;
            const currentLength = (bladeLength * charge) / 10;
            drawSolarCommand(centerX, centerY - currentLength, centerX, centerY + currentLength, '#00ff00', 8);
            drawSolarCommand(centerX, centerY - currentLength, centerX, centerY + currentLength, '#ffffff', 4);
            await new Promise(r => setTimeout(r, 100));
        }

        // Corte giratorio
        const totalSteps = rotations * 24;
        for (let step = 0; step < totalSteps; step++) {
            if (stopSignal) break;

            const angle = (step / 24) * Math.PI * 2;
            const blade1X = centerX + bladeLength * Math.cos(angle);
            const blade1Y = centerY + bladeLength * Math.sin(angle);
            const blade2X = centerX - bladeLength * Math.cos(angle);
            const blade2Y = centerY - bladeLength * Math.sin(angle);

            // Hoja del sable
            drawSolarCommand(centerX, centerY, blade1X, blade1Y, '#00ff00', 8);
            drawSolarCommand(centerX, centerY, blade2X, blade2Y, '#00ff00', 8);
            drawSolarCommand(centerX, centerY, blade1X, blade1Y, '#ffffff', 4);
            drawSolarCommand(centerX, centerY, blade2X, blade2Y, '#ffffff', 4);

            // Efectos de corte
            if (step % 4 === 0) {
                for (let spark = 0; spark < 5; spark++) {
                    const sparkAngle = angle + (Math.random() - 0.5) * 0.5;
                    const sparkDist = bladeLength * 0.8 + Math.random() * 20;
                    const sparkX = centerX + sparkDist * Math.cos(sparkAngle);
                    const sparkY = centerY + sparkDist * Math.sin(sparkAngle);
                    drawSolarCommand(blade1X, blade1Y, sparkX, sparkY, '#00ffff', 2);
                }
            }

            await new Promise(r => setTimeout(r, 80));
        }
    }

    // 🚀 Misil de Antimateria
    async function antimatterMissile(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🚀 Lanzando misil de antimateria`);

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

        let missileX = 50;
        let missileY = canvas.height - 100;
        const targetX = target.x;
        const targetY = target.y;

        // Vuelo del misil
        const flightSteps = 40;
        for (let step = 0; step < flightSteps; step++) {
            if (stopSignal) break;

            const progress = step / flightSteps;
            const nextX = 50 + (targetX - 50) * progress;
            const nextY = (canvas.height - 100) + (targetY - (canvas.height - 100)) * progress;

            // Cuerpo del misil
            drawSolarCommand(missileX, missileY, nextX, nextY, '#c0c0c0', 6);

            // Propulsión
            const thrustX = missileX - (nextX - missileX) * 2;
            const thrustY = missileY - (nextY - missileY) * 2;
            drawSolarCommand(missileX, missileY, thrustX, thrustY, '#00ffff', 4);
            drawSolarCommand(missileX, missileY, thrustX, thrustY, '#ffffff', 2);

            // Estela
            drawSolarCommand(missileX, missileY, nextX, nextY, '#87ceeb', 2);

            missileX = nextX;
            missileY = nextY;

            await new Promise(r => setTimeout(r, 100));
        }

        // Explosión de antimateria (aniquilación)
        const annihilationSteps = 20;
        for (let step = 0; step < annihilationSteps; step++) {
            if (stopSignal) break;

            const currentRadius = step * (15 + intensity * 5);

            // Ondas de aniquilación
            for (let wave = 0; wave < 3; wave++) {
                const waveRadius = currentRadius + wave * 20;
                const segments = 16;

                for (let seg = 0; seg < segments; seg++) {
                    const angle1 = (seg / segments) * Math.PI * 2;
                    const angle2 = ((seg + 1) / segments) * Math.PI * 2;
                    const x1 = targetX + waveRadius * Math.cos(angle1);
                    const y1 = targetY + waveRadius * Math.sin(angle1);
                    const x2 = targetX + waveRadius * Math.cos(angle2);
                    const y2 = targetY + waveRadius * Math.sin(angle2);

                    const colors = ['#ffffff', '#00ffff', '#ff00ff'];
                    drawSolarCommand(x1, y1, x2, y2, colors[wave], 8 - wave * 2);
                }
            }

            await new Promise(r => setTimeout(r, 150));
        }
    }

    // 🌪️ Vórtice Gravitacional (Version 1.1 - Weapon) - Delays y Batches
    async function gravityVortex(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🌪️ Generando vórtice gravitacional`);

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

        const centerX = target.x;
        const centerY = target.y;
        const duration = 400 + intensity * 100;
        const startTime = Date.now();

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

            const elapsed = Date.now() - startTime;
            const rotationSpeed = elapsed * 0.008;

            // Espiral gravitacional
            const spiralArms = 4;
            for (let arm = 0; arm < spiralArms; arm++) {
                const armOffset = (arm / spiralArms) * Math.PI * 2;

                // Cada brazo espiral
                for (let segment = 0; segment < 20; segment++) {
                    const segmentProgress = segment / 20;
                    const radius = segmentProgress * (80 + intensity * 20);
                    const angle = armOffset + rotationSpeed + segmentProgress * Math.PI * 6;

                    const x = centerX + radius * Math.cos(angle);
                    const y = centerY + radius * Math.sin(angle);

                    // Conectar al centro (BATCH)
                    const colors = ['#9400d3', '#4b0082', '#8a2be2'];
                    drawSolarCommand(centerX, centerY, x, y, colors[arm % colors.length], 8 - segmentProgress * 6);

                    // Efectos de distorsión (BATCH)
                    if (Math.random() < 0.3) {
                        const distortX = x + (Math.random() - 0.5) * 20;
                        const distortY = y + (Math.random() - 0.5) * 20;
                        drawSolarCommand(x, y, distortX, distortY, '#ffffff', 2);
                    }
                }
            }

            // Centro del vórtice (BATCH)
            const coreSize = 10 + Math.sin(elapsed * 0.01) * 5;
            for (let core = 0; core < 8; core++) {
                const coreAngle = (core / 8) * Math.PI * 2;
                const coreX = centerX + coreSize * Math.cos(coreAngle);
                const coreY = centerY + coreSize * Math.sin(coreAngle);
                drawSolarCommand(centerX, centerY, coreX, coreY, '#000000', 6);
            }

            await new Promise(r => setTimeout(r, 100)); // DELAY entre frames
        }
    }


    /* ----------  EFECTOS ÚNICOS (VERSION 1.1) ---------- */

    // 🛡️ Escudo Planetario (Version 1.1 - Effect) - Delays y Batches
    async function planetaryShield(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🛡️ Activando escudo planetario`);

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

        const centerX = target.x;
        const centerY = target.y;
        const shieldRadius = 60 + intensity * 20;
        const duration = 100 + intensity * 100;
        const startTime = Date.now();

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

            const elapsed = Date.now() - startTime;

            // Capas del escudo (BATCH)
            const shieldLayers = 4;
            for (let layer = 0; layer < shieldLayers; layer++) {
                const layerRadius = shieldRadius - layer * 10;
                const layerAlpha = 1 - (layer * 0.2);
                const layerSpeed = elapsed * (0.002 + layer * 0.001);

                const segments = 20;
                for (let seg = 0; seg < segments; seg++) {
                    const angle1 = (seg / segments) * Math.PI * 2 + layerSpeed;
                    const angle2 = ((seg + 1) / segments) * Math.PI * 2 + layerSpeed;

                    const x1 = centerX + layerRadius * Math.cos(angle1);
                    const y1 = centerY + layerRadius * Math.sin(angle1);
                    const x2 = centerX + layerRadius * Math.cos(angle2);
                    const y2 = centerY + layerRadius * Math.sin(angle2);

                    const shieldColors = ['#00ffff', '#0080ff', '#0040ff', '#0020ff'];
                    drawSolarCommand(x1, y1, x2, y2, shieldColors[layer], 6 - layer);
                }
            }

            // Nodos energéticos (BATCH)
            const nodes = 8;
            for (let node = 0; node < nodes; node++) {
                const nodeAngle = (node / nodes) * Math.PI * 2 + elapsed * 0.005;
                const nodeX = centerX + shieldRadius * Math.cos(nodeAngle);
                const nodeY = centerY + shieldRadius * Math.sin(nodeAngle);

                // Pulso del nodo (BATCH)
                const pulseSize = 8 + Math.sin(elapsed * 0.01 + node) * 4;
                for (let pulse = 0; pulse < 6; pulse++) {
                    const pulseAngle = (pulse / 6) * Math.PI * 2;
                    const pulseX = nodeX + pulseSize * Math.cos(pulseAngle);
                    const pulseY = nodeY + pulseSize * Math.sin(pulseAngle);
                    drawSolarCommand(nodeX, nodeY, pulseX, pulseY, '#ffffff', 4);
                }
            }

            await new Promise(r => setTimeout(r, 100)); // DELAY entre frames
        }
    }

    // 🎆 Fuegos Artificiales Solares
    async function solarFireworks(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🎆 Lanzando fuegos artificiales solares`);

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

        const fireworkCount = 8 + intensity * 3;

        for (let fw = 0; fw < fireworkCount; fw++) {
            if (stopSignal) break;

            const launchX = target.x + (Math.random() - 0.5) * 200;
            const launchY = canvas.height - 50;
            const explodeX = target.x + (Math.random() - 0.5) * 150;
            const explodeY = target.y + (Math.random() - 0.5) * 100;

            // Proyectil subiendo
            drawSolarCommand(launchX, launchY, explodeX, explodeY, '#ffff00', 4);

            await new Promise(r => setTimeout(r, 400));

            // Explosión de fuegos artificiales
            const colors = ['#ff0000', '#ff4500', '#ffff00', '#00ff00', '#00ffff', '#0000ff', '#ff00ff'];
            const sparkCount = 20 + intensity * 5;

            for (let spark = 0; spark < sparkCount; spark++) {
                const sparkAngle = (spark / sparkCount) * Math.PI * 2;
                const sparkDist = 30 + Math.random() * 40;
                const sparkX = explodeX + sparkDist * Math.cos(sparkAngle);
                const sparkY = explodeY + sparkDist * Math.sin(sparkAngle);
                const color = colors[Math.floor(Math.random() * colors.length)];

                drawSolarCommand(explodeX, explodeY, sparkX, sparkY, color, 3);

                // Chispas secundarias
                if (Math.random() < 0.4) {
                    const subSparkX = sparkX + (Math.random() - 0.5) * 20;
                    const subSparkY = sparkY + (Math.random() - 0.5) * 20;
                    drawSolarCommand(sparkX, sparkY, subSparkX, subSparkY, color, 1);
                }
            }

            await new Promise(r => setTimeout(r, 200));
        }
    }

    // ❄️ Era de Hielo Instantánea (Version 1.1 - Effect) - Delays y Batches
    async function instantIceAge(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`❄️ Iniciando era de hielo instantánea`);

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

        const freezeRadius = 20 + intensity * 10;
        const centerX = target.x;
        const centerY = target.y;

        // Expansión del hielo
        const iceSteps = 10;
        for (let step = 0; step < iceSteps; step++) { // Cada paso es un 'batch' de dibujo
            if (stopSignal) break;

            const currentRadius = (freezeRadius * step) / iceSteps;
            const iceColors = ['#e0ffff', '#b0e0e6', '#87ceeb', '#add8e6'];

            // Cristales de hielo (BATCH)
            const crystalCount = 16;
            for (let crystal = 0; crystal < crystalCount; crystal++) {
                const angle = (crystal / crystalCount) * Math.PI * 2;
                const crystalX = centerX + currentRadius * Math.cos(angle);
                const crystalY = centerY + currentRadius * Math.sin(angle);

                // Cristal hexagonal (BATCH)
                for (let side = 0; side < 6; side++) {
                    const sideAngle = angle + (side / 6) * Math.PI * 2;
                    const sideLength = 8 + step;
                    const sideEndX = crystalX + sideLength * Math.cos(sideAngle);
                    const sideEndY = crystalY + sideLength * Math.sin(sideAngle);

                    const color = iceColors[step % iceColors.length];
                    drawSolarCommand(crystalX, crystalY, sideEndX, sideEndY, color, 4);
                }

                // Conectar al centro (BATCH)
                drawSolarCommand(centerX, centerY, crystalX, crystalY, '#ffffff', 2);
            }

            // Copos de nieve cayendo (BATCH)
            for (let flake = 0; flake < 15; flake++) {
                const flakeX = centerX + (Math.random() - 0.5) * currentRadius * 2;
                const flakeY = centerY - currentRadius + Math.random() * currentRadius * 2;
                const flakeEndX = flakeX + (Math.random() - 0.5) * 10;
                const flakeEndY = flakeY + Math.random() * 20;

                drawSolarCommand(flakeX, flakeY, flakeEndX, flakeEndY, '#ffffff', 1);
            }

            await new Promise(r => setTimeout(r, 150)); // DELAY entre batches
        }
    }

    // 🌋 Erupción Volcánica
    async function volcanicEruption(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🌋 Provocando erupción volcánica`);

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

        const volcanoX = target.x;
        const volcanoY = target.y + 50;

        // Formar el volcán
        const volcanoHeight = 60 + intensity * 15;
        for (let layer = 0; layer < 10; layer++) {
            if (stopSignal) break;

            const layerY = volcanoY - layer * (volcanoHeight / 10);
            const layerWidth = (40 - layer * 3) + intensity * 5;

            drawSolarCommand(volcanoX - layerWidth, layerY, volcanoX + layerWidth, layerY, '#8b4513', 13);
        }

        await new Promise(r => setTimeout(r, 500));

        // Erupción
        const eruptionSteps = 25;
        for (let step = 0; step < eruptionSteps; step++) {
            if (stopSignal) break;

            // Lava principal
            const lavaCount = 8 + intensity * 3;
            for (let lava = 0; lava < lavaCount; lava++) {
                const angle = (Math.random() - 0.5) * Math.PI;
                const velocity = 20 + Math.random() * (40 + intensity * 20);
                const lavaX = volcanoX + velocity * Math.cos(angle);
                const lavaY = volcanoY - volcanoHeight - velocity * Math.abs(Math.sin(angle));

                const lavaColors = ['#ff4500', '#ff6347', '#ffa500', '#ff0000'];
                const color = lavaColors[Math.floor(Math.random() * lavaColors.length)];

                drawSolarCommand(volcanoX, volcanoY - volcanoHeight, lavaX, lavaY, color, 6);

                // Partículas de lava
                if (Math.random() < 0.6) {
                    const particleX = lavaX + (Math.random() - 0.5) * 20;
                    const particleY = lavaY + Math.random() * 30;
                    drawSolarCommand(lavaX, lavaY, particleX, particleY, color, 2);
                }
            }

            // Humo y ceniza
            for (let smoke = 0; smoke < 5; smoke++) {
                const smokeX = volcanoX + (Math.random() - 0.5) * 30;
                const smokeY = volcanoY - volcanoHeight - step * 15;
                const smokeDrift = smokeX + (Math.random() - 0.5) * 50;

                drawSolarCommand(smokeX, volcanoY - volcanoHeight, smokeDrift, smokeY, '#696969', 4);
            }

            await new Promise(r => setTimeout(r, 200));
        }
    }

    // 🌀 Anomalía Espacial (Version 1.1 - Effect) - Delays y Batches
    async function spaceAnomaly(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🌀 Manifestando anomalía espacial`);

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

        const anomalyX = target.x;
        const anomalyY = target.y;
        const duration = 500 + intensity * 100;
        const startTime = Date.now();

        while (Date.now() - startTime < duration) { // Cada iteración es un 'batch' de dibujo
            if (stopSignal) break;

            const elapsed = Date.now() - startTime;

            // Distorsión del espacio-tiempo (BATCH)
            const distortionCount = 12;
            for (let distort = 0; distort < distortionCount; distort++) {
                const distortAngle = (distort / distortionCount) * Math.PI * 2 + elapsed * 0.005;
                const baseRadius = 60 + intensity * 15;
                const waveRadius = baseRadius + Math.sin(elapsed * 0.01 + distort) * 20;

                const normalX = anomalyX + waveRadius * Math.cos(distortAngle);
                const normalY = anomalyY + waveRadius * Math.sin(distortAngle);

                // Líneas de distorsión (BATCH)
                drawSolarCommand(anomalyX, anomalyY, normalX, normalY, '#9400d3', 3);

                // Efectos secundarios aleatorios (BATCH)
                if (Math.random() < 0.3) {
                    const randomX = normalX + (Math.random() - 0.5) * 40;
                    const randomY = normalY + (Math.random() - 0.5) * 40;
                    drawSolarCommand(normalX, normalY, randomX, randomY, '#ff00ff', 1);
                }
            }

            // Partículas cuánticas (BATCH)
            for (let quantum = 0; quantum < 8; quantum++) {
                const quantumAngle = Math.random() * Math.PI * 2;
                const quantumDist = Math.random() * 80;
                const quantumX = anomalyX + quantumDist * Math.cos(quantumAngle);
                const quantumY = anomalyY + quantumDist * Math.sin(quantumAngle);

                // Teletransporte cuántico (BATCH)
                const newQuantumX = quantumX + (Math.random() - 0.5) * 100;
                const newQuantumY = quantumY + (Math.random() - 0.5) * 100;

                drawSolarCommand(quantumX, quantumY, newQuantumX, newQuantumY, '#00ffff', 2);
            }

            // Núcleo de la anomalía (BATCH)
            const coreIntensity = Math.sin(elapsed * 0.02) * 10 + 15;
            for (let core = 0; core < 6; core++) {
                const coreAngle = (core / 6) * Math.PI * 2;
                const coreX = anomalyX + coreIntensity * Math.cos(coreAngle);
                const coreY = anomalyY + coreIntensity * Math.sin(coreAngle);
                drawSolarCommand(anomalyX, anomalyY, coreX, coreY, '#ffffff', 6);
            }

            await new Promise(r => setTimeout(r, 120)); // DELAY entre frames
        }
    }


    /* ----------  EFECTOS MOVIDOS DE ARMAS (VERSION 1.0) ---------- */

    // 🌑 Agujero Negro (Version 1.0 - Effect) - Solo Batches
    async function blackHole_v1_0(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🌑 Creando agujero negro en jugador ${playerId} (v1.0)`);

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

        const centerX = target.x;
        const centerY = target.y;
        const duration = 50 + intensity * 50;
        const startTime = Date.now();

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

            const elapsed = Date.now() - startTime;
            const progress = elapsed / duration;

            // Núcleo negro
            const coreRadius = 15 + intensity * 3;
            for (let angle = 0; angle < 16; angle++) {
                const radians = (angle / 16) * 2 * Math.PI;
                const x = centerX + coreRadius * Math.cos(radians);
                const y = centerY + coreRadius * Math.sin(radians);
                drawSolarCommand(centerX, centerY, x, y, '#000000', 6);
            }

            // Anillo de acreción
            const rings = 3;
            for (let ring = 0; ring < rings; ring++) {
                const ringRadius = (30 + ring * 20) * (1 + progress * 0.5);
                const ringSegments = 24;

                for (let seg = 0; seg < ringSegments; seg++) {
                    const angle1 = (seg / ringSegments) * 2 * Math.PI + elapsed * 0.005 * (ring + 1);
                    const angle2 = ((seg + 1) / ringSegments) * 2 * Math.PI + elapsed * 0.005 * (ring + 1);

                    const x1 = centerX + ringRadius * Math.cos(angle1);
                    const y1 = centerY + ringRadius * Math.sin(angle1) * 0.3;
                    const x2 = centerX + ringRadius * Math.cos(angle2);
                    const y2 = centerY + ringRadius * Math.sin(angle2) * 0.3;

                    const colors = ['#ff6600', '#ff9900', '#ffcc00'];
                    const color = colors[ring % colors.length];
                    drawSolarCommand(x1, y1, x2, y2, color, 3 - ring);
                }
            }

            // Partículas siendo absorbidas
            for (let p = 0; p < 5; p++) {
                const distance = 100 + Math.random() * 100;
                const angle = Math.random() * Math.PI * 2;
                const startX = centerX + distance * Math.cos(angle);
                const startY = centerY + distance * Math.sin(angle);

                drawSolarCommand(startX, startY, centerX, centerY, '#ffffff', 1);
            }

            await new Promise(r => setTimeout(r, 100)); // DELAY entre frames
        }
    }

    // 🛸 Invasión OVNI (Version 1.0 - Effect)
    async function ufoInvasion_v1_0(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🛸 Iniciando invasión OVNI contra jugador ${playerId} (v1.0)`);

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

        const ufoCount = 3 + intensity;
        const ufos = [];

        // Crear OVNIs
        for (let i = 0; i < ufoCount; i++) {
            ufos.push({
                x: Math.random() * canvas.width,
                y: 50 + i * 30,
                angle: 0,
                targetX: target.x + (Math.random() - 0.5) * 100,
                targetY: target.y + (Math.random() - 0.5) * 50
            });
        }

        const attackDuration = 4000;
        const startTime = Date.now();

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

            for (let i = 0; i < ufos.length; i++) {
                const ufo = ufos[i];

                // Mover OVNI hacia objetivo
                const dx = ufo.targetX - ufo.x;
                const dy = ufo.targetY - ufo.y;
                ufo.x += dx * 0.02;
                ufo.y += dy * 0.02;
                ufo.angle += 0.1;

                // Dibujar OVNI
                await drawUFO(ufo.x, ufo.y, ufo.angle, intensity);

                // Disparar ocasionalmente
                if (Math.random() < 0.3) {
                    await ufoLaserShot(ufo.x, ufo.y, target.x, target.y);
                }
            }

            await new Promise(r => setTimeout(r, 200));
        }
    }

    // 🌪️ Vórtice Gravitacional (Version 1.0 - Effect) - Delays y Batches
    async function gravityVortex_v1_0(playerId, intensity = 3) {
        if (stopSignal) return;
        console.log(`🌪️ Vórtice Gravitacional activado en jugador ${playerId}`);

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

        const centerX = target.x;
        const centerY = target.y;
        const duration = 50 + intensity * 50;
        const startTime = Date.now();

        while (Date.now() - startTime < duration) { // Cada iteración es un 'batch' de dibujo
            if (stopSignal) break;

            const elapsed = Date.now() - startTime;
            const progress = elapsed / duration;

            // Centro del vórtice (BATCH)
            const coreRadius = 10 + intensity * 2;
            for (let angle = 0; angle < 16; angle++) {
                const radians = (angle / 16) * 2 * Math.PI;
                const x = centerX + coreRadius * Math.cos(radians);
                const y = centerY + coreRadius * Math.sin(radians);
                drawSolarCommand(centerX, centerY, x, y, '#000000', 6);
            }

            // Espirales de atracción (BATCH)
            const spirals = 4;
            for (let spiral = 0; spiral < spirals; spiral++) {
                const spiralRadius = (30 + spiral * 20) * (1 + progress * 0.5);
                const spiralSegments = 24;

                for (let seg = 0; seg < spiralSegments; seg++) {
                    const angle1 = (seg / spiralSegments) * 2 * Math.PI + elapsed * 0.008 * (spiral + 1);
                    const angle2 = ((seg + 1) / spiralSegments) * 2 * Math.PI + elapsed * 0.008 * (spiral + 1);

                    const x1 = centerX + spiralRadius * Math.cos(angle1);
                    const y1 = centerY + spiralRadius * Math.sin(angle1) * 0.8;
                    const x2 = centerX + spiralRadius * Math.cos(angle2);
                    const y2 = centerY + spiralRadius * Math.sin(angle2) * 0.8;

                    const colors = ['#9400d3', '#4b0082', '#8a2be2'];
                    const color = colors[spiral % colors.length];
                    drawSolarCommand(x1, y1, x2, y2, color, 4 - spiral);
                }
            }

// Galaxia minimalista (BATCH) - Solo elementos esenciales
// Sol central
for (let ray = 0; ray < 4; ray++) {
    const rayAngle = (ray / 4) * 2 * Math.PI;
    const rayX = centerX + 20 * Math.cos(rayAngle);
    const rayY = centerY + 20 * Math.sin(rayAngle);
    drawSolarCommand(centerX, centerY, rayX, rayY, '#ffff00', 6);
}

// 3 planetas principales
const planets = [
    { radius: 40, color: '#4285f4' },  // Tierra
    { radius: 70, color: '#ff4444' },  // Marte
    { radius: 100, color: '#d2691e' }  // Júpiter
];

planets.forEach((planet, index) => {
    const planetAngle = elapsed * 0.005 + (index * 2);
    const planetX = centerX + planet.radius * Math.cos(planetAngle);
    const planetY = centerY + planet.radius * Math.sin(planetAngle) * 0.7;

    drawSolarCommand(planetX, planetY, planetX + 3, planetY + 3, planet.color, 4);
});

// 6 estrellas de fondo
for (let star = 0; star < 6; star++) {
    const starAngle = (star / 6) * 2 * Math.PI;
    const starX = centerX + 120 * Math.cos(starAngle);
    const starY = centerY + 120 * Math.sin(starAngle);
    drawSolarCommand(starX, starY, starX + 1, starY + 1, '#ffffff', 2);
}


            await new Promise(r => setTimeout(r, 100)); // DELAY entre frames
        }
    }


    /* ----------  FUNCIONES AUXILIARES (DE V1.0) ---------- */
    // Nota: Estas funciones auxiliares no se modifican ya que su comportamiento
    // es general y no afecta los requisitos específicos de delays/batches para los efectos mayores.
    async function createImpactExplosion(x, y, intensity) {
        if (stopSignal) return;
        const particles = 8 + intensity * 2;
        const colors = ['#ff4500', '#ffa500', '#ffff00'];

        for (let p = 0; p < particles; p++) {
            const angle = (p / particles) * 2 * Math.PI;
            const distance = 15 + Math.random() * 20;
            const endX = x + distance * Math.cos(angle);
            const endY = y + distance * Math.sin(angle);
            const color = colors[Math.floor(Math.random() * colors.length)];
            drawSolarCommand(x, y, endX, endY, color, 2 + intensity);
        }
        await new Promise(r => setTimeout(r, 50));
    }

    async function createEnergyImpact(x, y, intensity) {
        if (stopSignal) return;
        const steps = 10;
        for (let step = 0; step < steps; step++) {
            const radius = step * 5;
            const sparkCount = 8;
            for (let spark = 0; spark < sparkCount; spark++) {
                const angle = (spark / sparkCount) * 2 * Math.PI;
                const endX = x + radius * Math.cos(angle);
                const endY = y + radius * Math.sin(angle);
                drawSolarCommand(x, y, endX, endY, '#00ffff', 4 - step * 0.3);
            }
            await new Promise(r => setTimeout(r, 50));
        }
    }

    async function drawMushroomCloud(x, y, intensity) {
        if (stopSignal) return;
        const cloudSteps = 15;
        const colors = ['#8b4513', '#a0522d', '#cd853f'];

        for (let step = 0; step < cloudSteps; step++) {
            const stemHeight = step * 10;
            const capRadius = 20 + step * 3;

            // Stem
            drawSolarCommand(x, y, x, y - stemHeight, colors, 8 + intensity);

            // Cap
            const segments = 16;
            for (let seg = 0; seg < segments; seg++) {
                const angle1 = (seg / segments) * Math.PI;
                const angle2 = ((seg + 1) / segments) * Math.PI;
                const x1 = x + capRadius * Math.cos(angle1);
                const y1 = y - stemHeight + capRadius * Math.sin(angle1) * 0.5;
                const x2 = x + capRadius * Math.cos(angle2);
                const y2 = y - stemHeight + capRadius * Math.sin(angle2) * 0.5;
                drawSolarCommand(x1, y1, x2, y2, colors[step % colors.length], 4);
            }
            await new Promise(r => setTimeout(r, 200));
        }
    }

    async function breatheFire(startX, startY, targetX, targetY, intensity) {
        if (stopSignal) return;
        const flames = 5 + intensity;
        const colors = ['#ff0000', '#ff4500', '#ffa500', '#ffff00'];

        for (let f = 0; f < flames; f++) {
            const progress = f / flames;
            const x = startX + (targetX - startX) * progress;
            const y = startY + (targetY - startY) * progress;
            const offsetX = (Math.random() - 0.5) * 30;
            const offsetY = (Math.random() - 0.5) * 30;
            const color = colors[Math.floor(Math.random() * colors.length)];
            drawSolarCommand(startX, startY, x + offsetX, y + offsetY, color, 3 + intensity);
        }
    }

    async function drawUFO(x, y, angle, intensity) {
        if (stopSignal) return;
        const size = 20 + intensity * 3;

        // Cuerpo principal
        drawSolarCommand(x - size, y, x + size, y, '#c0c0c0', 6);
        drawSolarCommand(x - size * 0.7, y - size * 0.3, x + size * 0.7, y - size * 0.3, '#c0c0c0', 4);

        // Luces
        const lights = 6;
        for (let light = 0; light < lights; light++) {
            const lightAngle = (light / lights) * 2 * Math.PI + angle;
            const lightX = x + size * 0.8 * Math.cos(lightAngle);
            const lightY = y + size * 0.8 * Math.sin(lightAngle) * 0.3;
            drawSolarCommand(lightX - 2, lightY - 2, lightX + 2, lightY + 2, '#00ff00', 3);
        }

        // Rayo tractor
        if (Math.random() < 0.5) {
            drawSolarCommand(x, y + size * 0.5, x, y + size * 2, '#00ffff', 8);
        }
    }

    async function ufoLaserShot(startX, startY, targetX, targetY) {
        if (stopSignal) return;
        drawSolarCommand(startX, startY, targetX, targetY, '#ff0000', 3);
        await new Promise(r => setTimeout(r, 100));
    }


    /* ----------  FUNCIONES PRINCIPALES  ---------- */

function updatePlayerOptions() {
    // Guardar la selección actual antes de limpiar
    const currentSelection = playerSelect.value;

    // Clear existing options
    playerSelect.innerHTML = '';

    // Try multiple selectors for better compatibility
    const playerElements = document.querySelectorAll('.spawnedavatar[data-playerid], .playerlist-row[data-playerid]');
    const validPlayers = [];

    playerElements.forEach(el => {
        const playerId = el.dataset.playerid;

        // Skip if no player ID or if it's the current player
        if (!playerId || playerId === '0' || el.dataset.self === 'true') {
            return;
        }

        // Try different ways to get player name
        let playerName = '';

        // Method 1: Check for nickname in avatar
        const nicknameEl = el.querySelector('.nickname, .playerlist-name a, .player-name');
        if (nicknameEl) {
            playerName = nicknameEl.textContent.trim();
        }

        // Method 2: Check parent elements
        if (!playerName) {
            const parentRow = el.closest('.playerlist-row');
            if (parentRow) {
                const nameEl = parentRow.querySelector('.playerlist-name a, .player-name');
                if (nameEl) {
                    playerName = nameEl.textContent.trim();
                }
            }
        }

        // Method 3: Use player ID as fallback
        if (!playerName) {
            playerName = `Player ${playerId}`;
        }

        // Avoid duplicates
        if (!validPlayers.some(p => p.id === playerId)) {
            validPlayers.push({
                id: playerId,
                name: playerName
            });
        }
    });

    console.log('🎯 Players found:', validPlayers); // Debug log

    if (validPlayers.length === 0) {
        const opt = document.createElement('option');
        opt.value = '';
        opt.textContent = '❌ No players available';
        playerSelect.appendChild(opt);
        executeBtn.disabled = true;
    } else {
        // Poblar la lista con los jugadores válidos
        validPlayers.forEach(player => {
            const opt = document.createElement('option');
            opt.value = player.id;
            opt.textContent = `🎯 ${player.name}`;
            playerSelect.appendChild(opt);
        });

        // Intentar mantener la selección anterior
        const stillExists = validPlayers.some(p => p.id === currentSelection);

        if (currentSelection && stillExists) {
            // El jugador previamente seleccionado todavía existe, mantener selección
            playerSelect.value = currentSelection;
            console.log('🎯 Manteniendo selección:', currentSelection);
        } else if (currentSelection && !stillExists) {
            // El jugador previamente seleccionado ya no existe
            console.log('⚠️ El jugador seleccionado salió de la sala');
            // Mantener el primer jugador como selección por defecto
            playerSelect.selectedIndex = 0;
        }

        executeBtn.disabled = false;
    }
}


    async function executeSolarAction() {
        if (isExecuting) return;

        const playerId = playerSelect.value;
        const weaponType = weaponSelect.value;
        const effectType = effectSelect.value;
        const intensity = parseInt(intensitySlider.value);
        const shouldRepeat = repeatToggle.checked;

        if (!playerId) {
            alert('🚫 Por favor selecciona un objetivo válido');
            return;
        }

        if (!weaponType && !effectType) {
            alert('🚫 Por favor selecciona un arma o efecto');
            return;
        }

        isExecuting = true;
        stopSignal = false;
        executeBtn.disabled = true;
        stopBtn.disabled = false;

        do {
            try {
                if (weaponType) {
                    switch (weaponType) {
                        case 'weapon:meteor_rain':
                            await meteorRain(playerId, intensity);
                            break;
                        case 'weapon:giant_asteroid':
                            await giantAsteroid(playerId, intensity);
                            break;
                        case 'weapon:laser_beam':
                            await laserBeam(playerId, intensity);
                            break;
                        case 'weapon:plasma_beam': // Rayo Plasma (reordenado)
                            await plasmaBeam(playerId, intensity);
                            break;
                        case 'weapon:space_dragon':
                            await spaceDragon(playerId, intensity);
                            break;
                        case 'weapon:black_hole':
                            await blackHole(playerId, intensity);
                            break;
                        case 'weapon:ufo_invasion':
                            await ufoInvasion(playerId, intensity);
                            break;
                        // case 'weapon:supernova': // Eliminado
                        //     await supernova(playerId, intensity);
                        //     break;
                        case 'weapon:galactic_lightsaber':
                            await galacticLightsaber(playerId, intensity);
                            break;
                        case 'weapon:antimatter_missile':
                            await antimatterMissile(playerId, intensity);
                            break;
                        // case 'weapon:stellar_explosion': // Eliminado
                        //     await stellarExplosion(playerId, intensity);
                        //     break;
                        case 'weapon:gravity_vortex':
                            await gravityVortex(playerId, intensity);
                            break;
                    }
                }

                if (effectType) {
                    switch (effectType) {
                        case 'effect:planetary_shield':
                            await planetaryShield(playerId, intensity);
                            break;
                        case 'effect:solar_fireworks':
                            await solarFireworks(playerId, intensity);
                            break;
                        // case 'effect:solar_storm': // Eliminado
                        //     await solarStorm(playerId, intensity);
                        //     break;
                        case 'effect:instant_ice_age':
                            await instantIceAge(playerId, intensity);
                            break;
                        case 'effect:volcanic_eruption':
                            await volcanicEruption(playerId, intensity);
                            break;
                        // case 'effect:asteroid_field': // Eliminado
                        //     await asteroidField(playerId, intensity);
                        //     break;
                        case 'effect:space_anomaly':
                            await spaceAnomaly(playerId, intensity);
                            break;
                        case 'effect:laser_beam_v1_0': // Rayo Láser (v1.0) (reordenado)
                            await laserBeam_v1_0(playerId, intensity);
                            break;
                        case 'effect:black_hole_v1_0':
                            await blackHole_v1_0(playerId, intensity);
                            break;
                        case 'effect:ufo_invasion_v1_0':
                            await ufoInvasion_v1_0(playerId, intensity);
                            break;
                        case 'effect:gravity_vortex_v1_0':
                            await gravityVortex_v1_0(playerId, intensity);
                            break;
                    }
                }

                if (shouldRepeat && !stopSignal) {
                    await new Promise(r => setTimeout(r, 1000));
                }

            } catch (error) {
                console.error('🔥 Error ejecutando Solar Smash:', error);
                break;
            }
        } while (shouldRepeat && !stopSignal);

        isExecuting = false;
        executeBtn.disabled = false;
        stopBtn.disabled = true;
        console.log('🌌 Secuencia Solar Smash completada');
    }

    function stopExecution() {
        stopSignal = true;
        isExecuting = false;
        if (activeEffectInterval) {
            clearInterval(activeEffectInterval);
            activeEffectInterval = null;
        }
        executeBtn.disabled = false;
        stopBtn.disabled = true;
        console.log('🛑 Destrucción detenida por el usuario');
    }

    /* ----------  EVENT LISTENERS  ---------- */

    executeBtn.addEventListener('click', executeSolarAction);
    stopBtn.addEventListener('click', stopExecution);

    // Actualizar jugadores cada 2 segundos
    setInterval(updatePlayerOptions, 2000);
    updatePlayerOptions();

    // Hacer el contenedor arrastrable
    let isDragging = false;
    let dragOffsetX = 0;
    let dragOffsetY = 0;

    titleBar.addEventListener('mousedown', (e) => {
        isDragging = true;
        dragOffsetX = e.clientX - container.offsetLeft;
        dragOffsetY = e.clientY - container.offsetTop;
        titleBar.style.cursor = 'grabbing';
    });

    document.addEventListener('mousemove', (e) => {
        if (isDragging) {
            container.style.left = (e.clientX - dragOffsetX) + 'px';
            container.style.top = (e.clientY - dragOffsetY) + 'px';
            container.style.right = 'auto';
            container.style.bottom = 'auto';
        }
    });

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

    // Efectos hover para los controles
    [executeBtn, stopBtn, playerSelect, weaponSelect, effectSelect].forEach(element => {
        element.addEventListener('mouseenter', () => {
            element.style.transform = 'translateY(-2px)';
            element.style.boxShadow = element.style.boxShadow.replace(/rgba$$[^)]+$$/, 'rgba(0, 255, 255, 0.6)');
        });

        element.addEventListener('mouseleave', () => {
            element.style.transform = 'translateY(0)';
            element.style.boxShadow = element.style.boxShadow.replace(/rgba$$[^)]+$$/, element === executeBtn ? 'rgba(255, 107, 53, 0.4)' : 'rgba(255, 23, 68, 0.4)');
        });
    });

    console.log('🌌 THE SOLAR SMASH MOD cargado exitosamente! 🌌');
    console.log('🚀 Versión 1.3 - Actualizaciones de armas y efectos completadas');
    console.log('⚡ Cada arma ahora tiene su propio comportamiento distintivo');

})();