您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Simulates the impossible maneuvers of UFOs: instantaneous acceleration from subsonic to supersonic speeds!
// ==UserScript== // @name Drawaria OVNI Simulator Mod // @namespace http://tampermonkey.net/ // @version 1.0 // @description Simulates the impossible maneuvers of UFOs: instantaneous acceleration from subsonic to supersonic speeds! // @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'; /* ---------- MANIOBRAS OVNI DOCUMENTADAS ---------- */ const UFO_MANEUVERS = { 'Ninguno': '', '🛸 Tic Tac - Movimiento Errático': 'maneuver:tic_tac_erratic', // Caso USS Nimitz '⚡ Aceleración Instantánea': 'maneuver:instant_acceleration', // Subsónica a supersónica '🌀 Vuelo Parado Absoluto': 'maneuver:absolute_hover', // Sin propulsión visible '↩️ Curvas Imposibles': 'maneuver:impossible_turns', // Radios constantes indefinidos '🎯 Evasión Inteligente': 'maneuver:intelligent_evasion', // Acompañar y mantener distancia '📡 Manifestación Multi-Sensor': 'maneuver:multi_sensor_detection', // Radar + visual simultáneo '🔄 Giro GIMBAL': 'maneuver:gimbal_rotation', // 90 grados sin perder altitud '💨 Desaparición Súbita': 'maneuver:sudden_disappearance', // Velocidades superiores a 620 nudos '🌊 Patrón de Vuelo Oceánico': 'maneuver:oceanic_pattern', // Atracción a masas de agua '☢️ Monitoreo Nuclear': 'maneuver:nuclear_monitoring' // Apariciones en instalaciones nucleares }; const UFO_PHENOMENA = { 'Ninguno': '', '🌟 Encuentro Cercano Tipo I': 'phenomenon:close_encounter_1', // Observación a menos de 150m '👽 Encuentro Cercano Tipo II': 'phenomenon:close_encounter_2', // Efectos físicos en el entorno '🛸 Encuentro Cercano Tipo III': 'phenomenon:close_encounter_3', // Avistamiento de ocupantes '⚫ Fenómeno de Absorción Lumínica': 'phenomenon:light_absorption', // Horizonte de eventos visual '🌌 Distorsión Espacial Localizada': 'phenomenon:spatial_distortion', // Efectos gravitacionales '📊 Anomalía Multi-Espectral': 'phenomenon:multispectral_anomaly', // Detección en múltiples sensores '🔮 Manifestación Plasmática': 'phenomenon:plasma_manifestation', // Efectos electromagnéticos '🌪️ Vórtice Atmosférico Controlado': 'phenomenon:controlled_vortex', // Manipulación atmosférica '⭐ Formación en Triángulo': 'phenomenon:triangular_formation' // Caso Phoenix Lights }; /* ---------- 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, #0a0a0a, #1a1a2e, #2d1b69); color:#00ffff; padding:15px 20px; border-radius:15px; font-family: 'Courier New', 'Consolas', monospace; font-size:13px; display:flex; flex-direction:column; gap:12px; box-shadow: 0 8px 25px rgba(0,255,255,0.4), inset 0 1px 0 rgba(255,255,255,0.1); border: 2px solid #00ffff; min-width: 340px; backdrop-filter: blur(10px); cursor: default; `; const titleBar = document.createElement('div'); titleBar.innerHTML = '🛸 SIMULADOR FENÓMENOS OVNI 🛸'; titleBar.style.cssText = ` font-weight: bold; font-size: 16px; text-align: center; cursor: grab; background: linear-gradient(45deg, #00ffff, #00bfff, #87ceeb); -webkit-background-clip: text; -webkit-text-fill-color: transparent; text-shadow: 0 0 10px rgba(0, 255, 255, 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 ufoInputStyle = ` flex-grow: 1; padding: 8px 12px; border-radius: 8px; border: 2px solid #00ffff; background: rgba(0, 0, 20, 0.9); color: #00ffff; font-size: 13px; font-family: 'Courier New', monospace; transition: all 0.3s ease; appearance: none; cursor: pointer; `; function createUFORow(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: 100px;`; wrapper.appendChild(label); wrapper.appendChild(inputElement); parent.appendChild(wrapper); return { wrapper, label, inputElement }; } // Selector de jugadores const playerSelect = document.createElement('select'); playerSelect.style.cssText = ufoInputStyle; createUFORow(contentDiv, '🎯 Objetivo:', playerSelect); // Selector de maniobras const maneuverSelect = document.createElement('select'); maneuverSelect.style.cssText = ufoInputStyle; for (const name in UFO_MANEUVERS) { const opt = document.createElement('option'); opt.value = UFO_MANEUVERS[name]; opt.textContent = name; maneuverSelect.appendChild(opt); } maneuverSelect.value = UFO_MANEUVERS['Ninguno']; createUFORow(contentDiv, '🛸 Maniobra:', maneuverSelect); // Selector de fenómenos const phenomenonSelect = document.createElement('select'); phenomenonSelect.style.cssText = ufoInputStyle; for (const name in UFO_PHENOMENA) { const opt = document.createElement('option'); opt.value = UFO_PHENOMENA[name]; opt.textContent = name; phenomenonSelect.appendChild(opt); } phenomenonSelect.value = UFO_PHENOMENA['Ninguno']; createUFORow(contentDiv, '✨ Fenómeno:', phenomenonSelect); // Auto-reset de selectores maneuverSelect.addEventListener('change', () => { if (maneuverSelect.value !== '') { phenomenonSelect.value = UFO_PHENOMENA['Ninguno']; } }); phenomenonSelect.addEventListener('change', () => { if (phenomenonSelect.value !== '') { maneuverSelect.value = UFO_MANEUVERS['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%, #0080ff 100%); outline: none; `; createUFORow(contentDiv, '⚡ Intensidad:', intensitySlider); // Repeat toggle const repeatToggle = document.createElement('input'); repeatToggle.type = 'checkbox'; repeatToggle.id = 'ufoRepeatToggle'; repeatToggle.style.cssText = `margin-right: 8px; cursor: pointer; transform: scale(1.3);`; const repeatLabel = document.createElement('label'); repeatLabel.htmlFor = 'ufoRepeatToggle'; repeatLabel.textContent = ' 🔄 Repetir Fenómeno'; 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 = '🛸 INICIAR SIMULACIÓN OVNI'; executeBtn.disabled = true; executeBtn.style.cssText = ` padding: 12px 20px; border-radius: 10px; border: none; background: linear-gradient(145deg, #0080ff, #00bfff); color: white; font-weight: bold; font-size: 15px; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 15px rgba(0, 128, 255, 0.4); text-transform: uppercase; letter-spacing: 1px; `; stopBtn = document.createElement('button'); stopBtn.textContent = '🛑 DETENER FENÓMENO'; 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 drawUFOCommand(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 }; } /* ---------- MANIOBRAS OVNI DOCUMENTADAS ---------- */ // 🛸 Tic Tac - Movimiento Errático (Caso USS Nimitz) async function ticTacErratic(playerId, intensity = 3) { if (stopSignal) return; console.log(`🛸 Simulando comportamiento Tic Tac`); const target = getPlayerCoords(playerId); if (!target) return; let currentX = target.x - 100; let currentY = target.y - 50; const movementSteps = 40 + intensity * 10; // Patrón errático: "izquierda, derecha, adelante, atrás, al azar" const directions = ['left', 'right', 'forward', 'backward', 'random']; for (let step = 0; step < movementSteps; step++) { if (stopSignal) break; // Seleccionar movimiento según patrón Tic Tac const direction = directions[step % directions.length]; let nextX = currentX; let nextY = currentY; switch (direction) { case 'left': nextX = currentX - (30 + Math.random() * 40); break; case 'right': nextX = currentX + (30 + Math.random() * 40); break; case 'forward': nextY = currentY - (20 + Math.random() * 30); break; case 'backward': nextY = currentY + (20 + Math.random() * 30); break; case 'random': nextX = currentX + (Math.random() - 0.5) * 80; nextY = currentY + (Math.random() - 0.5) * 60; break; } // Dibujar cuerpo del OVNI const ufoSize = 12 + intensity * 2; for (let segment = 0; segment < 8; segment++) { const angle = (segment / 8) * Math.PI * 2; const segmentX = nextX + ufoSize * Math.cos(angle); const segmentY = nextY + ufoSize * Math.sin(angle) * 0.3; drawUFOCommand(nextX, nextY, segmentX, segmentY, '#c0c0c0', 4); } // Cúpula for (let dome = 0; dome < 6; dome++) { const domeAngle = (dome / 6) * Math.PI * 2; const domeX = nextX + (ufoSize * 0.6) * Math.cos(domeAngle); const domeY = nextY - 8 + (ufoSize * 0.6) * Math.sin(domeAngle) * 0.4; drawUFOCommand(nextX, nextY - 8, domeX, domeY, '#87ceeb', 2); } // Estela de movimiento drawUFOCommand(currentX, currentY, nextX, nextY, '#00ffff', 2); // Luces parpadeantes if (Math.random() < 0.6) { const lightColors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00']; const lightColor = lightColors[Math.floor(Math.random() * lightColors.length)]; drawUFOCommand(nextX - 5, nextY, nextX + 5, nextY, lightColor, 3); } currentX = nextX; currentY = nextY; await new Promise(r => setTimeout(r, 150 + Math.random() * 100)); } } // ⚡ Aceleración Instantánea (Subsónica a Supersónica) async function instantAcceleration(playerId, intensity = 3) { if (stopSignal) return; console.log(`⚡ Simulando aceleración instantánea`); const target = getPlayerCoords(playerId); if (!target) return; const startX = target.x - 200; const startY = target.y; const endX = target.x + 200; const endY = target.y; // Fase 1: Vuelo parado (subsónico) for (let hover = 0; hover < 8; hover++) { if (stopSignal) break; const ufoSize = 15 + intensity * 3; // OVNI estático for (let segment = 0; segment < 12; segment++) { const angle = (segment / 12) * Math.PI * 2; const segmentX = startX + ufoSize * Math.cos(angle); const segmentY = startY + ufoSize * Math.sin(angle) * 0.4; drawUFOCommand(startX, startY, segmentX, segmentY, '#c0c0c0', 5); } // Efecto de suspensión for (let field = 0; field < 4; field++) { const fieldAngle = (field / 4) * Math.PI * 2 + hover * 0.3; const fieldX = startX + (ufoSize + 10) * Math.cos(fieldAngle); const fieldY = startY + (ufoSize + 10) * Math.sin(fieldAngle) * 0.3; drawUFOCommand(startX, startY, fieldX, fieldY, '#00ffff', 1); } await new Promise(r => setTimeout(r, 200)); } // Fase 2: Aceleración instantánea (supersónica) const accelerationSteps = 3; // Muy pocas fases para mostrar instantaneidad for (let step = 0; step < accelerationSteps; step++) { if (stopSignal) break; const progress = step / accelerationSteps; const currentX = startX + (endX - startX) * Math.pow(progress, 0.3); // Aceleración exponencial // Estela supersónica const trailLength = 80 + step * 40; for (let trail = 0; trail < 8; trail++) { const trailX = currentX - trailLength - trail * 15; drawUFOCommand(currentX, startY, trailX, startY, '#ff4500', 6 - trail); } // Onda de choque if (step > 0) { for (let shock = 0; shock < 6; shock++) { const shockAngle = (shock / 6) * Math.PI * 2; const shockRadius = 30 + step * 20; const shockX = currentX + shockRadius * Math.cos(shockAngle); const shockY = startY + shockRadius * Math.sin(shockAngle) * 0.6; drawUFOCommand(currentX, startY, shockX, shockY, '#ffffff', 4); } } await new Promise(r => setTimeout(r, 100)); } } // 🌀 Vuelo Parado Absoluto async function absoluteHover(playerId, intensity = 3) { if (stopSignal) return; console.log(`🌀 Simulando vuelo parado absoluto`); const target = getPlayerCoords(playerId); if (!target) return; const hoverX = target.x; const hoverY = target.y - 60; const duration = 100 + intensity * 50; for (let frame = 0; frame < duration; frame++) { if (stopSignal) break; const ufoSize = 18 + intensity * 2; // Cuerpo del OVNI perfectamente estático for (let segment = 0; segment < 16; segment++) { const angle = (segment / 16) * Math.PI * 2; const segmentX = hoverX + ufoSize * Math.cos(angle); const segmentY = hoverY + ufoSize * Math.sin(angle) * 0.3; drawUFOCommand(hoverX, hoverY, segmentX, segmentY, '#c0c0c0', 6); } // Campo anti-gravitatorio const fieldIntensity = Math.sin(frame * 0.1) * 5 + 15; for (let field = 0; field < 8; field++) { const fieldAngle = (field / 8) * Math.PI * 2; const fieldX = hoverX + fieldIntensity * Math.cos(fieldAngle); const fieldY = hoverY + fieldIntensity * Math.sin(fieldAngle); drawUFOCommand(hoverX, hoverY, fieldX, fieldY, '#9400d3', 2); } // Partículas de suspensión if (frame % 5 === 0) { for (let particle = 0; particle < 4; particle++) { const particleX = hoverX + (Math.random() - 0.5) * 40; const particleY = hoverY + 20 + Math.random() * 20; drawUFOCommand(hoverX, hoverY + ufoSize, particleX, particleY, '#00ffff', 1); } } await new Promise(r => setTimeout(r, 80)); } } // ↩️ Curvas Imposibles async function impossibleTurns(playerId, intensity = 3) { if (stopSignal) return; console.log(`↩️ Simulando curvas imposibles`); const target = getPlayerCoords(playerId); if (!target) return; const centerX = target.x; const centerY = target.y; const radius = 60 + intensity * 15; // Realizar múltiples curvas con radios constantes pero imposibles const totalRotations = 2 + intensity; const stepsPerRotation = 24; for (let rotation = 0; rotation < totalRotations; rotation++) { for (let step = 0; step < stepsPerRotation; step++) { if (stopSignal) break; const angle = (step / stepsPerRotation) * Math.PI * 2; const currentX = centerX + radius * Math.cos(angle); const currentY = centerY + radius * Math.sin(angle); // OVNI en la curva const ufoSize = 14 + intensity * 2; for (let segment = 0; segment < 10; segment++) { const segmentAngle = (segment / 10) * Math.PI * 2 + angle; const segmentX = currentX + (ufoSize * 0.8) * Math.cos(segmentAngle); const segmentY = currentY + (ufoSize * 0.8) * Math.sin(segmentAngle) * 0.4; drawUFOCommand(currentX, currentY, segmentX, segmentY, '#c0c0c0', 4); } // Mostrar trayectoria circular perfecta const nextAngle = ((step + 1) / stepsPerRotation) * Math.PI * 2; const nextX = centerX + radius * Math.cos(nextAngle); const nextY = centerY + radius * Math.sin(nextAngle); drawUFOCommand(currentX, currentY, nextX, nextY, '#00ff00', 3); // Efectos de fuerza G imposible (debería ser letal para humanos) if (step % 4 === 0) { for (let gforce = 0; gforce < 3; gforce++) { const gAngle = angle + Math.PI / 2 + gforce * 0.5; const gX = currentX + 25 * Math.cos(gAngle); const gY = currentY + 25 * Math.sin(gAngle); drawUFOCommand(currentX, currentY, gX, gY, '#ff0000', 2); } } await new Promise(r => setTimeout(r, 120)); } } } // 🎯 Evasión Inteligente async function intelligentEvasion(playerId, intensity = 3) { if (stopSignal) return; console.log(`🎯 Simulando evasión inteligente`); const target = getPlayerCoords(playerId); if (!target) return; let ufoX = target.x - 80; let ufoY = target.y - 60; const pursuitSteps = 30 + intensity * 10; // Simular persecución de interceptores for (let step = 0; step < pursuitSteps; step++) { if (stopSignal) break; // OVNI mantiene distancia exacta del "observador" const targetDistance = 100 + intensity * 20; const currentDistance = Math.sqrt(Math.pow(ufoX - target.x, 2) + Math.pow(ufoY - target.y, 2)); if (currentDistance < targetDistance) { // Alejarse si está muy cerca const escapeAngle = Math.atan2(ufoY - target.y, ufoX - target.x); ufoX += 25 * Math.cos(escapeAngle); ufoY += 25 * Math.sin(escapeAngle); } else if (currentDistance > targetDistance + 50) { // Acercarse si está muy lejos const approachAngle = Math.atan2(target.y - ufoY, target.x - ufoX); ufoX += 15 * Math.cos(approachAngle); ufoY += 15 * Math.sin(approachAngle); } else { // Mantener distancia con movimiento lateral const tangentAngle = Math.atan2(target.y - ufoY, target.x - ufoX) + Math.PI / 2; ufoX += 20 * Math.cos(tangentAngle + step * 0.2); ufoY += 20 * Math.sin(tangentAngle + step * 0.2); } // Dibujar OVNI const ufoSize = 16 + intensity * 2; for (let segment = 0; segment < 12; segment++) { const angle = (segment / 12) * Math.PI * 2; const segmentX = ufoX + ufoSize * Math.cos(angle); const segmentY = ufoY + ufoSize * Math.sin(angle) * 0.35; drawUFOCommand(ufoX, ufoY, segmentX, segmentY, '#c0c0c0', 5); } // Línea de "observación" al objetivo drawUFOCommand(ufoX, ufoY, target.x, target.y, '#ff00ff', 1); // Simular interceptores persiguiendo if (step % 8 === 0) { const interceptorX = target.x + Math.random() * 100 - 50; const interceptorY = target.y + Math.random() * 100 - 50; // Interceptor "convencional" drawUFOCommand(interceptorX - 10, interceptorY, interceptorX + 10, interceptorY, '#ff0000', 3); drawUFOCommand(interceptorX, interceptorY - 5, interceptorX, interceptorY + 5, '#ff0000', 3); // Línea de persecución (siempre un paso atrás) drawUFOCommand(interceptorX, interceptorY, ufoX, ufoY, '#ff4444', 1); } await new Promise(r => setTimeout(r, 180)); } } // 📡 Manifestación Multi-Sensor async function multiSensorDetection(playerId, intensity = 3) { if (stopSignal) return; console.log(`📡 Simulando detección multi-sensor`); const target = getPlayerCoords(playerId); if (!target) return; const duration = 80 + intensity * 30; // Simular diferentes "sensores" o rayos de detección const sensors = ['radar', 'infrared', 'visual']; for (let frame = 0; frame < duration; frame++) { if (stopSignal) break; sensors.forEach((sensorType, index) => { const angle = (index / sensors.length) * Math.PI * 2 + frame * 0.1; const sensorX = target.x + (60 + intensity * 10) * Math.cos(angle); const sensorY = target.y + (60 + intensity * 10) * Math.sin(angle); let color; switch(sensorType) { case 'radar': color = '#00ff00'; break; // Green for radar case 'infrared': color = '#ff4500'; break; // Orange-red for IR case 'visual': color = '#00ffff'; break; // Cyan for visual (lights) } // Línea de detección drawUFOCommand(target.x, target.y, sensorX, sensorY, color, 2); // Indicador de sensor (punto o pulso) for (let i = 0; i < 3; i++) { const pulseRadius = 5 + Math.sin(frame * 0.2 + index * 0.5) * 3; drawUFOCommand(sensorX - pulseRadius, sensorY, sensorX + pulseRadius, sensorY, color, 3); } }); // OVNI central (observando) const ufoSize = 15 + intensity * 2; for (let segment = 0; segment < 8; segment++) { const angle = (segment / 8) * Math.PI * 2; const segmentX = target.x + ufoSize * Math.cos(angle); const segmentY = target.y + ufoSize * Math.sin(angle) * 0.3; drawUFOCommand(target.x, target.y, segmentX, segmentY, '#c0c0c0', 5); } await new Promise(r => setTimeout(r, 150)); } } // 🔄 Giro GIMBAL async function gimbalRotation(playerId, intensity = 3) { if (stopSignal) return; console.log(`🔄 Simulando giro GIMBAL`); const target = getPlayerCoords(playerId); if (!target) return; const rotations = 2 + intensity; // Number of 90-degree turns const stepsPerRotation = 36; // Smoothness of rotation let currentAngle = 0; // Initial "orientation" const ufoX = target.x - 50; const ufoY = target.y - 50; for (let rotation = 0; rotation < rotations; rotation++) { for (let step = 0; step < stepsPerRotation; step++) { if (stopSignal) break; // Calculate the target angle (e.g., a 90-degree turn) const targetAngle = (rotation + 1) * (Math.PI / 2); // 0.5PI, 1PI, 1.5PI, 2PI... // Interpolate angle for smooth rotation currentAngle = currentAngle + ((targetAngle - currentAngle) / (stepsPerRotation - step)); // Draw the UFO as a "gimbal" object (e.g., a rectangle rotating) const ufoWidth = 30 + intensity * 5; const ufoHeight = 10 + intensity * 2; const cosA = Math.cos(currentAngle); const sinA = Math.sin(currentAngle); // Simulate "arms" or structure that remains level const armLength = 40; drawUFOCommand(ufoX, ufoY, ufoX + armLength * cosA, ufoY + armLength * sinA, '#d3d3d3', 4); drawUFOCommand(ufoX, ufoY, ufoX - armLength * cosA, ufoY - armLength * sinA, '#d3d3d3', 4); // Simulate the "body" that rotates independently (e.g., a square) const bodySize = 15 + intensity * 3; drawUFOCommand(ufoX - bodySize, ufoY - bodySize, ufoX + bodySize, ufoY - bodySize, '#ff00ff', 2); drawUFOCommand(ufoX + bodySize, ufoY - bodySize, ufoX + bodySize, ufoY + bodySize, '#ff00ff', 2); drawUFOCommand(ufoX + bodySize, ufoY + bodySize, ufoX - bodySize, ufoY + bodySize, '#ff00ff', 2); drawUFOCommand(ufoX - bodySize, ufoY + bodySize, ufoX - bodySize, ufoY - bodySize, '#ff00ff', 2); // Indicate the "level" axis (e.g., a horizontal line that stays horizontal) drawUFOCommand(ufoX - 20, ufoY, ufoX + 20, ufoY, '#00ffff', 2); await new Promise(r => setTimeout(r, 100)); } } } // 💨 Desaparición Súbita async function suddenDisappearance(playerId, intensity = 3) { if (stopSignal) return; console.log(`💨 Simulando desaparición súbita`); const target = getPlayerCoords(playerId); if (!target) return; const ufoX = target.x + 80; const ufoY = target.y - 40; const durationVisible = 30; // Frames visible const durationFade = 10; // Frames to disappear // Fase 1: OVNI visible for (let frame = 0; frame < durationVisible; frame++) { if (stopSignal) break; const ufoSize = 20 + intensity * 3; // Draw a solid UFO for (let segment = 0; segment < 12; segment++) { const angle = (segment / 12) * Math.PI * 2; const segmentX = ufoX + ufoSize * Math.cos(angle); const segmentY = ufoY + ufoSize * Math.sin(angle) * 0.4; drawUFOCommand(ufoX, ufoY, segmentX, segmentY, '#a9a9a9', 6); } // Add a light pulse drawUFOCommand(ufoX - 10, ufoY + 5, ufoX + 10, ufoY + 5, '#ffff00', 4); await new Promise(r => setTimeout(r, 150)); } // Fase 2: Desaparición instantánea con efectos de rastro for (let fade = 0; fade < durationFade; fade++) { if (stopSignal) break; // Simulate rapidly dissipating energy/plasma const trailLength = (durationFade - fade) * (20 + intensity * 5); const trailAlpha = (durationFade - fade) / durationFade; // Fade out effect // Draw a streaking line that fades drawUFOCommand(ufoX, ufoY, ufoX + trailLength, ufoY - trailLength, `rgba(135,206,250,${trailAlpha})`, 5); // Light blue streaking drawUFOCommand(ufoX, ufoY, ufoX - trailLength, ufoY + trailLength, `rgba(255,165,0,${trailAlpha})`, 5); // Orange streaking // Small "burst" or "implosion" at origin point for (let i = 0; i < 5; i++) { const burstRadius = (fade * 5) + (Math.random() * 10); drawUFOCommand(ufoX, ufoY, ufoX + burstRadius * (Math.random() - 0.5), ufoY + burstRadius * (Math.random() - 0.5), `rgba(255,255,255,${1 - fade/durationFade})`, 2); } await new Promise(r => setTimeout(r, 80)); } // Ensure it's completely gone after fading // No drawing command here means the canvas clears previous drawings implicitly } // 🌊 Patrón de Vuelo Oceánico async function oceanicPattern(playerId, intensity = 3) { if (stopSignal) return; console.log(`🌊 Simulando patrón de vuelo oceánico`); const target = getPlayerCoords(playerId); if (!target) return; const duration = 80 + intensity * 30; const amplitude = 40 + intensity * 10; // Vertical movement const wavelength = 0.1; // Horizontal speed for (let frame = 0; frame < duration; frame++) { if (stopSignal) break; const currentX = target.x + Math.sin(frame * wavelength) * amplitude * 0.5; const currentY = target.y + Math.cos(frame * wavelength) * amplitude; // Vertical oscillation const ufoSize = 15 + intensity * 2; // Basic UFO drawing for (let segment = 0; segment < 8; segment++) { const angle = (segment / 8) * Math.PI * 2; const segmentX = currentX + ufoSize * Math.cos(angle); const segmentY = currentY + ufoSize * Math.sin(angle) * 0.4; drawUFOCommand(currentX, currentY, segmentX, segmentY, '#add8e6', 5); // Light blue for oceanic theme } // Water ripples below for (let ripple = 0; ripple < 3; ripple++) { const rippleRadius = (frame % 20) + ripple * 10; // Expanding ripple const rippleAlpha = 1 - (rippleRadius / (20 + 2 * 10 + 20)); // Fade out drawUFOCommand(currentX - rippleRadius, currentY + ufoSize + 10, currentX + rippleRadius, currentY + ufoSize + 10, `rgba(0,191,255,${Math.max(0, rippleAlpha)})`, 2); } await new Promise(r => setTimeout(r, 120)); } } // ☢️ Monitoreo Nuclear async function nuclearMonitoring(playerId, intensity = 3) { if (stopSignal) return; console.log(`☢️ Simulando monitoreo nuclear`); const target = getPlayerCoords(playerId); if (!target) return; const duration = 90 + intensity * 40; const scanRadius = 50 + intensity * 15; for (let frame = 0; frame < duration; frame++) { if (stopSignal) break; const ufoX = target.x + Math.sin(frame * 0.05) * 80; const ufoY = target.y - 70 + Math.cos(frame * 0.07) * 40; const ufoSize = 18 + intensity * 2; // UFO body for (let segment = 0; segment < 10; segment++) { const angle = (segment / 10) * Math.PI * 2; const segmentX = ufoX + ufoSize * Math.cos(angle); const segmentY = ufoY + ufoSize * Math.sin(angle) * 0.3; drawUFOCommand(ufoX, ufoY, segmentX, segmentY, '#c0c0c0', 6); } // Scanning beam const beamColor = `rgba(255,255,0,${0.5 + Math.sin(frame * 0.3) * 0.4})`; for (let beam = 0; beam < 5; beam++) { drawUFOCommand(ufoX, ufoY + ufoSize / 2, ufoX + (Math.random() - 0.5) * scanRadius * 2, target.y + target.height / 2 + Math.random() * scanRadius, beamColor, 1 + Math.random() * 2); } // Radiation symbols (simplified, flickering) if (frame % 15 === 0) { // Draw a stylized radiation symbol (3 arcs + central circle) const radSymbolSize = 15 + intensity * 2; const radColor = '#ff0000'; // Red for danger drawUFOCommand(target.x - radSymbolSize, target.y, target.x + radSymbolSize, target.y, radColor, 2); drawUFOCommand(target.x, target.y - radSymbolSize, target.x, target.y + radSymbolSize, radColor, 2); drawUFOCommand(target.x - radSymbolSize * 0.7, target.y - radSymbolSize * 0.7, target.x + radSymbolSize * 0.7, target.y + radSymbolSize * 0.7, radColor, 2); } await new Promise(r => setTimeout(r, 100)); } } /* ---------- FENÓMENOS OVNI DOCUMENTADOS ---------- */ // 🌟 Encuentro Cercano Tipo I async function closeEncounter1(playerId, intensity = 3) { if (stopSignal) return; console.log(`🌟 Simulando Encuentro Cercano Tipo I`); const target = getPlayerCoords(playerId); if (!target) return; // Observación a menos de 150m sin efectos físicos const observationDistance = 150 - intensity * 20; const duration = 60 + intensity * 30; const ufoX = target.x + (Math.random() - 0.5) * 100; // Slightly randomized start const ufoY = target.y - (100 + Math.random() * 50); for (let frame = 0; frame < duration; frame++) { if (stopSignal) break; const ufoSize = 18 + intensity * 2; // Simple disc-shaped UFO for (let segment = 0; segment < 12; segment++) { const angle = (segment / 12) * Math.PI * 2; const segmentX = ufoX + ufoSize * Math.cos(angle); const segmentY = ufoY + ufoSize * Math.sin(angle) * 0.3; drawUFOCommand(ufoX, ufoY, segmentX, segmentY, '#d3d3d3', 5); } // Add subtle lights if (frame % 10 < 5) { // Flickering effect drawUFOCommand(ufoX - 8, ufoY + 5, ufoX + 8, ufoY + 5, '#00ffff', 2); } await new Promise(r => setTimeout(r, 120)); } } // 👽 Encuentro Cercano Tipo II async function closeEncounter2(playerId, intensity = 3) { if (stopSignal) return; console.log(`👽 Simulando Encuentro Cercano Tipo II (Efectos físicos)`); const target = getPlayerCoords(playerId); if (!target) return; const encounterX = target.x + 50; const encounterY = target.y - 100; const duration = 100 + intensity * 40; for (let frame = 0; frame < duration; frame++) { if (stopSignal) break; const ufoSize = 20 + intensity * 3; // Solid UFO body for (let segment = 0; segment < 16; segment++) { const angle = (segment / 16) * Math.PI * 2; const segmentX = encounterX + ufoSize * Math.cos(angle); const segmentY = encounterY + ufoSize * Math.sin(angle) * 0.4; drawUFOCommand(encounterX, encounterY, segmentX, segmentY, '#d3d3d3', 6); } // Physical effects (e.g., ground disturbance, electromagnetic interference) if (frame % 8 === 0) { // Ground disturbance for (let i = 0; i < 5; i++) { const randOffset = (Math.random() - 0.5) * 50; drawUFOCommand(target.x + randOffset, target.y + target.height / 2, target.x + randOffset + 10, target.y + target.height / 2 + 10, '#8b4513', 2); // Brown lines for disturbed ground } // Electromagnetic pulse (visualized as expanding rings) const empRadius = (frame % 30) * (2 + intensity * 0.5); const empAlpha = 1 - (empRadius / (30 * (2 + intensity * 0.5))); drawUFOCommand(target.x, target.y, target.x + empRadius, target.y + empRadius, `rgba(0,255,255,${empAlpha})`, 2); // Cyan rings drawUFOCommand(target.x, target.y, target.x - empRadius, target.y - empRadius, `rgba(0,255,255,${empAlpha})`, 2); } await new Promise(r => setTimeout(r, 100)); } } // 🛸 Encuentro Cercano Tipo III async function closeEncounter3(playerId, intensity = 3) { if (stopSignal) return; console.log(`🛸 Simulando Encuentro Cercano Tipo III (Avistamiento de ocupantes)`); const target = getPlayerCoords(playerId); if (!target) return; const ufoX = target.x - 100; const ufoY = target.y - 80; const duration = 80 + intensity * 30; for (let frame = 0; frame < duration; frame++) { if (stopSignal) break; const ufoSize = 25 + intensity * 4; // Large, prominent UFO for (let segment = 0; segment < 20; segment++) { const angle = (segment / 20) * Math.PI * 2; const segmentX = ufoX + ufoSize * Math.cos(angle); const segmentY = ufoY + ufoSize * Math.sin(angle) * 0.3; drawUFOCommand(ufoX, ufoY, segmentX, segmentY, '#808080', 7); } // Beam descending from UFO (for occupants) const beamHeight = 40 + Math.sin(frame * 0.1) * 10; const beamWidth = 10 + intensity * 2; drawUFOCommand(ufoX - beamWidth / 2, ufoY + ufoSize / 2, ufoX - beamWidth / 2, ufoY + ufoSize / 2 + beamHeight, '#ffffcc', 3); drawUFOCommand(ufoX + beamWidth / 2, ufoY + ufoSize / 2, ufoX + beamWidth / 2, ufoY + ufoSize / 2 + beamHeight, '#ffffcc', 3); drawUFOCommand(ufoX - beamWidth / 2, ufoY + ufoSize / 2 + beamHeight, ufoX + beamWidth / 2, ufoY + ufoSize / 2 + beamHeight, '#ffffcc', 3); // Occupant silhouette (very simplified) if (frame % 20 < 10) { // Flickering drawUFOCommand(ufoX, ufoY + ufoSize / 2 + beamHeight + 5, ufoX, ufoY + ufoSize / 2 + beamHeight + 25, '#000000', 5); // Body drawUFOCommand(ufoX, ufoY + ufoSize / 2 + beamHeight, ufoX, ufoY + ufoSize / 2 + beamHeight + 5, '#000000', 8); // Head } await new Promise(r => setTimeout(r, 150)); } } // ⚫ Fenómeno de Absorción Lumínica async function lightAbsorption(playerId, intensity = 3) { if (stopSignal) return; console.log(`⚫ Simulando absorción lumínica`); const target = getPlayerCoords(playerId); if (!target) return; const duration = 100 + intensity * 40; const absorptionCenterX = target.x; const absorptionCenterY = target.y - 30; for (let frame = 0; frame < duration; frame++) { if (stopSignal) break; const maxAbsorbRadius = 60 + intensity * 20; const currentAbsorbRadius = (frame / duration) * maxAbsorbRadius; const alpha = 1 - (frame / duration); // Fades out as it "absorbs" // Darkening/absorbing core for (let i = 0; i < 10; i++) { const angle = (i / 10) * Math.PI * 2 + frame * 0.1; const innerRadius = currentAbsorbRadius * 0.5; const outerRadius = currentAbsorbRadius; drawUFOCommand( absorptionCenterX + innerRadius * Math.cos(angle), absorptionCenterY + innerRadius * Math.sin(angle), absorptionCenterX + outerRadius * Math.cos(angle + 0.5), // Offset for a swirl absorptionCenterY + outerRadius * Math.sin(angle + 0.5), `rgba(0,0,0,${alpha * 0.8})`, // Black, fading 5 ); } // "Light particles" being drawn in if (frame % 5 === 0) { for (let j = 0; j < 5; j++) { const particleX = absorptionCenterX + (Math.random() - 0.5) * maxAbsorbRadius; const particleY = absorptionCenterY + (Math.random() - 0.5) * maxAbsorbRadius; drawUFOCommand(particleX, particleY, absorptionCenterX, absorptionCenterY, `rgba(255,255,255,${alpha})`, 1); } } await new Promise(r => setTimeout(r, 100)); } } // 🌌 Distorsión Espacial Localizada async function spatialDistortion(playerId, intensity = 3) { if (stopSignal) return; console.log(`🌌 Simulando distorsión espacial localizada`); const target = getPlayerCoords(playerId); if (!target) return; const duration = 90 + intensity * 40; const distortionRadius = 50 + intensity * 20; for (let frame = 0; frame < duration; frame++) { if (stopSignal) break; const centerX = target.x + (Math.sin(frame * 0.08) * 30); const centerY = target.y + (Math.cos(frame * 0.06) * 20); // Distorting lines for (let i = 0; i < 10; i++) { const startAngle = (i / 10) * Math.PI * 2; const endAngle = startAngle + Math.sin(frame * 0.1 + i) * 0.5; // Warping effect const startX = centerX + distortionRadius * Math.cos(startAngle); const startY = centerY + distortionRadius * Math.sin(startAngle); const endX = centerX + distortionRadius * 1.2 * Math.cos(endAngle); const endY = centerY + distortionRadius * 1.2 * Math.sin(endAngle); drawUFOCommand(startX, startY, endX, endY, '#8a2be2', 1); // Blue-violet for space distortion } // Central anomaly const anomalySize = 10 + Math.sin(frame * 0.2) * 5; for (let j = 0; j < 6; j++) { const angle = (j / 6) * Math.PI * 2; drawUFOCommand(centerX, centerY, centerX + anomalySize * Math.cos(angle), centerY + anomalySize * Math.sin(angle), '#ffffff', 3); } await new Promise(r => setTimeout(r, 100)); } } // 📊 Anomalía Multi-Espectral async function multispectralAnomaly(playerId, intensity = 3) { if (stopSignal) return; console.log(`📊 Simulando anomalía multi-espectral`); const target = getPlayerCoords(playerId); if (!target) return; const anomalyX = target.x + 30; const anomalyY = target.y - 50; const duration = 100 + intensity * 40; const colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff']; // RGB, CMY for (let frame = 0; frame < duration; frame++) { if (stopSignal) break; const pulseSize = 20 + Math.sin(frame * 0.1) * 10; const pulseColor = colors[Math.floor((frame / 5) % colors.length)]; // Central anomaly pulse for (let i = 0; i < 8; i++) { const angle = (i / 8) * Math.PI * 2; const rayX = anomalyX + pulseSize * Math.cos(angle); const rayY = anomalyY + pulseSize * Math.sin(angle); drawUFOCommand(anomalyX, anomalyY, rayX, rayY, pulseColor, 4); } // Fading rings for different spectrums for (let layer = 0; layer < 3; layer++) { const ringRadius = (frame % 40) + layer * 15; const ringAlpha = 1 - (ringRadius / (40 + 2 * 15)); const ringColor = colors[(layer + frame) % colors.length]; // Draw a circle segment for simplicity for (let segment = 0; segment < 12; segment++) { const startAngle = (segment / 12) * Math.PI * 2; const endAngle = ((segment + 1) / 12) * Math.PI * 2; drawUFOCommand(anomalyX + ringRadius * Math.cos(startAngle), anomalyY + ringRadius * Math.sin(startAngle), anomalyX + ringRadius * Math.cos(endAngle), anomalyY + ringRadius * Math.sin(endAngle), `rgba(${parseInt(ringColor.substring(1,3),16)},${parseInt(ringColor.substring(3,5),16)},${parseInt(ringColor.substring(5,7),16)},${Math.max(0, ringAlpha)})`, 2); } } await new Promise(r => setTimeout(r, 80)); } } // 🔮 Manifestación Plasmática async function plasmaManifestation(playerId, intensity = 3) { if (stopSignal) return; console.log(`🔮 Simulando manifestación plasmática`); const target = getPlayerCoords(playerId); if (!target) return; const centerX = target.x; const centerY = target.y - 60; const duration = 100 + intensity * 40; for (let frame = 0; frame < duration; frame++) { if (stopSignal) break; const plasmaRadius = 30 + Math.sin(frame * 0.1) * 15; const plasmaColor = `hsl(${frame * 5 % 360}, 100%, 50%)`; // Hue changes over time // Plasma core for (let i = 0; i < 15; i++) { const angle = (i / 15) * Math.PI * 2 + Math.random() * 0.5; const dist = plasmaRadius * Math.random(); drawUFOCommand(centerX, centerY, centerX + dist * Math.cos(angle), centerY + dist * Math.sin(angle), plasmaColor, 2); } // Flickering arcs if (frame % 5 === 0) { for (let j = 0; j < 5; j++) { const arcAngle = (Math.random() * Math.PI * 2); const arcX = centerX + (plasmaRadius + 10) * Math.cos(arcAngle); const arcY = centerY + (plasmaRadius + 10) * Math.sin(arcAngle); drawUFOCommand(centerX, centerY, arcX, arcY, '#ffd700', 1); // Gold sparks } } await new Promise(r => setTimeout(r, 70)); } } // 🌪️ Vórtice Atmosférico Controlado async function controlledVortex(playerId, intensity = 3) { if (stopSignal) return; console.log(`🌪️ Simulando vórtice atmosférico controlado`); const target = getPlayerCoords(playerId); if (!target) return; const vortexX = target.x; const vortexY = target.y - 50; const duration = 120 + intensity * 50; const maxRadius = 80 + intensity * 20; for (let frame = 0; frame < duration; frame++) { if (stopSignal) break; // Spiral lines forming the vortex for (let i = 0; i < 10; i++) { const angleOffset = i * 0.5; const radiusGrowth = frame * 0.8; const currentAngle = (frame * 0.2) + angleOffset; const currentRadius = Math.min(radiusGrowth, maxRadius); const startX = vortexX + (currentRadius - 10) * Math.cos(currentAngle - 0.1); const startY = vortexY + (currentRadius - 10) * Math.sin(currentAngle - 0.1); const endX = vortexX + currentRadius * Math.cos(currentAngle); const endY = vortexY + currentRadius * Math.sin(currentAngle); drawUFOCommand(startX, startY, endX, endY, '#808080', 2); // Grey for cloud/vortex } // Central eye effect const eyeSize = 5 + Math.sin(frame * 0.1) * 3; for (let j = 0; j < 4; j++) { const angle = (j / 4) * Math.PI * 2; drawUFOCommand(vortexX, vortexY, vortexX + eyeSize * Math.cos(angle), vortexY + eyeSize * Math.sin(angle), '#ffffff', 3); } await new Promise(r => setTimeout(r, 90)); } } /* ---------- FUNCIONES PRINCIPALES ---------- */ function updatePlayerOptions() { const currentSelection = playerSelect.value; playerSelect.innerHTML = ''; const playerElements = document.querySelectorAll('.spawnedavatar[data-playerid], .playerlist-row[data-playerid]'); const validPlayers = []; playerElements.forEach(el => { const playerId = el.dataset.playerid; if (!playerId || playerId === '0' || el.dataset.self === 'true') return; let playerName = ''; const nicknameEl = el.querySelector('.nickname, .playerlist-name a, .player-name'); if (nicknameEl) { playerName = nicknameEl.textContent.trim(); } 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(); } } if (!playerName) playerName = `Sujeto ${playerId}`; if (!validPlayers.some(p => p.id === playerId)) { validPlayers.push({ id: playerId, name: playerName }); } }); if (validPlayers.length === 0) { const opt = document.createElement('option'); opt.value = ''; opt.textContent = '❌ No hay objetivos disponibles'; playerSelect.appendChild(opt); executeBtn.disabled = true; } else { validPlayers.forEach(player => { const opt = document.createElement('option'); opt.value = player.id; opt.textContent = `🎯 ${player.name}`; playerSelect.appendChild(opt); }); const stillExists = validPlayers.some(p => p.id === currentSelection); if (currentSelection && stillExists) { playerSelect.value = currentSelection; } else { playerSelect.selectedIndex = 0; } executeBtn.disabled = false; } } async function executeUFOSimulation() { if (isExecuting) return; const playerId = playerSelect.value; const maneuverType = maneuverSelect.value; const phenomenonType = phenomenonSelect.value; const intensity = parseInt(intensitySlider.value); const shouldRepeat = repeatToggle.checked; if (!playerId) { alert('🚫 Por favor selecciona un objetivo válido'); return; } if (!maneuverType && !phenomenonType) { alert('🚫 Por favor selecciona una maniobra o fenómeno'); return; } isExecuting = true; stopSignal = false; executeBtn.disabled = true; stopBtn.disabled = false; do { try { if (maneuverType) { switch (maneuverType) { case 'maneuver:tic_tac_erratic': await ticTacErratic(playerId, intensity); break; case 'maneuver:instant_acceleration': await instantAcceleration(playerId, intensity); break; case 'maneuver:absolute_hover': await absoluteHover(playerId, intensity); break; case 'maneuver:impossible_turns': await impossibleTurns(playerId, intensity); break; case 'maneuver:intelligent_evasion': await intelligentEvasion(playerId, intensity); break; case 'maneuver:multi_sensor_detection': await multiSensorDetection(playerId, intensity); break; case 'maneuver:gimbal_rotation': await gimbalRotation(playerId, intensity); break; case 'maneuver:sudden_disappearance': await suddenDisappearance(playerId, intensity); break; case 'maneuver:oceanic_pattern': await oceanicPattern(playerId, intensity); break; case 'maneuver:nuclear_monitoring': await nuclearMonitoring(playerId, intensity); break; } } if (phenomenonType) { switch (phenomenonType) { case 'phenomenon:triangular_formation': await triangularFormation(playerId, intensity); break; case 'phenomenon:close_encounter_1': await closeEncounter1(playerId, intensity); break; case 'phenomenon:close_encounter_2': await closeEncounter2(playerId, intensity); break; case 'phenomenon:close_encounter_3': await closeEncounter3(playerId, intensity); break; case 'phenomenon:light_absorption': await lightAbsorption(playerId, intensity); break; case 'phenomenon:spatial_distortion': await spatialDistortion(playerId, intensity); break; case 'phenomenon:multispectral_anomaly': await multispectralAnomaly(playerId, intensity); break; case 'phenomenon:plasma_manifestation': await plasmaManifestation(playerId, intensity); break; case 'phenomenon:controlled_vortex': await controlledVortex(playerId, intensity); break; } } if (shouldRepeat && !stopSignal) { await new Promise(r => setTimeout(r, 1500)); } } catch (error) { console.error('🛸 Error en simulación OVNI:', error); break; } } while (shouldRepeat && !stopSignal); isExecuting = false; executeBtn.disabled = false; stopBtn.disabled = true; console.log('🛸 Simulación de fenómenos OVNI completada'); } function stopExecution() { stopSignal = true; isExecuting = false; if (activeEffectInterval) { clearInterval(activeEffectInterval); activeEffectInterval = null; } executeBtn.disabled = false; stopBtn.disabled = true; console.log('🛑 Simulación detenida por el operador'); } /* ---------- EVENT LISTENERS ---------- */ executeBtn.addEventListener('click', executeUFOSimulation); stopBtn.addEventListener('click', stopExecution); 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'; }); console.log('🛸 SIMULADOR DE FENÓMENOS OVNI cargado exitosamente! 🛸'); console.log('📡 Basado en casos documentados del Pentágono - USS Nimitz, GIMBAL, FLIR1'); console.log('⚡ Maniobras imposibles: Tic Tac, aceleración instantánea, curvas indefinidas'); })();