Back to Index Page generated: May 8, 2024, 6:16:03 AM

Expansion In-System Taxi

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description This oxp adds in-system passenger contracts to the game. Passenger Berth is required along with some extra stations. In-System Taxi Comms equipment allows you to get in-system passenger offers while cruising. This oxp adds in-system passenger contracts to the game. Passenger Berth is required along with some extra stations. In-System Taxi Comms equipment allows you to get in-system passenger offers while cruising.
Identifier oolite.oxp.spara.in-system_taxi oolite.oxp.spara.in-system_taxi
Title In-System Taxi In-System Taxi
Category Activities Activities
Author spara spara
Version 1.2.3 1.2.3
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL http://wiki.alioth.net/index.php/In-System_Taxi n/a
Download URL https://wiki.alioth.net/img_auth.php/2/23/In-system_taxi_1.2.3.oxz n/a
License CC-BY-NC-SA 3.0 CC-BY-NC-SA 3.0
File Size n/a
Upload date 1610873249

Documentation

Also read http://wiki.alioth.net/index.php/In-System%20Taxi

In-System_Taxi_readme_&_license.txt

In-System Taxi OXP ver 1.2.3 (7.2.2015)

Author: spara (Mika Spåra)

_Story_

Taxi Galactica has expanded it's repertoire from interstellar taxi service to in-system taxi service. If you need to get from Kiota Manufacturing Station to RSS Station, Taxi Galactica's in-system taxi service is here for you. Just call our in-system taxi center, and we'll send a cab for you.

_Overview_

This oxp adds in-system passenger contracts to the game. These contracts are fast deliveries from one station to another that must be executed in given time (~15 - 30 min). For a succesful delivery you are paid a fee of ~5-40 credits, depending on distance of the starting point and destination as well as your performance.

With In-System Taxi Comms device you can get receive in-system passenger contract offers through your Comms while you are in flight. The device can be bought from Taxi Galactica stations or if that oxp is not present from main stations.

Type of the contracts offered depends on the oxps installed.

_Usage_with_other_oxps_

You must meet at least one of the following conditions for this oxp to do anything.

1. Some odd oxp stations installed, like WildShips oxp.

With some extra stations installed you get in-system station to station passenger contracts. If there is a passenger waiting at the station you currently are, he/she/it can be found from the interfaces screen (f4). Look for In-system taxi deliveries. If you accept a contract, launch and fly to the destination station. If you reach it in time, you will be thanked and payed. If you performed good, you'll get a premium.

2. Taxi Galactica oxp installed

From Taxi Galactica Station you can buy an In-System Taxi Comms device. The device allows you to receive in-system passenger contract offers through your Comms while you are cruising. To buy such a device, you must have the advanced space compass and at least one passenger berth installed. Device costs you 90 credits. After you have bought the device you have a new primable equipment that is used for accepting in-system taxi offers in-flight. After receiving an offer through comms, you have 60 seconds to accept it. (select equipment with shift-n and activate it with n). After accepting the contract, it is added to your manifest screen. Next pick the passenger from the correct station. You'll be notified, when he/she/it is on board.

Taxi Comms goes to "Taxi unavailable" mode on condition red and stays that way. Mode can be toggled between "Taxi available" and "Taxi unavailable" by priming (shift-n and b). After launch and hyperspace, mode is resetted to "Taxi available." This behaviour can be changed through a variable in taxi_worldscript.js.

3. Planetfall oxp and Planetary Compass oxp installed

These two oxps add planetside locations to in-system passenger contracts. You must have Planetary Landing Cababilities to be offered contracts.

4. Liners oxp installed

This oxp adds liners that are currently in system to in-system passenger contracts.

_Some_notes_

* Only one in-system passenger is allowed at a time.
* Accepted contract can be cancelled by activating the primable equipment second time. The passenger must not have boarded yet.
* Systems with more stations are more likely to offer contracts than systems with fewer stations.
* In-system contract, along with a possible passenger, is resetted when loading a saved game.
* Reset to "Taxi available" mode on lauch and hyperspace can be switched off from this.$availableOnLaunch variable in taxi_worldscript.js.
* In-flight offers' pickup points are limited to max 1000 km dist from player. Max distance is toggleable via this.$maxDistance variable.

_Credits_

Taxi Galactica logo used in a background image.

_Requirements_

Oolite version 1.79.

_Installing_

Install the OXP by copying In-System_Taxi.oxp to your AddOns-folder.

------

This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 4.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/

Equipment

Name Visible Cost [deci-credits] Tech-Level
In-System Taxi Comms yes 600 1+
Remove In-System Taxi Comms yes 100 1+

Ships

This expansion declares no ships.

Models

This expansion declares no models.

Scripts

Path
Scripts/equipment.plist
(
	(
		0, 600, "In-System Taxi Comms",
		"EQ_IN_SYSTEM_TAXI_LICENCE",
		"Join Taxi Galactica's in-system taxi drivers division. Deliver customers from one station to another in-system. Buy this device and you'll receive local delivery offers right to your Comms while cruising. When you get an offer, you have one minute to decide to take it or not. If you want to take it, just prime this small gadget and activate it.",
		{
			"available_to_all" = yes;
			"requires_equipment" = "EQ_ADVANCED_COMPASS";
			"portable_between_ships" = yes;
			"script" = "taxi_equipment.js";
			"damage_probability" = 0.0;
			"condition_script" = "taxi_equipment.js";
		}
	),
	(
		1, 100, "Remove In-System Taxi Comms",
		"EQ_WEAPON_IN_SYSTEM_TAXI_LICENCE_REMOVAL",
		"Stop receiving in-system delivery offers through Comms.",
		{
			"available_to_all" = yes;
			"requires_equipment" = "EQ_IN_SYSTEM_TAXI_LICENCE";
			"condition_script" = "taxi_equipment.js";
		}
	)  
)
Scripts/taxi_equipment.js
this.name           =    "in-system_taxi_equipment";
this.author         =    "spara";
this.copyright      =    "2013-2014 Mika Spåra";
this.licence        =    "CC BY-NC-SA 3.0"; 
this.description    =    "Equipment to accept delivery jobs";
this.version        =    "1.2.2";
"use strict";

//accept or cancel offers with n
this.activated = function() {
	if (worldScripts["in-system_taxi"].$currentOffer[0] == 1) {
		worldScripts["in-system_taxi"].$acceptOffer();	
	}
	else if (worldScripts["in-system_taxi"].$currentOffer[0] == 2){
		worldScripts["in-system_taxi"].$cancelContract();
	}
	else {
		worldScripts["in-system_taxi"].$commsMessage("No contract to accept or cancel");
	}
}

//start or stop receiving offers with b
this.mode = function() {
	if (!worldScripts["in-system_taxi"].$taxiAvailable) {
		player.consoleMessage("Taxi available");
		worldScripts["in-system_taxi"].$taxiAvailable = true;
		if (!worldScripts["in-system_taxi"].$startOfferTimer()) {
			worldScripts["in-system_taxi"].$taxiAvailable = false;
			player.consoleMessage("Taxi unavailable");
		}
	}
	else {
		player.consoleMessage("Taxi unavailable");
		worldScripts["in-system_taxi"].$taxiAvailable = false;
		worldScripts["in-system_taxi"].$stopInFlightTimer();				
	}
}

//equipment restiction. Need passenger berth to buy.
this.allowAwardEquipment = function(eqKey, ship, context) {
	if (eqKey == "EQ_IN_SYSTEM_TAXI_LICENCE" && player.ship.passengerCapacity == 0)
		return false;
	if (worldScripts.taxi_galactica_main) {
		if (player.ship.dockedStation.hasRole("taxi_station")) {
			return true;
		}
	}
	else if (player.ship.dockedStation.isMainStation)
		return true;
	else
		return false;
}
Scripts/taxi_worldscript.js
"use strict";
this.name        = "in-system_taxi"; 
this.description = "In-system passenger contracts"; 

this.startUp = function() {
	//USER TOGGLEABLE VARIABLES START
	this.$availableOnLaunch = true;
	//true sets taxi to available on launch, false sets taxi to unavailable on launch
	this.$maxDistance = 1000000; //maximum distance of pickup point (in meters)
	
	//USER TOGGLEABLE VARIABLES END
	
	// this.$currentOffer = [offer_status, from_name, to_name, deadline, base_fare, passenger_name, system.ID, whole_time]
	// status = 0 no offer or offer declined
	// status = 1 offer waiting for approval
	// status = 2 offer accepted
	// status = 3 passenger on board
	this.$currentOffer = [0];
	if (missionVariables.inSystemTaxi != null) {//remove possible passenger
		player.ship.removePassenger(missionVariables.inSystemTaxi);
	}
	this.$deleteMissionInstructions() //remove possible mission instructions
	this.$stationOffers = []; //array for station offers
	this.$fireMissionScreen = 0; //flag for selecting different mission screens
	this.$readyToOffer = false; //start offering only after first launch
	this.$refTime = clock.seconds;//time keeping for refreshing station contracts
	this.$addedBeacon = [false, false];//flags for temporary beacons
	this.$premium = 0;//needed in different functions, thus global variable
	this.$offerFrequency = 90;//frequency at which new in-flight offers are generated and possibly offered. min 60
	this.$taxiAvailable = this.$availableOnLaunch; //status of availability
}

//fare, based on distance
this.$fare = function(distance) {
	return Math.floor(5 + 0.000005 * distance); //5 cr + 0.5 cr/100 km
}

this.playerWillSaveGame = function () {
	if (this.$currentOffer[0] == 3)//mark in-system passenger to be removed on load
		missionVariables.inSystemTaxi = this.$currentOffer[5]+" (going to "+this.$currentOffer[2].displayName+")";
	else
		missionVariables.inSystemTaxi = null;
}

//Taxi Comms comes through this function
this.$commsMessage = function(message) {
	var notifySound = new SoundSource;
	notifySound.sound = "beep.ogg";
	notifySound.play();
	player.commsMessage("Taxi Galactica's In-System Service:\n"+message, 6);	
}

//find suitable stations
this.$listOfStations = function() {
    function $isAllowed(entity) {
		if (entity.scanClass == "CLASS_STATION") {
			//excludes that have scanClass CLASS_STATION
			if (entity.hasRole("gates_jumpGate")) return false;
			if (entity.hasRole("fuelStation_satellite")) return false;
			if (entity.hasRole("fuelStation_station")) return false;
			if (entity.hasRole("jaguar_company_base")) return false;
			return true;
		}
		if (entity.isStation) {
			//includes that have isStation but not scanClass CLASS_STATION
			if (entity.hasRole("liners_liner")) return true;
			if (entity.hasRole("casinoship")) return true;
			if (entity.hasRole("random_hits_any_spacebar")) return true;
		}
		if (entity.isPlanet && entity.displayName != null) {
			//planetfall && planetary compass
			if (!entity.isSun && !entity.hasOwnProperty("solarGasGiant") && !entity.hasOwnProperty("isGasGiant") && !entity.hasOwnProperty("PFNoLand") && !entity.hasOwnProperty("PFNoLandQuiet") && player.ship.equipmentStatus("EQ_PLANETFALL") == "EQUIPMENT_OK") return true;
		}
		return false;
    }
    return system.filteredEntities(this, $isAllowed);
}

//IN-FLIGHT OFFERING FUNCTIONS START HERE

//set taxi to not available on condition red
this.alertConditionChanged = function(newCondition, oldCondition) {
	if (newCondition == 3) {
		//worldScripts["in-system_taxi"].$commsMessage("Taxi Comms switched off");
		this.$stopInFlightTimer();
	}
}

//start in-flight offer timer
this.$startOfferTimer = this.playerCancelledJumpCountdown = function() {
	//show in-flight contract offers
	if (this.$taxiAvailable && this.$currentOffer[0] < 2 && (player.ship.passengerCapacity - player.ship.passengerCount) > 0 && player.ship.equipmentStatus("EQ_IN_SYSTEM_TAXI_LICENCE") == "EQUIPMENT_OK") {
		this.$startInFlightTimer();
		return true;
	}
	return false;
}

//start in-flight offer timer on launch only if available on launch is set.
this.shipLaunchedFromStation = function(station) {
	if (this.$availableOnLaunch)
		this.$taxiAvailable = true;
	this.$startOfferTimer();
}

//stop in-flight offer timer
this.playerStartedJumpCountdown = function() {
	this.$stopInFlightTimer();
}

//remove in-system contract when exiting system
this.shipWillEnterWitchspace = function() {
	if (this.$currentOffer[0] == 3) {//make in-system passenger regular passenger
		if (player.ship.removePassenger(this.$currentOffer[5]+" (going to "+this.$currentOffer[2].displayName+")"))//try to rename passenger
			player.ship.addPassenger(this.$currentOffer[5], system.ID, system.ID, clock.seconds+10, this.$currentOffer[4]);
		var message = "Taxi passenger "+this.$currentOffer[5]+" is very disappointed having missed the deadline. Return passenger to the main station of "+System.infoForSystem(system.info.galaxyID, this.$currentOffer[6]).name+".";
		var delayedMessage = new Timer(this, function(){this.$commsMessage(message)}, 10);
	}
	if (this.$availableOnLaunch)
		this.$taxiAvailable = true;	
	this.$endContract();
}

//create new in-flight offers
this.$taxiOffer = function() {
	if (system.isInterstellarSpace) return;//sanity check;
	var listOfStations = this.$listOfStations();
	var probability = 0.05 * listOfStations.length; //0.05 * number of stations => 0.10 for 2 stations ... 1 for 20 stations
	if (Math.random() < probability && listOfStations.length > 1) {
		var to = listOfStations.splice(Math.floor(Math.random() * listOfStations.length), 1)[0];
		var from = to;
		var found = false;
		while (listOfStations.length > 0 && !found) {//select suitable pickup point
			from = listOfStations.splice(Math.floor(Math.random() * listOfStations.length), 1)[0];
			if (player.ship.position.distanceTo(from) < this.$maxDistance)
				found = true;
		}
		if (!found) return;//no suitable pickup points
		if (to.isPlanet && from.isPlanet)
			var distance = from.position.distanceTo(to) - to.radius - from.radius;
		else if (to.isPlanet)
			var distance = from.position.distanceTo(to) - to.radius;
		else if (from.isPlanet)
			var distance = from.position.distanceTo(to) - from.radius;
		else
			var distance = from.position.distanceTo(to);
		var baseTime =  0.0002 * distance + 1200; //20 secs per 100 km + 20 mins for reach, launch and incidents.
		var time = clock.seconds + baseTime;
		var fee = this.$fare(distance);
		var name = global.randomName() +" "+ global.randomName();
		this.$commsMessage("Name: "+name+"\nFrom: "+from.displayName + "\nTo: " + to.displayName + "\nTime: "+  Math.floor((time - clock.seconds)/60) +" minutes\nBase fare: " + formatCredits(fee, true, true) + "\nAccept contract in 60 seconds");
		this.$removeOfferTimer();
		this.$offerTimer = new Timer(this, function(){this.$currentOffer = [0];}, 60);//offer ends in 60 secs
		//time contract, so it can be removed if deadline is met before picking the passenger up.
		this.$removeContractTimer();
		this.$contractTimer = new Timer(this, this.$endContract, time - clock.seconds);
		this.$currentOffer = [1, from, to, time, fee, name, system.ID, baseTime];
	}
}

//accept offer
this.$acceptOffer = function() {
	this.$stopInFlightTimer();
	this.$removeOfferTimer();
	this.$currentOffer[0] = 2;
	this.$addMissionInstructions();
	this.$commsMessage("Contract accepted. Pick up passenger at "+this.$currentOffer[1].displayName);
	this.$addBeacon();
}

//cancel contract
this.$cancelContract = function() {
	this.$endContract();
	this.$commsMessage("Contract cancelled");
}

//cancel contract before picking passenger up.
this.$endContract = function() {
	if (this.$currentOffer[0] < 3) {//passenger not on board yet.
		this.$removeBeacon();
		this.$deleteMissionInstructions();
		this.$currentOffer = [0];
		this.$removeContractTimer();
		this.$startOfferTimer();
	}
}

//add mission instructions when accepting contract
this.$addMissionInstructions = function() {
	var deadline = new Date(0, 0, 0, 0, 0, this.$currentOffer[3]);
	var instructionText = "Taxi: "+this.$currentOffer[5]+" from " + this.$currentOffer[1].displayName + " to " + this.$currentOffer[2].displayName + " before " + deadline.toLocaleTimeString() +".";
	mission.setInstructions(instructionText, this.name);	
}

//delete mission instructions when cancelling contract
this.$deleteMissionInstructions = function() {
	mission.setInstructions(null, this.name);
}

//IN-FLIGHT OFFERING FUNCTIONS END HERE

//STATION OFFERING FUNCTIONS START HERE

//create new station offers
this.$createStationOffers = function() {
	if (system.isInterstellarSpace) return;//sanity check;
	var i;
	var listOfStations = this.$listOfStations();
	for (i = 0; i < listOfStations.length; i++) {
		if (listOfStations[i] != player.ship.dockedStation && Math.random() < 0.1) {//contract probability of 0.1 per station in system.
			var from = player.ship.dockedStation;
			var to = listOfStations[i];
			if (to.isplanet)
				var distance = from.position.distanceTo(to) - to.radius;
			else
				var distance = from.position.distanceTo(to);
			var baseTime =  0.0002 * distance + 900; //20 secs per 100 km + 15 mins for launch and incidents.			
			var time = clock.seconds + baseTime;
			var fee = this.$fare(distance);
			var name = global.randomName() +" "+ global.randomName();
			this.$stationOffers.push([1, from, to, time, fee, name, system.ID, baseTime]);
			if (this.$stationOffers.length == 8) break; //cap possible offers to 8
		}
	}
}

//create station offers when docking
this.shipDockedWithStation = function(station) {
	this.$stationOffers = [];
	this.$createStationOffers();
	this.$stationOffersInterface();
	this.$refTime = clock.seconds;
}

//handle f4-screen
this.$stationOffersInterface = function() {
	//show interface if no contract accepted, no room or no offers
	if (this.$readyToOffer && this.$stationOffers.length > 0 && this.$currentOffer[0] < 2 && player.ship.passengerCapacity - player.ship.passengerCount  > 0) {
		player.ship.dockedStation.setInterface("in-system_taxi",{
			title: "In-system taxi deliveries (" +this.$stationOffers.length+" available)",
			category: "Deliveries",
			summary: "Taxi Galactica's in-system taxi contracts. Pick a passenger from this station and make a fast transport to another station in-system.",
			callback: this.$showStationOffers.bind(this)
		});
	}
	else {
		player.ship.dockedStation.setInterface("in-system_taxi",null);//remove interface if contract accepted, no room or no offers
	}
}

//clean old offers and add new offers time to time
this.guiScreenChanged = function(to, from) {
	if (player.ship.docked && !system.isInterstellarSpace && clock.seconds - this.$refTime > 600) {//refresh every 10 mins of game time
		this.$createStationOffers();	
		this.$clearOldOffers();
		this.$refTime = clock.seconds;
	}
}

this.$clearOldOffers = function() {
		var i;
		var validOffers = [];
		for (i = 0; i < this.$stationOffers.length; i++) {
			//leave only ones that have at least 5 mins of fly time left, 10 goes to launching
			if ((Math.floor((this.$stationOffers[i][3] - clock.seconds))) > 900) {
				validOffers.push(this.$stationOffers[i]);
			}
		}
		this.$stationOffers = validOffers;
		this.$stationOffersInterface();	
}

//mission screen for showing offers
this.$showStationOffers = function() {
	var options = {};
	var emptyMessage = "";
	this.$clearOldOffers();
	if (this.$stationOffers.length == 0) {
		emptyMessage = "\n\nToo late. You just missed the last passenger. Come back later."
	}
	else {
		var i;
		for (i = 0; i < this.$stationOffers.length; i++) {
			options[i+"_TAXI"] = this.$stationOffers[i][5] +" to "+ this.$stationOffers[i][2].displayName +" in " + Math.floor((this.$stationOffers[i][3] - clock.seconds)/60) +" minutes. Fare: "+ formatCredits(this.$stationOffers[i][4], true, true);
		}
	}
	options["99_NO_THANKS"] = "Exit in-system contracts";
	mission.runScreen({
		title: "Taxi Galactica's In-System Contracts",
		message: "Welcome to Taxi Galactica's in-system taxi services of "+system.name+". We have busy customers waiting for a fast in-system transportation. For a fast delivery, you will get a tip. The faster you go, the bigger tip you'll get."+emptyMessage,
		choices: options,
		exitScreen: "GUI_SCREEN_INTERFACES",
		background: "tg_is_background.png"
	},
	function (choice) {
		if (!choice || choice == "99_NO_THANKS") return;
		else {
			this.$removeOfferTimer();//in case there is an offerTimer running from in-flight offers.
			this.$currentOffer = this.$stationOffers[choice.charAt(0)];
			this.$currentOffer[0] = 2;
			player.ship.dockedStation.setInterface("in-system_taxi",null);//remove station interface after accepting contract.
		}
	});		
}

//STATION OFFERING FUNCTIONS END HERE

//CONTRACT HANDLING

//add temporary beacons
this.$addBeacon =  function() {
	//add temporary from beacon
	if (this.$currentOffer[0] == 2 && !this.$currentOffer[1].beaconCode) {
		this.$currentOffer[1].beaconCode = "Taxi beacon";
		this.$addedBeacon[0] = true;
	}	
	//add temporary to beacon
	if (this.$currentOffer[0] == 3 && !this.$currentOffer[2].beaconCode) {
		this.$currentOffer[2].beaconCode = "Taxi beacon";
		this.$addedBeacon[1] = true;
	}
}

//remove temporary beacons
this.$removeBeacon = function() {
	//remove temporary from beacon
	if (this.$addedBeacon[0]) {
		this.$currentOffer[1].beaconCode = null;
		this.$addedBeacon[0] = false;
	}
	//remove temporary to beacon
	if (this.$addedBeacon[1]) {
		this.$currentOffer[2].beaconCode = null;
		this.$addedBeacon[1] = false;
	}		
}

this.shipWillLaunchFromStation = function(station) {
	this.$readyToOffer = true;//after frist launch, allow offering
	this.$addBeacon();//add temporary beacons
}

//handle passenger when docking
this.shipWillDockWithStation = function(station) {
	this.$removeBeacon();//remove temporary beacons
	this.$stopInFlightTimer();//stop in-flight offering
	//is there a passenger on board?
	if (this.$currentOffer[0] == 3) {
		//over 15 minutes (15*60 = 900 secs) late, cancel contract if possible.
		if (this.$currentOffer[3] - clock.seconds < -900) {
			if (player.ship.removePassenger(this.$currentOffer[5]+" (going to "+this.$currentOffer[2].displayName+")")) {
				//switch taxi passenger to a game passenger and let the game handle rest
				if (station != this.$currentOffer[2]) {
					player.ship.addPassenger(this.$currentOffer[5], system.ID, system.ID, clock.seconds+10, this.$currentOffer[4]);
					this.$fireMissionScreen = 6;
					this.$currentOffer[0] = 0;
				}
				//if we're already at home, no switching is required, just fire mission screen
				else {
					this.$fireMissionScreen = 5;
					this.$currentOffer[0] = 0;
				}
			}
			return;
		}
		//destination check
		var rightDestination = false;
		if (this.$currentOffer[2].isPlanet) {
			if (worldScripts.PlanetFall.lastPlanet == this.$currentOffer[2] && (station.hasRole("planetFall_surface")))
				rightDestination = true;
		}
		else if (station == this.$currentOffer[2])
			rightDestination = true;
		//right destination, 0 - 15 mins late, remove passenger, pay fare
		if (this.$currentOffer[3] - clock.seconds < 0 && rightDestination) {
			player.ship.removePassenger(this.$currentOffer[5]+" (going to "+this.$currentOffer[2].displayName+")");
			player.credits = player.credits + this.$currentOffer[4];
			this.$fireMissionScreen = 4;
			this.$currentOffer[0] = 0;
			return;
		}
		//right destination in time, remove passenger, pay fare and possibly premium
		if (rightDestination) {
			player.ship.removePassenger(this.$currentOffer[5]+" (going to "+this.$currentOffer[2].displayName+")");
			this.$premium = 30 * ((this.$currentOffer[3] - clock.seconds) / this.$currentOffer[7]);//tip 30*proportion
			player.credits = player.credits + this.$currentOffer[4] + this.$premium;
			this.$fireMissionScreen = 2;
			this.$currentOffer[0] = 0;
			return;
		}
		//docking main station
		if (station.isMainStation) {
			//if late, can't swap passengers at main station. Passenger just leaves.
			if (this.$currentOffer[3] - clock.seconds < 0) {
				player.ship.removePassenger(this.$currentOffer[5]+" (going to "+this.$currentOffer[2].displayName+")");
				this.$fireMissionScreen = 5;
				this.$currentOffer[0] = 0;
			}
			//if time remaining, replace real passenger with bogus passenger
			else if (player.ship.removePassenger(this.$currentOffer[5]+" (going to "+this.$currentOffer[2].displayName+")"))
				player.ship.addPassenger("Taxi temp stand in", ((system.ID+2) % 256 - 1), ((system.ID+2) % 256 - 1), clock.seconds+3600, 0);
		}
	}
}


//handle unhiding the passenger and passenger picking. show mission screens, when there's something to show.
this.missionScreenOpportunity= function() {
	//check berth status when passenger on board and docked at main station.
	if (player.ship.docked && player.ship.dockedStation.isMainStation && this.$currentOffer[0] == 3) {
		//unhide passenger, if hidden.
		if (player.ship.removePassenger("Taxi temp stand in")) {//remove bogus
			if (!player.ship.addPassenger(this.$currentOffer[5]+" (going to "+this.$currentOffer[2].displayName+")", system.ID, system.ID, this.$currentOffer[3], 0)) {	//put passenger back
				this.$fireMissionScreen = 5;//very rare case, where passenger has vanished while docking.
			}
		}
		else {//has passenger contract has been removed by game?
			var passengers = player.ship.passengers;
			var i;
			var passengerInBerth = false;
			for (i = 0; i < passengers.length; i++) {
				if (passengers[i].name == this.$currentOffer[5]+" (going to "+this.$currentOffer[2].displayName+")") {
					passengerInBerth = true;
					break;
				}
			}
			if (!passengerInBerth)//passenger has vanished, fire mission screen
				this.$fireMissionScreen = 5;
		}
	}
	//If we are at the right starting point, let's pick the passenger on board.
	else if (player.ship.docked && this.$currentOffer[0] == 2) {
		var rightStartingPoint = false;
		if (this.$currentOffer[1].isPlanet) {//is it a planetary starting point?
			if (worldScripts.PlanetFall.lastPlanet == this.$currentOffer[1] && (player.ship.dockedStation.hasRole("planetFall_surface")))
				rightStartingPoint = true;
		}
		else if (player.ship.dockedStation == this.$currentOffer[1])
			rightStartingPoint = true;
		if (rightStartingPoint) {//right starting point
			this.$deleteMissionInstructions();
			//is there room for the passenger?
			if (player.ship.passengerCapacity - player.ship.passengerCount == 0) {
				this.$fireMissionScreen = 3;
			}
			//all is probably well, let's add new contract
			else {
				player.ship.addPassenger(this.$currentOffer[5]+" (going to "+this.$currentOffer[2].displayName+")", system.ID, system.ID, this.$currentOffer[3], 0);
				this.$currentOffer[0] = 3;
				this.$currentOffer[7] = this.$currentOffer[3] - clock.seconds;//premium is based on basetime. basetime is defined when pickin up passenger.
				this.$fireMissionScreen = 1;
			}
		}
	}
	switch(this.$fireMissionScreen) {
		case 1:
			mission.runScreen({
				title: "Passenger boarding",
				message: "Taxi passenger "+this.$currentOffer[5]+" has boarded and is expecting to arrive "+ this.$currentOffer[2].displayName + " in " + Math.floor((this.$currentOffer[3] - clock.seconds)/60) +" minutes. Will pay you a fare of "+formatCredits(this.$currentOffer[4], true, true)+" for reaching the destination in time and a tip, if you're fast enough.",
				background: "tg_is_background.png"
			});
			this.$fireMissionScreen = 0;
			break;
		case 2:
			var tipTalk = "";
			if (this.$premium > 0.05)
				tipTalk = " For fast delivery, you receive a tip of "+formatCredits(this.$premium, true, true) +".";
			mission.runScreen({
				title: "Satisfied customer",
				message: "Taxi passenger "+this.$currentOffer[5]+" has arrived the destination in time. Fare of "+formatCredits(this.$currentOffer[4], true, true)+ " has been paid to your account." + tipTalk,
				background: "tg_is_background.png"
			});
			this.$currentOffer = [0];
			this.$fireMissionScreen = 0;
			break;
		case 3:
			mission.runScreen({
				title: "No room for passenger",
				message: "Taxi passenger "+this.$currentOffer[5]+" is very disappointed after finding that there is no room in your ship. The contract is cancelled.",
				background: "tg_is_background.png"
			});
			this.$currentOffer = [0];
			this.$fireMissionScreen = 0;
			break;
		case 4:
			mission.runScreen({
				title: "Missed deadline",
				message: "Taxi passenger "+this.$currentOffer[5]+" is not happy at all as you missed the deadline. You get your fare of "+formatCredits(this.$currentOffer[4], true, true)+ ", but no tip.",
				background: "tg_is_background.png"
			});
			this.$currentOffer = [0];
			this.$fireMissionScreen = 0;
			break;
		case 5:
			mission.runScreen({
				title: "Unhappy customer",
				message: "Taxi passenger "+this.$currentOffer[5]+" was not pleased with your service and promises never to set foot on your ship again.",
				background: "tg_is_background.png"
			});
			this.$currentOffer = [0];
			this.$fireMissionScreen = 0;
			break;
		case 6:
			mission.runScreen({
				title: "Demanding customer",
				message: "Taxi passenger "+this.$currentOffer[5]+" is very disappointed having missed the deadline and demands to be taken to the main station of "+System.infoForSystem(system.info.galaxyID, this.$currentOffer[6]).name+".",
				background: "tg_is_background.png"
			});
			this.$fireMissionScreen = 0;
			break;			
	}
}

//Timer functions
this.$startInFlightTimer = function() {
	if (this.$showOfferTimer == null)
		this.$showOfferTimer = new Timer(this, this.$taxiOffer, 60, this.$offerFrequency);
	else this.$showOfferTimer.start();
};

this.$stopInFlightTimer = function() {
	if (this.$showOfferTimer != null)
		this.$showOfferTimer.stop();
};

this.$removeInFlightTimer = function() {
	if (this.$showOfferTimer != null) {
		this.$showOfferTimer.stop();
		delete this.$showOfferTimer;
	}
};

this.$removeOfferTimer = function() {
	if (this.$offerTimer != null) {
		this.$offerTimer.stop();
		delete this.$offerTimer;
	}
};

this.$removeContractTimer = function() {
	if (this.$contractTimer != null) {
		this.$contractTimer.stop();
		delete this.$contractTimer;
	}
};

this.playerBoughtEquipment = function(equipment) {
	if (equipment === "EQ_IN_SYSTEM_TAXI_LICENCE_REMOVAL") {
		player.ship.removeEquipment("EQ_IN_SYSTEM_TAXI_LICENCE");
		player.ship.removeEquipment("EQ_IN_SYSTEM_TAXI_LICENCE_REMOVAL");
	}
}