"use strict";
this.name = "ShipConfiguration_Core";
this.author = "phkb";
this.copyright = "2016 phkb";
this.description = "Core routines for ShipConfiguration.";
this.licence = "CC BY-NC-SA 3.0";

/*
	This OXP adds the concept of equipment space and weight: equipment space is limited, meaning you can't install everything at once, and having a lot of equipment installed will
	change the performance stats of the ship.

	Please read the "readme.txt" file - there's a lot of important info in there that's worth reading in order to make the most of this OXP.

	Borrows code from Capt Murphy's Breakable Energy Unit OXP, Breakable Engines OXP, Breakable Shield Generators OXP, and Breakable Witchdrive OXP
	Because of this, those OXP's are incompatible with this one, and the manifest has the incompatibilities flagged.

	TODO:
	- work out how to calculate and display ship heat profile (ie what units will generate heat with use and how much, and what units will increase cabin temp and how much)

*/

this._disabled = false; // quick way to disable entire OXP
this._debug = false; // turns on/off logging messages
this._disableBoosterSound = false; // turns on/off the warning sound when boosters start generating heat
this._disableF3HUD = false; // turns on/off the specialised F3 HUD (showing equipment & cargo space allocations)
this._heatControl = true; // indicates that the heat transfer system is in use (ie laser temp adds to cabin temp, inclusion of heat sinks etc)
this._installationTime = true; // flag that controls whether changing ship config also takes time
this._freeUpgrades = false; // flag to make all upgrades free (yay!) for testing period only (boo!)
this._refundPct = 0.85; // value between 0 and 1 that indicates how much refund you get on equipment sold. 0 = no refund, 1 = refund full original price
this._weightFactor = 2; // increase to make ship weight have less weight (!) when doing adjustment calculations
this._applyToNPC = true; // flag to indicate whether NPC ships will have same weight performance calculations applied to their ships
this._suppressEquipSpecs = false; // flag to indicate whether the F4 "Equipment Specification" page is suppressed/hidden
this._shipModel = true; // flag to turn on player ship model on configuration screens.

this._busOverloadLimit = 20; // at what point the electrical bus overloads (counter value trigger)
this._shipRespray = false; // indicates that the Ship Respray OXP is installed
this._resprayActive = false; // indicates that a respray is happening right now
this._holdEquipSpace = "";
this._torusSync = false; // indicates that the Synchronised Torus OXP is installed
this._menuColor = "orangeColor"; // color of general menu items
this._itemColor = "yellowColor"; // color of special menu items (eg exit menu items)
this._installedColor = "greenColor"; // color of installed equipment items
this._damagedColor = "redColor"; // color of damaged equipment items
this._disabledColor = "darkGrayColor"; // color of disabled equipment items
this._riskColor = "0.8 0.8 0.8 1"; // color of risky equipment items (items installed over the recommended power coupling/bus level)
this._defaultHeatShieldHSFactor = 1.7; // default heat sink factor if no heat shield installed
this._simulator = false; // holding variable to work out whether this launch/dock routine was part of a simulator run
this._OXPHyperdrives = false; // indicates the Hyperdrives OXP is installed
this._hyperHangar = false; // indicates the Hyperspace Hangar OXP is installed
this._hyperHangarActive = false; // indicates that Hyperspace Hangar is active
this._hyperHangarTimer = null; // timer to update hyperhangar's stored ship image

this._current = {}; // dictionary of current list of installed options
this._startUp = true; // flag to indicate startup procedures are underway
this._initialSetup = false; // flag to indicate that initial equipment setup is necessary
this._promptPlayer = false; // flag to indicate that the player needs to be prompted about equipment (overload)
this._page = 0; // current page of the active display
this._display = 0; // indicates which display is being shown
this._source = ""; // source location string, set when various mission screens are shown and used by the choice handler to determine what screen to return to
this._adding = false; // flag to indicate that the "equipmentAdded" routine is underway, in order to prevent endless loops
this._removing = false; // flag to indicate that the "equipmentRemoved" routine is underway, in order to prevent endless loops
this._damaging = false; // flag to indicate that the "equipmentDamaged" routine is underway, in order to prevent endless loops
this._repairing = false; // flag to indicate that the "equipmentRepaired" routine is underway, in order to prevent endless loops
this._sellEquipExitScreen = "GUI_SCREEN_STATUS"; // which screen sell equipment mission screen will exit to
this._counter = 0; // counter used in the energy depletion routine
this._busOverload = 0; // calculated value that indicates the players chance of receiving a bus overload
this._busOverloadCounter = 0; // counter used in the bus overload routine. Counts number of times damage received, events triggered when
this._busMessageCounter = 0; // counter used in the bus overload routine
this._busOverloadResetTimer = null;
this._busProcessing = false;
this._energyRechargeRate_Stored = 0; // stored value of the energy recharge rate
this._forwardShieldRechargeRate_Stored = 0; // stored value of the forward shield recharge rate
this._aftRechargeRate_Stored = 0; // stored value of the aft shield recharge rate
this._lastChoice = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]; // players last selection on each mission screen
this._trueValues = ["yes", "1", 1, "true", true];
this._currEquip = [];
this._callbacks = [];

// configuration settings for use in Lib_Config
this._scConfig = {
	Name: this.name,
	Alias: expandDescription("[sc_config_alias]"),
	Display: expandDescription("[sc_config_display]"),
	Alive: "_scConfig",
	Bool: {
		B0: { Name: "_disableBoosterSound", Def: false, Desc: expandDescription("[sc_config_disable_booster_sound]") },
		B1: { Name: "_disableF3HUD", Def: false, Desc: expandDescription("[sc_config_disable_f3hud]") },
		B2: { Name: "_installationTime", Def: true, Desc: expandDescription("[sc_config_installtime]") },
		B3: { Name: "_freeUpgrades", Def: false, Desc: expandDescription("[sc_config_freeupgrades]") },
		B4: { Name: "_applyToNPC", Def: true, Desc: expandDescription("[sc_config_applynpc]") },
		B5: { Name: "_suppressEquipSpecs", Def: false, Desc: expandDescription("[sc_config_suppress_equipspecs]") },
		Info: expandDescription("[sc_config_bool_info]")
	}
};

// for when the calculations need manual tweaking...
this._shipSpaceExceptions = {
	"Asp Mark II": 30, // ex-military design, so more equipment space available to make up for no cargo space.
	"Asp Mark II Special": 35,
	"Boa Class Cruiser": 35,
	"Boa": 30,
	"Cobra Mark III-XT": 23,
	"Constrictor": 30,
	"Fer-de-Lance": 20,
	"GalCop Viper Interceptor": 25,
	"GalCop Viper": 20,
	"Night Adder": 20,
	"Yasen-N 'Advanced'": 30,
};

// provides consistency for ship mass calculations
// really only applies to ships that have multiple installation variations, where the mass value might return a slightly different number
this._shipMassExceptions = {
	"Cobra Mark III": 214737.6875,
};

// higher numbers mean equipment weight will have less impact on ship performance (better power to weight ratio)
this._shipPowerToWeight = {
	"Boa Class Cruiser": 0.8,
	"Boa": 0.7,
	"Cobra Mark III": 1.5,
	"Constrictor": 8,
	"Fer-de-Lance": 1.5,
	"Mining Transporter": 3,
	"Orbital Shuttle": 3,
	"Pitviper Mark II": 1,
	"Pitviper": 1,
	"Transporter": 3,
};

// not in use atm
this._shipHeatRateExceptions = {
	"Boa": 0.97,
	"Boa Class Cruiser": 0.94,
};

// default zoom is 3.6 - higher values mean smaller view, lower values mean bigger view
// these values make ships look bigger or smaller, as appropriate
this._zoomOverride = {
	"Adder": 4.6,
	"Anaconda": 2.3,
	"Anaconda MMS": 2.3,
	"Aphid": 3.2,
	"Arafura": 3,
	"Boa Class Cruiser": 2.5,
	"Boa Class Cruiser MMS": 2.5,
	"Boa": 2.5,
	"Boa MMS": 2.5,
	"Bug": 4.4,
	"Chameleon": 3.3,
	"Chopped Cobra": 3,
	"Cobra Mark I": 4.6,
	"Cobra Mark II-X": 4,
	"Cobra Mark III": 3,
	"Cobra Mark III MMS": 3,
	"Cobra Mark III-XT": 3,
	"Cobra Mark IV": 2.9,
	"Cobra Mark IV MMS": 2.9,
	"Cobra Rapier": 3,
	"Copperhead Mk2": 3,
	"Cruzer": 3,
	"D.T.T. Atlas": 2.5,
	"D.T.T. Cyclops": 2.5,
	"D.T.T. Kraken": 2.8,
	"D.T.T. MK-1": 3.4,
	"D.T.T. Snake Charmer": 2.7,
	"D.T.T. War Lance": 3.3,
	"Fer-de-Lance": 3.3,
	"Gecko": 4.2,
	"Griffin Mk I": 3.3,
	"Griff Boa Prototype": 2.5,
	"Hognose": 4.3,
	"Iguana": 3.2,
	"Krait": 4.2,
	"Lira": 1.9,
	"Mamba Escort": 4.2,
	"Mamba": 4.2,
	"Miner Cobra Mark III": 3,
	"Mining Transporter": 4.6,
	"Monitor Mark II": 3,
	"Monitor": 3,
	"Moray Medical Boat": 4.2,
	"Moray Star Boat": 4.2,
	"Mussurana": 3,
	"Night Adder": 4.2,
	"Ophidian": 3,
	"Orbital Shuttle": 4.6,
	"Pitviper": 3.4,
	"Pitviper (Vindicator)": 3.4,
	"Pitviper (Buccaneer)": 3.4,
	"Pitviper (Bountyhunter)": 3.4,
	"Pitviper S.E. Beast": 3.4,
	"Pitviper Mark II": 3,
	"Python Class Cruiser": 2.5,
	"Python ET Special": 2.6,
	"Python ET Special MMS": 2.6,
	"Python": 2.5,
	"Python MMS": 2.5,
	"Python SG": 2.5,
	"Python SG-MMS": 2.5,
	"Python BattleCruiser MMS": 2.5,
	"Serpent Class Cruiser": 2.5,
	"Sidewinder Scout Ship": 4.5,
	"Sidewinder Special": 4.3,
	"Skat": 3.4,
	"Taxi Cab": 4.6,
	"Tembo": 2.2,
	"Transporter": 4.6,
	"Worm": 4.6,
	"Yasen-N": 3.2,
	"Yasen-N 'Advanced' variant 1": 3.2,
	"Yasen-N 'Advanced' variant 2": 3.2,
	"Yasen-N 'Advanced' variant 3": 3.2,
	"YellOo Cab": 4.4,
};

// dictionary of npc equivalent roles for translation purposes
this._NPCEquivalents = {
	"ftzpirate": "pirate",
	"ftzhauler": "trader",
	"jaguar_company_patrol": "hunter-medium",
	"jaguar_company_ship_splinter": "hunter",
	"jaguar_company_tug": "shuttle",
	"jaguar_company_miner": "miner",
	"bigTrader": "trader",
	"trident": "shuttle",
	"strelka": "trader",
	"random_hits_big_boss_fighter": "pirate",
	"random_hits_big_boss": "pirate-heavy-fighter",
	"random_hits_patrol": "hunter-medium",
	"random_hits_mining_hopper": "miner",
	"blackmonk_gunship": "hunter-heavy",
	"clipper-rescueship": "trader",
	"dredgershuttle_up": "shuttle",
	"dredgershuttle": "shuttle",
	"wildShips_tanker": "trader",
	"defense_ship": "police",
	"ups_shuttle": "shuttle",
	"ups-sun-police": "police",
	"rrs-escort": "escort",
	"anarchies_salvager_tugger": "scavenger",
	"con-a-hauler": "trader",
	"con-a-haulret": "trader",
	"con-b-hauler": "trader",
	"con-b-haulret": "trader",
	"con-c-hauler": "trader",
	"con-c-haulret": "trader",
	"con-d-hauler": "trader",
	"con-d-haulret": "trader",
	"con-e-hauler": "trader",
	"con-e-haulret": "trader",
	"con-f-hauler": "trader",
	"con-f-haulret": "trader",
	"con-g-hauler": "trader",
	"con-g-haulret": "trader",
	"starsecurity": "escort",
	"pi42security": "escort",
	"tescoosecurity": "escort",
	"mallwartsecurity": "escort",
	"gmartsecurity": "escort",
	"sainsboorysecurity": "escort",
	"oodlessecurity": "escort",
};

/*
	NPC configuration item definition:
		{primaryRole:"", minSpace:X, maxSpace:Y, equipmentList:[]}
				primaryRole     role to which this definition applies (eg "assassin-light")
				minSpace		equipment space of ship must be greater than or equal to this value
				maxSpace		equipment space of ship must be less than or equal to this value
				equipmentlist   array of equipment areas with a number that indicates how far over default to go
								can be a generic name or a specific equipment item
								generic names: engines, thrusters, energy, frontshields, aftdhields, heatshields, fuelinjectors, fuelscoops
								specific name example: EQ_ENGINE_TYPE3C, EQ_THRUSTERS_TYPE3B

	eg 	{primaryRole:"assassin-light", minSpace:0, maxSpace:20, equipmentList:["engines:1", "thrusters:2", "energy:2", "EQ_HEAT_SHIELD_TYPE4"],
		this would translate as:
			for assassin-light roles, where the equipment space is between 0 and 20, put engines 1 over default, thrusters 2 over default, energy banks 2 over default, and give the ship type 4 heat shields.

	ships not conforming to items in this list will receive default equipment
	Please note: these values are open for discussion! Please let me know if you think some other settings would be more appropriate.
*/
this._NPCConfig = [{
	primaryRole: "assassin-light",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3C", "EQ_THRUSTERS_TYPE3A", "EQ_ELEC_BUS_TYPE3", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:1"]
}, // Krait
{
	primaryRole: "assassin-light",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_THRUSTERS_TYPE4A", "EQ_ELEC_BUS_TYPE4", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:2"]
}, // Cobra I, Moray Starboat
{
	primaryRole: "assassin-light",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_THRUSTERS_TYPE5A", "EQ_ELEC_BUS_TYPE5", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:3"]
}, //
{
	primaryRole: "assassin-medium",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3C", "EQ_THRUSTERS_TYPE3A", "EQ_ELEC_BUS_TYPE3", "EQ_FUEL_INJECTION_TYPE2", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:1"]
}, //
{
	primaryRole: "assassin-medium",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_THRUSTERS_TYPE4A", "EQ_ELEC_BUS_TYPE4", "EQ_FUEL_INJECTION_TYPE3", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:2"]
}, // Fer-de-Lance
{
	primaryRole: "assassin-medium",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_THRUSTERS_TYPE5A", "EQ_ELEC_BUS_TYPE5", "EQ_FUEL_INJECTION_TYPE3", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:2"]
}, // Cobra III (no cargo extension)
{
	primaryRole: "assassin-medium",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_THRUSTERS_TYPE6A", "EQ_ELEC_BUS_TYPE6", "EQ_FUEL_INJECTION_TYPE4", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:2"]
}, // Cobra III
{
	primaryRole: "assassin-heavy",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_THRUSTERS_TYPE4A", "heatsinks:1"]
},
{
	primaryRole: "assassin-heavy",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_THRUSTERS_TYPE5A", "energy:2", "EQ_ELEC_BUS_TYPE5", "EQ_FUEL_INJECTION_TYPE2", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:2"]
}, // Asp Mark II
{
	primaryRole: "assassin-heavy",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_THRUSTERS_TYPE6A", "energy:2", "EQ_ELEC_BUS_TYPE6", "EQ_FUEL_INJECTION_TYPE3", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:3"]
}, //
{
	primaryRole: "assassin-heavy",
	minSpace: 41,
	maxSpace: 60,
	equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_THRUSTERS_TYPE6A", "energy:4", "EQ_ELEC_BUS_TYPE6", "EQ_FUEL_INJECTION_TYPE4", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:4"]
}, //
{
	primaryRole: "assassin-heavy",
	minSpace: 61,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE7B", "EQ_THRUSTERS_TYPE7A", "energy:4", "EQ_ELEC_BUS_TYPE7", "EQ_FUEL_INJECTION_TYPE4", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:4"]
},
{
	primaryRole: "hunter",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "HEAT_SHIELD_TYPE4", "heatsinks:1"]
}, // gecko, krait, mamba, sidewinder
{
	primaryRole: "hunter",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:1", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "heatsinks:2"]
}, //
{
	primaryRole: "hunter",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "heatsinks:3"]
}, //
{
	primaryRole: "hunter-medium",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:1", "HEAT_SHIELD_TYPE4", "heatsinks:1"]
}, //
{
	primaryRole: "hunter-medium",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ELEC_BUS_TYPE4", "energy:2", "HEAT_SHIELD_TYPE4", "heatsinks:2"]
}, // asp mark II, cobra I, fer-de-lance, moray starboat
{
	primaryRole: "hunter-medium",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_ELEC_BUS_TYPE5", "energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "heatsinks:3"]
}, // cobra III (std model)
{
	primaryRole: "hunter-medium",
	minSpace: 41,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_ELEC_BUS_TYPE6", "energy:3", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE4", "heatsinks:3"]
}, // cobra III (+ extra cargo)
{
	primaryRole: "hunter-heavy",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "HEAT_SHIELD_TYPE4", "heatsinks:1"]
}, //
{
	primaryRole: "hunter-heavy",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ELEC_BUS_TYPE4", "HEAT_SHIELD_TYPE4", "heatsinks:2"]
}, // asp mark II, fer-de-lance
{
	primaryRole: "hunter-heavy",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_ELEC_BUS_TYPE5", "energy:1", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "heatsinks:3"]
}, // cobra III (std model)
{
	primaryRole: "hunter-heavy",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_ELEC_BUS_TYPE6", "energy:1", "frontshields:2", "aftshields:2", "EQ_FUEL_INJECTION_TYPE4", "HEAT_SHIELD_TYPE4", "heatsinks:4"]
}, // cobra III (+ extra cargo)
{
	primaryRole: "hunter-heavy",
	minSpace: 51,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_ELEC_BUS_TYPE6", "energy:2", "frontshields:2", "aftshields:2", "EQ_FUEL_INJECTION_TYPE4", "HEAT_SHIELD_TYPE4", "heatsinks:5"]
}, // cobra III (+ extra cargo)
{
	primaryRole: "trader",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["energy:1", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE2", "heatsinks:1"]
}, // adder
{
	primaryRole: "trader",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE3", "heatsinks:2"]
}, // cobra I, fer-de-lance, moray star boat, moray medical boat
{
	primaryRole: "trader",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["energy:3", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE3", "heatsinks:3"]
}, //
{
	primaryRole: "trader",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["energy:3", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE3", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:4"]
}, //
{
	primaryRole: "trader",
	minSpace: 51,
	maxSpace: 60,
	equipmentList: ["energy:4", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "heatsinks:5"]
}, //
{
	primaryRole: "trader",
	minSpace: 61,
	maxSpace: 70,
	equipmentList: ["energy:4", "frontshields:3", "aftshields:3", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:6"]
}, // boa, python
{
	primaryRole: "trader",
	minSpace: 71,
	maxSpace: 80,
	equipmentList: ["energy:5", "frontshields:3", "aftshields:3", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:7"]
}, // anaconda, boa cc
{
	primaryRole: "trader-courier",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:1", "HEAT_SHIELD_TYPE2", "heatsinks:1"]
}, // adder
{
	primaryRole: "trader-courier",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE3", "heatsinks:2"]
}, // asp mark II, fer-de-lance, moray starboat
{
	primaryRole: "trader-courier",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ELEC_BUS_TYPE4", "energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE3", "heatsinks:3"]
}, // cobra III (std model)
{
	primaryRole: "trader-courier",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ELEC_BUS_TYPE4", "energy:3", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:3"]
}, // cobra III (+ extra cargo)
{
	primaryRole: "trader-courier",
	minSpace: 51,
	maxSpace: 60,
	equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_ELEC_BUS_TYPE5", "energy:4", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "heatsinks:4"]
}, //
{
	primaryRole: "trader-courier",
	minSpace: 61,
	maxSpace: 70,
	equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_ELEC_BUS_TYPE5", "energy:4", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:5"]
}, //
{
	primaryRole: "trader-courier",
	minSpace: 71,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_ELEC_BUS_TYPE6", "energy:4", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:6"]
}, // anaconda, boa cc
{
	primaryRole: "trader-smuggler",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:1", "HEAT_SHIELD_TYPE2", "heatsinks:1"]
}, // adder,
{
	primaryRole: "trader-smuggler",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE3", "heatsinks:2"]
}, // cobra I, fer-de-lance, moray starboat
{
	primaryRole: "trader-smuggler",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ELEC_BUS_TYPE4", "energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE3", "heatsinks:3"]
}, // cobra III (std model)
{
	primaryRole: "trader-smuggler",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ELEC_BUS_TYPE4", "energy:3", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:3"]
}, // cobra III (+ extra cargo)
{
	primaryRole: "trader-smuggler",
	minSpace: 51,
	maxSpace: 60,
	equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_ELEC_BUS_TYPE5", "energy:4", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "heatsinks:4"]
}, //
{
	primaryRole: "trader-smuggler",
	minSpace: 61,
	maxSpace: 70,
	equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_ELEC_BUS_TYPE5", "energy:4", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:5"]
}, // python
{
	primaryRole: "trader-smuggler",
	minSpace: 71,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_ELEC_BUS_TYPE6", "energy:4", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:6"]
}, //
{
	primaryRole: "pirate",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:1"]
}, // adder, gecko, krait, mamba, sidewinder
{
	primaryRole: "pirate",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "heatsinks:1"]
}, // cobra I, fer-de-lance, moray starboat
{
	primaryRole: "pirate",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "heatsinks:2"]
}, // cobra III (std model)
{
	primaryRole: "pirate",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:2", "heatsinks:2"]
}, // cobra III (+ extra cargo)
{
	primaryRole: "pirate",
	minSpace: 51,
	maxSpace: 60,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "heatsinks:3"]
}, //
{
	primaryRole: "pirate",
	minSpace: 61,
	maxSpace: 70,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "thrusters:2", "frontshields:1", "aftshields:1", "heatsinks:4"]
}, // python
{
	primaryRole: "pirate",
	minSpace: 71,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:4", "thrusters:2", "frontshields:1", "aftshields:1", "heatsinks:4"]
}, //
{
	primaryRole: "pirate-light-fighter",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:1"]
}, // adder, gecko, krait, mamba, sidewinder
{
	primaryRole: "pirate-light-fighter",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "heatsinks:2"]
}, //
{
	primaryRole: "pirate-light-fighter",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "heatsinks:2"]
}, //
{
	primaryRole: "pirate-light-fighter",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:4", "heatsinks:3"]
}, //
{
	primaryRole: "pirate-medium-fighter",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:1"]
}, // gecko
{
	primaryRole: "pirate-medium-fighter",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "heatsinks:2"]
}, // asp mark II, cobra I, fer-de-lance, moray starboat
{
	primaryRole: "pirate-medium-fighter",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:1", "aftshields:1", "heatsinks:2"]
}, //
{
	primaryRole: "pirate-medium-fighter",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:4", "frontshields:1", "aftshields:1", "heatsinks:3"]
}, //
{
	primaryRole: "pirate-medium-fighter",
	minSpace: 51,
	maxSpace: 60,
	equipmentList: ["EQ_ENGINE_TYPE5B", "energy:5", "frontshields:2", "aftshields:2", "heatsinks:3"]
}, //
{
	primaryRole: "pirate-heavy-fighter",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:1"]
}, //
{
	primaryRole: "pirate-heavy-fighter",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:2", "heatsinks:2"]
}, // asp mark II, fer-de-lance,
{
	primaryRole: "pirate-heavy-fighter",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "heatsinks:2"]
}, // cobra III (std model)
{
	primaryRole: "pirate-heavy-fighter",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE5B", "energy:4", "frontshields:1", "aftshields:1", "heatsinks:2"]
}, // cobra III (+ extra cargo)
{
	primaryRole: "pirate-heavy-fighter",
	minSpace: 51,
	maxSpace: 60,
	equipmentList: ["EQ_ENGINE_TYPE5B", "energy:5", "frontshields:1", "aftshields:1", "heatsinks:3"]
}, //
{
	primaryRole: "pirate-heavy-fighter",
	minSpace: 61,
	maxSpace: 70,
	equipmentList: ["EQ_ENGINE_TYPE6B", "energy:6", "frontshields:2", "aftshields:2", "heatsinks:3"]
}, //
{
	primaryRole: "pirate-heavy-fighter",
	minSpace: 71,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE6B", "energy:7", "frontshields:2", "aftshields:2", "heatsinks:4"]
}, //
{
	primaryRole: "pirate-interceptor",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE4A", "heatsinks:1"]
}, //
{
	primaryRole: "pirate-interceptor",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE5A", "heatsinks:1"]
}, // asp mark II, fer-de-lance, moray starboat
{
	primaryRole: "pirate-interceptor",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE6A", "heatsinks:2"]
}, // cobra III (std model)
{
	primaryRole: "pirate-interceptor",
	minSpace: 41,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE7A", "heatsinks:3"]
}, // cobra III (+ extra cargo)
{
	primaryRole: "pirate-aegis-raider",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3A", "heatsinks:1"]
}, //
{
	primaryRole: "pirate-aegis-raider",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE4A", "heatsinks:1"]
}, // asp mark II, fer-de-lance
{
	primaryRole: "pirate-aegis-raider",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE4B", "heatsinks:2"]
}, // cobra III (std model)
{
	primaryRole: "pirate-aegis-raider",
	minSpace: 41,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE5A", "heatsinks:3"]
}, // cobra III (+ extra cargo)
{
	primaryRole: "pirate-light-freighter",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:1"]
}, //
{
	primaryRole: "pirate-light-freighter",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:1"]
}, // cobra I, moray starboat
{
	primaryRole: "pirate-light-freighter",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "heatsinks:2"]
}, // cobra III (std model)
{
	primaryRole: "pirate-light-freighter",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:2", "frontshields:1", "aftshields:1", "heatsinks:2"]
}, // cobra III (+ extra cargo)
{
	primaryRole: "pirate-light-freighter",
	minSpace: 51,
	maxSpace: 60,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:1", "aftshields:1", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:3"]
}, //
{
	primaryRole: "pirate-light-freighter",
	minSpace: 61,
	maxSpace: 70,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:2", "aftshields:2", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "heatsinks:4"]
}, // python
{
	primaryRole: "pirate-medium-freighter",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: []
}, // shouldn't get many ships in this bracket
{
	primaryRole: "pirate-medium-freighter",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:2"]
}, //
{
	primaryRole: "pirate-medium-freighter",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:2"]
}, // cobra III (std model)
{
	primaryRole: "pirate-medium-freighter",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "frontshields:1", "aftshields:1", "heatsinks:3"]
}, // cobra III (+ extra cargo)
{
	primaryRole: "pirate-medium-freighter",
	minSpace: 51,
	maxSpace: 60,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:2", "frontshields:1", "aftshields:1", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:4"]
}, //
{
	primaryRole: "pirate-medium-freighter",
	minSpace: 61,
	maxSpace: 70,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:2", "aftshields:2", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:5"]
}, // python
{
	primaryRole: "pirate-medium-freighter",
	minSpace: 71,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:2", "aftshields:2", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "heatsinks:6"]
}, // boa
{
	primaryRole: "pirate-heavy-freighter",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: []
}, // shouldn't get many ships in these brackets
{
	primaryRole: "pirate-heavy-freighter",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: []
}, //
{
	primaryRole: "pirate-heavy-freighter",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:3"]
}, //
{
	primaryRole: "pirate-heavy-freighter",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "frontshields:1", "aftshields:1", "heatsinks:3"]
}, //
{
	primaryRole: "pirate-heavy-freighter",
	minSpace: 51,
	maxSpace: 60,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:2", "frontshields:2", "aftshields:2", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:4"]
}, //
{
	primaryRole: "pirate-heavy-freighter",
	minSpace: 61,
	maxSpace: 70,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:3", "aftshields:3", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "heatsinks:5"]
}, // boa, python
{
	primaryRole: "pirate-heavy-freighter",
	minSpace: 71,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:4", "aftshields:4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:6"]
}, // anaconda, boa cc
{
	primaryRole: "escort",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B"]
},
{
	primaryRole: "escort",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE3B"]
},
{
	primaryRole: "escort",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE4B"]
},
{
	primaryRole: "escort",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE4B"]
},
{
	primaryRole: "escort",
	minSpace: 51,
	maxSpace: 60,
	equipmentList: ["EQ_ENGINE_TYPE5B"]
},
{
	primaryRole: "escort-medium",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B"]
},
{
	primaryRole: "escort-medium",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE4B", "heatsinks:2"]
},
{
	primaryRole: "escort-medium",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE4B", "heatsinks:2"]
},
{
	primaryRole: "escort-medium",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE5B", "heatsinks:3"]
},
{
	primaryRole: "escort-medium",
	minSpace: 51,
	maxSpace: 60,
	equipmentList: ["EQ_ENGINE_TYPE5B", "heatsinks:3"]
},
{
	primaryRole: "escort-medium",
	minSpace: 61,
	maxSpace: 70,
	equipmentList: ["EQ_ENGINE_TYPE6B", "heatsinks:4"]
},
{
	primaryRole: "escort-heavy",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B"]
},
{
	primaryRole: "escort-heavy",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE4B", "heatsinks:2"]
},
{
	primaryRole: "escort-heavy",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE4B", "heatsinks:2"]
},
{
	primaryRole: "escort-heavy",
	minSpace: 41,
	maxSpace: 50,
	equipmentList: ["EQ_ENGINE_TYPE5B", "heatsinks:3"]
},
{
	primaryRole: "escort-heavy",
	minSpace: 51,
	maxSpace: 60,
	equipmentList: ["EQ_ENGINE_TYPE5B", "heatsinks:3"]
},
{
	primaryRole: "escort-heavy",
	minSpace: 61,
	maxSpace: 70,
	equipmentList: ["EQ_ENGINE_TYPE6B", "heatsinks:4"]
},
{
	primaryRole: "escort-heavy",
	minSpace: 71,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE6B", "heatsinks:4"]
},
{
	primaryRole: "shuttle",
	minSpace: 0,
	maxSpace: 20,
	equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "EQ_HEAT_SHIELD_TYPE3"]
},
{
	primaryRole: "shuttle",
	minSpace: 21,
	maxSpace: 30,
	equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "EQ_HEAT_SHIELD_TYPE3"]
},
{
	primaryRole: "shuttle",
	minSpace: 31,
	maxSpace: 40,
	equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "EQ_HEAT_SHIELD_TYPE3"]
},
{
	primaryRole: "shuttle",
	minSpace: 41,
	maxSpace: 80,
	equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "EQ_HEAT_SHIELD_TYPE3"]
},
{
	primaryRole: "police",
	minSpace: 0,
	maxSpace: 80,
	equipmentList: ["engines:2", "energy:1", "thrusters:2"]
},
{
	primaryRole: "police-station-patrol",
	minSpace: 0,
	maxSpace: 80,
	equipmentList: ["engines:2", "energy:1", "thrusters:2"]
},
{
	primaryRole: "police-witchpoint-patrol",
	minSpace: 0,
	maxSpace: 80,
	equipmentList: ["engines:3", "energy:2", "thrusters:3"]
},
{
	primaryRole: "wingman",
	minSpace: 0,
	maxSpace: 80,
	equipmentList: ["engines:2", "energy:1", "thrusters:2"]
},
{
	primaryRole: "miner",
	minSpace: 0,
	maxSpace: 80,
	equipmentList: ["EQ_ARMOUR_TYPE2"]
},
{
	primaryRole: "scavenger",
	minSpace: 0,
	maxSpace: 80,
	equipmentList: ["EQ_ARMOUR_TYPE2"]
},
];

// these equipment items don't take up space or weight, or can just be ignored altogether
this._ignoreEquip = ["EQ_FUEL", "EQ_SCANNER_SHOW_MISSILE_TARGET", "EQ_MULTI_TARGET", "EQ_ADVANCED_NAVIGATIONAL_ARRAY", "EQ_INTEGRATED_TARGETING_SYSTEM", "EQ_REVOVATION",
	"EQ_TARGET_MEMORY", "EQ_SMUGGLING_PHASE_ADJUSTMENT", "EQ_SDC_HACK_CHIP", "EQ_IG_INSURANCE", "EQ_IG_LEGAL_HACK", "EQ_LMSS_ACTUATOR", "EQ_ESCORTCONTRACTS", "EQ_TEA_MAKER", "EQ_TEAPOT",
	"EQ_RENOVATION", "EQ_COMMSLOGMFD", "EQ_COMMSLOGMFD_PASSIVE", "EQ_BROADCASTCOMMSMFD", "EQ_DAMAGE_REPORT_MFD", "EQ_DAMAGE_REPORT_MFD_PASSIVE", "EQ_COMBATMFD", "EQ_NAVIGATION_MFD",
	"EQ_WEAPON_NONE", "EQ_APRIL_INVENTORY", "EQ_APRIL_TRANSFER", "EQ_APRIL_UNLOAD", "EQ_AMS_1", "EQ_AMS_2", "EQ_AMS_3", "EQ_AMS_4", "EQ_GLARE_FILTER", "EQ_GLARE_FILTER_REPLACE",
	"EQ_RRS_FUEL", "EQ_AMS_5", "EQ_AMS_6", "EQ_AUTO_EJECT", "EQ_BOUNTY_INFORMER", "EQ_CARGOSPOTTER", "EQ_ELITE_RANK", "EQ_RESERVE_TANK_EMPTY", "EQ_AUX_TANK_EMPTY",
	"EQ_WEAPON_GATLING_LASER_COOLER", "EQ_NDC_AUTODOCK", "EQ_OXPDevHelper", "EQ_HUDSELECTOR", "EQ_MARKET_INQUIRER_MFD", "EQ_TROPHY_MFD", "EQ_UPS_IDCLEANER", "EQ_UPS_PRIVATE_ESCORT",
	"EQ_MULTIPASS", "EQ_MULTIPASSED_ID", "EQ_HARDWIRE_ORE_PROCESSOR", "EQ_HARDWIRE_ORE_SCANNER", "EQ_SCANNER_SHOW_MISSILE_TARGET_SALVAGED", "EQ_MULTI_TARGET_SALVAGED", "EQ_ADVANCED_NAVIGATIONAL_ARRAY_SALVAGED",
	"EQ_TARGETSELECTOR", "EQ_HULL_REPAIR", "EQ_SHIPS_CAT_1", "EQ_SHIPS_CAT_2", "EQ_SHIPS_CAT_3", "EQ_SHIPS_CAT_4", "EQ_SHIPS_CAT_5", "EQ_SHIPS_CAT_6", "EQ_SHIPS_CAT_7", "EQ_SHIPS_CAT_8",
	"EQ_SHIPS_CAT_9", "EQ_TARGET_MEMORY_SALVAGED", "EQ_CTE_TRADERNET", "EQ_CTE_TRADERNET_RENEWAL", "EQ_CAMERA_DRONES", "EQ_HOLY_FUEL", "EQ_WPH_ASC_UPGRADE", "EQ_RRS_ANA",
	"EQ_RRS_FLIGHTFORM", "EQ_RRS_FLIGHTFORM_DISCOUNT", "EQ_RRS_SERVICE", "EQ_RRS_ESCORT_TARGETING_SYSTEM", "EQ_RRS_ESCORT_TARGETING_SYSTEM_WAYSTATION",
	"EQ_RRS_ESCORT_TARGETING_SYSTEM_DISCOUNT", "EQ_RRS_SCANNER_SHOW_MISSILE_TARGET", "EQ_RRS_SCANNER_SHOW_MISSILE_TARGET_DISCOUNT", "EQ_RRS_FULLEQUIP", "EQ_BREAKABLE_HUD_IFF_SCANNER",
	"EQ_ESCORTDECK", "EQ_ESCORTDECKXL", "EQ_ESCORTDECK_adder", "EQ_ESCORTDECK_asp", "EQ_ESCORTDECK_gecko", "EQ_ESCORTDECK_sidewinder", "EQ_ESCORTDECK_viper", "EQ_ESCORTDECK_ophidian",
	"EQ_ESCORTDECK_ghavial", "EQ_ESCORTDECK_wolf", "EQ_ESCORTDECK_arachnid", "EQ_ESCORTDECK_s8", "EQ_ESCORTDECK_sniper-wolf", "EQ_ESCORTDECK_sniper-arachnid", "EQ_ESCORTDECK_sniper-s8",
	"EQ_HYPER_RADIO", "EQ_HYPER_RADIO_ADD", "EQ_HYPER_RADIO_PIRATE", "EQ_HIREDGUN_HIGH", "EQ_HIREDGUN_MID", "EQ_HIREDGUN_LOW", "EQ_ILS", "EQ_WEAPON_LASER_COOLER", "EQ_MANIFEST_MFD",
	"EQ_RMB_CHAFF_MINE", "EQ_POLICE_SCANNER_UPGRADE", "EQ_Q-CHARGER_MESS", "EQ_REPAIRBOTS_RECHARGE", "EQ_SAFETYCATCH", "EQ_SAFETY_MINE", "EQ_SCANNER_ALERTING_ENHANCEMENT",
	"EQ_SC_MANUAL_CONFIGURATOR_BASIC", "EQ_SC_MANUAL_CONFIGURATOR_STANDARD", "EQ_SC_MANUAL_CONFIGURATOR_ADVANCED", "EQ_SC_SC_REPAIR", "EQ_ENEMY_TARGETER_UPGRADE",
	"EQ_TELESCOPE_REPAIR", "EQ_TELESCOPE_FULLREPAIR", "EQ_TELESCOPEEXT", "EQ_GRAVSCANNER_REPAIR", "EQ_GRAVSCANNER_FULLREPAIR", "EQ_GRAVSCANNER2_REPAIR", "EQ_GRAVSCANNER2_FULLREPAIR",
	"EQ_SMALLDISH_REPAIR", "EQ_SMALLDISH_FULLREPAIR", "EQ_LARGEDISH_REPAIR", "EQ_LARGEDISH_FULLREPAIR", "EQ_TORUSTOSUN", "EQ_TRACKER", "EQ_TRACKERCAM_LINK", "EQ_TWS_GALACTICSATNAV",
	"EQ_WELCOME_MAT", "EQ_SMUGGLING_COMPARTMENT_REPAIR_1", "EQ_SMUGGLING_COMPARTMENT_REPAIR_2", "EQ_SMUGGLING_COMPARTMENT_REPAIR_3", "EQ_SMUGGLING_COMPARTMENT_REPAIR_4",
	"EQ_SMUGGLING_COMPARTMENT_REPAIR_5", "EQ_SMUGGLING_COMPARTMENT_REPAIR_6", "EQ_SMUGGLING_COMPARTMENT_REPAIR_7", "EQ_SMUGGLING_COMPARTMENT_REPAIR_8",
	"EQ_SMUGGLING_COMPARTMENT_REPAIR_9", "EQ_SMUGGLING_COMPARTMENT_REPAIR_10", "EQ_SMUGGLING_COMPARTMENT_REPAIR_11", "EQ_SMUGGLING_COMPARTMENT_REPAIR_12",
	"EQ_SMUGGLING_COMPARTMENT_REPAIR_13", "EQ_SMUGGLING_COMPARTMENT_REPAIR_14", "EQ_SMUGGLING_COMPARTMENT_REPAIR_15", "EQ_SMUGGLING_COMPARTMENT_REPAIR_16",
	"EQ_SMUGGLING_COMPARTMENT_REPAIR_17", "EQ_SMUGGLING_COMPARTMENT_REPAIR_18", "EQ_SMUGGLING_COMPARTMENT_REPAIR_19", "EQ_SMUGGLING_COMPARTMENT_REPAIR_20", "EQ_FHUD_OOLITE",
	"EQ_BREAKABLE_LIFE_SUPPORT_SYSTEM", "EQ_SHIPCONFIG", "EQ_FUEL_INJECTION", "EQ_HEAT_SHIELD", "EQ_RAILGUN_1_AMMUNITION", "EQ_RAILGUN_2_AMMUNITION", "EQ_XS_SELLPYLON_BASEDEQUIPMENT",
	"EQ_RAILGUN_3_AMMUNITION", "EQ_RAILGUN_4_AMMUNITION", "EQ_COTBS_RESTORE", "EQ_GAL_DRIVE_MOD", "EQ_CATACLYSM_ALL_INCLUSIVE", "EQ_SALON_CONTROL", "EQ_SNIPER_SCOPE",
	"EQ_SYSTEM_MARKET_WATCH", "EQ_AUTOECM", "EQ_FS_CLOAK_PLACEHOLDER", "EQ_FS_BOMB_PLACEHOLDER", "EQ_FS_INJECTION_PLACEHOLDER", "EQ_GALAXY_INFO", "EQ_LONG_RANGE_SCANNER_JUMP",
	"EQ_RETICLE_TARGET_SENSITIVE", "EQ_SELL_ENERGY_GRID", "EQ_ECM_SALVAGED", "EQ_FUEL_SCOOPS_SALVAGED", "EQ_ESCAPE_POD_SALVAGED", "EQ_ENERGY_BOMB_SALVAGED", "EQ_ENERGY_UNIT_SALVAGED",
	"EQ_NAVAL_ENERGY_UNIT_SALVAGED", "EQ_DOCK_COMP_SALVAGED", "EQ_GAL_DRIVE_SALVAGED", "EQ_FUEL_INJECTION_SALVAGED", "EQ_ADVANCED_COMPASS_SALVAGED", "EQ_SHIELD_BOOSTER_SALVAGED",
	"EQ_NAVAL_SHIELD_BOOSTER_SALVAGED", "EQ_HEAT_SHIELD_SALVAGED", "EQ_WORMHOLE_SCANNER_SALVAGED", "EQ_OXPCONFIG_COLORS", "EQ_OXPCONFIG_M0", "EQ_OXPCONFIG_M1", "EQ_OXPCONFIG_M2",
	"EQ_OXPCONFIG_M3", "EQ_OXPCONFIG_M4", "EQ_OXPCONFIG_M5", "EQ_OXPCONFIG_W0", "EQ_DTADAM", "EQ_DTADER", "EQ_DTAWEA", "EQ_CCL_OXPS_MINE", "EQ_CABAL_COMMON_SPECIALMARKETS",
	"EQ_CABAL_COMMON_COMM", "EQ_MANIF_SCANNERX", "EQ_MC_DESCRAMBLER", "EQ_MURPH_THARGOID_DRIVE_TOFIT", "EQ_MURPH_THARGOID_DRIVE_QUOTE", "EQ_SHIP_RESPRAY", "EQ_SHIP_RESPRAY_180",
	"EQ_HEAT_SINK_CONTROL", "EQ_HEAT_SINK_CONTROL_PASSIVE", "EQ_SYNC_TORUS", "EQ_AI_TRADING_ASSISTANT", "EQ_AUTO_CROSSHAIRS", "EQ_SELECTABLE_CROSSHAIRS", "EQ_TRAIL_DETECTOR",
	"EQ_EREHWON_PHOTOCAMERA", "EQ_ENEMY_TARGETER_UPGRADE", "EQ_SNIPERLOCK", "EQ_VECTOR_PAD", "EQ_RINGRACER", "EQ_IN_SYSTEM_TAXI_LICENCE", "EQ_NS_MINING_SCANNER_UPGRADE",
	"EQ_LUCKYCHARM", "EQ_PIRATE_FUEL", "EQ_FUEL_ALT1", "EQ_FUEL_ALT2", "EQ_FUEL_ALT3", "EQ_FUEL_ALT4", "EQ_FUEL_ALT5", "EQ_FUEL_ALT6", "EQ_SHIPS_LIBRARY", "EQ_ALMANAC_UNIT_MFD",
	"EQ_VIMANA_TARGET_MODULE", "EQ_VIMANA_TRAVEL_MODULE", "EQ_VIMANA_SHIP_MODULE", "EQ_VIMANAX_TARGET_MODULE", "EQ_VIMANAX_TRAVEL_MODULE", "EQ_VIMANAX_SHIP_MODULE",
	"EQ_SHIP_VERSION_10", "EQ_SHIP_VERSION_11", "EQ_SHIP_VERSION_12", "EQ_SHIP_VERSION_13", "EQ_SHIP_VERSION_14",
	"EQ_SHIP_VERSION_15", "EQ_SHIP_VERSION_16", "EQ_SHIP_VERSION_17", "EQ_SHIP_VERSION_18", "EQ_SHIP_VERSION_19",
	"EQ_SHIP_VERSION_20", "EQ_SHIP_VERSION_21", "EQ_SHIP_VERSION_22", "EQ_SHIP_VERSION_23", "EQ_SHIP_VERSION_24",
	"EQ_SHIP_VERSION_25", "EQ_SHIP_VERSION_26", "EQ_SHIP_VERSION_27", "EQ_SHIP_VERSION_28", "EQ_SHIP_VERSION_29",
	"EQ_SHIP_VERSION_30", "EQ_SHIP_VERSION_31", "EQ_SHIP_VERSION_32", "EQ_SHIP_VERSION_33", "EQ_SHIP_VERSION_34",
	"EQ_SHIP_VERSION_35", "EQ_SHIP_VERSION_36", "EQ_SHIP_VERSION_37", "EQ_SHIP_VERSION_38", "EQ_SHIP_VERSION_39",
	"EQ_SHIP_VERSION_40", "EQ_SHIP_VERSION_41", "EQ_SHIP_VERSION_42", "EQ_SHIP_VERSION_43", "EQ_SHIP_VERSION_44",
	"EQ_SHIP_VERSION_45", "EQ_SHIP_VERSION_46", "EQ_SHIP_VERSION_47", "EQ_SHIP_VERSION_48", "EQ_SHIP_VERSION_49",
	"EQ_SHIP_VERSION_50", "EQ_SHIP_VERSION_51", "EQ_SHIP_VERSION_52", "EQ_SHIP_VERSION_53", "EQ_SHIP_VERSION_54",
	"EQ_SHIP_VERSION_55", "EQ_SHIP_VERSION_56", "EQ_SHIP_VERSION_57", "EQ_SHIP_VERSION_58", "EQ_SHIP_VERSION_59",
	"EQ_SHIP_VERSION_60", "EQ_SHIP_VERSION_61", "EQ_SHIP_VERSION_62", "EQ_SHIP_VERSION_63", "EQ_SHIP_VERSION_64",
	"EQ_SHIP_VERSION_65", "EQ_SHIP_VERSION_66", "EQ_SHIP_VERSION_67", "EQ_SHIP_VERSION_68", "EQ_SHIP_VERSION_69",
	"EQ_SHIP_VERSION_70", "EQ_SHIP_VERSION_71", "EQ_SHIP_VERSION_72", "EQ_SHIP_VERSION_73", "EQ_SHIP_VERSION_74",
	"EQ_SHIP_VERSION_75", "EQ_SHIP_VERSION_76", "EQ_SHIP_VERSION_77", "EQ_SHIP_VERSION_78", "EQ_SHIP_VERSION_79",
	"EQ_SHIP_VERSION_80", "EQ_SHIP_VERSION_81", "EQ_SHIP_VERSION_82", "EQ_SHIP_VERSION_83", "EQ_SHIP_VERSION_84",
	"EQ_SHIP_VERSION_85", "EQ_SHIP_VERSION_86", "EQ_SHIP_VERSION_87", "EQ_SHIP_VERSION_88", "EQ_SHIP_VERSION_89",
	"EQ_SHIP_VERSION_90", "EQ_SHIP_VERSION_91", "EQ_SHIP_VERSION_92", "EQ_SHIP_VERSION_93", "EQ_SHIP_VERSION_94",
	"EQ_SHIP_VERSION_95", "EQ_SHIP_VERSION_96", "EQ_SHIP_VERSION_97", "EQ_SHIP_VERSION_98", "EQ_SHIP_VERSION_99",
	"EQ_SHIP_VERSION_100",
	"EQ_SERVICE_LEVEL_75", "EQ_SERVICE_LEVEL_76", "EQ_SERVICE_LEVEL_77", "EQ_SERVICE_LEVEL_78", "EQ_SERVICE_LEVEL_79",
	"EQ_SERVICE_LEVEL_80", "EQ_SERVICE_LEVEL_81", "EQ_SERVICE_LEVEL_82", "EQ_SERVICE_LEVEL_83", "EQ_SERVICE_LEVEL_84",
	"EQ_SERVICE_LEVEL_85", "EQ_SERVICE_LEVEL_86", "EQ_SERVICE_LEVEL_87", "EQ_SERVICE_LEVEL_88", "EQ_SERVICE_LEVEL_89",
	"EQ_SERVICE_LEVEL_90", "EQ_SERVICE_LEVEL_91", "EQ_SERVICE_LEVEL_92", "EQ_SERVICE_LEVEL_93", "EQ_SERVICE_LEVEL_94",
	"EQ_SERVICE_LEVEL_95", "EQ_SERVICE_LEVEL_96", "EQ_SERVICE_LEVEL_97", "EQ_SERVICE_LEVEL_98", "EQ_SERVICE_LEVEL_99",
	"EQ_SERVICE_LEVEL_100", "EQ_NAVBEACONS_MFD", "EQ_DRAVEN"
];

this._filler = ["EQ_EQUIPSPACE_1", "EQ_EQUIPSPACE_2", "EQ_EQUIPSPACE_3", "EQ_EQUIPSPACE_4", "EQ_EQUIPSPACE_5", "EQ_EQUIPSPACE_6", "EQ_EQUIPSPACE_7", "EQ_EQUIPSPACE_8",
	"EQ_EQUIPSPACE_9", "EQ_EQUIPSPACE_10", "EQ_EQUIPSPACE_11", "EQ_EQUIPSPACE_12", "EQ_EQUIPSPACE_13", "EQ_EQUIPSPACE_14", "EQ_EQUIPSPACE_15", "EQ_EQUIPSPACE_16",
	"EQ_EQUIPSPACE_17", "EQ_EQUIPSPACE_18", "EQ_EQUIPSPACE_19", "EQ_EQUIPSPACE_20", "EQ_EQUIPSPACE_21", "EQ_EQUIPSPACE_22", "EQ_EQUIPSPACE_23", "EQ_EQUIPSPACE_24",
	"EQ_EQUIPSPACE_25", "EQ_EQUIPSPACE_26", "EQ_EQUIPSPACE_27", "EQ_EQUIPSPACE_28", "EQ_EQUIPSPACE_29", "EQ_EQUIPSPACE_30", "EQ_EQUIPSPACE_31", "EQ_EQUIPSPACE_32",
	"EQ_EQUIPSPACE_33", "EQ_EQUIPSPACE_34", "EQ_EQUIPSPACE_35", "EQ_EQUIPSPACE_36", "EQ_EQUIPSPACE_37", "EQ_EQUIPSPACE_38", "EQ_EQUIPSPACE_39", "EQ_EQUIPSPACE_40"
];

this._engines = ["EQ_ENGINE_TYPE1A", "EQ_ENGINE_TYPE1B", "EQ_ENGINE_TYPE1C", "EQ_ENGINE_TYPE1D", "EQ_ENGINE_TYPE1E", "EQ_ENGINE_TYPE1F",
	"EQ_ENGINE_TYPE2A", "EQ_ENGINE_TYPE2B", "EQ_ENGINE_TYPE2C", "EQ_ENGINE_TYPE2D", "EQ_ENGINE_TYPE2E", "EQ_ENGINE_TYPE2F",
	"EQ_ENGINE_TYPE3A", "EQ_ENGINE_TYPE3B", "EQ_ENGINE_TYPE3C", "EQ_ENGINE_TYPE3D", "EQ_ENGINE_TYPE3E", "EQ_ENGINE_TYPE3F",
	"EQ_ENGINE_TYPE4A", "EQ_ENGINE_TYPE4B", "EQ_ENGINE_TYPE4C", "EQ_ENGINE_TYPE4D", "EQ_ENGINE_TYPE4E", "EQ_ENGINE_TYPE4F",
	"EQ_ENGINE_TYPE5A", "EQ_ENGINE_TYPE5B", "EQ_ENGINE_TYPE5C", "EQ_ENGINE_TYPE5D", "EQ_ENGINE_TYPE5E", "EQ_ENGINE_TYPE5F",
	"EQ_ENGINE_TYPE6A", "EQ_ENGINE_TYPE6B", "EQ_ENGINE_TYPE6C", "EQ_ENGINE_TYPE6D", "EQ_ENGINE_TYPE6E", "EQ_ENGINE_TYPE6F",
	"EQ_ENGINE_TYPE7A", "EQ_ENGINE_TYPE7B", "EQ_ENGINE_TYPE7C", "EQ_ENGINE_TYPE7D", "EQ_ENGINE_TYPE7E", "EQ_ENGINE_TYPE7F"
];
this._boosters = ["EQ_BOOSTERS_TYPE1", "EQ_BOOSTERS_TYPE2", "EQ_BOOSTERS_TYPE3", "EQ_BOOSTERS_TYPE4", "EQ_BOOSTERS_TYPE5", "EQ_BOOSTERS_TYPE6", "EQ_BOOSTERS_TYPE7"];
this._hyperdrive = ["EQ_HYPERDRIVE_TYPE1", "EQ_HYPERDRIVE_TYPE2", "EQ_HYPERDRIVE_TYPE3", "EQ_HYPERDRIVE_TYPE4"];
this._thrusters = ["EQ_THRUSTERS_TYPE1", "EQ_THRUSTERS_TYPE2A", "EQ_THRUSTERS_TYPE2B", "EQ_THRUSTERS_TYPE2C", "EQ_THRUSTERS_TYPE2D", "EQ_THRUSTERS_TYPE2E", "EQ_THRUSTERS_TYPE2F",
	"EQ_THRUSTERS_TYPE3A", "EQ_THRUSTERS_TYPE3B", "EQ_THRUSTERS_TYPE3C", "EQ_THRUSTERS_TYPE3D", "EQ_THRUSTERS_TYPE3E", "EQ_THRUSTERS_TYPE3F",
	"EQ_THRUSTERS_TYPE4A", "EQ_THRUSTERS_TYPE4B", "EQ_THRUSTERS_TYPE4C", "EQ_THRUSTERS_TYPE4D", "EQ_THRUSTERS_TYPE4E", "EQ_THRUSTERS_TYPE4F",
	"EQ_THRUSTERS_TYPE5A", "EQ_THRUSTERS_TYPE5B", "EQ_THRUSTERS_TYPE5C", "EQ_THRUSTERS_TYPE5D", "EQ_THRUSTERS_TYPE5E", "EQ_THRUSTERS_TYPE5F",
	"EQ_THRUSTERS_TYPE6A", "EQ_THRUSTERS_TYPE6B", "EQ_THRUSTERS_TYPE6C", "EQ_THRUSTERS_TYPE6D", "EQ_THRUSTERS_TYPE6E", "EQ_THRUSTERS_TYPE6F",
	"EQ_THRUSTERS_TYPE7A", "EQ_THRUSTERS_TYPE7B", "EQ_THRUSTERS_TYPE7C", "EQ_THRUSTERS_TYPE7D", "EQ_THRUSTERS_TYPE7E", "EQ_THRUSTERS_TYPE7F"
];
this._energy = ["EQ_ENERGYBANK_TYPE1", "EQ_ENERGYBANK_TYPE2", "EQ_ENERGYBANK_TYPE3", "EQ_ENERGYBANK_TYPE4", "EQ_ENERGYBANK_TYPE5", "EQ_ENERGYBANK_TYPE6",
	"EQ_ENERGYBANK_TYPE7", "EQ_ENERGYBANK_TYPE8", "EQ_ENERGYBANK_TYPE9", "EQ_ENERGYBANK_TYPE10", "EQ_ENERGYBANK_TYPE11", "EQ_ENERGYBANK_TYPE12",
	"EQ_ENERGYBANK_TYPE13", "EQ_ENERGYBANK_TYPE14", "EQ_ENERGYBANK_TYPE15", "EQ_ENERGYBANK_TYPE16", "EQ_ENERGYBANK_TYPE17", "EQ_ENERGYBANK_TYPE18",
	"EQ_ENERGYBANK_TYPE19", "EQ_ENERGYBANK_TYPE20", "EQ_ENERGYBANK_TYPE21", "EQ_ENERGYBANK_TYPE22", "EQ_ENERGYBANK_TYPE23", "EQ_ENERGYBANK_TYPE24",
	"EQ_ENERGYBANK_TYPE25",
	"EQ_ENERGYBANK_TYPE1A", "EQ_ENERGYBANK_TYPE2A", "EQ_ENERGYBANK_TYPE3A", "EQ_ENERGYBANK_TYPE4A", "EQ_ENERGYBANK_TYPE5A", "EQ_ENERGYBANK_TYPE6A",
	"EQ_ENERGYBANK_TYPE7A", "EQ_ENERGYBANK_TYPE8A", "EQ_ENERGYBANK_TYPE9A", "EQ_ENERGYBANK_TYPE10A", "EQ_ENERGYBANK_TYPE11A", "EQ_ENERGYBANK_TYPE12A",
	"EQ_ENERGYBANK_TYPE13A", "EQ_ENERGYBANK_TYPE14A", "EQ_ENERGYBANK_TYPE15A", "EQ_ENERGYBANK_TYPE16A", "EQ_ENERGYBANK_TYPE17A", "EQ_ENERGYBANK_TYPE18A",
	"EQ_ENERGYBANK_TYPE19A", "EQ_ENERGYBANK_TYPE20A", "EQ_ENERGYBANK_TYPE21A", "EQ_ENERGYBANK_TYPE22A", "EQ_ENERGYBANK_TYPE23A", "EQ_ENERGYBANK_TYPE24A",
	"EQ_ENERGYBANK_TYPE25A"
];
this._frontshields = ["EQ_NO_FORWARD_SHIELD", "EQ_FORWARD_SHIELD_TYPE1", "EQ_FORWARD_SHIELD_TYPE2", "EQ_FORWARD_SHIELD_TYPE3", "EQ_FORWARD_SHIELD_TYPE4", "EQ_FORWARD_SHIELD_TYPE5"];
this._aftshields = ["EQ_NO_AFT_SHIELD", "EQ_AFT_SHIELD_TYPE1", "EQ_AFT_SHIELD_TYPE2", "EQ_AFT_SHIELD_TYPE3", "EQ_AFT_SHIELD_TYPE4", "EQ_AFT_SHIELD_TYPE5"];
this._heatshields = ["EQ_HEAT_SHIELD_TYPE1", "EQ_HEAT_SHIELD_TYPE2", "EQ_HEAT_SHIELD_TYPE3", "EQ_HEAT_SHIELD_TYPE4", "EQ_HEAT_SHIELD_TYPE5", "EQ_HEAT_SHIELD_TYPE6"];
this._fuelinjectors = ["EQ_FUEL_INJECTION_TYPE1", "EQ_FUEL_INJECTION_TYPE2", "EQ_FUEL_INJECTION_TYPE3", "EQ_FUEL_INJECTION_TYPE4"];
this._fuelscoops = ["EQ_FUEL_SCOOPS_TYPE1", "EQ_FUEL_SCOOPS_TYPE2", "EQ_FUEL_SCOOPS_TYPE3", "EQ_FUEL_SCOOPS_TYPE4"];
this._armour = [];
this._frontarmour = ["EQ_ARMOUR_FORWARD_TYPE1", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE5",
	"EQ_ARMOUR_FORWARD_TYPE6", "EQ_ARMOUR_FORWARD_TYPE7"
];
this._aftarmour = ["EQ_ARMOUR_AFT_TYPE1", "EQ_ARMOUR_AFT_TYPE2", "EQ_ARMOUR_AFT_TYPE3", "EQ_ARMOUR_AFT_TYPE4", "EQ_ARMOUR_AFT_TYPE5", "EQ_ARMOUR_AFT_TYPE6",
	"EQ_ARMOUR_AFT_TYPE7"
];
this._electricalbus = ["EQ_ELEC_BUS_TYPE1", "EQ_ELEC_BUS_TYPE2", "EQ_ELEC_BUS_TYPE3", "EQ_ELEC_BUS_TYPE4", "EQ_ELEC_BUS_TYPE5", "EQ_ELEC_BUS_TYPE6", "EQ_ELEC_BUS_TYPE7"];
this._hdCoupling = ["EQ_HYPERDRIVE_COUPLING_TYPE1", "EQ_HYPERDRIVE_COUPLING_TYPE2", "EQ_HYPERDRIVE_COUPLING_TYPE3", "EQ_HYPERDRIVE_COUPLING_TYPE4"];
this._enCoupling = ["EQ_ENGINE_COUPLING_TYPE1", "EQ_ENGINE_COUPLING_TYPE2", "EQ_ENGINE_COUPLING_TYPE3", "EQ_ENGINE_COUPLING_TYPE4", "EQ_ENGINE_COUPLING_TYPE5",
	"EQ_ENGINE_COUPLING_TYPE6", "EQ_ENGINE_COUPLING_TYPE7"
];
this._bsCoupling = ["EQ_BOOSTERS_COUPLING_TYPE1", "EQ_BOOSTERS_COUPLING_TYPE2", "EQ_BOOSTERS_COUPLING_TYPE3", "EQ_BOOSTERS_COUPLING_TYPE4", "EQ_BOOSTERS_COUPLING_TYPE5",
	"EQ_BOOSTERS_COUPLING_TYPE6", "EQ_BOOSTERS_COUPLING_TYPE7"
];
this._ebCoupling = ["EQ_ENERGYBANK_COUPLING_TYPE1", "EQ_ENERGYBANK_COUPLING_TYPE2", "EQ_ENERGYBANK_COUPLING_TYPE3", "EQ_ENERGYBANK_COUPLING_TYPE4", "EQ_ENERGYBANK_COUPLING_TYPE5",
	"EQ_ENERGYBANK_COUPLING_TYPE6", "EQ_ENERGYBANK_COUPLING_TYPE7", "EQ_ENERGYBANK_COUPLING_TYPE8"
];
this._thCoupling = ["EQ_THRUSTERS_COUPLING_TYPE1", "EQ_THRUSTERS_COUPLING_TYPE2", "EQ_THRUSTERS_COUPLING_TYPE3", "EQ_THRUSTERS_COUPLING_TYPE4", "EQ_THRUSTERS_COUPLING_TYPE5",
	"EQ_THRUSTERS_COUPLING_TYPE6", "EQ_THRUSTERS_COUPLING_TYPE7"
];
this._fsCoupling = ["EQ_FORWARD_SHIELD_COUPLING_TYPE1", "EQ_FORWARD_SHIELD_COUPLING_TYPE2", "EQ_FORWARD_SHIELD_COUPLING_TYPE3", "EQ_FORWARD_SHIELD_COUPLING_TYPE4",
	"EQ_FORWARD_SHIELD_COUPLING_TYPE5"
];
this._asCoupling = ["EQ_AFT_SHIELD_COUPLING_TYPE1", "EQ_AFT_SHIELD_COUPLING_TYPE2", "EQ_AFT_SHIELD_COUPLING_TYPE3", "EQ_AFT_SHIELD_COUPLING_TYPE4", "EQ_AFT_SHIELD_COUPLING_TYPE5"];
// these items will have a ship-size based price factor applied to their purchase price
this._priceFactor = [].concat(this._engines).concat(this._boosters).concat(this._hyperdrive).concat(this._thrusters)
	.concat(this._energy).concat(this._frontshields).concat(this._aftshields).concat(this._frontarmour).concat(this._aftarmour)
	.concat(this._electricalbus).concat(this._hdCoupling).concat(this._enCoupling).concat(this._bsCoupling).concat(this._ebCoupling)
	.concat(this._thCoupling).concat(this._fsCoupling).concat(this._asCoupling);

this._equipCouplingBus = {
	"EQ_THRUSTERS_TYPE1": "EQ_THRUSTERS_COUPLING_TYPE1",
	"EQ_THRUSTERS_TYPE2A": "EQ_THRUSTERS_COUPLING_TYPE2",
	"EQ_THRUSTERS_TYPE2B": "EQ_THRUSTERS_COUPLING_TYPE2",
	"EQ_THRUSTERS_TYPE2C": "EQ_THRUSTERS_COUPLING_TYPE2",
	"EQ_THRUSTERS_TYPE2D": "EQ_THRUSTERS_COUPLING_TYPE2",
	"EQ_THRUSTERS_TYPE2E": "EQ_THRUSTERS_COUPLING_TYPE2",
	"EQ_THRUSTERS_TYPE2F": "EQ_THRUSTERS_COUPLING_TYPE2",
	"EQ_THRUSTERS_TYPE3A": "EQ_THRUSTERS_COUPLING_TYPE3",
	"EQ_THRUSTERS_TYPE3B": "EQ_THRUSTERS_COUPLING_TYPE3",
	"EQ_THRUSTERS_TYPE3C": "EQ_THRUSTERS_COUPLING_TYPE3",
	"EQ_THRUSTERS_TYPE3D": "EQ_THRUSTERS_COUPLING_TYPE3",
	"EQ_THRUSTERS_TYPE3E": "EQ_THRUSTERS_COUPLING_TYPE3",
	"EQ_THRUSTERS_TYPE3F": "EQ_THRUSTERS_COUPLING_TYPE3",
	"EQ_THRUSTERS_TYPE4A": "EQ_THRUSTERS_COUPLING_TYPE4",
	"EQ_THRUSTERS_TYPE4B": "EQ_THRUSTERS_COUPLING_TYPE4",
	"EQ_THRUSTERS_TYPE4C": "EQ_THRUSTERS_COUPLING_TYPE4",
	"EQ_THRUSTERS_TYPE4D": "EQ_THRUSTERS_COUPLING_TYPE4",
	"EQ_THRUSTERS_TYPE4E": "EQ_THRUSTERS_COUPLING_TYPE4",
	"EQ_THRUSTERS_TYPE4F": "EQ_THRUSTERS_COUPLING_TYPE4",
	"EQ_THRUSTERS_TYPE5A": "EQ_THRUSTERS_COUPLING_TYPE5",
	"EQ_THRUSTERS_TYPE5B": "EQ_THRUSTERS_COUPLING_TYPE5",
	"EQ_THRUSTERS_TYPE5C": "EQ_THRUSTERS_COUPLING_TYPE5",
	"EQ_THRUSTERS_TYPE5D": "EQ_THRUSTERS_COUPLING_TYPE5",
	"EQ_THRUSTERS_TYPE5E": "EQ_THRUSTERS_COUPLING_TYPE5",
	"EQ_THRUSTERS_TYPE5F": "EQ_THRUSTERS_COUPLING_TYPE5",
	"EQ_THRUSTERS_TYPE6A": "EQ_THRUSTERS_COUPLING_TYPE6",
	"EQ_THRUSTERS_TYPE6B": "EQ_THRUSTERS_COUPLING_TYPE6",
	"EQ_THRUSTERS_TYPE6C": "EQ_THRUSTERS_COUPLING_TYPE6",
	"EQ_THRUSTERS_TYPE6D": "EQ_THRUSTERS_COUPLING_TYPE6",
	"EQ_THRUSTERS_TYPE6E": "EQ_THRUSTERS_COUPLING_TYPE6",
	"EQ_THRUSTERS_TYPE6F": "EQ_THRUSTERS_COUPLING_TYPE6",
	"EQ_THRUSTERS_TYPE7A": "EQ_THRUSTERS_COUPLING_TYPE7",
	"EQ_THRUSTERS_TYPE7B": "EQ_THRUSTERS_COUPLING_TYPE7",
	"EQ_THRUSTERS_TYPE7C": "EQ_THRUSTERS_COUPLING_TYPE7",
	"EQ_THRUSTERS_TYPE7D": "EQ_THRUSTERS_COUPLING_TYPE7",
	"EQ_THRUSTERS_TYPE7E": "EQ_THRUSTERS_COUPLING_TYPE7",
	"EQ_THRUSTERS_TYPE7F": "EQ_THRUSTERS_COUPLING_TYPE7",
	"EQ_ENERGYBANK_TYPE1": "EQ_ENERGYBANK_COUPLING_TYPE1",
	"EQ_ENERGYBANK_TYPE2": "EQ_ENERGYBANK_COUPLING_TYPE1",
	"EQ_ENERGYBANK_TYPE3": "EQ_ENERGYBANK_COUPLING_TYPE1",
	"EQ_ENERGYBANK_TYPE4": "EQ_ENERGYBANK_COUPLING_TYPE1",
	"EQ_ENERGYBANK_TYPE5": "EQ_ENERGYBANK_COUPLING_TYPE2",
	"EQ_ENERGYBANK_TYPE6": "EQ_ENERGYBANK_COUPLING_TYPE2",
	"EQ_ENERGYBANK_TYPE7": "EQ_ENERGYBANK_COUPLING_TYPE2",
	"EQ_ENERGYBANK_TYPE8": "EQ_ENERGYBANK_COUPLING_TYPE3",
	"EQ_ENERGYBANK_TYPE9": "EQ_ENERGYBANK_COUPLING_TYPE3",
	"EQ_ENERGYBANK_TYPE10": "EQ_ENERGYBANK_COUPLING_TYPE3",
	"EQ_ENERGYBANK_TYPE11": "EQ_ENERGYBANK_COUPLING_TYPE4",
	"EQ_ENERGYBANK_TYPE12": "EQ_ENERGYBANK_COUPLING_TYPE4",
	"EQ_ENERGYBANK_TYPE13": "EQ_ENERGYBANK_COUPLING_TYPE4",
	"EQ_ENERGYBANK_TYPE14": "EQ_ENERGYBANK_COUPLING_TYPE5",
	"EQ_ENERGYBANK_TYPE15": "EQ_ENERGYBANK_COUPLING_TYPE5",
	"EQ_ENERGYBANK_TYPE16": "EQ_ENERGYBANK_COUPLING_TYPE5",
	"EQ_ENERGYBANK_TYPE17": "EQ_ENERGYBANK_COUPLING_TYPE6",
	"EQ_ENERGYBANK_TYPE18": "EQ_ENERGYBANK_COUPLING_TYPE6",
	"EQ_ENERGYBANK_TYPE19": "EQ_ENERGYBANK_COUPLING_TYPE6",
	"EQ_ENERGYBANK_TYPE20": "EQ_ENERGYBANK_COUPLING_TYPE7",
	"EQ_ENERGYBANK_TYPE21": "EQ_ENERGYBANK_COUPLING_TYPE7",
	"EQ_ENERGYBANK_TYPE22": "EQ_ENERGYBANK_COUPLING_TYPE7",
	"EQ_ENERGYBANK_TYPE23": "EQ_ENERGYBANK_COUPLING_TYPE8",
	"EQ_ENERGYBANK_TYPE24": "EQ_ENERGYBANK_COUPLING_TYPE8",
	"EQ_ENERGYBANK_TYPE25": "EQ_ENERGYBANK_COUPLING_TYPE8",
	"EQ_ENERGYBANK_TYPE1A": "EQ_ENERGYBANK_COUPLING_TYPE1",
	"EQ_ENERGYBANK_TYPE2A": "EQ_ENERGYBANK_COUPLING_TYPE1",
	"EQ_ENERGYBANK_TYPE3A": "EQ_ENERGYBANK_COUPLING_TYPE1",
	"EQ_ENERGYBANK_TYPE4A": "EQ_ENERGYBANK_COUPLING_TYPE1",
	"EQ_ENERGYBANK_TYPE5A": "EQ_ENERGYBANK_COUPLING_TYPE2",
	"EQ_ENERGYBANK_TYPE6A": "EQ_ENERGYBANK_COUPLING_TYPE2",
	"EQ_ENERGYBANK_TYPE7A": "EQ_ENERGYBANK_COUPLING_TYPE2",
	"EQ_ENERGYBANK_TYPE8A": "EQ_ENERGYBANK_COUPLING_TYPE3",
	"EQ_ENERGYBANK_TYPE9A": "EQ_ENERGYBANK_COUPLING_TYPE3",
	"EQ_ENERGYBANK_TYPE10A": "EQ_ENERGYBANK_COUPLING_TYPE3",
	"EQ_ENERGYBANK_TYPE11A": "EQ_ENERGYBANK_COUPLING_TYPE4",
	"EQ_ENERGYBANK_TYPE12A": "EQ_ENERGYBANK_COUPLING_TYPE4",
	"EQ_ENERGYBANK_TYPE13A": "EQ_ENERGYBANK_COUPLING_TYPE4",
	"EQ_ENERGYBANK_TYPE14A": "EQ_ENERGYBANK_COUPLING_TYPE5",
	"EQ_ENERGYBANK_TYPE15A": "EQ_ENERGYBANK_COUPLING_TYPE5",
	"EQ_ENERGYBANK_TYPE16A": "EQ_ENERGYBANK_COUPLING_TYPE5",
	"EQ_ENERGYBANK_TYPE17A": "EQ_ENERGYBANK_COUPLING_TYPE6",
	"EQ_ENERGYBANK_TYPE18A": "EQ_ENERGYBANK_COUPLING_TYPE6",
	"EQ_ENERGYBANK_TYPE19A": "EQ_ENERGYBANK_COUPLING_TYPE6",
	"EQ_ENERGYBANK_TYPE20A": "EQ_ENERGYBANK_COUPLING_TYPE7",
	"EQ_ENERGYBANK_TYPE21A": "EQ_ENERGYBANK_COUPLING_TYPE7",
	"EQ_ENERGYBANK_TYPE22A": "EQ_ENERGYBANK_COUPLING_TYPE7",
	"EQ_ENERGYBANK_TYPE23A": "EQ_ENERGYBANK_COUPLING_TYPE8",
	"EQ_ENERGYBANK_TYPE24A": "EQ_ENERGYBANK_COUPLING_TYPE8",
	"EQ_ENERGYBANK_TYPE25A": "EQ_ENERGYBANK_COUPLING_TYPE8",
};
this._extensions = ["EQ_EXTENSION_1", "EQ_EXTENSION_2", "EQ_EXTENSION_5"];
this._equipHeatList = {
	"EQ_ENERGYBANK_TYPE1A": 0.004,
	"EQ_ENERGYBANK_TYPE2A": 0.008,
	"EQ_ENERGYBANK_TYPE3A": 0.012,
	"EQ_ENERGYBANK_TYPE4A": 0.016,
	"EQ_ENERGYBANK_TYPE5A": 0.02,
	"EQ_ENERGYBANK_TYPE6A": 0.024,
	"EQ_ENERGYBANK_TYPE7A": 0.028,
	"EQ_ENERGYBANK_TYPE8A": 0.032,
	"EQ_ENERGYBANK_TYPE9A": 0.036,
	"EQ_ENERGYBANK_TYPE10A": 0.04,
	"EQ_ENERGYBANK_TYPE11A": 0.044,
	"EQ_ENERGYBANK_TYPE12A": 0.048,
	"EQ_ENERGYBANK_TYPE13A": 0.052,
	"EQ_ENERGYBANK_TYPE14A": 0.056,
	"EQ_ENERGYBANK_TYPE15A": 0.06,
	"EQ_ENERGYBANK_TYPE16A": 0.064,
	"EQ_ENERGYBANK_TYPE17A": 0.068,
	"EQ_ENERGYBANK_TYPE18A": 0.072,
	"EQ_ENERGYBANK_TYPE19A": 0.076,
	"EQ_ENERGYBANK_TYPE20A": 0.08,
	"EQ_ENERGYBANK_TYPE21A": 0.084,
	"EQ_ENERGYBANK_TYPE22A": 0.088,
	"EQ_ENERGYBANK_TYPE23A": 0.092,
	"EQ_ENERGYBANK_TYPE24A": 0.096,
	"EQ_ENERGYBANK_TYPE25A": 0.1,
	"EQ_ENGINE_TYPE1D": 0.02,
	"EQ_ENGINE_TYPE1E": 0.02,
	"EQ_ENGINE_TYPE1F": 0.02,
	"EQ_ENGINE_TYPE2D": 0.04,
	"EQ_ENGINE_TYPE2E": 0.04,
	"EQ_ENGINE_TYPE2F": 0.04,
	"EQ_ENGINE_TYPE3D": 0.06,
	"EQ_ENGINE_TYPE3E": 0.06,
	"EQ_ENGINE_TYPE3F": 0.06,
	"EQ_ENGINE_TYPE4D": 0.08,
	"EQ_ENGINE_TYPE4E": 0.08,
	"EQ_ENGINE_TYPE4F": 0.08,
	"EQ_ENGINE_TYPE5D": 0.1,
	"EQ_ENGINE_TYPE5E": 0.1,
	"EQ_ENGINE_TYPE5F": 0.1,
	"EQ_ENGINE_TYPE6D": 0.12,
	"EQ_ENGINE_TYPE6E": 0.12,
	"EQ_ENGINE_TYPE6F": 0.12,
	"EQ_ENGINE_TYPE7D": 0.14,
	"EQ_ENGINE_TYPE7E": 0.14,
	"EQ_ENGINE_TYPE7F": 0.14,
	"EQ_THRUSTERS_TYPE2D": 0.0266,
	"EQ_THRUSTERS_TYPE2E": 0.0266,
	"EQ_THRUSTERS_TYPE2F": 0.0266,
	"EQ_THRUSTERS_TYPE3D": 0.04,
	"EQ_THRUSTERS_TYPE3E": 0.04,
	"EQ_THRUSTERS_TYPE3F": 0.04,
	"EQ_THRUSTERS_TYPE4D": 0.0533,
	"EQ_THRUSTERS_TYPE4E": 0.0533,
	"EQ_THRUSTERS_TYPE4F": 0.0533,
	"EQ_THRUSTERS_TYPE5D": 0.0666,
	"EQ_THRUSTERS_TYPE5E": 0.0666,
	"EQ_THRUSTERS_TYPE5F": 0.0666,
	"EQ_THRUSTERS_TYPE6D": 0.08,
	"EQ_THRUSTERS_TYPE6E": 0.08,
	"EQ_THRUSTERS_TYPE6F": 0.08,
	"EQ_THRUSTERS_TYPE7D": 0.0933,
	"EQ_THRUSTERS_TYPE7E": 0.0933,
	"EQ_THRUSTERS_TYPE7F": 0.0933,
};

// this items will be suppressed on the "Sell Equipment" screen
this._noSell = ["EQ_BREAKABLE_TORUSDRIVE", "EQ_BREAKABLE_HUD_IFF_SCANNER"];
// array of rare equipment items that will require negotiation if they are sold
this._sellNegotiate = [];

// if any of these are installed, ship config won't allow its own armour to be installed
this._altArmour = ["EQ_IRONHIDE", "EQ_HARDNOSE", "EQ_VERYHARDNOSE", "EQ_VERYVERYHARDNOSE", "EQ_HARDARMOUR_III", "EQ_HARDARMOUR_V", "EQ_HARDARMOUR_X"];

this._shieldEquipment = ["EQ_SHIELD_BOOSTER", "EQ_NAVAL_SHIELD_BOOSTER", "EQ_NAVAL_GRID", "EQ_ENERGY_GRID"];

// matrix consists of: equipment key, then space required (t), weight of item (t)
// eg: "EQ_EQUIPMENTITEM":[space,weight]
// items not on this list (and not in ignore list) will default to 1t space, 1t weight
this._equipmentMatrix = {
	"EQ_MISSILE": [0, 0.1],
	"EQ_HARDENED_MISSILE": [0, 0.3],
	"EQ_QC_MINE": [0, 0.2],
	"EQ_WEAPON_PULSE_LASER": [0, 1],
	"EQ_WEAPON_BEAM_LASER": [0, 2],
	"EQ_WEAPON_MINING_LASER": [0, 1.5],
	"EQ_WEAPON_MILITARY_LASER": [0, 3],
	"EQ_PASSENGER_BERTH": [0, 5],
	"EQ_CARGO_BAY": [0, 5],
	"EQ_ECM": [1, 1],
	"EQ_FUEL_SCOOPS": [0, 0],
	"EQ_ESCAPE_POD": [0, 1],
	"EQ_ENERGY_UNIT": [3, 3],
	"EQ_NAVAL_ENERGY_UNIT": [5, 5],
	"EQ_DOCK_COMP": [1, 1],
	"EQ_GAL_DRIVE": [1, 1],
	"EQ_CLOAKING_DEVICE": [1, 1],
	"EQ_ADVANCED_COMPASS": [1, 1],
	"EQ_WORMHOLE_SCANNER": [1, 1],
	"EQ_SHIELD_BOOSTER": [4, 4],
	"EQ_NAVAL_SHIELD_BOOSTER": [6, 6],
	"EQ_MILITARY_SCANNER_FILTER": [4, 4],
	"EQ_MILITARY_JAMMER": [4, 4],

	"EQ_HYPERDRIVE_TYPE1": [1, 1],
	"EQ_HYPERDRIVE_TYPE2": [2, 2],
	"EQ_HYPERDRIVE_TYPE3": [5, 5],
	"EQ_HYPERDRIVE_TYPE4": [8, 8],
	"EQ_ENGINE_TYPE1A": [1, 1],
	"EQ_ENGINE_TYPE1B": [1, 1],
	"EQ_ENGINE_TYPE1C": [1, 1],
	"EQ_ENGINE_TYPE1D": [0.5, 1],
	"EQ_ENGINE_TYPE1E": [0.5, 1],
	"EQ_ENGINE_TYPE1F": [0.5, 1],
	"EQ_ENGINE_TYPE2A": [2, 2],
	"EQ_ENGINE_TYPE2B": [2, 2],
	"EQ_ENGINE_TYPE2C": [2, 2],
	"EQ_ENGINE_TYPE2D": [1, 1.5],
	"EQ_ENGINE_TYPE2E": [1, 1.5],
	"EQ_ENGINE_TYPE2F": [1, 1.5],
	"EQ_ENGINE_TYPE3A": [3, 3],
	"EQ_ENGINE_TYPE3B": [3, 3],
	"EQ_ENGINE_TYPE3C": [3, 3],
	"EQ_ENGINE_TYPE3D": [1.5, 2],
	"EQ_ENGINE_TYPE3E": [1.5, 2],
	"EQ_ENGINE_TYPE3F": [1.5, 2],
	"EQ_ENGINE_TYPE4A": [4, 3.5],
	"EQ_ENGINE_TYPE4B": [4, 3.5],
	"EQ_ENGINE_TYPE4C": [4, 3.5],
	"EQ_ENGINE_TYPE4D": [2, 3],
	"EQ_ENGINE_TYPE4E": [2, 3],
	"EQ_ENGINE_TYPE4F": [2, 3],
	"EQ_ENGINE_TYPE5A": [6, 4],
	"EQ_ENGINE_TYPE5B": [6, 4],
	"EQ_ENGINE_TYPE5C": [6, 4],
	"EQ_ENGINE_TYPE5D": [3, 3.5],
	"EQ_ENGINE_TYPE5E": [3, 3.5],
	"EQ_ENGINE_TYPE5F": [3, 3.5],
	"EQ_ENGINE_TYPE6A": [8, 5],
	"EQ_ENGINE_TYPE6B": [8, 5],
	"EQ_ENGINE_TYPE6C": [8, 5],
	"EQ_ENGINE_TYPE6D": [4, 4],
	"EQ_ENGINE_TYPE6E": [4, 4],
	"EQ_ENGINE_TYPE6F": [4, 4],
	"EQ_ENGINE_TYPE7A": [10, 6],
	"EQ_ENGINE_TYPE7B": [10, 6],
	"EQ_ENGINE_TYPE7C": [10, 6],
	"EQ_ENGINE_TYPE7D": [5, 5],
	"EQ_ENGINE_TYPE7E": [5, 5],
	"EQ_ENGINE_TYPE7F": [5, 5],
	"EQ_THRUSTERS_TYPE1": [0, 1],
	"EQ_THRUSTERS_TYPE2A": [1, 2],
	"EQ_THRUSTERS_TYPE2B": [1, 2],
	"EQ_THRUSTERS_TYPE2C": [1, 2],
	"EQ_THRUSTERS_TYPE2D": [0.5, 1],
	"EQ_THRUSTERS_TYPE2E": [0.5, 1],
	"EQ_THRUSTERS_TYPE2F": [0.5, 1],
	"EQ_THRUSTERS_TYPE3A": [2, 3],
	"EQ_THRUSTERS_TYPE3B": [2, 3],
	"EQ_THRUSTERS_TYPE3C": [2, 3],
	"EQ_THRUSTERS_TYPE3D": [1, 2],
	"EQ_THRUSTERS_TYPE3E": [1, 2],
	"EQ_THRUSTERS_TYPE3F": [1, 2],
	"EQ_THRUSTERS_TYPE4A": [3, 3.5],
	"EQ_THRUSTERS_TYPE4B": [3, 3.5],
	"EQ_THRUSTERS_TYPE4C": [3, 3.5],
	"EQ_THRUSTERS_TYPE4D": [1.5, 2.5],
	"EQ_THRUSTERS_TYPE4E": [1.5, 2.5],
	"EQ_THRUSTERS_TYPE4F": [1.5, 2.5],
	"EQ_THRUSTERS_TYPE5A": [4, 4],
	"EQ_THRUSTERS_TYPE5B": [4, 4],
	"EQ_THRUSTERS_TYPE5C": [4, 4],
	"EQ_THRUSTERS_TYPE5D": [2, 3],
	"EQ_THRUSTERS_TYPE5E": [2, 3],
	"EQ_THRUSTERS_TYPE5F": [2, 3],
	"EQ_THRUSTERS_TYPE6A": [6, 4.5],
	"EQ_THRUSTERS_TYPE6B": [6, 4.5],
	"EQ_THRUSTERS_TYPE6C": [6, 4.5],
	"EQ_THRUSTERS_TYPE6D": [3, 3.5],
	"EQ_THRUSTERS_TYPE6E": [3, 3.5],
	"EQ_THRUSTERS_TYPE6F": [3, 3.5],
	"EQ_THRUSTERS_TYPE7A": [8, 5],
	"EQ_THRUSTERS_TYPE7B": [8, 5],
	"EQ_THRUSTERS_TYPE7C": [8, 5],
	"EQ_THRUSTERS_TYPE7D": [4, 4],
	"EQ_THRUSTERS_TYPE7E": [4, 4],
	"EQ_THRUSTERS_TYPE7F": [4, 4],
	"EQ_BOOSTERS_TYPE1": [1, 1],
	"EQ_BOOSTERS_TYPE2": [1.5, 1.5],
	"EQ_BOOSTERS_TYPE3": [2, 2],
	"EQ_BOOSTERS_TYPE4": [2.5, 2.5],
	"EQ_BOOSTERS_TYPE5": [3, 3],
	"EQ_BOOSTERS_TYPE6": [3.5, 3.5],
	"EQ_BOOSTERS_TYPE7": [4, 4],
	"EQ_ENERGYBANK_TYPE1": [1, 1],
	"EQ_ENERGYBANK_TYPE2": [2, 2],
	"EQ_ENERGYBANK_TYPE3": [3, 3],
	"EQ_ENERGYBANK_TYPE4": [4, 4],
	"EQ_ENERGYBANK_TYPE5": [5, 5],
	"EQ_ENERGYBANK_TYPE6": [6, 6],
	"EQ_ENERGYBANK_TYPE7": [7, 7],
	"EQ_ENERGYBANK_TYPE8": [8, 8],
	"EQ_ENERGYBANK_TYPE9": [9, 9],
	"EQ_ENERGYBANK_TYPE10": [10, 10],
	"EQ_ENERGYBANK_TYPE11": [11, 11],
	"EQ_ENERGYBANK_TYPE12": [12, 12],
	"EQ_ENERGYBANK_TYPE13": [13, 13],
	"EQ_ENERGYBANK_TYPE14": [14, 14],
	"EQ_ENERGYBANK_TYPE15": [15, 15],
	"EQ_ENERGYBANK_TYPE16": [16, 16],
	"EQ_ENERGYBANK_TYPE17": [17, 17],
	"EQ_ENERGYBANK_TYPE18": [18, 18],
	"EQ_ENERGYBANK_TYPE19": [19, 19],
	"EQ_ENERGYBANK_TYPE20": [20, 20],
	"EQ_ENERGYBANK_TYPE21": [21, 21],
	"EQ_ENERGYBANK_TYPE22": [22, 22],
	"EQ_ENERGYBANK_TYPE23": [23, 23],
	"EQ_ENERGYBANK_TYPE24": [24, 24],
	"EQ_ENERGYBANK_TYPE25": [25, 25],
	"EQ_ENERGYBANK_TYPE1A": [0.5, 1],
	"EQ_ENERGYBANK_TYPE2A": [1, 2],
	"EQ_ENERGYBANK_TYPE3A": [1.5, 3],
	"EQ_ENERGYBANK_TYPE4A": [2, 4],
	"EQ_ENERGYBANK_TYPE5A": [2.5, 5],
	"EQ_ENERGYBANK_TYPE6A": [3, 6],
	"EQ_ENERGYBANK_TYPE7A": [3.5, 7],
	"EQ_ENERGYBANK_TYPE8A": [4, 8],
	"EQ_ENERGYBANK_TYPE9A": [4.5, 9],
	"EQ_ENERGYBANK_TYPE10A": [5, 10],
	"EQ_ENERGYBANK_TYPE11A": [5.5, 11],
	"EQ_ENERGYBANK_TYPE12A": [6, 12],
	"EQ_ENERGYBANK_TYPE13A": [6.5, 13],
	"EQ_ENERGYBANK_TYPE14A": [7, 14],
	"EQ_ENERGYBANK_TYPE15A": [7.5, 15],
	"EQ_ENERGYBANK_TYPE16A": [8, 16],
	"EQ_ENERGYBANK_TYPE17A": [8.5, 17],
	"EQ_ENERGYBANK_TYPE18A": [9, 18],
	"EQ_ENERGYBANK_TYPE19A": [9.5, 19],
	"EQ_ENERGYBANK_TYPE20A": [10, 20],
	"EQ_ENERGYBANK_TYPE21A": [10.5, 21],
	"EQ_ENERGYBANK_TYPE22A": [11, 22],
	"EQ_ENERGYBANK_TYPE23A": [11.5, 23],
	"EQ_ENERGYBANK_TYPE24A": [12, 24],
	"EQ_ENERGYBANK_TYPE25A": [12.5, 25],
	"EQ_NO_FORWARD_SHIELD": [0, 0],
	"EQ_FORWARD_SHIELD_TYPE1": [1, 1],
	"EQ_FORWARD_SHIELD_TYPE2": [2, 2],
	"EQ_FORWARD_SHIELD_TYPE3": [3, 3],
	"EQ_FORWARD_SHIELD_TYPE4": [4, 4],
	"EQ_FORWARD_SHIELD_TYPE5": [5, 5],
	"EQ_NO_AFT_SHIELD": [0, 0],
	"EQ_AFT_SHIELD_TYPE1": [1, 1],
	"EQ_AFT_SHIELD_TYPE2": [2, 2],
	"EQ_AFT_SHIELD_TYPE3": [3, 3],
	"EQ_AFT_SHIELD_TYPE4": [4, 4],
	"EQ_AFT_SHIELD_TYPE5": [5, 5],
	"EQ_HEAT_SHIELD_TYPE1": [0, 1],
	"EQ_HEAT_SHIELD_TYPE2": [0, 3],
	"EQ_HEAT_SHIELD_TYPE3": [0, 6],
	"EQ_HEAT_SHIELD_TYPE4": [0, 9],
	"EQ_HEAT_SHIELD_TYPE5": [0, 12],
	"EQ_HEAT_SHIELD_TYPE6": [0, 16],
	"EQ_FUEL_INJECTION_TYPE1": [0.5, 1],
	"EQ_FUEL_INJECTION_TYPE2": [1, 2],
	"EQ_FUEL_INJECTION_TYPE3": [2, 3],
	"EQ_FUEL_INJECTION_TYPE4": [4, 5],
	"EQ_FUEL_SCOOPS_TYPE1": [0, 2],
	"EQ_FUEL_SCOOPS_TYPE2": [0, 4],
	"EQ_FUEL_SCOOPS_TYPE3": [0, 6],
	"EQ_FUEL_SCOOPS_TYPE4": [0, 8],
	"EQ_ARMOUR_TYPE1": [0, 0], // obsolete
	"EQ_ARMOUR_TYPE2": [0, 0], // obsolete
	"EQ_ARMOUR_TYPE3": [0, 0], // obsolete
	"EQ_ARMOUR_TYPE4": [0, 0], // obsolete
	"EQ_ARMOUR_TYPE5": [0, 0], // obsolete
	"EQ_ARMOUR_TYPE6": [0, 0], // obsolete
	"EQ_ARMOUR_TYPE7": [0, 0], // obsolete
	"EQ_ARMOUR_FORWARD_TYPE1": [0, 2],
	"EQ_ARMOUR_FORWARD_TYPE2": [0, 7],
	"EQ_ARMOUR_FORWARD_TYPE3": [0, 15],
	"EQ_ARMOUR_FORWARD_TYPE4": [0, 25],
	"EQ_ARMOUR_FORWARD_TYPE5": [0, 40],
	"EQ_ARMOUR_FORWARD_TYPE6": [0, 52],
	"EQ_ARMOUR_FORWARD_TYPE7": [0, 70],
	"EQ_ARMOUR_AFT_TYPE1": [0, 2],
	"EQ_ARMOUR_AFT_TYPE2": [0, 7],
	"EQ_ARMOUR_AFT_TYPE3": [0, 15],
	"EQ_ARMOUR_AFT_TYPE4": [0, 25],
	"EQ_ARMOUR_AFT_TYPE5": [0, 40],
	"EQ_ARMOUR_AFT_TYPE6": [0, 52],
	"EQ_ARMOUR_AFT_TYPE7": [0, 70],
	"EQ_ELEC_BUS_TYPE1": [0, 1],
	"EQ_ELEC_BUS_TYPE2": [0, 4],
	"EQ_ELEC_BUS_TYPE3": [2, 7],
	"EQ_ELEC_BUS_TYPE4": [4, 12],
	"EQ_ELEC_BUS_TYPE5": [6, 17],
	"EQ_ELEC_BUS_TYPE6": [8, 23],
	"EQ_ELEC_BUS_TYPE7": [10, 30],
	"EQ_HYPERDRIVE_COUPLING_TYPE1": [0, 0.1],
	"EQ_HYPERDRIVE_COUPLING_TYPE2": [0, 0.2],
	"EQ_HYPERDRIVE_COUPLING_TYPE3": [0, 0.3],
	"EQ_HYPERDRIVE_COUPLING_TYPE4": [0, 0.4],
	"EQ_ENGINE_COUPLING_TYPE1": [0, 0.1],
	"EQ_ENGINE_COUPLING_TYPE2": [0, 0.2],
	"EQ_ENGINE_COUPLING_TYPE3": [0, 0.3],
	"EQ_ENGINE_COUPLING_TYPE4": [0, 0.4],
	"EQ_ENGINE_COUPLING_TYPE5": [0, 0.5],
	"EQ_ENGINE_COUPLING_TYPE6": [0, 0.6],
	"EQ_ENGINE_COUPLING_TYPE7": [0, 0.7],
	"EQ_BOOSTERS_COUPLING_TYPE1": [0, 0.1],
	"EQ_BOOSTERS_COUPLING_TYPE2": [0, 0.2],
	"EQ_BOOSTERS_COUPLING_TYPE3": [0, 0.3],
	"EQ_BOOSTERS_COUPLING_TYPE4": [0, 0.4],
	"EQ_BOOSTERS_COUPLING_TYPE5": [0, 0.5],
	"EQ_BOOSTERS_COUPLING_TYPE6": [0, 0.6],
	"EQ_BOOSTERS_COUPLING_TYPE7": [0, 0.7],
	"EQ_ENERGYBANK_COUPLING_TYPE1": [0, 0.1],
	"EQ_ENERGYBANK_COUPLING_TYPE2": [0, 0.2],
	"EQ_ENERGYBANK_COUPLING_TYPE3": [0, 0.3],
	"EQ_ENERGYBANK_COUPLING_TYPE4": [0, 0.4],
	"EQ_ENERGYBANK_COUPLING_TYPE5": [0, 0.5],
	"EQ_ENERGYBANK_COUPLING_TYPE6": [0, 0.6],
	"EQ_ENERGYBANK_COUPLING_TYPE7": [0, 0.7],
	"EQ_ENERGYBANK_COUPLING_TYPE8": [0, 0.8],
	"EQ_THRUSTERS_COUPLING_TYPE1": [0, 0.1],
	"EQ_THRUSTERS_COUPLING_TYPE2": [0, 0.2],
	"EQ_THRUSTERS_COUPLING_TYPE3": [0, 0.3],
	"EQ_THRUSTERS_COUPLING_TYPE4": [0, 0.4],
	"EQ_THRUSTERS_COUPLING_TYPE5": [0, 0.5],
	"EQ_THRUSTERS_COUPLING_TYPE6": [0, 0.6],
	"EQ_THRUSTERS_COUPLING_TYPE7": [0, 0.7],
	"EQ_FORWARD_SHIELD_COUPLING_TYPE1": [0, 0.1],
	"EQ_FORWARD_SHIELD_COUPLING_TYPE2": [0, 0.2],
	"EQ_FORWARD_SHIELD_COUPLING_TYPE3": [0, 0.3],
	"EQ_FORWARD_SHIELD_COUPLING_TYPE4": [0, 0.4],
	"EQ_FORWARD_SHIELD_COUPLING_TYPE5": [0, 0.5],
	"EQ_AFT_SHIELD_COUPLING_TYPE1": [0, 0.1],
	"EQ_AFT_SHIELD_COUPLING_TYPE2": [0, 0.2],
	"EQ_AFT_SHIELD_COUPLING_TYPE3": [0, 0.3],
	"EQ_AFT_SHIELD_COUPLING_TYPE4": [0, 0.4],
	"EQ_AFT_SHIELD_COUPLING_TYPE5": [0, 0.5],

	"EQ_ADDITIONAL_AFT_ARMOUR": [0, 3],
	"EQ_ADDITIONAL_CORE_HULL": [0, 5],
	"EQ_ADDITIONAL_FRONT_ARMOUR": [0, 3],
	"EQ_ADV_NAV_COMP": [1, 1],
	"EQ_AFT_SHIELD_CAPACITOR": [2, 2],
	"EQ_AMS": [0, 3],
	"EQ_ANTISAPPER": [3, 3],
	"EQ_APRIL": [0, 2],
	"EQ_APRIL_EXPANSION": [0, 2],
	"EQ_APRIL_NPC_MISSILE": [0, 2],
	"EQ_AQUATICS_1_GUARDIAN": [3, 3],
	"EQ_AQUATICS_1_JAMMER_MINE": [0, 0.1],
	"EQ_AQUATICS_1_TRIDENT_MISSILE": [0, 0.2],
	"EQ_AQUATICS_CLOAK": [1, 1],
	"EQ_AQUATICS_GUARDIAN": [2, 2],
	"EQ_AQUATICS_JAMMER_MINE": [0, 0.1],
	"EQ_AQUATICS_TRIDENT_MISSILE": [0, 0.2],
	"EQ_ARMOURY_BUGBOMB_MINE": [0, 0.3],
	"EQ_ARMOURY_BUZZBOMB_MINE": [0, 0.2],
	"EQ_ARMOURY_CUTPURSE_MISSILE": [0, 0.2],
	"EQ_ARMOURY_DECOY_MINE": [0, 0.5],
	"EQ_ARMOURY_DISPLACER_MISSILE": [0, 0.3],
	"EQ_ARMOURY_FIELD_MISSILE": [0, 0.3],
	"EQ_ARMOURY_HARD_MISSILE": [0, 0.2],
	"EQ_ARMOURY_INTERDICTOR_MINE": [0, 0.2],
	"EQ_ARMOURY_KICKER_MISSILE": [0, 0.2],
	"EQ_ARMOURY_MISSILEMACHINE_MINE": [0, 2],
	"EQ_ARMOURY_SCREAMER_MINE": [0, 0.3],
	"EQ_ARMOURY_STANDARD_MISSILE": [0, 0.1],
	"EQ_ARMOURY_STUNBOMB_MINE": [0, 0.2],
	"EQ_ARMOURY_TRACKER_MISSILE": [0, 0.5],
	"EQ_ARMOURY_UNIBOMB_MINE": [0, 0.3],
	"EQ_ATDRONE_LAUNCHER_MINE": [0, 0.2],
	"EQ_AUTO_SKIMMER": [1, 1],
	"EQ_AUX_TANK": [3, 3],
	"EQ_BEACONLAUNCHER_MINE": [0, 0.1],
	"EQ_BEACON_DEVICE": [0.5, 0.5],
	"EQ_BEACON_MISSILE": [0, 0.1],
	"EQ_BEERCOOLER": [0.1, 0.1],
	"EQ_BIGSHCAP": [12, 12],
	"EQ_BIGSHCAP2": [14, 14],
	"EQ_BREAKABLE_TORUSDRIVE": [1, 1],
	"EQ_CARGO_SCANNER": [1, 1],
	"EQ_CARGO_SHEPHERD_MINE": [0.5, 0.5],
	"EQ_CDRONE_LAUNCHER_MINE": [0, 0.2],
	"EQ_CRIPPLED_CLOAKING": [1, 1],
	"EQ_CT_CONVERT": [3, 3],
	"EQ_CT_DRONE_1": [2, 2],
	"EQ_CT_DRONE_2": [2, 2],
	"EQ_CT_DRONE_3": [2, 2],
	"EQ_CT_DRONE_4": [2, 2],
	"EQ_CT_MINE": [0, 0.3],
	"EQ_DREDGER_SALVAGE_MISSILE": [0, 0.2],
	"EQ_DUMMY1": [0, 1],
	"EQ_DUMMY10": [0, 10],
	"EQ_DUMMY100": [0, 100],
	"EQ_DUMMY5": [0, 5],
	"EQ_DUMMY50": [0, 50],
	"EQ_ECD_MINE": [0, 0.3],
	"EQ_EEG": [1, 1],
	"EQ_EEU": [3, 3],
	"EQ_ELECTRONICS_BOX": [1, 3],
	"EQ_ENERGY_BOMB": [0, 0.2],
	"EQ_ENERGY_GRID": [3, 3],
	"EQ_EQUIPMENT_BOX": [2, 5],
	"EQ_ERB": [1, 1],
	"EQ_ESG": [3, 3],
	"EQ_FEUDAL_FLARE_MINE": [0, 0.1],
	"EQ_FORWARD_SHIELD_CAPACITOR": [2, 2],
	"EQ_FTL_TORUS": [3, 3],
	"EQ_FTL_TORUS2": [3, 3],
	"EQ_FUELTANK_MINE": [3, 3],
	"EQ_GAL_DRIVE_MINE": [0, 0.1],
	"EQ_GRAVSCANNER": [2, 4],
	"EQ_GRAVSCANNER2": [3, 6],
	"EQ_HARDARMOUR_III": [0, 5],
	"EQ_HARDARMOUR_V": [0, 8],
	"EQ_HARDARMOUR_X": [0, 10],
	"EQ_HARDNOSE": [0, 1],
	"EQ_HARDSHIELD_1": [2, 4],
	"EQ_HARDSHIELD_10": [11, 22],
	"EQ_HARDSHIELD_2": [3, 6],
	"EQ_HARDSHIELD_3": [4, 8],
	"EQ_HARDSHIELD_4": [5, 10],
	"EQ_HARDSHIELD_5": [6, 12],
	"EQ_HARDSHIELD_6": [7, 14],
	"EQ_HARDSHIELD_7": [8, 16],
	"EQ_HARDSHIELD_8": [9, 18],
	"EQ_HARDSHIELD_9": [10, 20],
	"EQ_HRACK_1_MISSILE": [0, 0.2],
	"EQ_HRACK_2_MISSILE": [0, 0.3],
	"EQ_HRACK_3_MISSILE": [0, 0.4],
	"EQ_HTCAT": [2, 2],
	"EQ_Headlights": [0, 0.3],
	"EQ_INJECTOR_BOX": [2, 2],
	"EQ_IRACK_1_MISSILE": [0, 0.2],
	"EQ_IRACK_2_MISSILE": [0, 0.3],
	"EQ_IRACK_3_MISSILE": [0, 0.4],
	"EQ_IRONHIDE": [0, 5], // will need script to adjust for mil version
	"EQ_I_MISSILE": [0, 0.3],
	"EQ_KDRONE_LAUNCHER_MINE": [0, 0.3],
	"EQ_LARGEDISH": [3, 10],
	"EQ_LASERBOOSTER": [1, 1],
	"EQ_LASERREDUCTOR": [1, 1],
	"EQ_LASER_COOLER": [5, 5],
	"EQ_LASER_COUPLER": [0, 2],
	"EQ_LASER_STABILISER": [0, 2],
	"EQ_LBOOST_BEAM_AFT": [0, 2],
	"EQ_LBOOST_BEAM_FWD": [0, 2],
	"EQ_LBOOST_BEAM_PORT": [0, 2],
	"EQ_LBOOST_BEAM_STAR": [0, 2],
	"EQ_LBOOST_MILITARY_AFT": [0, 3],
	"EQ_LBOOST_MILITARY_FWD": [0, 3],
	"EQ_LBOOST_MILITARY_PORT": [0, 3],
	"EQ_LBOOST_MILITARY_STAR": [0, 3],
	"EQ_LBOOST_MINING_AFT": [0, 1.5],
	"EQ_LBOOST_MINING_FWD": [0, 1.5],
	"EQ_LBOOST_MINING_PORT": [0, 1.5],
	"EQ_LBOOST_MINING_STAR": [0, 1.5],
	"EQ_LBOOST_PULSE_AFT": [0, 1],
	"EQ_LBOOST_PULSE_FWD": [0, 1],
	"EQ_LBOOST_PULSE_PORT": [0, 1],
	"EQ_LBOOST_PULSE_STAR": [0, 1],
	"EQ_LIFE_BOX": [3, 3],
	"EQ_LMSS_ACTIVATOR": [0, 1],
	"EQ_LMSS_AFT": [0, 1],
	"EQ_LMSS_FRONT": [0, 1],
	"EQ_LMSS_PORT": [0, 1],
	"EQ_LMSS_STARBOARD": [0, 1],
	"EQ_LONG_RANGE_SCANNER": [2, 2],
	"EQ_MANIF_SCANNER": [1, 1],
	"EQ_MICRO_G_TORUS": [2, 2],
	"EQ_MICRO_G_TORUS2": [2, 2],
	"EQ_MILITARYTARGETTINGSYSTEM": [1, 1],
	"EQ_MIL_INJECTION": [3, 3],
	"EQ_MISJUMP_ANALYSER": [1, 1],
	"EQ_MISSILE_ANALYSER": [1, 1],
	"EQ_MURPH_THARGOID_DRIVE": [1, 1],
	"EQ_NAVAL_GRID": [5, 5],
	"EQ_NEXUS_BASIC_MISSILE": [0, 0.3],
	"EQ_NEXUS_BUG_MISSILE": [0, 0.4],
	"EQ_NEXUS_BUG_R_MISSILE": [0, 0.4],
	"EQ_NEXUS_PREMIUM_MISSILE": [0, 0.4],
	"EQ_NEXUS_ULTIMATE_MISSILE": [0, 0.5],
	"EQ_NRACK_1_MISSILE": [0, 0.2],
	"EQ_NRACK_2_MISSILE": [0, 0.3],
	"EQ_NRACK_3_MISSILE": [0, 0.4],
	"EQ_OCZ_CORONALHARVESTER": [2, 0],
	"EQ_ORE_PROCESSOR": [0, 5],
	"EQ_ORE_PROCESSOR_FULLAUTO": [0, 5],
	"EQ_ORE_SCANNER": [1, 2],
	"EQ_PHASE_SCANNER": [2, 2],
	"EQ_PLANETFALL": [0, 5],
	"EQ_PROBE_LAUNCHER_MINE": [0, 0.2],
	"EQ_Q-CHARGER": [2, 2],
	"EQ_QTHI_AuxEnergyGenerator": [0, 4],
	"EQ_QTHI_AuxEnergyGeneratorHT": [0, 4],
	"EQ_QTHI_AuxEnergyGeneratorHv": [0, 6],
	"EQ_QTHI_AuxEnergyGeneratorLt": [2, 2],
	"EQ_RAILGUN_1": [0, 1],
	"EQ_RAILGUN_2": [0, 1.5],
	"EQ_RAILGUN_3": [0, 2],
	"EQ_RAILGUN_4": [0, 2.5],
	"EQ_REG": [1, 1],
	"EQ_REPAIRBOTS_CONTROLLER": [2, 2],
	"EQ_REPAIRBOTS_MINE": [0, 0.1],
	"EQ_RESCUE_MISSILE": [0, 2],
	"EQ_RESERVE_TANK": [1, 1],
	"EQ_RETROROCKETS": [0, 3],
	"EQ_RMB_CASCADE_MISSILE": [0, 0.3],
	"EQ_RMB_CHAFF_LAUNCHER": [0, 0.3],
	"EQ_RMB_DEFENCE_MINE": [0, 0.4],
	"EQ_RMB_DISTRESS_MINE": [0, 0.2],
	"EQ_RMB_FRAG_MINE": [0, 0.3],
	"EQ_RMB_FRAG_MISSILE": [0, 0.3],
	"EQ_RMB_INTERCEPT_MISSILE": [0, 0.2],
	"EQ_RMB_LAW_MISSILE": [0, 0.3],
	"EQ_RMB_OVERRIDE_MISSILE": [0, 0.3],
	"EQ_RMB_REMOTE_MINE": [0, 0.5],
	"EQ_RMB_THARGOID_MISSILE": [0, 0.4],
	"EQ_ROCKHERMIT_SCANNER": [1, 1],
	"EQ_RRS_ASC": [1, 1],
	"EQ_RRS_DOCK_COMP": [1, 1],
	"EQ_RRS_HEAT_SHIELD": [0, 3],
	"EQ_RRS_SCOOPS": [0, 2],
	"EQ_RRS_SOLAR_MINE": [0, 2],
	"EQ_SAPPERMODE": [0, 1],
	"EQ_SAPPERNULLIFIER": [5, 5],
	"EQ_SC_SHIELD_CYCLER_ADVANCED": [3, 3],
	"EQ_SC_SHIELD_CYCLER_BASIC": [1, 1],
	"EQ_SC_SHIELD_CYCLER_STANDARD": [2, 2],
	"EQ_SHIELD_BOX": [5, 5],
	"EQ_SHIELD_EQUALIZER": [2, 2],
	"EQ_SHIPMINER": [1, 1],
	"EQ_SHIPMINERASSISTANT": [0.5, 0.5],
	"EQ_SMALLDISH": [1, 5],
	"EQ_SMUGGLING_COMPARTMENT_1": [0, 1],
	"EQ_SMUGGLING_COMPARTMENT_10": [0, 5],
	"EQ_SMUGGLING_COMPARTMENT_11": [0, 6],
	"EQ_SMUGGLING_COMPARTMENT_12": [0, 6],
	"EQ_SMUGGLING_COMPARTMENT_13": [0, 7],
	"EQ_SMUGGLING_COMPARTMENT_14": [0, 7],
	"EQ_SMUGGLING_COMPARTMENT_15": [0, 8],
	"EQ_SMUGGLING_COMPARTMENT_16": [0, 8],
	"EQ_SMUGGLING_COMPARTMENT_17": [0, 9],
	"EQ_SMUGGLING_COMPARTMENT_18": [0, 9],
	"EQ_SMUGGLING_COMPARTMENT_19": [0, 10],
	"EQ_SMUGGLING_COMPARTMENT_2": [0, 1],
	"EQ_SMUGGLING_COMPARTMENT_20": [0, 10],
	"EQ_SMUGGLING_COMPARTMENT_3": [0, 2],
	"EQ_SMUGGLING_COMPARTMENT_4": [0, 2],
	"EQ_SMUGGLING_COMPARTMENT_5": [0, 3],
	"EQ_SMUGGLING_COMPARTMENT_6": [0, 3],
	"EQ_SMUGGLING_COMPARTMENT_7": [0, 4],
	"EQ_SMUGGLING_COMPARTMENT_8": [0, 4],
	"EQ_SMUGGLING_COMPARTMENT_9": [0, 5],
	"EQ_SRACK_1_MISSILE": [0, 0.2],
	"EQ_SRACK_2_MISSILE": [0, 0.3],
	"EQ_SRACK_3_MISSILE": [0, 0.4],
	"EQ_SUWITCHDRIVE": [2, 2],
	"EQ_SUWITCHDRIVESPARECOILS": [1, 1],
	"EQ_TELESCOPE": [1, 1],
	"EQ_TOWBAR": [1, 1],
	"EQ_TOWBARINJ": [0.5, 0.5],
	"EQ_TOWBARREPAIRBOT": [0.5, 0.5],
	"EQ_TOWBARSTAB_MINE": [0, 0.1],
	"EQ_TRACKERCAM_MINE": [0, 0.2],
	"EQ_TUGDRONE_MISSILE": [0, 0.3],
	"EQ_UPS_POLICE_SCANNER": [0.3, 0.3],
	"EQ_UPS_UNIVERSAL_SCANNER": [0.5, 0.5],
	"EQ_VACUUM_PUMP": [0, 1],
	"EQ_VERYHARDNOSE": [0, 3],
	"EQ_VERYVERYHARDNOSE": [0, 5],
	"EQ_WARHEAD_MINE": [0, 0.2],
	"EQ_WEAPON_ANDERSON_LASER": [0, 3],
	"EQ_WEAPON_ASSAULT_LASER": [0, 2],
	"EQ_WEAPON_BEAM_LASER_2": [0, 4],
	"EQ_WEAPON_BEAM_LASER_3": [0, 6],
	"EQ_WEAPON_BEAM_LASER_4": [0, 8],
	"EQ_WEAPON_BEAM_LASER_5": [0, 10],
	"EQ_WEAPON_BLAST_LASER": [0, 1.5],
	"EQ_WEAPON_BURST_LASER": [0, 2],
	"EQ_WEAPON_CANNON_1": [0, 0.5],
	"EQ_WEAPON_CANNON_10": [0, 3],
	"EQ_WEAPON_CANNON_10_2": [0, 6],
	"EQ_WEAPON_CANNON_10_3": [0, 9],
	"EQ_WEAPON_CANNON_10_4": [0, 12],
	"EQ_WEAPON_CANNON_10_5": [0, 15],
	"EQ_WEAPON_CANNON_11": [1, 8],
	"EQ_WEAPON_CANNON_11_2": [2, 16],
	"EQ_WEAPON_CANNON_11_3": [3, 24],
	"EQ_WEAPON_CANNON_11_4": [4, 32],
	"EQ_WEAPON_CANNON_11_5": [5, 40],
	"EQ_WEAPON_CANNON_12": [2, 10],
	"EQ_WEAPON_CANNON_13": [2, 12],
	"EQ_WEAPON_CANNON_14": [3, 15],
	"EQ_WEAPON_CANNON_15": [3, 20],
	"EQ_WEAPON_CANNON_16": [3, 15],
	"EQ_WEAPON_CANNON_17": [5, 30],
	"EQ_WEAPON_CANNON_18": [8, 40],
	"EQ_WEAPON_CANNON_2": [0, 2],
	"EQ_WEAPON_CANNON_2_2": [0, 4],
	"EQ_WEAPON_CANNON_2_3": [0, 6],
	"EQ_WEAPON_CANNON_2_4": [0, 8],
	"EQ_WEAPON_CANNON_2_5": [0, 10],
	"EQ_WEAPON_CANNON_3": [0, 3],
	"EQ_WEAPON_CANNON_4": [0, 4],
	"EQ_WEAPON_CANNON_4_2": [0, 8],
	"EQ_WEAPON_CANNON_4_3": [0, 12],
	"EQ_WEAPON_CANNON_4_4": [0, 16],
	"EQ_WEAPON_CANNON_4_5": [0, 20],
	"EQ_WEAPON_CANNON_5": [0, 6],
	"EQ_WEAPON_CANNON_6": [0, 3],
	"EQ_WEAPON_CANNON_7": [0, 3],
	"EQ_WEAPON_CANNON_7_2": [0, 6],
	"EQ_WEAPON_CANNON_7_3": [0, 9],
	"EQ_WEAPON_CANNON_7_4": [0, 12],
	"EQ_WEAPON_CANNON_7_5": [0, 15],
	"EQ_WEAPON_CANNON_8": [0, 5],
	"EQ_WEAPON_CANNON_9": [1, 6],
	"EQ_WEAPON_CANNON_EA": [0, 5],
	"EQ_WEAPON_CANNON_EA_2": [0, 10],
	"EQ_WEAPON_CANNON_EA_3": [0, 15],
	"EQ_WEAPON_CANNON_EA_4": [0, 20],
	"EQ_WEAPON_CANNON_EA_5": [0, 25],
	"EQ_WEAPON_CANNON_ECO": [0, 1],
	"EQ_WEAPON_CANNON_ECO_2": [0, 2],
	"EQ_WEAPON_CANNON_ECO_3": [0, 3],
	"EQ_WEAPON_CANNON_ECO_4": [0, 4],
	"EQ_WEAPON_CANNON_ECO_5": [0, 5],
	"EQ_WEAPON_CANNON_HEAVY_SAPPER": [0, 5],
	"EQ_WEAPON_CANNON_HEAVY_SNIPER_GUN": [0, 5],
	"EQ_WEAPON_CANNON_HEAVY_SNIPER_GUN_2": [0, 10],
	"EQ_WEAPON_CANNON_HEAVY_SNIPER_GUN_3": [0, 15],
	"EQ_WEAPON_CANNON_HEAVY_SNIPER_GUN_4": [0, 20],
	"EQ_WEAPON_CANNON_HEAVY_SNIPER_GUN_5": [0, 25],
	"EQ_WEAPON_CANNON_SAPPER": [0, 3],
	"EQ_WEAPON_CANNON_SNIPER_GUN": [0, 3],
	"EQ_WEAPON_CANNON_SNIPER_GUN_2": [0, 6],
	"EQ_WEAPON_CANNON_SNIPER_GUN_3": [0, 9],
	"EQ_WEAPON_CANNON_SNIPER_GUN_4": [0, 12],
	"EQ_WEAPON_CANNON_SNIPER_GUN_5": [0, 15],
	"EQ_WEAPON_DEXM_LASER": [0, 3],
	"EQ_WEAPON_DUAL_LASER": [0, 2],
	"EQ_WEAPON_EBEAM_LASER": [0, 2],
	"EQ_WEAPON_ECO_LASER": [0, 1],
	"EQ_WEAPON_ECO_LASER_2": [0, 2],
	"EQ_WEAPON_ECO_LASER_3": [0, 3],
	"EQ_WEAPON_ECO_LASER_4": [0, 4],
	"EQ_WEAPON_ECO_LASER_5": [0, 5],
	"EQ_WEAPON_ECO_REACTOR": [0, 2],
	"EQ_WEAPON_ECO_REACTOR_2": [0, 4],
	"EQ_WEAPON_ECO_REACTOR_3": [0, 6],
	"EQ_WEAPON_ECO_REACTOR_4": [0, 8],
	"EQ_WEAPON_ECO_REACTOR_5": [0, 10],
	"EQ_WEAPON_EMILITARY_LASER": [0, 3],
	"EQ_WEAPON_EPULSE_LASER": [0, 1],
	"EQ_WEAPON_FRONTIER_LASER": [0, 2],
	"EQ_WEAPON_GATLING_LASER_1": [0, 1],
	"EQ_WEAPON_GATLING_LASER_2": [0, 1.5],
	"EQ_WEAPON_GATLING_LASER_3": [0, 2],
	"EQ_WEAPON_GATLING_LASER_4": [0, 2.5],
	"EQ_WEAPON_GATLING_LASER_5": [0, 3],
	"EQ_WEAPON_HIRAD_LASER": [0, 2],
	"EQ_WEAPON_HVARISCAN_LASER": [0, 1.5],
	"EQ_WEAPON_JKMINING_LASER": [0, 1.5],
	"EQ_WEAPON_LUCAS_LASER": [0, 2.5],
	"EQ_WEAPON_MILITARY_LASER_2": [0, 6],
	"EQ_WEAPON_MILITARY_LASER_3": [0, 9],
	"EQ_WEAPON_MILITARY_LASER_4": [0, 12],
	"EQ_WEAPON_MILITARY_LASER_5": [0, 15],
	"EQ_WEAPON_PULSE_LASER_2": [0, 2],
	"EQ_WEAPON_PULSE_LASER_3": [0, 3],
	"EQ_WEAPON_PULSE_LASER_4": [0, 4],
	"EQ_WEAPON_PULSE_LASER_5": [0, 5],
	"EQ_WEAPON_QVC_LASER": [0, 3],
	"EQ_WEAPON_RIMMERACE_LASER": [0, 3],
	"EQ_WEAPON_STAR_LASER": [0, 2],
	"EQ_WEAPON_VARISCAN_LASER": [0, 1.5],
	"EQ_WEAPON_WILLIAMS_LASER": [0, 2],
	"EQ_WEAPON_ZEUSCORP_LASER": [0, 2.5],
	"EQ_XS_SWORD_MISSILE": [0, 0.1],
	"EQ_X_SWORD_A_MISSILE": [0, 0.1],
	"EQ_X_SWORD_MISSILE": [0, 0.1],
	"EQ_AM18_HYPERDRIVE": [0.5, 0.5],
	"EQ_HZ_HYPERDRIVE": [0.8, 0.8],
	"EQ_TURBULEN_HYPEDRIVE": [1, 1],
	"EQ_PROSSET_HYPERDRIVE": [2, 2],
	"EQ_AMES_HYPERDRIVE": [2.5, 2.5],
	"EQ_TITRONIX_HYPERDRIVE": [3, 3],
	"EQ_IRRIKAN_HYPERDRIVE": [4, 4],
	"EQ_CARGO_TARGETER": [0.5, 0.5],
	"EQ_VECTOR_SPACELANE": [0.2, 0.2],
	"EQ_VECTOR_FUNA_MISSILE": [0, 0.2],
	"EQ_VECTOR_FUNB_MISSILE": [0, 0.3],
	"EQ_VECTOR_FUNC_MISSILE": [0, 0.4],
	"EQ_VECTOR_AREIDIS_SCANNER": [1.5, 1.5],
	"EQ_VECTOR_EMP_MINE": [0, 1.5],
	"EQ_VECTOR_SCOOPS": [0, 1],
	"EQ_TARGET_AUTOLOCK": [0, 0],
};

//-------------------------------------------------------------------------------------------------------------
this.$addCallback = function $addCallback(obj) {
	this._callbacks.push(obj);
}

//=============================================================================================================
// system functions

//-------------------------------------------------------------------------------------------------------------
this.startUp = function () {
	if (this._disabled === true) {
		delete this.equipmentAdded;
		delete this.equipmentRemoved;
		delete this.playerBoughtEquipment;
		delete this.missionScreenOpportunity;
		delete this.missionScreenEnded;
		delete this.equipmentDamaged;
		delete this.equipmentRepaired;
		delete this.playerBoughtNewShip;
		delete this.guiScreenChanged;
		delete this.guiScreenWillChange;
		delete this.shipDockedWithStation;
		delete this.shipWillLaunchFromStation;
		delete this.shipLaunchedFromStation;
		delete this.playerStartedJumpCountdown;
		delete this.playerStartedAutoPilot;
		delete this.shipDied;
		delete this.shipTakingDamage;
		delete this.shipSpawned;
		delete this.shipFiredMissile;
		delete this.shipScoopedOther;
		delete this.playerRescuedEscapePod;
		delete this.startUpComplete;
		delete this.startUp;
		return;
	}

	this._armour = [].concat(this._frontarmour).concat(this._aftarmour);

	var p = player.ship;
	var oldarmour = ["EQ_ARMOUR_TYPE1", "EQ_ARMOUR_TYPE2", "EQ_ARMOUR_TYPE3", "EQ_ARMOUR_TYPE4", "EQ_ARMOUR_TYPE5", "EQ_ARMOUR_TYPE6", "EQ_ARMOUR_TYPE7"];
	for (var i = 0; i < oldarmour.length; i++) {
		if (player.ship.equipmentStatus(oldarmour[i]) === "EQUIPMENT_OK") {
			p.awardEquipment("EQ_ARMOUR_FORWARD_TYPE" + (i + 1));
			p.awardEquipment("EQ_ARMOUR_AFT_TYPE" + (i + 1));
			p.removeEquipment(oldarmour[i]);
		}
	}

	// look for any equipment items that have a weight/space value set in script info
	this.$addEquipmentDataFromScriptInfo();
	// look for any ships that have an equipment space or power to weight ratio set in script info
	this.$addShipDataFromScriptInfo();
	// add essential equipment to the "no sell" list - do it programmatically, rather than hardcoding equipment keys,
	// so if we ever expand the list they'll get added automatically
	this.$populateNoSellList();

	if (worldScripts.ShipRespray) this._shipRespray = true;
	if (worldScripts.Synchronised_Torus) this._torusSync = true;

	// if the station dock control is installed, add a callback to tell it to check for launched ships
	if (worldScripts.StationDockControl && worldScripts.StationDockControl._disable == false) {
		this.$addCallback(worldScripts.StationDockControl.$checkForLaunchedShips.bind(worldScripts.StationDockControl));
	}
}

//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
	// register our settings, if Lib_Config is present
	if (worldScripts.Lib_Config) worldScripts.Lib_Config._registerSet(this._scConfig);

	if (worldScripts.EmailSystem) {
		var ga = worldScripts.GalCopAdminServices;
		for (var i = 1; i <= 7; i++) {
			ga._maint_repair_equip.push("EQ_ARMOUR_FORWARD_TYPE" + i + "_REPAIR");
			ga._maint_repair_equip.push("EQ_ARMOUR_AFT_TYPE" + i + "_REPAIR");
		}
	}

	var hy = worldScripts.Hyperdrives;
	if (hy) this._OXPHyperdrives = true;

	// remove the main config equip item from any new purchase emails
	var w = worldScripts.GalCopAdminServices;
	if (w) w._purchase_ignore_equip.push("EQ_SHIPCONFIG");

	if (worldScripts.NPC_Equipment_Damage) {
		var npcEq = worldScripts.NPC_Equipment_Damage
		// add in our equipmentdamaged processing event to the NPC damaged handler array
		npcEq.NPC_equipmentDamagedHandlers.push(this.$equipmentDamaged_Event);
	}

	var p = player.ship;
	// add base equipment items if this is the first time
	this._initialSetup = this.$installBaseEquipment(p);
	// check that there is space for all equipment
	// if not, we need to remove something, so load up the sell equipment screen
	this._promptPlayer = !this.$addEquipmentSpaceItem(p);

	// set up the interface screen, if required
	this.$initInterface(p.dockedStation);
	this._startUp = false;

	this.$setUpScriptConfig();

	if (this._OXPHyperdrives === true) {
		// make sure we remove any SC hyperdrives if the player has installed the Hyperdrives OXP
		for (var i = 0; i < this._hyperdrive.length; i++) {
			p.removeEquipment(this._hyperdrive[i]);
		}
		for (var i = 0; i < this._hdCoupling.length; i++) {
			p.removeEquipment(this._hdCoupling[i]);
		}
	}

	// tap into shipresprays pre/post function calls
	if (this._shipRespray) {
		var sr = worldScripts.ShipRespray;
		if (sr.$addPreSprayCall) {
			sr.$addPreSprayCall(this.name, "$preResprayFunction");
			sr.$addPostSprayCall(this.name, "$postResprayFunction");
		}
	}

	// monkey patch combat sim so we can do some pre-launch work done
	if (worldScripts["Combat Simulator"]) {
		worldScripts["Combat Simulator"]._startFight = this.$combatSim_startFight;
	}

	// check to see if hyperspace hangar is installed
	if (worldScripts.HyperspaceHangar) this._hyperHangar = true;

	// load up or repopulate the current equipment list (so we know what's brand new and what's used)
	if (missionVariables.ShipConfiguration_CurrentEquip) {
		this._currEquip = JSON.parse(missionVariables.ShipConfiguration_CurrentEquip);
		delete missionVariables.ShipConfiguration_CurrentEquip;
	} else {
		this._currEquip = [];
		var eq = player.ship.equipment;
		for (var i = 0; i < eq.length; i++) {
			this._currEquip.push(eq[i].equipmentKey);
		}
	}
	if (missionVariables.ShipConfiguration_BoosterSound) this._disableBoosterSound = (this._trueValues.indexOf(missionVariables.ShipConfiguration_BoosterSound) >= 0 ? true : false);
	if (missionVariables.ShipConfiguration_DisableF3HUD) this._disableF3HUD = (this._trueValues.indexOf(missionVariables.ShipConfiguration_DisableF3HUD) >= 0 ? true : false);
	if (missionVariables.ShipConfiguration_ApplyToNPC) this._applyToNPC = (this._trueValues.indexOf(missionVariables.ShipConfiguration_ApplyToNPC) >= 0 ? true : false);
	if (missionVariables.ShipConfiguration_FreeUpgrades) this._freeUpgrades = (this._trueValues.indexOf(missionVariables.ShipConfiguration_FreeUpgrades) >= 0 ? true : false);
	if (missionVariables.ShipConfiguration_InstallationTime) this._installationTime = (this._trueValues.indexOf(missionVariables.ShipConfiguration_InstallationTime) >= 0 ? true : false);
	if (missionVariables.ShipConfiguration_SuppressEquipSpecs) this._suppressEquipSpecs = (this._trueValues.indexOf(missionVariables.ShipConfiguration_SuppressEquipSpecs) >= 0 ? true : false);

	// upgraded features in v1.84
	if (0 < oolite.compareVersion("1.84")) {
		delete this.shipDumpedCargo;
	} else {
		delete this.shipSpawned;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
	missionVariables.ShipConfiguration_CurrentEquip = JSON.stringify(this._currEquip);
	missionVariables.ShipConfiguration_BoosterSound = this._disableBoosterSound;
	missionVariables.ShipConfiguration_DisableF3HUD = this._disableF3HUD;
	missionVariables.ShipConfiguration_ApplyToNPC = this._applyToNPC;
	missionVariables.ShipConfiguration_FreeUpgrades = this._freeUpgrades;
	missionVariables.ShipConfiguration_InstallationTime = this._installationTime;
	missionVariables.ShipConfiguration_SuppressEquipSpecs = this._suppressEquipSpecs;
}

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

	// re-load the current equipment list so we know what's used
	this._currEquip.length = 0;
	var eq = player.ship.equipment;
	for (var i = 0; i < eq.length; i++) {
		this._currEquip.push(eq[i].equipmentKey);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.shipDied = function (whom, why) {
	this.$stopTimers();
}

//-------------------------------------------------------------------------------------------------------------
this.missionScreenOpportunity = function () {
	// looks like we need to ask the player to remove some equipment
	if (this._promptPlayer === true) {
		this._promptPlayer = false;
		this._page = 0;
		this.$sellEquipment();
	}
}

//-------------------------------------------------------------------------------------------------------------
this.equipmentDamaged = function (equipmentKey) {
	// we're attaching the equipmentDamaged_Event to the script object of the player, so NPC Equipment failure can be implemented more simply.
	if (player.ship && player.ship.script) {
		// check to see if we've been set up yet
		if (!player.ship.script.$equipmentDamaged_Event) this.$setUpScriptConfig();
		if (player.ship.script.$equipmentDamaged_Event) player.ship.script.$equipmentDamaged_Event(equipmentKey);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.equipmentRepaired = function (equipmentKey) {

	if (this._repairing === true) return;
	if (this._damaging === true) return;

	this._repairing = true;

	// look for cases where equipment was repaired in flight
	var p = player.ship;

	if (equipmentKey === "EQ_HEAT_SINK") {
		if (p.equipmentStatus("EQ_HEAT_SINK_CONTROL") != "EQUIPMENT_OK") {
			if (worldScripts.ShipConfiguration_HeatSink.controlMode === 0) {
				p.awardEquipment("EQ_HEAT_SINK_CONTROL");
			} else {
				p.awardEquipment("EQ_HEAT_SINK_CONTROL_PASSIVE");
			}
		}
		this._repairing = false;
		return;
	}

	/*if (p.docked === false) {
		// can't repair shield boosters until shields are fixed
		if ((equipmentKey === "EQ_NAVAL_SHIELD_BOOSTER" || equipmentKey === "EQ_SHIELD_BOOSTER" || equipmentKey === "EQ_NAVAL_GRID" || equipmentKey === "EQ_ENERGY_GRID")
			&& (p.equipmentStatus(this.$equipmentItemInUse("frontshields", p)) != "EQUIPMENT_OK" || p.equipmentStatus(this.$equipmentItemInUse("aftshields", p)) != "EQUIPMENT_OK")) {
			this._damaging = true;
			p.setEquipmentStatus(equipmentKey, "EQUIPMENT_DAMAGED");
			this._damaging = false;
			equipmentKey = "";
		}
		// can't repair extra energy units until main unit is bank online
		if ((equipmentKey === "EQ_ENERGY_UNIT" || equipmentKey === "EQ_NAVAL_ENERGY_UNIT" || equipmentKey === "EQ_NAVAL_GRID" || equipmentKey === "EQ_ENERGY_GRID")
			&& p.equipmentStatus(this.$equipmentItemInUse("energy", p)) != "EQUIPMENT_OK") {
			this._damaging = true;
			p.setEquipmentStatus(equipmentKey, "EQUIPMENT_DAMAGED");
			this._damaging = false;
			equipmentKey = "";
		}
	} */
	if (this._engines.indexOf(equipmentKey) >= 0) {
		p.maxSpeed = this.$calculatedValue("speed", p);
		p.maxThrust = this.$calculatedValue("thrust", p);
		p.thrust = p.maxThrust;
	}
	if (this._thrusters.indexOf(equipmentKey) >= 0) {
		p.maxPitch = this.$calculatedValue("pitch", p);
		p.maxRoll = this.$calculatedValue("roll", p);
		p.maxYaw = this.$calculatedValue("yaw", p);
	}
	if (this._boosters.indexOf(equipmentKey) >= 0) {
		var boostEq = EquipmentInfo.infoForKey(equipmentKey);
		p.script._boosterHeatPoint = boostEq.scriptInfo.heat_buildup;
		p.maxSpeed = this.$calculatedValue("speed", p);
		p.maxThrust = this.$calculatedValue("thrust", p);
		p.thrust = p.maxThrust;
		p.maxPitch = this.$calculatedValue("pitch", p);
		p.maxRoll = this.$calculatedValue("roll", p);
		p.maxYaw = this.$calculatedValue("yaw", p);
	}
	if (this._energy.indexOf(equipmentKey) >= 0) {
		p.energyRechargeRate = p.script._energyRechargeRate_Stored;
		p.script._energyRechargeRate_Stored = 0;
	}
	if (this._frontshields.indexOf(equipmentKey) >= 0) {
		p.forwardShieldRechargeRate = p.script._forwardShieldRechargeRate_Stored;
		p.script._forwardShieldRechargeRate_Stored = 0;
		this.$enableShieldOXPs();
	}
	if (this._aftshields.indexOf(equipmentKey) >= 0) {
		p.aftShieldRechargeRate = p.script._aftshieldsRechargeRate_Stored;
		p.script._aftshieldsRechargeRate_Stored = 0;
		this.$enableShieldOXPs();
	}
	if (this._heatshields.indexOf(equipmentKey) >= 0) {
		p.awardEquipment("EQ_HEAT_SHIELD");
		var info = EquipmentInfo.infoForKey(equipmentKey);
		var shipspec = Ship.shipDataForKey(p.dataKey);
		var shipdef = 1;
		if (typeof shipspec["heat_insulation"] != "undefined") shipdef = parseFloat(shipspec["heat_insulation"]);
		p.heatInsulation = shipdef + parseFloat(info.scriptInfo.oolite_heat_insulation_strength);
	}
	if (equipmentKey === "EQ_HEAT_SHIELD") {
		p.setEquipmentStatus(this.$equipmentItemInUse("heatshields", p), "EQUIPMENT_OK");
		var info = EquipmentInfo.infoForKey(equipmentKey);
		p.heatInsulation += info.scriptInfo.oolite_heat_insulation_strength;
	}
	if (this._fuelinjectors.indexOf(equipmentKey) >= 0) {
		// can't repair injectors until main engines are repaired
		if (p.equipmentStatus(this.$equipmentItemInUse("engines", p)) != "EQUIPMENT_OK") {
			this._damaging = true;
			p.setEquipmentStatus(equipmentKey, "EQUIPMENT_DAMAGED");
			this._damaging = false;
			this._repairing = false;
			return;
		}
		p.setEquipmentStatus("EQ_FUEL_INJECTION", "EQUIPMENT_OK");
	}
	// special case for when an OXP repairs the fuel injectors directly
	if (equipmentKey === "EQ_FUEL_INJECTION") {
		p.setEquipmentStatus(this.$equipmentItemInUse("fuelinjectors", p), "EQUIPMENT_OK");
	}
	if (this._fuelscoops.indexOf(equipmentKey) >= 0) {
		p.setEquipmentStatus("EQ_FUEL_SCOOPS", "EQUIPMENT_OK");
	}
	// special case for when an OXP repairs the fuel scoops directly
	if (equipmentKey === "EQ_FUEL_SCOOPS") {
		p.setEquipmentStatus(this.$equipmentItemInUse("fuelscoops", p), "EQUIPMENT_OK");
	}

	this._repairing = false;
}

//-------------------------------------------------------------------------------------------------------------
this.playerBoughtNewShip = function (ship, price) {
	//log(this.name, "playerBoughtNewShip - " + ship);
	if (this._resprayActive === true) return;
	if (this._simulator === true) return;
	this.$setUpScriptConfig();
	this._current = {};
	this._startUp = true;
	var result = this.$installBaseEquipment(ship);
	this._startUp = false;
	this.equipmentAdded("");
}

//-------------------------------------------------------------------------------------------------------------
this.playerBoughtEquipment = function (equipmentKey) {
	if (equipmentKey === "EQ_HEAT_SINK") {
		if (player.ship.equipmentStatus("EQ_HEAT_SINK_CONTROL") != "EQUIPMENT_OK") {
			worldScripts.ShipConfiguration_HeatSink.controlMode = 0;
			player.ship.awardEquipment("EQ_HEAT_SINK_CONTROL");
		}
	}

	this._sellEquipExitScreen === "GUI_SCREEN_EQUIP_SHIP";

	if (equipmentKey === "EQ_SHIPCONFIG") {
		player.ship.removeEquipment(equipmentKey);
		this._lastChoice = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""];
		this._source = "";
		this._display = 0;
		this._page = 0;
		this.$shipConfig();
		return;
	}
	// armour repair handled in it's own script
	if (equipmentKey.indexOf("_REPAIR") >= 0) return;

	if (this._promptPlayer === true) {
		this.missionScreenOpportunity();
	}
}

//-------------------------------------------------------------------------------------------------------------
this.equipmentAdded = function (equipmentKey) {
	if (this._debug) log(this.name, "equipAdded " + equipmentKey + ", startup = " + this._startUp + ", removing = " + this._removing + ", adding = " + this._adding);

	//if (this._simulator === true) return;

	// make sure we don't end up in a perpetual loop
	if (this._startUp === true) return;
	if (this._removing === true) return;
	if (this._adding === true) return;

	// ignore any of the filler items
	if (this._filler.indexOf(equipmentKey) >= 0) return;

	// ignore any removal equipment items
	if (equipmentKey.indexOf("REMOVE") > 0 || equipmentKey.indexOf("REMOVAL") > 0 || equipmentKey.indexOf("REFUND") > 0 ||
		equipmentKey.indexOf("_DAMAGED") > 0 || equipmentKey.indexOf("_REPAIR") > 0) return;
	if (this._ignoreEquip.indexOf(equipmentKey) >= 0) return;

	this._adding = true;

	var p = player.ship;

	// special cases for the equipment items we're overriding. If another OXP ever adds these items, we need to also add our specialised item
	if (equipmentKey === "EQ_FUEL_INJECTION" && p.alertCondition === 0) {
		p.awardEquipment("EQ_FUEL_INJECTION_TYPE2");
		this._adding = false;
		return;
	}
	if (equipmentKey === "EQ_HEAT_SHIELD" && p.alertCondition === 0) {
		p.awardEquipment("EQ_HEAT_SHIELD_TYPE2");
		this._adding = false;
		return;
	}
	if (equipmentKey === "EQ_FUEL_SCOOPS" && p.alertCondition === 0) {
		p.awardEquipment("EQ_FUEL_SCOOPS_TYPE1");
		this._adding = false;
		return;
	}

	// ignore anything that's not visible
	if (equipmentKey != "" && equipmentKey != "EQ_NO_FORWARD_SHIELD" && equipmentKey != "EQ_NO_AFT_SHIELD") {
		var eqinfo = EquipmentInfo.infoForKey(equipmentKey);
		if (eqinfo && eqinfo.isVisible === false) { this._adding = false; return; }
		if (!eqinfo && this._debug) log(this.name, "!!ERROR: No equipmentInfo for equipment key " + equipmentKey);
	}
	var stn = p.dockedStation;
	var equipSpace = this.$equipmentSpaceTotal(p);
	var cargoSpace = this.$cargoSpaceAvailable(p);

	// if we're installing one of the replacement items, make a note of it so we can remove it
	var original = "";
	var state = "";
	var originalSpace = 0;
	var applyPF = true;

	if (this._electricalbus.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._electricalbus.length; i++) {
			if (this._electricalbus[i] != equipmentKey) {
				check = p.equipmentStatus(this._electricalbus[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._electricalbus[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}

	if (this._hyperdrive.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._hyperdrive.length; i++) {
			if (this._hyperdrive[i] != equipmentKey) {
				check = p.equipmentStatus(this._hyperdrive[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._hyperdrive[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._hdCoupling.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._hdCoupling.length; i++) {
			if (this._hdCoupling[i] != equipmentKey) {
				check = p.equipmentStatus(this._hdCoupling[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._hdCoupling[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._engines.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._engines.length; i++) {
			if (this._engines[i] != equipmentKey) {
				check = p.equipmentStatus(this._engines[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._engines[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._enCoupling.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._enCoupling.length; i++) {
			if (this._enCoupling[i] != equipmentKey) {
				check = p.equipmentStatus(this._enCoupling[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._enCoupling[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._thrusters.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._thrusters.length; i++) {
			if (this._thrusters[i] != equipmentKey) {
				check = p.equipmentStatus(this._thrusters[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._thrusters[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._thCoupling.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._thCoupling.length; i++) {
			if (this._thCoupling[i] != equipmentKey) {
				check = p.equipmentStatus(this._thCoupling[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._thCoupling[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._boosters.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._boosters.length; i++) {
			if (this._boosters[i] != equipmentKey) {
				check = p.equipmentStatus(this._boosters[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._boosters[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._bsCoupling.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._bsCoupling.length; i++) {
			if (this._bsCoupling[i] != equipmentKey) {
				check = p.equipmentStatus(this._bsCoupling[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._bsCoupling[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._energy.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._energy.length; i++) {
			if (this._energy[i] != equipmentKey) {
				check = p.equipmentStatus(this._energy[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._energy[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._ebCoupling.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._ebCoupling.length; i++) {
			if (this._ebCoupling[i] != equipmentKey) {
				check = p.equipmentStatus(this._ebCoupling[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._ebCoupling[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._frontshields.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._frontshields.length; i++) {
			if (this._frontshields[i] != equipmentKey) {
				check = p.equipmentStatus(this._frontshields[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._frontshields[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._fsCoupling.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._fsCoupling.length; i++) {
			if (this._fsCoupling[i] != equipmentKey) {
				check = p.equipmentStatus(this._fsCoupling[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._fsCoupling[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._aftshields.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._aftshields.length; i++) {
			if (this._aftshields[i] != equipmentKey) {
				check = p.equipmentStatus(this._aftshields[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._aftshields[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._asCoupling.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._asCoupling.length; i++) {
			if (this._asCoupling[i] != equipmentKey) {
				check = p.equipmentStatus(this._asCoupling[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._asCoupling[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._heatshields.indexOf(equipmentKey) >= 0) {
		applyPF = false;
		p.awardEquipment("EQ_HEAT_SHIELD");
		var check = "";
		for (var i = 0; i < this._heatshields.length; i++) {
			if (this._heatshields[i] != equipmentKey) {
				check = p.equipmentStatus(this._heatshields[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._heatshields[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._fuelinjectors.indexOf(equipmentKey) >= 0) {
		applyPF = false;
		p.awardEquipment("EQ_FUEL_INJECTION");
		var check = "";
		for (var i = 0; i < this._fuelinjectors.length; i++) {
			if (this._fuelinjectors[i] != equipmentKey) {
				check = p.equipmentStatus(this._fuelinjectors[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._fuelinjectors[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._fuelscoops.indexOf(equipmentKey) >= 0) {
		applyPF = false;
		p.awardEquipment("EQ_FUEL_SCOOPS");
		var check = "";
		for (var i = 0; i < this._fuelscoops.length; i++) {
			if (this._fuelscoops[i] != equipmentKey) {
				check = p.equipmentStatus(this._fuelscoops[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._fuelscoops[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._frontarmour.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._frontarmour.length; i++) {
			if (this._frontarmour[i] != equipmentKey) {
				check = p.equipmentStatus(this._frontarmour[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._frontarmour[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}
	if (this._aftarmour.indexOf(equipmentKey) >= 0) {
		var check = "";
		for (var i = 0; i < this._aftarmour.length; i++) {
			if (this._aftarmour[i] != equipmentKey) {
				check = p.equipmentStatus(this._aftarmour[i]);
				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
					original = this._aftarmour[i];
					originalSpace = this._equipmentMatrix[original][0];
					state = check;
				}
			}
		}
	}

	// remove and refund old equipment
	if (original != "") {
		// is this new or used? idx === -1 means new, otherwise any number >= 0 means used
		var idx = this._currEquip.indexOf(original);
		if (idx >= 0) this._currEquip.splice(idx, 1);

		if (this._freeUpgrades === false) {
			var oldinfo = EquipmentInfo.infoForKey(original);
			var priceFactor = this.$equipmentPriceFactor(p.shipClassName, this.$getShipMass(p));
			if (applyPF === false) priceFactor = 1;
			if (state === "EQUIPMENT_OK") {
				player.credits += ((oldinfo.price / 10) * priceFactor) * (idx >= 0 ? this._refundPct : 1) * (stn.equivalentTechLevel >= oldinfo.techLevel ? stn.equipmentPriceFactor : 1);
			} else {
				// only refund half if it's damaged
				player.credits += ((oldinfo.price / 10) * priceFactor) * 0.5 * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1);
			}
		}
		if (this._debug) log(this.name, "Removing " + original);
		p.removeEquipment(original);
	}

	this.$checkForOverload();

	/*var used = this.$calcEquipmentSpace(p);
	if (used > equipSpace) {
		// allocate cargo space to equipment space
		var diff = parseInt(used - equipSpace);
		if (diff > cargoSpace) {
			// we don't have space for this
			// switch into "overloaded" mode so the player can choose what item to remove
			this._initialSetup = true;
			this._promptPlayer = true;
		}
	}*/

	this.$addEquipmentSpaceItem(p);
	this._adding = false;
}

//-------------------------------------------------------------------------------------------------------------
this.equipmentRemoved = function (equipmentKey) {

	//if (this._simulator === true) return;

	// make sure we don't end up in a perpetual loop
	if (this._adding === true) return;
	if (this._removing === true) return;

	// ignore any of the filler items
	if (this._filler.indexOf(equipmentKey) >= 0) return;

	// special case for IronHide Armour - clear out the mission variables as well as the equipment.
	if (equipmentKey === "EQ_IRONHIDE") {
		missionVariables.ironHide_percentage = 0;
		missionVariables.ironHide_milFlag = 0;
		mission.setInstructionsKey(null, "IronHide Armour Script");
	}
	// ignore any removal equipment items
	if (equipmentKey.indexOf("REMOVE") > 0 || equipmentKey.indexOf("REMOVAL") > 0 || equipmentKey.indexOf("REFUND") > 0 ||
		equipmentKey.indexOf("_DAMAGED") > 0 || equipmentKey.indexOf("_REPAIR") > 0) return;

	// armour handled in it's own script
	if (this._armour.indexOf(equipmentKey) >= 0) return;

	if (equipmentKey === "EQ_HEAT_SINK") {
		if (player.ship.equipmentStatus("EQ_HEAT_SINK") != "EQUIPMENT_OK") {
			player.ship.removeEquipment("EQ_HEAT_SINK_CONTROL");
			player.ship.removeEquipment("EQ_HEAT_SINK_CONTROL_PASSIVE");
		}
	}

	// special cases for when an OXP removes these items directly
	if (equipmentKey === "EQ_FUEL_INJECTION" && player.ship.docked) {
		this._removing = true;
		var fieq = this.$equipmentItemInUse("fuelinjectors", player.ship);
		if (fieq != "") player.ship.removeEquipment(fieq);
		this._removing = false;
		return;
	}
	if (equipmentKey === "EQ_FUEL_SCOOPS" && player.ship.docked) {
		this._removing = true;
		var fseq = this.$equipmentItemInUse("fuelscoops", player.ship);
		if (fseq != "") player.ship.removeEquipment(fseq);
		this._removing = false;
		return;
	}
	if (equipmentKey === "EQ_HEAT_SHIELD" && player.ship.docked) {
		this._removing = true;
		var hseq = this.$equipmentItemInUse("heatshields", player.ship);
		if (hseq != "") player.ship.removeEquipment(hseq);
		this._removing = false;
		return;
	}

	if (this._ignoreEquip.indexOf(equipmentKey) >= 0) return;
	if (equipmentKey === "EQ_SHIPCONFIG") return;

	var p = player.ship;

	this._removing = true;

	// if we're removing fuel injectors, remove the core equipment item as well
	if (this._fuelinjectors.indexOf(equipmentKey) >= 0) {
		p.removeEquipment("EQ_FUEL_INJECTION");
	}
	// if we're removing fuel scoops, remove the core equipment item as well
	if (this._fuelscoops.indexOf(equipmentKey) >= 0) {
		p.removeEquipment("EQ_FUEL_SCOOPS");
	}
	// if we're removing the heat shield, remove the core equipment item as well
	if (this._heatshields.indexOf(equipmentKey) >= 0) {
		p.removeEquipment("EQ_HEAT_SHIELD");
	}

	this.$checkForOverload();

	/*var equipSpace = this.$equipmentSpaceTotal(p);
	var cargoSpace = this.$cargoSpaceAvailable(p);// + this.$cargoEquipmentSpaceAmount(p));

	var used = this.$calcEquipmentSpace(p);
	if (used > equipSpace) {
		// allocate cargo space to equipment space
		var diff = parseInt(used - equipSpace);
		if (diff > cargoSpace) {
			// we don't have space for this
			// switch into "overloaded" mode so the player can choose what item to remove
			this._initialSetup = true;
			this._promptPlayer = true;
		}
	}*/

	this.$addEquipmentSpaceItem(p);
	this._removing = false;
}

//-------------------------------------------------------------------------------------------------------------
this.shipTakingDamage = function (amount, whom, type) {
	// pass energy damage onto the unshielded ship as a heat increase
	if (player.ship && type === "energy damage" && this._heatControl === true && amount > 0) {
		//if (this._debug) log(this.name, amount + " ... adding to temp (" + player.ship.temperature + ") " + (amount / (player.ship.maxEnergy * player.ship.heatInsulation)));
		var amt = amount / (player.ship.maxEnergy * player.ship.heatInsulation);
		player.ship.temperature += Math.pow((1.1 - player.ship.temperature), 4) * amt;
	}
	// check for bus overload 
	if (this._busProcessing === false && player.ship && amount === 0 && type === "energy damage" && this._busOverload > 0 && Math.random() < (this._busOverload / 50)) {
		this._busProcessing = true;
		// the higher the busoverload figure, the more frequently the counter will trip and damage is taken somewhere.
		this._busOverloadCounter += this._busOverload;
		var damaged = false;
		if (this._debug) log(this.name, "bus overload actvated - " + this._busOverloadCounter);
		if (this._busOverloadResetTimer != null && this._busOverloadResetTimer.isRunning) {
			this._busOverloadResetTimer.stop();
		}
		this._busOverloadResetTimer = new Timer(this, this.$decreaseBusOverload, 30, 30);
		if (this._busOverloadCounter > this._busOverloadLimit) {
			this._busMessageCounter += 1;
			if (this._debug) log(this.name, "bus overload hit limit. messagecounter = " + this._busMessageCounter);
			if (this._debug) log(this.name, "check val = " + ((1 / this._busOverload) * 10));
			// reset the counter a bit, but not back to zero
			this._busOverloadCounter /= 2;
			player.consoleMessage(expandDescription("[sc_bus_overload]"));
			if (this._busMessageCounter > ((1 / this._busOverload) * 10) && Math.random() > 0.1) {
				if (this._debug) log(this.name, "**HIT** bus overload damage routine");
				// fully reset the counter now
				this._busMessageCounter = 0;
				// ok time to damage a piece of equipment
				var count = 0;
				var p = player.ship;
				var eq = p.equipment;
				// try 5 times to find an undamaged piece of kit that can be damaged and isn't already
				do {
					count += 1;
					var idx = Math.floor(Math.random() * eq.length);
					if (eq[idx].isVisible && eq[idx].damageProbability != 0 && p.equipmentStatus(eq[idx].equipmentKey) === "EQUIPMENT_OK") {
						// make sure the armour doesn't auto-fix the equipment we're about to damage (it shouldn't, but just in case)
						worldScripts.ShipConfiguration_Armour._override = true;
						player.consoleMessage(expandDescription("[sc_bus_powersurge]", { item: eq[idx].name }));
						p.setEquipmentStatus(eq[idx].equipmentKey, "EQUIPMENT_DAMAGED");
						if (this._debug) log(this.name, "bus overload equipment damage on " + eq[idx].equipmentKey);
						worldScripts.ShipConfiguration_Armour._override = false;
						break;
					}
				} while (count < 5);
			}
		}
		this._busProcessing = false;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.playerStartedJumpCountdown = function (type, seconds) {
	// abort the countdown if the equipment is damaged
	if (type === "standard") {
		var p = player.ship;
		var hd = this.$equipmentItemInUse("hyperdrive", p);
		if (p.equipmentStatus(hd) === "EQUIPMENT_DAMAGED") {
			p.hyperspaceSpinTime = 50;
			if (Math.random() > 0.3) {
				// sometimes just cancel the countdown
				p.cancelHyperspaceCountdown();
				player.consoleMessage(expandDescription("[sc_hyperdrive_aborted]"));
			} else if (Math.random() > 0.3) {
				// and sometimes force a misjump
				p.scriptedMisjump = true;
			}

			// don't try to reset this here if the equipment isn't damaged
			// assume the correct spin time was set on launch
			/*} else {
				// make sure we get the right spin time for the class of drive
				// just in case something overwrites the value
				var info = EquipmentInfo.infoForKey(hd);
				p.hyperspaceSpinTime = parseInt(info.scriptInfo.spin_time);*/
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// this will adjust the specs of the player ship whenever missiles are launched (making the ship lighter),
this.shipFiredMissile = function (missile, target) {
	this.$updateShipSpecs(player.ship);
}

//-------------------------------------------------------------------------------------------------------------
// this will adjust the specs of the player ship whenever cargo or a standard escape pod is scooped (making the ship heavier),
this.shipScoopedOther = function (whom) {
	this.$updateShipSpecs(player.ship);
}

//-------------------------------------------------------------------------------------------------------------
this.shipWillLaunchFromStation = function (station) {
	var p = player.ship;
	this._counter = 0;
	this.$updateShipSpecs(p);
	var energyeq = this.$equipmentItemInUse("energy", p);
	if (energyeq != "" && p.equipmentStatus(energyeq) === "EQUIPMENT_DAMAGED") {
		//if (this._debug) log(this.name, "!!ALERT: Energy equipment " + energyeq + " reported as damaged");
		if (!p.script._energyTimer || !p.script._energyTimer.isRunning) {
			//if (this._debug) log(this.name, "!!NOTE: Starting timer to drain energy");
			p.script._energyTimer = new Timer(this, p.script.$checkRemainingEnergy, 1, 1);
		}
	}
	this._busOverload = this.$busOverloadChance(p);
	// store it in a script value for easy pickup by heat routine
	p.script._busOverload = this._busOverload;
	// store the amount of equip extensions installed as this will result in more heat as well
	p.script._equipExt = this.$getEquipmentExtensions(p);
	// store values from any equipment items that increase cabin temp
	p.script._equipmentClassHeat = 0;
	var eqlist = p.equipment;
	for (var i = 0; i < eqlist.length; i++) {
		var eq = eqlist[i];
		if (this._equipHeatList[eq.equipmentKey]) p.script._equipmentClassHeat += this._equipHeatList[eq.equipmentKey];
	}
	//log(this.name, "final class heat = " + p.script._equipmentClassHeat);
	if (p.temperature < (0.234375 + (p.script._busOverload / 100) + (p.script._equipExt / 100) + p.script._equipmentClassHeat)) {
		p.temperature = 0.234375 + (p.script._busOverload / 100) + (p.script._equipExt / 100) + p.script._equipmentClassHeat;
	}
}

//-------------------------------------------------------------------------------------------------------------
// check when the player launches if this is a simulator run
this.shipLaunchedFromStation = function (station) {
	if (this.$simulatorRunning()) this._simulator = true;
}

//-------------------------------------------------------------------------------------------------------------
this.shipWillDockWithStation = function (station) {
	if (this._simulator === true) this.$removeEquipSpaceItem();
}

//-------------------------------------------------------------------------------------------------------------
// this will adjust the specs of the player ship whenever cargo is dumped (making the ship lighter) (pre v1.84)
/*this.shipSpawned = function (ship) {
	// did the player just dump cargo?
	var p = player.ship;
	if (p && ship && ship.isCargo && ship.position && p.position && p.position.distanceTo(ship) < 300) {
		this.$updateShipSpecs(p);
	}
}*/

//-------------------------------------------------------------------------------------------------------------
// this will adjust the specs of the player ship whenever cargo is dumped (making the ship lighter) (post v1.84)
this.shipDumpedCargo = function (cargo) {
	this.$updateShipSpecs(player.ship);
}

//-------------------------------------------------------------------------------------------------------------
this.guiScreenChanged = function (to, from) {
	if (guiScreen === "GUI_SCREEN_SHIPYARD" && this._hyperHangar === true) {
		this._hyperHangarTimer = new Timer(this, this.$updateHyperHangarShipImage, 1, 0);
	}
	if (guiScreen === "GUI_SCREEN_MISSION" && mission.screenID === "HyperspaceHangar" && this._hyperHangarActive === false) {
		this._hyperHangarActive = true;
		this.$preResprayFunction();
	}
	if (player.ship.docked === true && guiScreen !== "GUI_SCREEN_EQUIP_SHIP") {
		this.$checkForOverload();
	}
}

//-------------------------------------------------------------------------------------------------------------
this.guiScreenWillChange = function (to, from) {
	if (to === "GUI_SCREEN_STATUS" && this._simulator === true) {
		this._simulator = false;
		this._startUp = true;
		this.$postResprayFunction();
	}
}

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

//=============================================================================================================
// interface screens

//-------------------------------------------------------------------------------------------------------------
// initialise the equipment specification list
this.$initInterface = function $initInterface(station) {
	if (station.isPolice) {
		// disable ship config at police/navy stations
		station.setInterface(this.name, null);
	} else {
		if (!this._suppressEquipSpecs) {
			station.setInterface(this.name, {
				title: expandDescription("[sc_equip_specs_title]"),
				category: expandDescription("[interfaces-category-ship-systems]"),
				summary: expandDescription("[sc_equip_specs_summary]"),
				callback: this.$openEquipmentListing.bind(this)
			});
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$openEquipmentListing = function $openEquipmentListing() {
	this._page = 0;
	this.$equipmentListing();
}

//-------------------------------------------------------------------------------------------------------------
this.$equipmentListing = function $equipmentListing() {
	function compare(a, b) {
		return ((a.name > b.name) ? 1 : -1);
	}

	var list = [];
	var curChoices = {};
	var text = "";
	var pagesize = 14;
	if (player.ship.hudHidden === true || this.$isBigGuiActive() === true) pagesize = 20;

	var spc = String.fromCharCode(31) + String.fromCharCode(31) + String.fromCharCode(31);
	var def = "99_EXIT";
	var col1 = 15;
	var col2 = 4;

	//text += "Equipment available at this station:\n";
	text += this.$padTextRight("", col1 + col2) +
		this.$padTextLeft(expandDescription("[sc_config_equip]"), col2) +
		this.$padTextLeft(expandDescription("[sc_config_cargo]"), col2) + "\n";
	text += this.$padTextRight(expandDescription("[sc_equip_specs_equip]"), col1) +
		this.$padTextLeft(expandDescription("[sc_equip_specs_tl]"), col2) +
		this.$padTextLeft(expandDescription("[sc_equip_specs_space]"), col2) +
		this.$padTextLeft(expandDescription("[sc_equip_specs_space]"), col2) +
		this.$padTextLeft(expandDescription("[sc_equip_specs_weight]"), col2) + "\n\n";

	var eqlist = EquipmentInfo.allEquipment;
	for (var i = 0; i < eqlist.length; i++) {
		var eq = eqlist[i];
		//if (eq.name === "GalCop Scanner") log(this.name, "eq " + eq.equipmentKey);
		// skip any "repair" or "removal" equipment items
		if ((eq.equipmentKey.indexOf("REPAIR") >= 0 && eq.equipmentKey != "EQ_REPAIRBOTS_MINE" && eq.equipmentKey != "EQ_REPAIRBOTS_CONTROLLER" && eq.equipmentKey != "EQ_REPAIRBOTS_RECHARGE") ||
			eq.equipmentKey.indexOf("REMOVE") >= 0 || eq.equipmentKey.indexOf("REMOVAL") >= 0 || eq.equipmentKey.indexOf("REFUND") >= 0 || eq.equipmentKey.indexOf("_SALVAGED") >= 0 ||
			eq.name.indexOf("(RRS discount)") >= 0 || eq.equipmentKey === "EQ_MILITARY_JAMMER" || eq.equipmentKey === "EQ_MILITARY_SCANNER_FILTER" ||
			eq.equipmentKey.indexOf("EQ_CRIPPLED") >= 0) continue;

		// system.info.techlevel >= eq.techLevel && 
		if (this._ignoreEquip.indexOf(eq.equipmentKey) === -1 && eq.isVisible === true && eq.techLevel <= 16 && eq.isAvailableToPlayer) {
			// is this item already in the list?
			var found = false;
			for (var j = 0; j < list.length; j++) {
				if (list[j].name === eq.name) found = true;
			}
			if (found === true) continue;

			var space = 0;
			var weight = 0;
			var cargo = 0;
			var lookup = this._equipmentMatrix[eq.equipmentKey];
			if (lookup) {
				space = lookup[0];
				weight = lookup[1];
				cargo = eq.requiredCargoSpace;
			} else {
				if (this._debug) log(this.name, "!!NOTE: Equipment item not found " + eq.equipmentKey);
				if (eq.requiredCargoSpace === 0) {
					space = 1;
					weight = 1;
					cargo = 0;
				} else {
					space = 0;
					cargo = eq.requiredCargoSpace;
					weight = eq.requiredCargoSpace;
				}
			}
			if (space > 0 || weight > 0) {
				list.push({
					name: eq.name,
					tl: (parseInt(eq.techLevel) + 1).toString(),
					space: space,
					weight: weight,
					cargo: cargo
				});
			}
		}
	}
	list.sort(compare);

	var maxpage = Math.ceil(list.length / (pagesize));
	var end = ((this._page * (pagesize)) + (pagesize));
	if (end > list.length) end = list.length;
	for (var i = (this._page * (pagesize)); i < end; i++) {
		text += this.$padTextRight(list[i].name, col1) +
			this.$padTextLeft(list[i].tl, col2) +
			this.$padTextLeft(list[i].space.toFixed(1) + spc + "t", col2) +
			this.$padTextLeft(list[i].cargo.toFixed(1) + spc + "t", col2) +
			this.$padTextLeft(list[i].weight.toFixed(1) + spc + "t", col2) + "\n";
	}

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

	curChoices["99_EXIT"] = {
		text: "[sc-return]",
		color: this._itemColor
	};

	if (this._lastChoice[24] != "") def = this._lastChoice[24];

	var opts = {
		screenID: "oolite-shipconfig-equipmentlist-map",
		title: expandDescription("[sc_equip_specs_header]", { page: (parseInt(this._page) + 1), max: maxpage }),
		overlay: {
			name: "shipconfig_rocket.png",
			height: 546
		},
		allowInterrupt: true,
		exitScreen: "GUI_SCREEN_INTERFACES",
		choices: curChoices,
		initialChoicesKey: def,
		message: text
	};

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

//-------------------------------------------------------------------------------------------------------------
this.$equipmentListScreenHandler = function $equipmentListScreenHandler(choice) {

	if (!choice) return;

	if (choice === "95_NEXT") this._page += 1;
	if (choice === "96_PREV") this._page -= 1;
	this._lastChoice[24] = choice;

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

//-------------------------------------------------------------------------------------------------------------
this.$shipConfig = function $shipConfig() {
	function compare(a, b) {
		if (a.space != b.space) {
			return b.space - a.space;
		} else if (a.cargo != b.cargo) {
			return b.cargo - a.cargo;
		} else if (a.weight != b.weight) {
			return b.weight - a.weight;
		} else {
			return a.name > b.name;
		}
	}

	var p = player.ship;
	var stn = p.dockedStation;
	var used = this.$calcEquipmentSpace(p);
	var maxSpace = Math.ceil(this.$equipmentSpaceTotal(p) + this.$cargoSpaceAvailable(p));
	var spc = String.fromCharCode(31) + String.fromCharCode(31) + String.fromCharCode(31);
	var curr = this._currEquip;

	var priceFactor = this.$equipmentPriceFactor(p.shipClassName, this.$getShipMass(p));

	var col1 = 19;
	var col2 = 3.5;
	var col3 = 6;

	var interrupt = true;
	var text = "";
	var curChoices = {};
	var itemcount = 0;

	var pagesize = 22;
	if (this.$isBigGuiActive() === false) p.hudHidden = true;

	var def = "99_EXIT";
	text += this.$pageHeader("config");

	// display the list of options
	if (used > maxSpace) {
		// make sure we don't lock the player in during flight
		if (p.alertCondition === 0) {
			interrupt = false; // set to false to force the player to sell equipment before continuing
		}
	} else {
		this._initialSetup = false;
	}

	if (this._display === 0) {
		text += this.$padTextRight(expandDescription("[sc-mainmenu]"), col1) + this.$padTextLeft(expandDescription("[sc_config_equip]"), col2) + "\n";
		text += this.$padTextRight(expandDescription("[sc-menudescription]"), col1) +
			this.$padTextLeft(expandDescription("[sc_equip_specs_space]"), col2) +
			this.$padTextLeft(expandDescription("[sc_equip_specs_weight]"), col2);

		var itemcolor = this._menuColor;
		if (p.equipmentStatus(this.$equipmentItemInUse("engines", p)) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
		curChoices["01_ENGINES"] = {
			text: this.$padTextRight(expandDescription("[sc_config_engines]", { class: this.$equipmentItemInUse("engines", p).replace("EQ_ENGINE_TYPE", "") }), col1) +
				this.$padTextLeft(this.$equipmentSpaceInUse("engines", p).toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(this.$equipmentWeightInUse("engines", p).toFixed(1) + spc + "t", col2),
			alignment: "LEFT",
			color: itemcolor
		};
		if (this.$shipHasHyperspaceMotor(p.dataKey) === true && this._OXPHyperdrives === false) {
			itemcolor = this._menuColor;
			if (p.equipmentStatus(this.$equipmentItemInUse("hyperdrive", p)) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
			curChoices["02_HYPERDRIVE"] = {
				text: this.$padTextRight(expandDescription("[sc_config_hyperdrive]", { class: this.$equipmentItemInUse("hyperdrive", p).replace("EQ_HYPERDRIVE_TYPE", "") }), col1) +
					this.$padTextLeft(this.$equipmentSpaceInUse("hyperdrive", p).toFixed(1) + spc + "t", col2) +
					this.$padTextLeft(this.$equipmentWeightInUse("hyperdrive", p).toFixed(1) + spc + "t", col2),
				alignment: "LEFT",
				color: itemcolor
			};
		}
		var itemcolor = this._menuColor;
		if (p.equipmentStatus(this.$equipmentItemInUse("thrusters", p)) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
		curChoices["03_THRUSTERS"] = {
			text: this.$padTextRight(expandDescription("[sc_config_thrusters]", { class: this.$equipmentItemInUse("thrusters", p).replace("EQ_THRUSTERS_TYPE", "") }), col1) +
				this.$padTextLeft(this.$equipmentSpaceInUse("thrusters", p).toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(this.$equipmentWeightInUse("thrusters", p).toFixed(1) + spc + "t", col2),
			alignment: "LEFT",
			color: itemcolor
		};

		if (this._heatControl === true) {
			var itemcolor = this._menuColor;
			var bs = this.$equipmentItemInUse("boosters", p);
			if (bs != "") {
				if (p.equipmentStatus(bs) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
				curChoices["03A_BOOSTERS"] = {
					text: this.$padTextRight(expandDescription("[sc_config_boosters]", { class: this.$equipmentItemInUse("boosters", p).replace("EQ_BOOSTERS_TYPE", "") }), col1) +
						this.$padTextLeft(this.$equipmentSpaceInUse("boosters", p).toFixed(1) + spc + "t", col2) +
						this.$padTextLeft(this.$equipmentWeightInUse("boosters", p).toFixed(1) + spc + "t", col2),
					alignment: "LEFT",
					color: itemcolor
				};
			} else {
				curChoices["03A_BOOSTERS"] = {
					text: this.$padTextRight(expandDescription("[sc_config_boosters_none]"), col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft("0.0" + spc + "t", col2),
					alignment: "LEFT",
					color: itemcolor
				};
			}
		}

		var itemcolor = this._menuColor;
		if (p.equipmentStatus(this.$equipmentItemInUse("energy", p)) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
		curChoices["04_ENERGY"] = {
			text: this.$padTextRight(expandDescription("[sc_config_energy]", { class: this.$equipmentItemInUse("energy", p).replace("EQ_ENERGYBANK_TYPE", "") }), col1) +
				this.$padTextLeft(this.$equipmentSpaceInUse("energy", p).toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(this.$equipmentWeightInUse("energy", p).toFixed(1) + spc + "t", col2),
			alignment: "LEFT",
			color: itemcolor
		};
		var itemcolor = this._menuColor;
		var fs = this.$equipmentItemInUse("frontshields", p);
		if (fs === "EQ_NO_FORWARD_SHIELD") {
			curChoices["05_FRONTSHIELDS"] = {
				text: this.$padTextRight(expandDescription("[sc_config_frontshields_none]"), col1) +
					this.$padTextLeft(this.$equipmentSpaceInUse("frontshields", p).toFixed(1) + spc + "t", col2) +
					this.$padTextLeft(this.$equipmentWeightInUse("frontshields", p).toFixed(1) + spc + "t", col2),
				alignment: "LEFT",
				color: itemcolor
			};
		} else {
			if (p.equipmentStatus(this.$equipmentItemInUse("frontshields", p)) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
			curChoices["05_FRONTSHIELDS"] = {
				text: this.$padTextRight(expandDescription("[sc_config_frontshields]", { class: this.$equipmentItemInUse("frontshields", p).replace("EQ_FORWARD_SHIELD_TYPE", "") }), col1) +
					this.$padTextLeft(this.$equipmentSpaceInUse("frontshields", p).toFixed(1) + spc + "t", col2) +
					this.$padTextLeft(this.$equipmentWeightInUse("frontshields", p).toFixed(1) + spc + "t", col2),
				alignment: "LEFT",
				color: itemcolor
			};
		}
		var itemcolor = this._menuColor;
		var as = this.$equipmentItemInUse("aftshields", p);
		if (as === "EQ_NO_AFT_SHIELD") {
			curChoices["06_AFTSHIELDS"] = {
				text: this.$padTextRight(expandDescription("[sc_config_aftshields_none]"), col1) +
					this.$padTextLeft(this.$equipmentSpaceInUse("aftshields", p).toFixed(1) + spc + "t", col2) +
					this.$padTextLeft(this.$equipmentWeightInUse("aftshields", p).toFixed(1) + spc + "t", col2),
				alignment: "LEFT",
				color: itemcolor
			};
		} else {
			if (p.equipmentStatus(this.$equipmentItemInUse("aftshields", p)) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
			curChoices["06_AFTSHIELDS"] = {
				text: this.$padTextRight(expandDescription("[sc_config_aftshields]", { class: this.$equipmentItemInUse("aftshields", p).replace("EQ_AFT_SHIELD_TYPE", "") }), col1) +
					this.$padTextLeft(this.$equipmentSpaceInUse("aftshields", p).toFixed(1) + spc + "t", col2) +
					this.$padTextLeft(this.$equipmentWeightInUse("aftshields", p).toFixed(1) + spc + "t", col2),
				alignment: "LEFT",
				color: itemcolor
			};
		}
		var itemcolor = this._menuColor;
		var fi = this.$equipmentItemInUse("fuelinjectors", p);
		if (fi != "") {
			if (p.equipmentStatus(fi) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
			curChoices["07_FUELINJECTORS"] = {
				text: this.$padTextRight(expandDescription("[sc_config_injectors]", { class: this.$equipmentItemInUse("fuelinjectors", p).replace("EQ_FUEL_INJECTION_TYPE", "") }), col1) +
					this.$padTextLeft(this.$equipmentSpaceInUse("fuelinjectors", p).toFixed(1) + spc + "t", col2) +
					this.$padTextLeft(this.$equipmentWeightInUse("fuelinjectors", p).toFixed(1) + spc + "t", col2),
				alignment: "LEFT",
				color: itemcolor
			};
		} else {
			curChoices["07_FUELINJECTORS"] = {
				text: this.$padTextRight(expandDescription("[sc_config_injectors_none]"), col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft("0.0" + spc + "t", col2),
				alignment: "LEFT",
				color: itemcolor
			};
		}
		var itemcolor = this._menuColor;
		var sc = this.$equipmentItemInUse("fuelscoops", p);
		if (sc != "") {
			if (p.equipmentStatus(sc) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
			curChoices["08_FUELSCOOPS"] = {
				text: this.$padTextRight(expandDescription("[sc_config_scoops]", { class: this.$equipmentItemInUse("fuelscoops", p).replace("EQ_FUEL_SCOOPS_TYPE", "") }), col1) +
					this.$padTextLeft(this.$equipmentSpaceInUse("fuelscoops", p).toFixed(1) + spc + "t", col2) +
					this.$padTextLeft(this.$equipmentWeightInUse("fuelscoops", p).toFixed(1) + spc + "t", col2),
				alignment: "LEFT",
				color: itemcolor
			};
		} else {
			curChoices["08_FUELSCOOPS"] = {
				text: this.$padTextRight(expandDescription("[sc_config_scoops_none]"), col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft("0.0" + spc + "t", col2),
				alignment: "LEFT",
				color: itemcolor
			};
		}
		var itemcolor = this._menuColor;
		var hs = this.$equipmentItemInUse("heatshields", p);
		if (hs != "") {
			if (p.equipmentStatus(hs) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
			curChoices["09_HEATSHIELDS"] = {
				text: this.$padTextRight(expandDescription("[sc_config_heatshields]", { class: hs.replace("EQ_HEAT_SHIELD_TYPE", "") }), col1) +
					this.$padTextLeft(this.$equipmentSpaceInUse("heatshields", p).toFixed(1) + spc + "t", col2) +
					this.$padTextLeft(this.$equipmentWeightInUse("heatshields", p).toFixed(1) + spc + "t", col2),
				alignment: "LEFT",
				color: itemcolor
			};
		} else {
			curChoices["09_HEATSHIELDS"] = {
				text: this.$padTextRight(expandDescription("[sc_config_heatshields_none]"), col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft("0.0" + spc + "t", col2),
				alignment: "LEFT",
				color: itemcolor
			};
		}
		var itemcolor = this._menuColor;
		// if player has alternative armour installed, don't show this item at all
		if (this.$playerHasOtherArmour() === false) {
			var arf = this.$equipmentItemInUse("frontarmour", p);
			if (arf != "") {
				if (p.script._armourFront < 100) itemcolor = this._damagedColor;
				curChoices["10_ARMOUR_0FRONT"] = {
					text: this.$padTextRight(expandDescription("[sc_config_frontarmour]", { class: arf.replace("EQ_ARMOUR_FORWARD_TYPE", "") }), col1) +
						this.$padTextLeft("0.0" + spc + "t", col2) +
						this.$padTextLeft(this.$equipmentWeightInUse("frontarmour", p).toFixed(1) + spc + "t", col2),
					alignment: "LEFT",
					color: itemcolor
				};
			} else {
				curChoices["10_ARMOUR_0FRONT"] = {
					text: this.$padTextRight(expandDescription("[sc_config_frontarmour_none]"), col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft("0.0" + spc + "t", col2),
					alignment: "LEFT",
					color: itemcolor
				};
			}
			var ara = this.$equipmentItemInUse("aftarmour", p);
			if (ara != "") {
				if (p.script._armourAft < 100) itemcolor = this._damagedColor;
				curChoices["10_ARMOUR_1AFT"] = {
					text: this.$padTextRight(expandDescription("[sc_config_aftarmour]", { class: ara.replace("EQ_ARMOUR_AFT_TYPE", "") }), col1) +
						this.$padTextLeft("0.0" + spc + "t", col2) +
						this.$padTextLeft(this.$equipmentWeightInUse("aftarmour", p).toFixed(1) + spc + "t", col2),
					alignment: "LEFT",
					color: itemcolor
				};
			} else {
				curChoices["10_ARMOUR_1AFT"] = {
					text: this.$padTextRight(expandDescription("[sc_config_aftarmour_none]"), col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft("0.0" + spc + "t", col2),
					alignment: "LEFT",
					color: itemcolor
				};
			}
		} else {
			for (var i = 0; i < this._altArmour.length; i++) {
				if (p.equipmentStatus(this._altArmour[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._altArmour[i]) === "EQUIPMENT_DAMAGED") {
					var info = EquipmentInfo.infoForKey(this._altArmour[i]);
					var wt = 0;
					if (this._equipmentMatrix[this._altArmour[i]]) wt = this._equipmentMatrix[this._altArmour[i]][1];
					curChoices["10_ARMOUR"] = {
						text: this.$padTextRight(expandDescription("[sc_config_armour]", { name: info.name }), col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft(wt.toFixed(1) + spc + "t", col2),
						alignment: "LEFT",
						color: this._disabledColor,
						unselectable: true
					};
					break;
				}
			}
		}
		curChoices["11_ELECTRICAL"] = {
			text: this.$padTextRight(expandDescription("[sc_config_bus_couplings]"), col1) +
				this.$padTextLeft(this.$equipmentSpaceInUse("electrical", p).toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(this.$equipmentWeightInUse("electrical", p).toFixed(1) + spc + "t", col2),
			alignment: "LEFT",
			color: this._menuColor
		};

		for (var i = 0; i < (pagesize - (20 - (this.$shipHasHyperspaceMotor(p.dataKey) === true && this._OXPHyperdrives === false ? 0 : 1))); i++) {
			curChoices["90_SPACER_" + i] = "";
		}

		curChoices["96_VIEWEQUIP"] = {
			text: "[sc-viewinstalled]",
			color: this._itemColor
		};
		if (worldScripts.EquipmentStorage.$stationHasStorageFacilities(stn) === true) {
			curChoices["97A_STORAGE"] = {
				text: "[storage-store-equipment]",
				color: this._itemColor
			};
		} else {
			curChoices["97A_STORAGE"] = {
				text: "[storage-store-equipment]",
				color: this._disabledColor,
				unselectable: true
			};
		}
		curChoices["97_SELL"] = {
			text: "[sc-sellequip]",
			color: this._itemColor
		};

		// display the list of options
		if (used > maxSpace) {
			curChoices["99_EXIT"] = {
				text: "[sc-return]",
				color: this._disabledColor,
				unselectable: true
			};
		} else {
			curChoices["99_EXIT"] = {
				text: "[sc-return]",
				color: this._itemColor
			};
		}

		if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];

		var opts = {
			screenID: "oolite-shipconfig-main-map",
			title: expandDescription("[sc_config_alias]"),
			allowInterrupt: interrupt,
			exitScreen: "GUI_SCREEN_EQUIP_SHIP",
			choices: curChoices,
			initialChoicesKey: def,
			message: text
		};
	}

	var list = [];
	var dam = 1;
	var coupling = 0;
	var bus = this.$equipmentCouplingLevelInUse("electricalbus", p);
	var section = "";

	if (this._display === 1) { // engines
		section = "[sc-section-engines]";
		coupling = this.$equipmentCouplingLevelInUse("engines", p);
		for (var i = 0; i < this._engines.length; i++) {
			var eq = this._engines[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("engines", p)) <= maxSpace)) {
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("engines", eq, p)) check = "UNAVAILABLE";
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("engines", eq, p)) check = "RISK";
				dam = 1;
				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 2) { // hyperdrive
		section = "[sc-section-hyperdrive]";
		coupling = this.$equipmentCouplingLevelInUse("hyperdrive", p);
		for (var i = 0; i < this._hyperdrive.length; i++) {
			var eq = this._hyperdrive[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("hyperdrive", p)) <= maxSpace)) {
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("hyperdrive", eq, p)) check = "UNAVAILABLE";
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("hyperdrive", eq, p)) check = "RISK";
				dam = 1;
				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 3) { // thrusters
		section = "[sc-section-thrusters]";
		coupling = this.$equipmentCouplingLevelInUse("thrusters", p);
		for (var i = 0; i < this._thrusters.length; i++) {
			var eq = this._thrusters[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("thrusters", p)) <= maxSpace)) {
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("thrusters", eq, p)) check = "UNAVAILABLE";
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("thrusters", eq, p)) check = "RISK";
				dam = 1;
				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 18) { // boosters
		section = "[sc-section-boosters]";
		coupling = this.$equipmentCouplingLevelInUse("boosters", p);
		var found = false;
		var key = "";
		for (var i = 0; i < this._boosters.length; i++) {
			if (p.equipmentStatus(this._boosters[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._boosters[i]) === "EQUIPMENT_DAMAGED") {
				key = this._boosters[i];
				found = true;
			}
		}
		if (found === true && EquipmentInfo.infoForKey(key).effectiveTechLevel <= stn.equivalentTechLevel) {
			list.push({
				name: expandDescription("[sc-remove-boosters]"),
				extra: "",
				key: "EQ_BOOSTERS_REMOVE",
				space: 0,
				weight: 0,
				cost: 0,
				flag: ""
			});
		}
		for (var i = 0; i < this._boosters.length; i++) {
			var eq = this._boosters[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("boosters", p)) <= maxSpace)) {
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("boosters", eq, p)) check = "UNAVAILABLE";
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("boosters", eq, p)) check = "RISK";
				dam = 1;
				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 4) { // energy
		section = "[sc-section-energy]";
		coupling = this.$equipmentCouplingLevelInUse("energy", p);
		for (var i = 0; i < this._energy.length; i++) {
			var eq = this._energy[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("energy", p)) <= maxSpace)) {
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("energy", eq, p)) check = "UNAVAILABLE";
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("energy", eq, p)) check = "RISK";
				dam = 1;
				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 5) { // front shields
		var startpoint = 0;
		section = "[sc-section-frontshields]";
		coupling = this.$equipmentCouplingLevelInUse("frontshields", p);
		// if any shield boosters are in place, we can't remove shields
		if (p.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK" || p.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") startpoint = 1;
		for (var i = startpoint; i < this._frontshields.length; i++) {
			var eq = this._frontshields[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("frontshields", p)) <= maxSpace)) {
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("frontshields", eq, p)) check = "UNAVAILABLE";
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("frontshields", eq, p)) check = "RISK";
				dam = 1;
				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 6) { // aft shields
		var startpoint = 0;
		section = "[sc-section-aftshields]";
		coupling = this.$equipmentCouplingLevelInUse("aftshields", p);
		// if any shield boosters are in place, we can't remove shields
		if (p.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK" || p.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") startpoint = 1;
		for (var i = startpoint; i < this._aftshields.length; i++) {
			var eq = this._aftshields[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("aftshields", p)) <= maxSpace)) {
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("aftshields", eq, p)) check = "UNAVAILABLE";
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("aftshields", eq, p)) check = "RISK";
				dam = 1;
				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 7) { // fuel injectors
		// inject a "remove" item into the list
		// do we have any injectors?
		section = "[sc-section-fuelinjectors]";
		coupling = this.$equipmentCouplingLevelInUse("engines", p);
		var found = false;
		var key = "";
		for (var i = 0; i < this._fuelinjectors.length; i++) {
			if (p.equipmentStatus(this._fuelinjectors[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._fuelinjectors[i]) === "EQUIPMENT_DAMAGED") {
				found = true;
				key = this._fuelinjectors[i];
			}
		}
		if (found === true && EquipmentInfo.infoForKey(key).effectiveTechLevel <= stn.equivalentTechLevel) {
			list.push({
				name: expandDescription("[sc-remove-fuelinjectors]"),
				extra: "",
				key: "EQ_FUEL_INJECTION_REMOVE",
				space: 0,
				weight: 0,
				cost: 0,
				flag: ""
			});
		}
		for (var i = 0; i < this._fuelinjectors.length; i++) {
			var eq = this._fuelinjectors[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("fuelinjectors", p)) <= maxSpace)) {
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("engines", eq, p)) check = "UNAVAILABLE";
				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("engines", eq, p)) check = "RISK";
				dam = 1;
				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * stn.equipmentPriceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 20) { // fuel scoops
		// inject a "remove" item into the list
		// do we have any scoops?
		section = "[sc-section-fuelscoops]";
		var found = false;
		var key = "";
		for (var i = 0; i < this._fuelscoops.length; i++) {
			if (p.equipmentStatus(this._fuelscoops[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._fuelscoops[i]) === "EQUIPMENT_DAMAGED") {
				found = true;
				key = this._fuelscoops[i];;
			}
		}
		if (found === true && EquipmentInfo.infoForKey(key).effectiveTechLevel <= stn.equivalentTechLevel) {
			list.push({
				name: expandDescription("[sc-remove-fuelscoops]"),
				extra: "",
				key: "EQ_FUEL_SCOOPS_REMOVE",
				space: 0,
				weight: 0,
				cost: 0,
				flag: ""
			});
		}
		for (var i = 0; i < this._fuelscoops.length; i++) {
			var eq = this._fuelscoops[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || stn.equivalentTechLevel >= info.techLevel) {
				dam = 1;
				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * stn.equipmentPriceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 8) { // heat shields
		// inject a "remove" item into the list
		// do we have any heat shielding?
		section = "[sc-section-heatshields]";
		var found = false;
		var key = "";
		for (var i = 0; i < this._heatshields.length; i++) {
			if (p.equipmentStatus(this._heatshields[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._heatshields[i]) === "EQUIPMENT_DAMAGED") {
				found = true;
				key = this._heatshields[i];
			}
		}
		if (found === true && EquipmentInfo.infoForKey(key).effectiveTechLevel <= stn.equivalentTechLevel) {
			list.push({
				name: expandDescription("[sc-remove-heatshields]"),
				extra: "",
				key: "EQ_HEAT_SHIELD_REMOVE",
				space: 0,
				weight: 0,
				cost: 0,
				flag: ""
			});
		}
		for (var i = 0; i < this._heatshields.length; i++) {
			var eq = this._heatshields[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || stn.equivalentTechLevel >= info.techLevel) {
				dam = 1;
				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * stn.equipmentPriceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 9) { // front armour
		// inject a "remove" item into the list
		// do we have any armour?
		section = "[sc-section-forward-armour]";
		var found = false;
		var key = "";
		for (var i = 0; i < this._frontarmour.length; i++) {
			if (p.equipmentStatus(this._frontarmour[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._frontarmour[i]) === "EQUIPMENT_DAMAGED") {
				found = true;
				key = this._frontarmour[i];
			}
		}
		if (found === true && EquipmentInfo.infoForKey(key).effectiveTechLevel <= stn.equivalentTechLevel) {
			list.push({
				name: expandDescription("[sc-remove-front-armour]"),
				extra: "",
				key: "EQ_ARMOUR_FORWARD_REMOVE",
				space: 0,
				weight: 0,
				cost: 0,
				flag: ""
			});
		}
		for (var i = 0; i < this._frontarmour.length; i++) {
			var eq = this._frontarmour[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);

			if (check === "EQUIPMENT_OK" && p.script._armourFront < 100) check = "EQUIPMENT_DAMAGED";

			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || stn.equivalentTechLevel >= info.techLevel) {
				dam = 1;
				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 21) { // aft armour
		// inject a "remove" item into the list
		// do we have any armour?
		section = "[sc-section-aft-armour]";
		var found = false;
		var key = "";
		for (var i = 0; i < this._aftarmour.length; i++) {
			if (p.equipmentStatus(this._aftarmour[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._aftarmour[i]) === "EQUIPMENT_DAMAGED") {
				found = true;
				key = this._aftarmour[i];
			}
		}
		if (found === true && EquipmentInfo.infoForKey(key).effectiveTechLevel <= stn.equivalentTechLevel) {
			list.push({
				name: expandDescription("[sc-remove-aft-armour]"),
				extra: "",
				key: "EQ_ARMOUR_AFT_REMOVE",
				space: 0,
				weight: 0,
				cost: 0,
				flag: ""
			});
		}
		for (var i = 0; i < this._aftarmour.length; i++) {
			var eq = this._aftarmour[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);

			if (check === "EQUIPMENT_OK" && p.script._armourAft < 100) check = "EQUIPMENT_DAMAGED";

			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || stn.equivalentTechLevel >= info.techLevel) {
				dam = 1;
				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}

	if (this._display === 11) { // elec bus
		section = "[sc-section-electricalbus]";
		for (var i = 0; i < this._electricalbus.length; i++) {
			var eq = this._electricalbus[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("electricalbus", p)) <= maxSpace)) {
				// check for downgrade case where its not available if a +1 coupling is attached
				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < bus && (i + 1) <= (this.$maxEquipmentCouplingInUse(p) - 1)) check = "UNAVAILABLE";
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 12) { // engine coupling
		section = "[sc-section-enginecoupling]";
		for (var i = 0; i < this._enCoupling.length; i++) {
			var eq = this._enCoupling[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("enginecoupling", p)) <= maxSpace)) {
				if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
				if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("engines", p) - 1)) check = "UNAVAILABLE";
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this.$shipHasHyperspaceMotor(p.dataKey) === true && this._OXPHyperdrives === false) { // hyperdrive
		if (this._display === 13) {
			section = "[sc-section-hyperdrivecoupling]";
			for (var i = 0; i < this._hdCoupling.length; i++) {
				var eq = this._hdCoupling[i];
				var info = EquipmentInfo.infoForKey(eq);
				var idx = curr.indexOf(eq);

				var check = p.equipmentStatus(eq);
				if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("hyperdrivecoupling", p)) <= maxSpace)) {
					if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
					if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
					if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("hyperdrive", p) - 1)) check = "UNAVAILABLE";
					list.push({
						name: info.scriptInfo.short_title,
						extra: info.scriptInfo.description,
						key: eq,
						space: this._equipmentMatrix[eq][0],
						weight: this._equipmentMatrix[eq][1],
						cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
						flag: check
					});
				}
			}
		}
	}
	if (this._display === 14) { // thrusters coupling
		section = "[sc-section-thrusterscoupling]";
		for (var i = 0; i < this._thCoupling.length; i++) {
			var eq = this._thCoupling[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("thrusterscoupling", p)) <= maxSpace)) {
				if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
				if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("thrusters", p) - 1)) check = "UNAVAILABLE";
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 19 && this._heatControl === true) { // boosters
		section = "[sc-section-boosterscoupling]";
		for (var i = 0; i < this._bsCoupling.length; i++) {
			var eq = this._bsCoupling[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("boosterscoupling", p)) <= maxSpace)) {
				if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
				if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("boosters", p) - 1)) check = "UNAVAILABLE";
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 15) { // energy coupling
		section = "[sc-section-energycoupling]";
		for (var i = 0; i < this._ebCoupling.length; i++) {
			var eq = this._ebCoupling[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("energycoupling", p)) <= maxSpace)) {
				if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
				if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("energy", p) - 1)) check = "UNAVAILABLE";
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 16) { // front shield coupling
		section = "[sc-section-frontshieldscoupling]";
		for (var i = 0; i < this._fsCoupling.length; i++) {
			var eq = this._fsCoupling[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("frontshieldscoupling", p)) <= maxSpace)) {
				if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
				if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("frontshields", p) - 1)) check = "UNAVAILABLE";
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}
	if (this._display === 17) { // aft shield coupling
		section = "[sc-section-aftshieldscoupling]";
		for (var i = 0; i < this._asCoupling.length; i++) {
			var eq = this._asCoupling[i];
			var info = EquipmentInfo.infoForKey(eq);
			var idx = curr.indexOf(eq);

			var check = p.equipmentStatus(eq);
			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("aftshieldscoupling", p)) <= maxSpace)) {
				if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
				if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("aftshields", p) - 1)) check = "UNAVAILABLE";
				list.push({
					name: info.scriptInfo.short_title,
					extra: info.scriptInfo.description,
					key: eq,
					space: this._equipmentMatrix[eq][0],
					weight: this._equipmentMatrix[eq][1],
					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
					flag: check
				});
			}
		}
	}

	if ((this._display >= 1 && this._display <= 9) || (this._display >= 11 && this._display <= 21)) {
		def = "98_EXIT";

		itemcount -= 2;

		text += this.$padTextRight(expandDescription(section), col1) + this.$padTextLeft(expandDescription("[sc_config_equip]"), col2) + "\n";
		text += this.$padTextRight(expandDescription("[sc_equip_specs_equip]"), col1) +
			this.$padTextLeft(expandDescription("[sc_equip_specs_space]"), col2) +
			this.$padTextLeft(expandDescription("[sc_equip_specs_weight]"), col2) +
			this.$padTextLeft(expandDescription("[sc_config_cost]"), col3);

		if (list.length === 0) {
			text += expandDescription("[sc-no-items-available]");
			itemcount += 2;
		} else {
			var maxpage = Math.ceil(list.length / (pagesize - 7));
			var end = ((this._page * (pagesize - 7)) + (pagesize - 7));
			if (end > list.length) end = list.length;
			for (var i = (this._page * (pagesize - 7)); i < end; i++) {
				var c = this._menuColor;
				switch (list[i].flag) {
					case "EQUIPMENT_OK":
						c = this._installedColor;
						break;
					case "EQUIPMENT_DAMAGED":
						c = this._damagedColor;
						break;
					case "UNAVAILABLE":
						c = this._disabledColor;
						break;
					case "RISK":
						c = this._riskColor;
						break;
				}
				curChoices["01_EQUIP-" + (i < 10 ? "0" : "") + i + "~" + list[i].key] = {
					text: this.$padTextRight(list[i].name + (list[i].extra != "" ? " (" + list[i].extra + ")" : ""), col1) +
						this.$padTextLeft(list[i].space.toFixed(1) + spc + "t", col2) +
						this.$padTextLeft(list[i].weight.toFixed(1) + spc + "t", col2) +
						this.$padTextLeft(formatCredits((list[i].cost / 10), true, true), col3),
					alignment: "LEFT",
					color: c,
					unselectable: (list[i].flag === "EQUIPMENT_OK" || list[i].flag === "EQUIPMENT_DAMAGED" || list[i].flag === "UNAVAILABLE" ? true : false)
				};
				itemcount += 1;
			}
		}

		for (var i = 0; i < ((pagesize - 8) - itemcount); i++) {
			curChoices["90_SPACER_" + i] = "";
		}

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

		if (this._display <= 9 || this._display === 18 || this._display >= 20) {
			curChoices["98_EXIT"] = {
				text: "[sc-return]",
				color: this._itemColor
			};
		} else {
			def = "97_EXIT";
			curChoices["97_EXIT"] = {
				text: "[sc-return]",
				color: this._itemColor
			};
		}

		if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];

		var opts = {
			screenID: "oolite-shipconfig-section-map",
			title: expandDescription("[sc_config_alias]"),
			allowInterrupt: interrupt,
			exitScreen: "GUI_SCREEN_EQUIP_SHIP",
			choices: curChoices,
			initialChoicesKey: def,
			message: text
		};
	}

	// electrical sub menu
	if (this._display === 10) {
		text += this.$padTextRight(expandDescription("[sc-section-elecbuscouplings]"), col1) + this.$padTextLeft(expandDescription("[sc_config_equip]"), col2) + "\n";
		text += this.$padTextRight(expandDescription("[sc-menudescription]"), col1) +
			this.$padTextLeft(expandDescription("[sc_equip_specs_space]"), col2) +
			this.$padTextLeft(expandDescription("[sc_equip_specs_weight]"), col2);

		curChoices["11_BUS"] = {
			text: this.$padTextRight(expandDescription("[sc_config_bus]", { class: this.$equipmentItemInUse("electricalbus", p).replace("EQ_ELEC_BUS_TYPE", "") }), col1) +
				this.$padTextLeft(this.$equipmentSpaceInUse("electricalbus", p).toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(this.$equipmentWeightInUse("electricalbus", p).toFixed(1) + spc + "t", col2),
			alignment: "LEFT",
			color: this._menuColor
		};
		curChoices["12_ENGINES"] = {
			text: this.$padTextRight(expandDescription("[sc_config_engine_coupling]", { class: this.$equipmentItemInUse("enginecoupling", p).replace("EQ_ENGINE_COUPLING_TYPE", "") }), col1) +
				this.$padTextLeft(this.$equipmentSpaceInUse("enginecoupling", p).toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(this.$equipmentWeightInUse("enginecoupling", p).toFixed(1) + spc + "t", col2),
			alignment: "LEFT",
			color: this._menuColor
		};
		if (this.$shipHasHyperspaceMotor(p.dataKey) === true && this._OXPHyperdrives === false) {
			curChoices["13_HYPERDRIVE"] = {
				text: this.$padTextRight(expandDescription("[sc_config_hyperdrive_coupling]", { class: this.$equipmentItemInUse("hyperdrivecoupling", p).replace("EQ_HYPERDRIVE_COUPLING_TYPE", "") }), col1) +
					this.$padTextLeft(this.$equipmentSpaceInUse("hyperdrivecoupling", p).toFixed(1) + spc + "t", col2) +
					this.$padTextLeft(this.$equipmentWeightInUse("hyperdrivecoupling", p).toFixed(1) + spc + "t", col2),
				alignment: "LEFT",
				color: this._menuColor
			};
		}
		// do we have a wide font?
		var thrText = expandDescription("[sc_config_thrusters_full]");
		if (defaultFont.measureString("W") > 0.8) thrText = expandDescription("[sc_config_thrusters_short]");
		curChoices["14_THRUSTERS"] = {
			text: this.$padTextRight(expandDescription("[sc_config_thrusters_coupling]", { head: thrText, class: this.$equipmentItemInUse("thrusterscoupling", p).replace("EQ_THRUSTERS_COUPLING_TYPE", "") }), col1) +
				this.$padTextLeft(this.$equipmentSpaceInUse("thrusterscoupling", p).toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(this.$equipmentWeightInUse("thrusterscoupling", p).toFixed(1) + spc + "t", col2),
			alignment: "LEFT",
			color: this._menuColor
		};
		curChoices["14A_BOOSTERS"] = {
			text: this.$padTextRight(expandDescription("[sc_config_boosters_coupling]", { class: this.$equipmentItemInUse("boosterscoupling", p).replace("EQ_BOOSTERS_COUPLING_TYPE", "") }), col1) +
				this.$padTextLeft(this.$equipmentSpaceInUse("boosterscoupling", p).toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(this.$equipmentWeightInUse("boosterscoupling", p).toFixed(1) + spc + "t", col2),
			alignment: "LEFT",
			color: this._menuColor
		};
		curChoices["15_ENERGY"] = {
			text: this.$padTextRight(expandDescription("[sc_config_energy_coupling]", { class: this.$equipmentItemInUse("energycoupling", p).replace("EQ_ENERGYBANK_COUPLING_TYPE", "") }), col1) +
				this.$padTextLeft(this.$equipmentSpaceInUse("energycoupling", p).toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(this.$equipmentWeightInUse("energycoupling", p).toFixed(1) + spc + "t", col2),
			alignment: "LEFT",
			color: this._menuColor
		};
		curChoices["16_FRONTSHIELDS"] = {
			text: this.$padTextRight(expandDescription("[sc_config_frontshields_coupling]", { class: this.$equipmentItemInUse("frontshieldscoupling", p).replace("EQ_FORWARD_SHIELD_COUPLING_TYPE", "") }), col1) +
				this.$padTextLeft(this.$equipmentSpaceInUse("frontshieldscoupling", p).toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(this.$equipmentWeightInUse("frontshieldscoupling", p).toFixed(1) + spc + "t", col2),
			alignment: "LEFT",
			color: this._menuColor
		};
		curChoices["17_AFTSHIELDS"] = {
			text: this.$padTextRight(expandDescription("[sc_config_aftshields_coupling]", { class: this.$equipmentItemInUse("aftshieldscoupling", p).replace("EQ_AFT_SHIELD_COUPLING_TYPE", "") }), col1) +
				this.$padTextLeft(this.$equipmentSpaceInUse("aftshieldscoupling", p).toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(this.$equipmentWeightInUse("aftshieldscoupling", p).toFixed(1) + spc + "t", col2),
			alignment: "LEFT",
			color: this._menuColor
		};

		for (var i = 0; i < (pagesize - (12 - (this.$shipHasHyperspaceMotor(p.dataKey) === true && this._OXPHyperdrives === false ? 0 : 1))); i++) {
			curChoices["90_SPACER_" + i] = "";
		}

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

		if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];

		var opts = {
			screenID: "oolite-shipconfig-electrical-map",
			title: expandDescription("[sc_config_alias]"),
			allowInterrupt: interrupt,
			exitScreen: "GUI_SCREEN_EQUIP_SHIP",
			choices: curChoices,
			initialChoicesKey: def,
			message: text
		};

	}

	// view installed equipment
	if (this._display === 30) {
		text = expandDescription("[sc-spaceweight-profile]");
		text += this.$padTextRight("", col1) +
			this.$padTextLeft(expandDescription("[sc_config_equip]"), col2) +
			this.$padTextLeft(expandDescription("[sc_config_cargo]"), col2) + "\n";
		text += this.$padTextRight(expandDescription("[sc_config_item]"), col1) +
			this.$padTextLeft(expandDescription("[sc_equip_specs_space]"), col2) +
			this.$padTextLeft(expandDescription("[sc_equip_specs_space]"), col2) +
			this.$padTextLeft(expandDescription("[sc_equip_specs_weight]"), col2) + "\n\n";

		var eq = p.equipment;
		for (var i = 0; i < eq.length; i++) {
			var item = eq[i];
			if (this._ignoreEquip.indexOf(item.equipmentKey) >= 0) continue;
			var space = 0;
			var weight = 0;
			var cargos = 0;
			var lookup = this._equipmentMatrix[item.equipmentKey];

			if (lookup) {
				space = lookup[0];
				weight = lookup[1];
				cargos = item.requiredCargoSpace;
			} else {
				if (item.requiredCargoSpace === 0) {
					space = 1;
					weight = 1;
					cargos = 0;
				} else {
					space = 0;
					cargos = item.requiredCargoSpace;
					weight = item.requiredCargoSpace;
				}
			}
			if (item.isVisible && item.requiresEmptyPylon === false && (space > 0 || weight > 0)) {
				var dispname = item.name;
				if (item.equipmentKey === "EQ_PASSENGER_BERTH") {
					cargos *= p.passengerCapacity;
					weight *= p.passengerCapacity;
					dispname = expandDescription("[sc_config_berth]");
					if (p.passengerCapacity > 1) dispname = p.passengerCapacity + expandDescription("[sc_config_berths]");
				}
				list.push({
					eq: item.equipmentKey,
					space: space,
					weight: weight,
					cargo: cargos,
					name: dispname
				});
			}
		}
		// now add items not in the equipment list:
		if (p.forwardWeapon && p.forwardWeapon.equipmentKey != "EQ_WEAPON_NONE") {
			list.push({
				eq: p.forwardWeapon.equipmentKey,
				space: 0,
				weight: this.$weaponWeight(p.forwardWeapon.equipmentKey),
				cargo: 0,
				name: expandDescription("[sc_config_frontweapon]", { name: p.forwardWeapon.name })
			});
		}
		if (p.aftWeapon && p.aftWeapon.equipmentKey != "EQ_WEAPON_NONE") {
			list.push({
				eq: p.aftWeapon.equipmentKey,
				space: 0,
				weight: this.$weaponWeight(p.aftWeapon.equipmentKey),
				cargo: 0,
				name: expandDescription("[sc_config_aftweapon]", { name: p.aftWeapon.name })
			});
		}
		if (p.portWeapon && p.portWeapon.equipmentKey != "EQ_WEAPON_NONE") {
			list.push({
				eq: p.portWeapon.equipmentKey,
				space: 0,
				weight: this.$weaponWeight(p.portWeapon.equipmentKey),
				cargo: 0,
				name: expandDescription("[sc_config_portweapon]", { name: p.portWeapon.name })
			});
		}
		if (p.starboardWeapon && p.starboardWeapon.equipmentKey != "EQ_WEAPON_NONE") {
			list.push({
				eq: p.starboardWeapon.equipmentKey,
				space: 0,
				weight: this.$weaponWeight(p.starboardWeapon.equipmentKey),
				cargo: 0,
				name: expandDescription("[sc_config_starboardweapon]", { name: p.starboardWeapon.name })
			});
		}
		// any missiles?
		if (p.missileCapacity > 0) {
			var flag = false;
			try {
				var miss = p.missiles;
				flag = true;
			} catch (err) {
				if (this._debug) log(this.name, "!!ERROR: " + err);
			}
			if (flag === true) {
				for (var i = 0; i < miss.length; i++) {
					//if (this._debug) log(this.name, p.missileCapacity + " - " + i + ": " + miss[i].equipmentKey);
					if (this._ignoreEquip.indexOf(miss[i].equipmentKey) >= 0) continue;
					if (!this._equipmentMatrix[miss[i].equipmentKey]) {
						list.push({
							eq: miss[i].equipmentKey,
							space: 0,
							weight: 1,
							cargo: 0,
							name: (miss[i].name === expandDescription("[sc_config_missle_name]") ? expandDescription("[sc_config_missile_display]") : miss[i].name)
						});
					} else {
						list.push({
							eq: miss[i].equipmentKey,
							space: 0,
							weight: this._equipmentMatrix[miss[i].equipmentKey][1],
							cargo: 0,
							name: miss[i].name
						});
					}
				}
			}
		}

		// special items
		// LMSS weapons
		var lmss = worldScripts.LMSS_Core;
		if (lmss) {
			if (lmss._forwardAltKey != "EQ_WEAPON_NONE" && lmss._forwardAltKey != "") {
				list.push({
					eq: lmss._forwardAltKey,
					space: 0,
					weight: this.$weaponWeight(lmss._forwardAltKey),
					cargo: 0,
					name: expandDescription("[sc_config_lmss_secondary]", { name: EquipmentInfo.infoForKey(lmss._forwardAltKey).name })
				});
			}
			if (lmss._aftAltKey != "EQ_WEAPON_NONE" && lmss._aftAltKey != "") {
				list.push({
					eq: lmss._aftAltKey,
					space: 0,
					weight: this.$weaponWeight(lmss._aftAltKey),
					cargo: 0,
					name: expandDescription("[sc_config_lmss_secondary]", { name: EquipmentInfo.infoForKey(lmss._aftAltKey).name })
				});
			}
			if (lmss._portAltKey != "EQ_WEAPON_NONE" && lmss._portAltKey != "") {
				list.push({
					eq: lmss._portAltKey,
					space: 0,
					weight: this.$weaponWeight(lmss._portAltKey),
					cargo: 0,
					name: expandDescription("[sc_config_lmss_secondary]", { name: EquipmentInfo.infoForKey(lmss._portAltKey).name })
				});
			}
			if (lmss._starboardAltKey != "EQ_WEAPON_NONE" && lmss._starboardAltKey != "") {
				list.push({
					eq: lmss._starboardAltKey,
					space: 0,
					weight: this.$weaponWeight(lmss._starboardAltKey),
					cargo: 0,
					name: expandDescription("[sc_config_lmss_secondary]", { name: EquipmentInfo.infoForKey(lmss._starboardAltKey).name })
				});
			}
		}

		var cargo = 0;
		// add cargo weight
		if (this.$getCargoCapacity(p) > 0 && p.cargoList.length > 0) {
			for (var i = 0; i < p.cargoList.length; i++) {
				var itm = p.cargoList[i];
				switch (itm.unit) {
					case "t":
						cargo += itm.quantity;
						break;
					case "kg":
						cargo += (itm.quantity / 500);
						break;
					case "g":
						cargo += (itm.quantity / 500000);
						break;
				}
			}
		}

		var smuggling = worldScripts.Smugglers_Equipment;
		if (smuggling) {
			// add the weight of any cargo in the smuggling compartment
			var s_cargo = smuggling.$getSmugglingCargo();
			for (var i = 0; i < s_cargo.length; i++) {
				switch (s_cargo[i].unit) {
					case "t":
						cargo += s_cargo[i].quantity;
						break;
					case "kg":
						cargo += (s_cargo[i].quantity / 1000);
						break;
					case "g":
						cargo += (s_cargo[i].quantity / 1000000);
						break;
				}
			}
		}

		if (cargo > 0) {
			list.push({
				eq: "cargo",
				space: 0,
				weight: parseInt(cargo),
				cargo: cargo,
				name: expandDescription("[sc_config_cargo]")
			});
		}

		list.sort(compare);

		var maxpage = Math.ceil(list.length / (pagesize - 2));
		var end = ((this._page * (pagesize - 2)) + (pagesize - 2));
		if (end > list.length) end = list.length;
		for (var i = (this._page * (pagesize - 2)); i < end; i++) {
			text += this.$padTextRight(list[i].name, col1) +
				this.$padTextLeft(list[i].space.toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(list[i].cargo.toFixed(1) + spc + "t", col2) +
				this.$padTextLeft(list[i].weight.toFixed(1) + spc + "t", col2) + "\n";
			//itemcount += 1;
		}

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

		def = "98_EXIT";
		if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];


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

		var opts = {
			screenID: "oolite-shipconfig-installed-map",
			title: expandDescription("[sc_config_alias]"),
			allowInterrupt: interrupt,
			exitScreen: "GUI_SCREEN_EQUIP_SHIP",
			choices: curChoices,
			initialChoicesKey: def,
			message: text
		};

	}

	this.$addShipModelToScreen(opts);
	mission.runScreen(opts, this.$shipConfigScreenHandler, this);
	this.$finaliseShipModel();
}

//-------------------------------------------------------------------------------------------------------------
// returns the ship config page header
this.$pageHeader = function $pageHeader(pageType) {

	var p = player.ship;
	var shipspec = Ship.shipDataForKey(p.dataKey);
	var used = this.$calcEquipmentSpace(p);
	var cargoUsed = this.$cargoEquipmentSpaceAmount(p);
	var maxCargo = this.$cargoSpaceAvailable(p);
	var maxSpace = Math.ceil(this.$equipmentSpaceTotal(p) + maxCargo);
	var spc = String.fromCharCode(31) + String.fromCharCode(31) + String.fromCharCode(31);

	var text = "";

	var addtext = "";
	switch (pageType) {
		case "sell":
			if (used > maxSpace) {
				addtext = expandDescription("[sc-overload-sell]");
				cargoUsed = maxCargo;
			}
			break;
		case "store":
			if (used > maxSpace) {
				addtext = expandDescription("[sc-overload-store]");
				cargoUsed = maxCargo;
			}
			if (player.ship.dockedStation.isMainStation === true && worldScripts.EquipmentStorage.$storageSystemCount(galaxyNumber, system.ID) === 0) {
				addtext += expandDescription("[storage-deposit-required]", {
					fee: formatCredits(worldScripts.EquipmentStorage._establishmentFee, false, true)
				});
			}
			break;
		case "config":
			if (used > maxSpace) {
				addtext = expandDescription("[sc-overload-config]");
				cargoUsed = maxCargo;
			}
			if (this._freeUpgrades === true) addtext += expandDescription("[sc-free-upgrades]");
			break;
	}

	text += this.$padTextRight(expandDescription("[sc-header-cash]", {
		cash: formatCredits(player.credits, true, true)
	}), 18) + p.shipClassName + expandDescription("[sc-header-statistics]") + "\n";
	text += this.$padTextRight(expandDescription("[sc-header-equipspace]"), 11) + this.$padTextRight(used.toFixed(1) + spc + "t (" + maxSpace.toFixed(0) + spc + "t)", 7) +
		this.$padTextRight(expandDescription("[sc-header-thrust]"), 4) + this.$padTextRight(this.$calculatedValue("thrust", p).toFixed(1) + spc + "m/s²", 5) +
		"(" + parseInt(shipspec["thrust"]) + spc + "m/s²)\n";
	text += this.$padTextRight(expandDescription("[sc-header-cargo]"), 11) + this.$padTextRight(cargoUsed.toFixed(1) + spc + "t (" + maxCargo + spc + "t)", 7) +
		this.$padTextRight(expandDescription("[sc-header-speed]"), 4) + this.$padTextRight((this.$calculatedValue("speed", p) / 1000).toFixed(3) + spc + "LS", 5) +
		"(" + (parseInt(shipspec["max_flight_speed"]) / 1000).toFixed(3) + spc + "LS)\n";
	text += this.$padTextRight(expandDescription("[sc-header-weight]"), 11) + this.$padTextRight(this.$calcEquipmentWeight(p).toFixed(1) + spc + "t", 7) +
		this.$padTextRight(expandDescription("[sc-header-pitch]"), 4) + this.$padTextRight(this.$calculatedValue("pitch", p).toFixed(2), 5) +
		"(" + parseFloat(shipspec["max_flight_pitch"]).toFixed(2) + ")\n";
	text += this.$padTextRight(expandDescription("[sc-header-busovl]"), 11) + this.$padTextRight(this.$busOverloadChance(p).toFixed(0) + spc + "%", 7) +
		this.$padTextRight(expandDescription("[sc-header-roll]"), 4) + this.$padTextRight(this.$calculatedValue("roll", p).toFixed(2), 5) +
		"(" + parseFloat(shipspec["max_flight_roll"]).toFixed(2) + ")\n";
	text += addtext + "\n";

	return text;
}

//-------------------------------------------------------------------------------------------------------------
this.$shipConfigScreenHandler = function $shipConfigScreenHandler(choice) {

	if (!choice) return;

	var p = player.ship;
	var stn = p.dockedStation;

	this._lastChoice[this._display] = choice;

	if (choice.indexOf("01_EQUIP") >= 0) {
		var item = choice.substring(choice.indexOf("~") + 1);
		switch (item) {
			case "EQ_FUEL_INJECTION_REMOVE":
				for (var i = 0; i < this._fuelinjectors.length; i++) {
					if (p.equipmentStatus(this._fuelinjectors[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._fuelinjectors[i]) === "EQUIPMENT_DAMAGED") {
						this._source = "REMOVEITEM";
						this.$sellEquipmentScreenHandler("01_EQUIP~" + this._fuelinjectors[i]);
						break;
					}
				}
				break;
			case "EQ_FUEL_SCOOPS_REMOVE":
				for (var i = 0; i < this._fuelscoops.length; i++) {
					if (p.equipmentStatus(this._fuelscoops[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._fuelscoops[i]) === "EQUIPMENT_DAMAGED") {
						this._source = "REMOVEITEM";
						this.$sellEquipmentScreenHandler("01_EQUIP~" + this._fuelscoops[i]);
						break;
					}
				}
				break;
			case "EQ_HEAT_SHIELD_REMOVE":
				for (var i = 0; i < this._heatshields.length; i++) {
					if (p.equipmentStatus(this._heatshields[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._heatshields[i]) === "EQUIPMENT_DAMAGED") {
						this._source = "REMOVEITEM";
						this.$sellEquipmentScreenHandler("01_EQUIP~" + this._heatshields[i]);
						break;
					}
				}
				break;
			case "EQ_ARMOUR_FORWARD_REMOVE":
				for (var i = 0; i < this._frontarmour.length; i++) {
					if (p.equipmentStatus(this._frontarmour[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._frontarmour[i]) === "EQUIPMENT_DAMAGED") {
						this._source = "REMOVEITEM";
						this.$sellEquipmentScreenHandler("01_EQUIP~" + this._frontarmour[i]);
						break;
					}
				}
				break;
			case "EQ_ARMOUR_AFT_REMOVE":
				for (var i = 0; i < this._aftarmour.length; i++) {
					if (p.equipmentStatus(this._aftarmour[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._aftarmour[i]) === "EQUIPMENT_DAMAGED") {
						this._source = "REMOVEITEM";
						this.$sellEquipmentScreenHandler("01_EQUIP~" + this._aftarmour[i]);
						break;
					}
				}
				break;
			case "EQ_BOOSTERS_REMOVE":
				for (var i = 0; i < this._boosters.length; i++) {
					if (p.equipmentStatus(this._boosters[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._boosters[i]) === "EQUIPMENT_DAMAGED") {
						this._source = "REMOVEITEM";
						this.$sellEquipmentScreenHandler("01_EQUIP~" + this._boosters[i]);
						break;
					}
				}
				break;
			default:
				var info = EquipmentInfo.infoForKey(item);
				var priceFactor = this.$equipmentPriceFactor(p.shipClassName, this.$getShipMass(p)) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1);

				// scoops, injectors and heatshields don't have a price factor
				if (this._fuelscoops.indexOf(item) >= 0 || this._fuelinjectors.indexOf(item) >= 0 || this._heatshields.indexOf(item) >= 0) priceFactor = 1;

				if (this._freeUpgrades === true || (player.credits >= (info.price / 10) * priceFactor)) {
					this.$playSound("buy");
					// reset the holding dict
					this._current = {};
					p.awardEquipment(item);
					if (this._freeUpgrades === false) {
						player.credits -= (info.price / 10) * priceFactor;
						// give the player an email, if installed
						var ga = worldScripts.GalCopAdminServices;
						if (ga) {
							ga.playerBoughtEquipment(item);
						}
					}
					if (this._installationTime === true) {
						clock.addSeconds(600 + (info.price * priceFactor));
						// perform any callbacks that have been registered
						if (this._callbacks.length > 0) {
							for (var cb = 0; cb < this._callbacks.length; cb++) {
								this._callbacks[cb]();
							}
						}
					}
				} else {
					player.consoleMessage(expandDescription("[sc_config_no_cash]"));
				}
		}
	}

	if (choice === "01_ENGINES") {
		this._display = 1;
		this._page = 0;
	}
	if (choice === "02_HYPERDRIVE") {
		this._display = 2;
		this._page = 0;
	}
	if (choice === "03_THRUSTERS") {
		this._display = 3;
		this._page = 0;
	}
	if (choice === "03A_BOOSTERS") {
		this._display = 18;
		this._page = 0;
	}
	if (choice === "04_ENERGY") {
		this._display = 4;
		this._page = 0;
	}
	if (choice === "05_FRONTSHIELDS") {
		this._display = 5;
		this._page = 0;
	}
	if (choice === "06_AFTSHIELDS") {
		this._display = 6;
		this._page = 0;
	}
	if (choice === "07_FUELINJECTORS") {
		this._display = 7;
		this._page = 0;
	}
	if (choice === "08_FUELSCOOPS") {
		this._display = 20;
		this._page = 0;
	}
	if (choice === "09_HEATSHIELDS") {
		this._display = 8;
		this._page = 0;
	}
	if (choice === "10_ARMOUR_0FRONT") {
		this._display = 9;
		this._page = 0;
	}
	if (choice === "10_ARMOUR_1AFT") {
		this._display = 21;
		this._page = 0;
	}
	if (choice === "11_ELECTRICAL") {
		this._display = 10;
		this._page = 0;
	}

	if (choice === "11_BUS") {
		this._display = 11;
		this._page = 0;
	}
	if (choice === "12_ENGINES") {
		this._display = 12;
		this._page = 0;
	}
	if (choice === "13_HYPERDRIVE") {
		this._display = 13;
		this._page = 0;
	}
	if (choice === "14_THRUSTERS") {
		this._display = 14;
		this._page = 0;
	}
	if (choice === "14A_BOOSTERS") {
		this._display = 19;
		this._page = 0;
	}
	if (choice === "15_ENERGY") {
		this._display = 15;
		this._page = 0;
	}
	if (choice === "16_FRONTSHIELDS") {
		this._display = 16;
		this._page = 0;
	}
	if (choice === "17_AFTSHIELDS") {
		this._display = 17;
		this._page = 0;
	}

	if (choice === "97_EXIT") {
		this._display = 10;
		this._page = 0;
	}
	if (choice === "98_EXIT") {
		this._display = 0;
		this._page = 0;
	}

	if (choice === "95_NEXT") this._page += 1;
	if (choice === "96_PREV") this._page -= 1;

	if (choice === "96_VIEWEQUIP") {
		this._display = 30;
		this._page = 0;
	}

	if (choice === "97_SELL") {
		this._source = "CONFIGSCREEN";
		this.$sellEquipment();
		return;
	}
	if (choice === "97A_STORAGE") {
		this._source = "CONFIGSCREEN";
		worldScripts.EquipmentStorage.$storeEquipment();
		return;
	}
	if (choice != "99_EXIT") {
		this.$shipConfig();
	}
	//worldScripts.ShipConfiguration_F3HUDControl.guiScreenChanged();
}

//-------------------------------------------------------------------------------------------------------------
this.$sellEquipment = function $sellEquipment() {
	function compare(a, b) {
		return b.space - a.space;
	}

	var p = player.ship;
	var stn = p.dockedStation;
	var used = this.$calcEquipmentSpace(p);
	var maxSpace = Math.ceil(this.$equipmentSpaceTotal(p) + this.$cargoSpaceAvailable(p));
	var interrupt = true;
	var spc = String.fromCharCode(31) + String.fromCharCode(31) + String.fromCharCode(31);

	var text = "";
	var curChoices = {};
	var itemcount = 0;

	var pagesize = 15;
	if (this.$isBigGuiActive() === false) p.hudHidden = true;

	// display the list of options
	if (used > maxSpace) {
		// make sure we don't lock the player in during flight
		if (p.alertCondition === 0) {
			interrupt = false; // set to false to force the player to sell equipment before continuing
		}
		curChoices["98_SWITCH"] = {
			text: "[sc-change-config]",
			color: this._itemColor
		};
		curChoices["99_EXIT"] = {
			text: "[sc-return]",
			color: this._disabledColor,
			unselectable: true
		};
		pagesize -= 1;
	} else {
		curChoices["99_EXIT"] = {
			text: "[sc-return]",
			color: this._itemColor
		};
		this._initialSetup = false;
	}

	text += this.$pageHeader("sell");

	text += this.$padTextRight(expandDescription("[sc-selling-equipment]"), 16) + 
		this.$padTextLeft(expandDescription("[sc_config_equip]"), 4) + "\n";
	text += this.$padTextRight(expandDescription("[sc_equip_specs_equip]"), 16) +
		this.$padTextLeft(expandDescription("[sc_equip_specs_space]"), 4) +
		this.$padTextLeft(expandDescription("[sc_equip_specs_weight]"), 4) +
		this.$padTextLeft(expandDescription("[sc_config_refund]"), 8) + "\n\n";

	var eq = p.equipment;
	var list = [];
	var priceFactor = this.$equipmentPriceFactor(p.shipClassName, this.$getShipMass(p));
	var curr = this._currEquip;

	for (var i = 0; i < eq.length; i++) {
		var item = eq[i];
		// don't include "no sell" items
		if (this._noSell.indexOf(item.equipmentKey) >= 0) continue;
		// don't include any items in the ignore equipment list
		if (this._ignoreEquip.indexOf(item.equipmentKey) >= 0) continue;
		// don't include any items that have a zero cost
		if (item.cost === 0) continue;
		var space = 0;
		var weight = 0;
		var lookup = this._equipmentMatrix[item.equipmentKey];
		if (lookup) {
			space = lookup[0];
			weight = lookup[1];
		} else {
			if (item.requiredCargoSpace === 0) {
				space = 1;
				weight = 1;
			} else {
				space = 0;
				weight = item.requiredCargoSpace;
			}
		}
		var colr = this._menuColor;
		var dam = 1;
		if (p.equipmentStatus(item.equipmentKey) === "EQUIPMENT_DAMAGED") {
			colr = this._damagedColor;
			dam = 0.5;
		}
		// special case for armour
		if (this._frontarmour.indexOf(item.equipmentKey) >= 0 && p.script._armourFront < 100) {
			colr = this._damagedColor;
			dam = 0.5;
		}
		if (this._aftarmour.indexOf(item.equipmentKey) >= 0 && p.script._armourAft < 100) {
			colr = this._damagedColor;
			dam = 0.5;
		}

		if (item.isVisible && item.requiresEmptyPylon === false && (space > 0 || weight > 0)) {
			// any items in the negotiate list will show as "???" in the cost column
			// if the player chooses to sell this item he will have to negotiate a price
			var loop = 1;
			// special case for passenger berths - only 1 item is in the equipment list, but you could have multiple installed
			if (item.equipmentKey === "EQ_PASSENGER_BERTH") loop = p.passengerCapacity;

			var pf = stn.equipmentPriceFactor;
			// these items don't use the price factoring
			if (this._priceFactor.indexOf(item.equipmentKey) >= 0) {
				pf = priceFactor;
			}
			var idx = curr.indexOf(item.equipmentKey);
			var disabled = "";
			if (item.effectiveTechLevel > stn.equivalentTechLevel) { disabled = expandDescription("[sc_config_disabled_lowtl]"); colr = this._disabledColor; }
			if (this.$equipmentIsRequired(item.equipmentKey) === true) { disabled = expandDescription("[sc_config_disabled_required]"); colr = this._disabledColor; }

			for (var j = 1; j <= loop; j++) {
				list.push({
					eq: item.equipmentKey,
					space: space,
					weight: weight,
					cost: (this._sellNegotiate.indexOf(item.equipmentKey) >= 0 ? "???" : (item.price / 10) * dam * (idx >= 0 ? this._refundPct : 1) * pf),
					color: colr,
					name: (item.equipmentKey === "EQ_PASSENGER_BERTH" ? expandDescription("[sc_config_berth]") : item.name),
					section: "",
					disabled: disabled
				});
			}
		}
	}
	// laser weapons
	colr = this._menuColor;
	var lmss = worldScripts.LMSS_Core;
	var section = expandDescription("[sc_config_weapon_points]").split("|");
	for (var i = 0; i < 7; i++) {
		var key = "";
		switch (i) {
			case 0:
				key = p.forwardWeapon.equipmentKey;
				break;
			case 1:
				key = p.aftWeapon.equipmentKey;
				break;
			case 2:
				key = p.portWeapon.equipmentKey;
				break;
			case 3:
				key = p.starboardWeapon.equipmentKey;
				break;
			case 4:
				if (lmss) key = lmss._forwardAltKey;
				break;
			case 5:
				if (lmss) key = lmss._aftAltKey;
				break;
			case 6:
				if (lmss) key = lmss._portAltKey;
				break;
			case 7:
				if (lmss) key = lmss._starboardAltKey;
				break;
		}
		if (key !== "" && key !== "EQ_WEAPON_NONE") {
			var item = EquipmentInfo.infoForKey(key);
			var space = 0;
			var weight = 0;

			var lookup = this._equipmentMatrix[item.equipmentKey];
			if (lookup) {
				space = parseFloat(lookup[0]);
				weight = parseFloat(lookup[1]);
			} else {
				space = 0;
				weight = 1;
			}

			if (item.effectiveTechLevel <= stn.equivalentTechLevel) {
				list.push({
					eq: item.equipmentKey,
					space: space,
					weight: weight,
					cost: (item.price / 10),
					color: colr,
					name: item.name + " (" + section[i] + ")",
					section: i,
					disabled: ""
				});
			}
		}
	}

	if (list.length > 0) {
		list.sort(compare);

		var maxpage = Math.ceil(list.length / pagesize);
		if (maxpage < (this._page + 1)) this._page -= 1;
		var end = ((this._page * 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._page * pagesize); i < end; i++) {
			curChoices["01_EQUIP-" + (i < 10 ? "0" : "") + i + "~" + list[i].eq + (list[i].section !== "" ? "|" + list[i].section : "")] = {
				text: this.$padTextRight(list[i].name, 16) +
					this.$padTextLeft(list[i].space.toFixed(1) + spc + "t", 4) +
					this.$padTextLeft(list[i].weight.toFixed(1) + spc + "t", 4) +
					(list[i].disabled === "" ? (list[i].cost === "???" ? this.$padTextLeft("???", 8) :
						this.$padTextLeft(formatCredits((list[i].cost), true, true), 8)) : this.$padTextLeft(list[i].disabled, 8)), //* stn.equipmentPriceFactor
				alignment: "LEFT",
				color: list[i].color,
				unselectable: (list[i].disabled != "" ? true : false)
			};
			itemcount += 1;
		}
		for (var i = 0; i < ((pagesize + 1) - itemcount); i++) {
			curChoices["90_SPACER_" + i] = "";
		}
	} else {
		text += expandDescription("[sc-equipment-none-to-sell]");
	}

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

	var def = "99_EXIT";
	if (this._lastChoice[20] != "") def = this._lastChoice[20];

	var opts = {
		screenID: "oolite-shipconfig-sell-map",
		title: expandDescription("[sc_sellnegotiate_title]"),
		allowInterrupt: interrupt,
		exitScreen: this._sellEquipExitScreen,
		choices: curChoices,
		initialChoicesKey: def,
		message: text
	};

	this.$addShipModelToScreen(opts);
	mission.runScreen(opts, this.$sellEquipmentScreenHandler, this);
	this.$finaliseShipModel();
}

//-------------------------------------------------------------------------------------------------------------
this.$sellEquipmentScreenHandler = function $sellEquipmentScreenHandler(choice) {
	if (!choice) return;

	var p = player.ship;
	var stn = p.dockedStation;

	if (this._source != "REMOVEITEM") this._lastChoice[20] = choice;

	if (choice.indexOf("01_EQUIP") >= 0) {
		var item = choice.substring(choice.indexOf("~") + 1);
		var section = "";
		// check for a laser position
		if (item.indexOf("|") >= 0) {
			section = item.split("|")[1];
			item = item.split("|")[0];
		}

		var info = EquipmentInfo.infoForKey(item);
		if (section === "") {
			if (this._sellNegotiate.indexOf(item) >= 0) {
				var cost = (info.price / 10) * this._refundPct;
				if (p.equipmentStatus(item) === "EQUIPMENT_DAMAGED") cost *= 0.5;
				worldScripts.ShipConfiguration_SellNegotiate.$displayInitialScreen(item, cost);
				return;
			}
			var dam = p.equipmentStatus(item);

			// special case for passenger berths
			if (item === "EQ_PASSENGER_BERTH") {
				var creds = player.credits;
				p.awardEquipment("EQ_PASSENGER_BERTH_REMOVAL");
				p.credits = creds;
			} else {
				p.removeEquipment(item);
			}
		} else {
			var lmss = worldScripts.LMSS_Core;
			switch (section) {
				case "0":
					p.forwardWeapon = "EQ_WEAPON_NONE";
					break;
				case "1":
					p.aftWeapon = "EQ_WEAPON_NONE";
					break;
				case "2":
					p.portWeapon = "EQ_WEAPON_NONE";
					break;
				case "3":
					p.starboardWeapon = "EQ_WEAPON_NONE"
					break;
				case "4":
					lmss._forwardAltKey = "EQ_WEAPON_NONE";
					p.removeEquipment("EQ_LMSS_FRONT_WEAPON");
					break;
				case "5":
					lmss._aftAltKey = "EQ_WEAPON_NONE";
					p.removeEquipment("EQ_LMSS_AFT_WEAPON");
					break;
				case "6":
					lmss._portAltKey = "EQ_WEAPON_NONE";
					p.removeEquipment("EQ_LMSS_PORT_WEAPON");
					break;
				case "7":
					lmss._starboardAltKey = "EQ_WEAPON_NONE";
					p.removeEquipment("EQ_LMSS_STARBOARD_WEAPON");
					break;
			}
			if (lmss) lmss.$updateManifest();
			var dam = "EQUIPMENT_OK"; // lasers can't be damaged
		}
		// is this new or used? idx === -1 means new, otherwise any number >= 0 means used
		var idx = this._currEquip.indexOf(item);
		if (idx >= 0) this._currEquip.splice(idx, 1);

		var doRefund = true;
		// reset the holding dict
		this._current = {};
		if (this._freeUpgrades === true) {
			// don't give the player a refund for these, otherwise they can make money by buying and selling the same thing
			if (this._fuelinjectors.indexOf(item) >= 0 ||
				this._fuelscoops.indexOf(item) >= 0 ||
				this._heatshields.indexOf(item) >= 0 ||
				this._armour.indexOf(item) >= 0 ||
				this._boosters.indexOf(item) >= 0)
				doRefund = false;
		}
		var priceFactor = stn.equipmentPriceFactor;
		if (this._priceFactor.indexOf(item) >= 0) {
			priceFactor = this.$equipmentPriceFactor(p.shipClassName, this.$getShipMass(p));
		}
		// lasers get a full refund, to match what happens when you do a buy/replace
		var refund = (info.price / 10) * (info.equipmentKey.indexOf("EQ_WEAPON") >= 0 || (idx === -1 ? 1 : this._refundPct)) * priceFactor;
		if (dam === "EQUIPMENT_DAMAGED") refund *= 0.5;
		if (doRefund === true) player.credits += refund;

		// give the player an email, if installed
		var ga = worldScripts.GalCopAdminServices;
		if (ga && doRefund === true) {
			ga._oldCredits = player.credits - (doRefund === true ? refund : 0);
			ga.playerBoughtEquipment(item);
		}
		this.$addEquipmentSpaceItem(p);
		this.$playSound("sell");
	}

	if (choice === "95_NEXT") this._page += 1;
	if (choice === "96_PREV") this._page -= 1;
	if (choice === "98_SWITCH") {
		this._source = "";
		this.$shipConfig();
		return;
	}

	if (this._source === "REMOVEITEM") return;

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

	if (choice === "99_EXIT" && this._source === "CONFIGSCREEN") {
		this._source = "";
		this.$shipConfig();
	}
	worldScripts.ShipConfiguration_F3HUDControl.guiScreenChanged();
}

//-------------------------------------------------------------------------------------------------------------
// add the ship model, or an overlay, to the options for a mission screen
this.$addShipModelToScreen = function $addShipModelToScreen(opts) {
	var p = player.ship;
	if (this._shipModel === true) {
		opts["model"] = "[" + p.dataKey + "]";
		opts["modelPersonality"] = p.entityPersonality;
		opts["spinModel"] = false;
		if (p.hudHidden === true || this.$isBigGuiActive() === true) {
			opts["overlay"] = {
				name: "shipconfig_mask.png",
				height: 546
			};
		} else {
			opts["overlay"] = {
				name: "shipconfig_mask_sml.png",
				height: 546
			};
		}
	} else {
		opts["overlay"] = {
			name: "shipconfig_rocket.png",
			height: 546
		};
	}
}

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

	if (this._shipModel === false) return;

	var m = mission.displayModel;
	// rotate model for a better view
	if (m) {
		// if gallery has been loaded and used, remove the frame callback
		var w = worldScripts.gallery;
		if (w && isValidFrameCallback(w.$GalleryFCB)) removeFrameCallback(w.$GalleryFCB);

		var zoom_factor = 3.6;
		if (this._shipModel) {
			if (this._zoomOverride[player.ship.shipClassName]) zoom_factor = this._zoomOverride[player.ship.shipClassName];
		}
		// zoom and rotate the image
		m.position = Vector3D(0, 0, m.collisionRadius * zoom_factor);
		m.orientation = m.orientation.rotate([0, 0, 0]);
		m.orientation = m.orientation.rotateZ(Math.PI * 1.2);
		m.orientation = m.orientation.rotateX(-1.1);
	}
}

//=============================================================================================================
// calculation/general functions

//-------------------------------------------------------------------------------------------------------------
// attach our equipment processing scripts to the player ship script object
this.$setUpScriptConfig = function $setUpScriptConfig() {
	var p = player.ship;
	if (!p.script.$equipmentDamaged_Event) p.script.$equipmentDamaged_Event = this.$equipmentDamaged_Event;
	if (!p.script.$awaitEquipmentDamaged) p.script.$awaitEquipmentDamaged = this.$awaitEquipmentDamaged;
	if (!p.script.$checkRemainingEnergy) p.script.$checkRemainingEnergy = this.$checkRemainingEnergy;
	if (p.script.hasOwnProperty("_damagedItems") === false) p.script._damagedItems = []; // list of damaged items that required config adjustment
	if (p.script.hasOwnProperty("_checkForDamage") === false) p.script._checkForDamage = null; // timer used to call "$awaitEquipmentDamaged" to check the "damagedItems" array
}

//-------------------------------------------------------------------------------------------------------------
// this script should be attached to a ship.script object, including the player ship, for use inside the ship in question
this.$equipmentDamaged_Event = function $equipmentDamaged_Event(equipmentKey) {

	var isPlayer = this.ship.isPlayer;
	var sc = worldScripts.ShipConfiguration_Core;

	if (isPlayer && sc._damaging === true) return;

	// armour handled in it's own script
	if (sc._armour.indexOf(equipmentKey) >= 0) return;

	if (isPlayer) sc._damaging = true;

	if (equipmentKey === "EQ_HEAT_SINK") {
		// do we have any working heat sinks?
		if (this.ship.equipmentStatus("EQ_HEAT_SINK", true)["EQUIPMENT_OK"] == 0) {
			this.ship.removeEquipment("EQ_HEAT_SINK_CONTROL");
			this.ship.removeEquipment("EQ_HEAT_SINK_CONTROL_PASSIVE");
		}
	}

	if (!this.ship.script._damagedItems) this.ship.script._damagedItems = [];

	// when engines are damaged, reduce maxThrust/maxSpeed
	// when thrusters are damaged, reduce maxPitch and maxRoll
	// when hyperdrive is damaged, disable hyperjumps
	// when energy banks are disabled, stop recharging, start a slow energy leak
	// when shields are damaged, reduce to 0
	// when heat shield is damaged, reduce heat shielding on ship

	if (sc._engines.indexOf(equipmentKey) >= 0) {
		// damage the injectors before the engine
		if (this.ship.equipmentStatus(sc.$equipmentItemInUse("fuelinjectors", this.ship)) === "EQUIPMENT_OK") {
			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
			if (isPlayer) sc._damaging = false;
			this.ship.setEquipmentStatus(sc.$equipmentItemInUse("fuelinjectors", this.ship), "EQUIPMENT_DAMAGED");
			return;
		}
		this.ship.script._damagedItems.push(equipmentKey);
		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
		}
	}
	if (sc._thrusters.indexOf(equipmentKey) >= 0) {
		this.ship.script._damagedItems.push(equipmentKey);
		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
		}
	}
	if (sc._energy.indexOf(equipmentKey) >= 0) {
		// damage extra energy units before base energy units
		if (this.ship.equipmentStatus("EQ_ENERGY_GRID") === "EQUIPMENT_OK") {
			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
			this.ship.setEquipmentStatus("EQ_ENERGY_GRID", "EQUIPMENT_DAMAGED");
			if (isPlayer) {
				sc.$playSound("explosion");
				sc._damaging = false;
			}
			return;
		}
		if (this.ship.equipmentStatus("EQ_NAVAL_GRID") === "EQUIPMENT_OK") {
			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
			this.ship.setEquipmentStatus("EQ_NAVAL_GRID", "EQUIPMENT_DAMAGED");
			if (isPlayer) {
				sc.$playSound("explosion");
				sc._damaging = false;
			}
			return;
		}
		if (this.ship.equipmentStatus("EQ_NAVAL_ENERGY_UNIT") === "EQUIPMENT_OK") {
			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
			this.ship.setEquipmentStatus("EQ_NAVAL_ENERGY_UNIT", "EQUIPMENT_DAMAGED");
			if (isPlayer) {
				sc.$playSound("explosion");
				sc._damaging = false;
			}
			return;
		}
		if (this.ship.equipmentStatus("EQ_ENERGY_UNIT") === "EQUIPMENT_OK") {
			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
			this.ship.setEquipmentStatus("EQ_ENERGY_UNIT", "EQUIPMENT_DAMAGED");
			if (isPlayer) {
				sc.$playSound("explosion");
				sc._damaging = false;
			}
			return;
		}
		this.ship.script._damagedItems.push(equipmentKey);
		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
		}
	}

	if (sc._frontshields.indexOf(equipmentKey) >= 0 || sc._aftshields.indexOf(equipmentKey) >= 0 || sc._shieldEquipment.indexOf(equipmentKey) >= 0) {
		// damage the naval grid, shield booster and mil shield enhancements first
		/* if (this.ship.equipmentStatus("EQ_ENERGY_GRID") === "EQUIPMENT_OK") {
			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
			this.ship.setEquipmentStatus("EQ_ENERGY_GRID", "EQUIPMENT_DAMAGED");
			if (isPlayer) {
				sc.$playSound("explosion");
				sc._damaging = false;
			}
			return;
		}
		if (this.ship.equipmentStatus("EQ_NAVAL_GRID") === "EQUIPMENT_OK") {
			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
			this.ship.setEquipmentStatus("EQ_NAVAL_GRID", "EQUIPMENT_DAMAGED");
			if (isPlayer) {
				sc.$playSound("explosion");
				sc._damaging = false;
			}
			return;
		}
		if (this.ship.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
			this.ship.setEquipmentStatus("EQ_NAVAL_SHIELD_BOOSTER", "EQUIPMENT_DAMAGED");
			if (isPlayer) {
				sc.$playSound("explosion");
				sc._damaging = false;
			}
			return;
		}
		if (this.ship.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
			this.ship.setEquipmentStatus("EQ_SHIELD_BOOSTER", "EQUIPMENT_DAMAGED");
			if (isPlayer) {
				sc.$playSound("explosion");
				sc._damaging = false;
			}
			return;
		} */
		this.ship.script._damagedItems.push(equipmentKey);
		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
		}
	}
	if (sc._heatshields.indexOf(equipmentKey) >= 0) {
		this.ship.script._damagedItems.push(equipmentKey);
		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
		}
	}
	// special case for when another OXP causes damage to heat shield
	if (equipmentKey === "EQ_HEAT_SHIELD") {
		if (isPlayer) sc._damaging = false;
		this.ship.setEquipmentStatus(sc.$equipmentItemInUse("heatshields", this.ship), "EQUIPMENT_DAMAGED");
		return;
	}
	if (sc._fuelinjectors.indexOf(equipmentKey) >= 0) {
		this.ship.script._damagedItems.push(equipmentKey);
		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
		}
	}
	// special case for when another OXP causes damage to fuel injectors
	if (equipmentKey === "EQ_FUEL_INJECTION") {
		if (isPlayer) sc._damaging = false;
		this.ship.setEquipmentStatus(sc.$equipmentItemInUse("fuelinjectors", this.ship), "EQUIPMENT_DAMAGED");
		return;
	}
	if (sc._fuelscoops.indexOf(equipmentKey) >= 0) {
		this.ship.script._damagedItems.push(equipmentKey);
		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
		}
	}
	// special case for when another OXP causes damage to fuel scoops
	if (equipmentKey === "EQ_FUEL_SCOOPS") {
		if (isPlayer) sc._damaging = false;
		this.ship.setEquipmentStatus(sc.$equipmentItemInUse("fuelscoops", this.ship), "EQUIPMENT_DAMAGED");
		return;
	}
	if (sc._hyperdrive.indexOf(equipmentKey) >= 0) {
		this.ship.script._damagedItems.push(equipmentKey);
		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
		}
	}

	if (isPlayer) sc._damaging = false;
}

//-------------------------------------------------------------------------------------------------------------
// this script should be attached to a ship.script object, for use inside the ship in question
this.$awaitEquipmentDamaged = function $awaitEquipmentDamaged() {

	if (this.ship == null) return;
	if (!this.ship.script) return;

	//var p = player.ship;
	var sc = worldScripts.ShipConfiguration_Core;
	var isPlayer = this.ship.isPlayer;

	delete this.ship.script._checkForDamage;
	var i = this.ship.script._damagedItems.length;
	while (i--) {
		// make sure the equipment didn't get repaired by the armour script
		if (this.ship.equipmentStatus(this.ship.script._damagedItems[i]) === "EQUIPMENT_DAMAGED") {
			if (isPlayer) sc.$playSound("explosion");
			if (sc._engines.indexOf(this.ship.script._damagedItems[i]) >= 0) {
				this.ship.maxSpeed = this.ship.maxSpeed * 0.67;
				this.ship.maxThrust = this.ship.maxThrust * 0.67;
				this.ship.thrust = this.ship.maxThrust;
				if (isPlayer) player.consoleMessage(expandDescription("[sc_config_warning_engines]"), 4);
			}
			if (sc._thrusters.indexOf(this.ship.script._damagedItems[i]) >= 0) {
				this.ship.maxPitch = this.ship.maxPitch * 0.75;
				this.ship.maxRoll = this.ship.maxRoll * 0.75;
				if (isPlayer) player.consoleMessage(expandDescription("[sc_config_warning_thrusters]"), 4);
			}
			if (sc._boosters.indexOf(this.ship.script._damagedItems[i]) >= 0) {
				this.ship.script._boosterHeatPoint = 0;
				this.ship.maxSpeed = sc.$calculatedValue("speed", this.ship);
				this.ship.maxThrust = sc.$calculatedValue("thrust", this.ship);
				this.ship.thrust = this.ship.maxThrust;
				this.ship.maxPitch = sc.$calculatedValue("pitch", this.ship);
				this.ship.maxRoll = sc.$calculatedValue("roll", this.ship);
				this.ship.maxYaw = sc.$calculatedValue("yaw", this.ship);
				if (isPlayer) player.consoleMessage(expandDescription("[sc_config_warning_boosters]"), 4);
			}
			if (sc._energy.indexOf(this.ship.script._damagedItems[i]) >= 0) {
				this.ship.script._energyRechargeRate_Stored = this.ship.energyRechargeRate;
				this.ship.energyRechargeRate = 0;
				if (isPlayer) player.consoleMessage(expandDescription("[sc_config_warning_energy]"), 4);
				if (this.ship.alertCondition != 0) {
					if (!this.ship.script._energyTimer || !this.ship.script._energyTimer.isRunning) {
						this.ship.script._energyTimer = new Timer(this, this.ship.script.$checkRemainingEnergy, 1, 1);
					}
				}
			}
			if (sc._frontshields.indexOf(this.ship.script._damagedItems[i]) >= 0) {
				// should be compatible with naval grid - we are damaging those items before allowing damage to shields
				// so NG should have reset the recharge rate by this point
				//this.ship.script._forwardShieldRechargeRate_Stored = this.ship.forwardShieldRechargeRate;
				//this.ship.forwardShieldRechargeRate = -0.5;
				sc.$updateShieldValues(this.ship);
				if (isPlayer) {
					player.consoleMessage(expandDescription("[sc_config_warning_frontshield]"), 4);
					sc.$disableShieldOXPs();
				}
			}
			if (sc._aftshields.indexOf(this.ship.script._damagedItems[i]) >= 0) {
				//this.ship.script._aftshieldsRechargeRate_Stored = this.ship.aftShieldRechargeRate;
				//this.ship.aftShieldRechargeRate = -0.5;
				sc.$updateShieldValues(this.ship);
				if (isPlayer) {
					player.consoleMessage(expandDescription("[sc_config_warning_aftshield]"), 4);
					sc.$disableShieldOXPs();
				}
			}
			if (sc._shieldEquipment.indexOf(this.ship.script._damagedItems[i]) >= 0) {
				sc.$updateShieldValues(this.ship);
			}
			if (sc._fuelinjectors.indexOf(this.ship.script._damagedItems[i]) >= 0) {
				if (isPlayer) player.consoleMessage(expandDescription("[sc_config_warning_injectors]"), 4);
				if (isPlayer) sc._damaging = true;
				this.ship.setEquipmentStatus("EQ_FUEL_INJECTION", "EQUIPMENT_DAMAGED");
				if (isPlayer) sc._damaging = false;
			}
			if (sc._fuelscoops.indexOf(this.ship.script._damagedItems[i]) >= 0) {
				if (isPlayer) player.consoleMessage(expandDescription("[sc_config_warning_scoops]"), 4);
				if (isPlayer) sc._damaging = true;
				this.ship.setEquipmentStatus("EQ_FUEL_SCOOPS", "EQUIPMENT_DAMAGED");
				if (isPlayer) sc._damaging = false;
			}
			if (sc._heatshields.indexOf(this.ship.script._damagedItems[i]) >= 0) {
				// reset heat shield strength back to the baseline for the ship
				var shipspec = Ship.shipDataForKey(this.ship.dataKey);
				this.ship.heatInsulation = parseFloat((shipspec["heat_insulation"] ? shipspec["heat_insulation"] : 1.0));
				this.ship.script._heat_sink_factor = parseFloat(sc._defaultHeatShieldHSFactor);
				if (isPlayer) player.consoleMessage(expandDescription("[sc_config_warning_heatshield]"), 4);
				if (isPlayer) sc._damaging = true;
				this.ship.setEquipmentStatus("EQ_HEAT_SHIELD", "EQUIPMENT_DAMAGED");
				if (isPlayer) sc._damaging = false;
			}
			if (sc._hyperdrive.indexOf(this.ship.script._damagedItems[i]) >= 0) {
				this.ship.hyperdriveSpinTime = 50;
				if (isPlayer) player.consoleMessage(expandDescription("[sc_config_warning_hyperdrive]"), 4);
				if (Math.random() < 0.34) {
					this.ship.fuelLeakRate = 0.25;
					if (isPlayer) {
						sc.$playSound("leak");
						player.consoleMessage(expandDescription("[sc_config_fuelleak]"), 3);
					}
				}
			}
		}
		this.ship.script._damagedItems.splice(i, 1);
	}

	// if something got damaged while we were processing, set the timer up again
	if (this.ship.script._damagedItems.length > 0) {
		this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
	}
}

//-------------------------------------------------------------------------------------------------------------
// this script should be attached to a ship.script object, for use inside the ship in question
this.$checkRemainingEnergy = function $checkRemainingEnergy() {
	// make sure we're still attached to a valid entity
	if (this.ship.isValid === false || this.ship.isInSpace === false) {
		if (this.ship.script) {
			this.ship.script._energyTimer.stop();
			delete this.ship.script._energyTimer;
		}
		return;
	}
	this.ship.energy -= 1;
	this.ship.script._counter += 1;
	if (this.ship.script._counter === 30) {
		if (this.ship.isPlayer) player.consoleMessage(expandDescription("[sc_config_energy_low]"), 4);
		this.ship.script._counter = 0;
	}
	if (this.ship.energy < 30) {
		this.ship.script._energyTimer.stop();
		delete this.ship.script._energyTimer;
		this.ship.energyRechargeRate = 0;
		if (this.ship.isPlayer) player.consoleMessage(expandDescription("[sc_config_energy_critical]"), 4);
	}
}

//-------------------------------------------------------------------------------------------------------------
// turn off shield cycler and shield equaliser, if installed
this.$disableShieldOXPs = function $disableShieldOXPs() {
	var p = player.ship;
	// disables Shield Cycler if fitted and active to prevent catastrophic shield/energy loss.
	if (p.equipmentStatus("EQ_SC_SHIELD_CYCLER_INTERNAL") === "EQUIPMENT_OK" && !worldScripts["Shield Cycler"].deactivated) {
		if (worldScripts["Shield Cycler"]._sc_stop()) {
			this._stoppedSC = true;
			player.consoleMessage(expandDescription("[sc_config_shieldcycler_off]"), 4);
		}
	}
	// disables Shield Equaliser (and Capacitors) if fitted to prevent catastrophic Shield Loss.
	if (p.equipmentStatus("EQ_SHIELD_EQUALIZER") === "EQUIPMENT_OK" && worldScripts["shieldequalizercapacitors"].shieldCheckTimer.isRunning) {
		worldScripts["shieldequalizercapacitors"].shieldCheckTimer.stop();
		this._stoppedSEC = true;
		player.consoleMessage(expandDescription("[sc_config_shieldequalizer_off]"), 4);
	}
}

//-------------------------------------------------------------------------------------------------------------
// turn on shield cycler and shield equaliser, if installed
this.$enableShieldOXPs = function $enableShieldOXPs() {
	var p = player.ship;
	if (this._stoppedSC && worldScripts["Shield Cycler"].deactivated) {
		if (worldScripts["Shield Cycler"]._sc_start()) {
			delete this._stoppedSC;
			if (p.equipmentStatus("EQ_SC_SHIELD_CYCLER_INTERNAL") === "EQUIPMENT_OK") {
				player.consoleMessage(expandDescription("[sc_config_shieldcycler_on]"), 4);
			}
		}
	}
	if (this._stoppedSEC && worldScripts["shieldequalizercapacitors"].shieldCheckTimer) {
		worldScripts["shieldequalizercapacitors"].shieldCheckTimer.start();
		delete this._stoppedSEC;
		if (player.ship.equipmentStatus("EQ_SHIELD_EQUALIZER") === "EQUIPMENT_OK") {
			player.consoleMessage(expandDescription("[sc_config_shieldequalizer_on]"), 4);
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$stopTimers = function $stopTimers() {
	var p = player.ship;
	if (p && p.script && p.script._energyTimer && p.script._energyTimer.isRunning) {
		p.script._energyTimer.stop();
		delete p.script._energyTimer;
	}
	if (this._busOverloadResetTimer && this._busOverloadResetTimer.isRunning) {
		this._busOverloadResetTimer.stop();
	}
	delete this._busOverloadResetTimer;
}

//-------------------------------------------------------------------------------------------------------------
// checks for an overload state and then sets up the flags if overloaded
this.$checkForOverload = function $checkForOverload() {
	var p = player.ship;
	var equipSpace = this.$equipmentSpaceTotal(p);
	var cargoSpace = this.$cargoSpaceAvailable(p); // + this.$cargoEquipmentSpaceAmount(p));

	var used = this.$calcEquipmentSpace(p);
	if (used > equipSpace) {
		// allocate cargo space to equipment space
		var diff = parseInt(used - equipSpace);
		if (diff > cargoSpace) {
			// we don't have space for this
			// switch into "overloaded" mode so the player can choose what item to remove
			this._initialSetup = true;
			this._promptPlayer = true;
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// returns true if the player has an alternative armour installed, otherwise false
this.$playerHasOtherArmour = function $playerHasOtherArmour() {
	var p = player.ship;
	var result = false;
	for (var i = 0; i < this._altArmour.length; i++) {
		var sts = p.equipmentStatus(this._altArmour[i]);
		if (sts === "EQUIPMENT_OK" || sts === "EQUIPMENT_DAMAGED") result = true;
	}
	return result;
}

//-------------------------------------------------------------------------------------------------------------
// calculate how much bus overload exists on the ship
this.$busOverloadChance = function $busOverloadChance(ship) {

	if (!ship) return 0;

	// work out if anything is over the coupling/bus class
	var total = 0;
	var eq = 0;
	var check = 0;

	var bus = this.$equipmentCouplingLevelInUse("electricalbus", ship);

	eq = parseInt(this.$equipmentCouplingLevelInUse("engines", ship));
	check = parseInt(this.$equipmentCouplingRequired("engines", this.$equipmentItemInUse("engines", ship), ship));
	if ((check - eq) > 0) total += ((check - eq) * 2);
	if ((eq - bus) > 0) total += (eq - bus);

	// fi use the engines power coupling
	eq = parseInt(this.$equipmentCouplingLevelInUse("fuelinjectors", ship));
	check = parseInt(this.$equipmentCouplingRequired("fuelinjectors", this.$equipmentItemInUse("fuelinjectors", ship), ship));
	if ((check - eq) > 0) total += ((check - eq) * 2);
	if ((eq - bus) > 0) total += (eq - bus);

	if (this.$shipHasHyperspaceMotor(ship.dataKey) === true && this._OXPHyperdrives === false) {
		eq = parseInt(this.$equipmentCouplingLevelInUse("hyperdrive", ship));
		check = parseInt(this.$equipmentCouplingRequired("hyperdrive", this.$equipmentItemInUse("hyperdrive", ship), ship));
		if ((check - eq) > 0) total += ((check - eq) * 2);
		if ((eq - bus) > 0) total += (eq - bus);
	}

	eq = parseInt(this.$equipmentCouplingLevelInUse("thrusters", ship));
	check = parseInt(this.$equipmentCouplingRequired("thrusters", this.$equipmentItemInUse("thrusters", ship), ship));
	if ((check - eq) > 0) total += ((check - eq) * 2);
	if ((eq - bus) > 0) total += (eq - bus);

	eq = parseInt(this.$equipmentCouplingLevelInUse("boosters", ship));
	check = parseInt(this.$equipmentCouplingRequired("boosters", this.$equipmentItemInUse("boosters", ship), ship));
	if ((check - eq) > 0) total += ((check - eq) * 2);
	if ((eq - bus) > 0) total += (eq - bus);

	eq = parseInt(this.$equipmentCouplingLevelInUse("energy", ship));
	check = parseInt(this.$equipmentCouplingRequired("energy", this.$equipmentItemInUse("energy", ship), ship));
	if ((check - eq) > 0) total += ((check - eq) * 2);
	if (eq > 7) eq = 7; // limit equipment coupling level to 7 - bus level 7 handles all energy couplings over 7
	if ((eq - bus) > 0) total += (eq - bus);

	eq = parseInt(this.$equipmentCouplingLevelInUse("frontshields", ship));
	check = parseInt(this.$equipmentCouplingRequired("frontshields", this.$equipmentItemInUse("frontshields", ship), ship));
	if ((check - eq) > 0) total += ((check - eq) * 2);
	if ((eq - bus) > 0) total += (eq - bus);

	eq = parseInt(this.$equipmentCouplingLevelInUse("aftshields", ship));
	check = parseInt(this.$equipmentCouplingRequired("aftshields", this.$equipmentItemInUse("aftshields", ship), ship));
	if ((check - eq) > 0) total += ((check - eq) * 2);
	if ((eq - bus) > 0) total += (eq - bus);

	return total;
}

//-------------------------------------------------------------------------------------------------------------
// decrease the bus overload counter if we haven't been hit for 30 seconds
this.$decreaseBusOverload = function $decreaseBusOverload() {
	if (this._busOverloadCounter > 0) {
		this._busOverloadCounter -= 1;
		if (this._busOverloadCounter < 0) this._busOverloadCounter = 0;
	} else {
		if (this._busOverloadResetTimer && this._busOverloadResetTimer.isRunning) this._busOverloadResetTimer.stop();
	}
}

//-------------------------------------------------------------------------------------------------------------
// returns true if the passed equipment key is required by another piece of installed equipment, otherwise false
this.$equipmentIsRequired = function $equipmentIsRequired(equipmentKey) {

	// todo: look at requiresAnyEquipment as well
	var p = player.ship;
	var eq = p.equipment;
	var result = false;

	// special case for passengers: make sure we always have enough berths for the number of passengers currently on board.
	if (equipmentKey === "EQ_PASSENGER_BERTH") {
		if (p.passengerCount > 0 && p.passengerCapacity <= p.passengerCount) {
			result = true;
		}
	} else {
		for (var i = 0; i < eq.length; i++) {
			// special case that isn't listed in equipment config
			//if (equipmentKey === "EQ_SHIELD_BOOSTER" && eq[i].equipmentKey === "EQ_NAVAL_SHIELD_BOOSTER") {
			//	result = true;
			//	break;
			// }
			var info = EquipmentInfo.infoForKey(eq[i].equipmentKey);
			if (info.requiresEquipment) {
				if (info.requiresEquipment.indexOf(equipmentKey) >= 0 ||
					// some special cases for ShipConfig items
					((equipmentKey.indexOf("EQ_FUEL_SCOOPS") >= 0 && info.requiresEquipment.indexOf("EQ_FUEL_SCOOPS") >= 0) ||
						(equipmentKey.indexOf("EQ_FUEL_INJECTION") >= 0 && info.requiresEquipment.indexOf("EQ_FUEL_INJECTION") >= 0) ||
						(equipmentKey.indexOf("EQ_HEAT_SHIELD") >= 0 && info.requiresEquipment.indexOf("EQ_HEAT_SHIELD") >= 0))) {
					result = true;
					break;
				}
			}
		}
	}
	return result;
}

//-------------------------------------------------------------------------------------------------------------
// returns the equipment item of a particular section of the ship
this.$equipmentItemInUse = function $equipmentItemInUse(section, ship) {
	if (!ship) return "";

	var item = "";
	var check = "";

	// check if we have a value stored in this._current. if so, we can pick it up from there
	// otherwise we'll scan through the various equipment item arrays
	if (ship.isPlayer === false || (!this._current[section] || this._current[section] === "")) {
		switch (section) {
			case "engines":
				for (var i = 0; i < this._engines.length; i++) {
					check = ship.equipmentStatus(this._engines[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._engines[i];
						break;
					}
				}
				break;
			case "hyperdrive":
				for (var i = 0; i < this._hyperdrive.length; i++) {
					check = ship.equipmentStatus(this._hyperdrive[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._hyperdrive[i];
						break;
					}
				}
				break;
			case "thrusters":
				for (var i = 0; i < this._thrusters.length; i++) {
					check = ship.equipmentStatus(this._thrusters[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._thrusters[i];
						break;
					}
				}
				break;
			case "boosters":
				for (var i = 0; i < this._boosters.length; i++) {
					check = ship.equipmentStatus(this._boosters[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._boosters[i];
						break;
					}
				}
				break;
			case "energy":
				for (var i = 0; i < this._energy.length; i++) {
					check = ship.equipmentStatus(this._energy[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._energy[i];
						break;
					}
				}
				break;
			case "frontshields":
				for (var i = 0; i < this._frontshields.length; i++) {
					check = ship.equipmentStatus(this._frontshields[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._frontshields[i];
						break;
					}
				}
				break;
			case "aftshields":
				for (var i = 0; i < this._aftshields.length; i++) {
					check = ship.equipmentStatus(this._aftshields[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._aftshields[i];
						break;
					}
				}
				break;
			case "heatshields":
				for (var i = 0; i < this._heatshields.length; i++) {
					check = ship.equipmentStatus(this._heatshields[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._heatshields[i];
						break;
					}
				}
				break;
			case "fuelinjectors":
				for (var i = 0; i < this._fuelinjectors.length; i++) {
					check = ship.equipmentStatus(this._fuelinjectors[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._fuelinjectors[i];
						break;
					}
				}
				break;
			case "fuelscoops":
				for (var i = 0; i < this._fuelscoops.length; i++) {
					check = ship.equipmentStatus(this._fuelscoops[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._fuelscoops[i];
						break;
					}
				}
				break;
			case "frontarmour":
				for (var i = 0; i < this._frontarmour.length; i++) {
					check = ship.equipmentStatus(this._frontarmour[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._frontarmour[i];
						break;
					}
				}
				break;
			case "aftarmour":
				for (var i = 0; i < this._aftarmour.length; i++) {
					check = ship.equipmentStatus(this._aftarmour[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._aftarmour[i];
						break;
					}
				}
				break;
			case "electricalbus":
				for (var i = 0; i < this._electricalbus.length; i++) {
					check = ship.equipmentStatus(this._electricalbus[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._electricalbus[i];
						break;
					}
				}
				break;
			case "hyperdrivecoupling":
				for (var i = 0; i < this._hdCoupling.length; i++) {
					check = ship.equipmentStatus(this._hdCoupling[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._hdCoupling[i];
						break;
					}
				}
				break;
			case "enginecoupling":
				for (var i = 0; i < this._enCoupling.length; i++) {
					check = ship.equipmentStatus(this._enCoupling[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._enCoupling[i];
						break;
					}
				}
				break;
			case "thrusterscoupling":
				for (var i = 0; i < this._thCoupling.length; i++) {
					check = ship.equipmentStatus(this._thCoupling[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._thCoupling[i];
						break;
					}
				}
				break;
			case "boosterscoupling":
				for (var i = 0; i < this._bsCoupling.length; i++) {
					check = ship.equipmentStatus(this._bsCoupling[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._bsCoupling[i];
						break;
					}
				}
				break;
			case "energycoupling":
				for (var i = 0; i < this._ebCoupling.length; i++) {
					check = ship.equipmentStatus(this._ebCoupling[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._ebCoupling[i];
						break;
					}
				}
				break;
			case "frontshieldscoupling":
				for (var i = 0; i < this._fsCoupling.length; i++) {
					check = ship.equipmentStatus(this._fsCoupling[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._fsCoupling[i];
						break;
					}
				}
				break;
			case "aftshieldscoupling":
				for (var i = 0; i < this._asCoupling.length; i++) {
					check = ship.equipmentStatus(this._asCoupling[i]);
					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
						item = this._asCoupling[i];
						break;
					}
				}
				break;
		}
		if (ship.isPlayer) this._current[section] = item;
	} else {
		item = this._current[section];
	}

	return item;
}

//-------------------------------------------------------------------------------------------------------------
// returns the space element of a particular section of the ship
this.$equipmentSpaceInUse = function $equipmentSpaceInUse(section, ship) {
	if (!ship) return 0;
	if (section === "electrical") {
		var total = 0;
		total += this._equipmentMatrix[this.$equipmentItemInUse("electricalbus", ship)][0];
		total += this._equipmentMatrix[this.$equipmentItemInUse("enginecoupling", ship)][0];
		total += this._equipmentMatrix[this.$equipmentItemInUse("energycoupling", ship)][0];
		total += this._equipmentMatrix[this.$equipmentItemInUse("thrusterscoupling", ship)][0];
		if (this.$equipmentItemInUse("boosterscoupling", ship))
			total += this._equipmentMatrix[this.$equipmentItemInUse("boosterscoupling", ship)][0];
		if (this.$shipHasHyperspaceMotor(ship.dataKey) === true && this._OXPHyperdrives === false) {
			total += this._equipmentMatrix[this.$equipmentItemInUse("hyperdrivecoupling", ship)][0];
		}
		total += this._equipmentMatrix[this.$equipmentItemInUse("frontshieldscoupling", ship)][0];
		total += this._equipmentMatrix[this.$equipmentItemInUse("aftshieldscoupling", ship)][0];
		return total;
	} else {
		var item = this.$equipmentItemInUse(section, ship);
		if (item != "") {
			return this._equipmentMatrix[item][0];
		} else {
			return 0;
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// returns the weight element of a particular section of the ship
this.$equipmentWeightInUse = function $equipmentWeightInUse(section, ship) {
	if (!ship) return 0;
	if (section === "electrical") {
		var total = 0;
		total += this._equipmentMatrix[this.$equipmentItemInUse("electricalbus", ship)][1];
		total += this._equipmentMatrix[this.$equipmentItemInUse("enginecoupling", ship)][1];
		total += this._equipmentMatrix[this.$equipmentItemInUse("energycoupling", ship)][1];
		total += this._equipmentMatrix[this.$equipmentItemInUse("thrusterscoupling", ship)][1];
		if (this.$equipmentItemInUse("boosterscoupling", ship))
			total += this._equipmentMatrix[this.$equipmentItemInUse("boosterscoupling", ship)][1];
		if (this.$shipHasHyperspaceMotor(ship.dataKey) === true && this._OXPHyperdrives === false) {
			total += this._equipmentMatrix[this.$equipmentItemInUse("hyperdrivecoupling", ship)][1];
		}
		total += this._equipmentMatrix[this.$equipmentItemInUse("frontshieldscoupling", ship)][1];
		total += this._equipmentMatrix[this.$equipmentItemInUse("aftshieldscoupling", ship)][1];
		return total;
	} else {
		var item = this.$equipmentItemInUse(section, ship);
		if (item != "") {
			return this._equipmentMatrix[item][1];
		} else {
			return 0;
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$equipmentLevelInUse = function $equipmentLevelInUse(section, ship) {
	if (!ship) return 0;
	var item = this.$equipmentItemInUse(section, ship);
	return (this.$equipmentCouplingRequired(section, item, ship));
}

//-------------------------------------------------------------------------------------------------------------
// returns the coupling level for the equipment in use
this.$equipmentCouplingLevelInUse = function $equipmentCouplingLevelInUse(section, ship) {

	if (!ship) return 0;

	var level = 0;
	var coupling = "";

	switch (section) {
		case "electricalbus":
			coupling = this.$equipmentItemInUse("electricalbus", ship);
			level = this._electricalbus.indexOf(coupling);
			break;
		case "engines":
		case "fuelinjectors":
			coupling = this.$equipmentItemInUse("enginecoupling", ship);
			level = this._enCoupling.indexOf(coupling);
			break;
		case "hyperdrive":
			coupling = this.$equipmentItemInUse("hyperdrivecoupling", ship);
			level = this._hdCoupling.indexOf(coupling);
			break;
		case "thrusters":
			coupling = this.$equipmentItemInUse("thrusterscoupling", ship);
			level = this._thCoupling.indexOf(coupling);
			break;
		case "boosters":
			coupling = this.$equipmentItemInUse("boosterscoupling", ship);
			level = this._bsCoupling.indexOf(coupling);
			break;
		case "energy":
			coupling = this.$equipmentItemInUse("energycoupling", ship);
			level = this._ebCoupling.indexOf(coupling);
			break;
		case "frontshields":
			coupling = this.$equipmentItemInUse("frontshieldscoupling", ship);
			level = this._fsCoupling.indexOf(coupling);
			break;
		case "aftshields":
			coupling = this.$equipmentItemInUse("aftshieldscoupling", ship);
			level = this._asCoupling.indexOf(coupling);
			break;
	}

	return (level + 1);
}

//-------------------------------------------------------------------------------------------------------------
// return max coupling level in use
this.$maxEquipmentCouplingInUse = function $maxEquipmentCouplingInUse(ship) {

	if (!ship) return 0;

	var coupling = "";
	var maxcoupling = 0;
	var level = 0;

	coupling = this.$equipmentItemInUse("enginecoupling", ship);
	level = this._enCoupling.indexOf(coupling);
	if (level > maxcoupling) maxcoupling = level;

	if (this.$shipHasHyperspaceMotor(ship.dataKey) === true && this._OXPHyperdrives === false) {
		coupling = this.$equipmentItemInUse("hyperdrivecoupling", ship);
		level = this._hdCoupling.indexOf(coupling);
		if (level > maxcoupling) maxcoupling = level;
	}

	coupling = this.$equipmentItemInUse("thrusterscoupling", ship);
	level = this._thCoupling.indexOf(coupling);
	if (level > maxcoupling) maxcoupling = level;

	coupling = this.$equipmentItemInUse("boosterscoupling", ship);
	if (coupling) {
		level = this._bsCoupling.indexOf(coupling);
		if (level > maxcoupling) maxcoupling = level;
	}

	coupling = this.$equipmentItemInUse("energycoupling", ship);
	level = this._ebCoupling.indexOf(coupling);
	if (level > maxcoupling) maxcoupling = level;

	if (this.$equipmentItemInUse("frontshields", ship) != "EQ_NO_FORWARD_SHIELD") {
		coupling = this.$equipmentItemInUse("frontshieldscoupling", ship);
		level = this._fsCoupling.indexOf(coupling);
		if (level > maxcoupling) maxcoupling = level;
	}

	if (this.$equipmentItemInUse("aftshields", ship) != "EQ_NO_AFT_SHIELD") {
		coupling = this.$equipmentItemInUse("aftshieldscoupling", ship);
		level = this._asCoupling.indexOf(coupling);
		if (level > maxcoupling) maxcoupling = level;
	}

	return maxcoupling;
}

//-------------------------------------------------------------------------------------------------------------
// returns the required level of coupling for a particular component
this.$equipmentCouplingRequired = function $equipmentCouplingRequired(section, equipmentKey, ship) {

	if (!ship) return 0;

	var level = 0;
	var coupling = "";

	switch (section) {
		case "all":
		case "engines":
		case "fuelinjectors":
		case "hyperdrive":
		case "thrusters":
		case "boosters":
		case "frontshields":
		case "aftshields":
			if (equipmentKey.indexOf("_TYPE1") >= 0) level = 1;
			if (equipmentKey.indexOf("_TYPE2") >= 0) level = 2;
			if (equipmentKey.indexOf("_TYPE3") >= 0) level = 3;
			if (equipmentKey.indexOf("_TYPE4") >= 0) level = 4;
			if (equipmentKey.indexOf("_TYPE5") >= 0) level = 5;
			if (equipmentKey.indexOf("_TYPE6") >= 0) level = 6;
			if (equipmentKey.indexOf("_TYPE7") >= 0) level = 7;
			if (equipmentKey.indexOf("_TYPE8") >= 0) level = 7;
			break;
		case "energy":
			var bustype = this._equipCouplingBus[equipmentKey];
			level = this._ebCoupling.indexOf(bustype) + 1;
			break;
	}

	return level;
}

//-------------------------------------------------------------------------------------------------------------
// puts all required equipment into the "no sell" array - this is only run once at startup
this.$populateNoSellList = function $populateNoSellList() {

	for (var i = 0; i < this._electricalbus.length; i++) {
		if (this._noSell.indexOf(this._electricalbus[i]) === -1) this._noSell.push(this._electricalbus[i]);
	}
	for (var i = 0; i < this._engines.length; i++) {
		if (this._noSell.indexOf(this._engines[i]) === -1) this._noSell.push(this._engines[i]);
	}
	for (var i = 0; i < this._enCoupling.length; i++) {
		if (this._noSell.indexOf(this._enCoupling[i]) === -1) this._noSell.push(this._enCoupling[i]);
	}
	for (var i = 0; i < this._hyperdrive.length; i++) {
		if (this._noSell.indexOf(this._hyperdrive[i]) === -1) this._noSell.push(this._hyperdrive[i]);
	}
	for (var i = 0; i < this._hdCoupling.length; i++) {
		if (this._noSell.indexOf(this._hdCoupling[i]) === -1) this._noSell.push(this._hdCoupling[i]);
	}
	for (var i = 0; i < this._thrusters.length; i++) {
		if (this._noSell.indexOf(this._thrusters[i]) === -1) this._noSell.push(this._thrusters[i]);
	}
	for (var i = 0; i < this._thCoupling.length; i++) {
		if (this._noSell.indexOf(this._thCoupling[i]) === -1) this._noSell.push(this._thCoupling[i]);
	}
	for (var i = 0; i < this._energy.length; i++) {
		if (this._noSell.indexOf(this._energy[i]) === -1) this._noSell.push(this._energy[i]);
	}
	for (var i = 0; i < this._ebCoupling.length; i++) {
		if (this._noSell.indexOf(this._ebCoupling[i]) === -1) this._noSell.push(this._ebCoupling[i]);
	}
	for (var i = 0; i < this._frontshields.length; i++) {
		if (this._noSell.indexOf(this._frontshields[i]) === -1) this._noSell.push(this._frontshields[i]);
	}
	for (var i = 0; i < this._fsCoupling.length; i++) {
		if (this._noSell.indexOf(this._fsCoupling[i]) === -1) this._noSell.push(this._fsCoupling[i]);
	}
	for (var i = 0; i < this._aftshields.length; i++) {
		if (this._noSell.indexOf(this._aftshields[i]) === -1) this._noSell.push(this._aftshields[i]);
	}
	for (var i = 0; i < this._asCoupling.length; i++) {
		if (this._noSell.indexOf(this._asCoupling[i]) === -1) this._noSell.push(this._asCoupling[i]);
	}
	for (var i = 0; i < this._bsCoupling.length; i++) {
		if (this._noSell.indexOf(this._bsCoupling[i]) === -1) this._noSell.push(this._bsCoupling[i]);
	}
}

//-------------------------------------------------------------------------------------------------------------
// installs the default factory equipment into a ship
this.$installBaseEquipment = function $installBaseEquipment(ship) {

	if (!ship) return;

	var changed = false;
	var equip = "";
	var maxSpace = 0;
	var equipmentList = [];
	if (ship.isPlayer === false) {
		maxSpace = Math.ceil(this.$equipmentSpaceTotal(ship) + this.$cargoSpaceAvailable(ship));
		equipmentList = this.$getNPCEquipmentList(ship.primaryRole, ship.roles, maxSpace);
		if (!equipmentList || equipmentList.length === 0) {
			if (this._debug) log(this.name, "!!NOTE: No match found for " + ship.primaryRole + ", ship type " + ship.shipClassName + ", space " + maxSpace + " - adding default equipment");
			equipmentList = [];
		} else {
			// based on accuracy (skill level) potentially remove some items from the list
			// the higher the accuracy, the fewer items will be removed
			// range is -5 to +10
			// below 0 = remove up to 3 items
			// 0 - 3 = remove up to 2 items
			// 3.1 - 6 = remove 1 item
			// above 6 no removal
			if (ship.isPolice === false) {
				var remove_count = 0;
				if (ship.accuracy <= 0) remove_count = 3;
				if (ship.accuracy > 0 && ship.accuracy <= 3) remove_count = 2;
				if (ship.accuracy > 3 && ship.accuracy <= 6) remove_count = 1;
				if (remove_count > 0) {
					for (var i = 1; i <= remove_count; i++) {
						// lower accuracy means more chance of removal
						// blanking out the equipmentList item will mean default equipment only
						if (Math.random() > ((ship.accuracy + 5) / 15)) {
							var idx = Math.floor(Math.random() * equipmentList.length);
							//if (this._debug && equipmentList[idx] != "") log(this.name, "removing " + equipmentList[idx] + " from " + ship);
							equipmentList[idx] = "";
						}
					}
				}
			}
		}
	}

	// are any of the default items installed? If no, install them now.
	// main electrical bus
	var found = false;
	var bus = -1;
	for (var i = 0; i < this._electricalbus.length; i++) {
		var check = ship.equipmentStatus(this._electricalbus[i]);
		if (check === "EQUIPMENT_OK") {
			found = true;
			bus = (i + 1);
		}
	}
	if (found === false) {
		if (ship.isPlayer) {
			equip = "EQ_ELEC_BUS_TYPE2";
			bus = 2;
		} else {
			equip = this.$selectNPCEquipment("electricalbus", equipmentList);
			bus = this._electricalbus.indexOf(equip) + 1;
		}
		ship.awardEquipment(equip);
		changed = true;
	}

	// engines
	found = false;
	var eng = -1;
	for (var i = 0; i < this._engines.length; i++) {
		var check = ship.equipmentStatus(this._engines[i]);
		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
			found = true;
			eng = Math.floor(i / 6) + 1;
		}
	}
	if (found === false) {
		// for NPC ships, change the engine type based on primary role
		if (ship.isPlayer) {
			equip = "EQ_ENGINE_TYPE2A";
			eng = 2;
		} else {
			equip = this.$selectNPCEquipment("engines", equipmentList);
			eng = Math.floor(this._engines.indexOf(equip) / 6) + 1;
		}
		ship.awardEquipment(equip);
		changed = true;
	}
	found = false;
	for (var i = 0; i < this._enCoupling.length; i++) {
		var check = ship.equipmentStatus(this._enCoupling[i]);
		if (check === "EQUIPMENT_OK") found = true;
	}
	if (found === false) {
		ship.awardEquipment("EQ_ENGINE_COUPLING_TYPE" + eng);
		changed = true;
	}

	// hyperspace motor
	found = false;
	if (this.$shipHasHyperspaceMotor(ship.dataKey) === true && this._OXPHyperdrives === false) {
		var hd = -1;
		for (var i = 0; i < this._hyperdrive.length; i++) {
			var check = ship.equipmentStatus(this._hyperdrive[i]);
			if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
				found = true;
				hd = i + 1;
			}
		}
		if (found === false) {
			if (ship.isPlayer) {
				equip = "EQ_HYPERDRIVE_TYPE2";
				hd = 2;
			} else {
				equip = this.$selectNPCEquipment("hyperdrive", equipmentList);
				hd = this._hyperdrive.indexOf(equip) + 1;
			}
			ship.awardEquipment(equip);
			changed = true;
		}
		found = false;
		for (var i = 0; i < this._hdCoupling.length; i++) {
			var check = ship.equipmentStatus(this._hdCoupling[i]);
			if (check === "EQUIPMENT_OK") found = true;
		}
		if (found === false) {
			ship.awardEquipment("EQ_HYPERDRIVE_COUPLING_TYPE" + hd);
			changed = true;
		}
	}

	// thrusters
	found = false;
	//var thr = -1;
	for (var i = 0; i < this._thrusters.length; i++) {
		var check = ship.equipmentStatus(this._thrusters[i]);
		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
			equip = this._thrusters[i];
			found = true;
			break;
		}
	}
	if (found === false) {
		equip = "EQ_THRUSTERS_TYPE2A";
		if (!ship.isPlayer) {
			equip = this.$selectNPCEquipment("thrusters", equipmentList);
		}
		ship.awardEquipment(equip);
		changed = true;
	}
	found = false;
	for (var i = 0; i < this._thCoupling.length; i++) {
		var check = ship.equipmentStatus(this._thCoupling[i]);
		if (check === "EQUIPMENT_OK") found = true;
	}
	if (found === false) {
		var thcp = this._equipCouplingBus[equip];
		ship.awardEquipment(thcp);
		changed = true;
	}

	// boosters - just install the minimum power coupling by default
	if (this._heatControl === true) {
		found = false;
		for (var i = 0; i < this._bsCoupling.length; i++) {
			var check = ship.equipmentStatus(this._bsCoupling[i]);
			if (check === "EQUIPMENT_OK") {
				found = true;
				break;
			}
		}
		if (found === false) {
			ship.awardEquipment("EQ_BOOSTERS_COUPLING_TYPE1");
			changed = true;
		}
	}

	// energy banks (standard class only, not class "A" types)
	found = false;
	var en = -1;
	for (var i = 0; i < this._energy.length; i++) {
		var check = ship.equipmentStatus(this._energy[i]);
		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
			found = true;
			en = (i + 1);
		}
	}
	if (found === false) {
		var banks = Math.floor(ship.maxEnergy / 64);
		if (banks <= 25) {
			if (banks === 0 && ship.maxEnergy > 0) banks = 1;
			// this should never happen, but just in case... default max energy should be 200, which is 3 banks
			if (ship.maxEnergy === 0) banks = 3;
			if (ship.isPlayer === false) {
				// check to see if this NPC configuration is overriding the number of banks
				equip = this.$selectNPCEquipment("energy", equipmentList, banks);
				if (equip != "") banks = this._energy.indexOf(equip) + 1;
				//log(this.name, "final equip = " + equip);
			}
			ship.awardEquipment("EQ_ENERGYBANK_TYPE" + banks);
			en = banks;
			changed = true;
		}
	}
	found = false;
	for (var i = 0; i < this._ebCoupling.length; i++) {
		var check = ship.equipmentStatus(this._ebCoupling[i]);
		if (check === "EQUIPMENT_OK") found = true;
	}
	// make sure the right electrical bus is fitted for the number of energy banks we have
	if (found === false) {
		switch (en) {
			case 1:
			case 2:
			case 3:
			case 4:
				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE1");
				break;
			case 5:
			case 6:
			case 7:
				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE2");
				break;
			case 8:
			case 9:
			case 10:
				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE3");
				if (bus < 3) {
					ship.removeEquipment("EQ_ELEC_BUS_TYPE" + bus);
					ship.awardEquipment("EQ_ELEC_BUS_TYPE3");
				}
				break;
			case 11:
			case 12:
			case 13:
				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE4");
				if (bus < 4) {
					ship.removeEquipment("EQ_ELEC_BUS_TYPE" + bus);
					ship.awardEquipment("EQ_ELEC_BUS_TYPE4");
				}
				break;
			case 14:
			case 15:
			case 16:
				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE5");
				if (bus < 5) {
					ship.removeEquipment("EQ_ELEC_BUS_TYPE" + bus);
					ship.awardEquipment("EQ_ELEC_BUS_TYPE5");
				}
				break;
			case 17:
			case 18:
			case 19:
				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE6");
				if (bus < 6) {
					ship.removeEquipment("EQ_ELEC_BUS_TYPE" + bus);
					ship.awardEquipment("EQ_ELEC_BUS_TYPE6");
				}
				break;
			case 20:
			case 21:
			case 22:
				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE7");
				if (bus < 7) {
					ship.removeEquipment("EQ_ELEC_BUS_TYPE" + bus);
					ship.awardEquipment("EQ_ELEC_BUS_TYPE7");
				}
				break;
			case 23:
			case 24:
			case 25:
				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE8");
				if (bus < 7) {
					ship.removeEquipment("EQ_ELEC_BUS_TYPE" + bus);
					ship.awardEquipment("EQ_ELEC_BUS_TYPE7");
				}
				break;
		}
		changed = true;
	}

	// note: we'll add the shield equipment to NPC's, even if they don't officially have shields - the game compensates for the lack of shields with addition energy
	// and we want the weight profile to be the same as for the player
	// front shields
	found = false;
	var fs = -1;
	for (var i = 0; i < this._frontshields.length; i++) {
		var check = ship.equipmentStatus(this._frontshields[i]);
		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
			found = true;
			fs = i;
		}
	}
	if (found === false) {
		if (ship.isPlayer) {
			equip = "EQ_FORWARD_SHIELD_TYPE2";
			fs = 2;
		} else {
			equip = this.$selectNPCEquipment("frontshields", equipmentList);
			fs = this._frontshields.indexOf(equip);
		}
		ship.awardEquipment(equip);
		changed = true;
	}
	found = false;
	if (fs === 0) fs = 1;
	for (var i = 0; i < this._fsCoupling.length; i++) {
		var check = ship.equipmentStatus(this._fsCoupling[i]);
		if (check === "EQUIPMENT_OK") found = true;
	}
	if (found === false) {
		ship.awardEquipment("EQ_FORWARD_SHIELD_COUPLING_TYPE" + fs);
		changed = true;
	}

	// aft shields
	found = false;
	var as = -1;
	for (var i = 0; i < this._aftshields.length; i++) {
		var check = ship.equipmentStatus(this._aftshields[i]);
		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
			found = true;
			as = i;
		}
	}
	if (found === false) {
		if (ship.isPlayer) {
			equip = "EQ_AFT_SHIELD_TYPE2";
			as = 2;
		} else {
			equip = this.$selectNPCEquipment("aftshields", equipmentList);
			as = this._aftshields.indexOf(equip);
		}
		ship.awardEquipment(equip);
		changed = true;
	}
	found = false;
	if (as === 0) as = 1;
	for (var i = 0; i < this._asCoupling.length; i++) {
		var check = ship.equipmentStatus(this._asCoupling[i]);
		if (check === "EQUIPMENT_OK") found = true;
	}
	if (found === false) {
		ship.awardEquipment("EQ_AFT_SHIELD_COUPLING_TYPE" + as);
		changed = true;
	}

	// fuel injectors
	var fi = ship.equipmentStatus("EQ_FUEL_INJECTION");
	equip = "";
	if (fi === "EQUIPMENT_OK" || fi === "EQUIPMENT_DAMAGED") {
		var fi_idx = -1;
		for (var i = 0; i < this._fuelinjectors.length; i++) {
			var check = ship.equipmentStatus(this._fuelinjectors[i]);
			if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
				equip = this._fuelinjectors[i];
				fi_idx = i;
			}
		}
		if (fi_idx === -1) {
			if (ship.isPlayer) {
				equip = "EQ_FUEL_INJECTION_TYPE2";
			} else {
				equip = this.$selectNPCEquipment("fuelinjectors", equipmentList);
			}
		}
		if (equip != "") {
			ship.awardEquipment(equip);
			changed = true;
		}
		if (fi === "EQUIPMENT_DAMAGED") ship.setEquipmentStatus(equip, "EQUIPMENT_DAMAGED");
	}
	// special case for NPCs with fuel injectors: don't install it if they don't already have it.
	/*if (!ship.isPlayer && fi === "EQUIPMENT_UNAVAILABLE") {
		equip = this.$selectNPCEquipment("fuelinjectors", equipmentList);
		if (equip != "") {
			ship.awardEquipment(equip);
			changed = true;
		}
	} */
	// fuel scoops
	var sc = ship.equipmentStatus("EQ_FUEL_SCOOPS");
	equip = "";
	if (sc === "EQUIPMENT_OK" || sc === "EQUIPMENT_DAMAGED") {
		var sc_idx = -1;
		for (var i = 0; i < this._fuelscoops.length; i++) {
			var check = ship.equipmentStatus(this._fuelscoops[i]);
			if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
				equip = this._fuelscoops[i];
				sc_idx = i;
			}
		}
		if (sc_idx === -1) {
			if (ship.isPlayer) {
				equip = "EQ_FUEL_SCOOPS_TYPE1";
			} else {
				equip = this.$selectNPCEquipment("fuelscoops", equipmentList);
			}
		}
		if (equip != "") {
			ship.awardEquipment(equip);
			changed = true;
		}
		if (sc === "EQUIPMENT_DAMAGED") ship.setEquipmentStatus(equip, "EQUIPMENT_DAMAGED");
	}

	// heat shields
	var hs = ship.equipmentStatus("EQ_HEAT_SHIELD");
	equip = "";
	// first check to see if we have a heat shield installed, but without the base Heat shield item (possibly it got lost)
	var equipHS = this.$equipmentItemInUse("heatshields", ship);
	var checkHS = ship.equipmentStatus(equipHS);
	if (checkHS === "EQUIPMENT_OK" || checkHS === "EQUIPMENT_DAMAGED") {
		if (hs === "EQUIPMENT_UNAVAILABLE") {
			ship.awardEquipment("EQ_HEAT_SHIELD");
			if (checkHS !== "EQUIPMENT_OK") ship.setEquipmentStatus("EQ_HEAT_SHIELD", checkHS);
			hs = checkHS;
		}
	}
	if ((hs === "EQUIPMENT_OK" || hs === "EQUIPMENT_DAMAGED") && equipHS === "") {
		if (ship.isPlayer) {
			equipHS = "EQ_HEAT_SHIELD_TYPE2";
		} else {
			equipHS = this.$selectNPCEquipment("heatshields", equipmentList);
		}
		if (equipHS != "") {
			ship.awardEquipment(equipHS);
			changed = true;
		}
		if (hs === "EQUIPMENT_DAMAGED") ship.setEquipmentStatus(equipHS, "EQUIPMENT_DAMAGED");
	}
	// only allocate NPC heat shields if they don't already have heat shields
	if (!ship.isPlayer && hs === "EQUIPMENT_UNAVAILABLE") {
		equip = this.$selectNPCEquipment("heatshields", equipmentList);
		if (equip != "") {
			ship.awardEquipment(equip);
			changed = true;
		}
	}

	// armour
	if (ship.isPlayer === false) {
		equip = this.$selectNPCEquipment("frontarmour", equipmentList);
		if (equip != "") {
			ship.awardEquipment(equip);
			changed = true;
		}
		equip = this.$selectNPCEquipment("aftarmour", equipmentList);
		if (equip != "") {
			ship.awardEquipment(equip);
			changed = true;
		}
	}

	// heatsinks
	// just need to make sure ship have enough cargo space for them
	var equip = this.$selectNPCEquipment("heatsinks", equipmentList);
	if (equip != "") {
		if (equip.indexOf(",") >= 0) {
			var itms = equip.split(",");
			for (var i = 0; i < itms.length; i++) {
				if (this.$cargoSpaceAvailable(ship) > 0) ship.awardEquipment(itms[i]);
			}
		} else {
			if (this.$cargoSpaceAvailable(ship) > 0) ship.awardEquipment(equip);
		}
	}

	return changed;
}

//-------------------------------------------------------------------------------------------------------------
// logic for NPC equipment choices
this.$selectNPCEquipment = function $selectNPCEquipment(section, equipmentList, defaultValue) {

	var result = "";
	switch (section) {
		case "engines":
			// logic hear to switch engines based on ship role and available space
			if (equipmentList) {
				for (var i = 0; i < this._engines.length; i++) {
					if (equipmentList.indexOf(this._engines[i]) >= 0) {
						result = this._engines[i];
						break;
					}
				}
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("engines:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				if (change != 0) {
					var newidx = this._engines.indexOf("EQ_ENGINE_TYPE2A") + (change * 3);
					if (newidx > this._engines.length - 1) newidx = this._engines.length - 1;
					if (newidx < 0) newidx = 0;
					result = this._engines[newidx];
				}
			}
			if (result === "") result = "EQ_ENGINE_TYPE2A";
			break;
		case "thrusters":
			if (equipmentList) {
				for (var i = 0; i < this._thrusters.length; i++) {
					if (equipmentList.indexOf(this._thrusters[i]) >= 0) {
						result = this._thrusters[i];
						break;
					}
				}
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("thrusters:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				if (change != 0) {
					var newidx = this._thrusters.indexOf("EQ_THRUSTERS_TYPE2A") + change;
					if (newidx > this._thrusters.length - 1) newidx = this._thrusters.length - 1;
					if (newidx < 0) newidx = 0;
					result = this._thrusters[newidx];
				}
			}
			if (result === "") result = "EQ_THRUSTERS_TYPE2A";
			break;
		case "boosters":
			if (equipmentList) {
				for (var i = 0; i < this._boosters.length; i++) {
					if (equipmentList.indexOf(this._boosters[i]) >= 0) {
						result = this._boosters[i];
						break;
					}
				}
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("boosters:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				if (change != 0) {
					if (change > this._boosters.length - 1) change = this._boosters.length - 1;
					if (change >= 0) result = this._boosters[change];
				}
			}
			break;
		case "hyperdrive":
			if (equipmentList) {
				for (var i = 0; i < this._hyperdrive.length; i++) {
					if (equipmentList.indexOf(this._hyperdrive[i]) >= 0) {
						result = this._hyperdrive[i];
						break;
					}
				}
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("hyperdrive:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				if (change != 0) {
					var newidx = this._hyperdrive.indexOf("EQ_HYPERDRIVE_TYPE2") + change;
					if (newidx > this._hyperdrive.length - 1) newidx = this._hyperdrive.length - 1;
					if (newidx < 0) newidx = 0;
					result = this._hyperdrive[newidx];
				}
			}
			if (result === "") result = "EQ_HYPERDRIVE_TYPE2";
			break;
		case "energy":
			// note: if NPC's need to get class "A" energy units installed, some changes to this routine will be required.
			// for the moment, though, I'm assuming that only standard class units will be installed
			if (equipmentList) {
				for (var i = 0; i < this._energy.length; i++) {
					if (equipmentList.indexOf(this._energy[i]) >= 0) {
						result = this._energy[i];
						break;
					}
				}
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("energy:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				if (change != 0) {
					var newidx = this._energy.indexOf("EQ_ENERGYBANK_TYPE" + defaultValue) + change;
					if (newidx > 24) newidx = 24;
					if (newidx < 0) newidx = 0;
					result = this._energy[newidx];
				}
			}
			if (result === "" && defaultValue) result = "EQ_ENERGYBANK_TYPE" + defaultValue;
			break;
		case "frontshields":
			if (equipmentList) {
				for (var i = 0; i < this._frontshields.length; i++) {
					if (equipmentList.indexOf(this._frontshields[i]) >= 0) {
						result = this._frontshields[i];
						break;
					}
				}
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("frontshields:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				if (change != 0) {
					var newidx = this._frontshields.indexOf("EQ_FORWARD_SHIELD_TYPE2") + change;
					if (newidx > this._frontshields.length - 1) newidx = this._frontshields.length - 1;
					if (newidx < 0) newidx = 0;
					result = this._frontshields[newidx];
				}
			}
			if (result === "") result = "EQ_FORWARD_SHIELD_TYPE2";
			break;
		case "aftshields":
			if (equipmentList) {
				for (var i = 0; i < this._aftshields.length; i++) {
					if (equipmentList.indexOf(this._aftshields[i]) >= 0) {
						result = this._aftshields[i];
						break;
					}
				}
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("aftshields:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				if (change != 0) {
					var newidx = this._aftshields.indexOf("EQ_AFT_SHIELD_TYPE2") + change;
					if (newidx > this._aftshields.length - 1) newidx = this._aftshields.length - 1;
					if (newidx < 0) newidx = 0;
					result = this._aftshields[newidx];
				}
			}
			if (result === "") result = "EQ_AFT_SHIELD_TYPE2";
			break;
		case "electricalbus":
			result = "EQ_ELEC_BUS_TYPE2";
			if (equipmentList) {
				for (var i = 0; i < this._electricalbus.length; i++) {
					if (equipmentList.indexOf(this._electricalbus[i]) >= 0) {
						result = this._electricalbus[i];
						break;
					}
				}
			}
			break;
		case "fuelinjectors":
			if (equipmentList) {
				for (var i = 0; i < this._fuelinjectors.length; i++) {
					if (equipmentList.indexOf(this._fuelinjectors[i]) >= 0) {
						result = this._fuelinjectors[i];
						break;
					}
				}
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("fuelinjectors:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				if (change != 0) {
					var newidx = this._fuelinjectors.indexOf("EQ_FUEL_INJECTION_TYPE2") + change;
					if (newidx > this._fuelinjectors.length - 1) newidx = this._fuelinjectors.length - 1;
					if (newidx < 0) newidx = 0;
					result = this._fuelinjectors[newidx];
				}
			}
			if (result === "") result = "EQ_FUEL_INJECTION_TYPE2";
			break;
		case "fuelscoops":
			if (equipmentList) {
				for (var i = 0; i < this._fuelscoops.length; i++) {
					if (equipmentList.indexOf(this._fuelscoops[i]) >= 0) {
						result = this._fuelscoops[i];
						break;
					}
				}
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("fuelscoops:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				if (change != 0) {
					var newidx = this._fuelscoops.indexOf("EQ_FUEL_SCOOPS_TYPE1") + change;
					if (newidx > this._fuelscoops.length - 1) newidx = this._fuelscoops.length - 1;
					if (newidx < 0) newidx = 0;
					result = this._fuelscoops[newidx];
				}
			}
			if (result === "") result = "EQ_FUEL_SCOOPS_TYPE1";
			break;
		case "heatshields":
			if (equipmentList) {
				for (var i = 0; i < this._heatshields.length; i++) {
					if (equipmentList.indexOf(this._heatshields[i]) >= 0) {
						result = this._heatshields[i];
						break;
					}
				}
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("heatshields:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				if (change != 0) {
					var newidx = this._heatshields.indexOf("EQ_HEAT_SHIELD_TYPE2") + change;
					if (newidx > this._heatshields.length - 1) newidx = this._heatshields.length - 1;
					if (newidx < 0) newidx = 0;
					result = this._heatshields[newidx];
				}
			}
			if (result === "") result = "EQ_HEAT_SHIELD_TYPE2";
			break;
		case "frontarmour":
			if (equipmentList) {
				for (var i = 0; i < this._frontarmour.length; i++) {
					if (equipmentList.indexOf(this._frontarmour[i]) >= 0) {
						result = this._frontarmour[i];
						break;
					}
				}
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("frontarmour:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				// the default is no armour, so if a change value is entered it has to be always positive
				if (change != 0) {
					if (change > this._frontarmour.length - 1) change = this._frontarmour.length - 1;
					if (change >= 0) result = this._frontarmour[change];
				}
			}
			break;
		case "aftarmour":
			if (equipmentList) {
				for (var i = 0; i < this._aftarmour.length; i++) {
					if (equipmentList.indexOf(this._aftarmour[i]) >= 0) {
						result = this._aftarmour[i];
						break;
					}
				}
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("aftarmour:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				// the default is no armour, so if a change value is entered it has to be always positive
				if (change != 0) {
					if (change > this._aftarmour.length - 1) change = this._aftarmour.length - 1;
					if (change >= 0) result = this._aftarmour[change];
				}
			}
			break;
		case "heatsinks":
			if (equipmentList) {
				if (equipmentList.indexOf("EQ_HEAT_SINK") >= 0) result = "EQ_HEAT_SINK";
				var change = 0;
				if (result === "") {
					for (var i = 0; i < equipmentList.length; i++) {
						if (equipmentList[i].indexOf("heatsinks:") >= 0) {
							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
							break;
						}
					}
				}
				// the default is no armour, so if a change value is entered it has to be always positive
				if (change != 0) {
					for (var i = 1; i <= change; i++)
						result += (result === "" ? "" : ",") + "EQ_HEAT_SINK";
				}
			}
			break;
	}

	return result;
}

//-------------------------------------------------------------------------------------------------------------
// returns the NPC equipment array for a given role and space
this.$getNPCEquipmentList = function $getNPCEquipmentList(primRole, roleList, equipmentSpace) {
	var role = primRole;
	// check if there is a translation item for the primary role
	if (this._NPCEquivalents[primRole] != null) role = this._NPCEquivalents[primRole];
	// try with the primary role first
	for (var i = 0; i < this._NPCConfig.length; i++) {
		if (this._NPCConfig[i].primaryRole == role && equipmentSpace >= this._NPCConfig[i].minSpace && equipmentSpace <= this._NPCConfig[i].maxSpace) {
			return this._NPCConfig[i].equipmentList;
		}
	}
	// if we get here there was no match for the primary role
	// now we'll check all the other roles
	for (var j = 0; j < roleList.length; j++) {
		for (var i = 0; i < this._NPCConfig.length; i++) {
			if (this._NPCConfig[i].primaryRole === roleList[j] && equipmentSpace >= this._NPCConfig[i].minSpace && equipmentSpace <= this._NPCConfig[i].maxSpace) {
				return this._NPCConfig[i].equipmentList;
			}
		}
	}
	// no match at all - return null
	return null;
}

//-------------------------------------------------------------------------------------------------------------
// adds the cargo space filler item for when the equipment requirements outstrip the base equipment space capacity
this.$addEquipmentSpaceItem = function $addEquipmentSpaceItem(ship) {
	if (!ship) return true;

	// don't add for NPC's
	if (ship.isPlayer === false) return true;
	// don't add during flight
	if (ship.alertCondition != 0) return true;

	var stn = system.mainStation;
	if (ship.dockedStation) stn = ship.dockedStation;
	var mkt = stn.market;

	// remove any existing equipment space items
	var remove = "";
	for (var i = 1; i <= 40; i++) {
		remove = "EQ_EQUIPSPACE_" + i;
		if (ship.equipmentStatus(remove) === "EQUIPMENT_OK") {
			ship.removeEquipment(remove);
			break;
		}
	}

	var equipSpace = this.$equipmentSpaceTotal(ship);
	var cargoSpace = this.$cargoSpaceAvailable(ship);
	var used = this.$calcEquipmentSpace(ship);
	if (used > equipSpace) {
		// allocate cargo space to equipment space
		var diff = parseInt(used - equipSpace);
		if (diff > cargoSpace) {
			// put in the maximum anyway
			if (cargoSpace > 0) ship.awardEquipment("EQ_EQUIPSPACE_" + cargoSpace);
			return false;
		} else if (diff > 0) {
			// add the new one
			var item = "EQ_EQUIPSPACE_" + diff;
			//if (this._debug) log(this.name, "adding item " + item);
			var result = false;
			var tries = 0;
			do {
				result = ship.awardEquipment(item);
				if (result === false) {
					// sell cargo until we fit in.
					if (ship.isPlayer) {
						var cargo = ship.manifest.list;
						for (var i = 0; i < cargo.length; i++) {
							if (cargo[i].quantity > 0 && cargo[i].unit === "t") {
								ship.manifest[cargo[i].commodity] -= 1;
								if (ship.isPlayer) {
									player.credits += (mkt[cargo[i].commodity].price / 10);
								}
								break;
							}
						}
					}
				}
				tries += 1;
			} while (result === false && tries < ship.cargoSpaceCapacity);

			this.$updateShipSpecs(ship);
			return result;
		}
	} else {
		this.$updateShipSpecs(ship);
		return true;
	}
}

//-------------------------------------------------------------------------------------------------------------
// returns calculated values for particular types of settings
this.$calculatedValue = function $calculatedValue(calcType, ship, shipspec, booster, weight, maxweight, damageFactor) {

	var loadData = false;
	var boostEq = null;
	if (!shipspec) {
		loadData = true;
		var shipspec = Ship.shipDataForKey(ship.dataKey);
		var weight = this.$calcEquipmentWeight(ship);
		var maxweight = this.$calcShipMaxWeight(ship.shipClassName, this.$getShipMass(ship));
		if (maxweight < weight) maxweight = weight;
		damageFactor = 1;
	}
	if (!booster) {
		boostEq = EquipmentInfo.infoForKey(this.$equipmentItemInUse("boosters", ship));
	} else {
		boostEq = booster;
	}

	var thrust = parseInt(shipspec["thrust"]);
	if (isNaN(thrust)) thrust = 30;
	var speed = parseInt(shipspec["max_flight_speed"]);
	if (isNaN(speed)) speed = 350;
	var pitch = parseFloat(shipspec["max_flight_pitch"]);
	if (isNaN(pitch)) pitch = 1;
	var roll = parseFloat(shipspec["max_flight_roll"]);
	if (isNaN(roll)) roll = 2;
	if (shipspec["max_flight_yaw"]) {
		var yaw = parseFloat(shipspec["max_flight_yaw"]);
	} else {
		var yaw = pitch;
	}
	var result = 0;
	var boost = 1;

	switch (calcType) {
		case "thrust":
			var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("engines", ship));
			if (boostEq != null) boost = parseFloat(boostEq.scriptInfo.thrust_adjust);
			result = ((thrust * parseFloat(info.scriptInfo.thrust_adjust)) * boost * (1 - (weight / (maxweight * this._weightFactor)))) * damageFactor;
			break;
		case "speed":
			var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("engines", ship));
			if (boostEq != null) boost = parseFloat(boostEq.scriptInfo.speed_adjust);
			result = ((speed * parseFloat(info.scriptInfo.speed_adjust)) * boost * (1 - (weight / (maxweight * this._weightFactor)))) * damageFactor;
			break;
		case "pitch":
			var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("thrusters", ship));
			if (boostEq != null) boost = parseFloat(boostEq.scriptInfo.pitch_adjust);
			result = ((pitch * parseFloat(info.scriptInfo.pitch_adjust)) * boost * (1 - (weight / (maxweight * this._weightFactor)))) * damageFactor;
			break;
		case "roll":
			var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("thrusters", ship));
			if (boostEq != null) boost = parseFloat(boostEq.scriptInfo.roll_adjust);
			result = ((roll * parseFloat(info.scriptInfo.roll_adjust)) * boost * (1 - (weight / (maxweight * this._weightFactor)))) * damageFactor;
			break;
		case "yaw":
			var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("thrusters", ship));
			if (boostEq != null) boost = parseFloat(boostEq.scriptInfo.pitch_adjust);
			result = ((yaw * parseFloat(info.scriptInfo.yaw_adjust)) * boost * (1 - (weight / (maxweight * this._weightFactor)))) * damageFactor;
			break;
	}

	if (loadData) shipspec = null;

	return result;
}

//-------------------------------------------------------------------------------------------------------------
// adjust the ships performance based on equipment and weight
this.$updateShipSpecs = function $updateShipSpecs(ship) {

	if (!ship || ship.isValid === false) return;

	var shipspec = Ship.shipDataForKey(ship.dataKey);
	var weight = this.$calcEquipmentWeight(ship);
	var mass = this.$getShipMass(ship);
	var maxweight = this.$calcShipMaxWeight(ship.shipClassName, mass);
	if (maxweight < weight) maxweight = weight;
	var check = "";

	/*if (this._debug && ship.isPlayer) {
		log(this.name, "Pre settings for ship " + ship + ":");
		log(this.name, "Max Thrust:           " + ship.maxThrust);
		log(this.name, "Max Speed:            " + ship.maxSpeed);
		log(this.name, "Hyperspace Spin Time: " + ship.hyperspaceSpinTime);
		log(this.name, "Pitch:                " + ship.maxPitch);
		log(this.name, "Roll:                 " + ship.maxRoll);
		log(this.name, "Yaw:                  " + ship.maxYaw);
		log(this.name, "Max Energy:           " + ship.maxEnergy);
		if (ship.isPlayer) {
			log(this.name, "Front Shield:         " + ship.maxForwardShield);
			log(this.name, "Aft Shield:           " + ship.maxAftShield);
		}
		log(this.name, "Heat Shield:          " + ship.heatInsulation);
		log(this.name, "Injector Burn Rate:   " + ship.injectorBurnRate);
		log(this.name, "Injector Speed Factor:" + ship.injectorSpeedFactor);
	}*/

	// boosters (if installed)
	var bstr = this.$equipmentItemInUse("boosters", ship);
	ship.script._boosterHeatPoint = 0;
	if (ship.equipmentStatus(bstr) === "EQUIPMENT_OK") {
		var boostEq = EquipmentInfo.infoForKey(bstr);
		if (boostEq != null) ship.script._boosterHeatPoint = boostEq.scriptInfo.heat_buildup;
	}

	// engine performance
	check = ship.equipmentStatus(this.$equipmentItemInUse("engines", ship));
	if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
		var dam = 1;
		if (check === "EQUIPMENT_DAMAGED") dam = 0.67;
		ship.maxSpeed = this.$calculatedValue("speed", ship, shipspec, boostEq, weight, maxweight, dam);
		ship.maxThrust = this.$calculatedValue("thrust", ship, shipspec, boostEq, weight, maxweight, dam);
		ship.thrust = ship.maxThrust;
	}

	// hyperspace performance
	if (this.$shipHasHyperspaceMotor(ship.dataKey) === true && this._OXPHyperdrives === false) {
		check = ship.equipmentStatus(this.$equipmentItemInUse("hyperdrive", ship));
		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
			if (check === "EQUIPMENT_OK") {
				var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("hyperdrive", ship));
				ship.hyperspaceSpinTime = parseInt(info.scriptInfo.spin_time);
			} else {
				ship.hyperspaceSpinTime = 50;
			}
		}
	}

	// thruster performance
	check = ship.equipmentStatus(this.$equipmentItemInUse("thrusters", ship));
	if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
		var dam = 1;
		if (check === "EQUIPMENT_DAMAGED") dam = 0.75;
		ship.maxPitch = this.$calculatedValue("pitch", ship, shipspec, boostEq, weight, maxweight, dam);
		ship.maxRoll = this.$calculatedValue("roll", ship, shipspec, boostEq, weight, maxweight, dam);
		ship.maxYaw = this.$calculatedValue("yaw", ship, shipspec, boostEq, weight, maxweight, dam);
	}


	// energy banks
	check = ship.equipmentStatus(this.$equipmentItemInUse("energy", ship));
	if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
		var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("energy", ship));
		var initial = 200;
		if (typeof shipspec["max_energy"] != "undefined") initial = parseInt(shipspec["max_energy"]);
		var checkbanks = Math.floor(initial / 64);
		if (checkbanks === 0) checkbanks = 1;
		if (checkbanks != parseInt(info.scriptInfo.energy_banks)) {
			initial = (parseInt(info.scriptInfo.energy_banks) * 64);
		}
		if (check === "EQUIPMENT_DAMAGED" && ship.isPlayer) {
			if (this._energyRechargeRate_Stored === 0) this._energyRechargeRate_Stored = ship.energyRechargeRate;
			ship.energyRechargeRate = 0;
		}
		ship.maxEnergy = initial;
		ship.energy = ship.maxEnergy;
	}

	// shield settings
	this.$updateShieldValues(ship);

	// heat shield
	check = ship.equipmentStatus(this.$equipmentItemInUse("heatshields", ship));
	ship.script._heat_sink_factor = parseFloat(this._defaultHeatShieldHSFactor);
	/*
	// work out how fast cabin heat will rise
	// smaller ships will heat faster, larger ships will heat slower
	if (this._shipHeatRateExceptions[ship.shipClassName]) {
		ship.script._heat_rate = this._shipHeatRateExceptions[ship.shipClassName];
	} else {
		//ship.script._heat_rate = 1 + (((214737.6875 - mass) / (mass > 214737 ? 50000 : 70000)) * 0.1);
		ship.script._heat_rate = 1 + (((250000 - mass) / (mass * 0.9)) * 0.15);
		//ship.script._heat_rate = 1 + ((1 - (mass / 500000)) / 1.2);

		if (this._debug && ship.isPlayer) log(this.name, "ship heat rate = " + ship.script._heat_rate);
	}
	*/

	// set the default heat shield value first
	var shipdef = 1;
	if (typeof shipspec["heat_insulation"] != "undefined") shipdef = parseFloat(shipspec["heat_insulation"]);
	ship.heatInsulation = shipdef;
	if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
		if (check === "EQUIPMENT_OK") {
			var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("heatshields", ship));
			ship.heatInsulation = shipdef + parseFloat(info.scriptInfo.oolite_heat_insulation_strength);
			ship.script._heat_sink_factor = parseFloat(info.scriptInfo.heat_sink_factor);
		}
	}

	// fuel injection
	check = ship.equipmentStatus(this.$equipmentItemInUse("fuelinjectors", ship));
	if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
		var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("fuelinjectors", ship));
		var burn = 0.25;
		if (typeof shipspec["injector_burn_rate"] != "undefined") burn = shipspec["injector_burn_rate"];
		ship.injectorBurnRate = parseFloat(burn) * parseFloat(info.scriptInfo.burn_rate);
		var factor = 7;
		if (typeof shipspec["injector_speed_factor"] != "undefined") factor = shipspec["injector_speed_factor"];
		ship.injectorSpeedFactor = parseFloat(factor) * parseFloat(info.scriptInfo.speed_factor);
	}

	// fuel scoops
	check = ship.equipmentStatus(this.$equipmentItemInUse("fuelscoops", ship));
	if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
		var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("fuelscoops", ship));
		ship.script._fuelScoopAccumulator = parseFloat(info.scriptInfo.accumulator_size);
	}

	/*if (this._debug && ship.isPlayer) {
		log(this.name, "Post settings:");
		log(this.name, "Max Thrust:           " + ship.maxThrust);
		log(this.name, "Max Speed:            " + ship.maxSpeed);
		log(this.name, "Hyperspace Spin Time: " + ship.hyperspaceSpinTime);
		log(this.name, "Pitch:                " + ship.maxPitch);
		log(this.name, "Roll:                 " + ship.maxRoll);
		log(this.name, "Yaw:                  " + ship.maxYaw);
		log(this.name, "Max Energy:           " + ship.maxEnergy);
		if (ship.isPlayer) {
			log(this.name, "Front Shield:         " + ship.maxForwardShield);
			log(this.name, "Aft Shield:           " + ship.maxAftShield);
		}
		log(this.name, "Heat Shield:          " + ship.heatInsulation);
		log(this.name, "Injector Burn Rate:   " + ship.injectorBurnRate);
		log(this.name, "Injector Speed Factor:" + ship.injectorSpeedFactor);
	}*/
}

//-------------------------------------------------------------------------------------------------------------
// due to their complexity, shield settings are performed in this separate routine
// this allows us to call it from multiple places
this.$updateShieldValues = function $updateShieldValues(ship) {

	var check = "";

	// shields (only for the player ship)
	if (ship.isPlayer) {
		// force the naval grid to update
		if (ship.equipmentStatus("EQ_NAVAL_GRID") === "EQUIPMENT_OK" || ship.equipmentStatus("EQ_ENERGY_GRID") === "EQUIPMENT_OK") {
			var ng = worldScripts["Naval Grid"];
			if (ng) ng._ng_player_modifiers();
		}

		var ctrl = worldScripts["Oolite Equipment Control"];
		// make sure the baselines have been set before we go any further.
		if (typeof ctrl.$baseline.maxForwardShield === "undefined") ctrl.playerBoughtNewShip();

		var eq = this.$equipmentItemInUse("frontshields", ship);
		check = ship.equipmentStatus(eq);
		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
			var info = EquipmentInfo.infoForKey(eq);

			// need to apply shield booster and naval shield booster values
			if (eq === "EQ_NO_FORWARD_SHIELD") {
				ship.maxForwardShield = 0;
			} else if (check === "EQUIPMENT_DAMAGED") {
				//if (this._forwardShieldRechargeRate_Stored === 0) this._forwardShieldRechargeRate_Stored = ship.forwardShieldRechargeRate;
				ship.forwardShieldRechargeRate = -0.5;
			} else {
				// reset the shield values
				var base = ship.maxForwardShield;
				if (typeof ctrl.$baseline.maxForwardShield != "undefined") base = ctrl.$baseline.maxForwardShield;
				ship.maxForwardShield = base + parseFloat(info.scriptInfo.oolite_shield_increase);
				ship.forwardShieldRechargeRate = 2;
				if (ship.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
					var boost = EquipmentInfo.infoForKey("EQ_SHIELD_BOOSTER");
					ship.maxForwardShield += parseFloat(boost.scriptInfo.oolite_shield_increase);
					ship.forwardShieldRechargeRate *= parseFloat(boost.scriptInfo.oolite_shield_recharge_multiplier);
				}
				if (ship.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
					var boost = EquipmentInfo.infoForKey("EQ_NAVAL_SHIELD_BOOSTER");
					ship.maxForwardShield += parseFloat(boost.scriptInfo.oolite_shield_increase);
					ship.forwardShieldRechargeRate *= parseFloat(boost.scriptInfo.oolite_shield_recharge_multiplier);
				}
			}
			if (ship.docked) ship.forwardShield = ship.maxForwardShield;
		}

		eq = this.$equipmentItemInUse("aftshields", ship);
		check = ship.equipmentStatus(eq);
		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
			var info = EquipmentInfo.infoForKey(eq);

			// need to apply shield booster and naval shield booster values
			if (eq === "EQ_NO_AFT_SHIELD") {
				ship.maxAftShield = 0;
			} else if (check === "EQUIPMENT_DAMAGED") {
				//if (this._aftshieldsRechargeRate_Stored === 0) this._aftshieldsRechargeRate_Stored = ship.aftShieldRechargeRate;
				ship.aftShieldRechargeRate = -0.5;
			} else {
				var base = ship.maxAftShield;
				if (typeof ctrl.$baseline.maxAftShield != "undefined") base = ctrl.$baseline.maxAftShield;
				ship.aftShieldRechargeRate = 2;
				ship.maxAftShield = base + parseFloat(info.scriptInfo.oolite_shield_increase);
				if (ship.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
					var boost = EquipmentInfo.infoForKey("EQ_SHIELD_BOOSTER");
					ship.maxAftShield += parseFloat(boost.scriptInfo.oolite_shield_increase);
					ship.aftShieldRechargeRate *= parseFloat(boost.scriptInfo.oolite_shield_recharge_multiplier);
				}
				if (ship.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
					var boost = EquipmentInfo.infoForKey("EQ_NAVAL_SHIELD_BOOSTER");
					ship.maxAftShield += parseFloat(boost.scriptInfo.oolite_shield_increase);
					ship.aftShieldRechargeRate *= parseFloat(boost.scriptInfo.oolite_shield_recharge_multiplier);
				}
			}
			if (ship.docked) ship.aftShield = ship.maxAftShield;
		}
	} else {
		// NPC's only have shields if one of these OXP's is installed.
		if (worldScripts["customshields"] || worldScripts["NPC-shields"]) {
			// based on the way things are set up, we should be confident that customshields has set the right value by now.
			// we're going to redo the settings, based on the factor that equipment choices might have moved things up or down
			// with customshields, the recharge rate is already handled, and as ShipConfig doesn't have any special equipment that adjusts the recharge rate, we can leave that part alone.
			// start with the front shields
			var front_shield = 0;
			var eq = this.$equipmentItemInUse("frontshields", ship);
			check = ship.equipmentStatus(eq);
			if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
				var info = EquipmentInfo.infoForKey(eq);

				// need to apply shield booster and naval shield booster values
				if (eq === "EQ_NO_FORWARD_SHIELD" || check === "EQUIPMENT_DAMAGED") {
					front_shield = 0;
				} else {
					// reset the shield values
					var base = 128;
					front_shield = base + parseFloat(info.scriptInfo.oolite_shield_increase);
					if (ship.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
						var boost = EquipmentInfo.infoForKey("EQ_SHIELD_BOOSTER");
						front_shield += parseFloat(boost.scriptInfo.oolite_shield_increase);
					}
					if (ship.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
						var boost = EquipmentInfo.infoForKey("EQ_NAVAL_SHIELD_BOOSTER");
						front_shield += parseFloat(boost.scriptInfo.oolite_shield_increase);
					}
				}
			}
			// now the aft shields
			var aft_shield = 0;
			var eq = this.$equipmentItemInUse("aftshields", ship);
			check = ship.equipmentStatus(eq);
			if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
				var info = EquipmentInfo.infoForKey(eq);

				// need to apply shield booster and naval shield booster values
				if (eq === "EQ_NO_AFT_SHIELD" || check === "EQUIPMENT_DAMAGED") {
					aft_shield = 0;
				} else {
					// reset the shield values
					var base = 128;
					aft_shield = base + parseFloat(info.scriptInfo.oolite_shield_increase);
					if (ship.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
						var boost = EquipmentInfo.infoForKey("EQ_SHIELD_BOOSTER");
						aft_shield += parseFloat(boost.scriptInfo.oolite_shield_increase);
					}
					if (ship.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
						var boost = EquipmentInfo.infoForKey("EQ_NAVAL_SHIELD_BOOSTER");
						aft_shield += parseFloat(boost.scriptInfo.oolite_shield_increase);
					}
				}
			}
			// now we have the correct shield amount, apply it to the appropriate OXP
			if (worldScripts["customshields"]) {
				ship.script.customshieldsmaxforwardshieldlevel = front_shield;
				ship.script.customshieldsmaxaftshieldlevel = aft_shield;
			}
			if (worldScripts["NPC-shields"]) {
				// this OXP only has 1 shield value, so we'll ignore the aft shields in this instance
				ship.script.maxShieldStrength = front_shields;
				ship.script.shieldStrength = front_shields;
			}
		}
	}

}

//-------------------------------------------------------------------------------------------------------------
// returns the total amount of equipment space available for a ship of a particular mass
// a cobra mk3 should have about 20t of equipment space
this.$equipmentSpaceTotal = function $equipmentSpaceTotal(ship) {
	if (!ship) return 0;
	// cobra3 			214737.6875 or 219634.265625
	// moray starboat	51203.4375
	// adder			16045.4931640625
	// python			259688.28125
	// cobra1			52291.8359375
	// miner			12074.4453125
	// gecko			24669.99609375

	// check for an exception entry for this ship data key
	if (this._shipSpaceExceptions[ship.shipClassName] && this._shipSpaceExceptions[ship.shipClassName] != "") {
		// we'll trust this number to be correct
		space = parseInt(this._shipSpaceExceptions[ship.shipClassName]);
	} else {
		// do a calc
		var space = parseInt((this.$getShipMass(ship) / 429475.375) * 40);

		if (space < 15) space = 15; // min of 15
		// do a check on cargo capacity
		if (space < 20) {
			var cargo = this.$getCargoCapacity(ship)
			// if our calc is less than 20 but the cargo is greater than 35, then set the min to 20 and add an extra 1 of equip space for each 5 tons of cargo space above 35 tons
			if (cargo > 35) space = 20 + parseInt((cargo - 35) / 5);
		}
		if (space > 40) space = 40; // max of 40
	}
	var ext = this.$getEquipmentExtensions(ship);
	return (space + ext);
}

//-------------------------------------------------------------------------------------------------------------
// external routine to return the equipment space and cargo space for a ship key
// we'll create a temporary ship object and use that to get the details
// returns a dictionary with 3 elements: "equipSpace", "cargoSpace", and "mass"
this.$getEquipmentSpaceFromShipKey = function $getEquipmentSpaceFromShipKey(shipKey) {
	var result = {};
	// find a spot well away from any possible objects
	if (system.sun) {
		var temppos = system.sun.position.cross(system.mainPlanet.position).direction().multiply(4E9).subtract(system.mainPlanet.position);
	} else {
		var temppos = Vector3D(0, 0, 0);
	}
	// add a ship with the particular key
	var tempship = system.addShips("[" + shipKey + "]", 1, temppos, 0);
	if (tempship != null) {
		// force this ship to be "dead" in space - we don't want it to do anything disruptive!
		tempship[0].switchAI("oolite-nullAI.js");
		// now we have a ship, we can use the standard functions for calculating available space
		result["equipSpace"] = this.$equipmentSpaceTotal(tempship[0]);
		result["cargoSpace"] = this.$cargoSpaceAvailable(tempship[0]);
		result["mass"] = this.$getShipMass(tempship[0]);
		// clean up our temp ship
		tempship[0].remove(true);
	} else {
		// this could happen if the ship is not allowed to be spawned in this system due to constraints in the shipdata.plist file for the ship
		result["equipSpace"] = "N/A";
		result["cargoSpace"] = "N/A";
		result["mass"] = "N/A";
	}
	return result;
}

//-------------------------------------------------------------------------------------------------------------
// returns the max permissible amount of cargo space that can be converted to equipment space
// attempting to avoid the issue of buying an anaconda and just putting max of everything in it.
this.$cargoSpaceAvailable = function $cargoSpaceAvailable(ship) {
	if (!ship) return 0;

	var reduction = this.$checkCargoReduction(ship);
	var maxCargo = this.$getCargoCapacity(ship);
	var curCargo = maxCargo - reduction;
	// if the ship doesn't have any cargo space to allocate, return 0
	if (curCargo === 0) return 0;

	var calc = parseInt(maxCargo * 0.75);
	if (calc > curCargo) calc = curCargo;

	if (calc > 40) {
		return 40;
	} else {
		// ships with small cargo holds can allocate it all
		if (calc < 10) {
			return curCargo;
		} else {
			return calc;
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// returns the current cargo space conversion amount
this.$cargoEquipmentSpaceAmount = function $cargoEquipmentSpaceAmount(ship) {
	if (!ship) return 0;

	for (var i = 0; i < this._filler.length; i++) {
		if (ship.equipmentStatus(this._filler[i]) === "EQUIPMENT_OK") return (i + 1);
	}
	return 0;
}

//-------------------------------------------------------------------------------------------------------------
// returns the space current available for equipment (including available reused cargo space)
this.$availableEquipmentSpace = function $availableEquipmentSpace(ship) {
	var equipSpace = this.$equipmentSpaceTotal(ship);
	var cargoSpace = this.$cargoSpaceAvailable(ship); // + this.$cargoEquipmentSpaceAmount(p));
	var used = this.$calcEquipmentSpace(ship);
	return ((equipSpace + cargoSpace) - used);
}

//-------------------------------------------------------------------------------------------------------------
// get the original capacity for this ship
// this will be independant of any item that reduces the cargo bay (eg passenger berths)
this.$getCargoCapacity = function $getCargoCapacity(ship) {
	if (!ship) return 0;

	var shipData = Ship.shipDataForKey(ship.dataKey);
	if (!shipData) return 0;
	var cargoAvail = 0;
	if (shipData["max_cargo"]) cargoAvail = parseInt(shipData["max_cargo"]);
	if (ship.equipmentStatus("EQ_CARGO_BAY") === "EQUIPMENT_OK") {
		var extra = 15;
		if (shipData["extra_cargo"]) extra = parseInt(shipData["extra_cargo"]);
		cargoAvail += extra;
	}
	return cargoAvail;
}

//-------------------------------------------------------------------------------------------------------------
// returns the total of equip items that that up cargo space
this.$checkCargoReduction = function $checkCargoReduction(ship) {
	var total = 0;
	var eq = ship.equipment;
	var mult = 0;
	// check that the equipment element is valid (it might not be after an ejection)
	if (!eq) return 0;
	for (var i = 0; i < eq.length; i++) {
		var itm = eq[i];
		if (this._filler.indexOf(itm.equipmentKey) >= 0) continue;
		mult = 1;
		if (itm.requiredCargoSpace > 0) {
			if (itm.equipmentKey === "EQ_PASSENGER_BERTH") mult = ship.passengerCapacity;
			total += itm.requiredCargoSpace * mult;
		}
	}
	return total;
}

//-------------------------------------------------------------------------------------------------------------
// returns the amount of space taken up by all ship equipment
this.$calcEquipmentSpace = function $calcEquipmentSpace(ship) {

	if (!ship) return 0;

	var equipSpace = this.$equipmentSpaceTotal(ship);
	//var cargoSpace = this.$cargoSpaceAvailable(ship);
	var used = 0;

	// cycle through the installed equipment
	var eq = ship.equipment;
	if (!eq) return 0;
	for (var i = 0; i < eq.length; i++) {
		var e_item = eq[i];
		if (this._ignoreEquip.indexOf(e_item.equipmentKey) >= 0) continue;
		if (!this._equipmentMatrix[e_item.equipmentKey]) {
			// don't know what this is, so try to work it out
			//var info = EquipmentInfo.infoForKey(e_item.equipmentKey);
			if (e_item.isVisible === true && e_item.requiredCargoSpace === 0) {
				// if it's not taking up space already, assume 1t
				used += 1;
				if (this._debug) log(this.name, "didn't find " + e_item.equipmentKey + " in matrix, using default");
			}
		} else {
			used += this._equipmentMatrix[e_item.equipmentKey][0];
		}
	}
	return used;
}

//-------------------------------------------------------------------------------------------------------------
// calculates a price factor for equipment, based on ship mass
this.$equipmentPriceFactor = function $equipmentPriceFactor(shipClass, shipMass, techlvl, sysID) {
	var factor = shipMass / 100000;
	if (factor < 0.4) factor = 0.4;
	if (factor > 3) factor = 3;
	// the cobra is the exception
	if (shipClass === "Cobra Mark III") {
		factor = 1;
	}
	if (typeof techlvl == "undefined") {
		// I've taken out the station equivalent tech level, because it's being applied in other ways
		//if (player.ship.dockedStation && player.ship.dockedStation.equivalentTechLevel < 16) {
		//	techlvl = player.ship.dockedStation.equivalentTechLevel;
		//} else {
		techlvl = system.info.techlevel;
		//}
	}
	if (typeof sysID == "undefined") sysID = system.ID;
	//if (this._debug) log(this.name, "price factor (pre tl factor)= " + factor);
	return (factor * this.$equipmentTechFactor(techlvl, sysID));
}

//-------------------------------------------------------------------------------------------------------------
// returns a calculated max weight for a shipclass
this.$calcShipMaxWeight = function $calcShipMaxWeight(shipClass, shipMass) {
	// cobra3 			214737.6875 or 219634.265625
	// anaconda			437686.875
	// moray starboat	51203.4375
	// adder			16045.4931640625
	// python			259688.28125
	// cobra1			52291.8359375
	// miner			12074.4453125
	// constrictor		28490.8984375
	// asp mk ii		75881.5625
	// ferdelance		65457.94921875
	// boa				181788.90625
	// Boa cc			215810.5
	// gecko			24669.99609375
	// krait			93291.40625
	// sidewinder		24966.326171875
	// transporter		12074.4453125
	// worm 			14597.208984375
	var mult = 1;
	if (this._shipPowerToWeight[shipClass]) {
		// get the preset value, if stored
		mult = this._shipPowerToWeight[shipClass];
	} else {
		// smaller ships have a greater power to weight ratio
		// add 1 point for every 15000 under 100000
		if (shipMass < 100000) mult = mult + (1 * (100000 - shipMass) / 15000);
		// larger ships have a lower power to weight ratio
		// take off 0.1 point for every 50000 over 200000
		if (shipMass > 200000) mult = mult - (0.1 * ((shipMass - 200000) / 50000));
	}
	var weight = ((shipMass * mult) / 700);
	return weight;
}

//-------------------------------------------------------------------------------------------------------------
// returns the weight (in whole t's) of all equipment and cargo on a ship
this.$calcEquipmentWeight = function $calcEquipmentWeight(ship) {

	if (!ship) return 0;

	var weight = 0;

	// any weapons?
	if (ship.aftWeapon && ship.aftWeapon.equipmentKey != "EQ_WEAPON_NONE") {
		weight += this.$weaponWeight(ship.aftWeapon.equipmentKey);
	}
	if (ship.forwardWeapon && ship.forwardWeapon.equipmentKey != "EQ_WEAPON_NONE") {
		weight += this.$weaponWeight(ship.forwardWeapon.equipmentKey);
	}
	if (ship.portWeapon && ship.portWeapon.equipmentKey != "EQ_WEAPON_NONE") {
		weight += this.$weaponWeight(ship.portWeapon.equipmentKey);
	}
	if (ship.starboardWeapon && ship.starboardWeapon.equipmentKey != "EQ_WEAPON_NONE") {
		weight += this.$weaponWeight(ship.starboardWeapon.equipmentKey);
	}

	// any missiles?
	if (ship.missileCapacity > 0) {
		var noerr = false;
		// have to do this because attempting to access ship.missiles when no missiles are installed will generate an Objective-C error
		try {
			var miss = ship.missiles;
			noerr = true;
		} catch (err) {
			if (this._debug && ship.isPlayer) log(this.name, "!!ERROR: " + err);
		}
		if (noerr) {
			for (var i = 0; i < miss.length; i++) {
				if (this._ignoreEquip.indexOf(miss[i].equipmentKey) >= 0) continue;
				if (!this._equipmentMatrix[miss[i].equipmentKey]) {
					weight += 1;
				} else {
					weight += this._equipmentMatrix[miss[i].equipmentKey][1];
				}
			}
		}
	}

	// cycle through the installed equipment
	var eq = ship.equipment;
	for (var i = 0; i < eq.length; i++) {
		var e_item = eq[i];
		if (this._ignoreEquip.indexOf(e_item.equipmentKey) >= 0) continue;
		if (!this._equipmentMatrix[e_item.equipmentKey]) {
			// don't know what this is, so try to work it out
			var info = EquipmentInfo.infoForKey(e_item.equipmentKey);
			// add it up if it's either (a) visible or (b) taking up space
			if (info.isVisible === true || info.requiredCargoSpace > 0) {
				if (info.requiredCargoSpace === 0) {
					// if it's not taking up space already, assume 1t
					weight += 1;
				} else {
					weight += info.requiredCargoSpace;
					if (info.equipmentKey === "EQ_PASSENGER_BERTH") weight *= ship.passengerCapacity;
				}
			}
		} else {
			weight += this._equipmentMatrix[e_item.equipmentKey][1];
		}
	}
	// special items:
	// LMSS weapons
	var lmss = worldScripts.LMSS_Core;
	if (lmss) {
		if (lmss._forwardAltKey != "EQ_WEAPON_NONE" && lmss._forwardAltKey != "") {
			weight += this.$weaponWeight(lmss._forwardAltKey);
		}
		if (lmss._aftAltKey != "EQ_WEAPON_NONE" && lmss._aftAltKey != "") {
			weight += this.$weaponWeight(lmss._aftAltKey);
		}
		if (lmss._portAltKey != "EQ_WEAPON_NONE" && lmss._portAltKey != "") {
			weight += this.$weaponWeight(lmss._portAltKey);
		}
		if (lmss._starboardAltKey != "EQ_WEAPON_NONE" && lmss._starboardAltKey != "") {
			weight += this.$weaponWeight(lmss._starboardAltKey);
		}
	}

	// add cargo weight
	if (this.$getCargoCapacity(ship) > 0 && ship.cargoList.length > 0) {
		for (var i = 0; i < ship.cargoList.length; i++) {
			var itm = ship.cargoList[i];
			switch (itm.unit) {
				case "t":
					weight += itm.quantity;
					break;
				case "kg":
					weight += (itm.quantity / 1000);
					break;
				case "g":
					weight += (itm.quantity / 1000000);
					break;
			}
		}
	}

	if (ship.isPlayer) {
		var smuggling = worldScripts.Smugglers_Equipment;
		if (smuggling) {
			// add the weight of any cargo in the smuggling compartment
			var cargo = smuggling.$getSmugglingCargo();

			for (var i = 0; i < cargo.length; i++) {
				switch (cargo[i].unit) {
					case "t":
						weight += cargo[i].quantity;
						break;
					case "kg":
						weight += (cargo[i].quantity / 1000);
						break;
					case "g":
						weight += (cargo[i].quantity / 1000000);
						break;
				}
			}
		}
	}

	return weight;
}

//-------------------------------------------------------------------------------------------------------------
// returns the weight (or calculated weight) of a paricular weapon
this.$weaponWeight = function $weaponWeight(weaponKey) {
	if (weaponKey === "EQ_WEAPON_NONE") return 0;
	if (!this._equipmentMatrix[weaponKey]) {
		var info = EquipmentInfo.infoForKey(weaponKey);
		// calc weight based on weapon range
		if (info && info.weaponInfo) {
			if (info.weaponInfo.range < 12000) {
				return 1;
			} else if (info.weaponInfo.range < 20000) {
				return 3;
			} else {
				return 5;
			}
		} else {
			// weird... shouldn't really happen
			return 1;
		}
	} else {
		return this._equipmentMatrix[weaponKey][1];
	}
}

//-------------------------------------------------------------------------------------------------------------
// 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;
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padTextRight = function $padTextRight(currentText, desiredLength, leftSwitch) {
	if (currentText == null) currentText = "";
	var space = " ";
	var hairSpace = String.fromCharCode(31);
	var ellip = "…";
	var currentLength = defaultFont.measureString(currentText.replace(/%%/g, "%"));
	var hairSpaceLength = defaultFont.measureString(hairSpace);
	var spaceLength = defaultFont.measureString(space);
	// calculate number needed to fill remaining length
	var spacesNeeded = parseInt(Math.floor((desiredLength - currentLength) / spaceLength));
	if (spacesNeeded < 0) {
		spacesNeeded = 0;
	} else {
		if (!leftSwitch || leftSwitch === false) {
			currentText += new Array(spacesNeeded).join(space);
		} else {
			currentText = new Array(spacesNeeded).join(space) + currentText;
		}
		currentLength = defaultFont.measureString(currentText.replace(/%%/g, "%"));
	}
	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.replace(/%%/g, "%")) > desiredLength);
		currentLength = defaultFont.measureString(tmp.replace(/%%/g, "%"));
		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);
}

//-------------------------------------------------------------------------------------------------------------
// adds any equipment space/weight values from script_info data
// this way we can just look in our array, rather than in two places
// this is only run once at startup
this.$addEquipmentDataFromScriptInfo = function $addEquipmentDataFromScriptInfo() {
	var eqlist = EquipmentInfo.allEquipment;
	for (var i = 0; i < eqlist.length; i++) {
		var eq = eqlist[i];
		if (eq.isVisible && eq.scriptInfo) {
			var space = -1;
			var weight = -1;
			if (eq.scriptInfo.equipment_space && parseFloat(eq.scriptInfo.equipment_space) >= 0) space = parseFloat(eq.scriptInfo.equipment_space);
			if (eq.scriptInfo.equipment_weight && parseFloat(eq.scriptInfo.equipment_weight) >= 0) weight = parseFloat(eq.scriptInfo.equipment_weight);
			// have we only been given a space setting? assume weight is the same
			if (space >= 0 && weight === -1) weight = space;
			// if the space or weight values are greater than zero, add the definition to the matrix
			if (space > 0 || weight > 0) this._equipmentMatrix[eq.equipmentKey] = [space, weight];
			// if the values are both zero, add it to the ignored list
			if (space === 0 && weight === 0) this._ignoreEquip.push(eq.equipmentKey);
		}
		// look for any equipment items that are outside the bounds for general sale but could potentially be sold (as they take up space/weight)
		if (this._ignoreEquip.indexOf(eq.equipmentKey) === -1 && eq.isVisible && eq.techLevel >= 15 && eq.techLevel < 100 && eq.effectiveTechLevel >= 15 && eq.isAvailableToPlayer === true && eq.isExternalStore === false) {
			var wt = 0;
			if (!this._equipmentMatrix[eq.equipmentKey]) {
				// don't know what this is, so try to work it out
				// add it up if it's either (a) visible or (b) taking up space
				if (eq.requiredCargoSpace > 0) {
					wt = eq.requiredCargoSpace;
				} else {
					wt = 1;
				}
			} else {
				wt = this._equipmentMatrix[eq.equipmentKey][1];
			}
			if (wt > 0) this._sellNegotiate.push(eq.equipmentKey);
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// adds script info data from ship data keys
// this way we can just look in our arrays, rather than in two places
// this is only run once at startup
this.$addShipDataFromScriptInfo = function $addShipDataFromScriptInfo() {
	var shipkeys = Ship.keys();
	for (var i = 0; i < shipkeys.length; i++) {
		var shipspec = Ship.shipDataForKey(shipkeys[i]);
		if (shipspec["script_info"]) {
			if (shipspec["script_info"].equipment_space) {
				var space = parseInt(shipspec["script_info"].equipment_space);
				this._shipSpaceExceptions[shipspec.name] = space;
			}
			if (shipspec["script_info"].power_to_weight) {
				var ratio = parseFloat(shipspec["script_info"].power_to_weight);
				this._shipPowerToWeight[shipspec.name] = ratio;
			}
			if (shipspec["script_info"].role_translation) {
				var def = shipspec["script_info"].role_translation;
				if (def.indexOf("|") >= 0) {
					var pri = def.split("|")[0].trim();
					var trans = def.split("|")[1].trim();
					if (pri.length > 0 && trans.length > 0) this._NPCEquivalents[pri] = trans;
				}
			}
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// player the buy/sell sound effects
this.$playSound = function $playSound(soundtype) {
	var mySound = new SoundSource;
	switch (soundtype) {
		case "explosion":
			mySound.sound = "[player-scrape-damage]";
			break;
		case "buy":
			mySound.sound = "[buy-commodity]";
			break;
		case "sell":
			mySound.sound = "[sell-commodity]";
			break;
		case "deploy_heat_sink":
			mySound.sound = "heat_sink_deployed.ogg";
			break;
		case "booster_warning":
			if (this._disableBoosterSound === true) return;
			mySound.sound = "booster_warning.ogg";
			break;
		case "leak":
			mySound.sound = "[fuel-leak]";
			break;
	}
	mySound.loop = false;
	mySound.play();
}

//-------------------------------------------------------------------------------------------------------------
// returns the standard maximum speed for a ship
this.$getShipSpecSpeed = function $getShipSpecSpeed(ship) {
	var spec = Ship.shipDataForKey(ship.dataKey);
	var specspeed = parseInt(spec["max_flight_speed"]);
	return specspeed;
}

//-------------------------------------------------------------------------------------------------------------
// returns the ships mass, either from the exception list, or from the ship itself
this.$getShipMass = function $getShipMass(ship) {
	var mass = this._shipMassExceptions[ship.shipClassName];
	if (!mass) mass = ship.mass;
	return mass;
}

//-------------------------------------------------------------------------------------------------------------
// returns true if the ship data spec says this ship has a hyperspace motor
this.$shipHasHyperspaceMotor = function $shipHasHyperspaceMotor(shipDataKey) {
	var check = Ship.shipDataForKey(shipDataKey)["hyperspace_motor"];
	if (typeof check === "undefined") return true;
	return (this._trueValues.indexOf(check) != -1);
}

//-------------------------------------------------------------------------------------------------------------
// returns the number of heat sinks remaining
this.$countHeatSinks = function $countHeatSinks() {
	var hs = 0;
	var eq = player.ship.equipment;
	for (var i = 0; i < eq.length; i++) {
		if (eq[i].equipmentKey === "EQ_HEAT_SINK") hs += 1;
	}
	return hs;
}

//-------------------------------------------------------------------------------------------------------------
// routine to check the combat simulator worldscript, to see if it's running or not
this.$simulatorRunning = function $SimulatorRunning() {
	var w = worldScripts["Combat Simulator"];
	if (w && w.$checkFight && w.$checkFight.isRunning) return true;
	return false;
}

//-------------------------------------------------------------------------------------------------------------
// gets the sum of all equipment space extensions installed
this.$getEquipmentExtensions = function $getEquipmentExtensions(ship) {
	var ext = 0;
	var eqlist = ship.equipment;
	if (eqlist) {
		for (var i = 0; i < eqlist.length; i++) {
			var eq = eqlist[i];
			if (eq.scriptInfo.equipment_extension && parseFloat(eq.scriptInfo.equipment_extension) >= 0) ext += parseFloat(eq.scriptInfo.equipment_extension);
		}
	}
	return ext;
}

//-------------------------------------------------------------------------------------------------------------
// these routines all relate to circumventing issues with ship storage helper
//-------------------------------------------------------------------------------------------------------------
// routine to be called before a respray to set things up for a change of ship
this.$preResprayFunction = function $preResprayFunction() {
	this._startUp = true;
	this._resprayActive = true;
	// remove the equipment space item before respray, otherwise strange things seem to happen to the amount of available cargo space
	for (var i = 1; i <= 40; i++) {
		var remove = "EQ_EQUIPSPACE_" + i;
		if (player.ship.equipmentStatus(remove) === "EQUIPMENT_OK") {
			this._holdEquipSpace = remove;
			player.ship.removeEquipment(remove);
			break;
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$restoreEquipSpaceItem = function $restoreEquipSpaceItem() {
	if (this._holdEquipSpace != "") player.ship.awardEquipment(this._holdEquipSpace);
	this._startUp = false;
}

//-------------------------------------------------------------------------------------------------------------
this.$removeEquipSpaceItem = function $removeEquipSpaceItem() {
	this._removing = true;
	if (this._holdEquipSpace != "") player.ship.removeEquipment(this._holdEquipSpace);
	this._removing = false;
}

//-------------------------------------------------------------------------------------------------------------
// routine to be called after a respray to get things setup correctly again
this.$postResprayFunction = function $postResprayFunction() {
	this._current = {};
	var result = this.$installBaseEquipment(player.ship);
	this._startUp = false;
	this.equipmentAdded("");
	this._resprayActive = false;
}

//-------------------------------------------------------------------------------------------------------------
// ensures that hyperspace hangar doesn't store ships with the equipspace item
this.$updateHyperHangarShipImage = function $updateHyperHangarShipImage() {
	var hh = worldScripts.HyperspaceHangar;
	this._startUp = true;
	// remove the equipment space item before respray, otherwise strange things seem to happen to the amount of available cargo space
	for (var i = 1; i <= 40; i++) {
		var remove = "EQ_EQUIPSPACE_" + i;
		if (player.ship.equipmentStatus(remove) === "EQUIPMENT_OK") {
			this._holdEquipSpace = remove;
			player.ship.removeEquipment(remove);
			break;
		}
	}
	// put the updated storage data into the Hyperspace hangar variable
	hh._shipsStored[hh._shipTempKey] = worldScripts["Ship_Storage_Helper.js"].storeCurrentShip();
	// put equipment space item back again
	this.$restoreEquipSpaceItem();
}

//-------------------------------------------------------------------------------------------------------------
// we're monkey patching combat sim so we can do a couple of steps in the right order
// essentially we need to remove the equipment space item before SSH stores the ship config, then put it back immediately after so the ship will work as normal
// then, just before the ship is restored we remove the equipment space item again, allow SSH to restore the ship and then add it back again.
this.$combatSim_startFight = function $combatSim_startFight() {
	worldScripts.ShipConfiguration_Core.$preResprayFunction();
	worldScripts["Ship_Storage_Helper.js"].disableTCATPBNSFunc();
	this.$shipState = worldScripts["Ship_Storage_Helper.js"].storeCurrentShip();
	worldScripts.ShipConfiguration_Core.$restoreEquipSpaceItem();
	this._setUpHandlers();
	this._setUpEnvironment();
	player.ship.removeEquipment("EQ_ESCAPE_POD");
	player.ship.launch();
}

//-------------------------------------------------------------------------------------------------------------
// returns the price factor for equipment based on the system's techlevel
this.$equipmentTechFactor = function $equipmentTechFactor(techlvl, sysID) {
	// prices would be higher in low tech worlds, cheaper in high-tech
	// range is high tech 14 (even 15) to low tech 0
	// prices should'nt vary by too much - 0.7 - 1.3 should probably be the greatest range
	// we'll add a small variance to the price, so no two systems should have exactly the same prices
	// but the price will always be the same in that system

	var factor = (((16 - techlvl) / 16) * 0.6) + 0.7;
	var sysFactor = 0.5;
	// make sure we're not in interstellar space
	if (sysID >= 0) {
		sysFactor = system.scrambledPseudoRandomNumber(sysID);
	}
	factor *= (1 + (sysFactor * 0.1 - 0.05));
	//if (this._debug) log(this.name, "tech factor = " + factor);
	return factor;
}