| Scripts/shiprespray.js | "use strict";
this.name = "ShipRespray";
this.author = "phkb";
this.copyright = "2015 phkb";
this.description = "Allows user to select a respray of their ship using one of the installed OXP ship styles";
this.license = "CC BY-NC-SA 4.0";
this._data = [];				// storage array of ship data keys
this._selectedItem = "";		// currently selected item from the main list
this._selectedIndex = 0;		// index of the currently selected item
this._personality = 0;			// current entityPersonality setting
this._displayType = 0;			// respray gui display mode 0 = main list, 1 = selected item
this._lastchoice = null;		// last item chosen from the list
this._curpage = 0;				// current page being shown
this._pagesize = 16;			// max number of entries on a page
this._lastsubchoice = "";		// last item chosen from the selected item display
this._showDetails = false;		// when on, displays the datakey on the list and on the selected item page
this._baseTime = 48;			// base time, using cobra mk3 as a reference
this._preCalls = [];
this._postCalls = [];
this._spinning = true;
//-------------------------------------------------------------------------------------------------------------
this.$addPreSprayCall = function (ws, fn) {
	this._preCalls.push({ worldScript: ws, functionName: fn });
}
//-------------------------------------------------------------------------------------------------------------
this.$addPostSprayCall = function (ws, fn) {
	this._postCalls.push({ worldScript: ws, functionName: fn });
}
//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
	this.$compileData();
	// pick a random personality to start with
	this._personality = this.$rand(32768) - 1;
}
//-------------------------------------------------------------------------------------------------------------
this.playerBoughtEquipment = function (equipment) {
	var respray = false;
	if (equipment === "EQ_SHIP_RESPRAY") {
		player.ship.removeEquipment("EQ_SHIP_RESPRAY");
		// for 1.82 and later, refund the credits at this point - if the player buys the respray it will be deducted later
		player.credits += 100;
		respray = true;
	}
	if (equipment === "EQ_SHIP_RESPRAY_180") {
		player.ship.removeEquipment("EQ_SHIP_RESPRAY_180");
		// for 1.80, the cost is already zero.
		respray = true;
	}
	if (respray === true) {
		// reset the menu before displaying
		this._spinning = true;
		this._displayType = 0;
		this._curpage = 0;
		this._selectedItem = "";
		this._selectedIndex = 0;
		this._lastchoice = null;
		this._lastsubchoice = null;
		this.$showPage();
	}
}
//-------------------------------------------------------------------------------------------------------------
// get a list of all datakeys available for the players current ship class type (ie. "Cobra Mark III")
this.$compileData = function () {
	this._data = [];
	// get a list of all ship keys that have a role of "player" (ie. these are playable ships, not NPC ships)
	var shipKeys = Ship.keysForRole("player");
	// get the shipdata for the player ship, so we can compare like to like.
	var psdata = Ship.shipDataForKey(player.ship.dataKey);
	// loop through the list
	for (var i = 0; i < shipKeys.length; i++) {
		// get the shipdata entry for this key
		var shipdata = Ship.shipDataForKey(shipKeys[i]);
		// does it match the player's current ship?
		if (shipdata.name == psdata.name && !this.$shipScriptInfoHasResprayOff(shipdata)) {
			// add it to the array if it's not there already
			if (this.$itemIsInArray(shipKeys[i], this._data) === false) {
				this._data.push(shipKeys[i]);
			}
		}
	}
	// sort the array (basic alpha sort)
	this._data.sort();
}
this.$shipScriptInfoHasResprayOff = function (shipdata) {
	if (!shipdata.hasOwnProperty("scriptInfo")) return false;
	if (!shipdata.scriptInfo.hasOwnProperty("respray")) return false;
	if (!shipdata.scriptInfo.respray) return false;
	return true;
}
//-------------------------------------------------------------------------------------------------------------
this.playerBoughtNewShip = function (ship, price) {
	// recompile the list whenever the player buys a new ship
	this.$compileData();
}
//=============================================================================================================
// screen interfaces
//-------------------------------------------------------------------------------------------------------------
this.$showPage = function () {
	var curChoices = {};
	if (this.$isBigGuiActive() === true) {
		this._pagesize = 22;
	} else {
		this._pagesize = 16;
	}
	if (this._displayType === 0) {
		var min = (this._curpage * this._pagesize);
		var max = this._curpage * this._pagesize + this._pagesize;
		if (max >= this._data.length) max = this._data.length;
		for (var i = min; i < max; i++) {
			curChoices["01_ITEM_" + (i < 10 ? "0" : "") + i + "~" + this._data[i]] = {
				text: expandDescription("[respray_style]", { name: player.ship.shipClassName, option: (i + 1).toString() }) +
					(this._showDetails === true ? " (" + this._data[i] + ")" : ""), color: "orangeColor", alignment: "LEFT"
			};
		}
		if (max - min < this._pagesize) {
			for (var i = (this._pagesize - (max - min)); i > 0; i--) {
				curChoices["02_SPACER_" + (i < 10 ? "0" : "") + i] = "";
			}
		}
		if (this._showDetails === true) {
			curChoices["94_HIDEKEYS"] = { text: expandDescription("[respray_hide_keys]") };
		} else {
			curChoices["95_SHOWKEYS"] = { text: expandDescription("[respray_show_keys]") };
		}
		if (this._curpage > 0) {
			curChoices["96_PREV"] = { text: expandDescription("[respray_prev_page]"), color: "yellowColor" };
		} else {
			curChoices["96_PREV"] = { text: expandDescription("[respray_prev_page]"), color: "darkGrayColor", unselectable: true };
		}
		if (this._data.length > this._pagesize && this._curpage < (Math.ceil(this._data.length / this._pagesize) - 1)) {
			curChoices["97_NEXT"] = { text: expandDescription("[respray_next_page]"), color: "yellowColor" };
		} else {
			curChoices["97_NEXT"] = { text: expandDescription("[respray_next_page]"), color: "darkGrayColor", unselectable: true };
		}
		curChoices["99_EXIT"] = { text: expandDescription("[respray_exit]"), color: "yellowColor" };
		var def = "99_EXIT";
		var opts = {
			screenID: "oolite-shiprespray-main-map",
			title: expandDescription("[respray_screen_title]", { class: player.ship.shipClassName }),
			allowInterrupt: true,
			overlay: { name: "sr-paint.png", height: 546 },
			exitScreen: "GUI_SCREEN_EQUIP_SHIP",
			choices: curChoices,
			initialChoicesKey: this._lastchoice ? this._lastchoice : def,
			message: expandDescription("[respray_select]")
		};
	}
	if (this._displayType === 1) {
		var calc = Math.floor((player.ship.mass / 214737.6875) * this._baseTime);
		if (calc < 24) calc = 24;
		if (worldScripts.HomeSystem && worldScripts.HomeSystem.$isHomeSystem(system.ID) === true) {
			calc /= 2;
		}
		var def = "98_CLOSE";
		curChoices["02_SELECT"] = { text: expandDescription("[respray_purchase]", { time: calc.toFixed(1) }), color: "yellowColor" };
		curChoices["03_PERSONALITY"] = { text: expandDescription("[respray_personality]", { personality: this._personality }), color: "yellowColor" };
		if (this._spinning === true) {
			curChoices["04_STOP_SPIN"] = { text: expandDescription("[respray_stop_spin]"), color: "yellowColor" };
		} else {
			curChoices["05_START_SPIN"] = { text: expandDescription("[respray_start_spin]"), color: "yellowColor" };
		}
		curChoices["98_CLOSE"] = { text: expandDescription("[respray_close]"), color: "yellowColor" };
		var opts = {
			screenID: "oolite-shiprespray-item-map",
			title: expandDescription("[respray_screen_title]", { class: player.ship.shipClassName }),
			model: "[" + this._selectedItem + "]",
			spinModel: this._spinning,
			modelPersonality: this._personality,
			exitScreen: "GUI_SCREEN_EQUIP_SHIP",
			allowInterrupt: true,
			choices: curChoices,
			initialChoicesKey: this._lastsubchoice ? this._lastsubchoice : def,
			message: expandDescription("[respray_style]", { name: player.ship.shipClassName, style: (this._selectedIndex + 1).toString() + (this._showDetails === true ? " (" + this._selectedItem + ")" : "") })
		};
	}
	mission.runScreen(opts, this.$selectScreenHandler, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$selectScreenHandler = function (choice) {
	if (choice == null) return;
	if (choice.indexOf("~") >= 0) {
		this._displayType = 1;
		this._selectedItem = choice.substring(choice.indexOf("~") + 1);
		this._selectedIndex = parseInt(choice.substring(8, 10));
		this._lastchoice = choice;
		this._lastsubchoice = null;
	} else if (choice === "02_SELECT") {
		// need code to recreate player ship, transferring all cargo and equipment
		this.$resprayShip(this._selectedItem, this._personality);
		choice = "99_EXIT";
	} else if (choice === "04_STOP_SPIN") {
		this._spinning = false;
	} else if (choice === "05_START_SPIN") {
		this._spinning = true;
	} else if (choice === "03_PERSONALITY") {
		this._personality = this.$rand(32768) - 1;
		this._lastsubchoice = "03_PERSONALITY";
	} else if (choice === "94_HIDEKEYS") {
		this._showDetails = false;
		this._lastchoice = "95_SHOWKEYS";
	} else if (choice === "95_SHOWKEYS") {
		this._showDetails = true;
		this._lastchoice = "94_HIDEKEYS";
	} else if (choice === "96_PREV") {
		this._curpage -= 1;
		if (this._curpage > 0) {
			this._lastchoice = choice;
		} else {
			this._lastchoice = "97_NEXT";
		}
	} else if (choice === "97_NEXT") {
		this._curpage += 1;
		if (this._curpage < (Math.ceil(this._data.length / this._pagesize) - 1)) {
			this._lastchoice = choice;
		} else {
			this._lastchoice = "96_PREV";
		}
	} else if (choice === "98_CLOSE") {
		this._displayType = 0;
	}
	if (choice != "99_EXIT") {
		this.$showPage();
	}
}
//-------------------------------------------------------------------------------------------------------------
// do the respray, using ShipStorageHelper
this.$resprayShip = function (dataKey, personality) {
	var p = player.ship;
	var playershipname = p.shipUniqueName;
	var hud = p.hud;
	if (this._preCalls.length > 0) {
		for (var i = 0; i < this._preCalls.length; i++) {
			var itm = this._preCalls[i];
			worldScripts[itm.worldScript][itm.functionName]();
		}
	}
	// first, store all equipment and cargo the player might have
	var shipstr = worldScripts["Ship_Storage_Helper.js"].storeCurrentShip();
	// change the datakey to the new one
	var data = JSON.parse(shipstr);
	data[1] = dataKey; // apply the data key to the ship
	data[13] = personality; // apply the selected personality to the ship
	shipstr = JSON.stringify(data);
	var lmss = worldScripts.LMSS_Core;
	if (lmss) lmss._switching = true;
	// store the current list of player roles
	var roles = [];
	for (var i = 0; i < p.roleWeights.length; i++) {
		roles.push(p.roleWeights[i]);
	}
	// restore the players ship
	worldScripts["Ship_Storage_Helper.js"].restoreStoredShip(shipstr);
	// restore the previous list of roles
	for (var i = 0; i < p.roleWeights.length; i++) {
		if (roles.length - 1 >= i) p.setPlayerRole(roles[i], i);
	}
	if (lmss) lmss._switching = false;
	// restore some things that the storage helper doesn't replace
	p.shipUniqueName = playershipname;
	p.hud = hud;
	// charge the player
	player.credits -= 100;
	if (this._postCalls.length > 0) {
		for (var i = 0; i < this._postCalls.length; i++) {
			var itm = this._postCalls[i];
			worldScripts[itm.worldScript][itm.functionName]();
		}
	}
	// send an email if the email system is installed
	var w = worldScripts.EmailSystem;
	if (w) {
		var ga = worldScripts.GalCopAdminServices;
		w.$createEmail({
			sender: expandDescription("[purchase-maintenance-sender]"),
			subject: expandDescription("[respray_screen_title]", { class: p.shipClassName }),
			date: global.clock.seconds,
			message: expandDescription("[respray_email]", { class: p.shipClassName }),
			expiryDays: ga._defaultExpiryDays
		}
		);
	}
	// work out how much install time is required
	// using cobra mass as the benchmark
	var install = Math.floor((p.mass / 214737.6875) * this._baseTime);
	if (install < 24) install = 24;
	// only half the time if this is our home system
	if (worldScripts.HomeSystem && worldScripts.HomeSystem.$isHomeSystem(system.ID) === true) {
		install /= 2;
	}
	install = parseInt(install * 60 * 60);
	mission.runScreen({
		screenID: "oolite-shiprespray-complete-map",
		title: expandDescription("[respray_screen_title]", { class: player.ship.shipClassName }),
		model: "[" + dataKey + "]",
		modelPersonality: personality,
		allowInterrupt: true,
		message: expandDescription("[respray_success]"),
		exitScreen: "GUI_SCREEN_EQUIP_SHIP",
	});
	global.clock.addSeconds(install);
	// if the station dock control is installed, tell it to check for launched ships
	if (worldScripts.StationDockControl) {
		var w = worldScripts.StationDockControl;
		if (w._disable === false) {
			w.$checkForLaunchedShips();
		}
	}
	this._displayType = 0;
	this._lastchoice = null;
}
//=============================================================================================================
// helper functions
//-------------------------------------------------------------------------------------------------------------
// return a random number between 1 and max
this.$rand = function (max) {
	return Math.floor((Math.random() * max) + 1)
}
//-------------------------------------------------------------------------------------------------------------
// checks if a given element is in the array
this.$itemIsInArray = function (element, array) {
	var found = false;
	if (array != null && array.length > 0) {
		for (var i = 0; i < array.length; i++) {
			if (array[i] === element) found = true;
		}
	}
	return found;
}
//-------------------------------------------------------------------------------------------------------------
// returns true if a HUD with allowBigGUI is enabled, otherwise false
this.$isBigGuiActive = function () {
	if (oolite.compareVersion("1.83") <= 0) {
		return player.ship.hudAllowsBigGui;
	} else {
		var bigGuiHUD = ["XenonHUD.plist", "coluber_hud_ch01-dock.plist"]; 	// until there is a property we can check, I'll be listing HUD's that have the allow_big_gui property set here
		if (bigGuiHUD.indexOf(player.ship.hud) >= 0) {
			return true;
		} else {
			return false;
		}
	}
}
 |