您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Predator vision thermal overlay with heat shimmer, triangular reticle, numeric stream, and draggable anchored toggle button.
// ==UserScript== // @name Lichess Predator Vision Overlay // @namespace http://tampermonkey.net/ // @version 1.6 // @description Predator vision thermal overlay with heat shimmer, triangular reticle, numeric stream, and draggable anchored toggle button. // @match https://lichess.org/ // @grant none // ==/UserScript== (function() { 'use strict'; // Load saved position or default let savedPos = localStorage.getItem('predatorVisionBtnPos'); let pos = savedPos ? JSON.parse(savedPos) : null; // Default: under Terminator Vision button (shift 50px down) const defaultTop = pos ? pos.top : 156; const defaultRight = pos ? null : 154; // Create toggle button const btn = document.createElement('button'); btn.textContent = 'Predator Vision'; Object.assign(btn.style, { position: 'fixed', top: `${defaultTop}px`, right: defaultRight !== null ? `${defaultRight}px` : '', left: pos ? `${pos.left}px` : '', zIndex: 999999, padding: '8px 14px', background: '#004400', color: 'lime', border: 'none', borderRadius: '5px', cursor: 'pointer', fontWeight: 'bold', fontFamily: 'Consolas, monospace', userSelect: 'none', boxShadow: '0 0 8px lime', letterSpacing: '0.05em', touchAction: 'none', }); btn.addEventListener('mouseenter', () => btn.style.backgroundColor = '#006600'); btn.addEventListener('mouseleave', () => btn.style.backgroundColor = '#004400'); document.body.appendChild(btn); // Dragging logic let dragging = false, dragStartX = 0, dragStartY = 0, btnStartLeft = 0, btnStartTop = 0; btn.addEventListener('mousedown', e => { dragging = true; dragStartX = e.clientX; dragStartY = e.clientY; const rect = btn.getBoundingClientRect(); btnStartLeft = rect.left; btnStartTop = rect.top; e.preventDefault(); }); window.addEventListener('mousemove', e => { if (!dragging) return; let newLeft = btnStartLeft + (e.clientX - dragStartX); let newTop = btnStartTop + (e.clientY - dragStartY); newLeft = Math.min(window.innerWidth - btn.offsetWidth, Math.max(0, newLeft)); newTop = Math.min(window.innerHeight - btn.offsetHeight, Math.max(0, newTop)); btn.style.left = `${newLeft}px`; btn.style.top = `${newTop}px`; btn.style.right = ''; localStorage.setItem('predatorVisionBtnPos', JSON.stringify({left: newLeft, top: newTop})); }); window.addEventListener('mouseup', () => dragging = false); // Overlay container const overlay = document.createElement('div'); Object.assign(overlay.style, { position: 'fixed', top: 0, left: 0, width: '100vw', height: '100vh', background: 'rgba(0, 50, 0, 0.6)', // greener overlay zIndex: 999998, pointerEvents: 'none', display: 'none', overflow: 'hidden' }); // Heatmap shimmer filter overlay.style.backdropFilter = 'contrast(200%) saturate(250%) hue-rotate(90deg)'; // Shimmer effect const shimmer = document.createElement('div'); Object.assign(shimmer.style, { position: 'absolute', width: '100%', height: '100%', background: 'radial-gradient(rgba(0,255,0,0.1), transparent)', mixBlendMode: 'screen', animation: 'heatShimmer 2s infinite linear', opacity: 0.4 }); overlay.appendChild(shimmer); // Numeric stream box (only numeric box now) const numStream = document.createElement('div'); Object.assign(numStream.style, { position: 'fixed', top: '300px', right: '20px', width: '80px', height: '170px', // reduced height to fit lines better color: 'lime', fontFamily: 'monospace', fontWeight: 'bold', fontSize: '14px', background: 'rgba(0,0,0,0.3)', textShadow: '0 0 10px lime', overflow: 'hidden', pointerEvents: 'none', zIndex: 40, userSelect: 'none', paddingLeft: '4px', // slight left shift to avoid cutoff lineHeight: '1.2', letterSpacing: '0.07em', borderRadius: '8px 0 0 8px', }); overlay.appendChild(numStream); const chars = '0123456789ABCDEF'; const lineCount = 10; const lines = []; for(let i=0; i<lineCount; i++){ const span = document.createElement('span'); span.textContent = Array.from({length:12}, () => chars[Math.floor(Math.random()*chars.length)]).join(''); span.style.opacity = Math.random() * 0.5 + 0.5; numStream.appendChild(span); if (i < lineCount - 1) { numStream.appendChild(document.createElement('br')); // no br after last line } lines.push(span); } function animateNumStream(){ lines.forEach(line => { if(Math.random() < 0.05){ // slower updates line.textContent = Array.from({length:12}, () => chars[Math.floor(Math.random()*chars.length)]).join(''); } }); requestAnimationFrame(animateNumStream); } // Text labels in corners and top center function createTextLabel(text, styles){ const d = document.createElement('div'); d.textContent = text.toUpperCase(); Object.assign(d.style, { position: 'fixed', color: 'lime', fontWeight: '900', fontFamily: 'Consolas, monospace', fontSize: '1.4rem', textShadow: '0 0 8px lime', userSelect: 'none', pointerEvents: 'none', letterSpacing: '0.1em', ...styles, }); overlay.appendChild(d); } createTextLabel('PREDATOR MODE ACTIVATED', {top: '20px', left: '50%', transform: 'translateX(-50%)'}); createTextLabel('THERMAL TARGET LOCKED', {top: '20px', left: '20px'}); createTextLabel('SCANNING', {top: '20px', right: '20px'}); // Triangular reticle element creation & animation const reticle = document.createElement('div'); reticle.innerHTML = ` <svg width="80" height="80" viewBox="0 0 80 80" xmlns="http://www.w3.org/2000/svg"> <polygon points="40,5 75,75 5,75" stroke="lime" stroke-width="2" fill="none" /> <circle cx="40" cy="50" r="5" fill="lime" /> </svg> `; Object.assign(reticle.style, { position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', pointerEvents: 'none', zIndex: 50, }); overlay.appendChild(reticle); let reticleTime = 0; function animateReticle(){ reticleTime += 0.015; // speed up slightly for smoothness const radius = 80; const centerX = window.innerWidth / 2; const centerY = window.innerHeight / 2; const x = centerX + Math.cos(reticleTime) * radius; const y = centerY + Math.sin(reticleTime) * radius; reticle.style.left = `${x}px`; reticle.style.top = `${y}px`; requestAnimationFrame(animateReticle); } // Create waiting message at bottom center, big green with sharp border and pulsate const waitingMsg = document.createElement('div'); waitingMsg.textContent = 'WAITING FOR GAME...'; Object.assign(waitingMsg.style, { position: 'fixed', bottom: '20px', left: '50%', transform: 'translateX(-50%)', color: 'lime', fontWeight: '900', fontFamily: 'Consolas, monospace', fontSize: '5rem', letterSpacing: '0.15em', textTransform: 'uppercase', userSelect: 'none', pointerEvents: 'none', whiteSpace: 'nowrap', zIndex: 1000000, textShadow: '-2px -2px 0 #000,' + '2px -2px 0 #000,' + '-2px 2px 0 #000,' + '2px 2px 0 #000', animation: 'pulseSharp 2.5s ease-in-out infinite', display: 'none' // initially hidden }); document.body.appendChild(waitingMsg); // Keyframes for shimmer and pulse plus pulseSharp for waiting message const style = document.createElement('style'); style.textContent = ` @keyframes pulseGreen { 0%, 100% { opacity: 1; text-shadow: 0 0 6px lime; } 50% { opacity: 0.5; text-shadow: 0 0 2px green; } } @keyframes heatShimmer { 0% { transform: translateY(0); } 50% { transform: translateY(-5px); } 100% { transform: translateY(0); } } @keyframes pulseSharp { 0%, 100% { opacity: 1; text-shadow: -2px -2px 0 #000, 2px -2px 0 #000, -2px 2px 0 #000, 2px 2px 0 #000; } 50% { opacity: 0.5; text-shadow: -1px -1px 0 #222, 1px -1px 0 #222, -1px 1px 0 #222, 1px 1px 0 #222; } } `; document.head.appendChild(style); document.body.appendChild(overlay); // Toggle overlay on button click let active = false; btn.addEventListener('click', () => { active = !active; overlay.style.display = active ? 'block' : 'none'; waitingMsg.style.display = active ? 'block' : 'none'; // Show waiting message only when overlay is ON btn.style.backgroundColor = active ? '#006600' : '#004400'; if (active) { animateNumStream(); animateReticle(); } }); })();