"use strict";
this.name = "Escort_Contracts";
this.version = "1.7.1"; // 2015-12-04
this.author = "capt murphy";
this.copyright = "2011 capt murphy";
this.licence = "CC BY-NC-SA 3.0"; // see http://creativecommons.org/licenses/by-nc-sa/3.0/ for more info.
this.description = "Allows players to enter into short-term escort contracts with NPC traders.";

//------------------------------------------------------------------------------------------------------------------------------------------
// constants for the contract creation procedure and the random chances involved (calculated in this.$EscortF4Interface()):

this.$ccOldStyle = 0; // If set to 1, contracts are only available to systems with lower government type than the current 
// system. This was the standard procedure for earlier versions. To accurately recreate the behaviour  
// of version 1.6.x, $ccFactor must be 0.4 and $ccSystemFactor 0.5. 

this.$ccFactor = 0.4; // Determines by the formula ccFactor * (1+(reputation/20)) how probable it is that contract 
// creation is started. Standard value is 0.4 for both old and new style creation, this value results 
// in p = 0.2 for minimum (-10), p = 0.4 for neutral (0) and p = 0.8 for maximum (20) reputation.

this.$ccSystemFactor = 0.5; // Determines how probable it is that a possible target system actually is chosen for a contract.
// Using the new style, the probability is calculated by p = ccSystemFactor*(1-govType/10). 
// Example: ccSystemFactor = 0.5 gives probabilities between 0.15 for type 7 (corporate states)
// and 0.5 for type 0 (anarchies). 
// The old style uses p = ccSystemFactor for all planets with government types lower than the
// current system. 
// Standard value is 0.5 for both old and new style creation. 

this.$ccMaxGovType = 5; // Safest government type that will be considered for contracts, ignored when old style is selected. 
// Standard value is 5 (confederation).									

this.$ccChooseAll = 0; // increase all contract offering chances to 1 for testing. Should of course be 0 for normal playing! 

//------------------------------------------------------------------------------------------------------------------------------------------

this.$debugMode = 0; // Write debug information to logfile 

this.$resetTargetSystem = 0; // for storing and resetting the selected target system when using the contract selection map

this._guiUI = "not_set";

// initialisation on game startup								
this.startUp = function () {
	if (!missionVariables.ec_escortrep) // first run of oxp - ec_escortrep should be only persistent variable between save games unless game is saved just after a contract is accepted.
	{
		this.ec_escortrep = 0;
	} else {
		this.ec_escortrep = missionVariables.ec_escortrep;
	} // otherwise load value from save game.

	// Clean up superflous missionVariables from previous versions of OXP.
	// This code was already in version 1.5.6., so it refers to really old versions of this OXP...
	delete missionVariables.ec_contractdifficultydesc;
	delete missionVariables.ec_contractdifficultystars;
	delete missionVariables.ec_escortrepstring;
	delete missionVariables.ec_motherfrustration;
	delete missionVariables.ec_numbertargetsystems;
	delete missionVariables.ec_targetsystemgovernmentname;
	delete missionVariables.ec_targetgovsymbol;
	delete missionVariables.ec_currentsystemeco;
	delete missionVariables.ec_targetecosymbol;
	delete missionVariables.ec_currentsystemname;
	delete missionVariables.ec_currentsystemgov;
	delete missionVariables.ec_currentsystemtech;
	delete missionVariables.ec_currentsystemeco;
	delete missionVariables.ec_targettech;

	if (missionVariables.ec_currentcontract && missionVariables.ec_currentcontract !== "no") {
		// values might be "no" or "YES" if upgrading from previous version of
		// oxp otherwise will be true, "success", or null/false.
		if (missionVariables.ec_currentcontract === "success") {
			// might happen if mother safely enters Aegis, and then player docks at OXP station and uses Save Anywhere.
			this.ec_currentcontract = "success";
		} else {
			// if true or "success" load other contract details from save file.
			this.ec_currentcontract = true;
		}
		this.ec_contractactualprice = parseInt(missionVariables.ec_dbcontractactualprice);
		this.ec_contractexpiretime = missionVariables.ec_contractexpiretime;
		this.ec_killsbonus = parseInt(missionVariables.ec_dbkillsbonus);
		this.ec_missionkills = parseInt(missionVariables.ec_missionkills);
		this.ec_mothername = missionVariables.ec_mothername;
		this.ec_targetsystem = missionVariables.ec_targetsystem;
		this.ec_payment = 0;
		missionVariables.ec_payment = 0;
		this.ec_runcontractsetup = false; // no contract offers when saved game already includes a contract (fix 1.7.1)
		if (this.$debugMode) log("Escort Contracts: start up, loaded game includes contract with trader " + this.ec_mothername);
	} else {
		// otherwise no current contract.
		this.ec_currentcontract = false;
		delete missionVariables.ec_currentcontract;
		this.ec_runcontractsetup = true;
		if (this.$debugMode) log("Escort Contracts: start up, loaded game doesn't include a contract");
	}
	this.$EscortF4Interface(this);
};

this.playerWillSaveGame = function () {
	missionVariables.ec_escortrep = this.ec_escortrep; // always save current reputation
	if (this.ec_currentcontract) // only save other contract essential missionVariables if game is saved whilst there is a current contract.
	{
		missionVariables.ec_currentcontract = this.ec_currentcontract;
		missionVariables.ec_dbcontractactualprice = this.ec_contractactualprice;
		missionVariables.ec_contractexpiretime = this.ec_contractexpiretime;
		missionVariables.ec_dbkillsbonus = this.ec_killsbonus;
		missionVariables.ec_missionkills = this.ec_missionkills;
		missionVariables.ec_mothername = this.ec_mothername;
		missionVariables.ec_targetsystem = this.ec_targetsystem;
	} else {
		delete missionVariables.ec_currentcontract;
	}
};


// Event handler driven function checking conditions for showing contract success mission screen or new contract offer screens. 
// Also defines contract failure if a player docks part way through a contract.
this.shipDockedWithStation = function () {
	this._guiUI = "not_set"; // reset here, in cse the gui UI has changed
	delete this.ec_leftScreen; // reset this flag if present.
	if (!this.ec_currentcontract && player.ship.equipmentStatus("EQ_FRAME_SAVE") !== "EQUIPMENT_OK") {
		// if no current contract and dock is not part of Save Anywhere Process then set flag for contract setup.
		this.ec_runcontractsetup = true;
	} else if (this.ec_currentcontract === "success" && system.info.systemID === this.ec_targetsystem && player.ship.dockedStation.isMainStation && player.ship.equipmentStatus("EQ_FRAME_SAVE") !== "EQUIPMENT_OK") {
		// if docking after successful contract then process award payment etc, unless dock is part of Save Anywhere process.
		this.ec_payment = this.ec_contractactualprice + (this.ec_missionkills * this.ec_killsbonus);
		player.credits += this.ec_payment;
		this.ec_escortrep++;
		if (this.ec_escortrep > 20) {
			this.ec_escortrep = 20;
		}
		mission.setInstructionsKey(null, "Escort_Contracts");
		delete this.ec_currentcontract;
		this.ec_runcontractsuccess = true;
		this.ec_runcontractsetup = true; // chance of another contract being offered after mission screen has ended (this was missing before 1.7.1)
		// remove mother from system if she hasn't docked before the player
		if (this.mother && this.mother.isValid) {
			this.mother.remove(true);
		}
	} else if (this.ec_currentcontract && this.ec_currentcontract !== "success") {
		// docking anywhere whilst contract is ongoing fails contract unless currentcontract is already a "success".
		if (system.info.systemID === this.ec_targetsystem) {
			delete this.ec_currentcontract;
			mission.setInstructionsKey(null, "Escort_Contracts");
			this.ec_escortrep -= 2;
			if (this.ec_escortrep < -10) {
				this.ec_escortrep = -10;
			}
			player.consoleMessage("Escort Contract: You have docked before your mother is safe. Contract terminated.", 10);
			if (this.mother && this.mother.isValid) {
				this.mother.remove(true);
			}
		} else {
			if (this.mother && this.mother.isValid) {
				this.mother.remove(true);
			}
			this.ec_failedtofollowmother();
		}
	}
	this.$EscortF4Interface(this);
};

// sets up appropriate mission screens for either contract success or new contract offers.
this.missionScreenOpportunity = function () {
	if (this._guiUI == "not_set") {
		this._guiUI = ""; // default to local background
		if (worldScripts.Lib_GUI) {
			var lib = worldScripts.Lib_GUI;
			this._guiUI = (lib.$cur == "XenonUI" || lib.$cur == "XenonReduxUI" ? lib.$cur : "");
		} else {
			if (worldScripts.XenonUI) {
				this._guiUI = "XenonUI";
			} else if (worldScripts.XenonReduxUI) {
				this._guiUI = "XenonReduxUI";
			}
		}
	}
	if (player.ship.docked && player.ship.dockedStation.isMainStation && this.ec_runcontractsuccess) {
		// show screens for contract success if appropriate flag is set.
		delete this.ec_runcontractsuccess;
		this.ec_runcontractsetup = true; // chance of another contract being offered after mission screen has ended.
		missionVariables.ec_mothername = this.ec_mothername;
		missionVariables.ec_targetsystemname = system.name;
		missionVariables.ec_payment = this.ec_payment;
		missionVariables.ec_missionkills = this.ec_missionkills;
		if (missionVariables.ec_missionkills === 0) {
			var bkg = "escort_contracts_bkg2.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			mission.runScreen({
				screenID: "escort-contracts",
				title: "ITHA Escort Contract Success",
				messageKey: "contract_success_nokill",
				background: bkg
			});
		} else if (missionVariables.ec_missionkills === 1) {
			var bkg = "escort_contracts_bkg2b.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			mission.runScreen({
				screenID: "escort-contracts",
				title: "ITHA Escort Contract Success",
				messageKey: "contract_success_onekill",
				background: bkg
			});
		} else if (missionVariables.ec_missionkills > 1) {
			var bkg = "escort_contracts_bkg2c.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			mission.runScreen({
				screenID: "escort-contracts",
				title: "ITHA Escort Contract Success",
				messageKey: "contract_success",
				background: bkg
			});
		}
		delete missionVariables.ec_mothername;
		delete missionVariables.ec_targetsystem;
		delete missionVariables.ec_payment;
		delete missionVariables.ec_missionkills;
		delete missionVariables.ec_targetsystemname;
	} else if (this.ec_runcontractsetup) {
		delete this.ec_runcontractsetup;
	}
};

//  the following functions control the offering and display of the available new contracts on mission screens.		
//  sets up arrays containing the info needed for potential contracts

this.$EscortF4Interface = function (w) {

	// Various validity checks including random factor modified by escortrep to see if contracts will be offered.
	if (player.ship.docked && player.ship.dockedStation.isMainStation && player.ship.equipmentStatus("EQ_ESCORTCONTRACTS") === "EQUIPMENT_OK" &&
		this.ec_runcontractsetup && player.bounty === 0 && (this.$ccChooseAll || Math.random() < (this.$ccFactor * (1 + (this.ec_escortrep / 20))))) {
		if (this.$debugMode) log("Escort Contracts: contracts available");

		// get IDs of all systems in jump range
		var systemsInRange = SystemInfo.systemsInRange(7); // array of systemInfos within 7 light years
		var systemsInRangeID = new Array(); // array to hold ID's only of systems in range
		var counter = 0;
		for (counter = 0; counter < systemsInRange.length; counter++) {
			systemsInRangeID[counter] = systemsInRange[counter].systemID;
		}

		// select only some of the systems in range 
		this.ec_targetsystems = new Array(); // array to hold IDs of possible contract destinations.
		var thisGalaxy = system.info.galaxyID;
		var tempcounter = 0;
		var targetGovernment = 0;
		var maxGovernment = 0;
		var systemProbability = 0;
		for (counter = 0; counter < systemsInRangeID.length; counter++) {
			targetGovernment = System.infoForSystem(thisGalaxy, systemsInRangeID[counter]).government;
			if (this.$ccOldStyle) {
				// Select only systems with lower government types than the current system. 
				systemProbability = this.$ccSystemFactor; // standard value is 0.5
				maxGovernment = system.government - 1;
			} else {
				// Select systems with government type $ccMaxGovType or lower. Safer systems have a lower probability of being chosen. 
				systemProbability = this.$ccSystemFactor * (1 - targetGovernment / 10);
				maxGovernment = this.$ccMaxGovType;
			}
			if (targetGovernment <= maxGovernment && (this.$ccChooseAll || Math.random() < systemProbability) && !System.infoForSystem(thisGalaxy, systemsInRangeID[counter]).sun_gone_nova) {
				// add system to the contract offers 
				this.ec_targetsystems[tempcounter] = systemsInRangeID[counter];
				tempcounter++;
				if (this.$debugMode) log("Escort Contracts: target system " + System.infoForSystem(thisGalaxy, systemsInRangeID[counter]).name + ", government: " + targetGovernment + ", probability: " + systemProbability + ", chosen");
			} else if (this.$debugMode) {
				log("Escort Contracts: target system " + System.infoForSystem(thisGalaxy, systemsInRangeID[counter]).name + ", government: " + targetGovernment + ", probability: " + systemProbability + ", not chosen");
			}
		}

		// Because of the random factors, the target list can be empty. 
		// In this case no contract interface is visible at all (fix 1.7.1).
		if (tempcounter === 0) {
			player.ship.dockedStation.setInterface("escort_f4contracts", null);
			if (this.$debugMode) log("Escort Contracts: target list empty");
		} else {
			// create and populate other arrays to hold contract info for each potential target system
			missionVariables.ec_numbertargetsystems = this.ec_targetsystems.length;
			this.ec_targetsystemsgovernment = new Array(this.ec_targetsystems.length);
			this.ec_targetsystemseco = new Array(this.ec_targetsystems.length);
			this.ec_targetsystemstech = new Array(this.ec_targetsystems.length);
			this.ec_targetsystemsnames = new Array(this.ec_targetsystems.length);
			this.ec_mothernames = new Array(this.ec_targetsystems.length);
			this.ec_contractbaseprices = new Array(this.ec_targetsystems.length);
			this.ec_contractactualprices = new Array(this.ec_targetsystems.length);
			this.ec_killsbonuses = new Array(this.ec_targetsystems.length);
			counter = 0;
			for (counter = 0; counter < this.ec_targetsystems.length; counter++) {
				this.ec_targetsystemsgovernment[counter] = System.infoForSystem(thisGalaxy, this.ec_targetsystems[counter]).government;
				this.ec_targetsystemseco[counter] = System.infoForSystem(thisGalaxy, this.ec_targetsystems[counter]).economy;
				this.ec_targetsystemstech[counter] = System.infoForSystem(thisGalaxy, this.ec_targetsystems[counter]).techlevel;
				this.ec_targetsystemsnames[counter] = System.infoForSystem(thisGalaxy, this.ec_targetsystems[counter]).name;
				this.ec_mothernames[counter] = randomName();
				this.ec_contractbaseprices[counter] = (75 + (75 * (7 - this.ec_targetsystemsgovernment[counter])));
				this.ec_contractactualprices[counter] = Math.round(this.ec_contractbaseprices[counter] * (0.51 + Math.random() + (this.ec_escortrep / 20)));
				this.ec_killsbonuses[counter] = Math.round(40 * (0.51 + Math.random() + (this.ec_escortrep / 20)));
			}
			player.ship.dockedStation.setInterface("escort_f4contracts", {
				title: "ITHA Escort Contracts (" + missionVariables.ec_numbertargetsystems + " available)",
				category: "Escort Jobs",
				summary: "Independent Traders & Hauliers Association pilots will pay you to escort them through a nearby system. You must launch within 3 hours of accepting a contract.",
				callback: this.ec_displaymissionScreens.bind(w)
			});
		}
	} else {
		//remove interface if contract accepted or no offers
		player.ship.dockedStation.setInterface("escort_f4contracts", null);
		if (this.$debugMode) log("Escort Contracts: no contracts available");
	}
};

// shows mission screen for selecting between available contracts
this.ec_displaymissionScreens = function () {
	if (this.$isBigGuiActive() == false && player.ship.hudHidden == false) {
		player.ship.hudHidden = true; // added with version 1.6.3 to make room on the map screen
	}

	var bkg = "escort_contracts_bkg4.png";
	if (this._guiUI != "") bkg = this.$getXenonBackground();

	if (missionVariables.ec_numbertargetsystems === 1) {
		this.$resetTargetSystem = player.ship.targetSystem; // save it because it will be changed when using the map
		this.ec_contractno = 0;
		this.ec_updatemissionvariables();
		mission.runScreen({
			screenID: "escort-contracts",
			title: "Escort Contract: Trader " + (this.ec_mothernames[this.ec_contractno]),
			messageKey: "contract_info",
			choicesKey: "agree_exit",
			initialChoicesKey: "2_VIEW_CHART",
			model: "ITHAcoin",
			background: bkg,
			overlay: "welcomeCom.png"
		}, this.ec_contractchoice2.bind(this));
	} else if (missionVariables.ec_numbertargetsystems > 1) {
		this.$resetTargetSystem = player.ship.targetSystem; // save it because it will be changed when using the map
		this.ec_contractno = 0;
		this.ec_updatemissionvariables();
		mission.runScreen({
			screenID: "escort-contracts",
			title: "Escort Contract " + (this.ec_contractno + 1) + ": Trader " + this.ec_mothernames[this.ec_contractno],
			messageKey: "contract_info",
			choicesKey: "agree_exit_next_previous",
			initialChoicesKey: "2_NEXT",
			model: "ITHAcoin",
			background: bkg,
			overlay: "welcomeCom.png"
		}, this.ec_contractchoice4.bind(this));
	} else if (this.ec_leftScreen) {
		player.consoleMessage("Escort Contracts - All Independent Traders have now secured an escort. No contracts currently available.", 10);
		delete this.ec_leftScreen;
		player.ship.dockedStation.setInterface("escort_f4contracts", null); //remove interface if contract accepted or no offers
	} else {
		player.ship.dockedStation.setInterface("escort_f4contracts", null); //remove interface if contract accepted or no offers
	}
};

// function used if player leaves mission screens without accepting a contract ("decline all")
this.ec_leaveScreen = function () {
	player.ship.hudHidden = false; // show HUD again (added 1.6.3) 
	player.ship.targetSystem = this.$resetTargetSystem; // reset previously selected target system (added 1.7.1)                 

	this.ec_updatecontractsTime = clock.minutes + (60 + Math.round(Math.random() * 660));
	if (!this.ec_pendingScreenTimer) {
		this.ec_pendingScreenTimer = new Timer(this, this.ec_screenCheck, 1, 3);
	} else {
		this.ec_pendingScreenTimer.start();
	}
};

// mission screen choices for 1 contract available (without next and previous options).
this.ec_contractchoice2 = function (choice) {
	if (this.$isBigGuiActive() == false && player.ship.hudHidden == false) {
		player.ship.hudHidden = true; // added 1.6.3
	}

	switch (choice) {
		case "1_AGREE":
			var bkg = "escort_contracts_bkg3.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			this.ec_currentcontract = true;
			this.ec_contractexpiretime = clock.minutes + 180;
			this.ec_missionkills = 0;
			this.ec_payment = 0;
			this.ec_mothername = missionVariables.ec_mothername;
			this.ec_targetsystem = missionVariables.ec_targetsystem;
			this.ec_contractactualprice = missionVariables.ec_dbcontractactualprice;
			this.ec_killsbonus = missionVariables.ec_dbkillsbonus;
			player.ship.hudHidden = false; // show HUD again (fix 1.7.1) 	
			mission.runScreen({
				screenID: "escort-contracts",
				title: "ITHA Escort Contract Agreed",
				messageKey: "contract_agreed",
				background: bkg
			});
			mission.setInstructionsKey("Contract_Details", "Escort_Contracts");
			this.ec_cleanupmissionVariables();
			delete this.ec_pendingScreenTimer;
			player.ship.dockedStation.setInterface("escort_f4contracts", null); //remove interfaces option after acceptance
			player.ship.targetSystem = this.$resetTargetSystem;
			break;
		case "2_VIEW_CHART":
			var bkg = "contracts_chart.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			player.ship.targetSystem = missionVariables.ec_targetsystem;
			mission.runScreen({
				screenID: "escort-contracts",
				title: "Escort Contract: Trader " + (this.ec_mothernames[this.ec_contractno]),
				messageKey: "contract_chart",
				choicesKey: "chart_agree_exit",
				initialChoicesKey: "2_RETURN",
				background: bkg,
				backgroundSpecial: "SHORT_RANGE_CHART"
			}, this.ec_contractchoice2.bind(this));
			break;
		case "2_RETURN":
			var bkg = "escort_contracts_bkg.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			mission.runScreen({
				screenID: "escort-contracts",
				title: "Escort Contract: Trader " + (this.ec_mothernames[this.ec_contractno]),
				messageKey: "contract_info",
				choicesKey: "agree_exit",
				initialChoicesKey: "2_VIEW_CHART",
				background: bkg
			}, this.ec_contractchoice2.bind(this));
			break;
		case "3_EXIT_RETURN":
			this.ec_leaveScreen();
			break;
		default:
			this.ec_cleanupmissionVariables();
			player.ship.dockedStation.setInterface("escort_f4contracts", null); //remove interfaces option after rejection, though these lines never should happen
	}
};

// mission screen choices for 2 or more contracts available (including next and previous options).
this.ec_contractchoice4 = function (choice) {
	if (this.$isBigGuiActive() == false && player.ship.hudHidden == false) {
		player.ship.hudHidden = true; // added 1.6.3
	}

	switch (choice) {
		case "1_AGREE":
			var bkg = "escort_contracts_bkg3.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			this.ec_currentcontract = true;
			this.ec_contractexpiretime = clock.minutes + 180;
			this.ec_missionkills = 0;
			this.ec_payment = 0;
			this.ec_mothername = missionVariables.ec_mothername;
			this.ec_targetsystem = missionVariables.ec_targetsystem;
			this.ec_contractactualprice = missionVariables.ec_dbcontractactualprice;
			this.ec_killsbonus = missionVariables.ec_dbkillsbonus;
			player.ship.hudHidden = false; // show HUD again (fix 1.7.1)	
			mission.runScreen({
				screenID: "escort-contracts",
				title: "ITHA Escort Contract Agreed",
				messageKey: "contract_agreed",
				background: bkg
			});
			mission.setInstructionsKey("Contract_Details", "Escort_Contracts");
			this.ec_cleanupmissionVariables();
			delete this.ec_pendingScreenTimer;
			player.ship.dockedStation.setInterface("escort_f4contracts", null); //remove interfaces option after acceptance
			player.ship.targetSystem = this.$resetTargetSystem;
			break;
		case "2_NEXT":
			var bkg = "escort_contracts_bkg.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			this.ec_contractno++;
			if (this.ec_contractno === missionVariables.ec_numbertargetsystems) {
				this.ec_contractno = 0;
			}
			this.ec_updatemissionvariables();
			mission.runScreen({
				screenID: "escort-contracts",
				title: "Escort Contract " + (this.ec_contractno + 1) + ": Trader " + this.ec_mothernames[this.ec_contractno],
				messageKey: "contract_info",
				choicesKey: "agree_exit_next_previous",
				initialChoicesKey: "2_NEXT",
				background: bkg
			}, this.ec_contractchoice4.bind(this));
			break;
		case "3_PREVIOUS":
			var bkg = "escort_contracts_bkg.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			this.ec_contractno--;
			if (this.ec_contractno < 0) {
				this.ec_contractno = (missionVariables.ec_numbertargetsystems - 1);
			}
			this.ec_updatemissionvariables();
			mission.runScreen({
				screenID: "escort-contracts",
				title: "Escort Contract " + (this.ec_contractno + 1) + ": Trader " + this.ec_mothernames[this.ec_contractno],
				messageKey: "contract_info",
				choicesKey: "agree_exit_next_previous",
				initialChoicesKey: "3_PREVIOUS",
				background: bkg
			}, this.ec_contractchoice4.bind(this));
			break;
		case "2_NEXTCHART":
			var bkg = "contracts_chart.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			this.ec_contractno++;
			if (this.ec_contractno === missionVariables.ec_numbertargetsystems) {
				this.ec_contractno = 0;
			}
			this.ec_updatemissionvariables();
			player.ship.targetSystem = missionVariables.ec_targetsystem;
			mission.runScreen({
				screenID: "escort-contracts",
				title: "Escort Contract " + (this.ec_contractno + 1) + ": Trader " + this.ec_mothernames[this.ec_contractno],
				messageKey: "contract_chart",
				choicesKey: "chart_agree_exit_next_previous",
				initialChoicesKey: "2_NEXTCHART",
				background: bkg,
				backgroundSpecial: "SHORT_RANGE_CHART"
			}, this.ec_contractchoice4.bind(this));
			break;
		case "3_PREVIOUSCHART":
			var bkg = "contracts_chart.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			this.ec_contractno--;
			if (this.ec_contractno < 0) {
				this.ec_contractno = (missionVariables.ec_numbertargetsystems - 1);
			}
			this.ec_updatemissionvariables();
			player.ship.targetSystem = missionVariables.ec_targetsystem;
			mission.runScreen({
				screenID: "escort-contracts",
				title: "Escort Contract " + (this.ec_contractno + 1) + ": Trader " + this.ec_mothernames[this.ec_contractno],
				messageKey: "contract_chart",
				choicesKey: "chart_agree_exit_next_previous",
				initialChoicesKey: "3_PREVIOUSCHART",
				background: bkg,
				backgroundSpecial: "SHORT_RANGE_CHART"
			}, this.ec_contractchoice4.bind(this));
			break;
		case "4_VIEW_CHART":
			var bkg = "contracts_chart.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			player.ship.targetSystem = missionVariables.ec_targetsystem;
			mission.runScreen({
				screenID: "escort-contracts",
				title: "Escort Contract " + (this.ec_contractno + 1) + ": Trader " + this.ec_mothernames[this.ec_contractno],
				messageKey: "contract_chart",
				choicesKey: "chart_agree_exit_next_previous",
				initialChoicesKey: "4_RETURN",
				background: bkg,
				backgroundSpecial: "SHORT_RANGE_CHART"
			}, this.ec_contractchoice4.bind(this));
			break;
		case "4_RETURN":
			var bkg = "escort_contracts_bkg.png";
			if (this._guiUI != "") bkg = this.$getXenonBackground();
			mission.runScreen({
				screenID: "escort-contracts",
				title: "Escort Contract " + (this.ec_contractno + 1) + ": Trader " + this.ec_mothernames[this.ec_contractno],
				messageKey: "contract_info",
				choicesKey: "agree_exit_next_previous",
				initialChoicesKey: "4_VIEW_CHART",
				background: bkg
			}, this.ec_contractchoice4.bind(this));
			break;
		case "5_EXIT_RETURN":
			this.ec_leaveScreen();
			break;
		default:
			this.ec_cleanupmissionVariables();
			player.ship.dockedStation.setInterface("escort_f4contracts", null); //remove interfaces option after rejection, though this line never should happen		
	}
};

// used to display prompt messages if player has left mission screens.
this.ec_screenCheck = function ec_screenCheck() {
	if (!player.ship.docked) {
		this.ec_pendingScreenTimer.stop();
		return;
	}
};

// returns player to missionscreens having looked at charts.
this.guiScreenChanged = function (to, from) {
	if (this.ec_pendingScreenTimer) {
		this.ec_pendingScreenTimer.stop();
		if (clock.minutes > this.ec_updatecontractsTime) // if player has been away from mission screens for some time re-evaluate contract offers.
		{
			this.ec_leftScreen = true;
			delete this.ec_pendingScreenTimer;
			this.ec_cleanupmissionVariables();
			player.ship.dockedStation.setInterface("escort_f4contracts", null); //remove interfaces option after timeout
		}
		return;
	}
};

// called to create missionVariables for display on the mission screens.
this.ec_updatemissionvariables = function () {
	missionVariables.ec_mothername = this.ec_mothernames[this.ec_contractno];
	missionVariables.ec_targetsystem = this.ec_targetsystems[this.ec_contractno];
	missionVariables.ec_dbcontractactualprice = this.ec_contractactualprices[this.ec_contractno];
	missionVariables.ec_targetsystemname = this.ec_targetsystemsnames[this.ec_contractno];
	missionVariables.ec_dbkillsbonus = this.ec_killsbonuses[this.ec_contractno];
	missionVariables.ec_targetgovsymbol = String.fromCharCode(this.ec_targetsystemsgovernment[this.ec_contractno]);
	missionVariables.ec_targetecosymbol = String.fromCharCode(23 - this.ec_targetsystemseco[this.ec_contractno]);
	missionVariables.ec_targettech = this.ec_targetsystemstech[this.ec_contractno] + 1;
	missionVariables.ec_currentsystemname = system.name;
	missionVariables.ec_currentsystemgov = String.fromCharCode(system.government);
	missionVariables.ec_currentsystemtech = system.techLevel + 1;
	missionVariables.ec_currentsystemeco = String.fromCharCode(23 - system.economy);

	switch (this.ec_targetsystemsgovernment[this.ec_contractno]) {
		case 0:
			missionVariables.ec_contractdifficultydesc = "very high";
			missionVariables.ec_contractdifficultystars = String.fromCharCode(8, 8, 8, 8, 8);
			missionVariables.ec_targetsystemgovernmentname = "an anarchy";
			break;
		case 1:
			missionVariables.ec_contractdifficultydesc = "high";
			missionVariables.ec_contractdifficultystars = String.fromCharCode(8, 8, 8, 8, 24);
			missionVariables.ec_targetsystemgovernmentname = "a feudal state";
			break;
		case 2:
			missionVariables.ec_contractdifficultydesc = "moderate";
			missionVariables.ec_contractdifficultystars = String.fromCharCode(8, 8, 8, 24, 24);
			missionVariables.ec_targetsystemgovernmentname = "a multi-government system";
			break;
		case 3:
			missionVariables.ec_contractdifficultydesc = "moderate";
			missionVariables.ec_contractdifficultystars = String.fromCharCode(8, 8, 8, 24, 24);
			missionVariables.ec_targetsystemgovernmentname = "a dictatorship";
			break;
		case 4:
			missionVariables.ec_contractdifficultydesc = "low";
			missionVariables.ec_contractdifficultystars = String.fromCharCode(8, 8, 24, 24, 24);
			missionVariables.ec_targetsystemgovernmentname = "a communist system";
			break;
		case 5:
			missionVariables.ec_contractdifficultydesc = "low";
			missionVariables.ec_contractdifficultystars = String.fromCharCode(8, 8, 24, 24, 24);
			missionVariables.ec_targetsystemgovernmentname = "a confederacy";
			break;
		case 6:
			missionVariables.ec_contractdifficultydesc = "very low";
			missionVariables.ec_contractdifficultystars = String.fromCharCode(8, 24, 24, 24, 24);
			missionVariables.ec_targetsystemgovernmentname = "a democracy";
			break;
		case 7:
			missionVariables.ec_contractdifficultydesc = "very low";
			missionVariables.ec_contractdifficultystars = String.fromCharCode(8, 24, 24, 24, 24);
			missionVariables.ec_targetsystemgovernmentname = "a corporate state";
			break;
			// case 7 couldn't happen in versions before 1.7.1 because the target system goverment was 
			// always at least 1 lower than the current government. With 1.7.1 this was changed, 
			// but now government 6 and 7 systems are excluded completely. But since this is user-configurable, 
			// somebody could chose to include type 7 systems, so better be safe. 	
	}
};

// clean up mission variables after contract mission screens.
this.ec_cleanupmissionVariables = function () {
	delete missionVariables.ec_contractdifficultydesc;
	delete missionVariables.ec_contractdifficultystars;
	delete missionVariables.ec_numbertargetsystems;
	delete missionVariables.ec_targetsystem;
	delete missionVariables.ec_targetsystemgovernmentname;
	delete missionVariables.ec_targetsystemname;
	delete missionVariables.ec_dbcontractactualprice;
	delete missionVariables.ec_dbkillsbonus;
	delete missionVariables.ec_mothername;
	delete missionVariables.ec_targetgovsymbol;
	delete missionVariables.ec_currentsystemeco;
	delete missionVariables.ec_targetecosymbol;
	delete missionVariables.ec_currentsystemname;
	delete missionVariables.ec_currentsystemgov;
	delete missionVariables.ec_currentsystemtech;
	delete missionVariables.ec_currentsystemeco;
	delete missionVariables.ec_targettech;
};

// event handler function to spawn the mother on player launch if she does not
// exist but there is a current contract.
this.shipWillLaunchFromStation = function () {
	if (this.ec_currentcontract && this.ec_currentcontract !== "success") {
		if (system.countShipsWithRole("ec_mother") === 0 && clock.minutes < this.ec_contractexpiretime) {
			this.mother = system.addShips("ec_mother", 1, system.mainStation.position.subtract(system.mainStation.vectorForward.multiply(14000)), 4000)[0];
		} else {
			// if more than 3 game hours passed since agreeing contract - fail contract.
			player.consoleMessage("Escort Contract - You failed to launch within the allocated time window. Your mother has already departed. Contract terminated.", 10);
			delete this.ec_currentcontract;
			mission.setInstructionsKey(null, "Escort_Contracts");
			this.ec_escortrep--;
			if (this.ec_escortrep < -10) {
				this.ec_escortrep = -10;
			}
		}
	}
};

// event handler driven function to fail the contract if the player exits
// witchspace into a system where the mother is not present. Also controls
// gradual reduction of positive or negative escort reputation in between
// contracts.
this.shipExitedWitchspace = function () {
	if (system.countShipsWithRole("ec_mother") === 0 && this.ec_currentcontract) {
		// wrong system? 
		if (this.ec_currentcontract === "success") {
			// case where mother safely docked, but player saved at OXP station and never collected reward.
			delete this.ec_currentcontract;
		} else {
			// It is possible that the ship following though a wormhole arrives some seconds 
			// earlier than the ship that had opened the wormhole. If this happens during
			// escorting, it will break the mission, so we have to accept a missing mother 
			// at this point, if the system is the right one. (fix 1.7.1)
			if (system.info.systemID !== this.ec_targetsystem) {
				// Player jumped definitely to the wrong system! Contract terminated immediately. 
				this.ec_failedtofollowmother();
				if (this.$debugMode) log("Escort Contracts: player jumped to wrong system");
			} else {
				// Correct system but no mother present. Either the wormhole arrival order was wrong
				// or the player has jumped on his own _before_ mother. In the latter case, mother 
				// will never show up, and the contract will be terminated at docking. 
				if (this.$debugMode) log("Escort Contracts: player early or has jumped on his own");
			}
		}
	}

	if (!this.ec_currentcontract && Math.random() < 0.1) // no contract - random (10%) chance of reputation erosion.
	{
		this.ec_escortrep = Math.round(this.ec_escortrep * 0.8);
	}

	if (!this.ec_currentcontract && system.countShipsWithRole("ec_mother") !== 0) // if contract has failed, but there is a mother in the system get rid of her.
	{
		this.mother.remove(true);
	}
};

// called from various points within the worldscript if the player has not managed to follow the mother to the target system.
this.ec_failedtofollowmother = function () {
	delete this.ec_currentcontract;
	mission.setInstructionsKey(null, "Escort_Contracts");
	this.ec_escortrep--;
	if (this.ec_escortrep < -10) {
		this.ec_escortrep = -10;
	}
	player.consoleMessage("Escort Contract - You have failed to follow your mother-ship to the target system. Contract terminated.", 10);
};

// keeps a record of hostile pirate kills during the course of the contract. Only kills that occur within 2 scanner ranges of the mother count.
this.shipTargetDestroyed = function (target) {
	if (this.mother && this.mother.isValid && this.ec_currentcontract && player.ship.position.distanceTo(this.mother.position) < (this.mother.scannerRange * 3)) {
		if (target.bounty > 0 && !target.isRock && !target.isCargo) // only kills that have a bounty and ain't rocks or cargo count!
		{
			this.ec_missionkills++;
			// message only if the killed pirate was the only/last one in scanner range 
			// note: The player will only see/hear the message when he is in scanner range. 
			if (!player.alertHostiles) {
				this.mother.commsMessage("[ec_comms_pirate_killed]");
			}
		}
	}
};

// timer called from mother shipscript on the mother entering witchspace to the target system. Fails the contract if the player fails to follow before the wormhole expires. 
this.ec_motherexitedsystem = function (mothermass) {
	var expirytime = 50 + (mothermass / 4000); // same formula as used by core game code to calculate wormhole expiry.
	this.wormholetimer = new Timer(this, this.ec_checkforfollowedmother, expirytime);
};

// called by timer at wormhole expiry. If player is still in original system contract has failed.
this.ec_checkforfollowedmother = function ec_checkforfollowedmother() {
	if (this.ec_currentcontract) {
		if (system.countShipsWithRole("ec_mother") === 0) {
			this.ec_failedtofollowmother();
		}
	}
};

// returns true if a HUD with allowBigGUI is enabled, otherwise false (added in version 1.6.3)
this.$isBigGuiActive = function () {
	if (oolite.compareVersion("1.83") < 0) {
		return player.ship.hudAllowsBigGui;
	} else {
		var bigGuiHUD = ["XenonHUD.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;
		}
	}
}

this.$getXenonBackground = function() {
	if (this._guiUI == "XenonUI") {
		if (worldScripts.XenonUI._amber == true) {
			return {name:"amber_standard_f0_nohud.png", height:546};
		} else {
			return {name:"xenon_standard_f0_nohud.png", height:546};
		}
	}
	if (this._guiUI == "XenonReduxUI") {
		if (worldScripts.XenonReduxUI._amber == true) {
			return {name:"amber_redux_nohud.png", height:546};
		} else {
			return {name:"xenon_redux_nohud.png", height:546};
		}
	}
}

// replaced in version 1.7.1  by damage_probability = 0 in equipment.plist
// function to stop the Escort License being damaged in combat.
//this.equipmentDamaged = function(equipment)
//{
//	if(equipment === "EQ_ESCORTCONTRACTS")
//	{
//		player.ship.setEquipmentStatus(equipment,"EQUIPMENT_OK");
//	}
//};