Planets.nu - Sensor Range Plugin

Plugin for Planets.nu which allows to visualize the sensor range of ships and planets on the starmap

// ==UserScript==
// @name          Planets.nu - Sensor Range Plugin
// @description   Plugin for Planets.nu which allows to visualize the sensor range of ships and planets on the starmap
// @namespace     kedalion/sensorRange
// @version       0.31
// @date          2014-12-24
// @author        kedalion
// @include       http://planets.nu/*
// @include       http://play.planets.nu/*
// @include       http://test.planets.nu/*
// @resource      userscript https://greasyfork.org/en/scripts/7149-planets-nu-sensor-range-plugin
// @homepage      http://planets.nu/discussion/utility-script-sensor-range-plugin

// ==/UserScript==

/*
Change log:
0.31    Moved script location to Greasyfork.org and added support for Sphere addon [2014-12-24]
0.3     Moved script location to monkeyguts.com [2014-05-30]
0.21    Added support for Dark Sense (created by Arcanix) [2014-04-09] 
0.20 	Fixed a bug which made sensor range include all planets [2013-08-11]
0.19    Change sensor range to ignore Safe Passage [2013-08-02]
0.18    Removed bug causing Firefox to show everything washed out [2013-08-01]
0.17    Added additional enemy sensor range view [2013-07-30]
0.15    Changed the sensor range display to joint area instead of individual circles [2013-07-29]
0.14    Added hotkey 'x' support [2013-07-25]
0.13    Fixed button behavior (time machine) [2013-07-25]
0.12    Minor fixes, ensure settings stay through turn changes (time machine) [2013-07-25]
0.11    Initial release [2013-07-25]
*/

function wrapper () { // wrapper for injection
    
	if (vgap.version < 3.0) {
		console.log("Sensor Range plugin requires at least NU version 3.0. Plugin disabled." );
		return;	
	}
	
	var plugin_version = 0.31;
   
    console.log("Sensor Range plugin version: v" + plugin_version );
	
	
	/*
	 *  Specify your plugin
	 *  You need to have all those methods defined or errors will be thrown. 
	 *  I inserted the print-outs in order to demonstrate when each method is 
	 *  being called. Just comment them out once you know your way around. 
	 *  
	 *  For any access to plugin class variables and methods from inside these
	 *  reserved methods, "vgap.plugins["nameOfMyPlugin"].my_variable" has to be 
	 *  used instead of "this.my_variable". 
	 */
	var sensorRangePlugin = {
			
			/*
			 * processload: executed whenever a turn is loaded: either the current turn or
			 * an older turn through time machine 
			 */
			processload: function() {
				//console.log("ProcessLoad: plugin called.");
				
				//check if plugin data is for current game
				if (vgap.plugins["sensorRangePlugin"].gameid != vgap.gameId) {
					vgap.plugins["sensorRangePlugin"].reset();
				}
			},	
			
			/*
			 * loaddashboard: executed to rebuild the dashboard content after a turn is loaded
			 */
			loaddashboard: function() {
				//console.log("LoadDashboard: plugin called.");
			},

			/*
			 * showdashboard: executed when switching from starmap to dashboard
			 */
			showdashboard: function() {
				//console.log("ShowDashboard: plugin called.");
			},
			
			/*
			 * showsummary: executed when returning to the main screen of the dashboard
			 */
			showsummary: function() {
				//console.log("ShowSummary: plugin called.");
			},
			
			/*
			 * 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() {
				//console.log("LoadMap: plugin called.");
				vgap.plugins["sensorRangePlugin"].reset();
				
				vgap.plugins["sensorRangePlugin"].addMapTool("Sensor Range", "ShowMinerals", "sensorrange", function () { 
					
					if (vgap.plugins["sensorRangePlugin"].enabled) {
						if (vgap.plugins["sensorRangePlugin"].mode == 0) {
							vgap.plugins["sensorRangePlugin"].enabled = false;									
						}
					} else {
						vgap.plugins["sensorRangePlugin"].enabled = true;
					}
					vgap.plugins["sensorRangePlugin"].mode = 0;
					
					vgap.plugins["sensorRangePlugin"].syncButtons();
					vgap.map.draw();	
					
				});
				vgap.plugins["sensorRangePlugin"].addMapTool("MineDetectRange", "ShowMinerals", "minedetectrange", function () {  
					if (vgap.plugins["sensorRangePlugin"].enabled) {
						if (vgap.plugins["sensorRangePlugin"].mode == 1) {
							vgap.plugins["sensorRangePlugin"].enabled = false;							
						}
					} else {
						vgap.plugins["sensorRangePlugin"].enabled = true;
					}
					vgap.plugins["sensorRangePlugin"].mode = 1;
						
					vgap.plugins["sensorRangePlugin"].syncButtons();
					vgap.map.draw();	
					
				});
				
				vgap.plugins["sensorRangePlugin"].addMapTool("EnemySense", "ShowMinerals", "enemysensorrange", function () {  
					if (vgap.plugins["sensorRangePlugin"].enabled) {
						if (vgap.plugins["sensorRangePlugin"].mode == 2) {
							vgap.plugins["sensorRangePlugin"].enabled = false;
						}	
					} else {
						vgap.plugins["sensorRangePlugin"].enabled = true;
					
					}
					vgap.plugins["sensorRangePlugin"].mode = 2;							
					
					vgap.plugins["sensorRangePlugin"].syncButtons();
					vgap.map.draw();	
					
				});
				
				if (vgap.player.raceid == 8) {
                    vgap.plugins["sensorRangePlugin"].addMapTool("Dark Sense", "ShowMinerals", "darksenserange", function () {  
                        if (vgap.plugins["sensorRangePlugin"].enabled) {
                            if (vgap.plugins["sensorRangePlugin"].mode == 3) {
                                vgap.plugins["sensorRangePlugin"].enabled = false;
                            }	
                        } else {
                            vgap.plugins["sensorRangePlugin"].enabled = true;
                        
                        }
                        vgap.plugins["sensorRangePlugin"].mode = 3;							
                        
                        vgap.plugins["sensorRangePlugin"].syncButtons();
                        vgap.map.draw();	
                        
                    });
                }
	
			},
			
			/*
			 * showmap: executed when switching from dashboard to starmap
			 */
			showmap: function() {
				//console.log("ShowMap: plugin called.");
			},
			
			/*
			 * draw: executed on any click or drag on the starmap
			 */			
			draw: function() {
				//console.log("Draw: plugin called.");
								
				if (vgap.plugins["sensorRangePlugin"].enabled) {
								
					if (vgap.plugins["sensorRangePlugin"].mode == 0) {
						var ctx = vgap.map.ctx;
							
						//ctx.clearRect(0, 0, vgap.map.canvas.width, vgap.map.canvas.height);	
						//ctx.globalAlpha = 0.2;
						vgap.plugins["sensorRangePlugin"].showSensorRange();
						//ctx.globalAlpha = 1.0;
						//vgap.plugins["sensorRangePlugin"].drawEssentials(false, ctx, false);					
						
					} else if (vgap.plugins["sensorRangePlugin"].mode == 2) {
						var ctx = vgap.map.ctx;
												
						vgap.plugins["sensorRangePlugin"].showEnemySensorRange();
					} else if (vgap.plugins["sensorRangePlugin"].mode == 3) { 
                        vgap.plugins["sensorRangePlugin"].showDarkSenseRange();
					} else {
						vgap.plugins["sensorRangePlugin"].showMineDetectRange();
					}			
				}
				
			},		
			
			/*
			 * loadplanet: executed a planet is selected on dashboard or starmap
			 */
			loadplanet: function() {
				//console.log("LoadPlanet: plugin called.");
			},
			
			/*
			 * loadstarbase: executed a planet is selected on dashboard or starmap
			 */
			loadstarbase: function() {
				//console.log("LoadStarbase: plugin called.");
			},
			
			/*
			 * loadship: executed a planet is selected on dashboard or starmap
			 */
			loadship: function() {
				//console.log("LoadShip: plugin called.");
			},
			
			version: plugin_version,
            plugin_name: "SensorRangePlugin",			
			enabled: false,
			mode: 0,  //0: range to detect ships and planets, 1: range of minefield detection, 2: Enemy Sensor Range, 3: Dark Sense
			gameid: -1,
			oldClearTools: null,
			canvas_shipscan: null,
			canvas_planetscan: null,

			
			reset: function () {	
				
				//reset plugin settings 			
				this.enabled = false;
				this.mode = 0;
				this.gameid = vgap.gameId;			
								
				//make sure the buttons represent the actual plugin state				
				this.syncButtons();
				
			},
			
			syncButtons: function () {
		
				//make sure the buttons represent the actual plugin state
				if (document.getElementById("sensorrange") != null) {
					var sensor_on = (document.getElementById("sensorrange").className.indexOf("selectedmaptool") != -1);
				
					if ((sensor_on && !this.enabled) || (!sensor_on && this.enabled && this.mode == 0) || (sensor_on && this.enabled && this.mode != 0)) {
						$('#sensorrange').toggleClass("selectedmaptool");
					}				
				}
				
				
				if (document.getElementById("minedetectrange") != null) {
					var mine_on = (document.getElementById("minedetectrange").className.indexOf("selectedmaptool") != -1);
					
					if ((mine_on && !this.enabled) || (!mine_on && this.enabled && this.mode == 1) || (mine_on && this.enabled && this.mode != 1)) {
						$('#minedetectrange').toggleClass("selectedmaptool");
					}	
				}
				
				if (document.getElementById("enemysensorrange") != null) {
					var enemy_on = (document.getElementById("enemysensorrange").className.indexOf("selectedmaptool") != -1);
					
					if ((enemy_on && !this.enabled) || (!enemy_on && this.enabled && this.mode == 2) || (enemy_on && this.enabled && this.mode != 2)) {
						$('#enemysensorrange').toggleClass("selectedmaptool");
					}	
				}
               
                if (document.getElementById("darksenserange") != null) {
					var dark_on = (document.getElementById("darksenserange").className.indexOf("selectedmaptool") != -1);
					
					if ((dark_on && !this.enabled) || (!dark_on && this.enabled && this.mode == 3) || (dark_on && this.enabled && this.mode != 3)) {
						$('#darksenserange').toggleClass("selectedmaptool");
					}	
				}
				
			},
			
			
			
			
			addMapTool: function (text, cls, id, onclick) {
		        
		        $("<li class='" + cls + "' id='" + id + "'>" + text + "</li>").tclick(onclick).appendTo("#MapTools");
		    },

			/**
			 * Determine if the player has an agreement with another player which will give him information.
			 * Requires at least 'share intel' from the other player.
			 * @param 	int id of target player
			 * @return  bool true if player is delivering information
			 */
		 	receiveInfoFrom: function (fromId) {
				var relation = vgap.getRelation(fromId);
				if (relation == null)
					return false;
				return relation.relationfrom >= 3;
			},

		    
			/**
			 * Draw the sensor range circles around own and allied ships and planets. Two different colors are used for
			 * ship and planet scan range. Planetscanrange is omitted if set to infinity (not explore map setting)			 
			 */
			showEnemySensorRange: function () {
				
				if (this.canvas_planetscan == null) {
					this.canvas_planetscan = document.createElement("canvas");
				}
		        this.canvas_planetscan.width = vgap.map.canvas.width;
        		this.canvas_planetscan.height = vgap.map.canvas.height;
		        var ctx_planetscan = this.canvas_planetscan.getContext("2d");
				ctx_planetscan.clearRect(0, 0, vgap.map.canvas.width, vgap.map.canvas.height);	
				
				var color_planetscan = "#FF8000";	
				var alpha_planetscan = 1.0;
				
				if (this.canvas_shipscan == null) {
					this.canvas_shipscan = document.createElement("canvas");
				}
		        this.canvas_shipscan.width = vgap.map.canvas.width;
        		this.canvas_shipscan.height = vgap.map.canvas.height;
		        var ctx_shipscan = this.canvas_shipscan.getContext("2d");
				ctx_shipscan.clearRect(0, 0, vgap.map.canvas.width, vgap.map.canvas.height);
					    		
				var color_shipscan = "#F5D0A9";								
				var alpha_shipscan = 1.0;
									   
				//var ctx = vgap.map.ctx; 
				//ctx.globalAlpha = 0.1;
				
				for (var i = 0; i < vgap.ships.length; i++) {
					var ship = vgap.ships[i];
												        
					//skip ship if owned by player or ally/neutral -> we want enemies
					if (ship.ownerid == vgap.player.id || (vgap.allied(ship.ownerid) && vgap.alliedTo(ship.ownerid))) {
						continue;	
					}

					//draw a circle for planet visibility around each ship
					if (vgap.settings.planetscanrange < 10000) {

						//console.log("ship #" + ship.id + " planet range");
						
						//check if area is visible
						if (vgap.map.isVisible(ship.x, ship.y, vgap.settings.planetscanrange)) {							
													
							//ctx_planetscan.strokeStyle = colorToRGBA(color_planetscan, alpha_planetscan);
							//ctx_planetscan.lineWidth = 2;
							ctx_planetscan.fillStyle = colorToRGBA(color_planetscan, alpha_planetscan);
							ctx_planetscan.beginPath();
							ctx_planetscan.arc(vgap.map.screenX(ship.x), vgap.map.screenY(ship.y), vgap.settings.planetscanrange * vgap.map.zoom, 0, Math.PI * 2, false);
							ctx_planetscan.closePath();
							ctx_planetscan.fill();
							//ctx_planetscan.stroke();									
						}					
					}
					
					//draw a circle for ship visibility around each ship
					
					//check if area is visible
					if (vgap.map.isVisible(ship.x, ship.y, vgap.settings.shipscanrange)) {						
						
						//console.log("ship #" + ship.id + " ship range");
															
						//ctx_shipscan.strokeStyle = colorToRGBA(color_shipscan, alpha_shipscan);
						//ctx_shipscan.lineWidth = 2;
						ctx_shipscan.fillStyle = colorToRGBA(color_shipscan, alpha_shipscan);
						ctx_shipscan.beginPath();
						ctx_shipscan.arc(vgap.map.screenX(ship.x), vgap.map.screenY(ship.y), vgap.settings.shipscanrange * vgap.map.zoom, 0, Math.PI * 2, false);
						ctx_shipscan.closePath();
						ctx_shipscan.fill();
						//ctx_shipscan.stroke();							
					}					
				}
				
				
				for (var i = 0; i < vgap.planets.length; i++) {
					var planet = vgap.planets[i];
												        
					//skip planet if not owned by player or ally/neutral 
					if (planet.ownerid == vgap.player.id || (vgap.allied(planet.ownerid) && vgap.alliedTo(planet.ownerid))) {
						continue;	
					}

					//skip unowned planets
					if (planet.ownerid == 0 ) {
						continue;	
					}
					
					//draw a circle for planet visibility around each ship
					if (vgap.settings.planetscanrange < 10000) {

						//console.log("planet #" + planet.id + " planet range");
						
						//check if area is visible
						if (vgap.map.isVisible(planet.x, planet.y, vgap.settings.planetscanrange)) {							
													
							//ctx_planetscan.strokeStyle = colorToRGBA(color_planetscan, alpha_planetscan);
							//ctx_planetscan.lineWidth = 3;
							ctx_planetscan.fillStyle = colorToRGBA(color_planetscan, alpha_planetscan);
							ctx_planetscan.beginPath();
							ctx_planetscan.arc(vgap.map.screenX(planet.x), vgap.map.screenY(planet.y), vgap.settings.planetscanrange * vgap.map.zoom, 0, Math.PI * 2, false);
							ctx_planetscan.closePath();
							ctx_planetscan.fill();
							//ctx_planetscan.stroke();									
						}					
					}
					
					//draw a circle for ship visibility around each planet
					
					//check if area is visible
					if (vgap.map.isVisible(planet.x, planet.y, vgap.settings.shipscanrange)) {						
						
						//console.log("planet #" + planet.id + " ship range");
						
						
						//ctx_shipscan.strokeStyle = colorToRGBA(color_shipscan, alpha_shipscan);
						//ctx_shipscan.lineWidth = 3;
						ctx_shipscan.fillStyle = colorToRGBA(color_shipscan, alpha_shipscan);
						ctx_shipscan.beginPath();
						ctx_shipscan.arc(vgap.map.screenX(planet.x), vgap.map.screenY(planet.y), vgap.settings.shipscanrange * vgap.map.zoom, 0, Math.PI * 2, false);
						ctx_shipscan.closePath();
						ctx_shipscan.fill();
						//ctx_shipscan.stroke();							
					}					
				}
								
				
				
				vgap.map.ctx.globalAlpha = 0.2;
				
				if ( vgap.settings.planetscanrange == 10000 ) {
					//console.log("shipscan only1");
					vgap.map.ctx.drawImage(this.canvas_shipscan, 0, 0);	
					//console.log("shipscan only2");
				} else if (vgap.settings.shipscanrange > vgap.settings.planetscanrange) {
					//console.log("shipsscan first1");
					ctx_shipscan.drawImage(this.canvas_planetscan, 0, 0);
					vgap.map.ctx.drawImage(this.canvas_shipscan, 0, 0);
					//console.log("shipsscan first2");
					
				} else {
					//console.log("shipsscan last1");
					ctx_planetscan.drawImage(this.canvas_shipscan, 0, 0);
					vgap.map.ctx.drawImage(this.canvas_planetscan, 0, 0);
					//console.log("shipsscan last2");
					
				}				
				vgap.map.ctx.globalAlpha = 1.0;
							    
			}, 
		    
		    
			/**
			 * Draw the sensor range circles around own and allied ships and planets. Two different colors are used for
			 * ship and planet scan range. Planetscanrange is omitted if set to infinity (not explore map setting)			 
			 */
			showSensorRange: function () {
				
				if (this.canvas_planetscan == null) {
					this.canvas_planetscan = document.createElement("canvas");
				}
		        this.canvas_planetscan.width = vgap.map.canvas.width;
        		this.canvas_planetscan.height = vgap.map.canvas.height;
		        var ctx_planetscan = this.canvas_planetscan.getContext("2d");
				ctx_planetscan.clearRect(0, 0, vgap.map.canvas.width, vgap.map.canvas.height);	
				
				var color_planetscan = "#FF8000";	
				var alpha_planetscan = 1.0;
				
				if (this.canvas_shipscan == null) {
					this.canvas_shipscan = document.createElement("canvas");
				}
		        this.canvas_shipscan.width = vgap.map.canvas.width;
        		this.canvas_shipscan.height = vgap.map.canvas.height;
		        var ctx_shipscan = this.canvas_shipscan.getContext("2d");
				ctx_shipscan.clearRect(0, 0, vgap.map.canvas.width, vgap.map.canvas.height);
					    		
				var color_shipscan = "#F5D0A9";								
				var alpha_shipscan = 1.0;
									   
				//var ctx = vgap.map.ctx; 
				//ctx.globalAlpha = 0.1;
				
				for (var i = 0; i < vgap.ships.length; i++) {
					var ship = vgap.ships[i];
												        
					//skip ship if not owned by player or ally
					if (ship.ownerid != vgap.player.id && !this.receiveInfoFrom(ship.ownerid)) { //   (vgap.allied(ship.ownerid) && vgap.alliedTo(ship.ownerid))) {
						continue;	
					}

					//draw a circle for planet visibility around each ship
					if (vgap.settings.planetscanrange < 10000) {

						//console.log("ship #" + ship.id + " planet range");
						
						//check if area is visible
						if (vgap.map.isVisible(ship.x, ship.y, vgap.settings.planetscanrange)) {							
													
							//ctx_planetscan.strokeStyle = colorToRGBA(color_planetscan, alpha_planetscan);
							//ctx_planetscan.lineWidth = 2;
							ctx_planetscan.fillStyle = colorToRGBA(color_planetscan, alpha_planetscan);
							ctx_planetscan.beginPath();
							ctx_planetscan.arc(vgap.map.screenX(ship.x), vgap.map.screenY(ship.y), vgap.settings.planetscanrange * vgap.map.zoom, 0, Math.PI * 2, false);
							ctx_planetscan.closePath();
							ctx_planetscan.fill();
							//ctx_planetscan.stroke();									
						}					
					}
					
					//draw a circle for ship visibility around each ship
					
					//check if area is visible
					if (vgap.map.isVisible(ship.x, ship.y, vgap.settings.shipscanrange)) {						
						
						//console.log("ship #" + ship.id + " ship range");
															
						//ctx_shipscan.strokeStyle = colorToRGBA(color_shipscan, alpha_shipscan);
						//ctx_shipscan.lineWidth = 2;
						ctx_shipscan.fillStyle = colorToRGBA(color_shipscan, alpha_shipscan);
						ctx_shipscan.beginPath();
						ctx_shipscan.arc(vgap.map.screenX(ship.x), vgap.map.screenY(ship.y), vgap.settings.shipscanrange * vgap.map.zoom, 0, Math.PI * 2, false);
						ctx_shipscan.closePath();
						ctx_shipscan.fill();
						//ctx_shipscan.stroke();							
					}					
				}
				
				
				for (var i = 0; i < vgap.planets.length; i++) {
					var planet = vgap.planets[i];
												        
					//skip planet if not owned by player or ally
					if (planet.ownerid != vgap.player.id &&  !this.receiveInfoFrom(planet.ownerid)) { //!(vgap.allied(planet.ownerid) && vgap.alliedTo(planet.ownerid))) {
						continue;	
					}

					//draw a circle for planet visibility around each ship
					if (vgap.settings.planetscanrange < 10000) {

						//console.log("planet #" + planet.id + " planet range");
						
						//check if area is visible
						if (vgap.map.isVisible(planet.x, planet.y, vgap.settings.planetscanrange)) {							
													
							//ctx_planetscan.strokeStyle = colorToRGBA(color_planetscan, alpha_planetscan);
							//ctx_planetscan.lineWidth = 3;
							ctx_planetscan.fillStyle = colorToRGBA(color_planetscan, alpha_planetscan);
							ctx_planetscan.beginPath();
							ctx_planetscan.arc(vgap.map.screenX(planet.x), vgap.map.screenY(planet.y), vgap.settings.planetscanrange * vgap.map.zoom, 0, Math.PI * 2, false);
							ctx_planetscan.closePath();
							ctx_planetscan.fill();
							//ctx_planetscan.stroke();									
						}					
					}
					
					//draw a circle for ship visibility around each planet
					
					//check if area is visible
					if (vgap.map.isVisible(planet.x, planet.y, vgap.settings.shipscanrange)) {						
						
						//console.log("planet #" + planet.id + " ship range");
						
						
						//ctx_shipscan.strokeStyle = colorToRGBA(color_shipscan, alpha_shipscan);
						//ctx_shipscan.lineWidth = 3;
						ctx_shipscan.fillStyle = colorToRGBA(color_shipscan, alpha_shipscan);
						ctx_shipscan.beginPath();
						ctx_shipscan.arc(vgap.map.screenX(planet.x), vgap.map.screenY(planet.y), vgap.settings.shipscanrange * vgap.map.zoom, 0, Math.PI * 2, false);
						ctx_shipscan.closePath();
						ctx_shipscan.fill();
						//ctx_shipscan.stroke();							
					}					
				}
								
				vgap.map.ctx.globalAlpha = 0.2;
			
				if ( vgap.settings.planetscanrange == 10000 ) {
					vgap.map.ctx.drawImage(this.canvas_shipscan, 0, 0);						
				} else if (vgap.settings.shipscanrange > vgap.settings.planetscanrange) {
					ctx_shipscan.drawImage(this.canvas_planetscan, 0, 0);
					vgap.map.ctx.drawImage(this.canvas_shipscan, 0, 0);					
				} else {
					ctx_planetscan.drawImage(this.canvas_shipscan, 0, 0);
					vgap.map.ctx.drawImage(this.canvas_planetscan, 0, 0);					
				}
						
				vgap.map.ctx.globalAlpha = 1.0;
							    
			}, 
			
			/**
			 * Draw the mine detection range circles around own ships that have mission 'mine sweep' set.
			 */
			showMineDetectRange: function () {
				//console.log("show mine detect range");
				
				var ctx = vgap.map.ctx; 
				
				var minefield_detect_range = 200;
				
				for (var i = 0; i < vgap.ships.length; i++) {
					var ship = vgap.ships[i];
												        
					//skip ship if not owned by player 
					if (ship.ownerid != vgap.player.id) { // && !(vgap.allied(ship.ownerid) && vgap.alliedTo(ship.ownerid))) {
						continue;	
					}
					
					var alpha = 0.2;
					var color = "#81F7F3";
					
					//negative ship ids come from sphere addon. Mission changes are only stored in their positive 
					//id counter part
					if (ship.id < 0) {
					   var ship_pos = vgap.getShip(-ship.id);
					   if (ship_pos == null || ship_pos.mission != 1) {
					       continue;
					   }					
					} else {					
					   if (ship.mission != 1) {
					       continue;	
                            //alpha = 0.05;
		                    //color = "#F7FE2E";
					   }
					}
					//draw a circle for ship visibility around each ship
					
					//check if area is visible
					if (vgap.map.isVisible(ship.x, ship.y, minefield_detect_range)) {						
						
						//console.log("ship #" + ship.id + " mine range");
											
						ctx.strokeStyle = colorToRGBA(color, 0.4);
						ctx.lineWidth = 2;
						ctx.fillStyle = colorToRGBA(color, alpha);
						ctx.beginPath();
						ctx.arc(vgap.map.screenX(ship.x), vgap.map.screenY(ship.y), minefield_detect_range * vgap.map.zoom, 0, Math.PI * 2, false);
						ctx.closePath();
						//ctx.fill();
						ctx.stroke();							
					}					
				}				
			},
			
			/**
			 * Draw the dark sense range circles around own ships that have mission 'dark sense' set.
			 */
			showDarkSenseRange: function () {
				//console.log("show dark sense range");
				
                if (vgap.player.raceid != 8) { return; }
                
				var ctx = vgap.map.ctx; 
				
				var darksense_range = 200;
				
				for (var i = 0; i < vgap.ships.length; i++) {
					var ship = vgap.ships[i];	        
					//skip ship if not owned by player 
					if (ship.ownerid != vgap.player.id) { // && !(vgap.allied(ship.ownerid) && vgap.alliedTo(ship.ownerid))) {
						continue;	
					}
					
					var alpha = 0.2;
					var color = "#909090";
					
					//negative ship ids come from sphere addon. Mission changes are only stored in their positive 
					//id counter part
					if (ship.id < 0) {
					   var ship_pos = vgap.getShip(-ship.id);
					   if (ship_pos == null || ship_pos.mission != 8) {
					       continue;
					   }					
					} else {
					   if (ship.mission != 8) {
						  continue;
					   }
                    }
					
					//draw a circle for ship visibility around each ship
					
					//check if area is visible
					if (vgap.map.isVisible(ship.x, ship.y, darksense_range)) {						
						
						//console.log("ship #" + ship.id + " mine range");
											
						ctx.strokeStyle = colorToRGBA(color, 0.4);
						ctx.lineWidth = 2;
						ctx.fillStyle = colorToRGBA(color, alpha);
						ctx.beginPath();
						ctx.arc(vgap.map.screenX(ship.x), vgap.map.screenY(ship.y), darksense_range * vgap.map.zoom, 0, Math.PI * 2, false);
						ctx.closePath();
						//ctx.fill();
						ctx.stroke();							
					}					
				}				
			}
						
	};
	
	// register your plugin with NU
	vgap.registerPlugin(sensorRangePlugin, "sensorRangePlugin");

	
	/**
	 * Overload the clearTools function in order to be able to
	 * disable the sensor range map through hotkey 'x' 
	 */	
	vgap.plugins["sensorRangePlugin"].oldClearTools = vgapMap.prototype.clearTools;
	
	vgapMap.prototype.clearTools = function(result) {
		
		vgap.plugins["sensorRangePlugin"].enabled = false;
		vgap.plugins["sensorRangePlugin"].syncButtons();
		
		//execute the normal clearTools function
		vgap.plugins["sensorRangePlugin"].oldClearTools.apply(this,arguments);
				
	};
	
} //wrapper for injection

var script = document.createElement("script");
script.type = "application/javascript";
script.textContent = "(" + wrapper + ")();";

document.body.appendChild(script);
document.body.removeChild(script);