您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automated PvP battle script with auto-queue and continuous fighting
// ==UserScript== // @name Veyra - PvP Auto Battle // @namespace http://tampermonkey.net/ // @version 1.1.2 // @description Automated PvP battle script with auto-queue and continuous fighting // @match https://demonicscans.org/pvp_battle.php // @match https://demonicscans.org/pvp.php // @icon https://www.google.com/s2/favicons?sz=64&domain=demonicscans.org // @grant none // @license GNU General Public License v3.0 // @run-at document-end // ==/UserScript== (function() { 'use strict'; // Battle and Queue state let battleState = { isActive: false, firstAttackMade: false, willWin: null, // null = unknown, true = will win, false = will lose autoSlashing: false, battleEnded: false }; let queueState = { autoQueue: false, battlesWon: 0, battlesLost: 0, totalBattles: 0, battleLimit: 0, // 0 = unlimited (use all tokens) battlesRemaining: 0 }; // Load session state from localStorage function loadSessionState() { const saved = localStorage.getItem('veyra_pvp_session'); if (saved) { const parsed = JSON.parse(saved); queueState = { ...queueState, ...parsed }; // Don't restore autoQueue - this resets on page load queueState.autoQueue = false; } } // Save session state to localStorage function saveSessionState() { localStorage.setItem('veyra_pvp_session', JSON.stringify(queueState)); } // Reset session stats function resetSessionStats() { queueState.battlesWon = 0; queueState.battlesLost = 0; queueState.totalBattles = 0; queueState.battleLimit = 0; queueState.battlesRemaining = 0; saveSessionState(); } let slashInterval = null; let currentPage = window.location.href; // --- HUD Setup --- function createHUD() { const hud = document.createElement("div"); hud.id = "veyra-pvp-hud"; hud.style.cssText = ` position: fixed; top: 10px; right: 10px; background: rgba(0,0,0,0.95); color: #ff6b35; font-size: 12px; font-family: 'Courier New', monospace; padding: 12px; border-radius: 8px; border: 2px solid #ff6b35; z-index: 99999; min-width: 280px; box-shadow: 0 4px 12px rgba(0,0,0,0.5); `; if (currentPage.includes('pvp.php')) { hud.innerHTML = createDashboardHUD(); } else if (currentPage.includes('pvp_battle.php')) { hud.innerHTML = createBattleHUD(); } document.body.appendChild(hud); setupHUDEvents(); } function createDashboardHUD() { return ` <div style="text-align: center; margin-bottom: 8px; font-weight: bold; color: #ffff00;"> ⚔️ VEYRA PvP v1.1 </div> <div id="tokens-container" style="margin-bottom: 10px; padding: 6px; background: rgba(255,255,255,0.1); border-radius: 4px;"> <div>🪙 PvP Tokens: <span id="token-display">Loading...</span></div> </div> <div id="battle-limit-container" style="margin-bottom: 10px; padding: 6px; background: rgba(255,255,255,0.1); border-radius: 4px;"> <div style="margin-bottom: 4px;">⚙️ Battle Limit:</div> <input type="number" id="battle-limit-input" value="0" min="0" max="20" style=" width: 50px; padding: 2px 4px; background: rgba(0,0,0,0.5); color: #ff6b35; border: 1px solid #ff6b35; border-radius: 3px; margin-right: 6px; "> <small style="color: #aaa;">battles (0 = use all tokens)</small> </div> <div id="stats-container" style="margin-bottom: 10px; padding: 6px; background: rgba(255,255,255,0.1); border-radius: 4px;"> <div>📊 Session Stats:</div> <div style="margin-left: 10px;"> <div>🏆 Wins: <span id="wins-display">0</span></div> <div>💀 Losses: <span id="losses-display">0</span></div> <div>⚡ Total: <span id="total-display">0</span></div> <div id="remaining-display" style="display: none;">🎯 Remaining: <span id="battles-remaining">0</span></div> </div> </div> <div id="queue-status" style="margin-bottom: 10px; text-align: center; font-weight: bold;"> Status: <span id="status-text">Ready to queue</span> </div> <div id="controls-container" style="text-align: center;"> <button id="auto-queue-btn" style=" padding: 8px 16px; background: #ff6b35; color: white; border: none; border-radius: 5px; cursor: pointer; font-weight: bold; font-size: 12px; margin-right: 8px; ">🚀 START AUTO QUEUE</button> <button id="stop-queue-btn" style=" padding: 8px 16px; background: #aa3333; color: white; border: none; border-radius: 5px; cursor: pointer; font-weight: bold; font-size: 12px; display: none; ">⏹️ STOP QUEUE</button> <button id="reset-stats-btn" style=" padding: 8px 16px; background: #303030; color: white; border: none; border-radius: 5px; cursor: pointer; font-weight: bold; font-size: 12px; ">🔁 Reset Stats</button> </div> <div id="log-container" style=" margin-top: 8px; max-height: 100px; overflow-y: auto; font-size: 10px; color: #ccc; border-top: 1px solid #555; padding-top: 6px; "> <div>Auto-queue ready!</div> </div> `; } function createBattleHUD() { return ` <div style="text-align: center; margin-bottom: 8px; font-weight: bold; color: #ffff00;"> ⚔️ VEYRA PvP v1.1 </div> <div id="hp-container" style="margin-bottom: 10px; padding: 6px; background: rgba(255,255,255,0.1); border-radius: 4px;"> <div>💚 Your HP: <span id="player-hp-display">Loading...</span></div> <div>❤️ Enemy HP: <span id="enemy-hp-display">Loading...</span></div> </div> <div id="battle-status" style="margin-bottom: 10px; text-align: center; font-weight: bold;"> Status: <span id="status-text">Auto-fighting...</span> </div> <div id="prediction-container" style="margin-bottom: 10px; padding: 6px; background: rgba(255,255,255,0.1); border-radius: 4px;"> <div style="text-align: center; font-weight: bold;"> <span id="prediction-text">Fighting to the end!</span> </div> </div> <div id="log-container" style=" margin-top: 8px; max-height: 120px; overflow-y: auto; font-size: 10px; color: #ccc; border-top: 1px solid #555; padding-top: 6px; "> <div>Auto-battle in progress...</div> </div> `; } function setupHUDEvents() { if (currentPage.includes('pvp.php')) { const autoQueueBtn = document.getElementById('auto-queue-btn'); const stopQueueBtn = document.getElementById('stop-queue-btn'); const resetStatsBtn = document.getElementById('reset-stats-btn'); const battleLimitInput = document.getElementById('battle-limit-input'); if (autoQueueBtn) { autoQueueBtn.addEventListener('click', startAutoQueue); } if (stopQueueBtn) { stopQueueBtn.addEventListener('click', stopAutoQueue); } if (resetStatsBtn) { resetStatsBtn.addEventListener('click', () => { if (confirm('Reset session statistics?')) { resetSessionStats(); updateHUDDisplay(); addLog('Session stats reset'); } }); } if (battleLimitInput) { battleLimitInput.addEventListener('change', (e) => { queueState.battleLimit = parseInt(e.target.value) || 0; saveSessionState(); updateBattleRemainingDisplay(); }); } } // Battle page doesn't need manual controls - auto-starts } function updateHUDDisplay() { if (currentPage.includes('pvp.php')) { const tokens = getPvPTokens(); document.getElementById('token-display').textContent = tokens ? `${tokens}/20` : 'N/A'; document.getElementById('wins-display').textContent = queueState.battlesWon; document.getElementById('losses-display').textContent = queueState.battlesLost; document.getElementById('total-display').textContent = queueState.totalBattles; updateBattleRemainingDisplay(); } else if (currentPage.includes('pvp_battle.php')) { const playerHP = getPlayerHP(); const enemyHP = getEnemyHP(); if (document.getElementById('player-hp-display')) { document.getElementById('player-hp-display').textContent = playerHP || 'N/A'; } if (document.getElementById('enemy-hp-display')) { document.getElementById('enemy-hp-display').textContent = enemyHP || 'N/A'; } } } function updateBattleRemainingDisplay() { const remainingDisplay = document.getElementById('remaining-display'); const battlesRemainingSpan = document.getElementById('battles-remaining'); if (queueState.battleLimit > 0) { queueState.battlesRemaining = Math.max(0, queueState.battleLimit - queueState.totalBattles); remainingDisplay.style.display = 'block'; battlesRemainingSpan.textContent = queueState.battlesRemaining; } else { remainingDisplay.style.display = 'none'; } } function updateStatus(message) { document.getElementById('status-text').textContent = message; addLog(message); } function addLog(message) { const logContainer = document.getElementById('log-container'); const logEntry = document.createElement('div'); const timestamp = new Date().toLocaleTimeString(); logEntry.textContent = `[${timestamp}] ${message}`; logContainer.appendChild(logEntry); logContainer.scrollTop = logContainer.scrollHeight; } function showPrediction(willWin) { const predictionText = document.getElementById('prediction-text'); if (predictionText) { if (willWin) { predictionText.textContent = '🎯 Victory predicted - fighting to the end!'; predictionText.style.color = '#00ff00'; } else { predictionText.textContent = '⚠️ Defeat predicted - fighting to the end!'; predictionText.style.color = '#ff4444'; } } } // --- Game Element Functions --- function getPvPTokens() { const tokenEl = document.evaluate( '//*[@id="pvp-coins"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; return tokenEl ? parseInt(tokenEl.textContent.trim()) : null; } function clickStartPvP() { const startBtn = document.evaluate( '//*[@id="btnStartTop"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (startBtn) { startBtn.click(); return true; } return false; } function getPlayerHP() { const hpEl = document.evaluate( '//*[@id="myHpText"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; return hpEl ? hpEl.textContent.trim() : null; } function getEnemyHP() { const hpEl = document.evaluate( '//*[@id="enemyHpText"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; return hpEl ? hpEl.textContent.trim() : null; } function getNotification() { const notificationEl = document.evaluate( '//*[@id="notification"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; return notificationEl ? notificationEl.textContent.trim() : null; } function isBattleEnded() { const endTitleEl = document.evaluate( '//*[@id="endTitle"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (endTitleEl) { const text = endTitleEl.textContent.trim(); if (text.includes('🏁 Victory!')) { return { ended: true, victory: true }; } else if (text.includes('❌ Defeat')) { return { ended: true, victory: false }; } } return { ended: false, victory: null }; } function containsSubstring(str, substring) { return str.toLowerCase().includes(substring.toLowerCase()); } function clickSlash() { const slashSubstring = "Slash"; const btn1 = document.evaluate( '/html/body/div[2]/div/div[3]/div[6]/button[1]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; const btn2 = document.evaluate( '/html/body/div[2]/div/div[4]/div[6]/button[1]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; const btn3 = document.evaluate( '/html/body/div[4]/div[6]/button', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; const btn4 = document.evaluate( '/html/body/div[5]/div[6]/button', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (btn1) { if (containsSubstring(btn1.textContent, slashSubstring)) { btn1.click() return true } } if (btn2) { if (containsSubstring(btn2.textContent, slashSubstring)) { btn2.click() return true } } if (btn3) { if (containsSubstring(btn3.textContent, slashSubstring)) { btn3.click() return true } } if (btn4) { if (containsSubstring(btn4.textContent, slashSubstring)) { btn4.click() return true } } return false; } // --- Queue Management --- function startAutoQueue() { // Get battle limit from input const battleLimitInput = document.getElementById('battle-limit-input'); queueState.battleLimit = parseInt(battleLimitInput.value) || 0; queueState.battlesRemaining = queueState.battleLimit; queueState.autoQueue = true; saveSessionState(); const autoQueueBtn = document.getElementById('auto-queue-btn'); const stopQueueBtn = document.getElementById('stop-queue-btn'); autoQueueBtn.style.display = 'none'; stopQueueBtn.style.display = 'inline-block'; if (queueState.battleLimit > 0) { updateStatus(`Auto-queue started! Target: ${queueState.battleLimit} battles`); addLog(`Auto-queue activated for ${queueState.battleLimit} battles`); } else { updateStatus('Auto-queue started! Using all tokens'); addLog('Auto-queue activated - will use all available tokens'); } updateBattleRemainingDisplay(); // Start the queue loop queueLoop(); } function stopAutoQueue() { queueState.autoQueue = false; const autoQueueBtn = document.getElementById('auto-queue-btn'); const stopQueueBtn = document.getElementById('stop-queue-btn'); autoQueueBtn.style.display = 'inline-block'; stopQueueBtn.style.display = 'none'; updateStatus('Auto-queue stopped'); addLog('Auto-queue deactivated'); } function queueLoop() { if (!queueState.autoQueue) return; updateHUDDisplay(); // Check battle limit first if (queueState.battleLimit > 0 && queueState.totalBattles >= queueState.battleLimit) { updateStatus('Battle limit reached!'); addLog(`Completed ${queueState.battleLimit} battles - stopping queue`); stopAutoQueue(); return; } // Check tokens const tokens = getPvPTokens(); if (!tokens || tokens <= 0) { updateStatus('No PvP tokens available - queue stopped'); addLog('No tokens remaining - auto-queue stopped'); stopAutoQueue(); return; } updateStatus('Starting PvP battle...'); if (queueState.battleLimit > 0) { addLog(`Starting battle ${queueState.totalBattles + 1}/${queueState.battleLimit} (${tokens} tokens)`); } else { addLog(`Starting battle (${tokens} tokens remaining)`); } if (clickStartPvP()) { // Battle will start and page will redirect // The script will continue on the battle page } else { updateStatus('❌ Start button not found'); setTimeout(() => queueLoop(), 5000); } } // --- Battle Logic --- function startAutoSlashing() { if (battleState.autoSlashing) return; battleState.isActive = true; battleState.autoSlashing = true; updateStatus('Auto-battle started'); addLog('Beginning auto-slash sequence'); // Make first attack immediately makeAttack(); } function makeAttack() { if (!battleState.autoSlashing || battleState.battleEnded) return; updateStatus('Attacking...'); if (clickSlash()) { // Wait for server response and check result setTimeout(() => { checkAttackResult(); }, 500); } else { updateStatus('❌ Slash button not found'); stopAutoSlashing(); } } function checkAttackResult() { const notification = getNotification(); if (!notification) { // No notification yet, wait a bit more setTimeout(() => checkAttackResult(), 300); return; } addLog(`Notification: ${notification}`); // Check for cooldown message if (notification.includes('⏳ Cooldown')) { updateStatus('Cooldown active, waiting...'); setTimeout(() => makeAttack(), 1100); return; } // First attack - determine win prediction if (!battleState.firstAttackMade) { battleState.firstAttackMade = true; if (notification.includes('You won the exchange: dealt')) { battleState.willWin = true; showPrediction(true); updateStatus('Victory predicted - continuing battle'); setTimeout(() => makeAttack(), 1100); } else if (notification.includes('Enemy gained the upper hand: dealt')) { battleState.willWin = false; showPrediction(false); updateStatus('Defeat predicted - fighting to the end'); setTimeout(() => makeAttack(), 1100); } else { // Unknown notification, continue updateStatus('Unknown result, continuing battle'); setTimeout(() => makeAttack(), 1100); } } else { // Subsequent attacks - continue fighting setTimeout(() => makeAttack(), 1100); } } function surrenderBattle() { // Removed - no longer surrendering } function stopAutoSlashing() { battleState.autoSlashing = false; if (slashInterval) { clearInterval(slashInterval); slashInterval = null; } updateStatus('Battle ended'); } function checkBattleEnd() { const battleResult = isBattleEnded(); if (battleResult.ended) { battleState.battleEnded = true; stopAutoSlashing(); // Update stats and save queueState.totalBattles++; if (battleResult.victory) { queueState.battlesWon++; updateStatus('🎉 Victory! Returning to queue...'); addLog('Battle won - returning to dashboard'); } else { queueState.battlesLost++; updateStatus('💀 Defeat! Returning to queue...'); addLog('Battle lost - returning to dashboard'); } saveSessionState(); saveSessionState(); // Set flag to continue queue when returning to dashboard localStorage.setItem('veyra_continue_queue', 'true'); // Return to PvP dashboard immediately (no delay) setTimeout(() => { window.location.href = 'https://demonicscans.org/pvp.php'; }, 1500); } } // --- Main Loop --- function gameLoop() { // Update HP display updateHUDDisplay(); // Check if battle ended checkBattleEnd(); // Continue loop if (!battleState.battleEnded) { setTimeout(() => gameLoop(), 1000); } } // --- Initialization --- function initialize() { currentPage = window.location.href; // Load saved session state first loadSessionState(); // Create HUD createHUD(); if (currentPage.includes('pvp.php')) { // PvP Dashboard function waitForDashboardElements() { const tokens = getPvPTokens(); if (tokens !== null) { updateStatus('Dashboard ready'); updateHUDDisplay(); // Restore battle limit input const battleLimitInput = document.getElementById('battle-limit-input'); if (battleLimitInput) { battleLimitInput.value = queueState.battleLimit; } // Check if we should continue auto-queuing if (localStorage.getItem('veyra_continue_queue') === 'true') { localStorage.removeItem('veyra_continue_queue'); // Check if we should continue based on limits const shouldContinue = (queueState.battleLimit === 0 && tokens > 0) || // Unlimited and has tokens (queueState.battleLimit > 0 && queueState.totalBattles < queueState.battleLimit && tokens > 0); // Has limit and not reached if (shouldContinue) { addLog('Continuing auto-queue after battle'); setTimeout(() => startAutoQueue(), 1000); } else { updateStatus('Auto-queue completed!'); if (queueState.battleLimit > 0) { addLog(`All ${queueState.battleLimit} battles completed!`); } else { addLog('All tokens used - queue completed'); } } } } else { setTimeout(waitForDashboardElements, 500); } } waitForDashboardElements(); } else if (currentPage.includes('pvp_battle.php')) { // PvP Battle - auto-start fighting function waitForBattleElements() { const playerHP = getPlayerHP(); if (playerHP) { updateHUDDisplay(); addLog('Battle detected - starting auto-fight'); // Auto-start battle setTimeout(() => startAutoSlashing(), 1000); // Start battle monitoring loop gameLoop(); } else { setTimeout(waitForBattleElements, 500); } } waitForBattleElements(); } } // Start the script initialize(); })();