Back to Index Page generated: Jun 26, 2025, 4:38:07 AM

Expansion Galactic Registry

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Shows system information for the current galactic sector. Shows system information for the current galactic sector.
Identifier oolite.oxp.phkb.GalacticRegistry oolite.oxp.phkb.GalacticRegistry
Title Galactic Registry Galactic Registry
Category Ambience Ambience
Author phkb phkb
Version 5.11 5.11
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL http://wiki.alioth.net/index.php/GalCop_Galactic_Registry n/a
Download URL https://wiki.alioth.net/img_auth.php/7/75/GalCopGalacticRegistry_5.11.oxz n/a
License CC-BY-NC-SA 3.0 CC-BY-NC-SA 3.0
File Size n/a
Upload date 1749449967

Documentation

Also read http://wiki.alioth.net/index.php/Galactic%20Registry

readme.txt

GalCop Galactic Registry
By Nick Rogers

With thanks to Okti for his code for the Gal Navy locations.

Overview
========
This OXP aims to provide pilots with data relating to their current sector, and provide tools pilots can use to better understand the galaxy they work in. This expansion adds a new interface screen, the "GalCop galactic registry", which had the following sub-options:

1. Regions: Each sector has a number of galactic regions, and this menu allows pilots to see all named regions and display their location.
2. Spacelanes: There are a number of spacelanes in each section, largely related to trade routes. This menu will list each of the different spacelanes defined in the current galactic sector, and allow you to display each route on the galactic chart.
3. TechLevel: This menu allows pilots to highlight all systems of a particular techlevel, and (if the Advanced Navigational Array is installed) to automatically plot a course to the closest one.
4. Government Types: This menu allows pilots to highlight all systems of government type, and (if the Advanced Navigational Array is installed) to automatically plot a course to the closest one.
5. Economy: This menu allows pilots to highlight all systems of a particular economy, and (if the Advanced Navigational Array is installed) to automatically plot a course to the closest one.
6. Galactic Navy Sector Commands: If you have the GalNavy OXP installed, this option will become available. This will highlight each system that is home to a GalNavy sector command, and (if the Advanced Navigational Array is installed) allow you to automatically plot a course to the closest one.
7. GalCop Sector HQ: This menu allows pilots to highlight the GalCop Sector HQ system in the sector.
8. Full system list: This function will list all systems in the sector. The list can be sorted by name, tech level, government type or economy type. Additionally, two systems can be selected from the list, and then the details of these two systems can be displayed along with a galactic map showing the route between them. 
9. Search registry: This function will take any text input and search all planetary descriptions for that criteria.

For any of the defined sections you have the option of keeping the information displayed on all system maps. When the section is selected, choose the "Set as permanent display" option to turn this on, and "Unset permanent display" to turn it off.

Notes about the 'Search Registry' function
------------------------------------------
The Search registry function will take all entered criteria and find any system where all the criteria are matched to at least one property.

The following properties will be searched:
- Planetary description
- Inhabitants description
- Government description
- Economy description
- Techlevel
- Productivity
- Population 
- Radius (ie Planet radius)

Some examples of search criteria:
"tl8+ ind prod>30000"
    Will find any industrial system with a TL of 8 or greater, and with a productivity of more than 30000.
"feline anarchy pop<3"
    Will find any Anarchy system with feline inhabitants and a population less than 3 billion. In Galaxy 1, there are two systems that will be found for this search: Erbiti and Orrira.
"tl6 tedious"
    Will find any TL6 system with 'tedious' in the planetary description. In Galaxy 1, there is only one system that will be found for this search: Aleusqu.
"frog agri tl7"
    Will find any agricultural-type (poor, mainly, average or rich) TL7 system, inhabited by frogs. In Galaxy 1, there are three systems that will be found for this search: Isinor, Rebia, and Teanrebi.
"human poet|wolf tl8+|industrial"
    Will find any system inhabited by humans or humanoids, AND where either "poet" OR "wolf" is mentioned in the description, AND has either a TL greater than or equal to 8 OR is an industrial-type economy.
    
Installation
============
After installing the OXP no additional set up is required. The "GalCop galactic registry" will be available whenever you dock.

3rd Party interface
===================
It's possible for other OXP's to add their own planet lists to the registry. The following is an example of the interface code:

	var data = {
		name: "My systems",
		markerColor:"whiteColor", 
		markerShape:"MARKER_DIAMOND",
		listType: "unconnected",
		systems:[
            {name:"System list 1", markerColor:"redColor", markerShape:"MARKER_X", systemIDList:[1,2,3,4,5]},
            {name:"System list 2", systemIDList:[6,7,8,9,10]},
            {name:"System list 3", systemIDList:[11,12,13,14,15]}
        ]
	};
    worldScripts.GalacticRegistry.$addCustomSystemList(data);

In new main menu item will be displayed, called "My systems". When you select that item, there will be 3 subsections inside, "System list 1", "System list 2", and "System list 3". "System list 1" has overriden the default markerColor and markerShape settings.

Full data definition:
    name:               The text to appear on the main menu.
    markerColor:        The color specifier to use when marking planets on the map. 
                        If not specified, will default to "whiteColor".
    markerShape:        The shape to use for the planet markers. Must be one of MARKER_X, MARKER_PLUS, MARKER_SQUARE, MARKER_DIAMOND.
                        If not specified, will default to "MARKER_DIAMOND".
    startMarkerShape:   The marker shape to use at the start of the path (path list type only) (defaults to "MARKER_SQUARE")
    endMarkerShape:     The marker shape to use at the end of the path (path list type only) (defaults to "MARKER_DIAMOND")
    listType:           Can be one of the following:
                        unconnected: all systems in the list are unconnected, and will be marked individually on the map. 
                            This is the default setting when "listType" is not specified.
                        region: all systems in the list are connected, and all possible connections between them will be highlighted on the map.
                            The systems themselves will not have markers.
                        path: each system in the list represents one point on a defined path, and only the links between consecutive items will be highlighted on the map.
                            The first and last system in the list will have map markers.
    linkColor:          The color specifier to use when highlighting links on the map. 
                        If not specified, this will default to "greenColor".
    systems:            An array of dictionary items to be shown. The ID's must be in the current galaxy.
                        The dictionary format is:
						name:				The name of this list of systems that will appear on the menu and on the title when selected
						markerColor: 		The color to use for any markers in this list (unconnected list type only) (overrides the parent markerColor)
						markerShape: 		The shape to use for any markers in this list (unconnected list type only) (overrides the parent markerShape)
	  					startMarkerShape: 	The shape to use at the start of a path (for path list types only) (overrides the parent startMarkerShape)
	  					endMarkerShape: 	The shape to use at the end of a path (for path list types only) (overrides the parent endMarkerShape)
						linkColor:			The color specified to be used for all links on the map (path and region list types only) (overrides the parent linkColor)
						systemIDList: 		an array of system ID's that define this list

Note: The list of custom items will be reset whenever the player enters a new galaxy. OXP's will need to re-add their data after a galactic jump. The best time to do this is during the "shipDockedWithStation" world event.

Adding an entry with the same name as an existing item will overwrite existing data with the new data.

License
=======
This OXP is released under the Creative Commons Attribution - Non-Commercial - Share Alike 3.0 license. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/

Galaxy image from http://simpleicon.com/solar_system.html

Discussion
==========
This OXP is discussed at this forum link: http://bb.oolite.space/viewtopic.php?f=4&t=17893

Version History
===============
5.11
- Fixed issue when hint about pressing shortcut key was being displayed in Oolite 1.90, where the key does nothing.

5.10
- Moved all text into descriptions.plist for easier localisation.
- Improved method of turning HUD on/off.

5.9.1
- Fixed bug when searching using < or > with tl.

5.9
- Fixed issues arising from accessing registry while in flight.
- Added ability to search for systems based on radius (ie planet radius).

5.8 
- Fixed issue where second selected system in the Full System List was not showing government, TL or economy in all circumstances.

5.7
- Fixed spelling error in region "The Siege Worlds".

5.6
- Added ability to search for government or economy based on the numeric value (eg gov>2).
- Added ability to search for techlevel using form "tl>8".

5.5
- Added ability to search for systems based on productivity or population.

5.4
- Fixed spelling mistake in code.
- Added features available in Oolite 1.91ff.
- Adjusted brightness of background overlay image, which couldn't be seen in Oolite 1.90.

5.3
- Made compatible with "SW Economy".

5.2
- Fixed some potential referencing errors on mission screens.

5.1
- Spacelane system lists are no longer sorted, so the planet list will be in path order.

5.0
- Re-engineered the internal structures so that all base criteria are now using the same data structures as the custom lists. Custom lists can now have multiple subsets defined within them.
- Custom lists now have the ability to be made a permanent display on the chart.
- Unconnected lists (that is, a series of unconnected planets) can now be made a permanent display on the chart.
- The 'Search registry' function can now do +/- searches on techlevel.
- The 'Search registry' function can now do an "OR" search, using the "|" bar separator. This allows for more complex search queries like "human poet|wolf tl8+|industrial", which translates to "find any system inhabited by humans or humanoids, AND where "poet" OR "wolf" is mentioned in the description, AND has either a TL greater than or equal to 8 OR an industrial-type economy"

4.4
- The 'Search registry' function will now also search government description, economy description, inhabitants description and techlevel. 
- Added a "New search" menu to the Search registry results screen.

4.3
- Bug fixes.

4.2
- Added ability for spacelanes and regions to be shown permanently on any chart.
- Fixed issue where showing the system list of a region would keep the system map visible.
- Moved some menu item text into descriptions.plist.
- Code refactoring and cleanup.

4.1
- Player's current route was always showing the shortest route on the map, even if the quickest route had been selected on the F6 screen.

4.0
- Made compatible with OXP's that change the system.concealment property.
- Added interface to allow 3rd party OXP's to add their own planet lists, regions and paths.

3.3
- When setting a course to a target system, F7 screen will now display the new destination.

3.2
- Added GalCop HQ system to the menu (used by Bounty System OXP, and Email System OXP).
- Added a "search" facility where planetary descriptions can be searched for entered criteria.
- Code refactoring.

3.1
- Removed debug log entries.

3.0
- Added a "Full system list", which lists all system names, and allows sorting by name, tech level, government or economy type. Also has ability to select two systems and show route between the two, as well as other system details.
- Removed redundant header from all system lists.

2.0
- Added ability to view a list of planet names for any given sub-section of the chart.
- Added markers to the start and end of spacelanes.

1.6
- Fixed issue with HUD not becoming visible again after use.

1.5
- Changed "==" comparisons to "===" for performance improvements.
- Fixed issue with the paging for TechLevels.

1.4 
- Updated check for "Allow Big GUI".
- Fixed issue where the interface screen wasn't being added when docking at a new station.

1.3
- Improved menu unsability by auto selecting the next item in the menu.
- Updated screenID's to enable BGS background sounds.
- Renamed background overlay image to prevent possibility of future duplication.
- Toned down overlay image.
- Code refactoring.

1.2
- Removed unnecessary link to "Display Current Course".
- Fixed issue where current course was always showing with the shortest plot.

1.1
- Small tweaks to menu text.
- Smugglers chart markers now removed from various Galactic Registry screens to make the image clearer.

1.0
- Initial release

Equipment

Name Visible Cost [deci-credits] Tech-Level
Advanced Navigational Array Tool no 100 1+

Ships

This expansion declares no ships.

Models

This expansion declares no models.

Scripts

Path
Scripts/galactic_registry.js
"use strict";
this.name = "GalacticRegistry";
this.author = "phkb";
this.copyright = "2017 phkb";
this.description = "Shows various details about the current galactic sector.";
this.license = "CC BY-NC-SA 3.0";

this._disabled = false;
this._regionColor = "greenColor";
this._techLevelColor = "greenColor";
this._governmentColor = ["0.5 0.0 0.7", "0.7 0.5 0.3", "0.0 1.0 0.3", "1.0 0.8 0.1", "1.0 0.0 0.0", "0.1 0.5 1.0", "0.7 0.7 0.7", "0.7 1.0 1.0"];
this._economyColor = ["1.0 1.0 0.0", "0.875 1.0 0.0", "0.75 1.0 0.0", "0.625 1.0 0.0", "0.5 1.0 0.0", "0.375 1.0 0.0", "0.25 1.0 0.0", "0.125 1.0 0.0"];
this._markedRegions = [];
this._markedPlanets = [];
this._permanentRegions = [];
this._permanentLanes = [];
this._explorersClub = false;
this._smugglers = false;
this._menuColor = "orangeColor";
this._itemColor = "yellowColor";
this._disabledColor = "darkGrayColor";
this._altColor = "greenColor";
this._menu = 0;
this._item = 0;
this._page = 0;
this._removeANATool = false;
this._holdDestination = -1;
this._lastChoice = [];
this._spaceLaneStart = -1;
this._spaceLaneEnd = -1;
this._select1 = -1;
this._select2 = -1;
this._selectLast = 2;
this._sortType = 0;
this._search = "";
this._searchMax = false;
this._pageLength = 16;
this._custom = [];
this._permanentChartData = { regions: [], paths: [], systems: [] };
this._setItem;
this._exitTo = "";
this._notice = false;

//-------------------------------------------------------------------------------------------------------------
// Interface to add a custom planet list to the registry
// data is dictionary with the following properties:
//    name: 			The text to appear on the menu.
//    markerColor: 		The default color specifier to use when marking planets on the map. Default is "whiteColor".
//    markerShape: 		The default shape to use for the planet markers. Must be one of MARKER_X, MARKER_PLUS, MARKER_SQUARE, MARKER_DIAMOND.
//	  startMarkerShape: The shape to use at the start of a path (for path list types only)
//	  endMarkerShape: 	The shape to use at the end of a path (for path list types only)
//	  linkColor:		The default color specifier to use for any links defined on the map (path and region list types only)
//    listType:			Can be one of the following: unconnected, path, region
//						unconnected		each system is marked individually, with no connections between them
//						path			each system in the list marks one point of a path, with connections between each
//										only the start and end systems will be marked with this type
//						region			each system is connected to each other system (within 7ly) in the list
//										systems will not be individually marked with this type
//						Note: for "path" and "region", only connections 7ly or less in length will be marked
//    systems: 			An array of dictionary objects that detail the systems to be shown
//						name:				The name of this list of systems that will appear on the menu and on the title when selected
//						markerColor: 		The color to use for any markers in this list (overrides the parent markerColor)
//						markerShape: 		The shape to use for any markers in this list (overrides the parent markerShape)
//	  					startMarkerShape: 	The shape to use at the start of a path (for path list types only) (overrides the parent startMarkerShape)
//	  					endMarkerShape: 	The shape to use at the end of a path (for path list types only) (overrides the parent endMarkerShape)
//						linkColor:			The color specified to be used for all links on the map (path and region list types only) (overrides the parent linkColor)
//						systemIDList: 		an array of system ID's that define this list
//
this.$addCustomSystemList = function $addCustomSystemList(data) {
	this.$addSystemList(data);
}

//-------------------------------------------------------------------------------------------------------------
this.$addSystemList = function $addSystemList(data, coreID) {
	var markers = ["MARKER_X", "MARKER_PLUS", "MARKER_SQUARE", "MARKER_DIAMOND"];
	var listTypes = ["unconnected", "region", "path"];

	if (data.hasOwnProperty("name") === false || data.name === "") {
		throw expandDescription("[gr_error_01]");
	}

	// if the name already exists in the data, remove it so we can re-add it.
	for (var i = this._custom.length - 1; i >= 0; i--) {
		if (this._custom[i].name === data.name) {
			this._custom.splice(i, 1);
			break;
		}
	}

	if (data.hasOwnProperty("listType") === false) data.listType = "unconnected";
	if (listTypes.indexOf(data.listType) === -1) {
		throw expandDescription("[gr_error_02]");
	}

	if (data.hasOwnProperty("markerColor") === false) data.markerColor = "whiteColor";

	if (data.hasOwnProperty("markerShape") === false) data.markerShape = "MARKER_DIAMOND";
	if (markers.indexOf(data.markerShape) === -1) {
		throw expandDescription("[gr_error_03]", { shape: data.markerShape });
	}
	if (data.hasOwnProperty("startMarkerShape") === true) {
		if (markers.indexOf(data.startMarkerShape) === -1) {
			throw expandDescription("[gr_error_04]", { shape: data.startMarkerShape });
		}
	} else {
		if (data.listType === "path") {
			data.startMarkerShape = "MARKER_SQUARE";
		}
	}
	if (data.hasOwnProperty("endMarkerShape") === true) {
		if (markers.indexOf(data.endMarkerShape) === -1) {
			throw expandDescription("[gr_error_05]", { shape: data.endMarkerShape });
		}
	} else {
		if (data.listType === "path") {
			data.endMarkerShape = "MARKER_DIAMOND";
		}
	}

	if (data.hasOwnProperty("systems") === true) {
		var valid = false;
		if (Array.isArray(data.systems)) valid = true; // we're ok
		if (typeof data.systems[0] === "object") {
			if (data.systems[0].hasOwnProperty("name") && data.systems[0].hasOwnProperty("systemIDList")) valid = true
			// give each system data element a (mostly) unique id
			for (var i = 0; i < data.systems.length; i++) {
				data.systems[i].id = data.name + "|" + data.systems[i].name
				if (data.systems[i].hasOwnProperty("linkColor") === false && data.hasOwnProperty("linkColor")) {
					data.systems[i].linkColor = data.linkColor;
				}
				if (data.systems[i].hasOwnProperty("markerShape") === false && data.hasOwnProperty("markerShape")) {
					data.systems[i].markerShape = data.markerShape;
				}
				if (data.systems[i].hasOwnProperty("markerColor") === false && data.hasOwnProperty("markerColor")) {
					data.systems[i].markerColor = data.markerColor;
				}
				if (data.listType == "path") {
					if (data.systems[i].hasOwnProperty("endMarkerShape") === false && data.hasOwnProperty("endMarkerShape")) {
						data.systems[i].endMarkerShape = data.endMarkerShape;
					}
					if (data.systems[i].hasOwnProperty("startMarkerShape") === false && data.hasOwnProperty("startMarkerShape")) {
						data.systems[i].startMarkerShape = data.startMarkerShape;
					}
				}
			}
		}
		if (valid == false) throw expandDescription("[gr_error_06]");
	} else {
		throw expandDescription("[gr_error_07]");
	}
	if (data.systems.length === 0) {
		throw expandDescription("[gr_error_08]");
	}

	if (coreID && coreID > 0) {
		this._custom.splice(coreID - 1, 0, data);
	} else {
		this._custom.push(data);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$addCoreData = function $addCoreData() {

	// regions
	var data = {
		name: "[gr_regions_menu]",
		linkColor: this._regionColor,
		listType: "region",
		systems: []
	};
	var regions = this.$getRegionData();
	for (var i = 0; i < regions.length; i++) {
		data.systems.push({ name: regions[i].name, systemIDList: regions[i].data })
	}
	this.$addSystemList(data, 1);

	// spacelanes
	var data = {
		name: "[gr_spacelanes_menu]",
		listType: "path",
		startMarkerShape: "MARKER_SQUARE",
		endMarkerShape: "MARKER_DIAMOND",
		systems: []
	};
	var lanes = this.$getSpacelanes();
	for (var i = 0; i < lanes.length; i++) {
		data.systems.push({ name: lanes[i].name, markerColor: lanes[i].color, linkColor: lanes[i].color, systemIDList: lanes[i].data })
	}
	this.$addSystemList(data, 2);

	// techlevel
	var data = {
		name: "[gr_techlevel_menu]",
		markerColor: this._techLevelColor,
		markerShape: "MARKER_DIAMOND",
		listType: "unconnected",
		systems: []
	};
	var maxlevel = this.$getMaxTechLevel();
	for (var i = 0; i <= maxlevel; i++) {
		data.systems.push({ name: "TechLevel " + (i + 1), systemIDList: this.$getSystemsByTechLevel(i) });
	}
	this.$addSystemList(data, 3);

	// government
	var data = {
		name: "[gr_govtype_menu]",
		listType: "unconnected",
		systems: []
	};
	for (var i = 0; i <= 7; i++) {
		data.systems.push({ name: this.$governmentDescriptionPlural(i), markerColor: this._governmentColor[i], systemIDList: this.$getSystemsByGovernment(i) })
	}
	this.$addSystemList(data, 4);

	// economy
	var data = {
		name: "[gr_ecotype_menu]",
		listType: "unconnected",
		systems: []
	};
	for (var i = 0; i <= 7; i++) {
		data.systems.push({ name: this.$economyDescription(i), markerColor: this._economyColor[i], systemIDList: this.$getSystemsByEconomy(i) })
	}
	this.$addSystemList(data, 5);

	// galcop hq
	var data = {
		name: "[gr_galcophq_menu]",
		listType: "unconnected",
		systems: [{ name: "[gr_galcophq_menu]", markerColor: "whiteColor", systemIDList: this.$galCopHQSystem() }]
	};
	this.$addSystemList(data, 6);

	// add the galactic navy sector commands for this sector
	if (worldScripts["GalNavy"]) {
		this.$addCustomSystemList({ name: expandDescription("[gr_galnavy_menu]"), systems: [{ name: expandDescription("[gr_galnavy]"), systemIDList: this.$galNavySectorCommands() }] });
	}
}

//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {

	for (var i = 0; i < 60; i++) this._lastChoice.push("");

	if (worldScripts["Explorers Club"]) this._explorersClub = true;
	if (worldScripts["Smugglers_Illegal"]) this._smugglers = true;

	// add a mission screen exception to Xenon UI
	if (worldScripts.XenonUI) {
		var wx = worldScripts.XenonUI;
		wx.$addMissionScreenException("oolite-galacticregistry-regions-map");
		wx.$addMissionScreenException("oolite-galacticregistry-lanes-map");
		wx.$addMissionScreenException("oolite-galacticregistry-techlevel-map");
		wx.$addMissionScreenException("oolite-galacticregistry-government-map");
		wx.$addMissionScreenException("oolite-galacticregistry-economy-map");
		wx.$addMissionScreenException("oolite-galacticregistry-custom-map");
		wx.$addMissionScreenException("oolite-galacticregistry-selected-map");
		wx.$addMissionScreenException("oolite-galacticregistry-galcophq-map");
		wx.$addMissionScreenException("oolite-galacticregistry-searchresults-map");
	}
	// add a mission screen exception to Xenon Redux UI
	if (worldScripts.XenonReduxUI) {
		var wxr = worldScripts.XenonReduxUI;
		wxr.$addMissionScreenException("oolite-galacticregistry-regions-map");
		wxr.$addMissionScreenException("oolite-galacticregistry-lanes-map");
		wxr.$addMissionScreenException("oolite-galacticregistry-techlevel-map");
		wxr.$addMissionScreenException("oolite-galacticregistry-government-map");
		wxr.$addMissionScreenException("oolite-galacticregistry-economy-map");
		wxr.$addMissionScreenException("oolite-galacticregistry-custom-map");
		wxr.$addMissionScreenException("oolite-galacticregistry-selected-map");
		wxr.$addMissionScreenException("oolite-galacticregistry-galcophq-map");
		wxr.$addMissionScreenException("oolite-galacticregistry-searchresults-map");
	}

	if (missionVariables.GalacticRegistry_PermanentRegions) {
		this._permanentRegions = JSON.parse(missionVariables.GalacticRegistry_PermanentRegions);
		delete missionVariables.GalacticRegistry_PermanentRegions;
	}
	if (missionVariables.GalacticRegistry_PermanentLanes) {
		this._permanentLanes = JSON.parse(missionVariables.GalacticRegistry_PermanentLanes);
		delete missionVariables.GalacticRegistry_PermanentLanes;
	}
	this.$removeHistoricPermanentMarkers();

	if (missionVariables.GalacticRegistry_PermenantChartData || missionVariables.GalacticRegistry_PermanentChartData) {
		if (missionVariables.GalacticRegistry_PermenantChartData) {
			this._permanentChartData = JSON.parse(missionVariables.GalacticRegistry_PermenantChartData);
		}
		if (missionVariables.GalacticRegistry_PermanentChartData) {
			this._permanentChartData = JSON.parse(missionVariables.GalacticRegistry_PermanentChartData);
		}
		delete missionVariables.GalacticRegistry_PermenantChartData;
		delete missionVariables.GalacticRegistry_PermanentChartData;
	}

	this.$addCoreData();

	if (oolite.compareVersion("1.91") <= 0) {
		setExtraGuiScreenKeys(this.name, {
			guiScreen: "GUI_SCREEN_LONG_RANGE_CHART",
			registerKeys: { "key1": [{ key: "g", mod1: true }] },
			callback: this.$setupMissionPage.bind(this)
		});
		setExtraGuiScreenKeys(this.name, {
			guiScreen: "GUI_SCREEN_SHORT_RANGE_CHART",
			registerKeys: { "key1": [{ key: "g", mod1: true }] },
			callback: this.$setupMissionPage.bind(this)
		});

		if (worldScripts.ContextualHelp) {
			worldScripts.ContextualHelp.$addHelpTextToGuiScreen(this.name, "GUI_SCREEN_LONG_RANGE_CHART", expandDescription("[gr_help_key]"));
			worldScripts.ContextualHelp.$addHelpTextToGuiScreen(this.name, "GUI_SCREEN_SHORT_RANGE_CHART", expandDescription("[gr_help_key]"));
		}

	} else {
		this._notice = true;
	}
	this.$initInterface(player.ship.dockedStation);
}

//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
	if (this._permanentChartData) {
		missionVariables.GalacticRegistry_PermanentChartData = JSON.stringify(this._permanentChartData);
	} else {
		if (missionVariables.GalacticRegistry_PermanentChartData) delete missionVariables.GalacticRegistry_PermanentChartData;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.shipDockedWithStation = function (station) {
	this.$initInterface(station);
}

//-------------------------------------------------------------------------------------------------------------
this.missionScreenEnded = function () {
	if (player.ship.hudHidden == true) player.ship.hudHidden = false;
}

//-------------------------------------------------------------------------------------------------------------
this.guiScreenChanged = function (to, from) {
	if (from === "GUI_SCREEN_MISSION" && this._screenActive) {
		this._screenActive = false;
		if (this._removeANATool === true) {
			// remove the ANA tool if it was installed
			player.ship.removeEquipment("EQ_ANA_TOOL");
			this._removeANATool = false;
		}
		if (this._holdDestination >= 0) {
			player.ship.targetSystem = this._holdDestination;
			this._holdDestination = -1;
		}
		if (this._smugglers) worldScripts.Smugglers_Illegal.$markSystems();
	}
	// clean up all the marks on the chart
	if (guiScreen != "GUI_SCREEN_MISSION" && guiScreen != "GUI_SCREEN_INTERFACES") {
		this.$removeChartData();
	}
	if ((to == "GUI_SCREEN_LONG_RANGE_CHART" || to == "GUI_SCREEN_SHORT_RANGE_CHART") && this._notice == false) {
		this._notice = true;
		player.consoleMessage(expandDescription("[gr_screen_key]"), 5);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.shipWillEnterWitchspace = function (cause) {
	if (cause === "galactic jump") {
		// clean up any permanent chart markers
		var regions = this._permanentChartData.regions;
		if (regions && regions.length > 0) {
			for (var i = regions.length - 1; i >= 0; i--) {
				this.$removePermanentRegion(regions[i].id);
			}
		}
		var paths = this._permanentChartData.paths;
		if (paths && paths.length > 0) {
			for (var i = paths.length - 1; i >= 0; i--) {
				this.$removePermanentPath(paths[i].id);
			}
		}
		var sys = this._permanentChartData.systems;
		if (sys && sys.length > 0) {
			for (var i = sys.length - 1; i >= 0; i--) {
				this.$removePermanentSystems(sys[i].id);
			}
		}
		this._permanentChartData = { regions: [], paths: [], systems: [] };
	}
}

//-------------------------------------------------------------------------------------------------------------
this.playerEnteredNewGalaxy = function (galaxyNumber) {
	// reset the custom array, so that there is no chance of displaying misleading info
	this._custom.length = 0;
	this.$addCoreData();
}

//-------------------------------------------------------------------------------------------------------------
this.$initInterface = function $initInterface(station) {
	station.setInterface(this.name, {
		title: expandDescription("[gr_screen_title]"),
		category: expandDescription("[gr_screen_category]"),
		summary: expandDescription("[gr_screen_summary]"),
		callback: this.$setupMissionPage.bind(this)
	});
}

//-------------------------------------------------------------------------------------------------------------
this.$setupMissionPage = function $setupMissionPage(key) {
	if (this._explorersClub) this.$hideExplorersClub();
	this._lastChoice = []; // reset all last choices
	this._menu = 0;
	this._page = 0;
	this._exitTo = "GUI_SCREEN_INTERFACES";
	if (key == "key1") this._exitTo = "GUI_SCREEN_SHORT_RANGE_CHART";
	this.$showMissionPage();
}

//-------------------------------------------------------------------------------------------------------------
this.$showMissionPage = function $showMissionPage() {
	function compareName(a, b) {
		if (a.name < b.name) return -1;
		if (a.name > b.name) return 1;
		return 0;
	}
	function compareTL(a, b) {
		if (a.techlevel < b.techlevel) return -1;
		if (a.techlevel > b.techlevel) return 1;
		if (a.name < b.name) return -1;
		if (a.name > b.name) return 1;
		return 0;
	}
	function compareEco(a, b) {
		if (a.economy < b.economy) return -1;
		if (a.economy > b.economy) return 1;
		if (a.name < b.name) return -1;
		if (a.name > b.name) return 1;
		return 0;
	}
	function compareGov(a, b) {
		if (a.government < b.government) return -1;
		if (a.government > b.government) return 1;
		if (a.name < b.name) return -1;
		if (a.name > b.name) return 1;
		return 0;
	}

	if (this._smugglers) this.$hideSmugglers();

	var curChoices = {};
	var p = player.ship;
	var def = "";
	var text = "";
	var pagesize = 8;
	this._pageLength = 16;
	var zeroMap = (worldScripts.ZeroMap ? true : false);

	if (zeroMap && worldScripts.BountySystem_MostWanted && worldScripts.BountySystem_MostWanted._unconcealmentActive === true) {
		if (this._retry) this._retry.stop();
		//log(this.name, "starting retry of missionpage");
		this._retry = new Timer(this, this.$showMissionPage, 0.25, 0);
		return;
	}

	if (zeroMap) worldScripts.ZeroMap._hideGUIScreen();

	var bg = "LONG_RANGE_CHART_SHORTEST";

	// in order to show connecting lines on the map, we need to make sure the player either has the ANA, or if not that, then a piece of equipment that can provide the same service
	if (player.ship.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY") === false) {
		player.ship.awardEquipment("EQ_ANA_TOOL");
		this._removeANATool = true;
		// if we've had to award the ANA tool to display lines between systems, then we don't want to give the player a free route planner
		// turn off the player's destination while we display these screens
		if (player.ship.docked) {
			this._holdDestination = p.targetSystem;
			p.targetSystem = system.ID;
		}
	} else {
		// otherwise, we have the array, so we can add the current course to any display, if it's not already there
		if (p.routeMode === "OPTIMIZED_BY_TIME") bg = "LONG_RANGE_CHART_QUICKEST";
	}

	if (this._removeANATool === false) pagesize = 6;

	if (this.$isBigGuiActive() === false) p.hudHidden = true;
	this._screenActive = true;

	this.$removeChartData();

	switch (this._menu) {
		case 0: // main menu
			{
				text = expandDescription("[gr_screen_welcome]");

				curChoices["11_FULLLIST"] = { text: "[gr_fulllist_menu]", color: this._menuColor };
				curChoices["12_SEARCH"] = { text: "[gr_search_menu]", color: this._menuColor };
				if (this._custom.length > 0) {
					for (var i = 0; i < this._custom.length; i++) {
						var item = this._custom[i];
						curChoices["10_CUSTOM~" + (i < 10 ? "0" : "") + i] = { text: expandDescription(item.name), color: this._menuColor };
					}
				}
				curChoices["99_EXIT"] = { text: "[gr_exit_menu]", color: this._itemColor };

				def = "99_EXIT";

				var opts = {
					screenID: "oolite-galacticregistry-intro-map",
					title: expandDescription("[gr_screen_menu]"),
					allowInterrupt: true,
					overlay: { name: "galreg-solar_system.png", height: 546 },
					exitScreen: this._exitTo,
					choices: curChoices,
					initialChoicesKey: (this._lastChoice[this._menu] != "" ? this._lastChoice[this._menu] : def),
					message: text
				};
				break;
			}
		case 8: // full list
			{
				var syslist = SystemInfo.filteredSystems(this, function (other) { return (!other.concealment || other.concealment <= 100); });
				var rows = 16;

				switch (this._sortType) {
					case 0:
						syslist.sort(compareName);
						break;
					case 1:
						syslist.sort(compareTL);
						break;
					case 2:
						syslist.sort(compareGov);
						break;
					case 3:
						syslist.sort(compareEco);
						break;
				}

				text = this.$padTextRight("", 2.1) +
					this.$padTextRight(expandDescription("[gr_display_name]"), 7) +
					this.$padTextRight(expandDescription("[gr_display_tl]"), 3) +
					this.$padTextRight(expandDescription("[gr_display_government]"), 10) +
					expandDescription("[gr_display_economy]") + "\n";

				var maxpage = Math.ceil(syslist.length / rows);
				var end = ((this._page * rows) + rows);
				var itemcount = 0;
				if (end > syslist.length) end = syslist.length;
				for (var i = (this._page * rows); i < end; i++) {
					curChoices["40_SYSLIST_" + (i < 10 ? "00" : (i < 100 ? "0" : "")) + i + "~" + syslist[i].systemID] =
					{
						text: this.$padTextRight((this._select1 === syslist[i].systemID || this._select2 === syslist[i].systemID ? "•" : ""), 2) +
							this.$padTextRight(syslist[i].name, 7) +
							this.$padTextRight(((!syslist[i].concealment || syslist[i].concealment === 0) ? syslist[i].techlevel + 1 : "??"), 3) +
							this.$padTextRight(((!syslist[i].concealment || syslist[i].concealment === 0) ? this.$governmentDescription(syslist[i].government) : "??"), 10) +
							((!syslist[i].concealment || syslist[i].concealment === 0) ? this.$economyDescription(syslist[i].economy) : "??"),
						alignment: "LEFT", color: this._itemColor
					};
					itemcount += 1;
				}

				curChoices["94_SPACER"] = "";
				for (var i = 0; i < (rows - itemcount); i++) {
					curChoices["94_SPACER_" + i] = "";
				}

				if (maxpage > 1 && this._page < (maxpage - 1)) {
					curChoices["95_NEXT"] = { text: "[gr_nextpage]", color: this._menuColor };
				} else {
					curChoices["95_NEXT"] = { text: "[gr_nextpage]", color: this._disabledColor, unselectable: true };
				}
				if (this._page > 0) {
					curChoices["96_PREV"] = { text: "[gr_prevpage]", color: this._menuColor };
				} else {
					curChoices["96_PREV"] = { text: "[gr_prevpage]", color: this._disabledColor, unselectable: true };
				}

				curChoices["97_1_SORT_NAME"] = { text: "[gr_sort_name]", color: (this._sortType === 0 ? this._disabledColor : this._menuColor), unselectable: (this._sortType === 0 ? true : false) };
				curChoices["97_2_SORT_TL"] = { text: "[gr_sort_tl]", color: (this._sortType === 1 ? this._disabledColor : this._menuColor), unselectable: (this._sortType === 1 ? true : false) };
				curChoices["97_3_SORT_GOV"] = { text: "[gr_sort_gov]", color: (this._sortType === 2 ? this._disabledColor : this._menuColor), unselectable: (this._sortType === 2 ? true : false) };
				curChoices["97_4_SORT_ECO"] = { text: "[gr_sort_eco]", color: (this._sortType === 3 ? this._disabledColor : this._menuColor), unselectable: (this._sortType === 3 ? true : false) };

				var sys1 = "(none)";
				var sys2 = "(none)";
				if (this._select1 >= 0) sys1 = System.systemNameForID(this._select1);
				if (this._selectLast === 2) sys1 = "• " + sys1;
				if (this._select2 >= 0) sys2 = System.systemNameForID(this._select2);
				if (this._selectLast === 1) sys2 = " •" + sys2;

				curChoices["97_9_SELECTED"] = { text: expandDescription("[gr_view_selected]", { select1: sys1, select2: sys2 }), color: (this._select1 === -1 || this._select2 === -1 ? this._disabledColor : this._menuColor), unselectable: (this._select1 === -1 || this._select2 === -1 ? true : false) };

				def = "98_EXIT";
				curChoices["98_EXIT"] = { text: "[gr_exit_menu]", color: this._exitColor };

				var opts = {
					screenID: "oolite-galacticregistry-fulllist-map",
					title: expandDescription("[gr_system_list_title]", { extra: (maxpage > 1 ? expandDescription("[gr_system_list_title_paging]", { page: (this._page + 1), max: maxpage }) : "") }),
					overlay: { name: "galreg-solar_system.png", height: 546 },
					allowInterrupt: true,
					exitScreen: this._exitTo,
					choices: curChoices,
					initialChoicesKey: (this._lastChoice[this._menu] != "" ? this._lastChoice[this._menu] : def),
					message: text
				};
				break;
			}

		case 9: // selected systems
			{
				mission.markSystem({ system: this._select1, markerColor: "greenColor", markerShape: "MARKER_SQUARE", name: "galreg_marked" });
				this._markedPlanets.push(this._select1);
				mission.markSystem({ system: this._select2, markerColor: "cyanColor", markerShape: "MARKER_SQUARE", name: "galreg_marked" });
				this._markedPlanets.push(this._select2);

				var data1 = this.$getSystemData(this._select1);
				var data2 = this.$getSystemData(this._select2);
				var conceal1 = System.infoForSystem(galaxyNumber, this._select1).concealment;
				var conceal2 = System.infoForSystem(galaxyNumber, this._select2).concealment;

				if (p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY") === true) {
					var rt = System.infoForSystem(galaxyNumber, this._select1).routeToSystem(System.infoForSystem(galaxyNumber, this._select2), p.routeMode);
					if (rt && rt.route.length > 1) {
						for (var i = 0; i < rt.route.length - 1; i++) {
							if (rt.route[i] < rt.route[i + 1]) {
								SystemInfo.setInterstellarProperty(galaxyNumber, rt.route[i], rt.route[i + 1], 2, "link_color", "whiteColor", "galreg_region");
								this._markedRegions.push({ id1: rt.route[i], id2: rt.route[i + 1] });
							} else {
								SystemInfo.setInterstellarProperty(galaxyNumber, rt.route[i + 1], rt.route[i], 2, "link_color", "whiteColor", "galreg_region");
								this._markedRegions.push({ id1: rt.route[i + 1], id2: rt.route[i] });
							}
						}
					}
				}

				var govs = new Array();
				for (var i = 0; i < 8; i++)
					govs.push(String.fromCharCode(i));
				this.ecos = new Array();
				for (i = 0; i < 8; i++) {
					this.ecos.push(String.fromCharCode(23 - i));
				}
				var spc = String.fromCharCode(31);

				text = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";

				text += this.$padTextRight(
					data1.name + ((!conceal1 || conceal1 === 0) ? " (" + spc + govs[data1.government] + spc + ecos[data1.economy] + spc + "TL" + spc + data1.techLevel + ")" : ""), 15.5) +
					data2.name + ((!conceal2 || conceal2 === 0) ? " (" + spc + govs[data2.government] + spc + ecos[data2.economy] + spc + "TL" + spc + data2.techLevel + ")" : "") + "\n";
				text += this.$padTextRight(((!conceal1 || conceal1 === 0) ? data1.population + " " + data1.inhabitants : ""), 15.5) +
					((!conceal2 || conceal2 === 0) ? data2.population + " " + data2.inhabitants : "") + "\n";
				text += this.$padTextRight(((!conceal1 || conceal1 === 0) ? expandDescription("[gr_system_data]", { prod: data1.productivity, radius: data1.radius }) : ""), 15.5) +
					((!conceal2 || conceal2 === 0) ? expandDescription("[gr_system_data]", { prod: data2.productivity, radius: data2.radius }) : "") + "\n\n";

				if (rt) {
					text += expandDescription("[gr_system_distance]", { dist: rt.distance.toFixed(1) }) + " / " +
						rt.time.toFixed(1) + " " + (rt.time > 0.95 && rt.time < 1.05 ? expandDescription("[sysdata-route-hours%0]") : expandDescription("[sysdata-route-hours%1]")) + " / " +
						(rt.route.length - 1) + " " + (rt.route.length === 2 ? expandDescription("[sysdata-route-jumps%0]") : expandDescription("[sysdata-route-jumps%1]"));
				} else {
					text += expandDescription("[gr_system_distance]", { dist: System.infoForSystem(galaxyNumber, this._select1).distanceToSystem(System.infoForSystem(galaxyNumber, this._select2)) });
				}

				if (p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY") === true) {
					var rt1 = system.info.routeToSystem(System.infoForSystem(galaxyNumber, this._select1), p.routeMode);
					if (rt1 && rt1.route.length > 1) {
						var rtText = expandDescription("[gr_system_nav_distance]", { dist: rt1.distance.toFixed(1) }) + " / " +
							rt1.time.toFixed(1) + " " + (rt1.time > 0.95 && rt1.time < 1.05 ? expandDescription("[sysdata-route-hours%0]") : expandDescription("[sysdata-route-hours%1]")) + " / " +
							(rt1.route.length - 1) + " " + (rt1.route.length === 2 ? expandDescription("[sysdata-route-jumps%0]") : expandDescription("[sysdata-route-jumps%1]"));
						curChoices["50_SETCOURSE~" + this._select1] = { text: expandDescription("[gr_setcourse3]", { select: System.systemNameForID(this._select1), details: rtText }), color: "greenColor" };
					} else {
						var rtText = expandDescription("[gr_system_nav_distance]", { dist: system.info.distanceToSystem(System.infoForSystem(galaxyNumber, this._select1)).toFixed(1) });
						curChoices["50_SETCOURSE~" + this._select1] = { text: expandDescription("[gr_nocourse]", { select: System.systemNameForID(this._select1), details: rtText }), color: "greenColor", unselectable: true };
					}
					var rt2 = system.info.routeToSystem(System.infoForSystem(galaxyNumber, this._select2), p.routeMode);
					if (rt2 && rt2.route.length > 1) {
						var rtText = expandDescription("[gr_system_nav_distance]", { dist: rt2.distance.toFixed(1) }) + " / " +
							rt2.time.toFixed(1) + " " + (rt2.time > 0.95 && rt2.time < 1.05 ? expandDescription("[sysdata-route-hours%0]") : expandDescription("[sysdata-route-hours%1]")) + " / " +
							(rt2.route.length - 1) + " " + (rt2.route.length === 2 ? expandDescription("[sysdata-route-jumps%0]") : expandDescription("[sysdata-route-jumps%1]"));
						curChoices["50_SETCOURSE~" + this._select2] = { text: expandDescription("[gr_setcourse3]", { select: System.systemNameForID(this._select2), details: rtText }), color: "cyanColor" };
					} else {
						var rtText = expandDescription("[gr_system_nav_distance]", { dist: system.info.distanceToSystem(System.infoForSystem(galaxyNumber, this._select2)).toFixed(1) });
						curChoices["50_SETCOURSE~" + this._select2] = { text: expandDescription("[gr_nocourse]", { select: System.systemNameForID(this._select2), details: rtText }), color: "cyanColor", unselectable: true };
					}
				}

				curChoices["97_EXIT"] = { text: "[gr_exit_menu]", color: this._itemColor };
				def = "97_EXIT";

				var opts = {
					screenID: "oolite-galacticregistry-selected-map",
					title: expandDescription("[gr_selected_systems_title]"),
					backgroundSpecial: bg,
					overlay: { name: "galreg-solar_system.png", height: 546 },
					allowInterrupt: true,
					exitScreen: this._exitTo,
					choices: curChoices,
					initialChoicesKey: (this._lastChoice[this._menu] != "" ? this._lastChoice[this._menu] : def),
					message: text
				};
				break;
			}

		case 10: // search results map
			{
				this._pageLength = 255;
				var planets = this.$searchSystems();
				var closest = this.$getClosestSystemFromList(planets);

				for (var i = 0; i < planets.length; i++) {
					mission.markSystem({ system: planets[i].systemID, markerColor: "cyanColor", markerShape: "MARKER_DIAMOND", name: "galreg_marked" });
					this._markedPlanets.push(planets[i].systemID);
				}

				curChoices["17_SEARCHRESULTS-X"] = { text: "[gr_showsystems0]", unselectable: false, color: this._altColor };

				if (this._removeANATool === false) {
					if (closest != -1) curChoices["50_SETCOURSE~" + closest] = { text: expandDescription("[gr_setcourse1]", { select: System.systemNameForID(closest) }), color: this._menuColor };
				}

				text = expandDescription("[gr_search_results]", { found: planets.length }) + expandDescription("[gr_search_criteria]", { criteria: this._search.join(" ") });

				curChoices["97_SEARCH_AGAIN"] = { text: "[gr_search_again]", color: this._itemColor };
				curChoices["98_EXIT"] = { text: "[gr_exit_menu]", color: this._itemColor };
				def = "98_EXIT";

				var opts = {
					screenID: "oolite-galacticregistry-searchresults-map",
					title: expandDescription("[gr_search_results_title]"),
					backgroundSpecial: bg,
					overlay: { name: "galreg-solar_system.png", height: 546 },
					allowInterrupt: true,
					exitScreen: this._exitTo,
					choices: curChoices,
					initialChoicesKey: (this._lastChoice[this._menu] != "" ? this._lastChoice[this._menu] : def),
					message: text
				};
				break;
			}
		case 17: // search results sys list
			{
				this._pageLength = 22;
				var planets = this.$searchSystems();
				planets.sort(compareName);
				var closest = this.$getClosestSystemFromList(planets);

				text = (this._searchMax === false ? "Found " + planets.length + " system(s).  " : "") + "Search criteria: " + this._search.join(" ") + "\n" + (this._searchMax === true ? "Note: More than 66 systems found - Only 66 systems shown" : "") + "\n";
				text = (this._searchMax === false ? expandDescription("[gr_search_results]", { found: planets.length }) : "") + expandDescription("[gr_search_criteria]", { criteria: this._search.join(" ") }) + "\n" + (this._searchMax === true ? expandDescription("[gr_search_max]") : "") + "\n";

				text += this.$formatSystemList(planets);

				curChoices["17_SEARCHRESULTS"] = { text: "[gr_showmap0]", color: this._altColor };

				if (this._removeANATool === false) {
					if (closest != -1) curChoices["50_SETCOURSE~" + closest] = { text: expandDescription("[gr_setcourse1]", { select: System.systemNameForID(closest) }), color: this._menuColor };
				}

				curChoices["97_SEARCH_AGAIN"] = { text: "[gr_search_again]", color: this._itemColor };
				curChoices["98_EXIT"] = { text: "[gr_exit_menu]", color: this._itemColor };
				def = "98_EXIT";

				var opts = {
					screenID: "oolite-galacticregistry-searchsystemslist-map",
					title: expandDescription("[gr_search_results_title]"),
					allowInterrupt: true,
					exitScreen: this._exitTo,
					choices: curChoices,
					initialChoicesKey: (this._lastChoice[this._menu] != "" ? this._lastChoice[this._menu] : def),
					message: text
				};
				break;
			}
	}

	if (this._menu >= 20) {
		var cust = this._menu - 20;
		var sub = false;
		if (cust >= 20) {
			cust -= 20;
			sub = true;
		}
		var custItem = this._custom[cust];
		this._setItem = custItem.systems[this._item];
		var planets = custItem.systems[this._item].systemIDList;
		def = "98_EXIT";

		if (sub === false) {
			var closest = this.$getClosestSystemFromList(planets);

			switch (custItem.listType) {
				case "unconnected": // (default)
					var colr = custItem.systems[this._item].markerColor;
					var shape = custItem.systems[this._item].markerShape;

					for (var i = 0; i < planets.length; i++) {
						var s = System.infoForSystem(galaxyNumber, planets[i]);
						if (!s.concealment || s.concealment <= 100) {
							mission.markSystem({ system: planets[i], markerColor: colr, markerShape: shape, name: "galreg_marked", markerScale: 1.0 });
							this._markedPlanets.push(planets[i]);
						}
					}
					break;
				case "region":
					var colr = custItem.systems[this._item].linkColor
					for (var j = 0; j < planets.length; j++) {
						for (var k = 0; k < planets.length; k++) {
							if (j != k && planets[j] < planets[k]) {
								this._markedRegions.push({ id1: planets[j], id2: planets[k] });
								SystemInfo.setInterstellarProperty(galaxyNumber, planets[j], planets[k], 2, "link_color", colr, "galreg_region");
							}
						}
					}
					break;
				case "path":
					var colr = custItem.systems[this._item].linkColor

					for (var j = 0; j < planets.length - 1; j++) {
						var s1 = System.infoForSystem(galaxyNumber, planets[j]);
						var c1 = s1.concealment;
						if (!c1) c1 = 0;
						var s2 = System.infoForSystem(galaxyNumber, planets[j + 1]);
						var c2 = s2.concealment;
						if (!c2) c2 = 0;
						if (c1 <= 100 && c2 <= 100 && s1.distanceToSystem(s2) <= 7) {
							if (planets[j] < planets[j + 1]) {
								SystemInfo.setInterstellarProperty(galaxyNumber, planets[j], planets[j + 1], 2, "link_color", colr, "galreg_region");
								this._markedRegions.push({ id1: planets[j], id2: planets[j + 1] });
							} else {
								SystemInfo.setInterstellarProperty(galaxyNumber, planets[j + 1], planets[j], 2, "link_color", colr, "galreg_region");
								this._markedRegions.push({ id1: planets[j + 1], id2: planets[j] });
							}
						}
					}
					// mark the end points on the route
					colr = custItem.systems[this._item].markerColor

					var c1 = System.infoForSystem(galaxyNumber, planets[0]).concealment;
					if (!c1 || c1 <= 100) {
						mission.markSystem({ system: planets[0], name: "galreg_marked", markerShape: custItem.systems[this._item].startMarkerShape, markerColor: colr, markerScale: 1.5 });
						this._spaceLaneStart = planets[0];
					}
					var c2 = System.infoForSystem(galaxyNumber, planets[planets.length - 1]).concealment;
					if (!c2 || c2 <= 100) {
						mission.markSystem({ system: planets[planets.length - 1], name: "galreg_marked", markerShape: custItem.systems[this._item].endMarkerShape, markerColor: colr, markerScale: 1.5 });
						this._spaceLaneEnd = planets[planets.length - 1];
					}
					break;
			}

			var opts = {
				screenID: "oolite-galacticregistry-custom-map",
				title: expandDescription("[gr_screen_title_prefix]") + expandDescription(custItem.systems[this._item].name),
				backgroundSpecial: bg,
				overlay: { name: "galreg-solar_system.png", height: 546 },
				allowInterrupt: true,
				exitScreen: this._exitTo,
				initialChoicesKey: (this._lastChoice[this._menu] != "" ? this._lastChoice[this._menu] : def),
				message: text
			};

		} else {
			var syslist = [];
			for (var i = 0; i < planets.length; i++) {
				var s = System.infoForSystem(galaxyNumber, planets[i]);
				syslist.push(s);
			}
			// only sort the non-path lists
			if (custItem.listType != "path") {
				syslist.sort(compareName);
				planets.sort(compareName);
			}
			var closest = this.$getClosestSystemFromList(planets);

			text = this.$formatSystemList(syslist);

			var opts = {
				screenID: "oolite-galacticregistry-customsystemslist-map",
				title: expandDescription("[gr_screen_title_prefix]") + expandDescription(custItem.systems[this._item].name),
				overlay: { name: "galreg-solar_system.png", height: 546 },
				allowInterrupt: true,
				exitScreen: this._exitTo,
				initialChoicesKey: (this._lastChoice[this._menu] != "" ? this._lastChoice[this._menu] : def),
				message: text
			};
		}

		var holdpagesize = pagesize;

		var maxpage = Math.ceil(custItem.systems.length / pagesize);
		// if we have three pages to display, we need to reduce the page size because the middle page will need a "Next" plus a "Back" item
		// which will reduce the actual space for techelevel items
		if (maxpage > 1) { //  && pagesize === 7
			pagesize -= 1;
			maxpage = Math.ceil(custItem.systems.length / pagesize);
		}

		var end = ((this._page * pagesize) + pagesize);
		if (end > custItem.systems.length) end = custItem.systems.length;

		for (var i = (this._page * pagesize); i < end; i++) {
			if (this._item === i) {
				if (sub === false) {
					curChoices["20_CUSTOM!" + (cust < 10 ? "0" : "") + cust + "~" + (i < 10 ? "0" : "") + i + "-X"] = { text: expandDescription("[gr_showsystems1]", { name: custItem.systems[i].name }), unselectable: false, color: this._altColor };
				} else {
					curChoices["20_CUSTOM!" + (cust < 10 ? "0" : "") + cust + "~" + (i < 10 ? "0" : "") + i] = { text: expandDescription("[gr_showmap1]", { name: custItem.systems[i].name }), unselectable: false, color: this._altColor };
				}
			} else {
				curChoices["20_CUSTOM!" + (cust < 10 ? "0" : "") + cust + "~" + (i < 10 ? "0" : "") + i] = { text: custItem.systems[i].name, color: this._menuColor };
			}
		}

		if (this._removeANATool === false) {
			if (closest != -1 && player.ship.docked) curChoices["50_SETCOURSE~" + closest] = { text: expandDescription("[gr_setcourse1]", { select: System.systemNameForID(closest) }), color: this._itemColor };
			switch (custItem.listType) {
				case "unconnected":
					curChoices["94U_PERMANENT"] = { text: (this.$checkPermanentSystems(this._setItem.id) ? "[gr_unset_permanent]" : "[gr_set_permanent]"), color: this._itemColor };
					break;
				case "region":
					curChoices["94R_PERMANENT"] = { text: (this.$checkPermanentRegions(this._setItem.id) ? "[gr_unset_permanent]" : "[gr_set_permanent]"), color: this._itemColor };
					break;
				case "path":
					curChoices["94P_PERMANENT"] = { text: (this.$checkPermanentPaths(this._setItem.id) ? "[gr_unset_permanent]" : "[gr_set_permanent]"), color: this._itemColor };
					break;
			}
		}

		if (maxpage > 1) {
			if (this._page < (maxpage - 1)) {
				curChoices["95_NEXT"] = { text: "[gr_nextpage]", color: this._itemColor };
			} else {
				curChoices["95_NEXT"] = { text: "[gr_nextpage]", color: this._disabledColor, unselectable: true };
			}
			if (this._page > 0) {
				curChoices["96_PREV"] = { text: "[gr_prevpage]", color: this._itemColor };
			} else {
				curChoices["96_NEXT"] = { text: "[gr_prevpage]", color: this._disabledColor, unselectable: true };
			}
		}

		curChoices["98_EXIT"] = { text: "[gr_exit_menu]", color: this._itemColor };

		pagesize = holdpagesize;
		opts.choices = curChoices;
	}

	if (zeroMap) worldScripts.ZeroMap._showAll(galaxyNumber);

	mission.runScreen(opts, this.$screenHandler, this);
}

//-------------------------------------------------------------------------------------------------------------
this.$screenHandler = function $screenHandler(choice) {
	if (this._holdDestination >= 0) {
		player.ship.targetSystem = this._holdDestination;
		this._holdDestination = -1;
	}

	if (!choice) return;

	this._lastChoice[this._menu] = choice;

	switch (choice) {
		case "11_FULLLIST":
			this._menu = 8;
			this._item = 0;
			this._page = 0;
			break;
		case "12_SEARCH":
			this.$getSearchPhrase();
			return;
		case "94U_PERMANENT": // systems
			if (this.$checkPermanentSystems(this._setItem.id)) {
				this.$removePermanentSystems(this._setItem.id);
			} else {
				this._permanentChartData.systems.push({
					id: this._setItem.id,
					markerShape: this._setItem.markerShape,
					markerColor: this._setItem.markerColor,
					markerScale: 1.0,
					systemIDList: this._setItem.systemIDList
				});
			}
			break;
		case "94P_PERMANENT":
			if (this.$checkPermanentPaths(this._setItem.id)) {
				this.$removePermanentPath(this._setItem.id);
				this.$removePermanentSystems(this._setItem.id);
			} else {
				this._permanentChartData.paths.push({
					id: this._setItem.id,
					linkColor: this._setItem.linkColor,
					systemIDList: this._setItem.systemIDList
				});
				this._permanentChartData.systems.push({
					id: this._setItem.id,
					markerShape: this._setItem.startMarkerShape,
					markerColor: this._setItem.markerColor,
					markerScale: 1.5,
					systemIDList: [this._setItem.systemIDList[0]]
				});
				this._permanentChartData.systems.push({
					id: this._setItem.id,
					markerShape: this._setItem.endMarkerShape,
					markerColor: this._setItem.markerColor,
					markerScale: 1.5,
					systemIDList: [this._setItem.systemIDList[this._setItem.systemIDList.length - 1]]
				});
			}
			break;
		case "94R_PERMANENT":
			if (this.$checkPermanentRegions(this._setItem.id)) {
				this.$removePermanentRegion(this._setItem.id);
			} else {
				this._permanentChartData.regions.push({
					id: this._setItem.id,
					linkColor: this._setItem.linkColor,
					systemIDList: this._setItem.systemIDList
				});
			}
			break;
		case "95_NEXT":
			this._page += 1;
			break;
		case "96_PREV":
			this._page -= 1;
			break;
		case "97_1_SORT_NAME":
			this._sortType = 0;
			break;
		case "97_2_SORT_TL":
			this._sortType = 1;
			break;
		case "97_3_SORT_GOV":
			this._sortType = 2;
			break;
		case "97_4_SORT_ECO":
			this._sortType = 3;
			break;
		case "97_9_SELECTED":
			this._menu = 9;
			break;
		case "97_EXIT":
			this._menu = 8;
			break;
		case "98_EXIT":
			this._menu = 0;
			break;
		case "97_SEARCH_AGAIN":
			this._menu = this.$getSearchPhrase();
			return;
		case "17_SEARCHRESULTS":
			this._menu = 10;
			this._lastChoice[this._menu] = "17_SEARCHRESULTS-X";
			break;
		case "17_SEARCHRESULTS-X":
			this._menu = 17;
			this._lastChoice[this._menu] = "17_SEARCHRESULTS";
			break;
	}

	if (choice.indexOf("10_CUSTOM~") >= 0) {
		var custIndex = parseInt(choice.substring(choice.indexOf("~") + 1), 10);
		this._menu = custIndex + 20;
		this._item = 0;
		this._page = 0;
	}
	if (choice.indexOf("20_CUSTOM") >= 0) {
		var menuIndex = parseInt(choice.substring(choice.indexOf("!") + 1), 10);
		this._menu = menuIndex + 20;
		var itemIndex = parseInt(choice.substring(choice.indexOf("~") + 1), 10);
		this._item = itemIndex;
		if (choice.indexOf("-X") === -1) {
			this._lastChoice[this._menu] = choice + "-X";
		} else {
			this._menu = menuIndex + 40;
			this._lastChoice[this._menu] = choice.replace("-X", "");
		}
	}

	if (choice.indexOf("40_SYSLIST") >= 0) {
		var sys = parseInt(choice.substring(choice.indexOf("~") + 1), 10);
		if (this._selectLast === 2) {
			this._select1 = sys;
			this._selectLast = 1;
		} else {
			this._select2 = sys;
			this._selectLast = 2;
		}
	}
	if (choice.indexOf("50_SETCOURSE") >= 0) {
		player.ship.targetSystem = parseInt(choice.substring(choice.indexOf("~") + 1), 10);
		player.ship.infoSystem = player.ship.targetSystem;
		player.consoleMessage("Course set for " + System.systemNameForID(player.ship.targetSystem));
		this._lastChoice[this._menu] = "";
	}

	if (choice != "99_EXIT") this.$showMissionPage();
}

//-------------------------------------------------------------------------------------------------------------
// prompts the user for search criteria
this.$getSearchPhrase = function $getSearchPhrase() {

	var text = expandDescription("[gr_search_help]");

	var opts = {
		screenID: "oolite-galacticregistry-searchphrase-map",
		title: expandDescription("[gr_search_title]"),
		allowInterrupt: false,
		exitScreen: "GUI_SCREEN_INTERFACES",
		overlay: { name: "galreg-solar_system.png", height: 546 },
		message: text,
		textEntry: true
	};
	mission.runScreen(opts, this.$extractSearchWords, this);
}

//-------------------------------------------------------------------------------------------------------------
// parses the input from the setLogSize screen
this.$extractSearchWords = function $extractSearchWords(param) {
	this._menu = 10;
	if (param === "") {
		this._menu = 0;
	} else {
		this._search = param.toLowerCase().split(" ");
		for (var i = this._search.length - 1; i >= 0; i--) {
			if (this._search[i].trim() === "" || this._search[i].length <= 2) this._search.splice(i, 1);
		}
		if (this._search.length === 0) this._menu = 0;
	}
	this.$showMissionPage();
}

//-------------------------------------------------------------------------------------------------------------
// returns a 3-column list of planets, formatted for display
this.$formatSystemList = function $formatSystemList(list) {
	var govs = new Array();
	for (var i = 0; i < 8; i++)
		govs.push(String.fromCharCode(i));
	this.ecos = new Array();
	for (i = 0; i < 8; i++) {
		this.ecos.push(String.fromCharCode(23 - i));
	}
	var spc = String.fromCharCode(31);

	var lines = [];
	for (var i = 0; i < this._pageLength; i++) lines.push("");
	var point = 0;
	var p = player.ship;

	var colwidth = 31;
	if (list.length > this._pageLength) colwidth = 15;
	if (list.length > (this._pageLength * 2)) colwidth = 10.2;

	for (var i = 0; i < list.length; i++) {
		if (isNaN(list[i])) {
			var sys = list[i];
		} else {
			var sys = System.infoForSystem(galaxyNumber, list[i]);
		}
		var item = sys.name + ((!sys.concealment || sys.concealment === 0) ? " " + expandDescription("[gr_system_data_sml]", { gov: govs[sys.government], spacer: spc, eco: ecos[sys.economy], tl: (sys.techlevel + 1) }) : "");

		lines[point] += this.$padTextRight(item, colwidth);
		point += 1;
		if (point === lines.length) point = 0;
	}
	var result = "";
	for (var i = 0; i < lines.length; i++) {
		result += lines[i] + "\n";
	}
	return result;
}

//-------------------------------------------------------------------------------------------------------------
this.$getClosestSystemFromList = function $getClosestSystemFromList(planets) {
	var dist = 0;
	var min_dist = 200;
	var closest = -1;
	var maxlevel = this.$getMaxTechLevel();
	var chk = -1;
	for (var i = 0; i < planets.length; i++) {
		if (isNaN(planets[i])) {
			chk = planets[i].systemID;
		} else {
			chk = planets[i];
		}
		var s = System.infoForSystem(galaxyNumber, chk);
		if (!s.concealment || s.concealment <= 100) {
			var dist = this.$getDistanceToPlanet(chk);
			if (dist < min_dist) { closest = chk; min_dist = dist; }
		}
	}
	return closest;
}

//-------------------------------------------------------------------------------------------------------------
this.$getRegionData = function $getRegionData() {
	var info = [];
	switch (galaxyNumber) {
		case 0:
			info = [
				{ name: expandDescription("[gr_region_g1_1]"), data: [43, 101, 141, 250, 197, 140, 48, 37, 58, 64, 188, 111] },
				{ name: expandDescription("[gr_region_g1_2]"), data: [167, 249, 131, 42, 93, 100, 139, 21, 230, 62] },
				{ name: expandDescription("[gr_region_g1_3]"), data: [221, 185, 99, 241, 84, 120, 191, 121, 60] },
				{ name: expandDescription("[gr_region_g1_4]"), data: [102, 18, 51, 246, 218, 8, 114, 215, 158, 49] },
				{ name: expandDescription("[gr_region_g1_5]"), data: [213, 59, 142, 174, 223, 238] },
				{ name: expandDescription("[gr_region_g1_6]"), data: [20, 148, 181] },
				{ name: expandDescription("[gr_region_g1_7]"), data: [3, 128, 94, 153, 132, 26, 196, 146, 234] },
				{ name: expandDescription("[gr_region_g1_8]"), data: [129, 255, 55, 46, 147, 7, 39] }
			];
			break;
		case 1:
			info = [
				{ name: expandDescription("[gr_region_g2_1]"), data: [159, 111, 157, 16, 139, 34, 248, 205, 59] },
				{ name: expandDescription("[gr_region_g2_2]"), data: [156, 92, 61] },
				{ name: expandDescription("[gr_region_g2_3]"), data: [231, 215, 147, 108, 140, 249, 189, 65, 204] },
				{ name: expandDescription("[gr_region_g2_4]"), data: [29, 13, 97, 102, 149, 124, 81, 20, 123] },
				{ name: expandDescription("[gr_region_g2_5]"), data: [32, 42, 26, 114, 202, 55, 142, 50, 69, 18, 36, 146, 251] },
				{ name: expandDescription("[gr_region_g2_6]"), data: [10, 2, 224, 172, 70, 120, 181, 76, 104, 7, 194] },
				{ name: expandDescription("[gr_region_g2_7]"), data: [87, 134, 38, 185, 155, 62, 227, 175, 235, 44, 220, 192] },
				{ name: expandDescription("[gr_region_g2_8]"), data: [242, 91, 167, 115, 178, 113, 226, 57, 94, 19, 33] },
				{ name: expandDescription("[gr_region_g2_9]"), data: [100, 229, 37, 5] },
				{ name: expandDescription("[gr_region_g2_10]"), data: [47, 0, 217, 213, 190, 135, 30, 137, 254, 64, 110, 225] }
			];
			break;
		case 2:
			info = [
				{ name: expandDescription("[gr_region_g3_1]"), data: [100, 18, 149, 62, 201, 223, 52, 145] },
				{ name: expandDescription("[gr_region_g3_2]"), data: [206, 133] },
				{ name: expandDescription("[gr_region_g3_3]"), data: [54, 161, 185, 118, 121, 186, 232, 165, 129] },
				{ name: expandDescription("[gr_region_g3_4]"), data: [40, 184, 36, 99, 210, 35, 61, 90, 51] },
				{ name: expandDescription("[gr_region_g3_5]"), data: [234, 49, 239, 22, 228, 175, 110, 140, 5, 56, 177, 150, 26, 58] },
				{ name: expandDescription("[gr_region_g3_6]"), data: [192, 207, 134, 244, 60, 107, 173, 215, 64, 119, 168, 114, 227, 19, 205, 94, 88, 101, 241, 82, 236, 32, 46, 248] },
				{ name: expandDescription("[gr_region_g3_7]"), data: [170, 231, 127, 45, 27, 108, 247, 199] }
			];
			break;
		case 3:
			info = [
				{ name: expandDescription("[gr_region_g4_1]"), data: [184, 86, 163, 116, 230, 167, 94, 36, 159, 12, 57, 65, 35, 55, 228] },
				{ name: expandDescription("[gr_region_g4_2]"), data: [234, 125, 245, 181, 73, 82, 117, 37, 237, 53, 74, 38] },
				{ name: expandDescription("[gr_region_g4_3]"), data: [99, 63, 51, 102, 31, 20, 44, 215, 158, 92, 224, 231, 220, 110, 68, 151, 248, 79, 71, 115] },
				{ name: expandDescription("[gr_region_g4_4]"), data: [222, 65, 137, 144, 101, 45, 105, 148, 95, 49, 34, 10, 54, 30, 119, 103, 241] }
			];
			break;
		case 4:
			info = [
				{ name: expandDescription("[gr_region_g5_1]"), data: [84, 66, 58, 49, 71, 125, 78, 242] },
				{ name: expandDescription("[gr_region_g5_1]"), data: [31, 127, 134, 44, 198, 37, 63, 95, 219] },
				{ name: expandDescription("[gr_region_g5_1]"), data: [3, 47, 111, 181, 231, 35, 122, 180, 102, 24, 19, 69, 156, 60, 1, 230, 112, 28] },
				{ name: expandDescription("[gr_region_g5_1]"), data: [151, 86, 133, 123, 36, 98, 223] },
				{ name: expandDescription("[gr_region_g5_1]"), data: [55, 128, 72, 185, 126, 100, 109] },
				{ name: expandDescription("[gr_region_g5_1]"), data: [205, 7, 161, 70, 173, 137, 191, 140] }
			];
			break;
		case 5:
			info = [
				{ name: expandDescription("[gr_region_g6_1]"), data: [32, 56, 47, 160, 242, 167, 129, 12] },
				{ name: expandDescription("[gr_region_g6_2]"), data: [88, 184, 196, 8, 3, 84, 236, 111, 214] },
				{ name: expandDescription("[gr_region_g6_3]"), data: [177, 185, 106, 44, 245, 171, 156, 113, 14, 146, 249, 230, 134, 205, 216, 82] },
				{ name: expandDescription("[gr_region_g6_4]"), data: [116, 178, 154, 45, 204, 163, 120, 7, 251, 72, 132, 137, 255, 90, 149, 241, 153, 141, 95, 218, 212, 198] },
				{ name: expandDescription("[gr_region_g6_5]"), data: [121, 203, 31, 30, 74, 126, 234] },
				{ name: expandDescription("[gr_region_g6_6]"), data: [240, 140, 159, 77, 66, 10, 118, 186, 46] },
				{ name: expandDescription("[gr_region_g6_7]"), data: [41, 202, 55, 33] },
				{ name: expandDescription("[gr_region_g6_8]"), data: [172, 208, 201, 87, 168, 2, 39, 246, 83, 42, 35, 65, 114, 224, 23] },
				{ name: expandDescription("[gr_region_g6_9]"), data: [22, 98, 53, 229, 248, 139, 16, 102, 130] },
				{ name: expandDescription("[gr_region_g6_10]"), data: [37, 75, 127, 6, 189, 89, 17, 1, 161, 250, 147, 67, 60, 138, 252, 155, 233, 225, 86, 254, 71, 0, 58, 210, 69, 4, 223, 144, 19, 206, 150, 194, 182, 5, 200] },
				{ name: expandDescription("[gr_region_g6_11]"), data: [176, 99, 174, 85, 237, 133, 213, 107, 187, 40, 164, 215, 117, 79, 9, 232, 50, 110, 81, 195, 183] }
			];
			break;
		case 6:
			info = [
				{ name: expandDescription("[gr_region_g7_1]"), data: [18, 234, 117, 49, 1] },
				{ name: expandDescription("[gr_region_g7_2]"), data: [124, 51, 172, 81, 102, 204] },
				{ name: expandDescription("[gr_region_g7_3]"), data: [215, 111, 181, 41, 39, 65, 44, 236, 150, 193, 247, 202, 72, 37, 179, 133] },
				{ name: expandDescription("[gr_region_g7_4]"), data: [187, 77, 53, 100, 240, 107, 174] },
				{ name: expandDescription("[gr_region_g7_5]"), data: [186, 110, 97, 248, 15, 134] },
				{ name: expandDescription("[gr_region_g7_6]"), data: [137, 153, 27, 228, 139] }
			];
			break;
		case 7:
			info = [
				{ name: expandDescription("[gr_region_g8_1]"), data: [242, 170, 87, 115, 150, 62, 240, 186, 34, 196, 185, 11, 253, 166, 132, 90, 134, 160] },
				{ name: expandDescription("[gr_region_g8_2]"), data: [52, 223, 247, 144, 67] },
				{ name: expandDescription("[gr_region_g8_3]"), data: [203, 255, 161, 98, 16, 20, 84, 107] },
				{ name: expandDescription("[gr_region_g8_4]"), data: [6, 81, 250, 65, 169, 232, 105, 80, 75, 40, 59, 252, 153, 72, 10, 219, 231, 200, 208, 86] },
				{ name: expandDescription("[gr_region_g8_5]"), data: [135, 73, 193, 120, 127, 7, 102, 184, 172, 177, 210, 70, 130, 123, 38, 175, 23, 233, 39, 168, 64, 104, 41, 125, 45, 110, 201, 241, 154] },
				{ name: expandDescription("[gr_region_g8_6]"), data: [216, 13, 147, 137, 9, 211, 88, 171, 2, 215] }
			];
			break;
	}
	return info;
}

//-------------------------------------------------------------------------------------------------------------
// loads the spacelane array with data for the current galaxy
this.$getSpacelanes = function $getSpacelanes() {
	var data = [];
	switch (galaxyNumber) {
		case 0:
			data = [
				{ name: expandDescription("[gr_spaceway_g1_1]"), color: "0.0 1.0 1.0 0.5", data: [141, 250, 111, 186, 50, 73, 35, 188, 250] },
				{ name: expandDescription("[gr_spaceway_g1_2]"), color: "1.0 1.0 0.0 0.5", data: [7, 129, 227, 73, 89, 222, 29, 93, 42, 131] },
				{ name: expandDescription("[gr_spaceway_g1_3]"), color: "whiteColor", data: [131, 62, 150, 198, 36, 28, 16, 221, 99] },
				{ name: expandDescription("[gr_spaceway_g1_4]"), color: "0.824 0.412 0.118 1.0", data: [99, 241, 86, 126, 18, 246] }
			];
			break;
		case 1:
			data = [
				{ name: expandDescription("[gr_spaceway_g2_1]"), color: "0.0 1.0 1.0 0.5", data: [82, 23, 188, 23, 54, 74, 122, 57, 115, 178, 45] },
				{ name: expandDescription("[gr_spaceway_g2_2]"), color: "redColor", data: [45, 144, 189, 140, 65, 48, 204, 193, 221, 236, 66, 58, 88, 127] },
				{ name: expandDescription("[gr_spaceway_g2_3]"), color: "1.0 1.0 0.0 0.5", data: [127, 109, 42, 114, 202] },
				{ name: expandDescription("[gr_spaceway_g2_4]"), color: "greenColor", data: [127, 207, 136, 6, 24, 53, 78, 48] },
				{ name: expandDescription("[gr_spaceway_g2_5]"), color: "whiteColor", data: [205, 59, 100, 9, 156, 92, 61, 41, 179, 189] },
				{ name: expandDescription("[gr_spaceway_g2_6]"), color: "0.824 0.412 0.118 1.0", data: [113, 115, 57, 94, 29] }
			];
			break;
		case 2:
			data = [
				{ name: expandDescription("[gr_spaceway_g3_1]"), color: "0.0 1.0 1.0 0.5", data: [38, 182, 246, 91, 22, 140, 5, 56, 177, 150, 26, 75, 144, 209, 17, 218] },
				{ name: expandDescription("[gr_spaceway_g3_2]"), color: "redColor", data: [50, 65, 79, 154, 38, 139, 189, 135, 42] },
				{ name: expandDescription("[gr_spaceway_g3_3]"), color: "whiteColor", data: [205, 241, 101, 132, 6, 180, 164, 70, 10, 85, 81, 225, 81, 85, 10, 70, 202, 53] },
				{ name: expandDescription("[gr_spaceway_g3_4]"), color: "0.824 0.412 0.118 1.0", data: [140, 58, 152, 76, 77, 97, 168] },
				{ name: expandDescription("[gr_spaceway_g3_5]"), color: "greenColor", data: [106, 250, 245, 160, 245, 22] },
				{ name: expandDescription("[gr_spaceway_g3_6]"), color: "1.0 1.0 0.0 0.5", data: [118, 161, 54, 165, 129, 186] }
			];
			break;
		case 3:
			data = [
				{ name: expandDescription("[gr_spaceway_g4_1]"), color: "greenColor", data: [116, 230, 167, 48, 210, 36, 150, 84, 240, 193, 223, 118, 197, 135, 85, 154, 213, 162, 166, 213] },
				{ name: expandDescription("[gr_spaceway_g4_2]"), color: "0.0 1.0 1.0 0.5", data: [16, 42, 172, 40, 80, 65, 144, 105, 119, 208, 189, 1, 174, 146, 100, 233] },
				{ name: expandDescription("[gr_spaceway_g4_3]"), color: "0.824 0.412 0.118 1.0", data: [50, 239, 103, 108, 103, 177, 17, 177, 103, 45, 105, 137, 95, 54, 77, 76, 21, 2, 249, 113, 141, 113, 97] },
				{ name: expandDescription("[gr_spaceway_g4_4]"), color: "whiteColor", data: [209, 33, 62, 25, 134, 58, 138, 191, 78, 57, 242, 234, 245, 181, 82, 117, 53, 74, 38] },
				{ name: expandDescription("[gr_spaceway_g4_5]"), color: "1.0 1.0 0.0 0.5", data: [71, 79, 68, 110, 220, 158, 215, 63, 44, 66, 146, 174, 1, 4, 121, 145, 142, 6, 142, 11, 7, 161, 140] },
				{ name: expandDescription("[gr_spaceway_g4_6]"), color: "redColor", data: [7, 32, 232, 216, 60] }
			];
			break;
		case 4:
			data = [
				{ name: expandDescription("[gr_spaceway_g5_1]"), color: "0.824 0.412 0.118 1.0", data: [41, 216, 112, 230, 28, 102, 181, 35, 180, 24, 19, 156, 1, 45, 79, 172, 169] },
				{ name: expandDescription("[gr_spaceway_g5_2]"), color: "whiteColor", data: [140, 137, 173, 70, 7, 253, 243, 135, 193, 225, 184, 150, 115, 201, 189, 227, 226, 221, 57, 202, 135, 202, 57, 221, 226, 227, 189, 115, 11, 54, 158, 175, 85, 178, 204, 12, 215, 212, 158] },
				{ name: expandDescription("[gr_spaceway_g5_3]"), color: "greenColor", data: [194, 8, 210, 41, 222, 183, 254, 149, 130, 108, 82, 92, 29, 121, 34, 183] },
				{ name: expandDescription("[gr_spaceway_g5_4]"), color: "redColor", data: [114, 118, 2, 116, 244, 248, 65, 146, 153, 10, 99, 91, 200, 244] },
				{ name: expandDescription("[gr_spaceway_g5_5]"), color: "blueColor", data: [120, 9, 233, 104, 136, 129, 139, 163, 61] },
				{ name: expandDescription("[gr_spaceway_g5_6]"), color: "1.0 1.0 0.0 0.5", data: [249, 16, 20, 39, 93, 207, 131, 74, 182, 252, 188, 40, 146, 153, 146, 40, 188, 252, 182, 166, 53, 221, 220, 225] },
				{ name: expandDescription("[gr_spaceway_g5_7]"), color: "0.0 1.0 1.0 0.5", data: [30, 89, 87, 89, 152, 170, 88, 194, 77, 246, 106, 190, 208, 167] }
			];
			break;
		case 5:
			data = [
				{ name: expandDescription("[gr_spaceway_g6_1]"), color: "0.824 0.412 0.118 1.0", data: [84, 3, 8, 88, 206, 136, 144, 13, 92, 99, 85, 133, 40, 215, 115, 83, 246, 39, 35, 114] },
				{ name: expandDescription("[gr_spaceway_g6_2]"), color: "1.0 1.0 0.0 0.5", data: [169, 51, 80, 103, 243, 98, 102, 16, 109, 101, 67, 142, 60, 209, 233, 112, 225, 131, 210, 12, 150, 91] },
				{ name: expandDescription("[gr_spaceway_g6_3]"), color: "whiteColor", data: [104, 54, 162, 148, 211, 6, 181, 17, 108, 28] },
				{ name: expandDescription("[gr_spaceway_g6_4]"), color: "0.0 1.0 1.0 0.5", data: [156, 113, 14, 216, 82, 177, 116, 154, 120, 50, 232, 124, 215] },
				{ name: expandDescription("[gr_spaceway_g6_5]"), color: "redColor", data: [10, 77, 159, 226, 31, 203, 30, 234, 240, 234, 140, 159] }
			];
			break;
		case 6:
			data = [
				{ name: expandDescription("[gr_spaceway_g7_1]"), color: "0.0 1.0 1.0 0.5", data: [103, 58, 253, 65, 39, 44, 236, 150, 247, 193, 179, 133, 215, 95, 109] },
				{ name: expandDescription("[gr_spaceway_g7_2]"), color: "whiteColor", data: [194, 73, 146, 239, 86, 74, 199, 23, 138, 18, 234, 244, 166, 152, 162, 242, 184] },
				{ name: expandDescription("[gr_spaceway_g7_3]"), color: "0.824 0.412 0.118 1.0", data: [218, 130, 125, 205, 79, 191, 17, 178] },
				{ name: expandDescription("[gr_spaceway_g7_4]"), color: "1.0 1.0 0.0 0.5", data: [211, 7, 163, 67, 209, 250, 19, 239] },
				{ name: expandDescription("[gr_spaceway_g7_5]"), color: "redColor", data: [46, 36, 212, 187, 53, 107, 174] }
			];
			break;
		case 7:
			data = [
				{ name: expandDescription("[gr_spaceway_g8_1]"), color: "whiteColor", data: [114, 12, 241, 39, 23, 38, 123, 130, 167, 63, 136, 8, 44, 91, 56, 62, 186, 93, 32, 61, 244, 243, 116, 46, 157, 230, 151, 213, 198, 148, 49, 76, 203, 255, 161, 98, 53, 1, 145, 33] },
				{ name: expandDescription("[gr_spaceway_g8_2]"), color: "0.0 1.0 1.0 0.5", data: [215, 2, 211, 9, 13, 147, 216, 225, 21, 218, 71, 206, 236, 190, 18, 26, 152, 51, 209, 24, 174, 82, 179, 173, 30, 251, 233, 125, 45, 41, 104, 110, 73, 135, 117, 55] },
				{ name: expandDescription("[gr_spaceway_g8_3]"), color: "1.0 1.0 0.0 0.5", data: [126, 6, 81, 65, 169, 232, 252] },
				{ name: expandDescription("[gr_spaceway_g8_4]"), color: "0.824 0.412 0.118 1.0", data: [75, 219, 248, 117] },
				{ name: expandDescription("[gr_spaceway_g8_5]"), color: "redColor", data: [10, 72, 219, 248, 117] }
			];
			break;
	}
	return data;
}

//-------------------------------------------------------------------------------------------------------------
// returns true if a HUD with allowBigGUI is enabled, otherwise false
this.$isBigGuiActive = function $isBigGuiActive() {
	if (oolite.compareVersion("1.83") <= 0) {
		return player.ship.hudAllowsBigGui;
	} else {
		var bigGuiHUD = ["XenonHUD.plist", "coluber_hud_ch01-dock.plist"]; 	// until there is a property we can check, I'll be listing HUD's that have the allow_big_gui property set here
		if (bigGuiHUD.indexOf(player.ship.hud) >= 0) {
			return true;
		} else {
			return false;
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// turns off any explorer club markers
this.$hideExplorersClub = function $hideExplorersClub() {
	for (var i = 0; i < 256; i++) {
		mission.unmarkSystem({ system: i, name: "exclubmap" });
	}
}

//-------------------------------------------------------------------------------------------------------------
// turns off any smugglers markers
this.$hideSmugglers = function $hideSmugglers() {
	var w = worldScripts.Smugglers_Illegal;
	// clear out existing marks
	for (var i = 0; i < w._markedSystems.length; i++) {
		mission.unmarkSystem({ system: w._markedSystems[i], name: "illegalgoods" });
	}

	// reset the array
	w._markedSystems = [];
}

//-------------------------------------------------------------------------------------------------------------
// removes any region, lane or planetary markers from the chart
this.$removeChartData = function $removeChartData() {
	for (var i = 0; i < this._markedRegions.length; i++) {
		SystemInfo.setInterstellarProperty(galaxyNumber, this._markedRegions[i].id1, this._markedRegions[i].id2, 2, "link_color", "galreg_region");
	}
	this._markedRegions = [];
	for (var i = 0; i < this._markedPlanets.length; i++) {
		mission.unmarkSystem({ system: this._markedPlanets[i], name: "galreg_marked" });
	}
	if (this._spaceLaneStart >= 0) mission.unmarkSystem({ system: this._spaceLaneStart, name: "galreg_marked" });
	if (this._spaceLaneEnd >= 0) mission.unmarkSystem({ system: this._spaceLaneEnd, name: "galreg_marked" });
	this._spaceLaneStart = -1;
	this._spaceLaneEnd = -1;
	this._markedPlanets = [];
	this.$reapplyPermanentInfo();
}

//-------------------------------------------------------------------------------------------------------------
this.$reapplyPermanentInfo = function $reapplyPermanentInfo() {
	var i = 0;
	var j = 0;
	var k = 0;
	if (this._permanentChartData) {
		if (this._permanentChartData.regions && this._permanentChartData.regions.length > 0) {
			var regions = this._permanentChartData.regions;
			for (i = 0; i < regions.length; i++) {
				if (regions[i].systemIDList && regions[i].systemIDList.length > 0) {
					var dta = regions[i].systemIDList;
					for (j = 0; j < dta.length; j++) {
						for (k = 0; k < dta.length; k++) {
							if (j != k && dta[j] < dta[k]) {
								SystemInfo.setInterstellarProperty(galaxyNumber, dta[j], dta[k], 2, "link_color", regions[i].linkColor, "galreg_region");
							}
						}
					}
				}
			}
		}
		if (this._permanentChartData.paths && this._permanentChartData.paths.length > 0) {
			var paths = this._permanentChartData.paths;
			for (i = 0; i < paths.length; i++) {
				var colr = paths[i].linkColor;
				var planets = paths[i].systemIDList;
				for (var j = 0; j < planets.length - 1; j++) {
					var s1 = System.infoForSystem(galaxyNumber, planets[j]);
					var c1 = s1.concealment;
					if (!c1) c1 = 0;
					var s2 = System.infoForSystem(galaxyNumber, planets[j + 1]);
					var c2 = s2.concealment;
					if (!c2) c2 = 0;
					if (c1 <= 100 && c2 <= 100 && s1.distanceToSystem(s2) <= 7) {
						if (planets[j] < planets[j + 1]) {
							SystemInfo.setInterstellarProperty(galaxyNumber, planets[j], planets[j + 1], 2, "link_color", colr, "galreg_region");
							this._markedRegions.push({ id1: planets[j], id2: planets[j + 1] });
						} else {
							SystemInfo.setInterstellarProperty(galaxyNumber, planets[j + 1], planets[j], 2, "link_color", colr, "galreg_region");
							this._markedRegions.push({ id1: planets[j + 1], id2: planets[j] });
						}
					}
				}
			}
		}
		if (this._permanentChartData.systems && this._permanentChartData.systems.length > 0) {
			var syslist = this._permanentChartData.systems;
			for (i = 0; i < syslist.length; i++) {
				if (syslist[i].systemIDList && syslist[i].systemIDList.length > 0) {
					var dta = syslist[i].systemIDList;
					for (j = 0; j < dta.length; j++) {
						mission.markSystem({ system: dta[j], name: "galreg_marked", markerShape: syslist[i].markerShape, markerColor: syslist[i].markerColor, markerScale: syslist[i].markerScale });
					}
				}
			}
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// gets the maximum techlevel for the sector
this.$getMaxTechLevel = function $getMaxTechLevel() {
	var tl = 0;
	for (var i = 0; i <= 255; i++) {
		var info = System.infoForSystem(galaxyNumber, i);
		if (info.techlevel > tl) tl = info.techlevel;
	}
	return tl;
}

//-------------------------------------------------------------------------------------------------------------
// returns a list of planets of a particular government type (0-7)
this.$getSystemsByGovernment = function $getSystemsByGovernment(govType) {
	var govs = SystemInfo.filteredSystems(this, function (other) {
		return (other.government === govType && (!other.concealment || other.concealment === 0));
	});
	var list = [];
	for (var i = 0; i < govs.length; i++) {
		list.push(govs[i].systemID);
	}
	return list;
}

//-------------------------------------------------------------------------------------------------------------
// returns a list of planets of a particular techlevel
this.$getSystemsByTechLevel = function $getSystemsByTechLevel(techLevel) {
	var tl = SystemInfo.filteredSystems(this, function (other) {
		return (other.techlevel === techLevel && (!other.concealment || other.concealment === 0));
	});
	var list = [];
	for (var i = 0; i < tl.length; i++) {
		list.push(tl[i].systemID);
	}
	return list;
}

//-------------------------------------------------------------------------------------------------------------
// returns a list of planets of a particular economy
this.$getSystemsByEconomy = function $getSystemsByEconomy(economy) {
	var ecos = SystemInfo.filteredSystems(this, function (other) {
		return (other.economy === economy && (!other.concealment || other.concealment === 0));
	});
	var list = [];
	for (var i = 0; i < ecos.length; i++) {
		list.push(ecos[i].systemID);
	}
	return list;
}

//-------------------------------------------------------------------------------------------------------------
this.$governmentDescription = function $governmentDescription(gov) {
	switch (gov) {
		case 0: return expandDescription("[gr_government_anarchy]");
		case 1: return expandDescription("[gr_government_feudal]");
		case 2: return expandDescription("[gr_government_multigov]");
		case 3: return expandDescription("[gr_government_dictatorship]");
		case 4: return expandDescription("[gr_government_communist]");
		case 5: return expandDescription("[gr_government_confederacy]");
		case 6: return expandDescription("[gr_government_democracy]");
		case 7: return expandDescription("[gr_government_corpstate]");
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$governmentDescriptionPlural = function $governmentDescriptionPlural(gov) {
	switch (gov) {
		case 0: return expandDescription("[gr_gov_plural_anarchy]");
		case 1: return expandDescription("[gr_gov_plural_feudal]");
		case 2: return expandDescription("[gr_gov_plural_multigov]");
		case 3: return expandDescription("[gr_gov_plural_dictatorship]");
		case 4: return expandDescription("[gr_gov_plural_communist]");
		case 5: return expandDescription("[gr_gov_plural_confederacy]");
		case 6: return expandDescription("[gr_gov_plural_democracy]");
		case 7: return expandDescription("[gr_gov_plural_corpstate]");
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$economyDescription = function $economyDescription(eco) {
	if (worldScripts["market_tweak.js"]) {
		switch (eco) {
			case 0: return expandDescription("[gr_eco_sw_extremeind]");
			case 1: return expandDescription("[gr_eco_sw_strongind]");
			case 2: return expandDescription("[gr_eco_sw_commonind]");
			case 3: return expandDescription("[gr_eco_sw_mainlyind]");
			case 4: return expandDescription("[gr_eco_sw_mainlyag]");
			case 5: return expandDescription("[gr_eco_sw_commonag]");
			case 6: return expandDescription("[gr_eco_sw_strongag]");
			case 7: return expandDescription("[gr_eco_sw_extremeag]");
		}
	} else {
		switch (eco) {
			case 0: return expandDescription("[gr_economy_richind]");
			case 1: return expandDescription("[gr_economy_averageind]");
			case 2: return expandDescription("[gr_economy_poorind]");
			case 3: return expandDescription("[gr_economy_mainlyind]");
			case 4: return expandDescription("[gr_economy_mainlyag]");
			case 5: return expandDescription("[gr_economy_richag]");
			case 6: return expandDescription("[gr_economy_averageag]");
			case 7: return expandDescription("[gr_economy_poorag]");
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// returns planet ID for galcop HQ (returned as an array)
this.$galCopHQSystem = function $galCopHQSystem() {
	var galCopHQ = [7, 33, 26, 49, 102, 85, 202, 184];			// galcop hq locations in each sector
	return [galCopHQ[galaxyNumber]];
}

//-------------------------------------------------------------------------------------------------------------
// returns list of planet ID's where gal navy sector commands reside
this.$galNavySectorCommands = function $galNavySectorCommands() {
	var data = new Array
	switch (galaxyNumber) {
		case 0:
			data = new Array(24, 193, 154, 188, 125, 109, 249, 150, 80, 175, 120, 220, 158, 15);
			break;
		case 1:
			data = new Array(248, 135, 106, 82, 150, 182, 33, 48, 227, 96, 127, 202, 243, 170);
			break;
		case 2:
			data = new Array(31, 165, 245, 84, 36, 21, 26, 139, 251, 205, 223, 204, 17, 247);
			break;
		case 3:
			data = new Array(39, 221, 188, 86, 9, 57, 186, 237, 49, 103, 254, 66, 140, 110);
			break;
		case 4:
			data = new Array(249, 71, 57, 144, 198, 153, 204, 73, 102, 222, 29, 233, 152, 190);
			break;
		case 5:
			data = new Array(151, 227, 6, 51, 60, 129, 8, 53, 85, 120, 208, 220, 146, 66);
			break;
		case 6:
			data = new Array(214, 161, 250, 127, 23, 154, 234, 24, 55, 64, 231, 140, 202, 35);
			break;
		case 7:
			data = new Array(26, 218, 9, 174, 156, 251, 75, 136, 184, 87, 212, 116, 98, 55);
			break;
	}
	return data;
}

//-------------------------------------------------------------------------------------------------------------
// returns the distance to a particular planet
this.$getDistanceToPlanet = function $getDistanceToPlanet(sysID) {
	if (sysID < 0 || sysID > 255) return 0;
	var dist = 200;
	var route = System.infoForSystem(galaxyNumber, system.ID).routeToSystem(System.infoForSystem(galaxyNumber, sysID), "OPTIMIZED_BY_JUMPS");
	if (route) dist = route.distance;
	return dist;
}

//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padTextRight = function $padTextRight(currentText, desiredLength, leftSwitch) {
	if (currentText == null) currentText = "";
	var hairSpace = String.fromCharCode(31);
	var ellip = "…";
	var currentLength = defaultFont.measureString(currentText);
	var hairSpaceLength = defaultFont.measureString(hairSpace);
	// calculate number needed to fill remaining length
	var padsNeeded = Math.floor((desiredLength - currentLength) / hairSpaceLength);
	if (padsNeeded < 1) {
		// text is too long for column, so start pulling characters off
		var tmp = currentText;
		do {
			tmp = tmp.substring(0, tmp.length - 2) + ellip;
			if (tmp === ellip) break;
		} while (defaultFont.measureString(tmp) > desiredLength);
		currentLength = defaultFont.measureString(tmp);
		padsNeeded = Math.floor((desiredLength - currentLength) / hairSpaceLength);
		currentText = tmp;
	}
	// quick way of generating a repeated string of that number
	if (!leftSwitch || leftSwitch === false) {
		return currentText + new Array(padsNeeded).join(hairSpace);
	} else {
		return new Array(padsNeeded).join(hairSpace) + currentText;
	}
}

//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padTextLeft = function $padTextLeft(currentText, desiredLength) {
	return this.$padTextRight(currentText, desiredLength, true);
}

//-------------------------------------------------------------------------------------------------------------
this.$getSystemData = function $getSystemData(sysID) {
	var sys = System.infoForSystem(galaxyNumber, sysID);
	var data = {};
	if (!sys.concealment || sys.concealment === 0) {
		data["name"] = sys.name;
		data["economy"] = sys.economy;
		data["government"] = sys.government;
		data["techLevel"] = sys.techlevel;
		data["population"] = expandDescription("[sysdata-pop-value]", { population: sys.population });
		data["inhabitants"] = sys.inhabitants;
		data["productivity"] = sys.productivity;
		data["radius"] = sys.radius;
	} else {
		if (sys.concealment > 100) {
			data["name"] = "??";
		} else {
			data["name"] = sys.name;
		}
		data["economy"] = "??";
		data["government"] = "??";
		data["techLevel"] = "??";
		data["population"] = "??";
		data["inhabitants"] = "??";
		data["productivity"] = "??";
		data["radius"] = "??";
	}
	return data;
}

//-------------------------------------------------------------------------------------------------------------
// returns a list of sysInfos which match search criteria
this.$searchSystems = function $searchSystems() {
	this._searchMax = false;

	var list = SystemInfo.filteredSystems(this, function (other) {
		var result = false; // set initial value to false, so if we fail the concealment check, the result will be false
		if (!other.concealment || other.concealment === 0) {
			var gtlt = [">=", "<=", ">", "<"];
			result = true; // but now we're going to assume a true result, and look for reasons to fail it.
			var w = worldScripts.GalacticRegistry._search
			var desc = other.description.toLowerCase();
			var govd = this.$governmentDescription(other.government).toLowerCase();
			var ecod = this.$economyDescription(other.economy).toLowerCase();
			var inhd = other.inhabitants.toLowerCase();
			for (var i = 0; i < w.length; i++) {
				var or_w = null;
				var word = w[i];
				var or_loop = 0;
				var or_check = true;
				var check = false;
				// check for the or "|" switch
				if (word.indexOf("|") >= 0) {
					or_w = word.toLowerCase().split("|");
					word = or_w[or_loop];
				}
				do {
					if (desc.indexOf(word) >= 0) check = true;
					if (govd.indexOf(word) >= 0) check = true;
					if (ecod.indexOf(word) >= 0) check = true;
					if (inhd.indexOf(word) >= 0) check = true;
					if (word.indexOf("gov") == 0 || word.indexOf("eco") == 0 || word.indexOf("pop") == 0 || word.indexOf("prod") == 0 || word.indexOf("tl") == 0 || word.indexOf("rad") == 0) {
						var val = -1.0;
						var chk = 0.0;
						if (word.indexOf("gov") == 0) chk = other.government;
						if (word.indexOf("eco") == 0) chk = other.economy;
						if (word.indexOf("pop") == 0) chk = other.population / 10;
						if (word.indexOf("prod") == 0) chk = other.productivity;
						if (word.indexOf("tl") == 0) chk = other.techlevel + 1; // checking for format of tl>8
						if (word.indexOf("rad") == 0) chk = other.radius;
						for (var j = 0; j < gtlt.length; j++) {
							if (word.indexOf(gtlt[j]) >= 0) {
								val = parseFloat(word.split(gtlt[j])[1]);
								if (!isNaN(val)) {
									switch (j) {
										case 0:
											if (chk >= val) check = true;
											break;
										case 1:
											if (chk <= val) check = true;
											break;
										case 2:
											if (chk > val) check = true;
											break;
										case 3:
											if (chk < val) check = true;
											break;
									}
								}
								break;
							}
						}
					}
					if (word.indexOf("tl") == 0) { // checking for format tl8+
						// first check for a straight 1-1 test (eg tl8)
						if (word + " " == "tl" + (other.techlevel + 1).toString() + " ") check = true;
						// if that fails, lets do the +/- checks
						if (check == false) {
							var checkTL = 0;
							var dir = 0;
							// parse the input to get an integer version of the request TL and the direction we'll be testing
							if (word.indexOf("+") > 0) { checkTL = parseInt(word.substring(2, word.indexOf("+")), 10); dir = 1; }
							if (word.indexOf("-") > 0) { checkTL = parseInt(word.substring(2, word.indexOf("-")), 10); dir = -1; }
							if (checkTL > 0) {
								if (dir == 1 && (other.techlevel + 1) >= checkTL) check = true;
								if (dir == -1 && (other.techlevel + 1) <= checkTL) check = true;
							}
						}
					}
					if (or_w) {
						or_loop++;
						if (or_loop > or_w.length - 1) {
							or_check = false;
						} else {
							word = or_w[or_loop];
						}
					} else {
						or_check = false;
					}
				} while (or_check == true);
				if (check == false) result = check;
			}
		}
		return result;
	});
	if (list.length > (this._pageLength * 3)) {
		this._searchMax = true;
		for (var i = list.length - 1; i >= (this._pageLength * 3); i--) {
			list.splice(i, 1);
		}
	}
	return list;
}

//-------------------------------------------------------------------------------------------------------------
// returns true if "id" is one of the current permanent regions, otherwise false
this.$checkPermanentRegions = function $checkPermanentRegions(id) {
	if (!this._permanentChartData || !this._permanentChartData.regions) return false;
	var regions = this._permanentChartData.regions;
	for (var i = 0; i < regions.length; i++) {
		if (regions[i].id === id) return true;
	}
	return false;
}

//-------------------------------------------------------------------------------------------------------------
// removes a region from the permanent list
this.$removePermanentRegion = function $removePermanentRegion(id) {
	if (!this._permanentChartData || !this._permanentChartData.regions) return;
	var regions = this._permanentChartData.regions;
	for (var i = 0; i < regions.length; i++) {
		if (regions[i].id === id) {
			var dta = regions[i].systemIDList;
			for (var j = 0; j < dta.length; j++) {
				for (var k = 0; k < dta.length; k++) {
					if (j != k && dta[j] < dta[k]) {
						SystemInfo.setInterstellarProperty(galaxyNumber, dta[j], dta[k], 2, "link_color", "galreg_region");
					}
				}
			}
			regions.splice(i, 1);
			return;
		};
	}
}

//-------------------------------------------------------------------------------------------------------------
// returns true if "id" is one of the current permanent paths, otherwise false
this.$checkPermanentPaths = function $checkPermanentPaths(id) {
	if (!this._permanentChartData || !this._permanentChartData.paths) return false;
	var paths = this._permanentChartData.paths;
	for (var i = 0; i < paths.length; i++) {
		if (paths[i].id === id) return true;
	}
	return false;
}

//-------------------------------------------------------------------------------------------------------------
// removes a region from the permanent list
this.$removePermanentPath = function $removePermanentPath(id) {
	if (!this._permanentChartData || !this._permanentChartData.paths) return;
	var paths = this._permanentChartData.paths;
	for (var i = 0; i < paths.length; i++) {
		if (paths[i].id === id) {
			var dta = paths[i].systemIDList;
			for (var j = 0; j < dta.length; j++) {
				for (var k = 0; k < dta.length; k++) {
					if (j != k && dta[j] < dta[k]) {
						SystemInfo.setInterstellarProperty(galaxyNumber, dta[j], dta[k], 2, "link_color", "galreg_region");
					}
				}
			}
			paths.splice(i, 1);
			return;
		};
	}
}

//-------------------------------------------------------------------------------------------------------------
// returns true if "id" is one of the current permanent systems, otherwise false
this.$checkPermanentSystems = function $checkPermanentSystems(id) {
	if (!this._permanentChartData || !this._permanentChartData.systems) return false;
	var syslist = this._permanentChartData.systems;
	for (var i = 0; i < syslist.length; i++) {
		if (syslist[i].id === id) return true;
	}
	return false;
}

//-------------------------------------------------------------------------------------------------------------
// removes a list of systems from the permanent list
this.$removePermanentSystems = function $removePermanentSystems(id) {
	if (!this._permanentChartData || !this._permanentChartData.systems) return;
	var syslist = this._permanentChartData.systems;
	for (var i = syslist.length - 1; i >= 0; i--) {
		if (syslist[i].id === id) {
			var dta = syslist[i].systemIDList;
			for (var j = 0; j < dta.length; j++) {
				mission.unmarkSystem({ system: dta[j], name: "galreg_marked" });
			}
			syslist.splice(i, 1);
		};
	}
}

//-------------------------------------------------------------------------------------------------------------
// removes any stored historic permanent markers/properties
this.$removeHistoricPermanentMarkers = function $removeHistoricPermanentMarkers() {
	// remove an permanent markings
	var i = 0;
	var j = 0;
	var k = 0;
	if (this._permanentRegions.length > 0) {
		var regions = this.$getRegionData();
		for (i = 0; i < this._permanentRegions.length; i++) {
			var dta = regions[this._permanentRegions[i]].data;
			for (j = 0; j < dta.length; j++) {
				for (k = 0; k < dta.length; k++) {
					if (j != k && dta[j] < dta[k]) {
						SystemInfo.setInterstellarProperty(galaxyNumber, dta[j], dta[k], 2, "link_color", "galreg_region");
					}
				}
			}
		}
	}
	if (this._permanentLanes.length > 0) {
		var lanes = this.$getSpacelanes();
		for (i = 0; i < this._permanentLanes.length; i++) {
			var lane = lanes[this._permanentLanes[i]];
			var dta = lane.data;
			for (j = 0; j < dta.length - 1; j++) {
				var c1 = System.infoForSystem(galaxyNumber, dta[j]).concealment;
				if (!c1) c1 = 0;
				var c2 = System.infoForSystem(galaxyNumber, dta[j + 1]).concealment;
				if (!c2) c2 = 0;
				if (c1 <= 100 && c2 <= 100) {
					if (dta[j] < dta[j + 1]) {
						SystemInfo.setInterstellarProperty(galaxyNumber, dta[j], dta[j + 1], 2, "link_color", "galreg_region");
					} else {
						SystemInfo.setInterstellarProperty(galaxyNumber, dta[j + 1], dta[j], 2, "link_color", "galreg_region");
					}
				}
			}
		}
		for (var i = mission.markedSystems.length - 1; i >= 0; i--) {
			if (mission.markedSystems[i].name.indexOf(this.name) >= 0 || mission.markedSystems[i].name.indexOf("galreg_marked") >= 0)
				mission.unmarkSystem({ system: mission.markedSystems[i].system, name: mission.markedSystems[i].name });
		}
	}
	this._permanentRegions.length = 0;
	this._permanentLanes.length = 0;
	delete this._permanentRegions;
	delete this._permanentLanes;
}
Scripts/galactic_registry_conditions.js
"use strict";
this.name        = "GalacticRegistry_Conditions";
this.author      = "phkb";
this.copyright   = "2015 phkb";
this.description = "Condition script for Galactic Registry equipment";
this.license     = "CC BY-NC-SA 3.0";

//-------------------------------------------------------------------------------------------------------------
this.allowAwardEquipment = function(equipment, ship, context) {
	if (context == "scripted") return true;
	return false;
}