Back to Index Page generated: May 8, 2024, 6:16:03 AM

Expansion Market Inquirer

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Market Inquirer adds an MFD that shows the markets of the main station and selected stations closest to the player. ASC is needed. When docked, information about distances and markets is available from the interfaces (f4). Market Inquirer adds an MFD that shows the markets of the main station and selected stations closest to the player. ASC is needed. When docked, information about distances and markets is available from the interfaces (f4).
Identifier oolite.oxp.spara.market_inquirer oolite.oxp.spara.market_inquirer
Title Market Inquirer Market Inquirer
Category Equipment Equipment
Author spara spara
Version 1.14.1 1.14.1
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL http://wiki.alioth.net/index.php/Market_Inquirer n/a
Download URL https://wiki.alioth.net/img_auth.php/0/06/Market_inquirer_1.14.1.oxz n/a
License CC-BY-NC-SA 4.0 CC-BY-NC-SA 4.0
File Size n/a
Upload date 1610873215

Documentation

Also read http://wiki.alioth.net/index.php/Market%20Inquirer

market_inquirer_readme_&_license.txt

Market Inquirer OXP ver 1.14.1 (12.10.2020)

Author: spara with additions by phkb

_Overview_

Market Inquirer adds an interface screen (f4) that shows the distances in system and an interface screen that shows the markets (prices and quantities) of the main station and selected stations closest to the player. Stations selected (if present) are

* Sfep stations (as secondary GalCop stations)

Interface screens are always available when docked to the selected stations and if ASC is installed, then at every station.

This oxp also enhances the ASC equipment by adding a free primable equipment Inquirer (prime with shift-n) that shows aforementioned market screen when pressing n and b using MFD. Inquirer MFD costs 1050.

If there are more than six stations to show the markets of, the inquirer uses multiple pages for the information. Pages can be switched by choosing "swap".

If Navigation MFD is installed, distances are shown in the same unit it uses. Otherwise kilOometes are used.

If you want to add a station to the list of selected stations, you can add one of it's roles to the this.$inquirerStations list of this oxp or you can add the role "inquirer_station" to the station's roles.

_Recommended oxps in addition to the aforementioned ones_

* Market Observer. This oxp shows in-flight information from Market Observer, if present.
* Distant Suns by Wildeblood (for sun names)
* Planetary Compass by Thargoid (for planet/moon names)

_Requirements_

* Oolite 1.81

_Installing_

Install the OXP by copying market_inquirer.oxp to your AddOns-folder.

------

This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 4.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/

Equipment

Name Visible Cost [deci-credits] Tech-Level
Market Inquirer MFD yes 10500 7+
Remove Market Inquirer MFD yes 100 7+

Ships

This expansion declares no ships.

Models

This expansion declares no models.

Scripts

Path
Config/script.js
"use strict";
this.name        = "market_inquirer"; 

//1.14.1 Added the current station to the station interface when the current station is not registered
//1.14.1 Changed the default from exit to swap in the station interface -fix by phkb-
//1.14 Fixed breakage from updating Nav MFD (phkb)
//1.13.1 Fixed main station undefined bug (apparent when not using smugglers underground oxp)
//1.13 Added ability to select the commodities to be shown on F4 screen. Not to mention quite a few lines of compatiblity fixes to better work with phkb's other oxps -changes by phkb-
//1.12.1 fixed the dublication issue when the main station is an inquirer station.
//1.12 Kiotas are back in the mix
//1.11 for Oolite 1.81 and Market Observer 3.x
//1.11 enabled the market screen and destinations screen to appear on start up.
//1.10.1 bug fix from mossfoot's report
//1.10 market observer buy log link
//1.10 mfd equipment
//1.9.1 fixed navi_mfd link in distances interface
//1.9 mission screen replaced with mfd and market hack is removed
//1.8 brought mission screens back and tidied up a bit
//1.7 removed in-flight mission screens and equipment and replaced them with a market hack.
//1.6 rename Navigation buoy to main station.
//1.6 hide the beacon of the station you're docked
//1.5 added pager to market viewer
//1.5 added sirf to inquirer stations
//1.5 limit station service to inquirerStations
//1.5 distances interface
//1.4 added more stations and inquirer_station role to the inquirer.
//1.4 moved station definitions to startUp.

this._menuColor = "yellowColor";
this._itemColor = "yellowColor";
this._disabledColor = "darkGrayColor";
this._maxslots = 17; // maximum number of commodity viewing slots

this.startUp = function() {
	//stations noted by market inquirer. any role of the station will do.
	this.$inquirerStations = ["sfep_station", "wildShips_kiota", "inquirer_station"];
	//this.$inquirerStations = ["inquirer_station", "sfep_station", "wildShips_kiota", "sothis", "constore", "pagroove_superhub", "casinoship", "rescue_station", "GRS-Station", "SIRF-YARD"];
	this.$commodity = 0;
	if (worldScripts["market_observer3"])
		this.$marketObserver = true;
	else this.$marketObserver = false;
}

this.startUpComplete = function() {
	this.$commodities = this.$gatherCommodities();
	this.shipDockedWithStation(player.ship.dockedStation);
	if (missionVariables.MarketInquirer_SelectedCommodities) this._selected = JSON.parse(missionVariables.MarketInquirer_SelectedCommodities);
	if (!this._selected) {
		// default to core commodities
		this._selected = ["food", "textiles", "radioactives", "slaves", "liquor_wines", "luxuries", "narcotics", "computers", "machinery", "alloys", "firearms", "furs", "minerals", "gold", "platinum", "gem_stones", "alien_items"];
		// remove anything that doesn't exist anymore (eg if an OXP has removed this commodity altogether)
		for (var i = this._selected.length - 1; i >= 0; i--) {
			if (!system.mainStation.market[this._selected[i]]) this._selected.splice(i, 1);
		}
	}
}

this.playerWillSaveGame = function() {
	missionVariables.MarketInquirer_SelectedCommodities = JSON.stringify(this._selected);
}

//make a list of commodities
this.$gatherCommodities = function() {
	var tempCommodities = new Array();
	for (var i in system.mainStation.market) {
		tempCommodities.push([i, system.mainStation.market[i].sort_order]);
	}
	//first order by name
	tempCommodities.sort();
	//then order by sort_order
	tempCommodities.sort(function(a, b) {return a[1] - b[1]});
	var commodities = new Array();
	for (var i = 0; i < tempCommodities.length; i++)
		commodities.push(tempCommodities[i][0]);
	return commodities;
}

this.$changeCommodity = function(action) {
	if (player.ship.equipmentStatus("EQ_ADVANCED_COMPASS") === "EQUIPMENT_OK") {
		this.$commodity = this.$commodity + action;
		if (this.$commodity < 0)
			this.$commodity = this.$commodities.length - 1;
		else if (this.$commodity > this.$commodities.length - 1)
			this.$commodity = 0;
		this.$commodityPrices();
	}
	else player.consoleMessage("Inquirer malfunction. ASC is not responding.");
}

this.shipLaunchedFromStation = this.shipExitedWitchspace = function() {
	this.$commodityPrices();
}

this.$commodityPrices = function() {
	if (player.ship.equipmentStatus("EQ_MARKET_INQUIRER_MFD") !== "EQUIPMENT_OK") {
		player.ship.setMultiFunctionText("inquirer_mfd", null);
		return;
	}
	if (!system.mainStation)
		var message = "No market data available.";
	else {
		var commodity = this.$commodities[this.$commodity];
		var hairSpace = String.fromCharCode(31);
		var noUnits = "--";
		var width = global.defaultFont.measureString(666);
		while (global.defaultFont.measureString(" " + noUnits) < width)
			noUnits = " " + noUnits;
		while (global.defaultFont.measureString(hairSpace + noUnits) < width)
			noUnits = hairSpace + noUnits;
		var stations = system.filteredEntities(this, this.$stations, player.ship);
		var price = formatCredits(system.mainStation.market[commodity].price);
		var quantity = system.mainStation.market[commodity].quantity;
		if (quantity === 0) quantity = noUnits;
		else quantity = formatUnits(quantity);
        var lgl = "";
		if (worldScripts.Smugglers_Illegal) {
			if (system.mainStation.market[commodity].legality_import != 0) lgl = " (Imp)";
			if (system.mainStation.market[commodity].legality_export != 0) lgl = " (Exp)";
		}
		var statBlock = price + " /" + quantity + " Main Station" + lgl + "\n";
		for (var i = 0; i < stations.length; i++) {
			var name = stations[i].displayName;
			price = formatCredits(stations[i].market[commodity].price);
			quantity = stations[i].market[commodity].quantity;
			if (quantity === 0) quantity = noUnits;
			else quantity = formatUnits(quantity);
			lgl = "";
			if (stations[i].market[commodity].legality_import != 0) lgl = " (Imp)";
			if (stations[i].market[commodity].legality_export != 0) lgl = " (Exp)";
			statBlock = statBlock + truncate(price + " /" + quantity + " " + name + lgl) + "\n";
		}

		var message = expandDescription("[commodity-name " + commodity +"]");
			
		if (manifest[commodity] > 0)
			message += " (" + manifest[commodity] + ")";
		if (this.$marketObserver && worldScripts["market_observer3"].$priceData[commodity]) {
			var observer = worldScripts["market_observer3"];
			var referencePrice = "Avg: " + global.formatCredits(observer.$priceData[commodity].average/10, true, false);
			while (global.defaultFont.measureString(message + " " + referencePrice) < 14.3) {
				referencePrice = " " + referencePrice;
			}
			var hairSpace = String.fromCharCode(31);
			while (global.defaultFont.measureString(message + hairSpace + referencePrice) < 14.3) {
				referencePrice = hairSpace + referencePrice;
			}
			message += referencePrice;
			var buyLog = observer.$buyLog;
			if (buyLog[this.$commodities[this.$commodity]]) {
				//add buy log to the second line
				var logLine = "(";
				for (var i = 0; i < buyLog[commodity].length; i++) {
					var logEvent = buyLog[commodity][i][0] + " x " +  global.formatCredits(buyLog[commodity][i][1]/10, true, false);
					if (global.defaultFont.measureString(logLine + logEvent + "...)") < 14.5) 
						logLine += logEvent + ", ";
					else break;
				}
				message += "\n" + logLine;
				message = message.slice(0, -2);
				//too many log events to show?
				if (buyLog[commodity].length > i)
					message += "..."; 
				message += ")";
			}
			else message += "\n";
		}
		message += "\n";
		message += statBlock;
	}
	player.ship.setMultiFunctionText("inquirer_mfd", message);
	//helper function to truncate lines
	function truncate(line) {
		var lastChar = "";
		while (global.defaultFont.measureString(line) > 14) {
			lastChar = line.charAt(line.length - 1);
			line = line.slice(0, -1);
		}
		if (lastChar === "") return line;
		if (line.charAt(line.length - 1) === " " || lastChar === " ")
			return line;
		if (line.charAt(line.length - 2) === " ") 
			return line.slice(0, -1);
		line = line + ".";
		while (global.defaultFont.measureString(line) > 14) {
			line = line.slice(0, -2);
			line = line + ".";
		}
		return line;
	}
	//helper function to format credits
	function formatCredits(credits) {
		if (credits < 99.5) 
			return "    " + global.formatCredits(credits/10, true, false);
		else if (credits < 999.5)
			return "  " + global.formatCredits(credits/10, true, false);
		else return global.formatCredits(credits/10, true, false);
	};
	//helper function to format units
	function formatUnits(units) {
		if (units < 10) return "    " + units;
		else if (units < 100 ) return "  " + units;
		else return units;
	};
}

//Add f4 interfaces when docked
this.shipDockedWithStation = function(station) {
	if (player.ship.equipmentStatus("EQ_ADVANCED_COMPASS") === "EQUIPMENT_OK" || this.$stations(station) || station.isMainStation)
		this.$marketInquirerInterface();
};

//remove interfaces
this.$removeInterfaces = this.shipWillLaunchFromStation = function() {
	player.ship.dockedStation.setInterface("inquirer_market",null);
	player.ship.dockedStation.setInterface("inquirer_distances",null);
}

//Add interfaces
this.$marketInquirerInterface = function() {
	player.ship.dockedStation.setInterface("inquirer_market",{
		title: "Commodity markets",
		category: "Commerce",
		summary: "Show commodity markets of selected stations in system.",
		callback: this.$showMarkets.bind(this)
	});
	player.ship.dockedStation.setInterface("inquirer_distances",{
		title: "In-system distances",
		category: "Informational",
		summary: "Show distances to the star, planets, moons and beacons in system.",
		callback: this.$showDistances.bind(this)
	});	
};

//function to filter suitable stations
this.$stations = function(entity) {	
	if (entity.isStation && !entity.isMainStation) {
		var k;
		for (k = 0; k < this.$inquirerStations.length; k++) {
			if (entity.hasRole(this.$inquirerStations[k]))
				return true;
		}	
	}
	return false;
};

//build and show markets screen
this.$showMarkets = function(page) {
	
	var text = "";
	var hairSpace = String.fromCharCode(31);
	var stations = new Array();
	//No asc
	if (player.ship.docked && (player.ship.equipmentStatus("EQ_ADVANCED_COMPASS") !== "EQUIPMENT_OK" && !player.ship.dockedStation.isMainStation && !this.$stations(player.ship.dockedStation))) {
		text = "No market data available.";
		this.$removeInterfaces();
	}
	//sanity check
	else if (system.isInterstellarSpace || !system.sun || system.sun.isGoingNova || system.sun.hasGoneNova || !system.mainStation) {
		text = "No market data available.";
	}
	//let's rock
	else {
		if (typeof page === 'undefined' || page === 'inquirer_market') page = 0;
		var commodities  = this.$gatherCommodities();
		var i,j, quantity;
		// remove unselected commodities
		for (i = commodities.length - 1; i >= 0; i--) {
			if (this._selected.indexOf(commodities[i]) === -1) commodities.splice(i, 1);
		}
		//description column width
		var descriptionWidth = Math.ceil(global.defaultFont.measureString("Liquor/Wines:"));
		//width for market data columns
		var dataWidth = 31 - descriptionWidth;
		//minimum width for market data column
		var minColWidth = global.defaultFont.measureString(" "+formatCredits(1020)+" / 64 ");
		//maximum number of data columns per page
		var maxCols = Math.floor(dataWidth / minColWidth);
		//filtered stations
		stations = system.filteredEntities(this, this.$stations, player.ship);
		// add the current, possibly unregistered, station to the start of the list
		if (!this.$stations(player.ship.dockedStation) && !player.ship.dockedStation.isMainStation) {
			stations.unshift(player.ship.dockedStation);
		}
		// add main station to the start of the list
		stations.unshift(system.mainStation);
		//handle swapping back to start
		if (page > stations.length / maxCols) page = 0;
		var sfepStations = new Array();
		//page handling
		var startInd = page * maxCols;
		//show full pages
		if (startInd > 0 && stations.length > maxCols && startInd + maxCols > stations.length - 1)
			startInd = stations.length - maxCols;
		//select stations to show
		for (i = startInd; i < startInd + maxCols; i++) {
			sfepStations.push(stations[i]);
			if (i > stations.length - 2) break;
		}
		//calculate actual data column width
		if (sfepStations.length >= maxCols) var colWidth = dataWidth / maxCols;
		else var colWidth = (dataWidth) / (sfepStations.length);
		//array for formatted (truncated and centered) stations names
		var statNames = new Array();
		//add the station names to the array
		for (i = 0; i < sfepStations.length; i++) {
			if (sfepStations[i].isMainStation)
				statNames.push(format("Main Station", colWidth));
			else statNames.push(format(sfepStations[i].displayName, colWidth));
		}
		//tabulate over the description column
		while (global.defaultFont.measureString(text) < descriptionWidth - 0.1)
			text = text + " ";
		while (global.defaultFont.measureString(text) < descriptionWidth)
			text = text + hairSpace;

		//add and tabulate station names
		for (i = 0; i < statNames.length; i++) {
			text = text + statNames[i];
			while (global.defaultFont.measureString(text) < (descriptionWidth) + colWidth * (i + 1) - 0.1)
				text = text + " ";
			while (global.defaultFont.measureString(text) < (descriptionWidth) + colWidth * (i + 1))
				text = text + hairSpace;
			if (i === maxCols - 1) break;
		}
		text += "\n";
		// we can add an extra space when there will only be 2 menu options
		if (stations.length <= maxCols || stations.length === 0) text += "\n";
		//then the prices
		for (j = 0; j < commodities.length; j++) {
			var line = "";
			//add commodity name
			line = expandDescription("[commodity-name " + commodities[j]+"]")+": ";
			//tabulate
			while (global.defaultFont.measureString(line) < descriptionWidth - 0.1)
				line = line + " ";
			while (global.defaultFont.measureString(line) < descriptionWidth)
				line = line + hairSpace;
			//add prices/quantities
			for (i = 0; i < sfepStations.length; i++) {
				quantity = sfepStations[i].market[commodities[j]].quantity;
				if (quantity === 0) {
					quantity = " --";
					var width = global.defaultFont.measureString("00");
					while (global.defaultFont.measureString(quantity) < width)
						quantity = hairSpace + quantity;
				}
				else quantity = formatUnits(quantity);
				var price = sfepStations[i].market[commodities[j]].price;
				line = line + format(formatCredits(price)+" / "+quantity, colWidth);
				while (global.defaultFont.measureString(line) < descriptionWidth + colWidth * (i + 1) - 0.1)
					line = line + " ";
				while (global.defaultFont.measureString(line) < descriptionWidth + colWidth * (i + 1))
					line = line + hairSpace;
				if (i === maxCols - 1) break;
			}
			text = text + line + "\n";
		}
	}
	//select the correct background image
	var bgImage = "sfep_flight.png";
	if (player.ship.docked) bgImage = "sfep_docked.png";
	//select correct options
	var options = {
		"0_SELECT" : "Select commodities to view",
		"1_NEXT" : "Swap",
		"2_QUIT" : "Exit"
	};
	var def = "1_NEXT";
	if (stations.length <= maxCols || stations.length === 0) {
		options = {
			"0_SELECT" : "Select commodities to view",
			"2_QUIT" : "Exit"
		};
		def = "2_QUIT"; 
	}
	//finally, the mission screen
	mission.runScreen({
		title: "Commodity Markets of " + system.name,
		screenID:"marketinquirer-markets",
		message: text,
		choices: options,
		background: bgImage,
		exitScreen: "GUI_SCREEN_INTERFACES",
		initialChoicesKey: def
	},
	function (choice) {
		if (choice === "1_NEXT") worldScripts.market_inquirer.$showMarkets(page + 1);
		if (choice === "0_SELECT") worldScripts.market_inquirer.$selectCommoditiesToView();
	});
	//helper function to format credits
	function formatCredits(credits) {
		if (credits < 99.5) 
			return "    " + global.formatCredits(credits/10, true, false);
		else if (credits < 999.5)
			return "  " + global.formatCredits(credits/10, true, false);
		else return global.formatCredits(credits/10, true, false);
	};
	//helper function to format units
	function formatUnits(units) {
		if (units < 10) return "  " + units;
		else return units;
	};
	//helper function to truncate and center station names
	function format(string, width) {
		//if too wide, truncate
		if (global.defaultFont.measureString(string) >= width) {
			var lastChar = "";
			while (global.defaultFont.measureString(string) > width - 1) {
				lastChar = string.charAt(string.length - 1);
				string = string.slice(0, -1);
			}
			if (string.charAt(string.length - 1) === " ")
				string = string.slice(0, -1);
			else if (lastChar !== " ")
				string = string + ".";
		}
		var stringWidth = global.defaultFont.measureString(string);
		//if too narrow, center 
		if (stringWidth < width) {
			var fill = (width - stringWidth) / 2;
			var tab = " ";
			while (global.defaultFont.measureString(tab) < fill)
				tab = tab + " ";
			string = tab + string;
		};
		return string;
	};
};

this.$selectCommoditiesToView = function() {
	
	var list = this.$gatherCommodities();

	var text = "Select commodities to view (" + this._selected.length + " of " + this._maxslots + " selected):\n\n";
	var itemcount = 0;
	var curChoices = {};
	var pagesize = 15;
	if (this.$isBigGuiActive() === true) pagesize = 21;

	if (typeof this._selpage === "undefined") this._selpage = 0;
	if (list.length > 0) {
		var maxpage = Math.ceil(list.length / pagesize);
		if (maxpage < (this._selpage + 1)) this._selpage -= 1;
		var end = ((this._selpage * pagesize) + pagesize);
		if (end > list.length) end = list.length;
		// note: then station equipmentPriceFactor has been removed to prevent exploitation of equipment sales at different stations (galcop => rock hermit)
		for (var i = (this._selpage * pagesize); i < end; i++) {
			curChoices["01_CMDTY-" + (i < 10 ? "0" : "") + i + "~" + list[i]] =
				{text:this.$padTextRight((this._selected.indexOf(list[i]) >= 0 ? "X" : " "), 3) +
					displayNameForCommodity(list[i]),
					alignment:"LEFT", color:this._menuColor};
			itemcount += 1;
		}
		for (var i = 0; i < ((pagesize + 1) - itemcount); i++) {
			curChoices["90_SPACER_" + i] = "";
		}
	} else {
		text += "No commodities?";
	}

	if (maxpage > 1 && this._selpage < (maxpage - 1)) {
		curChoices["95_NEXT"] = {text:"Next page", color:this._itemColor};
	} else {
		curChoices["95_NEXT"] = {text:"Next page", color:this._disabledColor, unselectable:true};
	}
	if (this._selpage > 0) {
		curChoices["96_PREV"] = {text:"Previous page", color:this._itemColor};
	} else {
		curChoices["96_PREV"] = {text:"Previous page", color:this._disabledColor, unselectable:true};
	}
	curChoices["99_EXIT"] = {text:"Return", color:this._itemColor};

	var def = "99_EXIT";
	if (this._lastChoice && this._lastChoice !== "") def = this._lastChoice;

	//select the correct background image
	var bgImage = "sfep_flight.png";
	if (player.ship.docked) bgImage = "sfep_docked.png";

	var opts = {
		screenID: "marketinquirer-markets",
		title: "Select Commodities",
		allowInterrupt: false,
		choices: curChoices,
		background: bgImage,
		initialChoicesKey: def,
		message: text
	};
	mission.runScreen(opts, this.$chooseCommodity, this);
}

this.$chooseCommodity = function(choice) {
	if (choice == null) return;

	if (choice.indexOf("01_CMDTY") >= 0) {
		var sel = choice.substring(choice.indexOf("~") + 1);
		if (this._selected.indexOf(sel) >= 0) {
			this._selected.splice(this._selected.indexOf(sel), 1);
		} else {
			if (this._selected.length < this._maxslots) {
				this._selected.push(sel);
			} else {
				player.consoleMessage("Unable to add commodity - too many already selected", 5);
			}
		}
		this._lastChoice = choice;
	}
	if (choice === "95_NEXT") {this._selpage += 1; this._lastChoice = choice;}
	if (choice === "96_PREV") {this._selpage -= 1; this._lastChoice = choice;}

	if (choice !== "99_EXIT") {
		this.$selectCommoditiesToView();
		return;
	}
	this.$showMarkets();
}

//build and show distances screen
this.$showDistances = function() {
	var text = "";
	//No asc
	if (player.ship.docked && player.ship.equipmentStatus("EQ_ADVANCED_COMPASS") !== "EQUIPMENT_OK" && !player.ship.dockedStation.isMainStation && !this.$stations(player.ship.dockedStation)) {
		text = "No distance data available.";
		this.$removeInterfaces();
	}
	//sanity check;
	else if (system.isInterstellarSpace) {
		text = "No distance data available.";
	}
	else {
		//define distance unit
		var unitBase = 1000;
		var unit = "km";
		var rnd = 3;
		//use the same unit as Updating TSC
		if (worldScripts.navi_mfd) {
			var ver = worldScripts.navi_mfd.version.split(".");
			if (parseInt(ver[0]) > 1 || (ver[0] === "1" && parseInt(ver[1]) >= 9)) {
				unitBase = worldScripts.navi_mfd.$ostronomicalUnits[worldScripts.navi_mfd.$unitSetting];
				unit = worldScripts.navi_mfd.$distUnits[worldScripts.navi_mfd.$unitSetting];
				rnd = worldScripts.navi_mfd.$rounding[worldScripts.navi_mfd.$unitSetting]
			} else {
				unitBase = worldScripts.navi_mfd.$ostronomicalUnit;
				unit = worldScripts.navi_mfd.$distUnit;
			}
		}
		var i;
		var lines = new Array();
		//star
		if (system.sun) {
			var name = "Sun";
			if (system.info.sun_name) name = system.info.sun_name;
			lines.push(["Star:",""]);
			lines.push(["* " +name, dist(system.sun, rnd)]);
			lines.push([" ",""]);
		};
		//planets
		var planets = system.filteredEntities(this, planets, player.ship);
		if (planets.length !== 0) {
			lines.push(["Planets:",""]);
			for (i = 0; i < planets.length; i++) {
				if (planets[i].displayName)
					lines.push(["* " + planets[i].displayName.replace(" (Planet)",""),dist(planets[i], rnd)]);
				else lines.push(["* Planet " + (i+1),dist(planets[i], rnd)]);
			}
			lines.push([" ",""]);
		};
		//moons
		var moons = system.filteredEntities(this, moons, player.ship);
		if (moons.length !== 0) {
			lines.push(["Moons:",""]);
			for (i = 0; i < moons.length; i++) {
				if (moons[i].displayName)
					lines.push(["* " + moons[i].displayName.replace(" (Moon)",""),dist(moons[i], rnd)]);
				else lines.push(["* Moon " + (i+1),dist(moons[i], rnd)]);
			}
			lines.push([" ",""]);
		};
		//beacons
		var beacons = system.filteredEntities(this, beacons, player.ship);
		if (beacons.length !== 0) {
			lines.push(["Beacons:",""]);
			for (i = 0; i < beacons.length; i++) {
				if (beacons[i].displayName) {
					if (!player.ship.docked || player.ship.position.distanceTo(beacons[i]) > 10E4) {
						if (beacons[i].displayName === "Navigation Buoy" && system.mainStation.position.distanceTo(beacons[i]) <= 10E4)
							lines.push(["* " + "Main Station Buoy", dist(beacons[i], rnd)]);
						else
							lines.push(["* " + beacons[i].displayName, dist(beacons[i], rnd)]);
					}
				}
				else lines.push(["* Beacon " + (i+1)+": ", dist(beacons[i], rnd)]);
			}
		}
		//build lines for mission screen
		var column1 = lines;
		var column2 = new Array();
		if (column1.length > 19)
			column2 = column1.splice(19, column1.length - 19);
		for (i = 0; i < column1.length; i++) {
			if (column2.length > i)
				text = text + formatStrToCol(column1[i][0], column1[i][1], 15.5) + formatStrToCol(column2[i][0], column2[i][1], 15.5) + "\n";
			else
			text = text + formatStrToCol(column1[i][0], column1[i][1], 31) + "\n";
		}
	}
	//show mission screen
	var bgImage = "sfep_flight.png";
	if (player.ship.docked) bgImage = "sfep_docked.png";
	var options = {
			"1_QUIT" : "Exit"
	}
	mission.runScreen({
		title: "Distances of " + system.name,
		screenID:"marketinquirer-distances",
		message: text,
		choices: options,
		background: bgImage,
		exitScreen: "GUI_SCREEN_INTERFACES"
	});

	//helper functions
	function planets(entity) {return (entity.isPlanet && entity.hasAtmosphere)};
	function moons(entity) {return (entity.isPlanet && !entity.hasAtmosphere)};
	function beacons(entity) {return entity.isBeacon};
	function dist(entity, rounding) {
		var distInKm = (player.ship.position.distanceTo(entity) - entity.collisionRadius)/unitBase;
		return (distInKm.toFixed(rounding) + " " + unit);
	};
	//format columns
	function formatStrToCol(name, distStr, colWidth) {
		//if too wide, truncate
		var punct = "";
		if (distStr !== "") punct = ": ";
		if (global.defaultFont.measureString(name+punct+distStr) > colWidth) {
			var lastChar = "";
			while (global.defaultFont.measureString(name+punct+distStr) > colWidth) {
				lastChar = name.charAt(name.length - 1);
				name = name.slice(0, -1);
			}
			if (name.charAt(name.length - 1) === " ")
				name = name.slice(0, -1);
			else if (lastChar !== " ")
				name = name + ".";
		}
		//if too narrow, add spaces to end 
		while (global.defaultFont.measureString(name+punct+distStr) < colWidth) {
			distStr = distStr + " ";
		};
		if (distStr.charAt(distStr.length - 1) === " ")
			distStr = distStr.slice(0, -1);
		return name + punct + distStr;
	};	
}

this.playerBoughtEquipment = function(equipment) {
	if (equipment === "EQ_MARKET_INQUIRER_MFD_REMOVE") {
		player.ship.removeEquipment("EQ_MARKET_INQUIRER_MFD");
		player.ship.removeEquipment("EQ_MARKET_INQUIRER_MFD_REMOVE");
	}
}

//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padTextRight = function(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(currentText, desiredLength) {
	return this.$padTextRight(currentText, desiredLength, true);
}

//-------------------------------------------------------------------------------------------------------------
// returns true if a HUD with allowBigGUI is enabled, otherwise false
this.$isBigGuiActive = function() {
	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;
		}
	}
}
Scripts/market_inquirer.js
"use strict";
this.name        = "market_inquirer_equipment_script"; 
this.author      = "spara"; 
this.copyright   = "2013 - 2014 Mika Spara";
this.licence     = "CC BY-NC-SA 3.0"; 
this.description = "equipment activation script"; 
this.version     = "1.10";

//equipment activation n
this.activated = function() {
	worldScripts.market_inquirer.$changeCommodity(1);
};

//equipment activation b
this.mode = function() {
	worldScripts.market_inquirer.$changeCommodity(-1);
};

this.allowAwardEquipment = function() {
	if (player.ship.dockedStation.isMainStation || worldScripts.market_inquirer.$stations(player.ship.dockedStation))
		return true;
	return false;
}