// ==UserScript==
// @author blsmit5728
// @id throwrange@blsmit5728
// @name Under-Field Throw Range
// @category Layer
// @version 1.1.2
// @downloadURL https://raw.githubusercontent.com/IITC-CE/Community-plugins/master/dist/blsmit5728/throwrange.user.js
// @updateURL https://raw.githubusercontent.com/IITC-CE/Community-plugins/master/dist/blsmit5728/throwrange.meta.js
// @description Shows under field throw range at 500m
// @match *://intel.ingress.com/*
// @match *://*.ingress.com/mission/*
// @grant none
// ==/UserScript==
/* globals dialog */
function wrapper(plugin_info) {
// Make sure that window.plugin exists. IITC defines it as a no-op function,
// and other plugins assume the same.
if (typeof window.plugin !== "function") window.plugin = function () { };
const KEY_SETTINGS = "FieldThrowrange-settings";
// Use own namespace for plugin
window.plugin.FieldThrowrange = function () { };
const thisPlugin = window.plugin.FieldThrowrange;
// Name of the IITC build for first-party plugins
plugin_info.buildName = "FieldThrowrange";
// Datetime-derived version of the plugin
plugin_info.dateTimeVersion = "20201112000000";
// ID/name of the plugin
plugin_info.pluginId = "FieldThrowrange";
const TIMERS = {};
function createThrottledTimer(name, callback, ms) {
if (TIMERS[name]) clearTimeout(TIMERS[name]);
// throttle if there are several calls to the functions
TIMERS[name] = setTimeout(function () {
delete TIMERS[name];
if (typeof window.requestIdleCallback == "undefined") callback();
// and even now, wait for iddle
else
requestIdleCallback(
function () {
callback();
},
{ timeout: 2000 }
);
}, ms || 100);
}
window.portalFieldThrowrangeIndicator = null;
FieldThrowrangeLayer = null;
dFieldThrowrangeLayerGroup = null;
let lastPortalGuid = null;
map = window.map;
const defaultSettings = {
circleColor: "#800080",
circleWidth: 2,
circleRange: 500
};
let settings = defaultSettings;
function saveSettings() {
createThrottledTimer("saveSettings", function () {
localStorage[KEY_SETTINGS] = JSON.stringify(settings);
});
drawFieldThrowRange(lastPortalGuid);
}
thisPlugin.loadSettings = function () {
const tmp = localStorage[KEY_SETTINGS];
try {
settings = JSON.parse(tmp);
} catch (e) {
// eslint-disable-line no-empty
}
if (!settings.circleWidth) {
settings.circleWidth = "2";
}
if (!settings.circleRange) {
settings.circleRange = 500;
}
}
window.resetSettings = function () {
settings = JSON.parse(JSON.stringify(defaultSettings));
showSettingsDialog();
}
// The entry point for this plugin.
function setup() {
thisPlugin.loadSettings();
window.addHook(
"portalSelected",
window.drawFieldThrowRange
);
FieldThrowrangeLayer = L.layerGroup();
window.addLayerGroup('Under Field Throw Range', FieldThrowrangeLayer, true);
dFieldThrowrangeLayerGroup = L.layerGroup();
const toolbox = document.getElementById("toolbox");
let buttonFieldThrowrange = document.createElement("a");
buttonFieldThrowrange.textContent = "Under Field Throw Range Settings";
buttonFieldThrowrange.title = "Configuration for Under Field Throw Range Plugin";
buttonFieldThrowrange.addEventListener("click", showSettingsDialog);
toolbox.appendChild(buttonFieldThrowrange);
}
thisPlugin.saveToFile = function (text, filename) {
if (typeof text != 'string') {
text = JSON.stringify(text);
}
if (typeof window.saveFile != 'undefined') {
window.saveFile(text, filename, 'application/json');
return;
}
};
thisPlugin.readFromFile = function (callback) {
if (typeof L.FileListLoader != 'undefined') {
L.FileListLoader.loadFiles({ accept: 'application/json' })
.on('load', function (e) {
callback(e.reader.result);
});
return;
}
};
function showSettingsDialog() {
const html =
`
Reset to Defaults
`;
const width = Math.min(screen.availWidth, 420);
const container = dialog({
id: "settings",
width: width + "px",
html: html,
title: "Under Field Throw Range Settings",
});
const div = container[0];
const colorCircleColorPicker = div.querySelector("#colorCircleColor");
colorCircleColorPicker.value = settings.circleColor;
colorCircleColorPicker.addEventListener("change", (e) => {
settings.circleColor = colorCircleColorPicker.value;
saveSettings();
});
const textCircleWidthStr = div.querySelector("#textCircleWidth");
textCircleWidthStr.value = settings.circleWidth;
textCircleWidthStr.addEventListener("change", (e) => {
settings.circleWidth = textCircleWidthStr.value;
saveSettings();
});
const textCircleRangeStr = div.querySelector("#textCircleRange");
textCircleRangeStr.value = settings.circleRange;
textCircleRangeStr.addEventListener("change", (e) => {
settings.circleRange = textCircleRangeStr.value;
saveSettings();
});
};
window.drawFieldThrowRange = function (guid) {
portalFieldThrowrangeIndicator = null;
dFieldThrowrangeLayerGroup.clearLayers();
if (guid) {
if (guid.selectedPortalGuid) {
lastPortalGuid = guid;
p = window.portals[guid.selectedPortalGuid];
if (p) {
const coord = new LatLng(p._latlng.lat, p._latlng.lng);
console.log("[UFTR] ", settings.circleRange);
console.log("[UFTR] ", Number(settings.circleRange));
portalFieldThrowrangeIndicator = L.circle(coord, Number(settings.circleRange),
{ fill: false, color: settings.circleColor, weight: settings.circleWidth, interactive: false }
)
dFieldThrowrangeLayerGroup.addLayer(portalFieldThrowrangeIndicator);
}
updateMap();
} else {
if (FieldThrowrangeLayer.hasLayer(dFieldThrowrangeLayerGroup)) {
FieldThrowrangeLayer.removeLayer(dFieldThrowrangeLayerGroup);
}
}
}
};
setup.info = plugin_info; //add the script info data to the function as a property
// if IITC has already booted, immediately run the 'setup' function
if (window.iitcLoaded) {
setup();
} else {
if (!window.bootPlugins) {
window.bootPlugins = [];
}
window.bootPlugins.push(setup);
}
function updateMap() {
if (!portalFieldThrowrangeIndicator) {
return;
}
const zoom = map.getZoom();
console.log("[UFTR] ", zoom);
if (zoom > 2) {
if (!FieldThrowrangeLayer.hasLayer(dFieldThrowrangeLayerGroup)) {
FieldThrowrangeLayer.addLayer(dFieldThrowrangeLayerGroup);
}
}
}
function LatLng(lat, lng, alt) {
if (isNaN(lat) || isNaN(lng)) {
throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');
}
// @property lat: Number
// Latitude in degrees
this.lat = +lat;
// @property lng: Number
// Longitude in degrees
this.lng = +lng;
// @property alt: Number
// Altitude in meters (optional)
if (alt !== undefined) {
this.alt = +alt;
}
}
LatLng.prototype = {
// @method toString(): String
// Returns a string representation of the point (for debugging purposes).
toString: function (precision) {
return 'LatLng(' +
formatNum(this.lat, precision) + ', ' +
formatNum(this.lng, precision) + ')';
}
};
}
(function () {
const plugin_info = {};
if (typeof GM_info !== 'undefined' && GM_info && GM_info.script) {
plugin_info.script = {
version: GM_info.script.version,
name: GM_info.script.name,
description: GM_info.script.description
};
}
// Greasemonkey. It will be quite hard to debug
if (typeof unsafeWindow != 'undefined' || typeof GM_info == 'undefined' || GM_info.scriptHandler != 'Tampermonkey') {
// inject code into site context
const script = document.createElement('script');
script.appendChild(document.createTextNode('(' + wrapper + ')(' + JSON.stringify(plugin_info) + ');'));
(document.body || document.head || document.documentElement).appendChild(script);
} else {
// Tampermonkey, run code directly
wrapper(plugin_info);
}
})();