您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Shows paths between planets that can be reached by gravitonic and hyperjump connections
// ==UserScript== // @name Planets.nu gravitonic connections // @description Shows paths between planets that can be reached by gravitonic and hyperjump connections // @author robodoc // @license Creative Commons Attribution 4.0 (CC BY 4.0) // @include http://planets.nu/home // @include http://planets.nu/games/* // @include http://*.planets.nu/* // @include https://*.planets.nu/* // @include http://planets.nu/* // @include https://planets.nu/* // @version 3.0 (2019) // @date 2019-08-01 // @namespace https://greasyfork.org/users/5275 // ==/UserScript== // The movement information is based on the article // "Movement Limits Tim's Host: How far can you go?" by Stefan Reuther: // http://www.phost.de/~stefan/movement.html // Thanks to McNimble for suggesting improvements to version 2! // 1. Fixed a line weight problem that caused this plugin to not play well with // others such as Ion Storm Predictor. // 2. Made some cosmetic improvements to make the Grav and HYP lines // easier on the eyes. // Improvements to Version 3: // 1. This version includes connections that can be reached via "inexact" // movement (i.e., movement where you don't end up at your waypoint) // The inexact movement displacements are partly taken from Reuther's document // and partly taken from new calculations using the Nu client source code. // 2. These "inexact" connections are shown in purple. // 3. The W9Connect tool now shows "regular" connections (i.e. the same ones // shown by the Nu client) in gray and "hidden" connections in a different // color. // Features: // 1. The GravConnect tool shows paths between planets that can be reached by // gravitonic connections. Paths that can be reached by non-gravitonic // engines via normal connections are not shown. Special "inexact" // connections that can only be reached by setting a waypoint that can't be // reached in a single turn are shown in a differnt color (purple). // 2. The HYPConnect tool shows paths between planets that can be reached by // hyperjump connections. // 3. The W9Connect tool is an improved version of the built-in connections // tool that shows normal connections (gray), hidden connections (orange) // and special "inexact" connections that can only be reached by setting a // waypoint that can't be reached in a single turn (purple). // Instructions: Click the "GravConnect", "W9Connect" or "HYPConnect" items on // the Map Tools menu to turn these features on and off. function wrapper () { // wrapper for injection if (vgap.version < 3) { } // NEW VERSION else { // Change values from true to false if you do not want to show the features in your menu: var show_GravConnect = true; var show_HYPConnect = true; var show_W9Connect = true; var plugin = { /* * processload: executed whenever a turn is loaded: either the current turn or * an older turn through time machine */ processload: function() { }, /* * loaddashboard: executed to rebuild the dashboard content after a turn is loaded */ loaddashboard: function() { }, /* * showdashboard: executed when switching from starmap to dashboard */ showdashboard: function() { }, /* * showsummary: executed when returning to the main screen of the dashboard */ showsummary: function() { }, /* * loadmap: executed after the first turn has been loaded to create the map * as far as I can tell not executed again when using time machine */ loadmap: function() { vgap.map.gravconnect = false; if (show_GravConnect) vgap.map.addMapTool("GravConnect", "ShowMinerals", function () { if (vgap.map.gravconnect) { vgap.map.gravconnect = false; vgap.map.draw(); } else { vgap.map.gravconnect = true; vgap.plugins["GravConnect"].renderGravConnections(); vgap.map.draw(); } } ); vgap.map.hypconnect = false; if (show_HYPConnect) vgap.map.addMapTool("HYPConnect", "ShowMinerals", function () { if (vgap.map.hypconnect) { vgap.map.hypconnect = false; vgap.map.draw(); } else { vgap.map.hypconnect = true; vgap.plugins["GravConnect"].renderHypConnections(); vgap.map.draw(); } } ); vgap.map.w9connect = false; if (show_W9Connect) vgap.map.addMapTool("W9Connect", "ShowMinerals", function () { //vgap.map.w9connect.toggleClass("selectedmaptool") if (vgap.map.w9connect) { vgap.map.w9connect = false; vgap.map.draw(); } else { vgap.map.w9connect = true; vgap.plugins["GravConnect"].renderW9Connections(); vgap.map.draw(); } } ); }, /* * showmap: executed when switching from dashboard to starmap */ showmap: function() { }, /* * draw: executed on any click or drag on the starmap */ draw: function() { if (vgap.map.gravconnect) vgap.plugins["GravConnect"].renderGravConnections(); if (vgap.map.hypconnect) vgap.plugins["GravConnect"].renderHypConnections(); if (vgap.map.w9connect) vgap.plugins["GravConnect"].renderW9Connections(); }, /* * loadplanet: executed a planet is selected on dashboard or starmap * loadstarbase: executed a planet is selected on dashboard or starmap * Inside the function "load" of vgapPlanetScreen (vgapPlanetScreen.prototype.load) the normal planet screen * is set up. You can find the function in "nu.js" if you search for 'vgap.callPlugins("loadplanet");'. * * Things accessed inside this function several variables can be accessed. Elements accessed as "this.X" * can be accessed here as "vgap.planetScreen.X". */ loadplanet: function() { }, /* * loadstarbase: executed a planet is selected on dashboard or starmap * Inside the function "load" of vgapStarbaseScreen (vgapStarbaseScreen.prototype.load) the normal starbase screen * is set up. You can find the function in "nu.js" if you search for 'vgap.callPlugins("loadstarbase");'. * * Things accessed inside this function several variables can be accessed. Elements accessed as "this.X" * can be accessed here as "vgap.starbaseScreen.X". */ loadstarbase: function() { }, /* * loadship: executed a planet is selected on dashboard or starmap * Inside the function "load" of vgapShipScreen (vgapShipScreen.prototype.load) the normal ship screen * is set up. You can find the function in "nu.js" if you search for 'vgap.callPlugins("loadship");'. * * Things accessed inside this function several variables can be accessed. Elements accessed as "this.X" * can be accessed here as "vgap.shipScreen.X". */ loadship: function() {}, // END PLUGIN FUNCS renderGravConnections: function() { //console.log("Rendering connections" ); var conn2 = []; // regular grav connections var conn3 = []; // inexact connections for (var i = 0; i < vgap.planets.length; i++) { var planetA = vgap.planets[i]; for (var j = i + 1; j < vgap.planets.length; j++) { var planetB = vgap.planets[j]; var dist = Math.dist(planetA.x, planetA.y, planetB.x, planetB.y); var connection = false; if (dist > 83.5 && dist <= 165.505) { if (dist <= 165.0) { // This should always be a valid connection connection = 2; } else { // This will be close, so check individual points in warp well connection = vgap.plugins["GravConnect"].checkGravConnection(planetA.x, planetA.y, planetB.x, planetB.y); } } if (connection == 2) { conn2.push({x1:planetA.x, x2:planetB.x, y1:planetA.y, y2:planetB.y}); // ctx.moveTo(vgap.map.screenX(planetA.x), vgap.map.screenY(planetA.y)); // ctx.lineTo(vgap.map.screenX(planetB.x), vgap.map.screenY(planetB.y)); } else if (connection == 3) { conn3.push({x1:planetA.x, x2:planetB.x, y1:planetA.y, y2:planetB.y}); // ctx.moveTo(vgap.map.screenX(planetA.x), vgap.map.screenY(planetA.y)); // ctx.lineTo(vgap.map.screenX(planetB.x), vgap.map.screenY(planetB.y)); } } } var ctx = vgap.map.ctx ctx.beginPath(); console.log("Number of grav connections:",conn2.length) ctx = vgap.map.ctx ctx.beginPath(); for (var i = 0; i < conn2.length; i++) { ctx.moveTo(vgap.map.screenX(conn2[i].x1), vgap.map.screenY(conn2[i].y1)); ctx.lineTo(vgap.map.screenX(conn2[i].x2), vgap.map.screenY(conn2[i].y2)); } ctx.closePath(); ctx.strokeStyle = "#ff4545"; ctx.lineWidth = 0.5; // suggested by McNimble ctx.stroke(); console.log("Number of inexact grav connections:",conn3.length) ctx = vgap.map.ctx ctx.beginPath(); for (var i = 0; i < conn3.length; i++) { ctx.moveTo(vgap.map.screenX(conn3[i].x1), vgap.map.screenY(conn3[i].y1)); ctx.lineTo(vgap.map.screenX(conn3[i].x2), vgap.map.screenY(conn3[i].y2)); } ctx.closePath(); ctx.strokeStyle = "#9932CC"; ctx.lineWidth = 1.5; ctx.stroke(); ctx.lineWidth = 1; // suggested by McNimble //console.log("Rendered connections" ); }, checkGravConnection: function(Ax,Ay,Bx,By) { //console.log("Rendering connections" ); // Determine if a point in the warp well is within the "maximum safe distance" var delx = [3.0,2.0,0,-2.0,-3.0,-2.0,0,2.0]; var dely = [0,2.0,3.0,2.0,0,-2.0,-3.0,-2.0]; var Bx2, By2; for (var i = 0; i < delx.length; i++) { Bx2 = Bx + delx[i]; By2 = By + dely[i]; var dist = Math.dist(Ax, Ay, Bx2, By2); if (dist <= 162.505) { //console.log("Safe distance at ",dist," to point in warp well"); return 2; } } // Determine if a point in the warp well beyond the "maximum safe distance" can be reached exactly var exactx = [89,92,99,104,113,114,115,116,117,125,129,134,136]; var exacty = [136,134,129,125,117,116,115,114,113,104,99,92,89]; // Expanded list: for (var i = 0; i < delx.length; i++) { Bx2 = Bx + delx[i]; By2 = By + dely[i]; for (var j = 0; j < exactx.length; j++) { if (Math.abs(Bx2-Ax) == exactx[j] && Math.abs(By2-Ay) == exacty[j]) { //console.log("Beyond max safe distance at ",Math.dist(Ax, Ay, Bx2, By2)," to point in warp well"); return 2; } } } // Determine if a point in the warp well beyond the "maximum safe distance" can be reached inexactly // Streu's numbers: // var inexactx = [13,34,42,49,52,55,63,65,81,86,95,98,102,103,126,127,130,132,138,141,149, 150,153,154,155,157,159,162]; // var inexacty = [162,159,157,155,154,153,150,149,141,138,132,130,127,126,103,102,98,95, 86,81,65,63,55,52,49,42,34,13] // Inexact numbers, including Streu's: var inexactx = [13,34,42,49,52,55,63,65,81,86,95,98,102,103,126,127,130,132,138,141,149, 150,153,154,155,157,159,162,121,120,119,122,118,126,127,130,132,138,141,135,140,137,133,149,150,153,154,155,157,158,159,156,162,152,109,110,111,108,112,103,102,98,95,86,81,91,83,88,94,65,63,55,52,49,42,38,34,46,13,58]; var inexacty = [162,159,157,155,154,153,150,149,141,138,132,130,127,126,103,102,98,95, 86,81,65,63,55,52,49,42,34,13,109,110,111,108,112,103,102,98,95,86,81,91, 83,88,94,65,63,55,52,49,42,38,34,46,13,58,121,120,119,122,118,126,127,130, 132,138,141,135,140,137,133,149,150,153,154,155,157,158,159,156,162,152]; for (var i = 0; i < delx.length; i++) { Bx2 = Bx + delx[i]; By2 = By + dely[i]; for (var j = 0; j < inexactx.length; j++) { if (Math.abs(Bx2-Ax) == inexactx[j] && Math.abs(By2-Ay) == inexacty[j]) { //console.log("Beyond max safe distance at ",Math.dist(Ax, Ay, Bx2, By2)," to point in warp well"); return 3; // Connection can be reached by "inexact" movement } } } //console.log("Connection not made for a distance of ",Math.dist(Ax, Ay, Bx, By)); return 0; //console.log("Rendered connections" ); }, renderHypConnections: function() { // console.log("Rendering connections" ); var ctx = vgap.map.ctx ctx.beginPath(); for (var i = 0; i < vgap.planets.length; i++) { var planetA = vgap.planets[i]; for (var j = i + 1; j < vgap.planets.length; j++) { var planetB = vgap.planets[j]; var dist = Math.dist(planetA.x, planetA.y, planetB.x, planetB.y); var connection = false; if (dist >= 337 && dist <= 363) { if (dist >= 340 && dist <= 360) { // This should always be a valid connection connection = true; } else { // This will be close, so check individual points in warp well connection = vgap.plugins["GravConnect"].checkHypConnection(planetA.x, planetA.y, planetB.x, planetB.y); } } if (connection) { ctx.moveTo(vgap.map.screenX(planetA.x), vgap.map.screenY(planetA.y)); ctx.lineTo(vgap.map.screenX(planetB.x), vgap.map.screenY(planetB.y)); } } } ctx.closePath(); ctx.strokeStyle = "#8FBC8F"; ctx.lineWidth = 0.5; // finer line weight suggested by McNimble ctx.stroke(); ctx.lineWidth = 1; // suggested by McNimble //console.log("Rendered connections" ); }, checkHypConnection: function(Ax,Ay,Bx,By) { // console.log("Rendering Hyp connections" ); // Determine if a point in the warp well can be jumped to to reach the planet var Bx2, By2; for (var i = -2; i < 2; i++) { for (var j = -2; j < 2; j++) { if (Math.abs(i) !=2) if (Math.abs(j) !=2) continue; // skip inner pixels Bx2 = Bx + i; By2 = By + j; var dist = Math.dist(Ax, Ay, Bx2, By2); if (dist >= 340 && dist <= 360) { //console.log("Hyp Connection made for a distance of ",Math.dist(Ax, Ay, Bx, By)); return true; } } } //console.log("Hyp Connection not made for a distance of ",Math.dist(Ax, Ay, Bx, By)); return false; //console.log("Rendered Hyp connections" ); }, renderW9Connections: function() { // console.log("Rendering connections" ); var conn1 = []; // "normal" connections var conn2 = []; // hidden connections var conn3 = []; // inexact connections for (var i = 0; i < vgap.planets.length; i++) { var planetA = vgap.planets[i]; for (var j = i + 1; j < vgap.planets.length; j++) { var planetB = vgap.planets[j]; var dist = Math.dist(planetA.x, planetA.y, planetB.x, planetB.y); var connection = 0; if (dist <= 84.57) { if (dist <= 83.5) { // This should always be a valid connection // This is the connection reported by the Nu client connection = 1; // Basic "Nu client" connection } else { // This will be close, so check individual points in warp well connection = vgap.plugins["GravConnect"].checkW9Connection(planetA.x, planetA.y, planetB.x, planetB.y); } } if (connection == 1) { // console.log("Saving",planetA.x,planetA.y,planetB.x,planetB.y); conn1.push({x1:planetA.x, x2:planetB.x, y1:planetA.y, y2:planetB.y}); // ctx.moveTo(vgap.map.screenX(planetA.x), vgap.map.screenY(planetA.y)); // ctx.lineTo(vgap.map.screenX(planetB.x), vgap.map.screenY(planetB.y)); } else if (connection == 2) { conn2.push({x1:planetA.x, x2:planetB.x, y1:planetA.y, y2:planetB.y}); // ctx.moveTo(vgap.map.screenX(planetA.x), vgap.map.screenY(planetA.y)); // ctx.lineTo(vgap.map.screenX(planetB.x), vgap.map.screenY(planetB.y)); } else if (connection == 3) { conn3.push({x1:planetA.x, x2:planetB.x, y1:planetA.y, y2:planetB.y}); // ctx.moveTo(vgap.map.screenX(planetA.x), vgap.map.screenY(planetA.y)); // ctx.lineTo(vgap.map.screenX(planetB.x), vgap.map.screenY(planetB.y)); } } } // Draw connections var ctx = vgap.map.ctx ctx.beginPath(); for (var i = 0; i < conn1.length; i++) { // console.log("Drawing line",i,conn1[i].x1,conn1[i].y1,conn1[i].x2,conn1[i].y2) ctx.moveTo(vgap.map.screenX(conn1[i].x1), vgap.map.screenY(conn1[i].y1)); ctx.lineTo(vgap.map.screenX(conn1[i].x2), vgap.map.screenY(conn1[i].y2)); } // console.log("conn1.length",conn1.length); // console.log(conn1[1].x1,conn1[1].x2,conn1[1].y1,conn1[1].y2); ctx.closePath(); ctx.strokeStyle = "#666666"; ctx.lineWidth = 1; // suggested by McNimble ctx.stroke(); console.log("Number of hidden connections:",conn2.length) ctx = vgap.map.ctx ctx.beginPath(); for (var i = 0; i < conn2.length; i++) { ctx.moveTo(vgap.map.screenX(conn2[i].x1), vgap.map.screenY(conn2[i].y1)); ctx.lineTo(vgap.map.screenX(conn2[i].x2), vgap.map.screenY(conn2[i].y2)); } ctx.closePath(); ctx.strokeStyle = "#FA8072"; ctx.lineWidth = 1; // suggested by McNimble ctx.stroke(); console.log("Number of inexact connections:",conn3.length) ctx = vgap.map.ctx ctx.beginPath(); for (var i = 0; i < conn3.length; i++) { ctx.moveTo(vgap.map.screenX(conn3[i].x1), vgap.map.screenY(conn3[i].y1)); ctx.lineTo(vgap.map.screenX(conn3[i].x2), vgap.map.screenY(conn3[i].y2)); } ctx.closePath(); ctx.strokeStyle = "#9932CC"; ctx.lineWidth = 1.5; ctx.stroke(); ctx.lineWidth = 1; // suggested by McNimble }, checkW9Connection: function(Ax,Ay,Bx,By) { //console.log("Rendering connections" ); // Determine if a point in the warp well is within the "maximum safe distance" var delx = [3.0,2.0,0,-2.0,-3.0,-2.0,0,2.0]; var dely = [0,2.0,3.0,2.0,0,-2.0,-3.0,-2.0]; var Bx2, By2; for (var i = 0; i < delx.length; i++) { Bx2 = Bx + delx[i]; By2 = By + dely[i]; var dist = Math.dist(Ax, Ay, Bx2, By2); if (dist <= 81.57) { //console.log("Safe distance at ",dist," to point in warp well"); return 2; // Connection can be reached by "safe" movement } } // Determine if a point in the warp well beyond the "maximum safe distance" can be reached exactly var exactx = [48,66]; var exacty = [66,48]; for (var i = 0; i < delx.length; i++) { Bx2 = Bx + delx[i]; By2 = By + dely[i]; for (var j = 0; j < exactx.length; j++) { if (Math.abs(Bx2-Ax) == exactx[j] && Math.abs(By2-Ay) == exacty[j]) { //console.log("Beyond max safe distance at ",Math.dist(Ax, Ay, Bx2, By2)," to point in warp well"); return 2; // Connection can be reached by "exact" movement } } } // Determine if a point in the warp well beyond the "maximum safe distance" can be reached inexactly // Streu's values: // var inexactx = [16, 24, 27, 43, 53, 54, 66, 67, 72, 78, 79, 82]; // var inexacty = [82, 79, 78, 72, 67, 66, 54, 53, 43, 27, 24, 16]; // Expanded values: // 63 52 81.68843247363729 // 64 51 81.83520025025906 // 70 42 81.6333265278342 // 67 47 81.8413098624405 // 77 27 81.59656855530139 // 78 24 81.60882305241266 // 80 16 81.58431221748455 // 69 44 81.83520025025906 // 76 30 81.70679286326198 // 58 58 82.02438661763951 // 59 57 82.03657720797473 var inexactx = [16, 16, 24, 24, 27, 27, 30, 42, 43, 44, 47, 51, 52, 53, 54, 57, 58, 59, 63, 64, 66, 67, 67, 69, 70, 72, 76, 77, 78, 78, 79, 80, 82]; var inexacty = [80, 82, 78, 79, 77, 78, 76, 70, 72, 69, 67, 64, 63, 67, 66, 59, 58, 57, 52, 51, 54, 47, 53, 44, 42, 43, 30, 27, 24, 27, 24, 16, 16]; for (var i = 0; i < delx.length; i++) { Bx2 = Bx + delx[i]; By2 = By + dely[i]; for (var j = 0; j < inexactx.length; j++) { if (Math.abs(Bx2-Ax) == inexactx[j] && Math.abs(By2-Ay) == inexacty[j]) { //console.log("Beyond max safe distance at ",Math.dist(Ax, Ay, Bx2, By2)," to point in warp well"); return 3; // Connection can be reached by "inexact" movement } } } //console.log("Connection not made for a distance of ",Math.dist(Ax, Ay, Bx, By)); return 0; //console.log("Rendered connections" ); }, }; // register your plugin with NU vgap.registerPlugin(plugin, "GravConnect"); } } //wrapper for injection var script = document.createElement("script"); script.type = "application/javascript"; script.textContent = "(" + wrapper + ")();"; document.body.appendChild(script);