您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
singleplayer 5k counter, counts per game and total, resettable
当前为
// ==UserScript== // @name GeoGuessr 5K Counter // @namespace https://greasyfork.org/en/users/1501889 // @version 1.3 // @description singleplayer 5k counter, counts per game and total, resettable // @author Clemens // @match https://www.geoguessr.com/* // @icon https://www.google.com/s2/favicons?domain=geoguessr.com // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @run-at document-end // @license MIT // ==/UserScript== (function() { 'use strict'; const stats = { total: GM_getValue('geo5k_total', 0), currentGame: GM_getValue('geo5k_current', 0), lastDetection: 0, detectedElements: new Set() }; function saveStats() { GM_setValue('geo5k_total', stats.total); GM_setValue('geo5k_current', stats.currentGame); } GM_addStyle(` #geo5k-counter { position: fixed !important; left: 20px; top: 75vh; background: rgba(30, 30, 30, 0.9); color: #f0f0f0; padding: 12px 16px; border-radius: 8px; font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; font-size: 14px; z-index: 99999 !important; /* Higher z-index */ border: 1px solid rgba(255, 255, 255, 0.1); min-width: 180px; cursor: move; user-select: none; backdrop-filter: blur(4px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); transition: transform 0.1s ease, box-shadow 0.2s ease; } #geo5k-counter:hover { box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2); } #geo5k-counter.dragging { cursor: grabbing; transform: scale(1.02); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); transition: transform 0.05s ease, box-shadow 0.05s ease; } #geo5k-counter-header { font-weight: 600; margin-bottom: 8px; font-size: 15px; color: #58a6ff; display: flex; align-items: center; justify-content: space-between; } #geo5k-counter-header::before { content: "✓"; color: #58a6ff; font-weight: bold; margin-right: 6px; } .geo5k-counter-row { margin: 6px 0; display: flex; justify-content: space-between; } .geo5k-counter-value { font-weight: 500; color: #ffffff; } #geo5k-reset-btn { background: rgba(255, 255, 255, 0.1); color: #ff6b6b; border: none; border-radius: 4px; padding: 2px 8px; font-size: 12px; cursor: pointer; transition: all 0.2s ease; margin-left: 8px; } #geo5k-reset-btn:hover { background: rgba(255, 107, 107, 0.2); color: #ff4d4d; } .geo5k-highlight { animation: geo5k-pulse 0.5s; } @keyframes geo5k-pulse { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } `); function createDisplay() { // Only create if doesn't exist or was removed let display = document.getElementById('geo5k-counter'); if (!display) { display = document.createElement('div'); display.id = 'geo5k-counter'; display.innerHTML = ` <div id="geo5k-counter-header"> <span>5K COUNTER</span> <button id="geo5k-reset-btn" title="Reset Total Count">Reset</button> </div> <div class="geo5k-counter-row"> <span>This Game:</span> <span id="geo5k-current" class="geo5k-counter-value">${stats.currentGame}/5</span> </div> <div class="geo5k-counter-row"> <span>Total:</span> <span id="geo5k-total" class="geo5k-counter-value">${stats.total}</span> </div> `; document.body.appendChild(display); document.getElementById('geo5k-reset-btn').addEventListener('click', function(e) { e.stopPropagation(); if (confirm('Are you sure you want to reset your total 5K count?')) { stats.total = 0; saveStats(); updateDisplay(); } }); setupDragging(display); } return display; } function setupDragging(display) { let isDragging = false; let startX, startY, initialX, initialY; display.addEventListener('mousedown', (e) => { if (e.button !== 0 || e.target.id === 'geo5k-reset-btn') return; isDragging = true; startX = e.clientX; startY = e.clientY; initialX = display.offsetLeft; initialY = display.offsetTop; display.classList.add('dragging'); display.style.transition = 'none'; e.preventDefault(); }); const moveHandler = (e) => { if (!isDragging) return; const dx = e.clientX - startX; const dy = e.clientY - startY; const newX = Math.max(0, Math.min(initialX + dx, window.innerWidth - display.offsetWidth)); const newY = Math.max(0, Math.min(initialY + dy, window.innerHeight - display.offsetHeight)); display.style.left = `${newX}px`; display.style.top = `${newY}px`; }; const upHandler = () => { if (!isDragging) return; isDragging = false; display.classList.remove('dragging'); display.style.transition = ''; }; document.addEventListener('mousemove', moveHandler, { passive: true }); document.addEventListener('mouseup', upHandler); } function updateDisplay() { const display = document.getElementById('geo5k-counter'); if (!display) { createDisplay(); return; } const currentEl = document.getElementById('geo5k-current'); const totalEl = document.getElementById('geo5k-total'); if (currentEl) currentEl.textContent = `${stats.currentGame}/5`; if (totalEl) totalEl.textContent = stats.total; } function checkFor5K() { // Check all potential score-containing elements const elements = document.querySelectorAll('span, div, p, h1, h2, h3, h4, h5, h6, button'); for (const element of elements) { if (stats.detectedElements.has(element)) continue; const text = element.textContent.trim(); if (text === '5,000' || text === '5000' || text.replace(/\s/g,'') === '5000') { stats.detectedElements.add(element); handle5KDetection(element); setTimeout(() => stats.detectedElements.delete(element), 3000); break; // Only process one at a time } } } function handle5KDetection(element) { const now = Date.now(); if (now - stats.lastDetection < 1000) return; // 1 second cooldown stats.lastDetection = now; stats.total++; stats.currentGame++; saveStats(); updateDisplay(); element.classList.add('geo5k-highlight'); setTimeout(() => element.classList.remove('geo5k-highlight'), 500); if (stats.currentGame >= 5) { setTimeout(() => { stats.currentGame = 0; saveStats(); updateDisplay(); }, 3000); } } function checkGameState() { const indicators = ['Round 1/5', '1 / 5', 'round 1 of 5']; const bodyText = document.body.textContent; if (indicators.some(indicator => bodyText.includes(indicator))) { stats.currentGame = 0; stats.detectedElements.clear(); saveStats(); updateDisplay(); } } function init() { // Create display first createDisplay(); updateDisplay(); setInterval(() => { checkFor5K(); checkGameState(); }, 200); // Check every 200ms document.addEventListener('keyup', (e) => { if (e.code === 'Space') setTimeout(checkFor5K, 100); }); document.addEventListener('click', () => setTimeout(checkFor5K, 100)); setInterval(() => { if (!document.getElementById('geo5k-counter')) { createDisplay(); updateDisplay(); } }, 1000); } if (document.readyState === 'complete') { init(); } else { document.addEventListener('DOMContentLoaded', init); } })();