"use strict";
this.name = "GalCopBB_Investigations";
this.author = "phkb";
this.copyright = "2017 phkb";
this.description = "Looks after all investigation missions (130-139)";
this.license = "CC BY-NC-SA 4.0";

this._setupTimer = null;
this._monitorTimer = null;
this._bomb = null;
this._bombTimer = null;
this._bombCounter = 0;
this._pod = null;
this._thargoidTimer = null;
this._addedBeacon = false;
this._addedEntities = false;
this._missionID = 0;
this._debug = false;

/*
	investigate distant signal, which can be one of the following
	*130 - a stash of cargo pods with precious metals/gems
	*131 - a ship graveyard
	*132 - a damaged escape pod
	*133 - a pirate base
	*134 - a thargoid trap
	*135 - a proximity mine that causes a fuel leak
	*136 - a spooky noise/comms
	*137 - a pirate trap
	*138 - an asteroid field with blackbox
	139 - (currently unusued)
	*140 - destroy pirate base
	*141 - deliver goodbye messages

	todo:
		cargo pod with documents which, when scooped, will inform the player that they will need to dock to unpack the contents
			on docking, player will get a parcel mission in most circumstances
			however, other missions (eg beacon, collect cargo) could be launched through the same mechanism
		beacon waiting for a password to unlock content
			

*/

//-------------------------------------------------------------------------------------------------------------
this.startUp = function () {
	var gcm = worldScripts.GalCopBB_Missions;
	// add these mission types into the main control
	var list = [130, 131, 132, 133, 134, 135, 136, 137, 138, 140];
	gcm._availableMissionTypes = gcm._availableMissionTypes.concat(list);
	// note: 141 is not spawned via the main mission system - only after a 132 mission
	this._debug = gcm._debug;
}

//-------------------------------------------------------------------------------------------------------------
this.systemWillPopulate = function () {
	this.$checkForActiveMissions();
}

//-------------------------------------------------------------------------------------------------------------
this.shipWillLaunchFromStation = function (station) { }

//-------------------------------------------------------------------------------------------------------------
this.$gcm_shipDied = function $gcm_shipDied(whom, why) {
	this.$stopTimer();
}

//-------------------------------------------------------------------------------------------------------------
this.shipWillDockWithStation = function (station) {
	var gcm = worldScripts.GalCopBB_Missions;
	var list = gcm.$getListOfMissions(true, 141);
	if (list.length > 0) {
		var bb = worldScripts.BulletinBoardSystem;
		for (var i = 0; i < list.length; i++) {
			var item = list[i];
			if (item.destination === system.ID && station.isMainStation && item.data.quantity === 0) {
				item.data.quantity = 1;
				bb.$updateBBMissionPercentage(item.ID, 1);

				gcm.$logMissionData(item.ID);
				//player.consoleMessage(expandDescription("[goal_updated]"));
			}
		}
	}

	// stop the fuel leaking after we dock
	if (player.ship.fuelLeakRate != 0) player.ship.fuelLeakRate = 0;
}

//-------------------------------------------------------------------------------------------------------------
this.$gcm_shipWillEnterWitchspace = function $gcm_shipWillEnterWitchspace() {
	this.$stopTimer();
}

//-------------------------------------------------------------------------------------------------------------
this.$stopTimer = function $stopTimer() {
	delete this.shipDied;
	delete this.shipWillEnterWitchspace;
	if (this._monitorTimer && this._monitorTimer.isRunning) this._monitorTimer.stop();
	this._monitorTimer = null;
}

//-------------------------------------------------------------------------------------------------------------
this.$checkForActiveMissions = function $checkForActiveMissions() {
	var gcm = worldScripts.GalCopBB_Missions;
	var list = gcm.$getListOfMissions(true, [130, 131, 132, 133, 134, 135, 136, 137, 138, 139]);
	if (list.length > 0) {
		// loop through all active missions and see if any need to be set up for this system
		for (var i = 0; i < list.length; i++) {
			if (list[i].destination === system.ID &&
				list[i].data.quantity === 0 &&
				list[i].data.destroyedQuantity === 0 &&
				(list[i].expiry === -1 || list[i].expiry > clock.adjustedSeconds)) {

				var posData = this.$getRandomPosition(list[i].data.locationType, 0.5, list[i].ID);
				this._monitorPos = posData.position;
				// start the monitoring timer to check the players position
				this._monitorTimer = new Timer(this, this.$checkPlayerPosition, 5, 5);
				this._monitorDist = posData.checkDist / 2;
				this.shipWillEnterWitchSpace = this.$gcm_shipWillEnterWitchspace;
				this.shipDied = this.$gcm_shipDied;
				this._missionID = list[i].ID;

				switch (list[i].data.missionType) {
					case 130: // cargo pods with gold/platinum/gemstones
						var pd = gcm._preferredCargoPods[Math.floor(Math.random() * gcm._preferredCargoPods.length)];
						var pods = system.addShips("[" + pd + "]", Math.floor(Math.random() * 10 + 2), posData.position, 1000);
						// if we couldn't create them with our preferred pod type, use the default
						if (!pods) {
							pods = system.addShips("[barrel]", Math.floor(Math.random() * 10 + 2), posData.position, 1000);
						}
						if (pods) {
							var opts = ["computers", "luxuries", "furs", "alien_items", "liquor_wines", "firearms", "narcotics", "gold", "platinum", "gem_stones"];
							var amts = [1, 1, 1, 1, 1, 1, 1, 30, 30, 60];
							for (var j = 0; j < pods.length; j++) {
								var choice = Math.floor(Math.random() * opts.length);
								var amt = amts[choice];
								if (amt === 1) {
									pods[j].setCargo(opts[choice], amt);
								} else {
									pods[j].setCargo(opts[choice], Math.floor(Math.random() * amt + amt));
								}
							}
						} else {
							log("galcopBB_investigations", "!!ERROR: cargo pods not spawned");
						}
						break;
					case 131: // ship graveyard
						system.addShips("[alloy]", Math.floor(Math.random() * 20 + 10), posData.position, player.ship.scannerRange);
						var graveTypes = ["adder", "anaconda", "asp", "boa", "boa-mk2", "cobra3-trader", "cobramk1", "ferdelance", "gecko", "krait", "mamba", "moray", "morayMED", "python", "sidewinder"];
						var num = Math.floor(Math.random() * 20 + 5);
						for (var j = 0; j < num; j++) {
							var typ = graveTypes[Math.floor(Math.random() * graveTypes.length)];
							var checkShips = system.addShips("[" + typ + "]", 1, posData.position, player.ship.scannerRange * 1.5);
							if (checkShips) var s = checkShips[0];
							if (s) {
								s.bounty = 0;
								// set script to default, to avoid a special script for the trader doing stuff. (like setting a new AI)
								s.setScript("oolite-default-ship-script.js");
								s.switchAI("oolite-nullAI.js");

								// remove any escorts that came with the ship
								if (s.escorts) {
									for (var k = s.escorts.length - 1; k >= 0; k--) s.escorts[k].remove(true);
								}

								s.script.shipLaunchedEscapePod = this.$gcm_derelict_shipLaunchedEscapePod; // function to remove the escapepod after launch.
								if (s.equipmentStatus("EQ_ESCAPE_POD") === "EQUIPMENT_UNAVAILABLE") s.awardEquipment("EQ_ESCAPE_POD");
								s.abandonShip(); // make sure no pilot is left behind and this command turns the ship into cargo.
								s.primaryRole = "gcm_derelict"; // to avoid pirate attacks
								s.displayName = s.displayName + expandDescription("[gcm_ship_derelict]");
								s.maxEnergy = 32;
								s.lightsActive = false;
							}
						}
						break;
					case 132: // escape pod
						// no passenger (dead) but includes delayed comm message ("If you're receiving this...")
						// todo: comms message requests delivery of info to main station on system X (pilot's home system)
						// essentially like a parcel, but with no expiry (because the guy is already dead), and no payment amount
						// todo: will need customised completion message, rather than the standard. pay player as separate routine at end as reward
						var checkShips = null;
						for (var j = 0; j < 5; j++) {
							checkShips = system.addShips("gcm_stricken_pod_dead", 1, posData.position, 0);
							if (checkShips) this._pod = checkShips[0];
							if (this._pod) break;
						}
						// set up a broadcast message when the player is within 15k
						break;
					case 133: // pirate base
						var pb = worldScripts.GalCopBB_PirateBases;
						if (pb.$systemHasPirateBase() === null) {
							pb.$addPirateBaseDirect(system.ID, posData.x, posData.y, posData.z, posData.coordSystem, posData.locationType);
							// make sure our beacon position matches the actual location of the base
							this._monitorPos = pb.$forceSpawn();
						}
						var b = pb.$getSystemPirateBase();
						break;
					case 134: // thargoid trap
						// spawn thargoids at position, but only when player gets there
						break;
					case 135: // proximity mine + fuel leak
						this._bomb = system.addShips("gcm_remote_mine", 1, posData.position, 0)[0];
						break;
					case 136: // spooky noise
						break;
					case 137: // pirate trap
						// todo: spawn pirates at position and give them lurk position
						var gns = worldScripts.GalCopBB_GoonSquads;
						gns.$createGoonSquad(Math.floor(Math.random() * 5 + 2), posData.position, player.ship.scannerRange * 0.5);
						break;
					case 138: // asteroid field with black box
						// todo: spawn asteroids and blackbox
						// scooping blackbox might create new mission
						system.addShips("asteroid", 60, posData.position, 40E3);
						// maybe spawn a blackbox
						if (Math.random() > 0.6 && worldScripts["Rescue Stations"]) {
							system.addShips("rescue_blackbox_generic", 1, posData.position, 5000);
						}
						break;
					case 139: // unused
						break;
				}
				if (this._debug) gcm.$setWaypoint(posData.position, [0, 0, 0, 0], "D", "Debug position (" + list[i].data.missionType + ")", list[i].data.missionType);
			}
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$gcm_derelict_shipLaunchedEscapePod = function $gcm_derelict_shipLaunchedEscapePod(pod, passengers) {
	pod.remove(true); // we don't want floating escapepods around but need them initially to create the derelict.
}

//-------------------------------------------------------------------------------------------------------------
this.$checkPlayerPosition = function $checkPlayerPosition() {
	if (player.ship.isValid == false || !player.ship.position) {
		this.$stopTimer();
		return;
	}
	if (this._monitorDist >= 0) {
		var checkDist = player.ship.position.distanceTo(this._monitorPos);
		if (checkDist < player.ship.scannerRange * 0.9) {
			// mark mission as complete and turn off beacon
			this.$stopTimer();
			var gcm = worldScripts.GalCopBB_Missions;
			var bb = worldScripts.BulletinBoardSystem;
			var item = bb.$getItem(this._missionID);
			if (item) {
				if (item.data.destroyedQuantity === 0 && item.data.quantity === 0) {
					item.data.quantity = 1;
					bb.$updateBBMissionPercentage(item.ID, 1);

					gcm.$logMissionData(item.ID);
					player.consoleMessage(expandDescription("[goal_updated]"));

					if (item.data.missionType === 132) {
						// add an accepted mission and tell the player
						this.$createSecondaryPodMission(this._missionID);
					}
					if (item.data.missionType === 133) {
						// create a destroy the base mission (140)
						// we're going to do this manually here, rather than using the linked mission system
						// the reason being that the pirate base is hard, and the player might not want to do it.
						// it might be a bit much to force a hard mission on them like that
						// however, once a pirate base is established, it will be present until destroyed, and 
						// the mission will be recreated every time the system is populated, so the player can
						// always come back and try it later.
						gcm.$addLocalMissions([140], "", system.ID, "")
					}
					if (item.data.missionType === 134) {
						this._thargoidTimer = new Timer(this, this.$createThargoids, 2, 0);
					}
					if (item.data.missionType === 135) {
						// start the proximity mine countdown
						this._bombTimer = new Timer(this, this.$proximityMine, 1, 1);
					}
					if (item.data.missionType === 136) {
						var s_type = Math.floor(Math.random() * 10) + 1;
						var mySound = new SoundSource;
						mySound.sound = "gcm_spooky" + s_type + ".ogg";
						mySound.loop = false;
						mySound.play();
						// comms message delay
						var delay = parseInt(expandDescription("[gcm_spooky_length_" + s_type + "]")) - 3;
						this._commsTimer = new Timer(this, this.$sendSpookyComms, delay, 0);
					}
				}
			}
		}
		// if we're inside the max distance, add the beacon
		if (checkDist < this._monitorDist && checkDist > player.ship.scannerRange * 0.9) {
			if (this._debug) log(this.name, "adding beacon to system");
			//if (checkDist > player.ship.scannerRange * 0.9) { // debug version - on from start
			if (this._addedBeacon === false) {
				if (player.ship.isInSpace === true) {
					player.consoleMessage(expandDescription("[gcm_unrecognised_beacon]"), 3);
				}
				system.addVisualEffect("gcm_unidentified_signal2", this._monitorPos);
				this._addedBeacon = true;
			}
		} else {
			// otherwise, remove it, if present
			if (this._addedBeacon === true) {
				if (this._debug) log(this.name, "removing beacon from system");
				var targets = system.allVisualEffects;
				if (targets.length > 0) {
					for (var i = targets.length - 1; i >= 0; i--) {
						if (targets[i].dataKey === "gcm_unidentified_signal2") {
							targets[i].remove();
						}
					}
				}
				this._addedBeacon = false;
			}
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$proximityMine = function $proximityMine() {
	if (!this._bomb || this._bomb.isValid === false) {
		this._bombTimer.stop();
		return;
	}
	if (this._bombCounter <= 5) {
		if (this._bomb.position.distanceTo(player.ship) < player.ship.scannerRange) {
			this._bomb.commsMessage((5 - this._bombCounter), player.ship);
		}
		this._bombCounter += 1;
		if (this._bombCounter === 6) {
			this._bomb.dealEnergyDamage(500, player.ship.scannerRange * 0.94);
			if (this._bomb.position.distanceTo(player.ship) < player.ship.scannerRange) {
				player.ship.fuelLeakRate = 0.5;
				worldScripts.GalCopBB_Missions.$playSound("leak");
			}
			this._bomb.explode();
			this._bombTimer.stop();
			this._bomb = null;
			this._bombTimer = null;
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$sendSpookyComms = function $sendSpookyComms() {
	var p = player.ship;
	var checkShips = system.addShips("spookycomms", 1, p.position.add(p.vectorForward.multiply(5000)), 0);
	var cr = null;
	if (checkShips) cr = checkShips[0];
	if (cr) {
		cr.commsMessage(expandDescription("[gcm_spooky]"), p);
		cr.remove();
	}

	// 70% chance of a jump scare
	if (Math.random() > 0.7) return;

	var mySound = new SoundSource;
	mySound.sound = "gcm_spooky_punch.ogg";
	mySound.loop = false;
	mySound.play();

	p.script._thargoidVETime = 0;

	var key = "gcm_std_effect_thargoid";
	if (Ship.shipDataForKey("griff_thargoid-NPC") != null) key = "gcm_griff_effect_thargoid";
	p.script._thargoidVE = system.addVisualEffect(key, p.position.add(p.vectorForward.multiply(500)));
	p.script._thargoidVE.orientation = p.orientation;
	p.script._thargoidVE.orientation = p.script._thargoidVE.orientation.rotateZ(Math.PI * 1.2);
	p.script._thargoidVE.orientation = p.script._thargoidVE.orientation.rotateX(-0.5);

	// set up the frame callback
	this._fcbID = addFrameCallback(function (delta) {
		var p = player.ship;
		var ps = p.script;
		if (ps._thargoidVETime > 1) {
			ps._thargoidVE.remove();
			removeFrameCallback(worldScripts.GalCopBB_Investigations._fcbID);
			return;
		}
		ps._thargoidVETime += delta;
		ps._thargoidVE.position = p.position.add(p.vectorForward.multiply(500));
		ps._thargoidVE.orientation = p.orientation;
		ps._thargoidVE.orientation = ps._thargoidVE.orientation.rotateZ(Math.PI * 1.2);
		ps._thargoidVE.orientation = ps._thargoidVE.orientation.rotateX(-0.5);
	});
}

//-------------------------------------------------------------------------------------------------------------
this.$createThargoids = function $createThargoids() {
	system.addShips("thargoid", Math.floor(Math.random() * 4) + 1, player.ship.position, 20000);
}

//-------------------------------------------------------------------------------------------------------------
this.$createSecondaryPodMission = function $createSecondaryPodMission(missID) {
	// pick a destination
	if (this._pod.isValid === false || this._pod.isInSpace === false) return;
	var dest = null;
	var tries = 0;
	do {
		//var sysList = system.info.systemsInRange(5);
		//dest = sysList[Math.floor(Math.random() * sysList.length)];

		dest = System.infoForSystem(galaxyNumber, Math.floor(Math.random() * 256))
		if (!dest.routeToSystem(system.info)) {
			dest = null;
		}
		tries += 1;
	} while (dest === null && tries < 10);
	if (dest === null) return; // no secondary mission - no dest system found

	// create a client name
	var cust = [];
	var clientName = worldScripts.GalCopBB_Reputation.$getClientName(system.ID, "");
	cust.push({
		heading: expandDescription("[gcm_heading_client]"),
		value: clientName
	});

	var familyType = expandDescription("[gcm_141_target]");
	var gcm = worldScripts.GalCopBB_Missions;
	var bb = worldScripts.BulletinBoardSystem;
	var id = bb.$addBBMission({
		source: system.ID,
		destination: dest.systemID,
		stationKey: expandDescription("[missionType141_stationKeys]"),
		description: expandDescription("[missionType141_description]"),
		details: expandDescription("[missionType141_details]", {
			destination: dest.name
		}).replace(/family/g, familyType),
		overlay: gcm.$getTexture(expandDescription("[missionType141_bbOverlay]")),
		payment: 0,
		deposit: 0,
		allowTerminate: false,
		completionType: expandDescription("[missionType141_completionType]"),
		stopTimeAtComplete: true,
		allowPartialComplete: expandDescription("[missionType141_partialComplete]"),
		accepted: true,
		expiry: -1,
		percentComplete: 0,
		disablePercentDisplay: expandDescription("[missionType141_disablePercent]"),
		noEmails: true,
		customDisplayItems: cust,
		markerShape: "MARKER_X", // marker control will be handled by contracts system
		completedCallback: "$completedMission",
		confirmCompleteCallback: "$confirmCompleted",
		manifestCallback: "$updateManifestEntry",
		worldScript: this.name,
		postStatusMessages: [{
			status: "completed",
			text: expandDescription("[missionType141_completedMessage]", {
				name: clientName
			}).replace(/family/g, familyType),
			return: "list"
		}],
		data: {
			source: "GalCopBB_Missions",
			missionType: 141,
			quantity: 0,
			targetQuantity: 1,
			destroyedQuantity: 0,
			remaining: 0,
			commodity: "",
			unit: "",
			destination: dest.name,
			system: system.name,
			expiry: "",
			stage: "0"
		}
	});

	var txt = expandDescription("[missionType141_miniBriefing_escapepod]", {
		name: clientName,
		destination: dest.name
	}).replace(/family/g, familyType);

	// communicate with player about the new mission
	worldScripts.GalCopBB_Missions._pendingMissionID = id;
	worldScripts.GalCopBB_Missions._pendingMissionOrigID = missID;
	this._holdID = id;
	worldScripts.GalCopBB_Missions._pendingMissionCallback = this.$secondaryPodMissionCallback.bind(this);
	worldScripts.GalCopBB_Missions_MFD.$updateMFD(txt, true, this._pod, true);

	this._pod = null;
}

//-------------------------------------------------------------------------------------------------------------
this.$secondaryPodMissionCallback = function $secondaryPodMissionCallback() {
	var bb = worldScripts.BulletinBoardSystem;
	var rep = worldScripts.GalCopBB_Reputation;
	var missID = worldScripts.GalCopBB_Investigations._holdID;
	var item = bb.$getItem(missID);

	// update the manifest
	bb.$updateBBManifestText(
		missID,
		rep.$transformText(expandDescription("[missionType" + item.data.missionType + "_manifest]", {
			destination: System.systemNameForID(item.destination),
			expiry: ""
		}), item.source, item.destination)
	);
	bb.$updateBBStatusText(
		missID,
		rep.$transformText(expandDescription("[missionType" + item.data.missionType + "_status]", {
			destination: System.systemNameForID(item.destination)
		}), item.source, item.destination)
	);
	worldScripts.GalCopBB_Missions._pendingMissionCallback = null;
}

//-------------------------------------------------------------------------------------------------------------
this.$acceptedMission = function $acceptedMission(missID) {
	var bb = worldScripts.BulletinBoardSystem;
	var item = bb.$getItem(missID);
	var gcm = worldScripts.GalCopBB_Missions;

	if (this._debug) log(this.name, "accepted mission id = " + missID);

	if (!item) {
		log(this.name, "!!ERROR: BB returned null value from $getItem on mission ID " + missID);
		return;
	}
	gcm.$updateLastMissionDate(item.source, item.data.missionType);
	gcm.$updateGeneralSettings(item);

	// do some population-type things
	this.$checkForActiveMissions();
}

//-------------------------------------------------------------------------------------------------------------
this.$completedMission = function $completedMission(missID) {
	var p = player.ship;
	var bb = worldScripts.BulletinBoardSystem;
	var item = bb.$getItem(missID);
	var gcm = worldScripts.GalCopBB_Missions;

	// update mission history
	gcm.$updateSuccessHistoryReputation(item);

	if (item.data.missionType === 141) {
		var creds = Math.floor(Math.random() * 300 + 300);
		player.credits += creds;
		player.consoleMessage(expandDescription("[gcm_awarded]", { amount: formatCredits(creds, false, true) }));
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$confirmCompleted = function $confirmCompleted(missID) {
	var p = player.ship;
	var result = "";
	var bb = worldScripts.BulletinBoardSystem;
	var item = bb.$getItem(missID);
	if (item) {
		if (item.data.missionType === 141) {
			if (item.destination != system.ID) result = expandDescription("[gcm_travel_dest]");
		}
	}
	return result;
}

//-------------------------------------------------------------------------------------------------------------
this.$terminateMission = function $terminateMission(missID) {
	var bb = worldScripts.BulletinBoardSystem;
	var item = bb.$getItem(missID);
	//var sbm = worldScripts.Smugglers_BlackMarket;
	var gcm = worldScripts.GalCopBB_Missions;

	// adjust reputation only when the terminatePenalty flag is set to true 
	if (item.data.terminatePenalty === true) {
		// update mission history
		gcm.$updateFailedHistoryReputation(item);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$failedMission = function $failedMission(missID) {
	var bb = worldScripts.BulletinBoardSystem;
	var sbm = worldScripts.Smugglers_BlackMarket;
	var gcm = worldScripts.GalCopBB_Missions;
	var eq = "";

	if (!sbm) {
		// if there's no blackmarket option, just remove the equipment
		this.$terminateMission(missID);
		return;
	}

	var item = bb.$getItem(missID);
	// update mission history
	gcm.$updateFailedHistoryReputation(item);

	if (eq != "") gcm._equipmentFromFailedMissions.push({
		missionType: item.data.missionType,
		source: item.source,
		equip: eq,
		date: clock.adjustedSeconds
	});
}

//-------------------------------------------------------------------------------------------------------------
this.$updateManifestEntry = function $updateManifestEntry(missID) {
	var gcm = worldScripts.GalCopBB_Missions;
	gcm.$updateManifestEntry(missID);
}

//-------------------------------------------------------------------------------------------------------------
this.$missionAvailability = function $missionAvailability(missID, missType, origSysID) {
	return worldScripts.GalCopBB_Missions.$missionAvailability(missID, missType, origSysID);
}

//-------------------------------------------------------------------------------------------------------------
// 130
this.$missionType130_Values = function $missionType130_Values(workTime, routeTime, routeDistance, destSysInfo) {
	var mv = worldScripts.GalCopBB_CoreMissionValues;
	var locTypes = [0, 3, 4, 5, 6, 7];
	var result = {};
	result["locationType"] = locTypes[Math.floor(Math.random() * locTypes.length)];
	result["quantity"] = 1;
	result["price"] = parseInt((parseInt(Math.random() * 40) + 20) / 10) * 10 + (7 - destSysInfo.government) * 50 +
		mv.$calcPlayerBonus(200); // plus a possible bonus price, based on player score 
	result["expiry"] = -1; // no expiry
	result["penalty"] = 0;
	return result;
}

//-------------------------------------------------------------------------------------------------------------
// 140
this.$missionType140_Values = function $missionType140_Values(workTime, routeTime, routeDistance, destSysInfo) {
	var mv = worldScripts.GalCopBB_CoreMissionValues;
	var result = {};
	result["quantity"] = 1;
	result["price"] = parseInt((parseInt(Math.random() * 1000) + 2000) / 10) * 10 + (7 - destSysInfo.government) * 50 +
		mv.$calcPlayerBonus(2000); // plus a possible bonus price, based on player score 
	result["expiry"] = -1; // no expiry
	result["penalty"] = 0;
	return result;
}

//-------------------------------------------------------------------------------------------------------------
// gets a random position based on a locationType value. locationType can be 0, 3, 4, 5, or 6.
this.$getRandomPosition = function $getRandomPosition(locationType, factor, missID) {
	var gcm = worldScripts.GalCopBB_Missions;

	switch (locationType) {
		case 0:
			return gcm.$getRandomPosition(locationType, factor, missID, 2, 3);
		case 3:
			return gcm.$getRandomPosition(locationType, factor, missID, -2, -3);
		case 4:
			return gcm.$getRandomPosition(locationType, factor, missID, -2, -3);
		case 5:
			return gcm.$getRandomPosition(locationType, factor, missID, 2, 3);
		case 6:
			return gcm.$getRandomPosition(locationType, factor, missID, 2, 3);
		case 7:
			return gcm.$getRandomPosition(locationType, factor, missID);
	}
}