// ==UserScript== // @id ingress-intel-total-conversion@breunigs // @name intel map total conversion // @version 0.6-@@BUILDDATE@@ // @namespace https://github.com/breunigs/ingress-intel-total-conversion // @updateURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/dist/total-conversion-build.user.js // @downloadURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/dist/total-conversion-build.user.js // @description total conversion for the ingress intel map. // @include http://www.ingress.com/intel* // @match http://www.ingress.com/intel* // ==/UserScript== // REPLACE ORIG SITE /////////////////////////////////////////////////// if(document.getElementsByTagName('html')[0].getAttribute('itemscope') != null) throw('Ingress Intel Website is down, not a userscript issue.'); // disable vanilla JS window.onload = function() {}; // rescue user data from original page var scr = document.getElementsByTagName('script'); for(var x in scr) { var s = scr[x]; if(s.src) continue; if(s.type !== 'text/javascript') continue; var d = s.innerHTML.split('\n'); break; } if(!d) { // page doesn’t have a script tag with player information. if(document.getElementById('header_email')) { // however, we are logged in. setTimeout('location.reload();', 10*1000); throw('Page doesn’t have player data, but you are logged in. Reloading in 10s.'); } // FIXME: handle nia takedown in progress throw('Couldn’t retrieve player data. Are you logged in?'); } for(var i = 0; i < d.length; i++) { if(!d[i].match('var PLAYER = ')) continue; eval(d[i].match(/^var /, 'window.')); break; } // player information is now available in a hash like this: // window.PLAYER = {"ap": "123", "energy": 123, "available_invites": 123, "nickname": "somenick", "team": "ALIENS||RESISTANCE"}; var ir = window.internalResources || []; var mainstyle = 'http://breunigs.github.com/ingress-intel-total-conversion/style.css?@@BUILDDATE@@'; var smartphone = 'http://breunigs.github.com/ingress-intel-total-conversion/smartphone.css?@@BUILDDATE@@'; var leaflet = 'http://cdn.leafletjs.com/leaflet-0.5/leaflet.css'; var coda = 'http://fonts.googleapis.com/css?family=Coda'; // remove complete page. We only wanted the user-data and the page’s // security context so we can access the API easily. Setup as much as // possible without requiring scripts. document.getElementsByTagName('head')[0].innerHTML = '' //~ + '' + 'Ingress Intel Map' + (ir.indexOf('mainstyle') === -1 ? '' : '') + (ir.indexOf('leafletcss') === -1 ? '' : '') // this navigator check is also used in code/smartphone.js + (ir.indexOf('smartphonecss') === -1 && navigator.userAgent.match(/Android.*Mobile/) ? '' : '') + (ir.indexOf('codafont') === -1 ? '' : ''); document.getElementsByTagName('body')[0].innerHTML = '' + '
Loading, please wait
' + '' + '' + '' + '' + '
' // enable scrolling for small screens + ' ' + '
' + '
'; // putting everything in a wrapper function that in turn is placed in a // script tag on the website allows us to execute in the site’s context // instead of in the Greasemonkey/Extension/etc. context. function wrapper() { // LEAFLET PREFER CANVAS /////////////////////////////////////////////// // Set to true if Leaflet should draw things using Canvas instead of SVG // Disabled for now because it has several bugs: flickering, constant // CPU usage and it continuously fires the moveend event. L_PREFER_CANVAS = false; // CONFIG OPTIONS //////////////////////////////////////////////////// window.REFRESH = 30; // refresh view every 30s (base time) window.ZOOM_LEVEL_ADJ = 5; // add 5 seconds per zoom level window.REFRESH_GAME_SCORE = 5*60; // refresh game score every 5 minutes window.MAX_IDLE_TIME = 4; // stop updating map after 4min idling window.PRECACHE_PLAYER_NAMES_ZOOM = 17; // zoom level to start pre-resolving player names window.HIDDEN_SCROLLBAR_ASSUMED_WIDTH = 20; window.SIDEBAR_WIDTH = 300; // chat messages are requested for the visible viewport. On high zoom // levels this gets pretty pointless, so request messages in at least a // X km radius. window.CHAT_MIN_RANGE = 6; // this controls how far data is being drawn outside the viewport. Set // it 0 to only draw entities that intersect the current view. A value // of one will render an area twice the size of the viewport (or some- // thing like that, Leaflet doc isn’t too specific). Setting it too low // makes the missing data on move/zoom out more obvious. Setting it too // high causes too many items to be drawn, making drag&drop sluggish. window.VIEWPORT_PAD_RATIO = 0.3; // how many items to request each query window.CHAT_PUBLIC_ITEMS = 200; window.CHAT_FACTION_ITEMS = 50; // how many pixels to the top before requesting new data window.CHAT_REQUEST_SCROLL_TOP = 200; window.CHAT_SHRINKED = 60; // Leaflet will get very slow for MANY items. It’s better to display // only some instead of crashing the browser. window.MAX_DRAWN_PORTALS = 1000; window.MAX_DRAWN_LINKS = 400; window.MAX_DRAWN_FIELDS = 200; // Minimum zoom level resonator will display window.RESONATOR_DISPLAY_ZOOM_LEVEL = 17; window.COLOR_SELECTED_PORTAL = '#f00'; window.COLORS = ['#FFCE00', '#0088FF', '#03FE03']; // none, res, enl window.COLORS_LVL = ['#000', '#FECE5A', '#FFA630', '#FF7315', '#E40000', '#FD2992', '#EB26CD', '#C124E0', '#9627F4']; window.COLORS_MOD = {VERY_RARE: '#F78AF6', RARE: '#AD8AFF', COMMON: '#84FBBD'}; window.OPTIONS_RESONATOR_SELECTED = { color: '#fff', weight: 2, radius: 4}; window.OPTIONS_RESONATOR_NON_SELECTED = { color: '#aaa', weight: 1, radius: 3}; window.OPTIONS_RESONATOR_LINE_SELECTED = {opacity: 0.7, weight: 3}; window.OPTIONS_RESONATOR_LINE_NON_SELECTED = {opacity: 0.25, weight: 2}; // circles around a selected portal that show from where you can hack // it and how far the portal reaches (i.e. how far links may be made // from this portal) window.ACCESS_INDICATOR_COLOR = 'orange'; window.RANGE_INDICATOR_COLOR = 'red' // by how much pixels should the portal range be expanded on mobile // devices. This should make clicking them easier. window.PORTAL_RADIUS_ENLARGE_MOBILE = 5; window.DEFAULT_PORTAL_IMG = 'http://commondatastorage.googleapis.com/ingress/img/default-portal-image.png'; window.NOMINATIM = 'http://nominatim.openstreetmap.org/search?format=json&limit=1&q='; // INGRESS CONSTANTS ///////////////////////////////////////////////// // http://decodeingress.me/2012/11/18/ingress-portal-levels-and-link-range/ var RESO_NRG = [0, 1000, 1500, 2000, 2500, 3000, 4000, 5000, 6000]; var MAX_XM_PER_LEVEL = [0, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000]; var MIN_AP_FOR_LEVEL = [0, 10000, 30000, 70000, 150000, 300000, 600000, 1200000]; var HACK_RANGE = 40; // in meters, max. distance from portal to be able to access it var OCTANTS = ['E', 'NE', 'N', 'NW', 'W', 'SW', 'S', 'SE']; var DESTROY_RESONATOR = 75; //AP for destroying portal var DESTROY_LINK = 187; //AP for destroying link var DESTROY_FIELD = 750; //AP for destroying field var CAPTURE_PORTAL = 500; //AP for capturing a portal var DEPLOY_RESONATOR = 125; //AP for deploying a resonator var COMPLETION_BONUS = 250; //AP for deploying all resonators on portal // OTHER MORE-OR-LESS CONSTANTS ////////////////////////////////////// var TEAM_NONE = 0, TEAM_RES = 1, TEAM_ENL = 2; var TEAM_TO_CSS = ['none', 'res', 'enl']; var TYPE_UNKNOWN = 0, TYPE_PORTAL = 1, TYPE_LINK = 2, TYPE_FIELD = 3, TYPE_PLAYER = 4, TYPE_CHAT = 5, TYPE_RESONATOR = 6; var SLOT_TO_LAT = [0, Math.sqrt(2)/2, 1, Math.sqrt(2)/2, 0, -Math.sqrt(2)/2, -1, -Math.sqrt(2)/2]; var SLOT_TO_LNG = [1, Math.sqrt(2)/2, 0, -Math.sqrt(2)/2, -1, -Math.sqrt(2)/2, 0, Math.sqrt(2)/2]; var EARTH_RADIUS=6378137; var DEG2RAD = Math.PI / 180; // STORAGE /////////////////////////////////////////////////////////// // global variables used for storage. Most likely READ ONLY. Proper // way would be to encapsulate them in an anonymous function and write // getters/setters, but if you are careful enough, this works. var refreshTimeout; var urlPortal = null; window.playersToResolve = []; window.playersInResolving = []; window.selectedPortal = null; window.portalRangeIndicator = null; window.portalAccessIndicator = null; window.mapRunsUserAction = false; var portalsLayers, linksLayer, fieldsLayer; // contain references to all entities shown on the map. These are // automatically kept in sync with the items on *sLayer, so never ever // write to them. window.portals = {}; window.links = {}; window.fields = {}; window.resonators = {}; // plugin framework. Plugins may load earlier than iitc, so don’t // overwrite data if(typeof window.plugin !== 'function') window.plugin = function() {}; @@INJECTHERE@@ } // end of wrapper // inject code into site context var script = document.createElement('script'); script.appendChild(document.createTextNode('('+ wrapper +')();')); (document.body || document.head || document.documentElement).appendChild(script);