您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Find the fastest path in DFProfiler
当前为
// ==UserScript== // @name DFProfiler Path Finder // @namespace http://tampermonkey.net/ // @version 0.1 // @description Find the fastest path in DFProfiler // @author Runonstof // @match https://*.dfprofiler.com/bossmap // @match https://*.dfprofiler.com/profile/view/* // @icon https://www.google.com/s2/favicons?sz=64&domain=dfprofiler.com // @grant unsafeWindow // @license MIT // ==/UserScript== (function() { 'use strict'; // === Utility functions === function GM_addStyle(css) { var style = document.getElementById("GM_addStyleBy8626") || (function() { var style = document.createElement('style'); style.type = 'text/css'; style.id = "GM_addStyleBy8626"; document.head.appendChild(style); return style; })(); var sheet = style.sheet; console.log(sheet); sheet.insertRule(css, (sheet.rules || sheet.cssRules || []).length); } function GM_addStyle_object(selector, styles) { var css = selector + "{"; for (var key in styles) { css += key + ":" + styles[key] + ";"; } css += "}"; GM_addStyle(css); } function ready(fn) { if (document.readyState != 'loading'){ fn(); } else { document.addEventListener('DOMContentLoaded', fn); } } function AStar(emptyCells) { this.emptyCells == emptyCells || []; this.Node = function Node(x, y) { this.x = parseInt(x); this.y = parseInt(y); this.g = 0; // cost from start node this.h = 0; // heuristic (estimated cost to target) this.f = 0; // total cost (g + h) this.parent = null; } this.isInsideMap = function(x, y) { return x >= 1000 && x <= 1058 && y >= 981 && y <= 1019; }; this.isCellEmpty = function(x, y) { return emptyCells.some(function(cell) { return cell.x == x && cell.y == y; }); }; this.heuristic = function(node, target) { // Manhattan distance heuristic return Math.abs(node.x - target.x) + Math.abs(node.y - target.y); }; this.find = function(startPos, endPos) { var openList = []; var closedList = []; var startNode = new this.Node(startPos.x, startPos.y); var endNode = new this.Node(endPos.x, endPos.y); openList.push(startNode); while (openList.length > 0) { var currentNode = openList[0]; var currentIndex = 0; for (var i = 1; i < openList.length; i++) { if (openList[i].f < currentNode.f) { currentNode = openList[i]; currentIndex = i; } } openList.splice(currentIndex, 1); closedList.push(currentNode); if (currentNode.x === endNode.x && currentNode.y === endNode.y) { var path = []; var current = currentNode; while (current !== null) { path.push({ x: current.x, y: current.y }); current = current.parent; } return path.reverse(); } var neighbors = [ { x: 1, y: -1 }, { x: 1, y: 1 }, { x: -1, y: 1 }, { x: -1, y: -1 }, { x: 0, y: 1 }, { x: 1, y: 0 }, { x: 0, y: -1 }, { x: -1, y: 0 }, ]; for (var neighbourIndex in neighbors) { var neighborDelta = neighbors[neighbourIndex]; var neighborX = currentNode.x + neighborDelta.x; var neighborY = currentNode.y + neighborDelta.y; if (!this.isInsideMap(neighborX, neighborY) || this.isCellEmpty(neighborX, neighborY)) { // console.log('cell is empty or outside map:', neighborX, neighborY); continue; } var neighborNode = new this.Node(neighborX, neighborY); var checkNeighbor = function(node) { return node.x === neighborX && node.y === neighborY; }; if (closedList.some(checkNeighbor)) { continue; } var tentativeG = currentNode.g + 1; // Assuming each step costs 1 if (!openList.some(checkNeighbor) || tentativeG < neighborNode.g) { neighborNode.g = tentativeG; neighborNode.h = this.heuristic(neighborNode, endNode); neighborNode.f = neighborNode.g + neighborNode.h; neighborNode.parent = currentNode; if (!openList.some(checkNeighbor)) { openList.push(neighborNode); } } } } // console.log(closedList); return null; // No path found } } // === CSS styles === GM_addStyle_object('#boss-data-section #mission-info, #bossmap-page #mission-info', { 'border-radius': '25px 25px 0 0', }); GM_addStyle_object('#boss-data-section #mission-info-distance-viewer, #bossmap-page #mission-info-distance-viewer', { 'position': 'absolute !important', 'background-color': 'hsla(0,0%,5%,.8)', 'border-radius': '0 0 25px 25px', 'padding': '5px', 'top': '770px', 'left': 'calc(50% - 16pt * 20)', 'right': 'calc(50% - 16pt * 20)', }); GM_addStyle_object('#boss-data-section #mission-info-buttons-title, #bossmap-page #mission-info-buttons-title', { 'color': 'white', 'font-size': '20px', }); GM_addStyle_object('#boss-data-section #mission-info-buttons-subtitle, #bossmap-page #mission-info-buttons-subtitle', { 'color': 'white', 'font-size': '14px', }); GM_addStyle_object('#boss-data-section button.mission-info-button, #bossmap-page button.mission-info-button', { 'background-color': 'gray', 'color': 'black', 'padding': '0.25em 0.5em', }); GM_addStyle_object('#boss-data-section button.mission-info-button:hover, #bossmap-page button.mission-info-button:hover', { 'color': 'white', }); GM_addStyle_object('#boss-data-section #dist-buttons, #bossmap-page #dist-buttons', { 'display': 'flex', 'gap': '10px', 'justify-content': 'center', }); GM_addStyle_object('#boss-data-section td.coord.path, #bossmap-page td.coord.path', { 'background-color': 'yellow !important', 'color': 'black !important', }); ready(function () { // === Create Elements === var missionHolder = document.getElementById('mission-holder'); var container = document.createElement('div'); container.id = 'mission-info-distance-viewer'; container.innerHTML = '<div id="mission-info-buttons-title">Path finder</div>'; container.innerHTML += '<div id="mission-info-buttons-subtitle">No path selected</div>'; container.innerHTML += '<div id="dist-buttons"><button id="dist-set-start" class="mission-info-button">Set start cell</button><button id="dist-set-end" class="mission-info-button">Set end cell</button><button id="dist-clear" style="display: none;" class="mission-info-button">Clear path</button></div>'; missionHolder.appendChild(container); unsafeWindow.closeMissionHolder = function (event) { if (event.target.closest('#mission-info-distance-viewer')) return; missionHolder.style.display = 'none'; }; missionHolder.setAttribute('onclick', 'closeMissionHolder(event)'); var startCellButton = document.getElementById('dist-set-start'); var endCellButton = document.getElementById('dist-set-end'); var clearPathButton = document.getElementById('dist-clear'); var subtitle = document.getElementById('mission-info-buttons-subtitle'); // === Scan empty cells var emptyCells = Array.from(document.querySelectorAll('td.coord')) .filter(function (el) { return el.computedStyleMap().get('opacity').toString() == '0'; }) .map(function (el) { return { x: el.classList[1].replace('x', ''), y: el.classList[2].replace('y', ''), }; }); var startCell = null; var endCell = null; var pathFinder = new AStar(emptyCells); function maybeUpdatePath() { if (!startCell || !endCell) return; var path = pathFinder.find(startCell, endCell); // Clear existing path cells var pathCells = unsafeWindow.document.querySelectorAll('td.coord.path'); for (var i = 0; i < pathCells.length; i++) { pathCells[i].classList.remove('path'); } // console.log(path); if (!path) return; for(var i = 0; i < path.length; i++) { var cellCoord = path[i]; // console.log(cellCoord); var cell = unsafeWindow.document.querySelector('td.coord.x' + cellCoord.x + '.y' + cellCoord.y); cell.classList.add('path'); } clearPathButton.style.display = 'initial'; subtitle.innerHTML = 'Path length: ' + path.length + ' cells'; } startCellButton.onclick = function () { // current pos var img = unsafeWindow.document.querySelector('#mission-info img'); var matches = img.src.match(/Fairview_(\d+)x(\d+)/); var x = matches[1]; var y = matches[2]; startCell = { x: x, y: y }; unsafeWindow.document.querySelector('td.coord.x' + x + '.y' + y).classList.add('path'); missionHolder.style.display = 'none'; maybeUpdatePath(); }; endCellButton.onclick = function () { // current pos var img = document.querySelector('#mission-info img'); var matches = img.src.match(/Fairview_(\d+)x(\d+)/); var x = matches[1]; var y = matches[2]; endCell = { x: x, y: y }; unsafeWindow.document.querySelector('td.coord.x' + x + '.y' + y).classList.add('path'); missionHolder.style.display = 'none'; maybeUpdatePath(); }; clearPathButton.onclick = function () { startCell = null; endCell = null; clearPathButton.style.display = 'none'; // Clear existing path cells var pathCells = unsafeWindow.document.querySelectorAll('td.coord.path'); for (var i = 0; i < pathCells.length; i++) { pathCells[i].classList.remove('path'); } subtitle.innerHTML = 'No path selected'; missionHolder.style.display = 'none'; }; }); })();