| Scripts/Ship_Storage_Helper.js | "use strict";
this.name = "Ship_Storage_Helper.js";
this.author = "Capt. Murphy, Norby";
this.copyright = "2012 - Capt. Murphy";
this.license = "CC BY-NC-SA 3.0"; // see http://creativecommons.org/licenses/by-nc-sa/3.0/ for more info. This OXP is intended to be developed by the OXPer community to ensure maximum OXP compatibility with OXPs that need to store/restore the player ship.
this.credits = "A big thank-you to cim for coding the new JS commands necessary for changing player ships by script."
this.description = "Worldscript with helper functions to store/restore player ship characteristics as a variable.";
this.cargoType = ["food", "textiles", "radioactives", "slaves", "liquor_wines", "luxuries", "narcotics", "computers", "machinery", "alloys", "firearms", "furs", "minerals", "gold", "platinum", "gem_stones", "alien_items"];
this.loggingEnabled = false;
this.expectedLength = 35; // expected length of storedShipArray with current release. 
	//Must be incremented as new items are added. Used to add extra data on restore if necessary 
	// for backwards compatibility as this OXP develops.
this.dataKeyCounter = 128; // old variable, now use dataKeyMaxIt 
	//number of loop iterations used to build Array of available player dataKeys. 
	// A higher number of iterations will result in a more comprehensive list of unique dataKeys 
	// being identified (particularly if a lot of different player flyable ship OXPs are installed), 
	// but increases the chance of JS timeout/long startUp times on slower computers. However if there 
	// is timeout it will try again with a reduced number of iterations on the missionScreenOpportunity 
	// that fires shortly after startUp. Should be a power of 2.  Default value of 128 results in 
	// reasonable startUp delay on old WinXP test machine and captures around 90-95% of dataKeys when 
	// there are 60 player flyable ships actually installed. Win 7 machine can easily cope with figure 
	// of upto to 4096, with no noticeable delay
this.dataKeyMaxIt = 5; //max. iteration in Oolite v1.77, increase if you have many OXP ships, 
	// reduce if cause "Universe is full" or crash to desktop
this.dataKeyArray = new Array; // will be populated with valid player flyable dataKeys from the users 
	// currently installed OXPs at this.startUp.
this.startUp = function () {
	if (this.loggingEnabled) {
		log(this.name, "Building player dataKey Array.");
	}
	this.buildDataKeyArray(this.dataKeyMaxIt);
}
this.missionScreenOpportunity = function () {
	if (this.dataKeyArrayBuilt) {
		return;
	}
	if (this.loggingEnabled) {
		log(this.name, "Retry building player dataKey Array.");
	}
	this.dataKeyMaxIt = this.dataKeyMaxIt + 1;
	this.buildDataKeyArray(this.dataKeyMaxIt);
}
this.buildDataKeyArray = function (iterations) {
	var counter = 0;
	if (0 < oolite.compareVersion("1.79")) { //slow and limited method, use before Oolite v1.79 only
		var ship;
		var ships;
		var dataKey;
		for (counter = 0; counter < iterations; counter++) {
			ships = system.addShips("player", 64, [0, 0, 0], 1000000);
			if (ships)
				for (var j = 0; j < ships.length; j++) {
					ship = ships[j];
					if (ship) {
						dataKey = ship.dataKey;
						if (this.dataKeyArray.indexOf(dataKey) === -1)
							this.dataKeyArray.push(dataKey);
						if (ship.escorts && ship.escorts.length > 0) {
							for (var k = 0; k < ship.escorts.length; k++) {
								ship.escorts[k].remove(true);
							}
						}
						ship.remove(true);
					}
				}
		}
	} else { //Oolite v1.79 or later
		this.dataKeyArray = Ship.keysForRole("player"); //playable ships
	}
	this.dataKeyArrayBuilt = true;
	if (this.loggingEnabled) {
		var c = "";
		if (counter > 0) c = " in " + counter + " iterations.";
		log(this.name, "Unique player ship dataKeys found: " + this.dataKeyArray.length + c);
		log(this.name, "dataKeys: " + this.dataKeyArray);
	}
}
this.storeCurrentShip = function (ship) {
	if (!ship) ship = player.ship;
	var counter;
	var storedShipArray = new Array;
	var stationAttributes;
	if (ship.dockedStation) {
		stationAttributes = [ship.dockedStation.primaryRole, ship.dockedStation.dataKey, ship.dockedStation.position];
	} else {
		stationAttributes = [null, null, null];
	}
	storedShipArray.push([galaxyNumber, system.ID, clock.seconds, ship.displayName, system.name, stationAttributes, ship.price,
		ship.shipClassName, ship.shipUniqueName, ship.AIScriptWakeTime, ship.beaconLabel,
		ship.destinationSystem, ship.exhaustEmissiveColor, ship.homeSystem,
		ship.maxYaw, ship.maxPitch, ship.maxRoll, ship.maxThrust, ship.thrust,
		ship.maxSpeed, ship.maxEnergy, ship.energyRechargeRate, ship.cargoSpaceCapacity,
		ship.injectorBurnRate, ship.injectorSpeedFactor, ship.scanDescription, ship.hyperspaceSpinTime,
		ship.scannerHostileDisplayColor1, ship.scannerHostileDisplayColor2,
		ship.forwardShield, ship.maxForwardShield, ship.forwardShieldRechargeRate,
		ship.aftShield, ship.maxAftShield, ship.aftShieldRechargeRate,
		ship.passengerCapacity
	]); //storedShipArray[0][0-35]
	storedShipArray.push(ship.dataKey); // storedShipArray[1]
	if (!ship.aftWeapon) {
		storedShipArray.push(ship.aftWeapon);
	} else {
		storedShipArray.push(ship.aftWeapon.equipmentKey);
	} // storedShipArray[2]
	if (!ship.forwardWeapon) {
		storedShipArray.push(ship.forwardWeapon);
	} else {
		storedShipArray.push(ship.forwardWeapon.equipmentKey);
	} // storedShipArray[3]
	if (!ship.portWeapon) {
		storedShipArray.push(ship.portWeapon);
	} else {
		storedShipArray.push(ship.portWeapon.equipmentKey);
	} // storedShipArray[4]
	if (!ship.starboardWeapon) {
		storedShipArray.push(ship.starboardWeapon);
	} else {
		storedShipArray.push(ship.starboardWeapon.equipmentKey);
	} // storedShipArray[5]
	var missiles = [];
	if (ship.missileCapacity > 0) { //bugfix of "Tried to init array with nil object" in Oolite 1.81
		try {
			missiles = ship.missiles;
			for (counter = 0; counter < missiles.length; counter++) {
				missiles.splice(counter, 1, missiles[counter].equipmentKey);
			}
		} catch (err) {
			if (this.loggingEnabled) log(this.name, "!!ERROR: " + err);
		}
	}
	storedShipArray.push(missiles); // storedShipArray[6]
	var equipment = ship.equipment;
	var tempArray;
	for (counter = 0; counter < equipment.length; counter++) {
		tempArray = [equipment[counter].equipmentKey, ship.equipmentStatus(equipment[counter])];
		equipment.splice(counter, 1, tempArray);
	}
	storedShipArray.push(equipment); // storedShipArray[7]
    //var hold = new Array(17);
	var hold = {};
    if (ship == player.ship) {
		var ml = ship.manifest.list;
		for (counter = 0; counter < ml.length; counter++) {
			if (ml[counter].quantity > 0) hold[ml[counter].commodity] = ml[counter].quantity;
		}
        // ship is a player's ship
        //for (counter = 0; counter < 17; counter++) {
            //hold[counter] = ship.manifest[this.cargoType[counter]];
        //}
    } else {
        // ship is a NPC
        //var _shipManifest = {};
        //var _cargoList = ship.cargoList;
        //var i = ship.cargoList.length;
		var ml = ship.cargoList;
		for (counter = 0; counter < ml.length; counter++) {
			if (ml[counter].quantity > 0) hold[ml[counter].commodity] = ml[counter].quantity;
		}
        //while (i--) {
        //    _shipManifest[_cargoList[i].commodity] = _cargoList[i].quantity;
        //}
        //for (counter = 0; counter < 17; counter++) {
        //    if (_shipManifest[this.cargoType[counter]] != null)
        //        hold[counter] = _shipManifest[this.cargoType[counter]];
        //}
    }
	storedShipArray.push(hold); // storedShipArray[8]
	storedShipArray.push(ship.fuel); //storedShipArray[9]
	var passengers = ship.passengers;
	for (counter = 0; counter < passengers.length; counter++) {
		tempArray = [passengers[counter].name, passengers[counter].start, passengers[counter].destination, (clock.seconds + passengers[counter].eta), passengers[counter].fee];
		passengers.splice(counter, 1, tempArray);
	}
	storedShipArray.push(passengers); // storedShipArray[10]
	var subEnts = new Array;
	if (ship.subEntityCapacity > 0 && ship.subEntityCapacity !== ship.subEntities.length) { // only store subEnts if at less than capacity.
		for (counter = 0; counter < ship.subEntities.length; counter++) {
			var s = ship.subEntities[counter];
			subEnts.push([s.dataKey, s.position.x, s.position.y, s.position.z, s.subEntityRotation]);
		}
	}
	storedShipArray.push(subEnts); //storedShipArray[11]
	if (ship == player.ship) {
		storedShipArray.push(ship.serviceLevel); //storedShipArray[12]
		ship.script.$SSH_serviceLevel = ship.serviceLevel; //save for Carriers OXP
	} else if (ship.script) storedShipArray.push(ship.script.$SSH_serviceLevel);
	storedShipArray.push(ship.entityPersonality); //storedShipArray[13]
	//EscortDeck specific data in storedShipArray[14]
	var u = 0;
	if (ship == player.ship) u = 1; //player ship is always usable
	else if (ship.script) u = ship.script.$EscortDeckUsable;
	var b = ship.boundingBox; //mass and sizes for TooLarge check and salvage price calculation
	storedShipArray.push({
		usable: u,
		mass: ship.mass,
		x: b.x,
		y: b.y,
		z: b.z
	}); //storedShipArray[14]
	//the following section contain player-only data
	if (ship == player.ship) {
		// this section is to record OXP equipment/weapon missionVariables or anything else needed for OXP compatibility that needs to be reinstated on ship restore.
		// cim's New Cargoes.
		var newCargoesManifest = null;
		if (worldScripts["CargoTypeExtension"]) {
			newCargoesManifest = worldScripts["CargoTypeExtension"].suspendPlayerManifest();
		}
		storedShipArray.push(newCargoesManifest); // storedShipArray[15]
		// thargoid's Hypercargo
		var hyperCargoMemory = null;
		var hyperCargoNewCargoes = null;
		var hyperCargoFailChance = null;
		if (ship.equipmentStatus("EQ_HYPERCARGO") === "EQUIPMENT_OK" && worldScripts["HyperCargo"]) {
			if (missionVariables.hyperCargoMemory) {
				hyperCargoMemory = missionVariables.hyperCargoMemory;
			}
			if (missionVariables.hyperCargoNewCargoes) {
				hyperCargoNewCargoes = missionVariables.hyperCargoNewCargoes;
			}
			if (missionVariables.hyperCargoFailChance) {
				hyperCargoFailChance = missionVariables.hyperCargoFailChance;
			}
		}
		storedShipArray.push([hyperCargoMemory, hyperCargoNewCargoes, hyperCargoFailChance]); // storedShipArray[16]
		// thargoids Vortex
		var name;
		var missileBays = new Array;
		var cargoBays = new Array;
		var nccargoBays = new Array;
		if (worldScripts["vortex_player.js"]) {
			if (ship.name === "Vortex" || ship.name === "Maelstrom") {
				if (missionVariables.multiBay_storeShipName) {
					name = missionVariables.multiBay_storeShipName;
				}
				//if (missionVariables.multiBay_currentMissile) {missileBays.push(missionVariables.multiBay_currentMissile);}
				//if (missionVariables.multiBay_currentCargo) {cargoBays.push(missionVariables.multiBay_currentCargo);}
				for (counter = 0; counter < 5; counter++) {
					if (missionVariables["multiBay_missileBay" + counter]) {
						missileBays.push(missionVariables["multiBay_missileBay" + counter]);
					}
					if (missionVariables["multiBay_cargoBay" + counter]) {
						cargoBays.push(missionVariables["multiBay_cargoBay" + counter]);
					}
					if (missionVariables["multiBay_ncBay" + counter]) {
						nccargoBays.push(missionVariables["multiBay_ncBay" + counter]);
					}
				}
			}
		}
		storedShipArray.push([name, missileBays, cargoBays, nccargoBays]); // storedShipArray[17]
		// thargoid's APRIL
		var aprilMemory = null;
		var aprilExpanded = null;
		if (worldScripts["april_worldScript.js"] && ship.equipmentStatus("EQ_APRIL") !== "EQUIPMENT_UNAVAILABLE") {
			worldScripts["april_worldScript.js"].playerWillSaveGame("ship_storage_helper");
			if (missionVariables.aprilMemory) {
				aprilMemory = missionVariables.aprilMemory;
			}
			if (missionVariables.aprilExpanded) {
				aprilExpanded = missionVariables.aprilExpanded;
			}
		}
		storedShipArray.push([aprilMemory, aprilExpanded]); // storedShipArray[18]
		// thargoid's IronHide
		var ironHidePercentage = null;
		var ironHideMilFlag = null;
		if (worldScripts["IronHide Armour Script"] && ship.equipmentStatus("EQ_IRONHIDE") !== "EQUIPMENT_UNAVAILABLE") {
			if (missionVariables.ironHide_percentage) {
				ironHidePercentage = missionVariables.ironHide_percentage;
			}
			if (missionVariables.ironHide_milFlag) {
				ironHideMilFlag = missionVariables.ironHide_milFlag;
			}
		}
		storedShipArray.push([ironHidePercentage, ironHidePercentage]); // storedShipArray[19]
		// ramirez' Missiles & Bombs
		var rmbChaffCount = null;
		if (worldScripts["Missiles & Bombs"] && ship.equipmentStatus("EQ_RMB_CHAFF_LAUNCHER") !== "EQUIPMENT_UNAVAILABLE") {
			if (missionVariables.rmb_chaff_count) {
				rmbChaffCount = missionVariables.rmb_chaff_count;
			}
		}
		storedShipArray.push(rmbChaffCount); //storedShipArray[20]
		// mcclane's Railgun
		var railgunType = null;
		var railgunProjectile = null;
		var railgunProjectiles = null;
		if (worldScripts["railgun"]) {
			worldScripts["railgun"].playerWillSaveGame();
			if (missionVariables.railgun_type) {
				railgunType = missionVariables.railgun_type;
			}
			if (missionVariables.railgun_projectile) {
				railgunProjectile = missionVariables.railgun_projectile;
			}
			if (missionVariables.railgun_projectiles) {
				railgunProjectiles = missionVariables.railgun_projectiles;
			}
		}
		storedShipArray.push([railgunType, railgunProjectile, railgunProjectiles]); // storedShipArray[21]
		// thargoid's targetAutoLock Plus
		var targetAutolock = null;
		if (worldScripts["targetAutolock"] && missionVariables.targetAutolock) {
			targetAutolock = missionVariables.targetAutolock;
		}
		storedShipArray.push(targetAutolock); // storedShipArray[22]
		// eric's targetReticleSensitive
		var reticleTargetSensitive = null;
		if (worldScripts["reticle_target_sensitive"] && missionVariables.reticleTargetSensitive) {
			reticleTargetSensitive = missionVariables.reticleTargetSensitive;
		}
		storedShipArray.push(reticleTargetSensitive); // storedShipArray[23]
		// thargoid's Armoury
		var CT_thargonCount = null;
		if (worldScripts["CT_Script"] && missionVariables.CT_thargonCount) {
			CT_thargonCount = missionVariables.CT_thargonCount;
		}
		storedShipArray.push(CT_thargonCount); // storedShipArray[24]
		// thargoid's Aquatics
		var aquatics_guardianCount = null;
		if (worldScripts["aquatics_equipment"] && missionVariables.aquatics_guardianCount) {
			aquatics_guardianCount = missionVariables.aquatics_guardianCount;
		}
		storedShipArray.push(aquatics_guardianCount); // storedShipArray[25]
		// smivs' Battle-Damage
		var BattleDamage_status = null;
		if ((worldScripts["Battle Damage"] || worldScripts["Battle Damage SS"]) && missionVariables.BattleDamage_status) {
			BattleDamage_status = missionVariables.BattleDamage_status
		}
		storedShipArray.push(BattleDamage_status); // storedShipArray[26]
		// murphy's Respray for Griffs
		var favourite = null;
		var favouriteRGB = null;
		var currentRespray = null;
		var currentDecal = null;
		if (worldScripts["Respray_for_Griffs.js"]) {
			if (worldScripts["Respray_for_Griffs.js"].currentRespray) {
				currentRespray = worldScripts["Respray_for_Griffs.js"].currentRespray;
			}
			if (worldScripts["Respray_for_Griffs.js"].favourite) {
				favourite = worldScripts["Respray_for_Griffs.js"].favourite;
			}
			if (worldScripts["Respray_for_Griffs.js"].favouriteRGB) {
				favouriteRGB = worldScripts["Respray_for_Griffs.js"].favouriteRGB;
			}
			if (worldScripts["Respray_for_Griffs.js"].currentDecal) {
				currentDecal = worldScripts["Respray_for_Griffs.js"].currentDecal;
			}
		}
		storedShipArray.push([favourite, currentRespray, favouriteRGB, currentDecal]); // storedShipArray[27]
		//Shield Cycler
		var wsc = worldScripts["Shield Cycler"];
		var sco = "";
		if (wsc) {
            var _f_store_devices = wsc._sc_store_devices.bind(wsc);
            sco = _f_store_devices();
            if (this.loggingEnabled) log(this.name, ship.displayName+": Shield Cycler settings:"+JSON.stringify(sco));
		}
		storedShipArray.push(sco); // storedShipArray[28]
		// code to retrieve secondary laser settings
		var lmss = worldScripts["LMSS_Core"];
		var stored_lmss = ""; // variable to hold LMSS laser settings
		if (lmss && lmss.$weaponInstalled && lmss.$weaponInstalled() && lmss.$retrieveLaserSettings) {
			stored_lmss = lmss.$retrieveLaserSettings();
		}
		storedShipArray.push(stored_lmss); // storedShipArray[29]
		var sca = worldScripts.ShipConfiguration_Armour;
		var stored_sca = "";
		if (sca) {
			if (ship.script && ship.script._armourFront) {
				stored_sca += ship.script._armourFront.toString() + "|";
			} else {
				stored_sca += "0|";
			}
			if (ship.script && ship.script._armourAft) {
				stored_sca += ship.script._armourAft.toString();
			} else {
				stored_sca += "0";
			}
		}
		storedShipArray.push(stored_sca); // storedShipArray[30]
		// smugglers hold
		var smg_cargo = "";
		var smg_settings = "";
		if (worldScripts.Smugglers_Equipment) {
			var se = worldScripts.Smugglers_Equipment;
			if (se.$hasSmugglingCompartment() === true) {
				if (se._sc_Cargo.length > 0) {
					smg_cargo = JSON.stringify(se._sc_Cargo);
				}
				smg_settings = se._sc_Phase + "|" + se._sc_TechVersion + "|" + se._sc_VisibleAs + "|" + se._sc_Days;
			}
		}
		storedShipArray.push(smg_cargo); // storedShipArray[31] cargo
		storedShipArray.push(smg_settings); // storedShipArray[32] compartment settings
		// storedShipArray[33] breakable lasers
		if (worldScripts["laserBooster_worldScript.js"]) {
			storedShipArray.push(JSON.stringify(worldScripts["laserBooster_worldScript.js"]._holdDamage));
		} else {
			storedShipArray.push("");
		}
		// storedShipArray[34] repair bots missionvariable
		if (worldScripts["Repair system"]) {
			storedShipArray.push(missionVariables.repairCounter);
		} else {
			storedShipArray.push("");
		}
		// finally log contents of array and return stringified copy.
		if (this.loggingEnabled) {
			log(this.name, "storedShipArray:" + storedShipArray + " storedShipArray.length " + storedShipArray.length);
		}
	} //end of player-only section
	return JSON.stringify(storedShipArray);
}
this.restoreStoredShip = function (storedShipArray, ship) {
	if (!ship) ship = player.ship;
	if (!storedShipArray || typeof (storedShipArray) !== "string") {
		if (this.loggingEnabled) {
			log(this.name, "Error - restoreStoredShip called with invalid parameter.");
		}
		return "Error-Invalid Parameter, expected String";
	}
	if (worldScripts.ShipConfiguration_Core) {
		var sc = worldScripts.ShipConfiguration_Core;
		sc._adding = true;
		sc._removing = true;
	}
	storedShipArray = JSON.parse(storedShipArray); // destringify storedShipArray
	if (this.loggingEnabled) {
		log(this.name, "storedShipArray:" + storedShipArray + "storedShipArray.length" + storedShipArray.length);
	}
	var extraNulls = this.expectedLength - storedShipArray.length;
	if (extraNulls < 0) {// storedShipArray is bigger than expected - should not happen
		if (this.loggingEnabled) {
			log(this.name, "Error - storedShipArray longer than expected length.");
		}
		if (this.loggingEnabled) {
			log(this.name, "expectedLength" + this.expectedLength + "storedShipArray.length" + storedShipArray.length);
		}
		return "Error-Invalid Parameter, array incorrect length";
	}
	while (extraNulls > 0) { // add extra nulls if smaller than expected (may have been created with older version of OXP)
		storedShipArray.push(null);
		extraNulls--;
		if (this.loggingEnabled) {
			log(this.name, "Adding nulls.....expectedLength: " + this.expectedLength + " storedShipArray.length: " + storedShipArray.length);
		}
	}
	//remove all equipments before replaceShip
	var equipment = ship.equipment;
	if (this.loggingEnabled) {
		log(this.name, "Eq1: " + ship.equipment);
	}
	var r = [];
	for (counter = 0; counter < equipment.length; counter++)
		r.push(equipment[counter].equipmentKey);
	for (counter = 0; counter < r.length; counter++) {//separated to avoid problems during eq array shortening
		ship.removeEquipment(r[counter]);
		if (this.loggingEnabled) log(this.name, r[counter] + " removed");
	}
	if (this.loggingEnabled) {
		log(this.name, "Eq2: " + ship.equipment);
	}
	/*	var wsc = worldScripts["Shield Cycler"]; - old code
		if ( wsc ) { //need clear these before replaceShip to avoid cashback from selling
			wsc._sc_manual_version = wsc._sc_none;
			wsc._sc_version = wsc._sc_none;
		}*/
	// replace current ship with restored ship
	var creds = player.credits; // grab a record of the player's current credit balance
	if (ship == player.ship && !player.replaceShip(storedShipArray[1], storedShipArray[13])) {
		if (this.loggingEnabled) {
			log(this.name, "Cannot restore stored ship with dataKey " + storedShipArray[1] + ". dataKey not valid (suspect missing OXP)");
		}
		return "Error-Invalid dataKey";
	}
	if (this.loggingEnabled) {
		log(this.name, "Eq3: " + ship.equipment);
	}
	player.credits = creds; // restore player credit balance - sometimes the replaceship function will refund the player something
	//set new writable ship properties in Oolite 1.82
	var oolite182 = false;
	if (0 < oolite.compareVersion("1.82")) {;
	} else oolite182 = true;
	if (oolite182) { //these are not writable before Oolite 1.82
		var a = storedShipArray[0];
		if (a[7]) ship.shipClassName = a[7];
		if (a[8]) ship.shipUniqueName = a[8];
		if (a[9]) ship.AIScriptWakeTime = a[9];
		if (a[11]) ship.destinationSystem = a[11];
		if (a[12]) ship.exhaustEmissiveColor = a[12];
		if (a[13]) ship.homeSystem = a[13];
		if (a[14]) ship.maxYaw = a[14];
		if (a[15]) ship.maxPitch = a[15];
		if (a[16]) ship.maxRoll = a[16];
		if (a[17]) ship.maxThrust = a[17];
		if (a[18]) ship.thrust = a[18];
		if (a[19]) ship.maxSpeed = a[19];
		if (a[20] > 0) {
			ship.maxEnergy = a[20];
			if (ship.energy < ship.maxEnergy) ship.energy = ship.maxEnergy; //fix in dock
		}
		if (a[21] > 0) ship.energyRechargeRate = a[21];
		// use max cargo as preference to stored value, as the process of adding equipment could adjust
		// final value
		var shipdata = Ship.shipDataForKey(storedShipArray[1]);
        if (shipdata && shipdata.max_cargo)
            ship.cargoSpaceCapacity = shipdata.max_cargo;
		else
			if (a[22]) ship.cargoSpaceCapacity = a[22];
		if (a[23]) ship.injectorBurnRate = a[23];
		if (a[24]) ship.injectorSpeedFactor = a[24];
		if (a[25]) ship.scanDescription = a[25];
		if (a[26]) ship.hyperspaceSpinTime = a[26];
		if (a[27]) ship.scannerHostileDisplayColor1 = a[27];
		if (a[28]) ship.scannerHostileDisplayColor2 = a[28];
		if (ship == player.ship) {
			if (a[29]) ship.forwardShield = a[29];
			if (a[30]) ship.maxForwardShield = a[30];
			if (a[31]) ship.forwardShieldRechargeRate = a[31];
			if (a[32]) ship.aftShield = a[32];
			if (a[33]) ship.maxAftShield = a[33];
			if (a[34]) ship.aftShieldRechargeRate = a[34];
		} else if (a[10]) ship.beaconLabel = a[10]; //read-only for player
	}
	//reinstate pylons
	var counter;
	var counter1;
	var test;
	var missiles = [];
	if (ship.missileCapacity > 0) { //bugfix of "Tried to init array with nil object" in Oolite 1.81
		if (this.loggingEnabled) {
			log(this.name,
				"Remove missiles automatically awarded on replaceShip: " + ship.missiles);
		};
		try {
			missiles = ship.missiles;
			for (counter = 0; counter < missiles.length; counter++) {
				ship.removeEquipment(missiles[counter]);
			}
		} catch (err) {
			if (this.loggingEnabled) log(this.name, "!!ERROR: " + err);
		}
	}
	missiles = storedShipArray[6];
	if (missiles && missiles.length > 0) {
		if (this.loggingEnabled) {
			log(this.name,
				"Add missiles from storedShip: " + missiles);
		}
		for (counter = 0; counter < missiles.length; counter++)
			if (EquipmentInfo.infoForKey(missiles[counter]))
				ship.awardEquipment(missiles[counter]);
	}
	//reinstate equipment
	// if shipconfig armour is in play, turn on the override flag so that nothing gets auto-repaired
	if (worldScripts.ShipConfiguration_Armour) worldScripts.ShipConfiguration_Armour._override = true;
	if (worldScripts["Breakable_Energy_Unit"]) {
		worldScripts["Breakable_Energy_Unit"].shipRestore = true;
	}
	if (worldScripts["Breakable_Engines"]) {
		worldScripts["Breakable_Engines"].shipRestore = true;
	}
	if (worldScripts["Breakable_HUD_IFF_Scanner"]) {
		worldScripts["Breakable_HUD_IFF_Scanner"].shipRestore = true;
	}
	if (worldScripts["Breakable_Shield_Generators"]) {
		worldScripts["Breakable_Shield_Generators"].shipRestore = true;
	}
	if (worldScripts["Breakable_TorusDrive"]) {
		worldScripts["Breakable_TorusDrive"].shipRestore = true;
	}
	if (worldScripts["Breakable_WitchDrive"]) {
		worldScripts["Breakable_WitchDrive"].shipRestore = true;
	}
	var equipment = ship.equipment;
	if (this.loggingEnabled) {
		log(this.name, "Equipment automatically awarded on replaceShip: " + equipment);
	}
	var tempArray;
	var savedEQ = storedShipArray[7];
	if (this.loggingEnabled) {
		log(this.name, "Equipment from storedShip: " + savedEQ);
	}
	for (counter = 0; counter < equipment.length; counter++) {
		tempArray = [equipment[counter].equipmentKey, ship.equipmentStatus(equipment[counter])];
		for (counter1 = 0; counter1 < savedEQ.length; counter1++) {
			if (savedEQ[counter1][0] === tempArray[0]) {
				tempArray.push(true);
				tempArray.push(counter1);
				if (this.loggingEnabled) {
					log(this.name, "Equipment: " + tempArray[0] + " from storedShip already fitted.");
				}
				if (savedEQ[counter1][1] === "EQUIPMENT_DAMAGED") {
					ship.setEquipmentStatus(tempArray[0], "EQUIPMENT_DAMAGED");
					if (this.loggingEnabled) {
						log(this.name, "Setting status to: EQUIPMENT_DAMAGED");
					}
				}
				break;
			}
		}
		if (!tempArray[2]) {
			if (this.loggingEnabled) {
				log(this.name, "Not in storedShip equipment - removing equipment item: " + tempArray[0]);
			}
			ship.removeEquipment(tempArray[0]);
			continue;
		} else {
			savedEQ.splice(tempArray[3], 1);
			if (this.loggingEnabled) {
				log(this.name, "Updated storedShip equipment list: " + savedEQ);
			}
		}
	}
	if (this.loggingEnabled) {
		log(this.name, "Awarding remaining equipment from storedShip: " + savedEQ);
	}
	//must retry eq award if depends on another eq which comes later in the list
	var depth = 0;
	var retryArray = []; //try again if a required equipment comes later
	retryArray[depth] = savedEQ;
	do {
		var added = false;
		retryArray[depth + 1] = [];
		for (counter = 0; counter < retryArray[depth].length; counter++) {
			var e = retryArray[depth][counter][0]; //award if exists and has not
			var ed = retryArray[depth][counter][1];
			var ei = EquipmentInfo.infoForKey(e);
			if (ei) {
				if (!ship.awardEquipment(e)) //retry next time if failed
					if (ship.equipmentStatus(e) != "EQUIPMENT_OK")
						retryArray[depth + 1].push([e, ed]);
				else {
					added = true;
					if (oolite182) {
						var ec = ei.requiredCargoSpace;
						if (ec != 0) //give back the space of this equipment
							ship.cargoSpaceCapacity += ec;
						if (e == "EQ_CARGO_BAY") //a fix added in v0.27
							ship.cargoSpaceCapacity -= ship.extraCargo;
					}
					if (ed == "EQUIPMENT_DAMAGED")
						ship.setEquipmentStatus(e, "EQUIPMENT_DAMAGED");
				}
			}
		}
		depth++;
		if (this.loggingEnabled) {
			log(this.name, "depth:" + depth + " retryArray:" + retryArray[depth]);
		}
	} while (retryArray[depth].length > 0 && added && depth < 50) //until no more added eq
	// reduced depth to 50 (from 100) because next section should hopefully cover all the stragglers
	// This is a brute-force method of trying to bypass conditioning code on any remaining equipment items.
	// Many conditions for equipment items are related to the system type where they can be purchased, so this code
	// essentially runs through all the main economy/government/tl possibilities, trying to find one
	// that will work for this equipment item. There are 960 possibilities normally (8 x 8 x 15), but we'll hope that only 
	// one setting is required, to make this loop faster (8 + 8 + 15).
	//
	// This process can be avoided if the conditioning for the equipment item is changed to automatically allow any scripted 
	// event. This only works for JS-based conditions, though. For plist-based conditions, they will need to be converted
	// to JS conditions first.
	if (retryArray[depth] && retryArray[depth].length > 0) {
		// because this really is an error condition, I've left off the check for loggingEnabled, so it always shows up in the log file
		log(this.name, "ERROR! Some equipment items still not added!");
		for (var i = 0; i < retryArray[depth].length; i++) {
			var e = retryArray[depth][i][0];
			var ed = retryArray[depth][i][1];
			log(this.name, "** Equipment key: " + e);
			var done = false;
			if (player.bounty > 0) {
				// try clearing offender status, in case the equipment item "requires_clean"
				var hold_bounty = player.bounty;
				var bs = worldScripts.BountySystem_Core;
				if (bs) bs._changing = true;
				player.bounty = 0;
				if (ship.awardEquipment(e)) {
					if (ed == "EQUIPMENT_DAMAGED") ship.setEquipmentStatus(e, "EQUIPMENT_DAMAGED");
					log(this.name, ">>> FIXED! Added with system change to player bounty to 0");
					retryArray[depth][i] = [];
					done = true;
				}
				player.bounty = hold_bounty;
				if (bs) bs._changing = false;
			}
			if (done === false) {
				// for techlevel, it will most likely be one of two extremes, either a low TL is required, or a high one.
				// we'll two two steps here, starting with a high TL
				var hold_tl = system.techLevel;
				system.techLevel = 14;
				if (ship.awardEquipment(e)) {
					if (ed == "EQUIPMENT_DAMAGED") ship.setEquipmentStatus(e, "EQUIPMENT_DAMAGED");
					log(this.name, ">>> FIXED! Added with system change to techLevel 14");
					retryArray[depth][i] = [];
					done = true;
				}
				if (done === false) {
					system.techLevel = 0;
					if (ship.awardEquipment(e)) {
						if (ed == "EQUIPMENT_DAMAGED") ship.setEquipmentStatus(e, "EQUIPMENT_DAMAGED");
						log(this.name, ">>> FIXED! Added with system change to techLevel 0");
						retryArray[depth][i] = [];
						done = true;
					}
				}
				system.techLevel = hold_tl;
			}
			if (done === false) {
				// try changing government
				var hold_gov = system.government;
				for (var gov = 0; gov <= 7; gov++) {
					system.government = gov;
					if (ship.awardEquipment(e)) {
						if (ed == "EQUIPMENT_DAMAGED") ship.setEquipmentStatus(e, "EQUIPMENT_DAMAGED");
						log(this.name, ">>> FIXED! Added with system change to government " + gov);
						retryArray[depth][i] = [];
						done = true;
						break;
					}
				}
				system.government = hold_gov;
			}
			if (done === false) {
				// try changing economy
				var hold_ec = system.economy;
				for (var ec = 0; ec <= 7; ec++) {
					system.economy = ec;
					if (ship.awardEquipment(e)) {
						if (ed == "EQUIPMENT_DAMAGED") ship.setEquipmentStatus(e, "EQUIPMENT_DAMAGED");
						log(this.name, ">>> FIXED! Added with system change to economy " + ec);
						retryArray[depth][i] = ["", ""];
						done = true;
						break;
					}
				}
				system.economy = hold_ec;
			}
		}
	}
	// last chance
	for (var i = 0; i < retryArray[depth].length; i++) {
		if (retryArray[depth][i][0] != "" && retryArray[depth][i][0] != undefined) {
			var e = retryArray[depth][i][0];
			var ed = retryArray[depth][i][1];
			if (ship.awardEquipment(e)) {
				if (ed == "EQUIPMENT_DAMAGED") ship.setEquipmentStatus(e, "EQUIPMENT_DAMAGED");
				log(this.name, ">>> FIXED! On final pass");
			} else {
				log(this.name, "*** ERROR Equipment Item still not awarded: " + retryArray[depth][i][0]);
			}
		}
	}
	/* old code, can not award if depends on another eq which comes later in the list
		for(counter = 0;counter<savedEQ.length;counter++) {
			if(EquipmentInfo.infoForKey(savedEQ[counter][0])) {
				ship.awardEquipment(savedEQ[counter][0]);
				if(savedEQ[counter][1] === "EQUIPMENT_DAMAGED")
					{ship.setEquipmentStatus(savedEQ[counter][0],savedEQ[counter][1])};
			}
		}
	*/
	// turn off the shipconfig armour override flag
	if (worldScripts.ShipConfiguration_Armour) worldScripts.ShipConfiguration_Armour._override = false;
	var berths = storedShipArray[0][35];
	if (berths > 1) { //award additional passenger berths over the first
		for (counter = 1; counter < berths; counter++) {
			ship.awardEquipment("EQ_PASSENGER_BERTH");
			if (oolite182) ship.cargoSpaceCapacity += 5; //give back the space of this berth
		}
	}
	if (worldScripts["Breakable_Energy_Unit"]) {
		delete worldScripts["Breakable_Energy_Unit"].shipRestore;
	}
	if (worldScripts["Breakable_Engines"]) {
		delete worldScripts["Breakable_Engines"].shipRestore;
	}
	if (worldScripts["Breakable_HUD_IFF_Scanner"]) {
		delete worldScripts["Breakable_HUD_IFF_Scanner"].shipRestore;
	}
	if (worldScripts["Breakable_Shield_Generators"]) {
		delete worldScripts["Breakable_Shield_Generators"].shipRestore;
	}
	if (worldScripts["Breakable_TorusDrive"]) {
		delete worldScripts["Breakable_TorusDrive"].shipRestore;
	}
	if (worldScripts["Breakable_WitchDrive"]) {
		delete worldScripts["Breakable_WitchDrive"].shipRestore;
	}
	if (ship.aftShield !== ship.maxAftShield) {
		ship.aftShield = ship.maxAftShield;
	}
	if (ship.forwardShield !== ship.maxForwardShield) {
		ship.forwardShield = ship.maxForwardShield;
	}
    // reinstate hold/manifest
    var hold = storedShipArray[8];
	// if we have an array, it's the old version
	if (Array.isArray(hold)) {
		if (ship == player.ship) {
			for (counter = 0; counter < 17; counter++) {
				if (hold[counter]) {
					ship.manifest[this.cargoType[counter]] = hold[counter];
					if (this.loggingEnabled) log(this.name, "Inserting "+hold[counter]+" of "+this.cargoType[counter]+", result:"+ship.manifest[this.cargoType[counter]]);
				}
			}
		} else {
			var ret;
			for (counter = 0; counter < 17; counter++) {
				if (hold[counter]) {
					ret = ship.adjustCargo(this.cargoType[counter], hold[counter]);
					if (this.loggingEnabled) log(this.name, "Inserting "+hold[counter]+" of "+this.cargoType[counter]+", result:"+ret+", "+JSON.stringify(ship.cargoList));
				}
			}
		}
	} else {
		// otherwise, it's a dictionary object
		if (ship == player.ship) {
			var keys = Object.keys(hold);
			for (counter = 0; counter < keys.length; counter++) {
				ship.manifest[keys[counter]] = hold[keys[counter]];
				if (this.loggingEnabled) log(this.name, "Inserting "+hold[keys[counter]]+" of "+keys[counter]+", result:"+ship.manifest[keys[counter]]);
			}
		} else {
			var keys = Object.keys(hold);
			for (counter = 0; counter < keys.length; counter++) {
				ret = ship.adjustCargo(keys[counter], hold[keys[counter]]);
				if (this.loggingEnabled) log(this.name, "Inserting "+hold[keys[counter]]+" of "+keys[counter]+", result:"+ret+", "+JSON.stringify(ship.cargoList));
			}
		}
	}
	// reinstate fuel
	ship.fuel = storedShipArray[9];
	// reinstate passengers
	var passengers = storedShipArray[10];
	for (counter = 0; counter < passengers.length; counter++) {
		if (clock.seconds >= passengers[counter][3]) {
			if (this.loggingEnabled) {
				log(this.name, "Cannot re-instate passenger record: " + passengers[counter] + " as passenger contract arrival time is in the past");
			};
			player.decreasePassengerReputation();
			continue;
		}
		if (this.loggingEnabled) {
			log(this.name, "Attempting to add passenger: " + passengers[counter]);
		}
		var test = ship.addPassenger(passengers[counter][0], passengers[counter][1], passengers[counter][2], passengers[counter][3], passengers[counter][4]);
		if (!test && this.loggingEnabled) {
			log(this.name, "Failed to add passenger: " + passengers[counter]);
		}
	}
	// check for subents to be removed
	var subEnts = storedShipArray[11]; // will only exist if less subEnts than capacity when ship was stored.
	if (subEnts && subEnts.length > 0) {
		var currentSubEnts = ship.subEntities;
		if (this.loggingEnabled) {
			log(this.name, "Updating subEnts. current subEnts: " + currentSubEnts + " storedShip subEnts: " + subEnts);
		}
		for (counter = 0; counter < currentSubEnts.length; counter++) {
			currentSubEnts[counter].toBeRemoved = true;
			for (counter1 = 0; counter1 < subEnts.length; counter1++) {
				if (subEnts[counter1][0] === currentSubEnts[counter].dataKey &&
					subEnts[counter1][1] === currentSubEnts[counter].position.x &&
					subEnts[counter1][2] === currentSubEnts[counter].position.y &&
					subEnts[counter1][3] === currentSubEnts[counter].position.z) {
					var r = subEnts[counter1][4];
					if (r) ship.subEntities[counter].subEntityRotation = r;
					delete currentSubEnts[counter].toBeRemoved;
				}
			}
			if (currentSubEnts[counter].toBeRemoved) {
				delete currentSubEnts[counter].toBeRemoved;
				currentSubEnts[counter].remove(true);
			}
		}
		if (this.loggingEnabled) {
			log(this.name, "Updating subEnts complete. Current subEnts: " + ship.subEntities + " storedShip subEnts: " + subEnts);
		}
	}
	// reinstate serviceLevel
	if (storedShipArray[12] > 0) { //fixed for EscortDeck
		if (this.loggingEnabled) log(this.name, "Updating ship.serviceLevel: " + storedShipArray[12]);
		if (ship == player.ship) ship.serviceLevel = storedShipArray[12];
		else if (ship.script) s.script.$SSH_serviceLevel = storedShipArray[12];
	}
	//storedShipArray[13] contain entityPersonality which is used up in replaceShip() above
	//entityPersonality is not writable before Oolite 1.82
	if (oolite182 && ship != player.ship && storedShipArray[13])
		ship.entityPersonality = storedShipArray[13];
	//EscortDeck specific data in storedShipArray[14]
	if (storedShipArray[14]) {
		if (ship.script) ship.script.$EscortDeckUsable = storedShipArray[14].usable;
		//ship mass and sizes are read-only and set by the core from the ship model
	}
	// turn on switching mode for LMSS
	// for compatibility with UBER lasers in the condition script of new lasers
	if (worldScripts.LMSS_Core) worldScripts.LMSS_Core._switching = true;
	// reinstate weapons, must be after equipments for UBER types in new lasers
	ship.aftWeapon = storedShipArray[2];
	ship.forwardWeapon = storedShipArray[3];
	ship.portWeapon = storedShipArray[4];
	ship.starboardWeapon = storedShipArray[5];
	// turn off switching mode for LMSS
	if (worldScripts.LMSS_Core) worldScripts.LMSS_Core._switching = false;
	//the following section contain player-only data
	if (ship == player.ship) {
		// reinstate OXP saved information.
		// cim's New Cargoes
		if (worldScripts["CargoTypeExtension"]) {
			if (this.loggingEnabled) {
				log(this.name, "Restoring New Cargoes special manifest: " + storedShipArray[15]);
			}
			worldScripts["CargoTypeExtension"].restorePlayerManifest(storedShipArray[15]);
		}
		// thargoid's HyperCargo
		if (ship.equipmentStatus("EQ_HYPERCARGO") === "EQUIPMENT_OK" && worldScripts["HyperCargo"]) {
			if (this.loggingEnabled) {
				log(this.name, "Restoring Hypercargo missionVariables: " + storedShipArray[16]);
			}
			missionVariables.hyperCargoMemory = storedShipArray[16][0];
			missionVariables.hyperCargoNewCargoes = storedShipArray[16][1];
			missionVariables.hyperCargoFailChance = storedShipArray[16][2];
			worldScripts["HyperCargo"].startUp();
		}
		// thargoids Vortex
		if (worldScripts["vortex_player.js"]) {
			if (ship.name === "Vortex" || ship.name === "Maelstrom") {
				if (this.loggingEnabled) {
					log(this.name, "Restoring Vortex/Maelstrom missionVariables: " + storedShipArray[17]);
				}
				if (storedShipArray[17][0]) {
					missionVariables.multiBay_storeShipName = storedShipArray[17][0];
				}
				//if (storedShipArray[17][1][0]){missionVariables.multiBay_currentMissile = storedShipArray[17][1][0];}
				//if (storedShipArray[17][2][0]){missionVariables.multiBay_currentCargo = storedShipArray[17][2][0];}
				for (counter = 0; counter < 5; counter++) {
					if (storedShipArray[17][1][counter]) {
						missionVariables["multiBay_missileBay" + counter] = storedShipArray[17][1][counter];
					}
					if (storedShipArray[17][2][counter]) {
						missionVariables["multiBay_cargoBay" + counter] = storedShipArray[17][2][counter];
					}
					if (storedShipArray[17][3][counter]) {
						missionVariables["multiBay_ncBay" + counter] = storedShipArray[17][3][counter];
					}
				}
			}
		}
		// thargoid's APRIL
		if (worldScripts["april_worldScript.js"] && ship.equipmentStatus("EQ_APRIL") !== "EQUIPMENT_UNAVAILABLE") {
			if (this.loggingEnabled) {
				log(this.name, "Restoring APRIL missionVariables: " + storedShipArray[18]);
			}
			missionVariables.aprilMemory = storedShipArray[18][0];
			missionVariables.aprilExpanded = storedShipArray[18][1];
			worldScripts["april_worldScript.js"].startUp();
		}
		// thargoid's IronHide
		if (worldScripts["IronHide Armour Script"] && ship.equipmentStatus("EQ_IRONHIDE") !== "EQUIPMENT_UNAVAILABLE") {
			if (this.loggingEnabled) {
				log(this.name, "Restoring IronHide missionVariables: " + storedShipArray[19]);
			}
			missionVariables.ironHide_percentage = storedShipArray[19][0];
			missionVariables.ironHide_milFlag = storedShipArray[19][1];
			worldScripts["IronHide Armour Script"].startUp();
		}
		// ramirez's Missiles & Bombs
		if (worldScripts["Missiles & Bombs"] && ship.equipmentStatus("EQ_RMB_CHAFF_LAUNCHER") !== "EQUIPMENT_UNAVAILABLE") {
			if (this.loggingEnabled) {
				log(this.name, "Restoring Missile & Bombs missionVariable: " + storedShipArray[20]);
			}
			missionVariables.rmb_chaff_count = storedShipArray[20];
		}
		// mcclane's railgun
		if (worldScripts["railgun"]) {
			if (this.loggingEnabled) {
				log(this.name, "Restoring railgun missionVariables: " + storedShipArray[21]);
			}
			missionVariables.railgun_type = storedShipArray[21][0];
			missionVariables.railgun_projectile = storedShipArray[21][1];
			missionVariables.railgun_projectiles = storedShipArray[21][2];
			worldScripts["railgun"].startUp();
		}
		// thargoid's targetAutoLock Plus.
		if (worldScripts["targetAutolock"]) {
			if (this.loggingEnabled) {
				log(this.name, "Restoring targetAutoLock Plus missionVariables: " + storedShipArray[22]);
			}
			missionVariables.targetAutolock = storedShipArray[22];
		}
		// eric's targetReticleSensitive
		if (worldScripts["reticle_target_sensitive"]) {
			if (this.loggingEnabled) {
				log(this.name, "Restoring targetReticle missionVariables: " + storedShipArray[23]);
			}
			missionVariables.reticleTargetSensitive = storedShipArray[23];
			worldScripts["reticle_target_sensitive"].startUp();
		}
		// thargoid's Armoury
		if (worldScripts["CT_Script"]) {
			if (this.loggingEnabled) {
				log(this.name, "Restoring Armoury missionVariable: " + storedShipArray[24]);
			}
			missionVariables.CT_thargonCount = storedShipArray[24];
			worldScripts["CT_Script"].startUp();
		}
		// thargoid's Aquatics
		if (worldScripts["aquatics_equipment"]) {
			if (this.loggingEnabled) {
				log(this.name, "Restoring Aquatics missionVariable: " + storedShipArray[25]);
			}
			missionVariables.aquatics_guardianCount = storedShipArray[25];
		}
		// smiv's Battle Damage
		if (worldScripts["Battle Damage"] || worldScripts["Battle Damage SS"]) {
			if (this.loggingEnabled) {
				log(this.name, "Restoring Battle Damage missionVariable: " + storedShipArray[26]);
			}
			missionVariables.BattleDamage_status = storedShipArray[26];
		}
		// Respray for Griff's
		if (worldScripts["Respray_for_Griffs.js"]) {
			if (this.loggingEnabled) {
				log(this.name, "Restoring Respray for Griff's missionVariable: " + storedShipArray[27]);
			}
			worldScripts["Respray_for_Griffs.js"].favourite = storedShipArray[27][0];
			worldScripts["Respray_for_Griffs.js"].currentRespray = storedShipArray[27][1];
			worldScripts["Respray_for_Griffs.js"].favouriteRGB = storedShipArray[27][2];
			worldScripts["Respray_for_Griffs.js"].currentDecal = storedShipArray[27][3];
			worldScripts["Respray_for_Griffs.js"].playerWillSaveGame();
			worldScripts["Respray_for_Griffs.js"].startUp();
		}
		//Shield Cycler
		var errorcode = 0;
		var wsc = worldScripts["Shield Cycler"];
		if (wsc && storedShipArray[28]) wsc._sc_retrieve_devices(storedShipArray[28]);
		if (errorcode > 0) log(this.name, "Error in retrieving Shield Cycler data, code: " + errorcode);
		// code to restore secondary laser settings
		var lmss = worldScripts["LMSS_Core"];
		if (lmss && lmss.$restoreLaserSettings && storedShipArray[29]) {
			// pass stored settings to lmss to restore secondary lasers
			lmss.$restoreLaserSettings(storedShipArray[29]);
		}
		// code to restore ship config armour settings
		var sca = worldScripts.ShipConfiguration_Armour;
		if (sca && storedShipArray[30] && storedShipArray[30].indexOf("|") >= 0) {
			var stored_sca = storedShipArray[30].split("|");
			if (stored_sca[0] != "") ship.script._armourFront = parseInt(stored_sca[0]);
			if (stored_sca[1] != "") ship.script._armourAft = parseInt(stored_sca[1]);
		}
		// code to restore smuggling compartment cargo and settings
		var se = worldScripts.Smugglers_Equipment;
		if (se) {
			if (storedShipArray[31]) se._sc_Cargo = JSON.parse(storedShipArray[31]);
			if (storedShipArray[32] && storedShipArray[32].indexOf("|") >= 0) {
				var stored_smg = storedShipArray[32].split("|");
				if (stored_smg[0] != "") se._sc_Phase = stored_smg[0];
				if (stored_smg[1] != "") se._sc_TechVersion = stored_smg[1];
				if (stored_smg[2] != "") se._sc_VisibleAs = stored_smg[2];
				if (stored_smg[3] != "") se._sc_Days = stored_smg[2];
			}
		}
		var lb = worldScripts["laserBooster_worldScript.js"];
		if (lb) {
			if (storedShipArray[33]) {
				lb._holdDamage = JSON.parse(storedShipArray[33]);
			}
		}
		var rb = worldScripts["Repair system"];
		if (rb) {
			if (storedShipArray[34]) {
				missionVariables.repairCounter = parseInt(storedShipArray[34]);
			}
		}
	} //end of player-only section
	if (worldScripts.ShipConfiguration_Core) {
		var sc = worldScripts.ShipConfiguration_Core;
		sc._adding = false;
		sc._removing = false;
		sc.$postResprayFunction();
	}
	return true;
}
this.disableVortexPBNSFunc = function (context, ship) {
	if (!worldScripts["vortex_player.js"] || this.storeVortexFunc) {
		return false;
	}
	if (!ship) ship = player.ship;
	this.storeVortexFunc = new Object;
	this.storeVortexFunc = worldScripts["vortex_player.js"].playerBoughtNewShip;
	if (context === "delete") {
		delete worldScripts["vortex_player.js"].playerBoughtNewShip;
		if (this.loggingEnabled) {
			log(this.name, "Deleted Vortex this.playerBoughtNewShip");
		}
		return true;
	}
	if (context === "retainName") {
		this.replaceVortexFunc = new Object;
		this.replaceVortexFunc = function (ship) {
			this.stopMissileTimer();
			this.resetVortex();
			if (ship.name === "Vortex") {
				this.storeMissileBay(missionVariables.multiBay_currentMissile);
				this.startUp();
				this.shipTitle = missionVariables.multiBay_storeShipName;
				mission.runScreen({
					title: "Ship Specifications (Vortex)",
					model: "vortex_player"
				});
				this.AIName = "MAC" + Math.floor(Math.random() * 0.999999 * 10) + Math.floor(Math.random() * 0.999999 * 10) + Math.floor(Math.random() * 0.999999 * 10) + Math.floor(Math.random() * 0.999999 * 10);
				mission.addMessageText("Designation: Vortex - " + this.shipTitle);
				mission.addMessageText("MAC registration: " + this.AIName + "\n");
				mission.addMessageText("Shipyard: Aquarian Shipbuilding Corporation                                      Special Capabilities:");
				mission.addMessageText("Source: Ex-Military (blockade runner)                                                     Military grade AI");
				mission.addMessageText("Max speed: 450                                                                                     Damage auto-repair");
				mission.addMessageText("Cargo capacity: 5x 30t                                                                    Missile defense screen");
				mission.addMessageText("Missile capacity: 5x 5 pylons                                                  Regenerative fuel injection");
				mission.addMessageText("Energy: 6 banks                                                                             Multi-bay cargo storage");
				mission.addMessageText("Pitch/Roll/Yaw: 1.3/1.5/1.5                                                            Switchable missile bays");
				mission.addMessageText("\n\n\nGreetings Commander " + expandDescription("[commander_name]") + ".\n\nI am " + this.AIName + ", the military AI construct of your new ASC Vortex craft, the " + this.shipTitle + ". Self-diagnostics shows all systems functional and ready - I await your command.");
				mission.addMessageText("\nEnd of Line.");
			}
		}
		worldScripts["vortex_player.js"].playerBoughtNewShip = this.replaceVortexFunc;
		if (this.loggingEnabled) {
			log(this.name, "Modified Vortex this.playerBoughtNewShip");
		}
		return true;
	}
	return false;
}
this.enableVortexPBNSFunc = function () {
	if (!worldScripts["vortex_player.js"] || !this.storeVortexFunc) {
		return false;
	}
	worldScripts["vortex_player.js"].playerBoughtNewShip = this.storeVortexFunc;
	delete this.storeVortexFunc;
	if (this.loggingEnabled) {
		log(this.name, "Reinstated original Vortex this.playerBoughtNewShip");
	}
	return true;
}
this.disableMaelstromPBNSFunc = function (context, ship) {
	if (!worldScripts["vortex_maelstrom.js"] || this.storeMaelstromFunc) {
		return false;
	}
	if (!ship) ship = player.ship;
	this.storeMaelstromFunc = new Object;
	this.storeMaelstromFunc = worldScripts["vortex_maelstrom.js"].playerBoughtNewShip;
	if (context === "delete") {
		delete worldScripts["vortex_maelstrom.js"].playerBoughtNewShip;
		if (this.loggingEnabled) {
			log(this.name, "Deleted Maelstrom this.playerBoughtNewShip");
		}
		return true;
	}
	if (context === "retainName") {
		this.replaceMaelstromFunc = new Object;
		this.replaceMaelstromFunc = function (ship) {
			this.stopMissileTimer();
			this.resetShip();
			if (ship.name === "Maelstrom") {
				this.storeMissileBay(missionVariables.multiBay_currentMissile);
				this.startUp();
				this.shipTitle = missionVariables.multiBay_storeShipName;
				mission.runScreen({
					title: "Ship Specifications (Maelstrom)",
					model: "vortex_maelstrom_player"
				});
				this.AIName = "MAC" + Math.floor(Math.random() * 0.999999 * 10) + Math.floor(Math.random() * 0.999999 * 10) + Math.floor(Math.random() * 0.999999 * 10) + Math.floor(Math.random() * 0.999999 * 10);
				mission.addMessageText("Designation: Maelstrom - " + this.shipTitle);
				mission.addMessageText("MAC registration: " + this.AIName + "\n");
				mission.addMessageText("Shipyard: Aquarian Shipbuilding Corporation                                Special Capabilities:");
				mission.addMessageText("Source: Ex-Military (Armoured Transport)                                              Military grade AI");
				mission.addMessageText("Max speed: 250                                                                                     Damage auto-repair");
				mission.addMessageText("Cargo capacity: 3x 100t                                                                  Missile defense screen");
				mission.addMessageText("Missile capacity: 3x 4 pylons                                                  Regenerative fuel injection");
				mission.addMessageText("Energy: 10 banks                                                                            Multi-bay cargo storage");
				mission.addMessageText("Pitch/Roll/Yaw: 1.0/1.2/1.2                                                            Switchable missile bays");
				mission.addMessageText("\n\n\nGreetings Commander " + expandDescription("[commander_name]") + ".\n\nI am " + this.AIName + ", the military AI construct of your new ASC Maelstrom craft, the " + this.shipTitle + ". Self-diagnostics shows all systems functional and ready - I await your command.");
				mission.addMessageText("\nEnd of Line.");
			}
		}
		worldScripts["vortex_maelstrom.js"].playerBoughtNewShip = this.replaceMaelstromFunc;
		if (this.loggingEnabled) {
			log(this.name, "Modified Maelstrom this.playerBoughtNewShip");
		}
		return true;
	}
	return false;
}
this.enableMaelstromPBNSFunc = function () {
	if (!worldScripts["vortex_maelstrom.js"] || !this.storeMaelstromFunc) {
		return false;
	}
	worldScripts["vortex_maelstrom.js"].playerBoughtNewShip = this.storeMaelstromFunc;
	delete this.storeMaelstromFunc;
	if (this.loggingEnabled) {
		log(this.name, "Reinstated original Maelstrom this.playerBoughtNewShip");
	}
	return true;
}
this.disableTCATPBNSFunc = function () {
	if (!worldScripts["TCAT_missionScript"] || this.storeTCATFunc) {
		return false;
	}
	this.storeTCATFunc = new Object;
	this.storeTCATFunc = worldScripts["TCAT_missionScript"].playerBoughtNewShip;
	delete worldScripts["TCAT_missionScript"].playerBoughtNewShip;
	if (this.loggingEnabled) {
		log(this.name, "Deleted TCAT this.playerBoughtNewShip");
	}
	return true;
}
this.enableTCATPBNSFunc = function () {
	if (!worldScripts["TCAT_missionScript"] || !this.storeTCATFunc) {
		return false;
	}
	worldScripts["TCAT_missionScript"].playerBoughtNewShip = this.storeTCATFunc;
	delete this.storeTCATFunc;
	if (this.loggingEnabled) {
		log(this.name, "Reinstated original TCAT this.playerBoughtNewShip");
	}
	return true;
} |