您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Library for Planets.nu with diverse globally available basic functions to serve other plugins.
当前为
// ==UserScript== // @name Planets.nu - Meteor's Library // @description Library for Planets.nu with diverse globally available basic functions to serve other plugins. // @namespace Planets.nu // @version 1.2 // @grant none // @date 2021-12-29 // @author meteor // @include http://planets.nu/* // @include http://*.planets.nu/* // @include https://planets.nu/* // @include https://*.planets.nu/* // @exclude http://help.planets.nu/* // @exclude https://help.planets.nu/* // @exclude http://profile*.planets.nu/* // @exclude https://profile*.planets.nu/* // ==/UserScript== /* ----------------------------------------------------------------------- Change log: ----------------------------------------------------------------------- */ "use strict"; function wrapper(plugin_version) { xLibrary = new XPlugin("Meteor's Library", "xLibrary", plugin_version, -20180626); xLibrary.setLogEnabled(false); xMapUtils.initialize(); if (!xUtils.isMobileClient()) { var css = "<style type='text/css'>"; css += ".mapbutton {border-radius: 50%; position: absolute; right: 10px; font-size: 13px; color: #fff; width: 30px; height: 30px; cursor: pointer; text-align: center; vertical-align: middle; background-color: #333;}"; css += ".mapbutton.toolactive {box-shadow: 0px 0px 0px 2px #00ffff;}"; css += ".mapbutton:hover {opacity: 1;}"; css += ".mapbutton::before {content: ''; font-family: 'Font Awesome 5 Free'; display: block; position: absolute; left:0; top:0; width: 30px; line-height: 30px; font-size: 14px; font-style: normal; font-variant: normal; text-rendering: auto; font-weight: 900; color: #00ffff; -webkit-font-smoothing: antialiased; text-align: center;}"; css += ".mapbutton::after {content: ''; display:block; position:absolute; left: -10px; top:-10px; width: 50px; height: 50px;}"; css += "#MapControls .mapbutton {position: relative; margin-bottom: 10px;}"; css += "</style>"; $("head:first").append(css); } } function global() { var xLibrary; // ----------------------------------------------------------------------------------------------------------------- function XPlugin(fullName, registerName, version, notetype, minLibraryVersion) { this.name = fullName; this.registerName = registerName; this.version = version; this.notetype = notetype; if ((typeof vgap == 'undefined') || (vgap == null)) { window.alert("Cannot start " + fullName + "!\n\nThe plugin requires vgap."); throw "Cannot start " + fullName + ". vgap not found. Plugin disabled."; } if (vgap.version < 3.0) { throw "Cannot start " + fullName + ". Plugin requires at least NU version 3.0. Plugin disabled."; } if ((typeof minLibraryVersion != 'undefined') && (minLibraryVersion != null) && (xLibrary.getVersion() < minLibraryVersion)) { window.alert("Cannot start " + fullName + "!\n\nThe plugin requires at least " + xLibrary.getName() + " version " + minLibraryVersion + ".\nVersion found: " + xLibrary.getVersion() + "\n\nPlease update the library!"); throw "Cannot start " + fullName + ". Required " + xLibrary.getName() + " version " + minLibraryVersion + " not found. Plugin disabled."; } this.setLogEnabled(false); vgap.registerPlugin(this, registerName); console.log("Registered " + fullName + " (" + registerName + ") version: " + version); } XPlugin.prototype.getName = function() { return this.name; }; XPlugin.prototype.getVersion = function() { return this.version; }; XPlugin.prototype.saveObjectAsNote = function(id, obj) { let note = vgap.getNote(id, this.notetype); if (note == null) { note = vgap.addNote(id, this.notetype); } note.changed = 1; note.body = JSON.stringify(obj); vgap.save(); }; XPlugin.prototype.getObjectFromNote = function(id) { let note = vgap.getNote(id, this.notetype); if ((note == null) || (note.body == "")) { return null; } return JSON.parse(note.body); }; XPlugin.prototype.log = function(message) { if (this.isLogEnabled()) { console.log(this.getName() + "> " + message); } }; XPlugin.prototype.logWarning = function(warning) { console.log(this.getName() + "> Warning: " + warning); }; XPlugin.prototype.throwIllegalArgumentException = function(message) { throw this.getName() + "> IllegalArgumentException: " + message; }; XPlugin.prototype.throwIllegalStateException = function(message) { throw this.getName() + "> IllegalStateException: " + message; }; XPlugin.prototype.setLogEnabled = function(logEnabled) { this.logEnabled = logEnabled; }; XPlugin.prototype.isLogEnabled = function() { return this.logEnabled; }; XPlugin.prototype.processload = function() { }; XPlugin.prototype.loadmap = function() { }; XPlugin.prototype.draw = function() { }; XPlugin.prototype.loaddashboard = function() { }; XPlugin.prototype.showdashboard = function() { }; XPlugin.prototype.showsummary = function() { }; XPlugin.prototype.showmap = function() { }; XPlugin.prototype.loadplanet = function() { }; XPlugin.prototype.loadstarbase = function() { }; XPlugin.prototype.loadship = function() { }; // ----------------------------------------------------------------------------------------------------------------- var xConst = { colRaceId: { UNKNOWN: 0, FEDERATION: 1, LIZARDS: 2, BIRDS: 3, FASCISTS: 4, PRIVATEERS: 5, CYBORG: 6, CRYSTALLINE: 7, EMPIRE: 8, ROBOTS: 9, REBELS: 10, COLONIES: 11, HORWASP: 12 }, natRaceId: { NONE: 0, HUMANOID: 1, BOVINOID: 2, REPTILIAN: 3, AVIAN: 4, AMORPHOUS: 5, INSECTOID: 6, AMPHIBIAN: 7, GHIPSOLDAL: 8, SILICONOID: 9, OTHER_PLAYER: 10 }, natGovernmentId: { UNKNOWN: 0, ANARCHY: 1, PRE_TRIBAL: 2, EARLY_TRIBAL: 3, TRIBAL: 4, FEUDAL: 5, MONARCHY: 6, REPRESENTATIVE: 7, PARTICIPATORY: 8, UNITY: 9, }, sphereDuplication: { NONE: 1, FULL: 2, ALPHA: 3 }, buildingThreshold: { MINE: 200, FACTORY: 100, DEFENSE_POST: 50 }, shipFeature: { CLOAK: 1, DECLOAK: 2, ADVANCED_CLOAK: 3, RADIATION_SHIELDING: 4, GLORY_DEVICE: 5, GRAVITONIC: 6, HYPERJUMP: 7, RAMSCOOP: 8, BIOSCAN: 9, ADVANCED_BIOSCAN: 10, NEBULA_SCANNER: 11, TERRAFORMER: 12, GAMBLING: 13, ALCHEMY: 14, CHUNNEL_INITIATOR: 15, CHUNNEL_TARGET: 16, IMPERIAL_ASSAULT: 17, PLANET_IMMUNITY: 18, SEND_FIGHTERS: 19, RECEIVE_FIGHTERS: 20, CHAMELEON_DEVICE: 21, EMORKS_SPIRIT_BONUS: 22, TIDAL_FORCE_SHIELD: 23, CLOAKED_FIGHTER_BAYS: 24, EDUCATOR: 25, ORE_CONDENSOR: 26, RECLOAK_INTERCEPT: 27, SHIELD_GENERATOR: 28, STEALTH_ARMOR: 29, CHUNNEL_SELF: 30, TEMPORAL_LANCE: 31, CHUNNEL_STABILIZER: 32, STARGATE: 33, UNIVERSAL_CHUNNEL_TARGET: 34, ELUSIVE: 35, SQUADRON: 36, WEBMINE_IMMUNITY: 37, SUNBURST_DEVICE: 38, MOVE_MINEFIELDS: 39, REPAIR_SHIP: 40, COMMAND_SHIP: 41, TANTRUM_DEVICE: 42 } }; // ----------------------------------------------------------------------------------------------------------------- var xUtils = { cloneShallow: function(object) { if (object == null) { return null; } if (typeof object == "function") { // expectation unclear: exception or return the specified object? xLibrary.throwIllegalArgumentException("The specified object is a function. object = " + getLogString(object, [], 1)); } if (typeof object != "object") { return object; } let result = Object.create(object.constructor.prototype); Object.getOwnPropertyNames(object).forEach(function(propertyName) { result[propertyName] = object[propertyName]; }); return result; }, cloneDeep: function(object) { if (object == null) { return null; } if (typeof object == "function") { // expectation unclear: shallow clone, deep clone (feasible at all?), exception (rather not)? return object; } if (typeof object != "object") { return object; } let result = Object.create(object.constructor.prototype); Object.getOwnPropertyNames(object).forEach(function(propertyName) { result[propertyName] = xUtils.cloneDeep(object[propertyName]); }); return result; }, assume: function(object, properties) { let result = Object.create(object); Object.getOwnPropertyNames(properties).forEach(function(propertyName) { result[propertyName] = properties[propertyName]; }); return result; }, update: function(object, properties) { Object.getOwnPropertyNames(properties).forEach(function(propertyName) { object[propertyName] = properties[propertyName]; }); }, getLogString: function(object, arExcludedPropertyNames, maxRecursionDepth) { let getLogStringImpl = function(object, arObjectsSeen, arExcludedPropertyNames, maxRecursionDepth) { let str = object.constructor.name + "["; let isFirst = true; for ( let propertyName in object) { let propertyValue = object[propertyName]; if (!(propertyValue instanceof Function)) { let propertyValueStr = null; if (propertyValue instanceof Object) { if (arObjectsSeen.includes(propertyValue)) { propertyValueStr = "(cycle)"; } else { arObjectsSeen.push(propertyValue); if ((maxRecursionDepth > 0) && (!arExcludedPropertyNames.includes(propertyName))) { propertyValueStr = getLogStringImpl(propertyValue, arObjectsSeen, arExcludedPropertyNames, maxRecursionDepth - 1); } else { propertyValueStr = object.constructor.name + "[...]"; } } } else { propertyValueStr = arExcludedPropertyNames.includes(propertyName) ? "..." : propertyValue; } if (isFirst) { isFirst = false; } else { str += ", "; } str += propertyName + " = " + propertyValueStr; } } str += "]"; return str; }; let arObjectsSeen = []; arObjectsSeen.push(object); if (!arExcludedPropertyNames) { arExcludedPropertyNames = []; } if (maxRecursionDepth == undefined || maxRecursionDepth == null || maxRecursionDepth < 0) { maxRecursionDepth = Infinity; } return getLogStringImpl(object, arObjectsSeen, arExcludedPropertyNames, maxRecursionDepth); }, isMobileClient: function() { return (vgap.version >= 4.0); }, hasNatives: function(planet) { return planet.nativetype > 0; }, getMaxColPop: function(planet) { let oldPlanet = vgap.planetScreen.planet; vgap.planetScreen.planet = planet; let maxCol = vgap.planetScreen.maxPop(false); vgap.planetScreen.planet = oldPlanet; return maxCol; }, getMaxNatPop: function(planet) { if (!this.hasNatives(planet)) { return 0; } if (planet.nativetype == xConst.natRaceId.SILICONOID) { return planet.temp * 1000; } return Math.round(Math.sin(3.14 * (100 - planet.temp) / 100) * 150000); }, getNativeTaxRatio: function(planet) { let oldPlanet = vgap.planetScreen.planet; vgap.planetScreen.planet = this.assume(planet, { clans: 1, nativetaxrate: 100 }); let nativeTaxRatio = vgap.planetScreen.nativeTaxAmount(); vgap.planetScreen.planet = oldPlanet; return nativeTaxRatio; }, getMinColsForBuildings: function(countBuildings, buildingType) { if (countBuildings <= buildingType) { return countBuildings; } return buildingType + ((countBuildings - buildingType) * (countBuildings - buildingType)); }, getMaxBuildings: function(planet, buildingThreshold) { if (planet.clans <= buildingThreshold) { return planet.clans; } return Math.floor(buildingThreshold + Math.sqrt(planet.clans - buildingThreshold)); }, createColTaxTable: function(planet) { let oldPlanet = vgap.planetScreen.planet; vgap.planetScreen.planet = planet; let oldColTaxRate = planet.colonisttaxrate; let table = []; for (let taxRate = 0; taxRate < 101; taxRate++) { planet.colonisttaxrate = taxRate; let taxAmount = vgap.planetScreen.colonistTaxAmount(); let possibleTaxAmount = taxAmount; let happinessChange = vgap.colonistTaxChange(planet); let happiness = planet.colonisthappypoints + happinessChange; if (happiness > 100) happiness = 100; let absoluteGrowth = vgap.planetScreen.colPopGrowth() * 100; let relativeGrowth = absoluteGrowth / planet.clans; table[taxRate] = { taxRate: taxRate, taxAmount: taxAmount, possibleTaxAmount: possibleTaxAmount, happiness: happiness, happinessChange: happinessChange, absoluteGrowth: absoluteGrowth, relativeGrowth: relativeGrowth }; } planet.colonisttaxrate = oldColTaxRate; vgap.planetScreen.planet = oldPlanet; return table; }, createNatTaxTable: function(planet) { if (!this.hasNatives(planet)) { return null; } let oldPlanet = vgap.planetScreen.planet; vgap.planetScreen.planet = planet; let oldNatTaxRate = planet.nativetaxrate; let table = []; for (let taxRate = 0; taxRate < 101; taxRate++) { planet.nativetaxrate = taxRate; let taxAmount = vgap.planetScreen.nativeTaxAmount(); let possibleTaxAmount = vgap.planetScreen.nativeTaxAmount(true); let happinessChange = vgap.nativeTaxChange(planet); let happiness = planet.nativehappypoints + happinessChange; if (happiness > 100) happiness = 100; let absoluteGrowth = vgap.planetScreen.nativePopGrowth() * 100; let relativeGrowth = absoluteGrowth / planet.nativeclans; table[taxRate] = { taxRate: taxRate, taxAmount: taxAmount, possibleTaxAmount: possibleTaxAmount, happiness: happiness, happinessChange: happinessChange, absoluteGrowth: absoluteGrowth, relativeGrowth: relativeGrowth }; } planet.nativetaxrate = oldNatTaxRate; vgap.planetScreen.planet = oldPlanet; return table; }, getMaxFullCollectableTaxEntry: function(taxTable) { for (let i = taxTable.length - 1; i >= 0; i--) { let entry = taxTable[i]; if (entry.taxAmount == entry.possibleTaxAmount) { return entry; } } return taxTable[0]; }, getMaxTaxEntryByHappinessChange: function(taxTable, happinessChange) { for (let i = taxTable.length - 1; i >= 0; i--) { let entry = taxTable[i]; if (entry.happinessChange >= happinessChange) { return entry; } } return taxTable[0]; }, isSharingIntel: function(playerToId) { let relation = vgap.getRelation(playerToId); if (relation == null) { return false; } return relation.relationto >= 3; }, hasFeature: function(ship, feature) { switch (feature) { case xConst.shipFeature.CLOAK: { let hull = vgap.getHull(ship.hullid); return hull.cancloak; } case xConst.shipFeature.DECLOAK: { return (ship.hullid == 7); } case xConst.shipFeature.ADVANCED_CLOAK: { return ((ship.hullid == 29) || (ship.hullid == 31) || (ship.hullid == 1047) || (ship.hullid == 3033)); } case xConst.shipFeature.RADIATION_SHIELDING: { // TODO: untested: 107 ore condensor from client code (docu doesn't say it) return ((ship.hullid == 6) || (ship.hullid == 33) || (ship.hullid == 34) || (ship.hullid == 35) || (ship.hullid == 36) || (ship.hullid == 37) || (ship.hullid == 38) || (ship.hullid == 39) || (ship.hullid == 40) || (ship.hullid == 41) || (ship.hullid == 68) || (ship.hullid == 93) || (ship.hullid == 107) || (ship.hullid == 120) || (ship.hullid == 1006) || (ship.hullid == 1033) || (ship.hullid == 1034) || (ship.hullid == 1038) || (ship.hullid == 1039) || (ship.hullid == 1041) || (ship.hullid == 1068) || (ship.hullid == 1093) || (ship.hullid == 2006) || (ship.hullid == 2033) || (ship.hullid == 2038) || (ship.hullid == 3033)); } case xConst.shipFeature.GLORY_DEVICE: { return ((ship.hullid == 39) || (ship.hullid == 41) || (ship.hullid == 1034) || (ship.hullid == 1039) || (ship.hullid == 1041)); } case xConst.shipFeature.GRAVITONIC: { return ((ship.hullid == 44) || (ship.hullid == 45) || (ship.hullid == 46)); } case xConst.shipFeature.HYPERJUMP: { return ((ship.hullid == 51) || (ship.hullid == 77) || (ship.hullid == 87) || (ship.hullid == 110)); } case xConst.shipFeature.RAMSCOOP: { return (ship.hullid == 96); } case xConst.shipFeature.BIOSCAN: { return ((ship.hullid == 9) || (ship.hullid == 84) || (ship.hullid == 96) || (ship.hullid == 1084)); } case xConst.shipFeature.ADVANCED_BIOSCAN: { return ((ship.hullid == 84) || (ship.hullid == 1084)); } case xConst.shipFeature.NEBULA_SCANNER: { return ((ship.hullid == 27) || (ship.hullid == 54) || (ship.hullid == 1054)); } case xConst.shipFeature.TERRAFORMER: { return ((ship.hullid == 3) || (ship.hullid == 8) || (ship.hullid == 64)); } case xConst.shipFeature.GAMBLING: { return (ship.hullid == 42); } case xConst.shipFeature.ALCHEMY: { return ((ship.hullid == 97) || (ship.hullid == 104) || (ship.hullid == 105)); } case xConst.shipFeature.CHUNNEL_INITIATOR: { return ((ship.hullid == 56) || (ship.hullid == 1055)); } case xConst.shipFeature.CHUNNEL_TARGET: { return ((ship.hullid == 56) || (ship.hullid == 108) || (ship.hullid == 114) || (ship.hullid == 1054)); // || (ship.hullid == 51) // B200 can be a target of a B222b, but not general. Add it here or not??? } case xConst.shipFeature.IMPERIAL_ASSAULT: { return (ship.hullid == 69); } case xConst.shipFeature.PLANET_IMMUNITY: { return ((ship.hullid == 69) || (ship.hullid == 1065) || (ship.hullid == 1071) || (ship.hullid == 2065) || (ship.hullid == 2071)); } case xConst.shipFeature.SEND_FIGHTERS: { return (ship.hullid == 70); } case xConst.shipFeature.RECEIVE_FIGHTERS: { return (ship.hullid == 70); } case xConst.shipFeature.CHAMELEON_DEVICE: { return ((ship.hullid == 109) || (ship.hullid == 1023) || (ship.hullid == 1049)); } case xConst.shipFeature.EMORKS_SPIRIT_BONUS: { return (ship.hullid == 112); } case xConst.shipFeature.TIDAL_FORCE_SHIELD: { return (ship.hullid == 112); } case xConst.shipFeature.CLOAKED_FIGHTER_BAYS: { return (ship.hullid == 1047); } case xConst.shipFeature.EDUCATOR: { return (ship.hullid == 106); } case xConst.shipFeature.ORE_CONDENSER: { return (ship.hullid == 107); } case xConst.shipFeature.RECLOAK_INTERCEPT: { return (ship.hullid == 2033); } case xConst.shipFeature.SHIELD_GENERATOR: { return (ship.hullid == 1041); } case xConst.shipFeature.STEALTH_ARMOR: { return ((ship.hullid == 120) || (ship.hullid == 1050)); } case xConst.shipFeature.CHUNNEL_SELF: { return (ship.hullid == 1055); } case xConst.shipFeature.TEMPORAL_LANCE: { return (ship.hullid == 114); } case xConst.shipFeature.CHUNNEL_STABILIZER: { return (ship.hullid == 108); } case xConst.shipFeature.STARGATE: { return (ship.hullid == 108); } case xConst.shipFeature.UNIVERSAL_CHUNNEL_TARGET: { return (ship.hullid == 108); } case xConst.shipFeature.ELUSIVE: { return ((ship.hullid == 1065) || (ship.hullid == 1071) || (ship.hullid == 2065) || (ship.hullid == 2071)); } case xConst.shipFeature.SQUADRON: { return ((ship.hullid == 1065) || (ship.hullid == 1071) || (ship.hullid == 2065) || (ship.hullid == 2071)); } case xConst.shipFeature.WEBMINE_IMMUNITY: { return (ship.hullid == 110); } case xConst.shipFeature.SUNBURST_DEVICE: { return (ship.hullid == 1064); } case xConst.shipFeature.MOVE_MINEFIELDS: { return (ship.hullid == 113); } case xConst.shipFeature.REPAIR_SHIP: { return (ship.hullid == 1090); } case xConst.shipFeature.COMMAND_SHIP: { return (ship.hullid == 1089); } case xConst.shipFeature.TANTRUM_DEVICE: { return (ship.hullid == 111); } } return false; } }; // ################################################################################################################# var xMapUtils = { getMapCenterCoordinates: function() { return this._mapCenterCoordinates; }, getSphereBorderAddition: function() { return this._sphereBorderAddition; }, getMapWidth: function() { return vgap.settings.mapwidth + (vgap.settings.sphere ? 2 * this.getSphereBorderAddition().getWidth() : 0); }, getMapHeight: function() { return vgap.settings.mapheight + (vgap.settings.sphere ? 2 * this.getSphereBorderAddition().getHeight() : 0); }, getMaxCoordinatesRect: function() { let mapWidth = this.getMapWidth() - (vgap.settings.sphere ? 1 : 0); let mapHeight = this.getMapHeight() - (vgap.settings.sphere ? 1 : 0); let mapCenter = this.getMapCenterCoordinates(); let x1 = Math.floor(mapCenter.x - mapWidth / 2); let y1 = Math.floor(mapCenter.y - mapHeight / 2); let x2 = Math.floor(mapCenter.x + mapWidth / 2); let y2 = Math.floor(mapCenter.y + mapHeight / 2); return new XRect(x1, y1, x2, y2); }, getMapBoundingRect: function() { return this.getMaxCoordinatesRect().enlargeXY(0.5, 0.5); }, getSphereDuplicationBoundingRect: function() { return this.getMapBoundingRect().enlargeXY(vgap.accountsettings.sphereduplicate, vgap.accountsettings.sphereduplicate); }, getHeadingXY: function(x1, y1, x2, y2) { return vgap.getHeading(x1, y1, x2, y2); }, getHeading: function(point1, point2) { return vgap.getHeading(point1.x, point1.y, point2.x, point2.y); }, getOneDimensionalSphereDistance: function(c1, c2, sphereSize) { let dist = Math.abs(c1 - c2); if (vgap.settings.sphere) { while (dist > (sphereSize / 2)) { dist = Math.abs(dist - sphereSize); } } return dist; }, getSphereDistanceXY: function(x1, y1, x2, y2) { let xDiff = this.getOneDimensionalSphereDistance(x1, x2, this.getMapWidth()); let yDiff = this.getOneDimensionalSphereDistance(y1, y2, this.getMapHeight()); return Math.sqrt((xDiff * xDiff) + (yDiff * yDiff)); }, getSphereDistance: function(pointlikeObject1, pointlikeObject2) { return this.getSphereDistanceXY(pointlikeObject1.x, pointlikeObject1.y, pointlikeObject2.x, pointlikeObject2.y); }, screenX: function(x) { return Math.round((x - vgap.map.canvas.x) * vgap.map.zoom) + 0.5; }, screenY: function(y) { return vgap.map.canvas.height - (Math.round((y - vgap.map.canvas.y) * vgap.map.zoom) + 0.5); }, hasNebulas: function() { return (vgap.nebulas && (vgap.nebulas.length > 0)); }, getNebulaVisibilityFromIntensity: function(nebulaIntensity) { return Math.round(4000 / (nebulaIntensity + 1)); }, getNebulaVisibility: function(point) { let intensity = vgap.getNebulaIntensity(point.x, point.y); return this.getNebulaVisibilityFromIntensity(intensity); }, getNebulaVisibilityXY: function(x, y) { let intensity = this.getNebulaIntensityXY(x, y); return this.getNebulaVisibilityFromIntensity(intensity); }, getNebulaIntensityXY: function(x, y) { let intensity = 0; if (this.hasNebulas()) { for (let i = 0; i < vgap.nebulas.length; i++) { let nebula = vgap.nebulas[i]; if (nebula.id < 0) // sphere duplicated nebula { continue; } let dist = this.getSphereDistanceXY(nebula.x, nebula.y, x, y); if (dist <= nebula.radius) { intensity += Math.ceil(nebula.intensity * (1 - (dist / nebula.radius))); } } } return intensity; }, drawLineSection: function(section, drawParams) { if (section == null) { return; } let ctx = vgap.map.ctx; ctx.strokeStyle = drawParams.strokeStyle; ctx.lineWidth = drawParams.lineWidth; if (!vgap.settings.sphere) { ctx.beginPath(); ctx.moveTo(xMapUtils.screenX(section.x1), xMapUtils.screenY(section.y1)); ctx.lineTo(xMapUtils.screenX(section.x2), xMapUtils.screenY(section.y2)); ctx.closePath(); ctx.stroke(); return; } let mapBoundingRect = this.getMapBoundingRect(); let sphereDuplicationBoundingRect = this.getSphereDuplicationBoundingRect(); let mapWidth = mapBoundingRect.getWidth(); let mapHeight = mapBoundingRect.getHeight(); let sphereClipRects = []; let delta = XPoint.minDistance(); sphereClipRects.push(new XRect(sphereDuplicationBoundingRect.left, sphereDuplicationBoundingRect.bottom, mapBoundingRect.left - delta, sphereDuplicationBoundingRect.top)); sphereClipRects.push(new XRect(mapBoundingRect.right + delta, sphereDuplicationBoundingRect.bottom, sphereDuplicationBoundingRect.right, sphereDuplicationBoundingRect.top)); sphereClipRects.push(new XRect(mapBoundingRect.left, mapBoundingRect.top + delta, mapBoundingRect.right, sphereDuplicationBoundingRect.top)); sphereClipRects.push(new XRect(mapBoundingRect.left, sphereDuplicationBoundingRect.bottom, mapBoundingRect.right, mapBoundingRect.bottom - delta)); let collectSections = function(section, normalSections, sphereSections) { let clippedSection = section.clip(mapBoundingRect); if (clippedSection) { normalSections.push(clippedSection); } if (vgap.settings.sphere) { for (let i = 0; i < sphereClipRects.length; i++) { clippedSection = section.clip(sphereClipRects[i]); if (clippedSection) { sphereSections.push(clippedSection); } } } }; let normalSections = []; let sphereSections = []; collectSections(section, normalSections, sphereSections); if (vgap.settings.sphere) { collectSections(section.offsetXY(-mapWidth, -mapHeight), normalSections, sphereSections); collectSections(section.offsetXY(-mapWidth, 0), normalSections, sphereSections); collectSections(section.offsetXY(-mapWidth, +mapHeight), normalSections, sphereSections); collectSections(section.offsetXY(0, -mapHeight), normalSections, sphereSections); collectSections(section.offsetXY(0, +mapHeight), normalSections, sphereSections); collectSections(section.offsetXY(+mapWidth, -mapHeight), normalSections, sphereSections); collectSections(section.offsetXY(+mapWidth, 0), normalSections, sphereSections); collectSections(section.offsetXY(+mapWidth, +mapHeight), normalSections, sphereSections); } for (let i = 0; i < normalSections.length; i++) { let curSection = normalSections[i]; ctx.beginPath(); ctx.moveTo(xMapUtils.screenX(curSection.x1), xMapUtils.screenY(curSection.y1)); ctx.lineTo(xMapUtils.screenX(curSection.x2), xMapUtils.screenY(curSection.y2)); ctx.closePath(); ctx.stroke(); } if ((drawParams.sphereDuplication == xConst.sphereDuplication.FULL) || (drawParams.sphereDuplication == xConst.sphereDuplication.ALPHA)) { if (drawParams.sphereDuplication == xConst.sphereDuplication.ALPHA) { ctx.strokeStyle = colorToRGBA(drawParams.strokeStyle, 0.5); } for (i = 0; i < sphereSections.length; i++) { curSection = sphereSections[i]; ctx.beginPath(); ctx.moveTo(xMapUtils.screenX(curSection.x1), xMapUtils.screenY(curSection.y1)); ctx.lineTo(xMapUtils.screenX(curSection.x2), xMapUtils.screenY(curSection.y2)); ctx.closePath(); ctx.stroke(); } } }, drawRect: function(rect, drawParams) { if (rect == null) { return; } this.drawLineSection(rect.getLeftSection(), drawParams); this.drawLineSection(rect.getRightSection(), drawParams); this.drawLineSection(rect.getTopSection(), drawParams); this.drawLineSection(rect.getBottomSection(), drawParams); }, addMapTool: function(text, cls, onclick, target) { if (xUtils.isMobileClient()) { vgap.map.addMapTool(text, cls, onclick, target); return; } if (!target || (target == "#MapControls")) { $("<li class='" + cls + "'>" + text + "</li>").tclick(onclick).appendTo("#MapTools"); return; } $("<div class='mapbutton " + cls + "' title='" + text + "'></div>").tclick(function() { if (onclick) onclick(); }).appendTo(target); }, activateToggleMapTools: function(isToggleMapToolsActive) { this._isToggleMapToolsActive = isToggleMapToolsActive; if (isToggleMapToolsActive) { $("#MapToolsMenu").show(); } else { $("#MapToolsMenu").hide(); } }, initialize: function() { this._mapCenterCoordinates = new XPoint(2000, 2000); this._sphereBorderAddition = new XDimension(10, 10); this._isToggleMapToolsActive = true; } }; xMapUtils.oldToggleTools = vgapMap.prototype.toggleTools; vgapMap.prototype.toggleTools = function() { if (!xMapUtils._isToggleMapToolsActive || (typeof xMapUtils.oldToggleTools == 'undefined') || (xMapUtils.oldToggleTools == null)) { return; } xMapUtils.oldToggleTools.apply(this, arguments); }; // ----------------------------------------------------------------------------------------------------------------- const X_POINTS_PER_LIGHTYEAR = 4096; function XPoint(x, y) { this.x = XPoint.roundCoordinate(x); this.y = XPoint.roundCoordinate(y); } XPoint.fromPoint = function(pointlikeObject) { return new XPoint(pointlikeObject.x, pointlikeObject.y); }; XPoint.roundCoordinate = function(c) { return Math.round(c * X_POINTS_PER_LIGHTYEAR) / X_POINTS_PER_LIGHTYEAR; }; XPoint.minDistance = function() { return 1 / X_POINTS_PER_LIGHTYEAR; }; XPoint.prototype.equalsXY = function(x, y) { return ((this.x == XPoint.roundCoordinate(x)) && (this.y == XPoint.roundCoordinate(y))); }; XPoint.prototype.equals = function(pointlikeObject) { if (pointlikeObject == null) { return false; } if (pointlikeObject instanceof XPoint) { return ((this.x == pointlikeObject.x) && (this.y == pointlikeObject.y)); } return this.equalsXY(pointlikeObject.x, pointlikeObject.y); }; XPoint.prototype.getLogString = function() { return "XPoint(" + this.x + ", " + this.y + ")"; }; XPoint.prototype.offsetXY = function(dx, dy) { return new XPoint(this.x + dx, this.y + dy); }; // ----------------------------------------------------------------------------------------------------------------- function XDimension(width, height) { this.width = XPoint.roundCoordinate(width); this.height = XPoint.roundCoordinate(height); } XDimension.prototype.equals = function(dimension) { if (dimension == null) { return false; } return (this.width == dimension.width) && (this.height == dimension.height); }; XDimension.prototype.getLogString = function() { return "XDimension(" + this.width + ", " + this.height + ")"; }; XDimension.prototype.getWidth = function() { return this.width; }; XDimension.prototype.getHeight = function() { return this.height; }; // ----------------------------------------------------------------------------------------------------------------- function XRect(x1, y1, x2, y2) { this.left = XPoint.roundCoordinate((x1 < x2) ? x1 : x2); this.bottom = XPoint.roundCoordinate((y1 < y2) ? y1 : y2); this.right = XPoint.roundCoordinate((x1 < x2) ? x2 : x1); this.top = XPoint.roundCoordinate((y1 < y2) ? y2 : y1); } XRect.fromPoints = function(pointlikeObject1, pointlikeObject2) { return new XRect(pointlikeObject1.x, pointlikeObject1.y, pointlikeObject2.x, pointlikeObject2.y); }; XRect.prototype.equals = function(rect) { if (rect == null) { return false; } return ((this.left == rect.left) && (this.bottom == rect.bottom) && (this.right == rect.right) && (this.top == rect.top)); }; XRect.prototype.getLogString = function() { return "XRect(" + this.left + ", " + this.bottom + ", " + this.right + ", " + this.top + ")"; }; XRect.prototype.getWidth = function() { return this.right - this.left; }; XRect.prototype.getHeight = function() { return this.top - this.bottom; }; XRect.prototype.getDimension = function() { return new XDimension(this.getWidth(), this.getHeight()); }; XRect.prototype.getLeftSection = function() { return new XLineSection(this.left, this.bottom, this.left, this.top); }; XRect.prototype.getBottomSection = function() { return new XLineSection(this.left, this.bottom, this.right, this.bottom); }; XRect.prototype.getRightSection = function() { return new XLineSection(this.right, this.bottom, this.right, this.top); }; XRect.prototype.getTopSection = function() { return new XLineSection(this.left, this.top, this.right, this.top); }; XRect.prototype.getLeftBottomPoint = function() { return new XPoint(this.left, this.bottom); }; XRect.prototype.getRightBottomPoint = function() { return new XPoint(this.right, this.bottom); }; XRect.prototype.getLeftTopPoint = function() { return new XPoint(this.left, this.top); }; XRect.prototype.getRightTopPoint = function() { return new XPoint(this.right, this.top); }; XRect.prototype.getCenterPoint = function() { return new XPoint((this.left + this.right) * 0.5, (this.bottom + this.top) * 0.5); }; XRect.prototype.enlargeXY = function(x, y) { return new XRect(this.left - x, this.bottom - y, this.right + x, this.top + y); }; XRect.prototype.enlarge = function(dimension) { return this.enlarge(dimension.width, dimension.height); }; XRect.prototype.containsXY = function(x, y) { return ((x >= this.left) && (x <= this.right) && (y >= this.bottom) && (y <= this.top)); }; XRect.prototype.containsPoint = function(pointlikeObject) { if (pointlikeObject == null) { return false; } return this.containsXY(pointlikeObject.x, pointlikeObject.y); }; // ----------------------------------------------------------------------------------------------------------------- // a*x + b*y = c function XLine(a, b, c) { let a1 = a; let b1 = b; let c1 = c; if (b != 0) { if (b != 1) { a1 = a / b; b1 = 1; c1 = c / b; } } else if (a != 0) { if (a != 1) { a1 = 1; b1 = 0; c1 = c / a; } } else { xLibrary.throwIllegalArgumentException("XLine: Cannot create line. The specified parameters a and b both are 0."); } this.a = a1; this.b = b1; this.c = c1; } XLine.prototype.getLogString = function() { return "XLine(" + this.a + ", " + this.b + ", " + this.c + ")"; }; XLine.fromXY = function(x1, y1, x2, y2) { if ((x1 == x2) && (y1 == y2)) { xLibrary.throwIllegalArgumentException("XLine.fromXY(): Cannot create line. The specified points are identical. points = (" + x1 + ", " + y1 + ")"); } return new XLine(y1 - y2, x2 - x1, x2 * y1 - x1 * y2); }; XLine.fromPoints = function(pointlikeObject1, pointlikeObject2) { return XLine.fromXY(pointlikeObject1.x, pointlikeObject1.y, pointlikeObject2.x, pointlikeObject2.y); }; XLine.getPerpendicularBisector = function(pointlikeObject1, pointlikeObject2) { let x1 = pointlikeObject1.x; let y1 = pointlikeObject1.y; let x2 = pointlikeObject2.x; let y2 = pointlikeObject2.y; if (y1 == y2) { if (x1 == x2) { xLibrary.throwIllegalArgumentException("XLine.getPerpendicularBisector(): Cannot calculate the perpendicular bisector. The specified points are identical. points = (" + x1 + ", " + y1 + ")"); } return new XLine(1, 0, (x1 + x2) / 2); } let a = (x1 - x2) / (y1 - y2); let c = (x1 * x1 - x2 * x2 + y1 * y1 - y2 * y2) / (2 * (y1 - y2)); return new XLine(a, 1, c); }; XLine.prototype.getIntersectionPoint = function(lineOrLineSection) { if (lineOrLineSection instanceof (XLineSection)) { return lineOrLineSection.getIntersectionPoint(this); } let line2 = lineOrLineSection; let a1 = this.a; let b1 = this.b; let c1 = this.c; let a2 = line2.a; let b2 = line2.b; let c2 = line2.c; let d = a1 * b2 - a2 * b1; if (d == 0) // parallel (incl. identical) { return null; } let x = (b2 * c1 - b1 * c2) / d; let y = (a1 * c2 - a2 * c1) / d; return new XPoint(x, y); }; XLine.prototype.isVertical = function() { return (this.b == 0); }; XLine.prototype.isHorizontal = function() { return (this.a == 0); }; XLine.prototype.getPointFromX = function(x) { if (this.b == 0) { return null; } let xNormalized = XPoint.roundCoordinate(x); return new XPoint(xNormalized, (this.c - this.a * xNormalized) / this.b); }; XLine.prototype.getPointFromY = function(y) { if (this.a == 0) { return null; } let yNormalized = XPoint.roundCoordinate(y); return new XPoint((this.c - this.b * yNormalized) / this.a, yNormalized); }; XLine.prototype.getHeading = function() { let heading = xMapUtils.getHeadingXY(0, 0, this.a, this.b) + 90; while (heading >= 180) { heading -= 180; } return heading; }; XLine.prototype.clip = function(rect) { let ip = []; ip.push(rect.getLeftSection().getIntersectionPoint(this)); ip.push(rect.getRightSection().getIntersectionPoint(this)); ip.push(rect.getBottomSection().getIntersectionPoint(this)); ip.push(rect.getTopSection().getIntersectionPoint(this)); let p1 = null; let p2 = null; for (var i = 0; (p1 == null) && (i < ip.length); i++) { p1 = ip[i]; } for (; (p2 == null) && (i < ip.length); i++) { p2 = ip[i]; } if ((p1 == null) || (p2 == null) || p1.equals(p2)) { return null; } return XLineSection.fromPoints(p1, p2); }; // ----------------------------------------------------------------------------------------------------------------- function XLineSection(x1, y1, x2, y2) { this.x1 = XPoint.roundCoordinate(x1); this.y1 = XPoint.roundCoordinate(y1); this.x2 = XPoint.roundCoordinate(x2); this.y2 = XPoint.roundCoordinate(y2); if ((this.x1 == this.x2) && (this.y1 == this.y2)) { xLibrary.throwIllegalArgumentException("XLineSection: Cannot create line section. The specified points are identical. points = (" + this.x1 + ", " + this.y1 + ")"); } } XLineSection.fromPoints = function(pointlikeObject1, pointlikeObject2) { return new XLineSection(pointlikeObject1.x, pointlikeObject1.y, pointlikeObject2.x, pointlikeObject2.y); }; XLineSection.prototype.equals = function(lineSection) { if (lineSection == null) { return false; } return ((this.x1 == lineSection.x1) && (this.y1 == lineSection.y1) && (this.x2 == lineSection.x2) && (this.y2 == lineSection.y2)); }; XLineSection.prototype.getLogString = function() { return "XLineSection(" + this.x1 + ", " + this.y1 + ", " + this.x2 + ", " + this.y2 + ")"; }; XLineSection.prototype.getLine = function() { return XLine.fromXY(this.x1, this.y1, this.x2, this.y2); }; XLineSection.prototype.getBoundingRect = function() { return new XRect(this.x1, this.y1, this.x2, this.y2); }; XLineSection.prototype.isVertical = function() { return (this.x1 == this.x2); }; XLineSection.prototype.isHorizontal = function() { return (this.y1 == this.y2); }; XLineSection.prototype.offsetXY = function(dx, dy) { return new XLineSection(this.x1 + dx, this.y1 + dy, this.x2 + dx, this.y2 + dy); }; XLineSection.prototype.offsetDimension = function(dimension) { return this.offsetXY(dimension.getWidth(), dimension.getHeight()); }; XLineSection.prototype.getIntersectionPoint = function(lineOrLineSection) { let isParamLineSection = (lineOrLineSection instanceof (XLineSection)); let line1 = this.getLine(); let line2 = (isParamLineSection ? lineOrLineSection.getLine() : lineOrLineSection); let point = line1.getIntersectionPoint(line2); if ((point != null) && this.getBoundingRect().containsPoint(point) && (!isParamLineSection || lineOrLineSection.getBoundingRect().containsPoint(point))) { return point; } return null; }; XLineSection.prototype.getCenterPoint = function() { return new XPoint((this.x1 + this.x2) * 0.5, (this.y1 + this.y2) * 0.5); }; XLineSection.prototype.getPointFromX = function(x) { let point = this.getLine().getPointFromX(x); if ((point != null) && this.getBoundingRect().containsPoint(p)) { return point; } return null; }; XLineSection.prototype.getPointFromY = function(y) { let point = this.getLine().getPointFromY(y); if ((point != null) && this.getBoundingRect().containsPoint(p)) { return point; } return null; }; XLineSection.prototype.getHeading = function() { return xMapUtils.getHeadingXY(this.x1, this.y1, this.x2, this.y2); }; XLineSection.prototype.clip = function(rect) { let containsP1 = rect.containsXY(this.x1, this.y1); let containsP2 = rect.containsXY(this.x2, this.y2); if (containsP1 && containsP2) { return this; } let ips = []; ips.push(rect.getLeftSection().getIntersectionPoint(this)); ips.push(rect.getRightSection().getIntersectionPoint(this)); ips.push(rect.getBottomSection().getIntersectionPoint(this)); ips.push(rect.getTopSection().getIntersectionPoint(this)); let ip1 = null; let ip2 = null; for (var i = 0; (ip1 == null) && (i < ips.length); i++) { ip1 = ips[i]; } for (; (ip2 == null) && (i < ips.length); i++) { ip2 = ips[i]; } if (containsP1) { if (!ip1.equalsXY(this.x1, this.y1)) { return new XLineSection(this.x1, this.y1, ip1.x, ip1.y); } if ((ip2 != null) && (!ip2.equalsXY(this.x1, this.y1))) { return new XLineSection(this.x1, this.y1, ip2.x, ip2.y); } return null; } if (containsP2) { if (!ip1.equalsXY(this.x2, this.y2)) { return new XLineSection(ip1.x, ip1.y, this.x2, this.y2); } if ((ip2 != null) && (!ip2.equalsXY(this.x2, this.y2))) { return new XLineSection(ip2.x, ip2.y, this.x2, this.y2); } return null; } if ((ip1 == null) || (ip2 == null) || ip1.equals(ip2)) { return null; } let section = XLineSection.fromPoints(ip1, ip2); if (section.getHeading() == this.getHeading()) { return section; } return XLineSection.fromPoints(ip2, ip1); }; // ----------------------------------------------------------------------------------------------------------------- function XDrawParams() { this.strokeStyle = "#FFFFFF"; this.lineWidth = 1; this.sphereDuplication = xConst.sphereDuplication.ALPHA; } XDrawParams.prototype.getLogString = function() { return "XDrawParams(strokeStyle: " + this.strokeStyle + ", lineWidth: " + this.lineWidth + ", sphereDuplication: " + this.sphereDuplication + ")"; }; XDrawParams.prototype.setStrokeStyle = function(strokeStyle) { this.strokeStyle = strokeStyle; return this; }; XDrawParams.prototype.setLineWidth = function(lineWidth) { this.lineWidth = lineWidth; return this; }; XDrawParams.prototype.setSphereDuplication = function(sphereDuplication) { this.sphereDuplication = sphereDuplication; return this; }; // ----------------------------------------------------------------------------------------------------------------- } let script = document.createElement("script"); script.type = "application/javascript"; let globalText = "" + global; globalText = globalText.substring(globalText.indexOf('{') + 1, globalText.lastIndexOf('}')); script.textContent = globalText + ";(" + wrapper + ")(\"" + GM_info.script.version + "\");"; document.body.appendChild(script); document.body.removeChild(script);