| Config/script.js | "use strict";
this.name = "market_inquirer";
//1.14.2 Moved all text to descriptions.plist for easier localisation. Removed some odd characters in the code.
//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 compatibility fixes to better work with phkb's other oxps -changes by phkb-
//1.12.1 fixed the duplication 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(expandDescription("[mi_malfunction]"));
}
//-------------------------------------------------------------------------------------------------------------
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 = expandDescription("[mi_no_market]");
	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 + " " + expandDescription("[mi_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 = " " + expandDescription("[mi_illegal_import]");
			if (stations[i].market[commodity].legality_export != 0) lgl = " " + expandDescription("[mi_illegal_export]");
			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 = expandDescription("[mi_average]") + ": " + 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: expandDescription("[mi_markets_interface_title]"),
		category: expandDescription("[mi_markets_interface_category]"),
		summary: expandDescription("[mi_markets_interface_summary]"),
		callback: this.$showMarkets.bind(this)
	});
	player.ship.dockedStation.setInterface("inquirer_distances", {
		title: expandDescription("[mi_distances_interface_title]"),
		category: expandDescription("[mi_distances_interface_category]"),
		summary: expandDescription("[mi_distances_interface_summary]"),
		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 = expandDescription("[mi_no_market]");
		this.$removeInterfaces();
	}
	//sanity check
	else if (system.isInterstellarSpace || !system.sun || system.sun.isGoingNova || system.sun.hasGoneNova || !system.mainStation) {
		text = expandDescription("[mi_no_market]");
	}
	//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(expandDescription("[commodity-name 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(expandDescription("[mi_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": expandDescription("[mi_select_commodities]"),
		"1_NEXT": expandDescription("[mi_next]"),
		"2_QUIT": expandDescription("[mi_exit]")
	};
	var def = "1_NEXT";
	if (stations.length <= maxCols || stations.length === 0) {
		options = {
			"0_SELECT": expandDescription("[mi_select_commodities]"),
			"2_QUIT": expandDescription("[mi_exit]")
		};
		def = "2_QUIT";
	}
	//finally, the mission screen
	mission.runScreen({
		title: expandDescription("[mi_commodity_market_location]"),
		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 = expandDescription("[mi_select_view]", { num: this._selected.length, max: this._maxslots }) + ":\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 += expandDescription("[mi_none_selected]");
	}
	if (maxpage > 1 && this._selpage < (maxpage - 1)) {
		curChoices["95_NEXT"] = { text: "[mi_next_page]", color: this._itemColor };
	} else {
		curChoices["95_NEXT"] = { text: "[mi_next_page]", color: this._disabledColor, unselectable: true };
	}
	if (this._selpage > 0) {
		curChoices["96_PREV"] = { text: "[mi_prev_page]", color: this._itemColor };
	} else {
		curChoices["96_PREV"] = { text: "[mi_prev_page]", color: this._disabledColor, unselectable: true };
	}
	curChoices["99_EXIT"] = { text: "[mi_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: expandDescription("[mi_screen_title]"),
		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(expandDescription("[mi_too_many]"), 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 = expandDescription("[mi_no_distance_data]");
		this.$removeInterfaces();
	}
	//sanity check;
	else if (system.isInterstellarSpace) {
		text = expandDescription("[mi_no_distance_data]");
	}
	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;
			}
		}
		if (rnd > 4) rnd = 4;
		var i;
		var lines = new Array();
		//star
		if (system.sun) {
			var name = expandDescription("[mi_sun]");
			if (system.info.sun_name) name = system.info.sun_name;
			lines.push([expandDescription("[mi_star]") + ":", ""]);
			lines.push(["* " + name, dist(system.sun, rnd)]);
			lines.push([" ", ""]);
		};
		//planets
		var planets = system.filteredEntities(this, fn_planets, player.ship);
		if (planets.length !== 0) {
			lines.push([expandDescription("[mi_planets]") + ":", ""]);
			for (i = 0; i < planets.length; i++) {
				if (planets[i].displayName)
					lines.push(["* " + planets[i].displayName.replace(" (" + expandDescription("[mi_planet]") + ")", ""), dist(planets[i], rnd)]);
				else lines.push(["* " + expandDescription("[mi_planet]") + " " + (i + 1), dist(planets[i], rnd)]);
			}
			lines.push([" ", ""]);
		};
		//moons
		var moons = system.filteredEntities(this, fn_moons, player.ship);
		if (moons.length !== 0) {
			lines.push([expandDescription("[mi_moons]") + ":", ""]);
			for (i = 0; i < moons.length; i++) {
				if (moons[i].displayName)
					lines.push(["* " + moons[i].displayName.replace(" (" + expandDescription("[mi_moon]") + ")", ""), dist(moons[i], rnd)]);
				else lines.push(["* " + expandDescription("[mi_moon]") + " " + (i + 1), dist(moons[i], rnd)]);
			}
			lines.push([" ", ""]);
		};
		//beacons
		var beacons = system.filteredEntities(this, fn_beacons, player.ship);
		if (beacons.length !== 0) {
			lines.push([expandDescription("[mi_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 === expandDescription("[mi_navigation_buoy]") && system.mainStation.position.distanceTo(beacons[i]) <= 10E4)
							lines.push(["* " + expandDescription("[mi_main_station_buoy]"), dist(beacons[i], rnd)]);
						else
							lines.push(["* " + beacons[i].displayName, dist(beacons[i], rnd)]);
					}
				}
				else lines.push(["* " + expandDescription("[mi_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": expandDescription("[mi_exit]")
	}
	mission.runScreen({
		title: expandDescription("[mi_screen_distance_title]"),
		screenID: "marketinquirer-distances",
		message: text,
		choices: options,
		background: bgImage,
		exitScreen: "GUI_SCREEN_INTERFACES"
	});
	//helper functions
	function fn_planets(entity) { return (entity.isPlanet && entity.hasAtmosphere) };
	function fn_moons(entity) { return (entity.isPlanet && !entity.hasAtmosphere) };
	function fn_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;
		}
	}
}
 |