Path |
Scripts/oolite-contracts-cargo_hide.js |
/*
oolite-contracts-cargo.js
Script for managing cargo contracts
Oolite
Copyright © 2004-2013 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
=========================================================================================================
Note: Additions/changes by Nick Rogers
1. Adjusted columns widths for wide fonts
2. Added check for illegal good types when creating possible contracts, so only legal goods at destination are selected
3. Added check for BigGUIHUD's when determining if the HUD needs to be hidden or not.
=========================================================================================================
*/
/*jslint white: true, undef: true, eqeqeq: true, bitwise: true, regexp: true, newcap: true, immed: true */
/*global galaxyNumber, missionVariables, system*/
"use strict";
this.name = "oolite-contracts-cargo";
this.author = "cim";
this.copyright = "© 2012-2013 the Oolite team.";
this.description = "Cargo delivery contracts.";
/**** Configuration options and API ****/
/* OXPs which wish to add a background to the summary pages should
set this value */
this.$cargoSummaryPageBackground = "";
/* OXPs which wish to add an overlay to the cargo mission screens
should set this value */
this.$cargoPageOverlay = "";
/* this._addCargoContractToSystem(cargo)
* This function adds the defined cargo contract to the local main station's
* interface list. A contract definition is an object with the following
* parameters, all required:
*
* destination: system ID of destination system
* commodity: the cargo type
* size: the number of units of cargo
* deadline: the deadline for delivery, in clock seconds
* payment: the payment for delivery on time, in credits
*
* and optionally, the following parameters:
*
* deposit: the deposit payment required by the player (default 0)
* route: a route object generated with system.info.routeToSystem
* describing the route between the source and destination
* systems.
*
* If this is not specified, it will be generated automatically.
*
* The function will return true if the contract can be added, false
* otherwise.
*/
this._addCargoContractToSystem = function(cargo)
{
if (!system.mainStation)
{
log(this.name,"Contracts require a main station");
return false;
}
if (cargo.destination < 0 || cargo.destination > 255)
{
log(this.name,"Rejected contract: destination missing or invalid");
return false;
}
if (cargo.deadline <= clock.adjustedSeconds)
{
log(this.name,"Rejected contract: deadline invalid");
return false;
}
if (cargo.payment < 0)
{
log(this.name,"Rejected contract: payment invalid");
return false;
}
if (!cargo.size || cargo.size < 1)
{
log(this.name,"Rejected contract: size invalid");
return false;
}
if (!cargo.commodity)
{
log(this.name,"Rejected contract: commodity unspecified");
return false;
}
if (!system.mainStation.market[cargo.commodity])
{
log(this.name,"Rejected contract: commodity invalid");
return false;
}
if (!cargo.route)
{
var destinationInfo = System.infoForSystem(galaxyNumber,cargo.destination);
cargo.route = system.info.routeToSystem(destinationInfo);
if (!cargo.route)
{
log(this.name,"Rejected contract: route invalid");
return false;
}
}
if (!cargo.deposit)
{
cargo.deposit = 0;
}
else if (cargo.deposit >= cargo.payment)
{
log(this.name,"Rejected contract: deposit higher than total payment");
return false;
}
this.$contracts.push(cargo);
this._updateMainStationInterfacesList();
return true;
}
/**** Internal methods. Do not call these from OXPs as they may change
**** without warning. ****/
/* Event handlers */
this.startUp = function()
{
this.$helper = worldScripts["oolite-contracts-helpers"];
this.$suspendedDestination = null;
this.$suspendedHUD = false;
// stored contents of local main station's parcel contract list
if (missionVariables.oolite_contracts_cargo)
{
this.$contracts = JSON.parse(missionVariables.oolite_contracts_cargo);
}
else
{
this._initialiseCargoContractsForSystem();
}
this._updateMainStationInterfacesList();
}
this.shipWillExitWitchspace = function()
{
if (!system.isInterstellarSpace && !system.sun.hasGoneNova && system.mainStation)
{
// must be a regular system with a main station
this._initialiseCargoContractsForSystem();
this._updateMainStationInterfacesList();
}
}
this.playerWillSaveGame = function()
{
// encode the contract list to a string for storage in the savegame
missionVariables.oolite_contracts_cargo = JSON.stringify(this.$contracts);
}
// when the player exits the mission screens, reset their destination
// system and HUD settings, which the mission screens may have
// affected.
this.shipWillLaunchFromStation = function()
{
this._resetViews();
}
this.guiScreenWillChange = function(to, from)
{
this._resetViews();
}
this.guiScreenChanged = function(to, from)
{
if (to != "GUI_SCREEN_MISSION")
{
this._resetViews();
}
}
/* Interface functions */
// resets HUD and jump destination
this._resetViews = function()
{
if (this.$suspendedHUD !== false)
{
player.ship.hudHidden = false;
this.$suspendedHUD = false;
}
if (this.$suspendedDestination !== null)
{
player.ship.targetSystem = this.$suspendedDestination;
this.$suspendedDestination = null;
}
}
// initialise a new cargo contract list for the current system
this._initialiseCargoContractsForSystem = function()
{
// clear list
this.$contracts = [];
// this is not the same algorithm as in 1.76, but should give
// similar results with comparable efficiency.
// no point in generating too many, as route-finding is slow
var numContracts = Math.floor(5*Math.random()+5*Math.random()+5*Math.random()+(player.contractReputationPrecise*Math.random()));
if (player.contractReputationPrecise >= 0 && numContracts < 5)
{
numContracts += 5;
}
if (numContracts > 16)
{
numContracts = 16;
}
else if (numContracts < 0)
{
numContracts = 0;
}
// some of these possible contracts may be discarded later on
for (var i = 0; i < numContracts; i++)
{
var cargo = new Object;
// pick a random system to take the goods to
var destination = Math.floor(Math.random()*256);
// discard if chose the current system
if (destination === system.ID)
{
continue;
}
// get the SystemInfo object for the destination
var destinationInfo = System.infoForSystem(galaxyNumber,destination);
if (destinationInfo.sun_gone_nova)
{
continue;
}
var daysUntilDeparture = 1+(Math.random()*(7+player.contractReputationPrecise-destinationInfo.government));
if (daysUntilDeparture <= 0)
{
// loses some more contracts if reputation negative
continue;
}
var si = worldScripts.Smugglers_Illegal;
var illegal = null;
if (si) {
illegal = si.$illegalGoodsListCommodityOnly(destination, true);
// add slaves to the list
illegal.push("slaves");
}
var commodities = Object.keys(system.mainStation.market);
var attempts = 0;
do {
var remotePrice = 0;
attempts++;
var commodity = commodities[Math.floor(Math.random()*commodities.length)];
// sub-tc contracts only available for top rep
if (system.mainStation.market[commodity]["quantity_unit"] != 0 && player.contractReputationPrecise < 6.5)
{
}
// ignore commodities with 0 availability here
else if (system.mainStation.market[commodity].quantity == 0)
{
}
// ignore any illegal goods
else if (illegal && illegal.indexOf(commodity) >= 0)
{
}
else
{
remotePrice = this._priceForCommodity(commodity,destinationInfo);
}
} while (remotePrice < system.mainStation.market[commodity].price/20 && attempts < 10);
if (attempts == 10)
{
// failed to find a good one.
continue;
}
cargo.commodity = commodity;
var amount = 0;
while (amount < 30)
{
var unitsize = 1;
// larger unit sizes for kg/g commodities
if (system.mainStation.market[commodity]["quantity_unit"] == 1)
{
unitsize += Math.floor(Math.random()*6)+Math.floor(Math.random()*6)+Math.floor(Math.random()*6);
}
else if (system.mainStation.market[commodity]["quantity_unit"] == 2)
{
unitsize += Math.floor(Math.random()*16)+Math.floor(Math.random()*11)+Math.floor(Math.random()*6);
}
amount += (1+Math.floor(Math.random()*32))*(1+Math.floor(Math.random()*16))*unitsize;
}
if (amount > 125 && system.mainStation.market[commodity]["quantity_unit"] == 0)
{
// reduce the number of contracts only suitable for Anacondas
amount = Math.floor(amount/Math.floor(1+(Math.random()*4)));
}
cargo.size = amount;
// adjustment to prices based on quantity (larger = more profitable)
var discount = Math.min(10+Math.floor(amount/10),35);
var unitPrice = system.mainStation.market[commodity].price * (100-discount) / 1000;
var localValue = Math.floor(unitPrice * amount);
remotePrice = remotePrice * (200+discount) / 200;
var remoteValue = Math.floor(remotePrice * amount);
var profit = remoteValue-localValue;
// skip if unprofitable
if (profit <= 100)
{
continue;
}
// check that a route to the destination exists
// route calculation is expensive so leave this check to last
var routeToDestination = system.info.routeToSystem(destinationInfo);
// if the system cannot be reached, ignore this contract
if (!routeToDestination)
{
continue;
}
// we now have a valid destination, so generate the rest of
// the parcel details
cargo.destination = destination;
// we'll need this again later, and route calculation is slow
cargo.route = routeToDestination;
// higher share for transporter for longer routes, less safe systems
var share = 100 + destinationInfo.government - (10*routeToDestination.route.length);
if (share < 10)
{
share = 10;
}
share = 100-share;
// safety: now multiply the fee by 2 compared with 1.76 contracts
// prevents exploit discovered by Mad Hollander at
// http://bb.oolite.space/viewtopic.php?p=188127
localValue *= 2;
// this may need to be raised further
// absolute value of profit remains the same
var fee = localValue + Math.floor(profit * (share/100));
fee -= fee % 20; // round to nearest 20 credits;
cargo.payment = fee;
cargo.deposit = localValue - (localValue % 20);
if (cargo.deposit >= cargo.payment)
{
// rare but not impossible; last safety check
return;
}
// time allowed for delivery is time taken by "fewest jumps"
// route, plus timer above. Higher reputation makes longer
// times available.
cargo.deadline = clock.adjustedSeconds + Math.floor(daysUntilDeparture*86400)+(cargo.route.time*3600);
// add parcel to contract list
this._addCargoContractToSystem(cargo);
}
}
// this should be called every time the contents of this.$parcels
// changes, as it updates the summary of the interface entry.
this._updateMainStationInterfacesList = function()
{
if (this.$contracts.length === 0)
{
// no contracts, remove interface if it exists
system.mainStation.setInterface("oolite-contracts-cargo",null);
}
else
{
var title = expandMissionText("oolite-contracts-cargo-interface-title",{
"oolite-contracts-cargo-interface-title-count": this.$contracts.length
});
system.mainStation.setInterface("oolite-contracts-cargo",{
title: title,
category: expandMissionText("oolite-contracts-cargo-interface-category"),
summary: expandMissionText("oolite-contracts-cargo-interface-summary"),
callback: this._cargoContractsScreens.bind(this)
// could alternatively use "cbThis: this" parameter instead of bind()
});
}
}
// if the interface is activated, this function is run.
this._cargoContractsScreens = function(interfaceKey)
{
// the interfaceKey parameter is not used here, but would be useful if
// this callback managed more than one interface entry
this._validateContracts();
// set up variables used to remember state on the mission screens
this.$suspendedDestination = null;
this.$suspendedHUD = false;
this.$contractIndex = 0;
this.$routeMode = "LONG_RANGE_CHART_SHORTEST";
this.$lastOptionChosen = "06_EXIT";
// start on the summary page if more than one contract is available
var summary = (this.$contracts.length > 1);
this._cargoContractsDisplay(summary);
}
// this function is called after the player makes a choice which keeps
// them in the system, and also on initial entry to the system
// to select the appropriate mission screen and display it
this._cargoContractsDisplay = function(summary) {
// Again. Has to be done on every call to this function, but also
// has to be done at the start.
this._validateContracts();
// if there are no contracts (usually because the player has taken
// the last one) display a message and quit.
if (this.$contracts.length === 0)
{
var missionConfig = {titleKey: "oolite-contracts-cargo-none-available-title",
messageKey: "oolite-contracts-cargo-none-available-message",
allowInterrupt: true,
screenID: "oolite-contracts-cargo-none",
exitScreen: "GUI_SCREEN_INTERFACES"};
if (this.$cargoSummaryPageBackground != "") {
missionConfig.background = this.$cargoSummaryPageBackground;
}
if (this.$cargoPageOverlay != "") {
missionConfig.overlay = this.$cargoPageOverlay;
}
mission.runScreen(missionConfig);
// no callback, just exits contracts system
return;
}
// make sure that the 'currently selected contract' pointer
// is in bounds
if (this.$contractIndex >= this.$contracts.length)
{
this.$contractIndex = 0;
}
else if (this.$contractIndex < 0)
{
this.$contractIndex = this.$contracts.length - 1;
}
// sub functions display either summary or detail screens
if (summary)
{
this._cargoContractSummaryPage();
}
else
{
this._cargoContractSinglePage();
}
}
// display the mission screen for the summary page
this._cargoContractSummaryPage = function()
{
// column 'tab stops'
var columns = [9,15,21,26];
// column header line
var headline = expandMissionText("oolite-contracts-cargo-column-goods");
// pad to correct length to give a table-like layout
headline += this.$helper._paddingText(headline,columns[0]);
headline += expandMissionText("oolite-contracts-cargo-column-destination");
headline += this.$helper._paddingText(headline,columns[1]);
headline += expandMissionText("oolite-contracts-cargo-column-within");
headline += this.$helper._paddingText(headline,columns[2]);
headline += expandMissionText("oolite-contracts-cargo-column-deposit");
headline += this.$helper._paddingText(headline,columns[3]);
headline += expandMissionText("oolite-contracts-cargo-column-fee");
// required because of way choices are displayed.
headline = " "+headline;
// setting options dynamically; one contract per line
var options = new Object;
var i;
var anyWithSpace = false;
for (i=0; i<this.$contracts.length; i++)
{
// temp variable to simplify following code
var cargo = this.$contracts[i];
// write the description, padded to line up with the headers
var optionText = this._descriptionForGoods(cargo);
optionText += this.$helper._paddingText(optionText, columns[0]);
optionText += System.infoForSystem(galaxyNumber, cargo.destination).name;
optionText += this.$helper._paddingText(optionText, columns[1]);
optionText += this.$helper._timeRemaining(cargo);
optionText += this.$helper._paddingText(optionText, columns[2]);
// right-align the fee so that the credits signs line up
var priceText = formatCredits(cargo.deposit,false,true);
priceText = this.$helper._paddingText(priceText, 3.5)+priceText;
optionText += priceText
optionText += this.$helper._paddingText(optionText, columns[3]);
// right-align the fee so that the credits signs line up
priceText = formatCredits(cargo.payment-cargo.deposit,false,true);
priceText = this.$helper._paddingText(priceText, 3.5)+priceText;
optionText += priceText
// need to pad the number in the key to maintain alphabetical order
var istr = i;
if (i < 10)
{
istr = "0"+i;
}
// needs to be aligned left to line up with the heading
options["01_CONTRACT_"+istr] = { text: optionText, alignment: "LEFT" };
// check if there's space for this contract
if (!this._hasSpaceFor(cargo))
{
options["01_CONTRACT_"+istr].color = "darkGrayColor";
}
else
{
anyWithSpace = true;
// if there doesn't appear to be sufficient time remaining
if (this.$helper._timeRemainingSeconds(cargo) < this.$helper._timeEstimateSeconds(cargo))
{
options["01_CONTRACT_"+istr].color = "orangeColor";
}
}
}
// if we've come from the detail screen, make sure the last
// contract shown there is selected here
var icstr = this.$contractIndex;
if (icstr < 10)
{
icstr = "0"+this.$contractIndex;
}
var initialChoice = "01_CONTRACT_"+icstr;
// if none of them have any space...
if (!anyWithSpace)
{
initialChoice = "06_EXIT";
}
// next, an empty string gives an unselectable row
options["02_SPACER"] = "";
// numbered 06 to match the option of the same function in the other branch
options["06_EXIT"] = expandMissionText("oolite-contracts-cargo-command-quit");
// now need to add further spacing to fill the remaining rows, or
// the options will end up at the bottom of the screen.
var rowsToFill = 21;
if (player.ship.hudHidden || this.$isBigGuiActive() == true)
{
rowsToFill = 27;
}
for (i = 4 + this.$contracts.length; i < rowsToFill ; i++)
{
// each key needs to be unique at this stage.
options["07_SPACER_"+i] = "";
}
var missionConfig = {titleKey: "oolite-contracts-cargo-title-summary",
message: headline,
allowInterrupt: true,
screenID: "oolite-contracts-cargo-summary",
exitScreen: "GUI_SCREEN_INTERFACES",
choices: options,
initialChoicesKey: initialChoice};
if (this.$cargoSummaryPageBackground != "") {
missionConfig.background = this.$cargoSummaryPageBackground;
}
if (this.$cargoPageOverlay != "") {
missionConfig.overlay = this.$cargoPageOverlay;
}
// now run the mission screen
mission.runScreen(missionConfig, this._processCargoChoice, this);
}
// display the mission screen for the contract detail page
this._cargoContractSinglePage = function()
{
// temp variable to simplify code
var cargo = this.$contracts[this.$contractIndex];
// This mission screen uses the long range chart as a backdrop.
// This means that the first 18 lines are taken up by the chart,
// and we can't put text there without overwriting the chart.
// We therefore need to hide the player's HUD, to get the full 27
// lines.
if (!player.ship.hudHidden && this.$isBigGuiActive() == false)
{
this.$suspendedHUD = true; // note that we hid it, for later
player.ship.hudHidden = true;
}
// We also set the player's witchspace destination temporarily
// so we need to store the old one in a variable to reset it later
this.$suspendedDestination = player.ship.targetSystem;
// That done, we can set the player's destination so the map looks
// right.
player.ship.targetSystem = cargo.destination;
// start with 18 blank lines, since we don't want to overlap the chart
var message = new Array(18).join("\n");
message += expandMissionText("oolite-contracts-cargo-long-description",{
"oolite-contracts-cargo-longdesc-goods": this._descriptionForGoods(cargo),
"oolite-contracts-cargo-longdesc-destination": this.$helper._systemName(cargo.destination),
"oolite-contracts-cargo-longdesc-deadline": this.$helper._timeRemaining(cargo),
"oolite-contracts-cargo-longdesc-time": this.$helper._timeEstimate(cargo),
"oolite-contracts-cargo-longdesc-payment": formatCredits(cargo.payment,false,true),
"oolite-contracts-cargo-longdesc-deposit": formatCredits(cargo.deposit,false,true)
});
// use a special background
var backgroundSpecial = "LONG_RANGE_CHART";
// the available options will vary quite a bit, so this rather
// than a choicesKey in missiontext.plist
var options = new Object;
// this is the only option which is always available
options["06_EXIT"] = expandMissionText("oolite-contracts-cargo-command-quit");
// if the player has sufficient space
if (this._hasSpaceFor(cargo))
{
options["05_ACCEPT"] = {
text: expandMissionText("oolite-contracts-cargo-command-accept")
};
// if there's not much time left, change the option colour as a warning!
if (this.$helper._timeRemainingSeconds(cargo) < this.$helper._timeEstimateSeconds(cargo))
{
options["05_ACCEPT"].color = "orangeColor";
}
}
else
{
options["05_UNAVAILABLE"] = {
text: expandMissionText("oolite-contracts-cargo-command-unavailable"),
color: "darkGrayColor",
unselectable: true
};
}
// if the ship has a working advanced nav array, can switch
// between 'quickest' and 'shortest' routes
// (and also upgrade the special background)
if (player.ship.equipmentStatus("EQ_ADVANCED_NAVIGATIONAL_ARRAY") === "EQUIPMENT_OK")
{
backgroundSpecial = this.$routeMode;
if (this.$routeMode === "LONG_RANGE_CHART_SHORTEST")
{
options["01_MODE"] = expandMissionText("oolite-contracts-cargo-command-ana-quickest");
}
else
{
options["01_MODE"] = expandMissionText("oolite-contracts-cargo-command-ana-shortest");
}
}
// if there's more than one, need options for forward, back, and listing
if (this.$contracts.length > 1)
{
options["02_BACK"] = expandMissionText("oolite-contracts-cargo-command-back");
options["03_NEXT"] = expandMissionText("oolite-contracts-cargo-command-next");
options["04_LIST"] = expandMissionText("oolite-contracts-cargo-command-list");
}
else
{
// if not, we may need to set a different choice
// we never want 05_ACCEPT to end up selected initially
if (this.$lastChoice === "02_BACK" || this.$lastChoice === "03_NEXT" || this.$lastChoice === "04_LIST")
{
this.$lastChoice = "06_EXIT";
}
}
var title = expandMissionText("oolite-contracts-cargo-title-detail",{
"oolite-contracts-cargo-title-detail-number": this.$contractIndex+1,
"oolite-contracts-cargo-title-detail-total": this.$contracts.length
});
// finally, after all that setup, actually create the mission screen
var missionConfig = {
title: title,
message: message,
allowInterrupt: true,
screenID: "oolite-contracts-cargo-details",
exitScreen: "GUI_SCREEN_INTERFACES",
backgroundSpecial: backgroundSpecial,
choices: options,
initialChoicesKey: this.$lastChoice
};
if (this.$cargoPageOverlay != "") {
missionConfig.overlay = this.$cargoPageOverlay;
}
mission.runScreen(missionConfig,this._processCargoChoice, this);
}
this._processCargoChoice = function(choice)
{
this._resetViews();
if (choice === null)
{
// can occur if ship launches mid mission screen
return;
}
// now process the various choices
if (choice.match(/^01_CONTRACT_/))
{
// contract selected from summary page
// set the index to that contract, and show details
var index = parseInt(choice.slice(12),10);
this.$contractIndex = index;
this.$lastChoice = "04_LIST";
this._cargoContractsDisplay(false);
}
else if (choice === "01_MODE")
{
// advanced navigation array mode flip
this.$routeMode = (this.$routeMode === "LONG_RANGE_CHART_SHORTEST")?"LONG_RANGE_CHART_QUICKEST":"LONG_RANGE_CHART_SHORTEST";
this.$lastChoice = "01_MODE";
this._cargoContractsDisplay(false);
}
else if (choice === "02_BACK")
{
// reduce contract index (cargoContractsDisplay manages wraparound)
this.$contractIndex--;
this.$lastChoice = "02_BACK";
this._cargoContractsDisplay(false);
}
else if (choice === "03_NEXT")
{
// increase contract index (cargoContractsDisplay manages wraparound)
this.$contractIndex++;
this.$lastChoice = "03_NEXT";
this._cargoContractsDisplay(false);
}
else if (choice === "04_LIST")
{
// display the summary page
this._cargoContractsDisplay(true);
}
else if (choice === "05_ACCEPT")
{
this._acceptContract();
// do not leave the setting as accept for the next contract!
this.$lastChoice = "03_NEXT";
this._cargoContractsDisplay(false);
}
// if we get this far without having called cargoContractsDisplay
// that means either 'exit' or an unrecognised option was chosen
}
// move goods from the contracts list to the player's ship (if possible)
this._acceptContract = function()
{
var cargo = this.$contracts[this.$contractIndex];
if (cargo.deposit > player.credits)
{
this.$helper._soundFailure();
return;
}
// give the cargo to the player
var result = player.ship.awardContract(cargo.size,cargo.commodity,system.ID,cargo.destination,cargo.deadline,cargo.payment,cargo.deposit);
if (result)
{
// pay the deposit
player.credits -= cargo.deposit;
// remove the contract from the station list
this.$contracts.splice(this.$contractIndex,1);
// update the interface description
this._updateMainStationInterfacesList();
this.$helper._soundSuccess();
}
else
{
// else must have had manifest change recently
// (unlikely, but another OXP could have done it)
this.$helper._soundFailure();
}
}
// removes any expired contracts
this._validateContracts = function()
{
var c = this.$contracts.length-1;
var removed = false;
// iterate downwards so we can safely remove as we go
for (var i=c;i>=0;i--)
{
// if the time remaining is less than 1/3 of the estimated
// delivery time, even in the best case it's probably not
// going to get there.
if (this.$helper._timeRemainingSeconds(this.$contracts[i]) < this.$helper._timeEstimateSeconds(this.$contracts[i]) / 3)
{
// remove it
this.$contracts.splice(i,1);
removed = true;
}
}
if (removed)
{
// update the interface description if we removed any
this._updateMainStationInterfacesList();
}
}
/* Utility functions */
// calculates a sample price for a commodity in a distant system
this._priceForCommodity = function(commodity,systeminfo)
{
//sample price returns decicredits, need credits
return systeminfo.samplePrice(commodity)/10;
}
// description of the cargo
this._descriptionForGoods = function(cargo)
{
var unit = "tons";
if (system.mainStation.market[cargo.commodity]["quantity_unit"] == "1")
{
unit = "kilograms";
}
else if (system.mainStation.market[cargo.commodity]["quantity_unit"] == "2")
{
unit = "grams";
}
return cargo.size+expandDescription("[cargo-"+unit+"-symbol]")+" "+displayNameForCommodity(cargo.commodity);
}
// check if player's ship has space for the cargo and can afford the deposit
this._hasSpaceFor = function(cargo)
{
if (cargo.deposit > player.credits)
{
return false;
}
var amountInTC = cargo.size;
if (system.mainStation.market[cargo.commodity]["quantity_unit"] == "1")
{
var spareSafe = 499-(player.ship.manifest[cargo.commodity] % 1000);
amountInTC -= spareSafe;
amountInTC = Math.ceil(amountInTC/1000);
if (amountInTC < 0)
{
amountInTC = 0;
}
}
else if (system.mainStation.market[cargo.commodity]["quantity_unit"] == "2")
{
var spareSafe = 499999-(player.ship.manifest[cargo.commodity] % 1000000);
amountInTC -= spareSafe;
amountInTC = Math.ceil(amountInTC/1000000);
if (amountInTC < 0)
{
amountInTC = 0;
}
}
return (amountInTC <= player.ship.cargoSpaceAvailable);
}
//-------------------------------------------------------------------------------------------------------------
// returns true if a HUD with allowBigGUI is enabled, otherwise false
this.$isBigGuiActive = function() {
if (oolite.compareVersion("1.83") < 0) {
return player.ship.hudAllowsBigGui;
} else {
var bigGuiHUD = ["XenonHUD.plist"]; // 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;
}
}
}
|
Scripts/permit_conditions.js |
"use strict";
this.name = "Permit_Conditions";
this.author = "phkb";
this.copyright = "2015 phkb";
this.description = "Condition script for determining whether to include the 'Import permit' item on the F3 screen";
this.licence = "CC BY-NC-SA 3.0";
//-------------------------------------------------------------------------------------------------------------
this.allowAwardEquipment = function (equipment, ship, context) {
if (player.ship.dockedStation.allegiance != "galcop") return false;
var result = true;
switch (equipment) {
case "EQ_IMPORT_PERMIT_NC":
case "EQ_IMPORT_PERMIT":
if (equipment == "EQ_IMPORT_PERMIT_NC" && !worldScripts.CargoTypeExtension) return false;
if (equipment == "EQ_IMPORT_PERMIT" && worldScripts.CargoTypeExtension) return false;
var si = worldScripts.Smugglers_Illegal;
var goods = si.$illegalGoodsList(system.ID);
// are there any illegal goods in this system
if (goods.length === 0) {
return false;
}
// does the player already have permits for all the goods?
var count = 0;
var permitavail = 0;
for (var i = 0; i < goods.length; i++) {
if (goods[i].permit === 1) {
permitavail += 1;
if (si.$playerHasPermit(system.ID, goods[i].commodity) === true) {
count += 1;
permitavail -= 1;
}
}
}
if (count === goods.length) result = false;
if (permitavail <= 0) result = false;
break;
}
// otherwise allowed
return result;
} |
Scripts/smugglers_conditions.js |
"use strict";
this.name = "Smugglers_Conditions";
this.author = "phkb";
this.copyright = "2015 phkb";
this.description = "Condition script for determining when to include smuggling equipment (compartment, scanner, tech version upgrade)";
this.licence = "CC BY-NC-SA 3.0";
this._debug = false;
// station roles to be excluded
this._excludeRoles = ["rescue_station"];
//-------------------------------------------------------------------------------------------------------------
this.allowAwardEquipment = function (equipment, ship, context) {
if (context === "scripted") return true;
if (context === "npc") return false;
if (equipment === "EQ_SMUGGLING_COMP_STORAGE") return false;
var result = true;
var se = worldScripts.Smugglers_Equipment;
var existing = se.$getSmugglingCompartmentEquipment();
var alleg = ship.dockedStation.allegiance;
if (alleg == null) alleg = "neutral";
// is this station likely to have the equipment?
if (context === "purchase" && ship && ship.dockedStation && this._debug === false) {
if (se._equipmentList.indexOf(equipment) >= 0 && (existing === "" || player.ship.equipmentStatus(existing) === "EQUIPMENT_OK")) result = false;
if (se._smugglingAllegiance.indexOf(alleg) === -1 || this._excludeRoles.indexOf(ship.dockedStation.primaryRole) != -1) result = false;
if (result === false) {
return result;
}
}
// version 1.83 and above fix the issue with repair to items that take cargo space
if (oolite.compareVersion("1.83") <= 0) {
if (player.ship.equipmentStatus(equipment) === "EQUIPMENT_DAMAGED" && system.info.techlevel >= 2) {
return true;
}
}
if (equipment.indexOf("COMPARTMENT_REPAIR") >= 0 && oolite.compareVersion("1.83") > 0) {
if (system.info.techlevel < 2) result = false;
if (se.$isCompartmentDamaged() === false) result = false;
}
switch (equipment) {
case "EQ_SMUGGLING_COMPARTMENT":
// not available if there's no cargo space at all
if (ship.cargoSpaceCapacity === 0) result = false;
if (system.info.techlevel < 3) result = false;
if (se.$hasSmugglingCompartment() === true && se.$isCompartmentDamaged() === true && oolite.compareVersion("1.83") > 0) result = false;
// we should always be able to adjust the tonnage, even if the only way is down.
break;
case "EQ_PHASE_SCANNER":
var tl = 7;
if (ship.equipmentStatus(equipment) === "EQUIPMENT_DAMAGED") tl = 6;
if (system.government != 0) result = false;
if (system.info.techlevel < tl) result = false;
if (se._phaseScannerAvailable === false) result = false;
break;
case "EQ_SMUGGLING_PHASE_ADJUSTMENT":
if (system.info.techlevel < 6) result = false;
break;
case "EQ_SMUGGLING_VERSION_UPGRADE":
// higher techlevel systems will get the upgrade sooner
if (system.info.techlevel < 4) result = false;
if (se._sc_Days < (60 * ((60 - system.info.techlevel) / 60))) result = false;
break;
default:
// is this item damaged?
if (ship.equipmentStatus(equipment) === "EQUIPMENT_DAMAGED") {
// return true so that the "Repair" items are displayed.
result = true;
} else {
result = false;
}
}
return result;
} |
Scripts/smugglers_contracts.js |
"use strict";
this.name = "Smugglers_Contracts";
this.author = "phkb and cim";
this.description = "Adds smuggling contracts via an interface screen, with code borrowed heavily from the cargo contracts system, authored by cim.";
this.licence = "CC BY-NC-SA 3.0";
this._disabled = false;
/*
Note: The smuggling contract system is independent of the standard cargo contract system. The reason for this is that
smuggled cargo might exist in a number of different places (smuggling compartment, or hidden under a manifest relabel)
This means the normal cargo contract system cannot pick up the presence of hidden cargo.
The end result is that a lot of the standard cargo contract core code has been reproduced here as JS.
TODO: add "Negotiate" option to haggle for the fee
*/
//=============================================================================================================
/**** Configuration options and API ****/
/* OXPs which wish to add a background to the summary pages should
set this value */
this._smugglingSummaryPageBackground = "";
/* OXPs which wish to add an overlay to the parcel mission screens
should set this value */
this._smugglingPageOverlay = "";
this._smugglingPageOverlayHeight = 0;
this._suspendedDestination = null;
this._suspendedHUD = false;
this._smugglingContracts = [];
this._smugglingRepGood = 0;
this._smugglingRepBad = 0;
this._smugglingRepUnknown = 0;
this._maxRep = 70;
this._checkForCargo = false;
this._marketrnd = 0;
//=============================================================================================================
/* this.$addSmugglingContractToSystem(cargo)
* This function adds the defined smuggling contract to the black market contract list.
* A contract definition is an object with the following parameters, all required:
*
* destination: system ID of destination system
* commodity: the cargo type
* size: the number of units of cargo
* deadline: the deadline for delivery, in clock seconds
* payment: the payment for delivery on time, in credits
*
* and optionally, the following parameters:
*
* deposit: the deposit payment required by the player (default 0)
* route: a route object generated with system.info.routeToSystem
* describing the route between the source and destination
* systems.
*
* If this is not specified, it will be generated automatically.
*
* The function will return true if the contract can be added, false
* otherwise.
*/
this.$addSmugglingContractToSystem = function $addSmugglingContractToSystem(cargo) {
if (cargo.destination < 0 || cargo.destination > 255) {
log(this.name, "Rejected contract: destination missing or invalid");
return false;
}
if (cargo.deadline <= clock.adjustedSeconds) {
log(this.name, "Rejected contract: deadline invalid");
return false;
}
if (cargo.payment < 0) {
log(this.name, "Rejected contract: payment invalid");
return false;
}
if (!cargo.size || cargo.size < 1) {
log(this.name, "Rejected contract: size invalid");
return false;
}
if (!cargo.commodity) {
log(this.name, "Rejected contract: commodity unspecified");
return false;
}
if (!system.mainStation.market[cargo.commodity]) {
log(this.name, "Rejected contract: commodity invalid");
return false;
}
if (!cargo.route) {
var destinationInfo = System.infoForSystem(galaxyNumber, cargo.destination);
cargo.route = system.info.routeToSystem(destinationInfo);
if (!cargo.route) {
log(this.name, "Rejected contract: route invalid");
return false;
}
}
if (!cargo.deposit) {
cargo.deposit = 0;
} else if (cargo.deposit >= cargo.payment) {
log(this.name, "Rejected contract: deposit higher than total payment");
return false;
}
this._contracts.push(cargo);
return true;
}
//=============================================================================================================
/* Event handlers */
//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
if (this._disabled === true) {
delete this.shipExitedWitchspace;
delete this.playerWillSaveGame;
delete this.shipWillLaunchFromStation;
delete this.guiScreenWillChange;
delete this.guiScreenChanged;
delete this.startUp;
return;
}
this._helper = worldScripts["oolite-contracts-helpers"];
var core = worldScripts.Smugglers_CoreFunctions;
this.$padTextRight = core.$padTextRight;
this.$padTextLeft = core.$padTextLeft;
this.$isBigGuiActive = core.$isBigGuiActive;
this.$rand = core.$rand;
if (missionVariables.Smuggling_MarketRnd) this._marketrnd = missionVariables.Smuggling_MarketRnd;
if (missionVariables.Smuggling_RepGood) {
this._smugglingRepGood = missionVariables.Smuggling_RepGood;
this._smugglingRepBad = missionVariables.Smuggling_RepBad;
this._smugglingRepUnknown = missionVariables.Smuggling_RepUnknown;
}
this.$normaliseSmugglingReputation();
if (missionVariables.Smuggling_ActiveContracts) {
this._smugglingContracts = JSON.parse(missionVariables.Smuggling_ActiveContracts);
}
// stored contents of systems's cargo contract list
if (missionVariables.Smuggling_Contracts) {
this._contracts = JSON.parse(missionVariables.Smuggling_Contracts);
} else {
this.$initialiseSmugglingContractsForSystem();
}
// its unclear whether this or ContractsOnBB will get to it's startUpComplete first, so we'll force the issue here
if (worldScripts.ContractsOnBB) {
worldScripts.ContractsOnBB.$convertSmugglingContracts();
}
var xui = worldScripts.XenonUI;
if (xui) xui.$addMissionScreenException("oolite-smuggling-contracts-details"); // smuggling-contracts-details
var xrui = worldScripts.XenonReduxUI;
if (xrui) xrui.$addMissionScreenException("oolite-smuggling-contracts-details");
}
//-------------------------------------------------------------------------------------------------------------
this.shipExitedWitchspace = function () {
if (!system.isInterstellarSpace && !system.sun.hasGoneNova && system.stations.length > 1) {
// must be a regular system with at least one station other than the main one
this._marketrnd = this.$rand(256) - 1;
this.$erodeSmugglingReputation();
this.$initialiseSmugglingContractsForSystem();
this.$adjustMarket();
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
// encode the contract list to a string for storage in the savegame
missionVariables.Smuggling_Contracts = JSON.stringify(this._contracts);
missionVariables.Smuggling_RepGood = this._smugglingRepGood;
missionVariables.Smuggling_RepBad = this._smugglingRepBad;
missionVariables.Smuggling_RepUnknown = this._smugglingRepUnknown;
missionVariables.Smuggling_ActiveContracts = JSON.stringify(this._smugglingContracts);
missionVariables.Smuggling_MarketRnd = this._marketrnd;
}
//-------------------------------------------------------------------------------------------------------------
// when the player exits the mission screens, reset their destination
// system and HUD settings, which the mission screens may have
// affected.
this.shipWillLaunchFromStation = function () {
this.$resetViews();
}
//-------------------------------------------------------------------------------------------------------------
this.shipDockedWithStation = function (station) {
if (player.ship.dockedStation.allegiance === "galcop") this._checkForCargo = true;
}
//-------------------------------------------------------------------------------------------------------------
this.missionScreenOpportunity = function () {
if (this._checkForCargo === true) {
this._checkForCargo = false;
this.$checkForCompletedContracts();
}
}
//-------------------------------------------------------------------------------------------------------------
this.guiScreenWillChange = function (to, from) {
this.$resetViews();
if (to === "GUI_SCREEN_MANIFEST") this.$updateManifest();
}
//-------------------------------------------------------------------------------------------------------------
this.guiScreenChanged = function (to, from) {
if (to != "GUI_SCREEN_MISSION") this.$resetViews();
}
//=============================================================================================================
/* Interface functions */
//-------------------------------------------------------------------------------------------------------------
// runs through all smuggling contracts looking for any completed ones
this.$checkForCompletedContracts = function $checkForCompletedContracts() {
if (this._smugglingContracts.length === 0) return;
var sc = worldScripts.Smugglers_Equipment;
var sdm = worldScripts.Smugglers_DockMaster;
var p = player.ship;
var list = [];
for (var i = this._smugglingContracts.length - 1; i >= 0; i--) {
var m = this._smugglingContracts[i];
var errorCode = "";
var new_payment = 0;
var percent_delivered = 0;
// are we in the right system
if (m.destination === system.ID && m.destinationName === system.name) {
if (clock.adjustedSeconds <= m.deadline) {
var onhand = 0;
onhand += sdm.$getTotalUnlabelled(m.commodity); // add any cargo currently hiding under a relabel
onhand += p.manifest[m.commodity]; // add any visible cargo in the hold
onhand -= sdm.$getTotalRelabelled(m.commodity); // take away any cargo that might be masked by a label (ie. cargo that looks like the commodity but really isn't)
onhand += sc.$getCargoQuantity(m.commodity); // add any cargo in the smuggling compartment
onhand += sc.$checkHyperCargo(m.commodity); // add any cargo in hyper cargo
if (onhand >= m.size) {
errorCode = "success";
player.credits += m.fee;
this.$removeCargo(m.commodity, m.size);
player.setPlayerRole("trader-smuggler");
} else {
percent_delivered = 100.0 * (onhand / m.size);
var acceptable_ratio = 100.0 - 10.0 * system.ID / 256; // down to 90%
if (percent_delivered >= acceptable_ratio) {
var shortfall = 100 - percent_delivered;
new_payment = percent_delivered * (m.fee) / 100.0;
player.credits += new_payment;
errorCode = "short";
this.$removeCargo(m.commodity, m.size);
player.setPlayerRole("trader-smuggler");
} else {
errorCode = "refused_short";
}
}
} else {
errorCode = "late";
}
} else {
if (clock.adjustedSeconds > m.deadline) {
errorCode = "failed";
}
}
var desc = "";
// adjust the fee and reputation based on the result
switch (errorCode) {
case "success":
// build a contact
var contactHome = this.$rand(256) - 1;
var contact = "a " + System.infoForSystem(galaxyNumber, contactHome).inhabitant.toLowerCase() + " from " + System.systemNameForID(contactHome);
desc = expandDescription("[smuggled-cargo-delivered-okay]", {
cargo: this.$descriptionForGoods(m),
fee: formatCredits(m.fee, true, true),
contactdesc: contact
});
this.$increaseSmugglingReputation(10);
this.$contractCompletedEmail(errorCode, m.fee, m);
if (this.$anyContractsLeftForSystem(i, m.destination) === false)
mission.unmarkSystem({
system: m.destination,
name: "smuggling_contract_" + m.destination
});
break;
case "late":
desc = expandDescription("[smuggled-cargo-delivered-late]", {
cargo: this.$descriptionForGoods(m)
});
this.$decreaseSmugglingReputation(10);
this.$contractCompletedEmail(errorCode, 0, m);
if (this.$anyContractsLeftForSystem(i, m.destination) === false)
mission.unmarkSystem({
system: m.destination,
name: "smuggling_contract_" + m.destination
});
break;
case "failed":
desc = expandDescription("[smuggled-cargo-failed]", {
cargo: this.$descriptionForGoods(m)
});
this.$decreaseSmugglingReputation(10);
this.$contractCompletedEmail(errorCode, 0, m);
if (this.$anyContractsLeftForSystem(i, m.destination) === false)
mission.unmarkSystem({
system: m.destination,
name: "smuggling_contract_" + m.destination
});
break;
case "short":
desc = expandDescription("[smuggled-cargo-short]", {
cargo: this.$descriptionForGoods(m),
fee: formatCredits(new_payment, true, true),
percent: percent_delivered
});
this.$contractCompletedEmail(errorCode, new_payment, m);
if (this.$anyContractsLeftForSystem(i, m.destination) === false)
mission.unmarkSystem({
system: m.destination,
name: "smuggling_contract_" + m.destination
});
break;
case "refused_short":
desc = expandDescription("[smuggled-cargo-refused-short]", {
cargo: this.$descriptionForGoods(m)
});
// reset the error so we can skip this one - the player still has time to complete the contract
errorCode = "";
break;
}
if (desc != "") list.push(desc);
// if we got to this point with a result of some kind, remove the contract
if (errorCode != "") {
if (worldScripts.ContractsOnBB) {
worldScripts.ContractsOnBB.$removeSmugglingContract(i);
}
this._smugglingContracts.splice(i, 1);
}
}
if (list.length > 0) {
// add all contract summary items to the arrival report
var text = "";
for (var i = 0; i < list.length; i++) {
text += list[i] + "\n\n";
}
mission.runScreen({
titleKey: "smuggling-contracts-title-summary",
message: text,
exitScreen: "GUI_SCREEN_STATUS"
});
}
}
//-------------------------------------------------------------------------------------------------------------
// removes a specific amount of the commodity, from various locations in this order:
// 1. relabelled commodities, 2. standard hold, 3. smuggling compartmnt, 4. hypercargo
// returns quantity not found (should be zero in most circumstances)
this.$removeCargo = function $removeCargo(commodity, amount) {
var se = worldScripts.Smugglers_Equipment;
var sdm = worldScripts.Smugglers_DockMaster;
var p = player.ship;
var sum = amount;
// is there any relabelled cargo?
if (sdm.$getTotalRelabelled(commodity) > 0) {
// unlabel the cargo so the next bit will pick it up
var relbl_remain = sdm.$removeRealCargoQuantity(commodity, sum);
}
// do we have the cargo anywhere? check normal hold
if (p.manifest[commodity] >= sum) {
p.manifest[commodity] -= sum;
sum = 0;
} else if (p.manifest[commodity] > 0) {
sum -= p.manifest[commodity];
p.manifest[commodity] = 0;
}
// smuggling compartment
if (sum > 0 && se.$getCargoQuantity(commodity) > 0) {
var remain = se.$removeCargo(commodity, sum);
sum = remain;
}
// and hypercargo
if (sum > 0 && se.$checkHyperCargo(commodity) > 0) {
var remain = se.$removeHyperCargo(commodity, sum);
sum = remain;
}
return sum;
}
//-------------------------------------------------------------------------------------------------------------
// resets HUD and jump destination
this.$resetViews = function $resetViews() {
if (this._suspendedHUD !== false) {
player.ship.hudHidden = false;
this._suspendedHUD = false;
}
if (this._suspendedDestination !== null) {
player.ship.targetSystem = this._suspendedDestination;
this._suspendedDestination = null;
}
}
//-------------------------------------------------------------------------------------------------------------
// initialise a new smuggling contract list for the current system
this.$initialiseSmugglingContractsForSystem = function $initialiseSmugglingContractsForSystem() {
// clear list
this._contracts = [];
var checklist = [];
var si = worldScripts.Smugglers_Illegal;
var destlist = [];
if (si._illegalGoods.length > 0) {
for (var i = 0; i < si._illegalGoods.length; i++) {
if (destlist.indexOf(si._illegalGoods[i].systemID) === -1)
destlist.push(si._illegalGoods[i].systemID);
}
} else {
// no illegal goods defined - shouldn't happen, but just in case
return;
}
var numContracts = Math.floor(5 * Math.random() + 5 * Math.random() + 5 * Math.random() + (this.$getSmugglingReputationPrecise() * Math.random()));
if (this.$getSmugglingReputationPrecise() >= 0 && numContracts < 5) {
numContracts += 5;
}
if (numContracts > 16) {
numContracts = 16;
} else if (numContracts < 0) {
numContracts = 0;
}
for (var i = 0; i < numContracts; i++) {
var cargo = new Object;
// pick a random system to take the goods to
var destination = destlist[this.$rand(destlist.length) - 1];
// discard if chose the current system
if (destination === system.ID) continue;
if (typeof destination === "undefined") continue;
// get the SystemInfo object for the destination
var destinationInfo = System.infoForSystem(galaxyNumber, destination);
if (destinationInfo.sun_gone_nova) continue;
var daysUntilDeparture = 1 + (Math.random() * (7 + this.$getSmugglingReputationPrecise() - destinationInfo.government));
if (daysUntilDeparture <= 0) {
// loses some more contracts if reputation negative
continue;
}
var commodities = si.$illegalGoodsListCommodityOnly(destination, true);
var attempts = 0;
do {
var remotePrice = 0;
attempts++;
var commodity = commodities[Math.floor(Math.random() * commodities.length)];
// sub-tc contracts only available for top rep
if (system.mainStation.market[commodity]["quantity_unit"] != 0 && this.$getSmugglingReputationPrecise() < 6.5) {
} else {
remotePrice = this.$priceForCommodity(commodity, destinationInfo);
}
//log(this.name, "contract " + i + "--attempt " + attempts + ": " + commodity + " remoteprice = " + remotePrice + ", sourcepriceadj = " + system.mainStation.market[commodity].price / 20);
} while (remotePrice < system.mainStation.market[commodity].price / 20 && attempts < 10);
// failed to find a good one.
if (attempts === 10) continue;
// don't overload the player with all the same type of contracts
var checkcount = 0;
for (var j = 0; j < checklist.length; j++) {
if (checklist[j] === commodity) checkcount += 1;
}
if (checkcount >= 3) continue;
cargo.commodity = commodity;
var amount = 0;
// larger unit sizes for kg/g commodities
switch (parseInt(system.mainStation.market[commodity]["quantity_unit"])) {
case 1:
amount = this.$rand(20) + 10;
break;
case 2:
amount = this.$rand(40) + 20;
break;
case 0:
amount = this.$rand(10);
if (amount > 5 && Math.random() > 0.5) amount += (this.$rand(5) - 3);
break;
}
cargo.size = amount;
// adjustment to prices based on quantity (larger = more profitable)
var discount = Math.min(10 + Math.floor(amount / 10), 35);
var unitPrice = system.mainStation.market[commodity].price * (100 - discount) / 1000;
var localValue = Math.floor(unitPrice * amount);
remotePrice = remotePrice * (200 + discount) / 200;
var remoteValue = Math.floor(remotePrice * amount);
var profit = remoteValue - localValue;
// skip if unprofitable
if (profit <= 100) continue;
// check that a route to the destination exists
// route calculation is expensive so leave this check to last
var routeToDestination = system.info.routeToSystem(destinationInfo);
// if the system cannot be reached, ignore this contract
if (!routeToDestination) continue;
// we now have a valid destination, so generate the rest of
// the parcel details
cargo.destination = destination;
// we'll need this again later, and route calculation is slow
cargo.route = routeToDestination;
// higher share for transporter for longer routes, less safe systems
var share = 100 + destinationInfo.government - (10 * routeToDestination.route.length);
if (share < 10) share = 10;
share = 100 - share;
// safety: now multiply the fee by 2 compared with 1.76 contracts
// prevents exploit discovered by Mad Hollander at
// http://bb.oolite.space/viewtopic.php?p=188127
localValue *= 2;
// this may need to be raised further
// absolute value of profit remains the same
var fee = (localValue + Math.floor(profit * (share / 100))) * 2;
fee -= fee % 20; // round to nearest 20 credits;
cargo.payment = fee;
cargo.deposit = localValue - (localValue % 20);
// rare but not impossible; last safety check
if (cargo.deposit >= cargo.payment) continue;
// time allowed for delivery is time taken by "fewest jumps"
// route, plus timer above. Higher reputation makes longer
// times available.
cargo.deadline = clock.adjustedSeconds + Math.floor(daysUntilDeparture * 86400) + (cargo.route.time * 3600);
// make sure the illegal good will be illegal when the player arrives, based on the route time
var def = si.$illegalGoodsDefinition(destination, commodity);
if (def && def.end < cargo.deadline) continue;
// add it to the check list so we can make sure we don't offer too many of the same type of contract
checklist.push(commodity);
// add parcel to contract list
this.$addSmugglingContractToSystem(cargo);
}
}
//-------------------------------------------------------------------------------------------------------------
// if the interface is activated, this function is run.
this.$smugglingContractsScreens = function $smugglingContractsScreens(interfaceKey) {
// the interfaceKey parameter is not used here, but would be useful if
// this callback managed more than one interface entry
this.$validateSmugglingContracts();
// set up variables used to remember state on the mission screens
this._suspendedDestination = null;
this._suspendedHUD = false;
this._contractIndex = 0;
this._routeMode = "LONG_RANGE_CHART_SHORTEST";
this._lastOptionChosen = "06_EXIT";
// start on the summary page if more than one contract is available
var summary = (this._contracts.length > 1);
this.$smugglingContractsDisplay(summary);
}
//-------------------------------------------------------------------------------------------------------------
// this function is called after the player makes a choice which keeps
// them in the system, and also on initial entry to the system
// to select the appropriate mission screen and display it
this.$smugglingContractsDisplay = function $smugglingContractsDisplay(summary) {
// Again. Has to be done on every call to this function, but also
// has to be done at the start.
this.$validateSmugglingContracts();
// if there are no contracts (usually because the player has taken
// the last one) display a message and quit.
if (this._contracts.length === 0) {
var missionConfig = {
titleKey: "smuggling-contracts-none-available-title",
messageKey: "smuggling-contracts-none-available-message",
allowInterrupt: true,
screenID: "oolite-smuggling-contracts-none",
exitScreen: "GUI_SCREEN_INTERFACES"
};
if (this._smugglingSummaryPageBackground != "") {
missionConfig.background = this._smugglingSummaryPageBackground;
}
if (this._smugglingPageOverlay != "") {
if (this._smugglingPageOverlayHeight != 0) {
missionConfig.overlay = {
name: this._smugglingPageOverlay,
height: this._smugglingPageOverlayHeight
};
} else {
missionConfig.overlay = this._smugglingPageOverlay;
}
}
mission.runScreen(missionConfig);
// no callback, just exits contracts system
return;
}
// make sure that the 'currently selected contract' pointer
// is in bounds
if (this._contractIndex >= this._contracts.length) {
this._contractIndex = 0;
} else if (this._contractIndex < 0) {
this._contractIndex = this._contracts.length - 1;
}
// sub functions display either summary or detail screens
if (summary) {
this.$smugglingContractSummaryPage();
} else {
this.$smugglingContractSinglePage();
}
}
//-------------------------------------------------------------------------------------------------------------
// display the mission screen for the summary page
this.$smugglingContractSummaryPage = function $smugglingContractSummaryPage() {
var playerrep = this._helper._playerSkill(this.$getSmugglingReputationPrecise());
// column 'tab stops'
var columns = [9, 15, 21, 26];
var anyWithSpace = false;
// column header line
var headline = expandMissionText("smuggling-contracts-column-goods");
// pad to correct length to give a table-like layout
headline += this._helper._paddingText(headline, columns[0]);
headline += expandMissionText("smuggling-contracts-column-destination");
headline += this._helper._paddingText(headline, columns[1]);
headline += expandMissionText("smuggling-contracts-column-within");
headline += this._helper._paddingText(headline, columns[2]);
headline += expandMissionText("smuggling-contracts-column-deposit");
headline += this._helper._paddingText(headline, columns[3]);
headline += expandMissionText("smuggling-contracts-column-fee");
// required because of way choices are displayed.
headline = " " + headline;
// setting options dynamically; one contract per line
var options = new Object;
var i;
for (i = 0; i < this._contracts.length; i++) {
// temp variable to simplify following code
var cargo = this._contracts[i];
// write the description, padded to line up with the headers
var optionText = this.$descriptionForGoods(cargo);
optionText += this._helper._paddingText(optionText, columns[0]);
optionText += System.infoForSystem(galaxyNumber, cargo.destination).name;
optionText += this._helper._paddingText(optionText, columns[1]);
optionText += this._helper._timeRemaining(cargo);
optionText += this._helper._paddingText(optionText, columns[2]);
// right-align the fee so that the credits signs line up
var priceText = formatCredits(cargo.deposit, false, true);
priceText = this._helper._paddingText(priceText, 3.5) + priceText;
optionText += priceText
optionText += this._helper._paddingText(optionText, columns[3]);
// right-align the fee so that the credits signs line up
priceText = formatCredits(cargo.payment - cargo.deposit, false, true);
priceText = this._helper._paddingText(priceText, 3.5) + priceText;
optionText += priceText
// need to pad the number in the key to maintain alphabetical order
var istr = i;
if (i < 10) {
istr = "0" + i;
}
// needs to be aligned left to line up with the heading
options["01_CONTRACT_" + istr] = {
text: optionText,
alignment: "LEFT"
};
// check if there's space for this contract
if (!this.$hasSpaceFor(cargo)) {
options["01_CONTRACT_" + istr].color = "darkGrayColor";
} else {
anyWithSpace = true;
// if there doesn't appear to be sufficient time remaining
if (this._helper._timeRemainingSeconds(cargo) < this._helper._timeEstimateSeconds(cargo)) {
options["01_CONTRACT_" + istr].color = "orangeColor";
}
}
}
// if we've come from the detail screen, make sure the last
// contract shown there is selected here
var icstr = this._contractIndex;
if (icstr < 10) icstr = "0" + this._contractIndex;
var initialChoice = "01_CONTRACT_" + icstr;
// if none of them have any space...
if (!anyWithSpace) initialChoice = "06_EXIT";
// next, an empty string gives an unselectable row
options["02_SPACER"] = "";
// now need to add further spacing to fill the remaining rows, or
// the options will end up at the bottom of the screen.
var rowsToFill = 21;
if (player.ship.hudHidden || this.$isBigGuiActive() === true) rowsToFill = 27;
for (i = 4 + this._contracts.length; i < rowsToFill; i++) {
// each key needs to be unique at this stage.
options["07_SPACER_" + i] = "";
}
// numbered 06 to match the option of the same function in the other branch
options["06_EXIT"] = expandMissionText("smuggling-contracts-command-quit");
var missionConfig = {
titleKey: "smuggling-contracts-title-summary",
message: headline,
allowInterrupt: true,
screenID: "oolite-smuggling-contracts-summary",
exitScreen: "GUI_SCREEN_INTERFACES",
choices: options,
initialChoicesKey: initialChoice
};
if (this._smugglingSummaryPageBackground != "") {
missionConfig.background = this._smugglingSummaryPageBackground;
}
if (this._smugglingPageOverlay != "") {
if (this._smugglingPageOverlayHeight != 0) {
missionConfig.overlay = {
name: this._smugglingPageOverlay,
height: this._smugglingPageOverlayHeight
};
} else {
missionConfig.overlay = this._smugglingPageOverlay;
}
}
// now run the mission screen
mission.runScreen(missionConfig, this.$processSmugglingChoice, this);
}
//-------------------------------------------------------------------------------------------------------------
// display the mission screen for the contract detail page
this.$smugglingContractSinglePage = function $smugglingContractSinglePage() {
var playerrep = this._helper._playerSkill(this.$getSmugglingReputationPrecise());
// temp variable to simplify code
var cargo = this._contracts[this._contractIndex];
// This mission screen uses the long range chart as a backdrop.
// This means that the first 18 lines are taken up by the chart,
// and we can't put text there without overwriting the chart.
// We therefore need to hide the player's HUD, to get the full 27
// lines.
if (!player.ship.hudHidden && this.$isBigGuiActive() === false) {
this._suspendedHUD = true; // note that we hid it, for later
player.ship.hudHidden = true;
}
// We also set the player's witchspace destination temporarily
// so we need to store the old one in a variable to reset it later
this._suspendedDestination = player.ship.targetSystem;
// That done, we can set the player's destination so the map looks
// right.
player.ship.targetSystem = cargo.destination;
// start with 18 blank lines, since we don't want to overlap the chart
var message = new Array(18).join("\n");
message += expandMissionText("smuggling-contracts-long-description", {
"smuggling-contracts-longdesc-goods": this.$descriptionForGoods(cargo),
"smuggling-contracts-longdesc-destination": this._helper._systemName(cargo.destination),
"smuggling-contracts-longdesc-deadline": this._helper._timeRemaining(cargo),
"smuggling-contracts-longdesc-time": this._helper._timeEstimate(cargo),
"smuggling-contracts-longdesc-payment": formatCredits(cargo.payment, false, true),
"smuggling-contracts-longdesc-deposit": formatCredits(cargo.deposit, false, true)
});
// use a special background
var backgroundSpecial = "LONG_RANGE_CHART";
// the available options will vary quite a bit, so this rather
// than a choicesKey in missiontext.plist
var options = new Object;
// this is the only option which is always available
options["06_EXIT"] = expandMissionText("smuggling-contracts-command-quit");
// if the player has sufficient space
if (this.$hasSpaceFor(cargo)) {
options["05_ACCEPT"] = {
text: expandMissionText("smuggling-contracts-command-accept")
};
// if there's not much time left, change the option colour as a warning!
if (this._helper._timeRemainingSeconds(cargo) < this._helper._timeEstimateSeconds(cargo)) {
options["05_ACCEPT"].color = "orangeColor";
}
} else {
options["05_UNAVAILABLE"] = {
text: expandMissionText("smuggling-contracts-command-unavailable"),
color: "darkGrayColor",
unselectable: true
};
}
// if the ship has a working advanced nav array, can switch
// between 'quickest' and 'shortest' routes
// (and also upgrade the special background)
if (player.ship.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY")) {
backgroundSpecial = this._routeMode;
if (this._routeMode === "LONG_RANGE_CHART_SHORTEST") {
options["01_MODE"] = expandMissionText("smuggling-contracts-command-ana-quickest");
} else {
options["01_MODE"] = expandMissionText("smuggling-contracts-command-ana-shortest");
}
}
// if there's more than one, need options for forward, back, and listing
if (this._contracts.length > 1) {
options["02_BACK"] = expandMissionText("smuggling-contracts-command-back");
options["03_NEXT"] = expandMissionText("smuggling-contracts-command-next");
options["04_LIST"] = expandMissionText("smuggling-contracts-command-list");
} else {
// if not, we may need to set a different choice
// we never want 05_ACCEPT to end up selected initially
if (this._lastChoice === "02_BACK" || this._lastChoice === "03_NEXT" || this._lastChoice === "04_LIST") {
this._lastChoice = "06_EXIT";
}
}
var title = expandMissionText("smuggling-contracts-title-detail", {
"smuggling-contracts-title-detail-number": this._contractIndex + 1,
"smuggling-contracts-title-detail-total": this._contracts.length
});
// finally, after all that setup, actually create the mission screen
var missionConfig = {
title: title,
message: message,
allowInterrupt: true,
screenID: "oolite-smuggling-contracts-details",
exitScreen: "GUI_SCREEN_INTERFACES",
backgroundSpecial: backgroundSpecial,
choices: options,
initialChoicesKey: this._lastChoice
};
if (this._smugglingPageOverlay != "") {
if (this._smugglingPageOverlayHeight != 0) {
missionConfig.overlay = {
name: this._smugglingPageOverlay,
height: this._smugglingPageOverlayHeight
};
} else {
missionConfig.overlay = this._smugglingPageOverlay;
}
}
mission.runScreen(missionConfig, this.$processSmugglingChoice, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$processSmugglingChoice = function $processSmugglingChoice(choice) {
this.$resetViews();
// can occur if ship launches mid mission screen
if (choice == null) return;
// now process the various choices
if (choice.match(/^01_CONTRACT_/)) {
// contract selected from summary page
// set the index to that contract, and show details
var index = parseInt(choice.slice(12), 10);
this._contractIndex = index;
this._lastChoice = "04_LIST";
this.$smugglingContractsDisplay(false);
} else if (choice === "01_MODE") {
// advanced navigation array mode flip
this._routeMode = (this._routeMode === "LONG_RANGE_CHART_SHORTEST") ? "LONG_RANGE_CHART_QUICKEST" : "LONG_RANGE_CHART_SHORTEST";
this._lastChoice = "01_MODE";
this.$smugglingContractsDisplay(false);
} else if (choice === "02_BACK") {
// reduce contract index (parcelContractsDisplay manages wraparound)
this._contractIndex--;
this._lastChoice = "02_BACK";
this.$smugglingContractsDisplay(false);
} else if (choice === "03_NEXT") {
// increase contract index (parcelContractsDisplay manages wraparound)
this._contractIndex++;
this._lastChoice = "03_NEXT";
this.$smugglingContractsDisplay(false);
} else if (choice === "04_LIST") {
// display the summary page
this.$smugglingContractsDisplay(true);
} else if (choice === "05_ACCEPT") {
this.$acceptContract();
// do not leave the setting as accept for the next contract!
this._lastChoice = "03_NEXT";
this.$smugglingContractsDisplay(false);
}
// if we get this far without having called smugglingContractsDisplay
// that means either 'exit' or an unrecognised option was chosen
if (choice === "06_EXIT") {
var sbm = worldScripts.Smugglers_BlackMarket;
sbm.$initialBlackMarket();
}
}
//-------------------------------------------------------------------------------------------------------------
// move goods from the contracts list to the player's ship (if possible)
this.$acceptContract = function $acceptContract() {
var cargo = this._contracts[this._contractIndex];
if (cargo.deposit > player.credits) {
this._helper._soundFailure();
return;
}
// give the cargo to the player
var result = this.$awardContract(cargo.size, cargo.commodity, system.ID, cargo.destination, cargo.deadline, cargo.payment, cargo.deposit, cargo.route);
if (result) {
// pay the deposit
player.credits -= cargo.deposit;
// give the player the merchandise
player.ship.manifest[cargo.commodity] += cargo.size;
mission.markSystem({
system: cargo.destination,
name: "smuggling_contract_" + cargo.destination,
markerShape: "MARKER_PLUS"
});
// remove the contract from the station list
this._contracts.splice(this._contractIndex, 1);
this._helper._soundSuccess();
} else {
// else must have had manifest change recently
// (unlikely, but another OXP could have done it)
this._helper._soundFailure();
}
}
//-------------------------------------------------------------------------------------------------------------
// store the contract
this.$awardContract = function $awardContract(quantity, commodity, source, destination, deadline, payment, deposit, route) {
var cargo = {};
cargo.size = quantity;
cargo.commodity = commodity;
cargo.start = source;
cargo.startName = System.systemNameForID(source);
cargo.destination = destination;
cargo.destinationName = System.systemNameForID(destination);
cargo.deadline = deadline;
cargo.fee = payment;
cargo.premium = deposit;
cargo.route = route;
this._smugglingContracts.push(cargo);
this.$contractStartedEmail(cargo);
return true;
}
//-------------------------------------------------------------------------------------------------------------
// removes any expired parcels
this.$validateSmugglingContracts = function $validateSmugglingContracts() {
var c = this._contracts.length - 1;
var removed = false;
// iterate downwards so we can safely remove as we go
for (var i = c; i >= 0; i--) {
// if the time remaining is less than 1/3 of the estimated
// delivery time, even in the best case it's probably not
// going to get there.
if (this._helper._timeRemainingSeconds(this._contracts[i]) < this._helper._timeEstimateSeconds(this._contracts[i]) / 3) {
if (worldScripts.ContractsOnBB) {
worldScripts.ContractsOnBB.$reindexContracts(34000, i);
}
// remove it
this._contracts.splice(i, 1);
removed = true;
}
}
}
//=============================================================================================================
/* Utility functions */
//-------------------------------------------------------------------------------------------------------------
// lower-cases the initial letter of the package contents
this.$formatPackageName = function $formatPackageName(name) {
return name.charAt(0).toLowerCase() + name.slice(1);
}
//-------------------------------------------------------------------------------------------------------------
// calculates a sample price for a commodity in a distant system
this.$priceForCommodity = function $priceForCommodity(commodity, systeminfo) {
//sample price returns decicredits, need credits
var si = worldScripts.Smugglers_Illegal;
var goods = si.$illegalGoodsListCommodityOnly(systeminfo.systemID);
if (goods.indexOf(commodity) >= 0) {
//return Math.round((si._commodityInfo[commodity][1] - (Math.random() * 15)), 2)
return (systeminfo.samplePrice(commodity) * si._commodityInfo[commodity][1]) / 10;
} else {
return systeminfo.samplePrice(commodity) / 10;
}
}
//-------------------------------------------------------------------------------------------------------------
// description of the cargo
this.$descriptionForGoods = function $descriptionForGoods(cargo) {
var unit = expandMissionText("smuggling_tons");
var stn = system.mainStation;
if (!stn && system.stations.length > 0) stn = system.stations[0];
if (!stn) return "";
if (stn.market[cargo.commodity]["quantity_unit"] === "1") {
unit = expandMissionText("smuggling_kilos");
} else if (stn.market[cargo.commodity]["quantity_unit"] === "2") {
unit = expandMissionText("smuggling_grams");
}
return cargo.size + expandDescription("[cargo-" + unit + "-symbol]") + " " + displayNameForCommodity(cargo.commodity);
}
//-------------------------------------------------------------------------------------------------------------
// check if player's ship has space for the cargo and can afford the deposit
this.$hasSpaceFor = function $hasSpaceFor(cargo) {
if (cargo.deposit > player.credits) {
return false;
}
var amountInTC = cargo.size;
if (system.mainStation.market[cargo.commodity]["quantity_unit"] === "1") {
var spareSafe = 499 - (player.ship.manifest[cargo.commodity] % 1000);
amountInTC -= spareSafe;
amountInTC = Math.ceil(amountInTC / 1000);
if (amountInTC < 0) {
amountInTC = 0;
}
} else if (system.mainStation.market[cargo.commodity]["quantity_unit"] === "2") {
var spareSafe = 499999 - (player.ship.manifest[cargo.commodity] % 1000000);
amountInTC -= spareSafe;
amountInTC = Math.ceil(amountInTC / 1000000);
if (amountInTC < 0) {
amountInTC = 0;
}
}
return (amountInTC <= player.ship.cargoSpaceAvailable);
}
//-------------------------------------------------------------------------------------------------------------
// returns true if another contracts exists for the given system ID, otherwise false
this.$anyContractsLeftForSystem = function $anyContractsLeftForSystem(idx_ignore, sysID) {
for (var i = 0; i < this._smugglingContracts.length; i++) {
if (i != idx_ignore && this._smugglingContracts[i].destination === sysID) return true;
}
return false;
}
//-------------------------------------------------------------------------------------------------------------
// update the manifest screen with any contracts
this.$updateManifest = function $updateManifest() {
// don't try an update in interstellar space
if (system.isInterstellarSpace) return;
if (this._smugglingContracts.length > 0) {
var list = [];
list.push(expandMissionText("smuggling-contracts-title-summary") + ":");
for (var i = 0; i < this._smugglingContracts.length; i++) {
var cargo = this._smugglingContracts[i];
var message = expandMissionText("smuggling-contracts-long-descr-manifest", {
"smuggling-contracts-longdesc-goods": this.$descriptionForGoods(cargo),
"smuggling-contracts-longdesc-destination": cargo.destinationName,
"smuggling-contracts-longdesc-deadline": this.$formatTravelTime(this._helper._timeRemainingSeconds(cargo)),
"smuggling-contracts-longdesc-time": this._helper._timeEstimate(cargo),
"smuggling-contracts-longdesc-payment": formatCredits(cargo.fee, false, true),
"smuggling-contracts-longdesc-deposit": formatCredits(cargo.deposit, false, true)
});
list.push(message);
}
mission.setInstructions(list, this.name);
} else {
mission.setInstructions(null, this.name);
}
}
//=============================================================================================================
// Smuggling reputation functions
// essentially a JS recreation of the same rep functions in core code to give the player a separate reputation for smuggling
//-------------------------------------------------------------------------------------------------------------
this.$getSmugglingReputation = function $getSmugglingReputation() {
return parseInt(this.$smugglingReputation() / 10);
}
//-------------------------------------------------------------------------------------------------------------
this.$getSmugglingReputationPrecise = function $getSmugglingReputationPrecise() {
return this.$smugglingReputation() / 10;
}
//-------------------------------------------------------------------------------------------------------------
this.$smugglingReputation = function $smugglingReputation() {
var good = this._smugglingRepGood;
var bad = this._smugglingRepBad;
var unknown = this._smugglingRepUnknown;
if (unknown > 0) {
unknown = this._maxRep - (((2 * unknown) + (this._marketrnd % unknown)) / 3);
} else {
unknown = this._maxRep;
}
return (good + unknown - 3 * bad) / 2;
}
//-------------------------------------------------------------------------------------------------------------
this.$decreaseSmugglingReputation = function $decreaseSmugglingReputation(amount) {
var good = this._smugglingRepGood;
var bad = this._smugglingRepBad;
var unknown = this._smugglingRepUnknown;
for (var i = 0; i < amount; i++) {
if (good > 0) {
// shift a bean from good to bad
good--;
if (bad < this._maxRep) bad++;
} else {
// shift a bean from unknown to bad
if (unknown > 0) unknown--;
if (bad < this._maxRep) bad++;
}
}
this._smugglingRepGood = good;
this._smugglingRepBad = bad;
this._smugglingRepUnknown = unknown;
}
//-------------------------------------------------------------------------------------------------------------
this.$increaseSmugglingReputation = function $increaseSmugglingReputation(amount) {
var good = this._smugglingRepGood;
var bad = this._smugglignRepBad;
var unknown = this._smugglingRepUnknown;
for (var i = 0; i < amount; i++) {
if (bad > 0) {
// shift a bean from bad to unknown
bad--;
if (unknown < this._maxRep) unknown++;
} else {
// shift a bean from unknown to good
if (unknown > 0) unknown--;
if (good < this._maxRep) good++;
}
}
this._smugglingRepGood = good;
this._smugglingRepBad = bad;
this._smugglingRepUnknown = unknown;
}
//-------------------------------------------------------------------------------------------------------------
this.$erodeSmugglingReputation = function $erodeSmugglingReputation() {
var good = this._smugglingRepGood;
var bad = this._smugglingRepBad;
var unknown = this._smugglingRepUnknown;
if (unknown < this._maxRep) {
if (bad > 0) {
bad--;
} else {
if (good > 0) good--;
}
unknown++;
}
this._smugglingRepGood = good;
this._smugglingRepBad = bad;
this._smugglingRepUnknown = unknown;
}
//-------------------------------------------------------------------------------------------------------------
this.$normaliseSmugglingReputation = function $normaliseSmugglingReputation() {
var good = this._smugglingRepGood;
var bad = this._smugglingRepBad;
var unknown = this._smugglingRepUnknown;
var c = good + bad + unknown;
if (c === 0) {
unknown = this._maxRep;
} else if (c != this._maxRep) {
good = good * this._maxRep / c;
bad = bad * this._maxRep / c;
unknown = this._maxRep - good - bad;
}
this._smugglingRepGood = good;
this._smugglingRepBad = bad;
this._smugglingRepUnknown = unknown;
}
//-------------------------------------------------------------------------------------------------------------
// format the travel time
this.$formatTravelTime = function $formatTravelTime(seconds) {
// this function uses an hours-only format
// but provides enough information to use a days&hours format if
// oolite-contracts-time-format in missiontext.plist is overridden
// extra minutes are discarded
var hours = Math.floor(seconds / 3600);
var days = Math.floor(hours / 24);
var spareHours = hours % 24;
return expandMissionText("smuggling-time-format", {
"smuggling-time-format-hours": hours,
"smuggling-time-format-days": days,
"smuggling-time-format-spare-hours": spareHours
});
}
//-------------------------------------------------------------------------------------------------------------
// routine to zero out quantities of any illegal goods under contract
// so if the player arrives short, he can't just buy one, launch, redock and complete the contract
this.$adjustMarket = function $adjustMarket() {
var stn = system.mainStation;
if (stn) {
for (var i = this._smugglingContracts.length - 1; i >= 0; i--) {
var m = this._smugglingContracts[i];
// are we in the right system
if (m.destination === system.ID && m.destinationName === system.name) {
// set the market quantity to zero
stn.setMarketQuantity(m.commodity, 0);
}
}
}
}
//-------------------------------------------------------------------------------------------------------------
// send email to player when a contract is started. (1.81 only)
this.$contractStartedEmail = function $contractStartedEmail(contract) {
var w = worldScripts.EmailSystem;
if (!w) return;
var ga = worldScripts.GalCopAdminServices;
if (ga._disableContracts === true) return;
var msg = "";
var subj = "";
var sndr = "";
sndr = expandDescription("[smuggling-contract-sender]");
subj = expandMissionText("smuggling_accepted_contract") + ": " + this.$descriptionForGoods(contract);
msg = expandDescription("[smuggling-contract-start]", {
description: this.$descriptionForGoods(contract),
systemname: System.systemNameForID(contract.destination),
time: global.clock.clockStringForTime(contract.deadline),
fee: contract.fee.toFixed(2)
});
w.$createEmail({
sender: sndr,
subject: subj,
date: global.clock.seconds,
message: msg
});
}
//-------------------------------------------------------------------------------------------------------------
this.$contractCompletedEmail = function $contractCompletedEmail(result, fee, contract) {
var w = worldScripts.EmailSystem;
if (!w) return;
var ga = worldScripts.GalCopAdminServices;
if (ga._disableContracts === true) return;
var msg = "";
var subj = "";
var sndr = "";
sndr = expandDescription("[smuggling-contract-sender]");
msg = expandDescription("[smuggling-contract-" + result + "]", {
description: this.$descriptionForGoods(contract),
systemname: System.systemNameForID(contract.destination),
time: global.clock.clockStringForTime(contract.deadline),
fee: (fee / 10).toFixed(2)
});
subj = expandDescription("[smuggling-contract-" + result + "-subject]");
w.$createEmail({
sender: sndr,
subject: subj,
date: global.clock.seconds,
message: msg,
expiryDays: ga._defaultExpiryDays
});
} |
Scripts/smugglers_corefunctions.js |
"use strict";
this.name = "Smugglers_CoreFunctions";
this.author = "phkb";
this.description = "Holds common functions used across all routines";
this.licence = "CC BY-NC-SA 3.0";
//-------------------------------------------------------------------------------------------------------------
// returns true if a HUD with allowBigGUI is enabled, otherwise false
this.$isBigGuiActive = function $isBigGuiActive() {
if (oolite.compareVersion("1.83") <= 0) {
return player.ship.hudAllowsBigGui;
} else {
var bigGuiHUD = ["XenonHUD.plist", "coluber_hud_ch01-dock.plist"]; // until there is a property we can check, I'll be listing HUD's that have the allow_big_gui property set here
if (bigGuiHUD.indexOf(player.ship.hud) >= 0) {
return true;
} else {
return false;
}
}
}
//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padTextRight = function $padTextRight(currentText, desiredLength, leftSwitch) {
if (currentText == null) currentText = "";
var hairSpace = String.fromCharCode(31);
var ellip = "…";
var currentLength = defaultFont.measureString(currentText);
var hairSpaceLength = defaultFont.measureString(hairSpace);
// calculate number needed to fill remaining length
var padsNeeded = Math.floor((desiredLength - currentLength) / hairSpaceLength);
if (padsNeeded < 1) {
// text is too long for column, so start pulling characters off
var tmp = currentText;
do {
tmp = tmp.substring(0, tmp.length - 2) + ellip;
if (tmp === ellip) break;
} while (defaultFont.measureString(tmp) > desiredLength);
currentLength = defaultFont.measureString(tmp);
padsNeeded = Math.floor((desiredLength - currentLength) / hairSpaceLength);
currentText = tmp;
}
// quick way of generating a repeated string of that number
if (!leftSwitch || leftSwitch === false) {
return currentText + new Array(padsNeeded).join(hairSpace);
} else {
return new Array(padsNeeded).join(hairSpace) + currentText;
}
}
//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padTextLeft = function $padTextLeft(currentText, desiredLength) {
return this.$padTextRight(currentText, desiredLength, true);
}
//-------------------------------------------------------------------------------------------------------------
// return a random number between 1 and max
this.$rand = function $rand(max) {
return Math.floor((Math.random() * max) + 1)
} |
Scripts/smugglers_dockmaster.js |
"use strict";
this.name = "Smugglers_DockMaster";
this.author = "phkb";
this.description = "Looks after the Dock Master interface screen.";
this.licence = "CC BY-NC-SA 3.0";
this._disabled = false;
this._debug = true;
this._bribeChance = []; // holds the chance a each dock master can be bribed
this._cargoLabelled = []; // array of original commodity and quantities, and new labels
// {oldCommodity: name, newCommodity: name, quantity: number of tons relabelled
this._bribeAttempted = false;
this._dockMasterStartTime = 0;
this._dockMasterEndTime = 0;
this._noSwitch = []; // these commodities can't be relabelled - populated through the smugglers_equipment.startUpComplete function
this._display = 0;
this._milkRuns = [];
this._successfulBribes = [];
this._cargoAtLaunch = [];
this._bribeCount = [];
this._menuColor = "orangeColor";
this._itemColor = "yellowColor";
this._disabledColor = "darkGrayColor";
this._galJump = false;
this._destReleaseCount = 0;
this._flagged = [];
this._curPage = 0;
this._marker = {};
//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
if (this._disabled) {
delete this.shipDockedWithStation;
delete this.shipLaunchedFromStation;
delete this.playerWillSaveGame;
delete this.shipExitedWitchspace;
delete this.playerEnteredNewGalaxy;
delete this.shipSpawned;
delete this.shipTakingDamage;
delete this.playerSoldCargo;
delete this.startUpComplete;
delete this.guiScreenChanged;
return;
}
// add a mission screen exception to Xenon UI
if (worldScripts.XenonUI) {
var wx = worldScripts.XenonUI;
wx.$addMissionScreenException("oolite-smuggling-dockmaster-milkrun");
}
// add a mission screen exception to Xenon Redux UI
if (worldScripts.XenonReduxUI) {
var wxr = worldScripts.XenonReduxUI;
wxr.$addMissionScreenException("oolite-smuggling-dockmaster-milkrun");
}
var core = worldScripts.Smugglers_CoreFunctions;
this.$padTextRight = core.$padTextRight;
this.$padTextLeft = core.$padTextLeft;
this.$isBigGuiActive = core.$isBigGuiActive;
this.$rand = core.$rand;
this.$getMilkRuns();
if (missionVariables.Smuggling_BribeChance) {
this._bribeChance = JSON.parse(missionVariables.Smuggling_BribeChance);
delete missionVariables.Smuggling_BribeChance;
} else {
this.$setupChance();
}
if (missionVariables.Smuggling_Relabels) {
this._cargoLabelled = JSON.parse(missionVariables.Smuggling_Relabels);
delete missionVariables.Smuggling_Relabels;
}
if (missionVariables.Smuggling_SuccessfulBribes) {
this._successfulBribes = JSON.parse(missionVariables.Smuggling_SuccessfulBribes);
delete missionVariables.Smuggling_SuccessfulBribes;
}
if (missionVariables.Smuggling_BribeAttempted) this._bribeAttemped = (missionVariables.Smuggling_BribeAttemped === 1 ? true : false);
if (missionVariables.Smuggling_DockMasterStartTime) {
this._dockMasterStartTime = missionVariables.Smuggling_DockMasterStartTime;
this._dockMasterEndTime = missionVariables.Smuggling_DockMasterEndTime;
} else {
this.$setDockMasterHours();
}
if (missionVariables.Smuggling_BribeCount) {
this._bribeCount = JSON.parse(missionVariables.Smuggling_BribeCount);
delete missionVariables.Smuggling_BribeCount;
} else {
this.$resetBribeCount();
}
if (missionVariables.Smuggling_DockMasterFlagged) {
this._flagged = JSON.parse(missionVariables.Smuggling_DockMasterFlagged);
delete missionVariables.Smuggling_DockMasterFlagged;
}
if (missionVariables.Smuggling_DockMasterUnlockCount) {
this._destReleaseCount = missionVariables.Smuggling_DockMasterUnlockCount;
delete missionVariables.Smuggling_DockMasterUnlockCount;
}
// set up the interface screen, if required
this.$initMainInterface(player.ship.dockedStation);
if (this._cargoLabelled.length > 0) {
this.$initUnlabelInterface(player.ship.dockedStation);
}
// upgraded features in v1.84
if (0 < oolite.compareVersion("1.84")) {
delete this.shipDumpedCargo;
} else {
delete this.shipSpawned;
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipDockedWithStation = function (station) {
// set up dock master interface screen
this.$initMainInterface(station);
if (this._cargoLabelled.length > 0) {
this.$initUnlabelInterface(station);
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipLaunchedFromStation = function (station) {
if (missionVariables.Smuggling_BribeChance) delete missionVariables.Smuggling_BribeChance;
if (missionVariables.Smuggling_Relabels) delete missionVariables.Smuggling_Relabels;
if (missionVariables.Smuggling_SuccessfulBribes) delete missionVariables.Smuggling_SuccessfulBribes;
if (missionVariables.Smuggling_BribeCount) delete missionVariables.Smuggling_BribeCount;
var p = player.ship;
var m = p.manifest.list;
this._cargoAtLaunch = [];
// grab a snapshot of the cargo for comparison later
for (var i = 0; i < m.length; i++) {
if (m[i].quantity > 0) this._cargoAtLaunch.push({
commodity: m[i].commodity,
quantity: m[i].quantity
});
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
missionVariables.Smuggling_BribeChance = JSON.stringify(this._bribeChance);
missionVariables.Smuggling_Relabels = JSON.stringify(this._cargoLabelled);
missionVariables.Smuggling_SuccessfulBribes = JSON.stringify(this._successfulBribes);
missionVariables.Smuggling_BribeCount = JSON.stringify(this._bribeCount);
missionVariables.Smuggling_BribeAttempted = (this._bribeAttemped ? 1 : 0);
if (this._flagged.length > 0) {
missionVariables.Smuggling_DockMasterFlagged = JSON.stringify(this._flagged)
}
missionVariables.Smuggling_DockMasterUnlockCount = this._destReleaseCount;
}
//-------------------------------------------------------------------------------------------------------------
this.shipExitedWitchspace = function () {
this._bribeAttempted = false;
this._destReleaseCount = 0;
this._flagged = [];
this.$setDockMasterHours();
if (this._galJump === true) {
this._galJump = false;
this.$setupChance();
this.$getMilkRuns();
this.$resetBribeCount();
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerEnteredNewGalaxy = function (galaxyNumber) {
this._successfulBribes = [];
this._galJump = true;
}
//-------------------------------------------------------------------------------------------------------------
this.shipSpawned = function (ship) {
// did the player just dump relabelled cargo?
// if so, reduce the count in the array
// and unlabel the dumped cargo
var p = player.ship;
if (p && ship && ship.isCargo && ship.position && p.position && p.position.distanceTo(ship) < 300) {
//gotcha
var total = this.$getTotalRelabelled(ship.commodity);
if (p.manifest[ship.commodity] < total) {
for (var i = 0; i < this._cargoLabelled.length; i++) {
// find the first matching relabelled commodity and adjust it
if (this._cargoLabelled[i].newCommodity === ship.commodity && this._cargoLabelled[i].quantity > 0) {
this._cargoLabelled[i].quantity -= ship.commodityAmount;
var check = ship.setCargo(this._cargoLabelled[i].oldCommodity);
break;
}
}
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipDumpedCargo = function (cargo) {
var p = player.ship;
var total = this.$getTotalRelabelled(cargo.commodity);
if (p.manifest[cargo.commodity] < total) {
for (var i = 0; i < this._cargoLabelled.length; i++) {
// find the first matching relabelled commodity and adjust it
if (this._cargoLabelled[i].newCommodity === cargo.commodity && this._cargoLabelled[i].quantity > 0) {
this._cargoLabelled[i].quantity -= cargo.commodityAmount;
var check = ship.setCargo(this._cargoLabelled[i].oldCommodity);
break;
}
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipTakingDamage = function (dmg_amount, whom, type) {
// work out if the any of the relabelled cargo was destroyed
// if so, reduce the count in the array
// basically, relabelled cargo should be destroyed first
var p = player.ship;
var se = worldScripts.Smugglers_Equipment;
for (var i = 0; i < se._commodityIDList.length; i++) {
var holdamt = p.manifest[se._commodityIDList[i]];
var origamt = this.$launchAmount(se._commodityIDList[i]);
var amount = this.$getTotalRelabelled(se._commodityIDList[i]);
if (holdamt < origamt && amount > 0) {
// how many units do we have to remove?
var to_remove = (origamt - holdamt);
// find the first instance of a relabelled cargo
for (var j = 0; j < this._cargoLabelled.length; j++) {
if (this._cargoLabelled[j].quantity > 0 && to_remove > 0) {
// reduce the cargo by the removed amount
this._cargoLabelled[j].quantity -= to_remove;
// if we've just gone negative, we've wiped out all of that cargo batch
if (this._cargoLabelled[j].quantity < 0) {
// pick up the remainder
to_remove = this._cargoLabelled[j].quantity * -1;
// reset this one back to zero
this._cargoLabelled[j].quantity = 0;
}
}
}
}
}
}
//-------------------------------------------------------------------------------------------------------------
// if we scoop cargo make sure it gets added to the at_launch list
this.shipScoopedOther = function (whom) {
var si = worldScripts.Smugglers_Illegal;
var check = 0;
if (si._commodityInfo[whom.commodity]) {
check = si._commodityInfo[whom.commodity][0];
if (check > 0) {
var origamt = this.$launchAmount(whom.commodity);
if (origamt > 0) {
for (var i = 0; i < this._cargoAtLaunch.length; i++) {
if (this._cargoAtLaunch[i].commodity === whom.commodity) this._cargoAtLaunch[i].quantity += whom.commodityAmount;
}
} else {
this._cargoAtLaunch.push({
commodity: whom.commodity,
quantity: whom.commodityAmount
});
}
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerSoldCargo = function (commodity, units, price) {
// did the player just sell cargo that has been relabelled?
// if so, reverse the sale: add the relabelled units back, give the player their money back, and send a console message
var p = player.ship;
var relabelled_amount = this.$getTotalRelabelled(commodity);
if (relabelled_amount > 0 && p.manifest[commodity] < relabelled_amount) {
var goodunits = units - relabelled_amount;
if (units === 1) goodunits = 0;
var reclaimunits = units - goodunits;
p.manifest[commodity] = relabelled_amount;
p.dockedStation.setMarketQuantity(commodity, p.dockedStation.market[commodity].quantity - reclaimunits);
player.credits -= ((reclaimunits * price) / 10);
player.consoleMessage(expandMissionText("smuggling_sale_reversed"));
}
}
//-------------------------------------------------------------------------------------------------------------
this.guiScreenChanged_hide = function (to, from) {
if (guiScreen === "GUI_SCREEN_INTERFACES") {
mission.unmarkSystem({
system: this._marker.id1,
name: this.name + "_mark1"
});
mission.unmarkSystem({
system: this._marker.id2,
name: this.name + "_mark2"
});
if (this._marker.id1 < this._marker.id2) {
SystemInfo.setInterstellarProperty(galaxyNumber, this._marker.id1, this._marker.id2, 2, "link_color", null);
} else {
SystemInfo.setInterstellarProperty(galaxyNumber, this._marker.id2, this._marker.id1, 2, "link_color", null);
}
this._marker = {};
delete this.guiScreenChanged;
}
}
//-------------------------------------------------------------------------------------------------------------
// returns the total number of units that have been relabelled to the passed commodity type
this.$getTotalRelabelled = function $getTotalRelabelled(commodity) {
var amount = 0;
for (var i = 0; i < this._cargoLabelled.length; i++) {
if (this._cargoLabelled[i].newCommodity === commodity) amount += this._cargoLabelled[i].quantity;
}
return amount;
}
//-------------------------------------------------------------------------------------------------------------
// returns the total number of units of the original commodity
this.$getTotalUnlabelled = function $getTotalUnlabelled(commodity) {
var amount = 0;
for (var i = 0; i < this._cargoLabelled.length; i++) {
if (this._cargoLabelled[i].oldCommodity === commodity) amount += this._cargoLabelled[i].quantity;
}
return amount;
}
//-------------------------------------------------------------------------------------------------------------
// returns the amount of a particular commodity we had at launch
this.$launchAmount = function $launchAmount(commodity) {
for (var i = 0; i < this._cargoAtLaunch.length; i++) {
if (this._cargoAtLaunch[i].commodity === commodity) return this._cargoAtLaunch[i].quantity;
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------
// initialise the dock master F4 screen entries
this.$initMainInterface = function $initMainInterface(station) {
// no station? no interface
if (!station) return;
// not galcop aligned? no interface
if (station.allegiance != "galcop") return;
// did we get to the station when the dock master is on duty?
if (clock.hoursComponent < this._dockMasterStartTime || clock.hoursComponent > this._dockMasterEndTime) return;
if (this._bribeAttempted === false) {
station.setInterface(this.name + "dockmaster", {
title: expandMissionText("smuggling_dock_master"),
category: expandMissionText("smuggling_interface_category"),
summary: expandMissionText("smuggling_interface_summary"),
callback: this.$initialDockMasterOptions.bind(this)
});
}
}
//-------------------------------------------------------------------------------------------------------------
// initialises the remove labelling interface screen
this.$initUnlabelInterface = function $initUnlabelInterface(station) {
station.setInterface(this.name + "unlabel", {
title: expandMissionText("smuggling_unlabel"),
category: expandDescription("[interfaces-category-ship-systems]"),
summary: expandMissionText("smuggling_unlabel_summary"),
callback: this.$removeLabellingList.bind(this)
});
}
//-------------------------------------------------------------------------------------------------------------
this.$initialDockMasterOptions = function $initialDockMasterOptions() {
this._display = 0;
this.$showDockMasterOptions();
}
//-------------------------------------------------------------------------------------------------------------
this.$showDockMasterOptions = function $showDockMasterOptions() {
var curChoices = {};
var text = "";
var p = player.ship;
var def = "";
var pagesize = 20;
if (this.$isBigGuiActive() === true) pagesize = 26;
if (this._display === 0) {
if (clock.hoursComponent < 12) text += expandMissionText("smuggling_good_morning");
if (clock.hoursComponent >= 12 && clock.hoursComponent < 18) text += expandMissionText("smuggling_good_afternoon");
if (clock.hoursComponent >= 18) text += expandMissionText("smuggling_good_evening");
text += " " + expandDescription("[dockmaster-welcome]");
var itemcount = 1;
curChoices["01_MILKRUN"] = {
text: "[dockmaster-milkruns]",
color: this._menuColor
};
if (this._bribeAttempted === false && player.credits > 0 && this.$playerHasBribableCargo() === true) {
curChoices["02_BRIBE"] = {
text: "[dockmaster-bribe-cargo]",
color: this._menuColor
};
itemcount += 1;
}
if (worldScripts.BountySystem_MostWanted && worldScripts.StationDockControl && p.equipmentStatus("EQ_HUNTER_LICENCE") === "EQUIPMENT_OK" && this._destReleaseCount < 3 && this._flagged.length > 0) {
curChoices["05_HUNTER_REQ"] = {
text: "[dockmaster-release-dest]",
color: this._menuColor
};
itemcount += 1;
}
curChoices["98_SPACER"] = "";
itemcount += 1;
curChoices["99_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
for (var i = 0; i < ((pagesize - 2) - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
def = "99_EXIT";
var opts = {
screenID: "oolite-smuggling-dockmaster-map",
title: expandMissionText("smuggling_dock_master"),
allowInterrupt: true,
overlay: {
name: "stgu-chat.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// milk runs
if (this._display === 1) {
text = expandDescription("[milkrun-apology]");
var found = false;
for (var i = this._milkRuns.length - 1; i >= 0; i--) {
var dist1 = System.infoForSystem(galaxyNumber, system.ID).distanceToSystem(System.infoForSystem(galaxyNumber, this._milkRuns[i].id1));
var dist2 = System.infoForSystem(galaxyNumber, system.ID).distanceToSystem(System.infoForSystem(galaxyNumber, this._milkRuns[i].id2));
if (dist1 < 15 || dist2 < 15) {
// found one
text = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" + expandDescription("[milkrun]", {
system1: System.infoForSystem(galaxyNumber, this._milkRuns[i].id1).name,
system2: System.infoForSystem(galaxyNumber, this._milkRuns[i].id2).name
});
this._marker = this._milkRuns[i];
this.guiScreenChanged = this.guiScreenChanged_hide;
mission.markSystem({
system: this._marker.id1,
name: this.name + "_mark1",
markerShape: "MARKER_DIAMOND",
markerColor: "whiteColor",
markerScale: 1.1
});
mission.markSystem({
system: this._milkRuns[i].id2,
name: this.name + "_mark2",
markerShape: "MARKER_DIAMOND",
markerColor: "whiteColor",
markerScale: 1.1
});
if (this._marker.id1 < this._marker.id2) {
SystemInfo.setInterstellarProperty(galaxyNumber, this._marker.id1, this._marker.id2, 2, "link_color", "whiteColor");
} else {
SystemInfo.setInterstellarProperty(galaxyNumber, this._marker.id2, this._marker.id1, 2, "link_color", "whiteColor");
}
found = true;
break;
}
}
if (found === false) {
var opts = {
screenID: "oolite-smuggling-dockmaster-map",
title: expandMissionText("smuggling_dock_master"),
allowInterrupt: true,
overlay: {
name: "stgu-chat.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
message: text
};
} else {
var point1 = System.infoForSystem(galaxyNumber, this._marker.id1).coordinates;
var point2 = System.infoForSystem(galaxyNumber, this._marker.id2).coordinates;
var xdiff = (point1.x - point2.x) / 2;
var ydiff = (point1.y - point2.y) / 2;
var opts = {
screenID: "oolite-smuggling-dockmaster-milkrun",
title: expandMissionText("smuggling_dock_master"),
allowInterrupt: true,
backgroundSpecial: "CUSTOM_CHART",
customChartZoom: 1.4,
customChartCentreInLY: new Vector3D(point1.x - xdiff, point1.y - ydiff, 0),
exitScreen: "GUI_SCREEN_INTERFACES",
message: text
};
}
}
// display cargo to alter
if (this._display === 2) {
var cargo = p.manifest.list;
var itemcount = 0;
var list = [];
for (var i = 0; i < cargo.length; i++) {
// make sure we don't relabel relabelled cargo
var q = cargo[i].quantity;
if (this._cargoLabelled.length > 0) {
for (var j = 0; j < this._cargoLabelled.length; j++) {
if (this._cargoLabelled[j].newCommodity === cargo[i].commodity) q -= this._cargoLabelled[j].quantity;
}
}
// make sure we don't relabel New Cargoes
var cteCargo = worldScripts.Smugglers_Equipment.$calcCTEcargo(cargo[i].commodity);
if (cteCargo > 0) q -= cteCargo;
if (q > 0) {
if (this._noSwitch.indexOf(cargo[i].commodity) === -1) {
list.push({
menu: "50_" + (i < 10 ? "0" : "") + i + "_CARGO~" + cargo[i].commodity,
text: cargo[i].displayName + " (" + q + cargo[i].unit + ")",
color: this._menuColor
})
}
}
}
if (list.length >= pagesize) {
pagesize -= 4;
} else {
pagesize -= 2;
}
for (var i = 0; i < pagesize; i++) {
var ref = i + (this._curPage * pagesize);
if (ref < list.length) {
curChoices[list[ref].menu] = {
text: list[ref].text,
color: list[ref].color
};
itemcount += 1;
}
}
if (list.length > pagesize) {
if (this._curPage < Math.floor(list.length / pagesize)) {
curChoices["Z_NEXT"] = {
text: "[illegal-nextpage]",
color: this._itemColor
};
} else {
curChoices["Z_NEXT"] = {
text: "[illegal-nextpage]",
color: this._disabledColor,
unselectable: true
};
}
if (this._curPage > 0) {
curChoices["Z_PREV"] = {
text: "[illegal-prevpage]",
color: this._itemColor
};
} else {
curChoices["Z_PREV"] = {
text: "[illegal-prevpage]",
color: this._disabledColor,
unselectable: true
};
}
}
for (var i = 0; i < ((pagesize + 1) - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
var opts = {
screenID: "oolite-smuggling-dockmaster-map",
title: expandMissionText("smuggling_dock_master"),
overlay: {
name: "stgu-chat.png",
height: 546
},
allowInterrupt: false,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
messageKey: "cargo-relabel-accept"
};
}
// display options to switch to
if (this._display === 3) {
var se = worldScripts.Smugglers_Equipment;
text = expandMissionText("cargo-relabel-question", {
cargo: displayNameForCommodity(this._tfrCargo)
});
var itemcount = 0;
var list = [];
for (var i = 0; i < se._commodityIDList.length; i++) {
if (this._noSwitch.indexOf(se._commodityIDList[i]) === -1 && se._commodityIDList != this._tfrCargo) {
list.push({
menu: "40_" + (i < 10 ? "0" : "") + i + "~" + se._commodityIDList[i],
text: displayNameForCommodity(se._commodityIDList[i]),
color: this._menuColor
})
}
}
if (list.length >= pagesize) {
pagesize -= 4;
} else {
pagesize -= 2;
}
for (var i = 0; i < pagesize; i++) {
var ref = i + (this._curPage * pagesize);
if (ref < list.length) {
curChoices[list[ref].menu] = {
text: list[ref].text,
color: list[ref].color
};
itemcount += 1;
}
}
if (list.length > pagesize) {
if (this._curPage < Math.floor(list.length / pagesize)) {
curChoices["99_NEXT"] = {
text: "[illegal-nextpage]",
color: this._itemColor
};
} else {
curChoices["99_NEXT"] = {
text: "[illegal-nextpage]",
color: this._disabledColor,
unselectable: true
};
}
if (this._curPage > 0) {
curChoices["99_PREV"] = {
text: "[illegal-prevpage]",
color: this._itemColor
};
} else {
curChoices["99_PREV"] = {
text: "[illegal-prevpage]",
color: this._disabledColor,
unselectable: true
};
}
}
for (var i = 0; i < ((pagesize + 1) - itemcount); i++) {
curChoices["60_SPACER_" + i] = "";
}
var opts = {
screenID: "oolite-smuggling-dockmaster-map",
title: expandMissionText("smuggling_dock_master"),
overlay: {
name: "stgu-chat.png",
height: 546
},
allowInterrupt: false,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
message: text
};
}
// linking bounty most wanted and SDC
if (this._display === 4) {
// display list of flagged ships
text = expandMissionText("smuggling_ship_dest");
var itemcount = 0;
for (var i = 0; i < this._flagged.length; i++) {
// if you don't have the dough, it won't let you go
// saves having to have another response screen saying "You don't have enough cash"
if (player.credits > parseInt(this._flagged[i].cost)) {
curChoices["01_FLAGGED~" + i] = {
text: this._flagged[i].text,
color: this._menuColor,
alignment: "LEFT"
};
} else {
curChoices["01_FLAGGED~" + i] = {
text: this._flagged[i].text,
color: this._disabledColor,
alignment: "LEFT",
unselectable: true
};
}
itemcount += 1;
}
curChoices["97_SPACER"] = "";
itemcount += 1;
curChoices["98_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
for (var i = 0; i < ((pagesize - 2) - itemcount); i++) {
curChoices["97_SPACER_" + i] = "";
}
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-dockmaster-map",
title: expandMissionText("smuggling_dock_master"),
allowInterrupt: true,
overlay: {
name: "stgu-chat.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// ship dest unlock successful
if (this._display === 5) {
text = expandMissionText("smuggling_ship_dest_unlocked");
curChoices["98A_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
def = "98A_EXIT";
var opts = {
screenID: "oolite-smuggling-dockmaster-map",
title: expandMissionText("smuggling_dock_master"),
allowInterrupt: true,
overlay: {
name: "stgu-chat.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// ship dest unlock unsuccessful
if (this._display === 6) {
text = expandMissionText("smuggling_ship_not_found");
curChoices["98A_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
def = "98A_EXIT";
var opts = {
screenID: "oolite-smuggling-dockmaster-map",
title: expandMissionText("smuggling_dock_master"),
allowInterrupt: true,
overlay: {
name: "stgu-chat.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
mission.runScreen(opts, this.$screenHandler, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$screenHandler = function $screenHandler(choice) {
if (choice == null) return;
switch (choice) {
case "01_MILKRUN":
this._display = 1;
break;
case "02_BRIBE":
this.$getBribeAmount("manifest");
return;
case "05_HUNTER_REQ":
this._display = 4;
break;
case "98_EXIT":
this._display = 1;
break;
case "98A_EXIT":
this._display = 0;
break;
case "99_NEXT":
this._curPage += 1;
break;
case "99_PREV":
this._curPage -= 1;
break;
}
if (choice.indexOf("01_FLAGGED") >= 0) {
var idx = parseInt(choice.substring(choice.indexOf("~") + 1));
var ref = parseInt(this._flagged[idx].index);
var shpRef = parseInt(this._flagged[idx].shipIndex);
var cost = parseInt(this._flagged[idx].cost);
var mw = worldScripts.BountySystem_MostWanted;
var found = false;
for (var i = 0; i < mw._wanted.length; i++) {
if (mw._wanted[i].index === ref) {
var sdci = worldScripts.StationDockControl_Interface;
var item = sdci._viewing[shpRef];
if (item.pilotName === mw._wanted[i].pilotName) {
player.credits -= cost;
player.consoleMessage(expandMissionText("smuggling_charged", { amount: formatCredits(cost, false, true) }));
item.destinationHidden = false;
this._destReleaseCount += 1;
this._flagged.splice(idx, 1);
found = true;
this._display = 5;
}
}
}
if (found === false) {
this._display = 6;
}
}
if (choice.indexOf("50_") >= 0) {
this._tfrCargo = choice.substring(choice.indexOf("~") + 1);
this._display = 3;
this._curPage = 0;
}
if (choice.indexOf("40_") >= 0) {
var newCmdty = choice.substring(choice.indexOf("~") + 1);
var p = player.ship;
var amount = p.manifest[this._tfrCargo];
// if we already have relabelled the selected cargo, get the un-relabelled portion of it
for (var i = 0; i < this._cargoLabelled.length; i++) {
if (this._cargoLabelled[i].newCommodity === this._tfrCargo) amount -= this._cargoLabelled[i].quantity;
}
// do we already have some relabelled cargo of the same type (matching old and new
var found = false;
for (var i = 0; i < this._cargoLabelled.length; i++) {
if (this._cargoLabelled[i].newCommodity === newCmdty && this._cargoLabelled[i].oldCommodity === this._tfrCargo) {
this._cargoLabelled[i].quantity += amount
found = true;
}
}
if (found === false) this._cargoLabelled.push({
oldCommodity: this._tfrCargo,
newCommodity: newCmdty,
quantity: amount
});
p.manifest[this._tfrCargo] -= amount;
p.manifest[newCmdty] += amount;
this.$initUnlabelInterface(p.dockedStation);
var extramsg = "";
var se = worldScripts.Smugglers_Equipment;
if (se.$hasSmugglingCompartment() === true) extramsg = expandMissionText("cargo-relabel-reminder");
mission.runScreen({
screenID: "oolite-smuggling-dockmaster-map",
title: expandMissionText("smuggling_dock_master"),
overlay: {
name: "stgu-chat.png",
height: 546
},
message: expandDescription("[dockmaster-complete]") + extramsg,
exitScreen: "GUI_SCREEN_INTERFACES"
});
p.dockedStation.setInterface(this.name + "dockmaster", null);
}
if (choice != "99_EXIT" && choice.indexOf("40_") === -1) {
this.$showDockMasterOptions();
}
}
//-------------------------------------------------------------------------------------------------------------
// prompts the user for a new phase
this.$getBribeAmount = function $getBribeAmount(type) {
var text = "";
this._bribeAttempted = true;
var inttype = Math.floor((this._bribeChance[system.ID] * 4) + 1);
var inttypedesc = expandDescription("[interest-type" + inttype + "]");
var lastBribe = this.$previousBribeAmount();
if (type === "manifest") {
text = expandDescription("[dockmaster-question]", {
interesttype: inttypedesc
}) + "\n\n" +
"(" + expandDescription("[dockmaster-cost]", {
credits: formatCredits(player.credits, false, true)
}) +
(lastBribe > 0 ? expandDescription("[dockmaster-lastbribe]", {
bribeamount: formatCredits(lastBribe, false, true)
}) : "") + ")";
} else {
text = expandMissionText("smuggling_keys_kingdom") + " " + expandDescription("[dockmaster-question]", {
interesttype: inttypedesc
}) + "\n\n" +
"(" + expandDescription("[dockmaster-cost]", {
credits: formatCredits(player.credits, false, true)
})
}
var opts = {
screenID: "oolite-smuggling-dockmaster-map",
title: expandMissionText("smuggling_dock_master"),
allowInterrupt: false,
overlay: {
name: "stgu-chat.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
message: text,
textEntry: true
};
mission.runScreen(opts, this.$getBribeAmountInputManifest, this);
}
//-------------------------------------------------------------------------------------------------------------
// parses the input from the getBribeAmount screen
this.$getBribeAmountInputManifest = function $getBribeAmountInputManifest(param) {
var p = player.ship;
if (parseInt(param) >= 1 && parseInt(param) <= player.credits) {
var amount = parseInt(param);
// will this work
var chance = this._bribeChance[system.ID];
// higher amounts are more likely to be accepted
// chance of 0.5 would mean you would need to offer them 1690 credits
//if (this._debug) log(this.name, "min bribe amount = " + (Math.pow(parseInt(chance * 32), 1.8) * (1 + system.productivity / 56300) * this._bribeCount[system.ID]));
if ((Math.pow(parseInt(chance * 32), 1.8) * (1 + system.productivity / 56300) * this._bribeCount[system.ID]) <= amount) {
player.credits -= amount;
this._display = 2;
this._curPage = 0;
this.$addBribe(system.ID);
this._successfulBribes.push({
system: system.ID,
bribeAmount: amount
});
this.$showDockMasterOptions();
} else {
this._display = 0;
if (Math.random() > chance) {
mission.runScreen({
screenID: "oolite-smuggling-dockmaster-map",
title: expandMissionText("smuggling_dock_master"),
overlay: {
name: "stgu-chat.png",
height: 546
},
message: expandDescription("[dockmaster-angry-nopenalty]"),
exitScreen: "GUI_SCREEN_INTERFACES"
});
} else {
var penalty = (this.$rand(10) + 3);
p.setBounty(player.bounty + penalty, "attempted bribe");
mission.runScreen({
screenID: "oolite-smuggling-dockmaster-map",
title: expandMissionText("smuggling_dock_master"),
overlay: {
name: "stgu-chat.png",
height: 546
},
message: expandDescription("[dockmaster-angry-penalty]"),
exitScreen: "GUI_SCREEN_INTERFACES"
});
// send email (if installed)
var email = worldScripts.EmailSystem;
if (email) {
var ga = worldScripts.GalCopAdminServices;
email.$createEmail({
sender: "GalCop Customs",
subject: "Attempt to bribe official",
date: clock.seconds,
message: expandDescription("[smugglers-failed-bribe-email]", {
legal_penalty: penalty,
stationname: player.ship.dockedStation.displayName,
systemname: System.systemNameForID(system.ID)
}),
expiryDays: ga._defaultExpiryDays
});
}
}
p.dockedStation.setInterface(this.name + "dockmaster", null);
}
} else {
this._display = 0;
mission.runScreen({
screenID: "oolite-smuggling-dockmaster-map",
title: expandMissionText("smuggling_bribe_official"),
overlay: {
name: "stgu-chat.png",
height: 546
},
message: expandDescription("[dockmaster-skipbribe]"),
exitScreen: "GUI_SCREEN_STATUS"
});
p.dockedStation.setInterface(this.name + "dockmaster", null);
}
}
//-------------------------------------------------------------------------------------------------------------
this.$removeLabellingList = function $removeLabellingList() {
var curChoices = {};
var se = worldScripts.Smugglers_Equipment;
var pagesize = 20;
if (this.$isBigGuiActive() === true) pagesize = 26;
for (var i = 0; i < this._cargoLabelled.length; i++) {
curChoices["01_CARGO~" + (i < 10 ? "0" : "") + i] = {
text: this._cargoLabelled[i].quantity + se.$getCommodityType(this._cargoLabelled[i].newCommodity) + " " + displayNameForCommodity(this._cargoLabelled[i].newCommodity) +
", " + expandMissionText("smuggling_back_to") + " " + displayNameForCommodity(this._cargoLabelled[i].oldCommodity),
color: this._menuColor
};
}
curChoices["98_SPACER_" + i] = "";
curChoices["99_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
for (var i = 0; i < ((pagesize - 3) - this._cargoLabelled.length); i++) {
curChoices["99_SPACER_" + i] = "";
}
var def = "99_EXIT";
var opts = {
screenID: "oolite-smuggling-dockmaster-map",
titleKey: "smuggling_unlabel",
allowInterrupt: true,
overlay: {
name: "stgu-id.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
messageKey: "cargo-relabel-heading"
};
mission.runScreen(opts, this.$removeLabellingHandler, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$removeLabellingHandler = function $removeLabellingHandler(choice) {
if (choice == null) return;
if (choice.indexOf("01_") >= 0) {
var idx = parseInt(choice.substring(choice.indexOf("~") + 1));
this.$removeLabelling(idx);
if (this._cargoLabelled.length > 0) this.$removeLabellingList();
}
}
//-------------------------------------------------------------------------------------------------------------
this.$removeLabelling = function $removeLabelling(idx) {
var p = player.ship;
// revert cargo back to original
// make sure we still have the right amount
if (p.manifest[this._cargoLabelled[idx].newCommodity] < this._cargoLabelled[idx].quantity)
this._cargoLabelled[idx].quantity = p.manifest[this._cargoLabelled[idx].newCommodity];
// deduct from the new commodity name
p.manifest[this._cargoLabelled[idx].newCommodity] -= this._cargoLabelled[idx].quantity;
// add to the old commodity name
p.manifest[this._cargoLabelled[idx].oldCommodity] += this._cargoLabelled[idx].quantity;
this._cargoLabelled.splice(idx, 1);
if (this._cargoLabelled.length === 0) {
p.dockedStation.setInterface(this.name + "unlabel", null);
}
}
//-------------------------------------------------------------------------------------------------------------
// sets up the chance a dock master can be bribed, for each of the main stations
this.$setupChance = function $setupChance() {
this._bribeChance = [];
for (var i = 0; i <= 255; i++) {
this._bribeChance.push(Math.random());
}
}
//-------------------------------------------------------------------------------------------------------------
// sets the time frame where the dock master can be called on - he doesn't work 24 hours a day!
this.$setDockMasterHours = function $setDockMasterHours() {
// set a start time between 7 and 10
this._dockMasterStartTime = 6 + this.$rand(4);
// set an end time between 7 and 10 hours later
this._dockMasterEndTime = this.$dockMasterStartTime + (this.$rand(4) + 6)
}
//-------------------------------------------------------------------------------------------------------------
// removes labelling on a specific amount of cargo
this.$removeRealCargoQuantity = function $removeRealCargoQuantity(commodity, amount) {
var p = player.ship;
var remainder = amount;
for (var i = this._cargoLabelled.length - 1; i >= 0; i--) {
if (remainder > 0 && this._cargoLabelled[i].oldCommodity === commodity) {
if (this._cargoLabelled[i].quantity >= remainder) {
if (p.manifest[this._cargoLabelled[i].newCommodity] >= remainder) {
p.manifest[this._cargoLabelled[i].newCommodity] -= remainder;
p.manifest[this._cargoLabelled[i].oldCommodity] += remainder;
this._cargoLabelled[i].quantity -= remainder;
remainder = 0;
} else {
var subamt = p.manifest[this._cargoLabelled[i].newCommodity];
p.manifest[this._cargoLabelled[i].newCommodity] = 0;
p.manifest[this._cargoLabelled[i].oldCommodity] += subamt;
this._cargoLabelled[i].quantity -= subamt;
remainder -= subamt;
}
} else {
var correction = remainder - this._cargoLabelled[i].quantity;
if (p.manifest[this._cargoLabelled[i].newCommodity] >= correction) {
p.manifest[this._cargoLabelled[i].newCommodity] -= correction;
p.manifest[this._cargoLabelled[i].oldCommodity] += correction;
this._cargoLabelled[i].quantity -= correction;
remainder -= correction;
} else {
var subamt = p.manifest[this._cargoLabelled[i].oldCommodity];
p.manifest[this._cargoLabelled[i].newCommodity] = 0;
p.manifest[this._cargoLabelled[i].oldCommodity] += subamt;
this._cargoLabelled[i].quantity = 0;
remainder -= subamt;
}
}
}
}
return remainder;
}
//-------------------------------------------------------------------------------------------------------------
// returns true if the player cargo that the dock master can relabel, otherwise false
this.$playerHasBribableCargo = function $playerHasBribableCargo() {
var p = player.ship;
var cargo = p.manifest.list;
var result = false;
for (var i = 0; i < cargo.length; i++) {
if (this._noSwitch.indexOf(cargo[i].commodity) === -1) result = true;
}
return result;
}
//-------------------------------------------------------------------------------------------------------------
// increment the number of times the dm has been bribed
this.$addBribe = function $addBribe(sysID) {
this._bribeCount[sysID] += 0.1 + (system.pseudoRandomNumber > 0.5 ? 0.1 : 0);
}
//-------------------------------------------------------------------------------------------------------------
// reset the bribecount array
this.$resetBribeCount = function $resetBribeCount() {
this._bribeCount = [];
for (var i = 0; i <= 255; i++) {
this._bribeCount.push(1);
}
}
//-------------------------------------------------------------------------------------------------------------
// returns the last successful bribe amount for the current system
this.$previousBribeAmount = function $previousBribeAmount() {
var bribeAmt = 0;
for (var i = 0; i < this._successfulBribes.length; i++) {
if (this._successfulBribes[i].system === system.ID && this._successfulBribes[i].bribeAmount > bribeAmt) {
bribeAmt = this._successfulBribes[i].bribeAmount;
}
}
return bribeAmt;
}
//-------------------------------------------------------------------------------------------------------------
// loads the mulk run array with data for the current galaxy
this.$getMilkRuns = function $getMilkRuns() {
this._milkRuns = [];
switch (galaxyNumber) {
case 0:
this._milkRuns = [
{ id1: 99, id2: 84, rating: 70 },
{ id1: 99, id2: 191, rating: 72 },
{ id1: 12, id2: 116, rating: 73 },
{ id1: 163, id2: 192, rating: 73 },
{ id1: 131, id2: 42, rating: 73 },
{ id1: 254, id2: 187, rating: 74 },
{ id1: 158, id2: 116, rating: 75 },
{ id1: 98, id2: 84, rating: 75 },
{ id1: 98, id2: 191, rating: 75 },
{ id1: 195, id2: 63, rating: 76 },
{ id1: 254, id2: 251, rating: 76 },
{ id1: 79, id2: 174, rating: 76 },
{ id1: 49, id2: 116, rating: 76 },
{ id1: 254, id2: 74, rating: 77 },
{ id1: 100, id2: 42, rating: 77 },
{ id1: 207, id2: 116, rating: 77 },
{ id1: 131, id2: 167, rating: 78 },
{ id1: 240, id2: 187, rating: 78 },
{ id1: 79, id2: 191, rating: 79 },
{ id1: 33, id2: 123, rating: 81 },
{ id1: 99, id2: 185, rating: 81 },
{ id1: 82, id2: 244, rating: 83 },
{ id1: 227, id2: 154, rating: 83 },
{ id1: 35, id2: 186, rating: 84 },
{ id1: 221, id2: 185, rating: 84 },
{ id1: 163, id2: 252, rating: 86 },
{ id1: 141, id2: 101, rating: 89 },
{ id1: 250, id2: 101, rating: 89 },
{ id1: 218, id2: 18, rating: 90 },
{ id1: 82, id2: 154, rating: 90 },
{ id1: 246, id2: 18, rating: 93 },
];
break;
case 1:
this._milkRuns = [
{ id1: 255, id2: 37, rating: 72 },
{ id1: 191, id2: 37, rating: 74 },
{ id1: 128, id2: 165, rating: 74 },
{ id1: 57, id2: 94, rating: 76 },
{ id1: 24, id2: 20, rating: 78 },
{ id1: 237, id2: 174, rating: 79 },
{ id1: 16, id2: 157, rating: 80 },
{ id1: 81, id2: 20, rating: 80 },
{ id1: 167, id2: 94, rating: 81 },
{ id1: 82, id2: 174, rating: 82 },
{ id1: 40, id2: 68, rating: 82 },
{ id1: 106, id2: 211, rating: 83 },
{ id1: 57, id2: 19, rating: 83 },
{ id1: 57, id2: 115, rating: 84 },
{ id1: 185, id2: 38, rating: 84 },
{ id1: 92, id2: 211, rating: 85 },
{ id1: 191, id2: 83, rating: 85 },
{ id1: 16, id2: 34, rating: 87 },
{ id1: 40, id2: 179, rating: 88 },
{ id1: 209, id2: 115, rating: 88 },
{ id1: 81, id2: 97, rating: 90 },
{ id1: 82, id2: 86, rating: 92 },
{ id1: 167, id2: 115, rating: 92 },
{ id1: 231, id2: 147, rating: 94 },
];
break;
case 2:
this._milkRuns = [
{ id1: 205, id2: 168, rating: 71 },
{ id1: 144, id2: 147, rating: 73 },
{ id1: 34, id2: 57, rating: 73 },
{ id1: 64, id2: 168, rating: 73 },
{ id1: 76, id2: 152, rating: 76 },
{ id1: 76, id2: 66, rating: 76 },
{ id1: 205, id2: 82, rating: 77 },
{ id1: 155, id2: 57, rating: 77 },
{ id1: 116, id2: 152, rating: 77 },
{ id1: 17, id2: 24, rating: 77 },
{ id1: 205, id2: 114, rating: 79 },
{ id1: 17, id2: 41, rating: 79 },
{ id1: 17, id2: 147, rating: 79 },
{ id1: 22, id2: 140, rating: 79 },
{ id1: 64, id2: 215, rating: 79 },
{ id1: 58, id2: 152, rating: 80 },
{ id1: 50, id2: 65, rating: 82 },
{ id1: 42, id2: 163, rating: 83 },
{ id1: 58, id2: 140, rating: 84 },
{ id1: 205, id2: 241, rating: 84 },
{ id1: 43, id2: 98, rating: 84 },
{ id1: 22, id2: 91, rating: 84 },
{ id1: 42, id2: 135, rating: 85 },
{ id1: 54, id2: 118, rating: 86 },
{ id1: 18, id2: 100, rating: 87 },
{ id1: 5, id2: 66, rating: 87 },
{ id1: 79, id2: 65, rating: 89 },
{ id1: 10, id2: 141, rating: 89 },
{ id1: 6, id2: 180, rating: 89 },
{ id1: 58, id2: 66, rating: 89 },
{ id1: 10, id2: 70, rating: 90 },
{ id1: 5, id2: 140, rating: 90 },
{ id1: 116, id2: 122, rating: 92 },
{ id1: 10, id2: 85, rating: 94 },
];
break;
case 3:
this._milkRuns = [
{ id1: 38, id2: 160, rating: 70 },
{ id1: 25, id2: 24, rating: 72 },
{ id1: 25, id2: 62, rating: 74 },
{ id1: 220, id2: 171, rating: 75 },
{ id1: 137, id2: 105, rating: 76 },
{ id1: 209, id2: 33, rating: 77 },
{ id1: 29, id2: 168, rating: 78 },
{ id1: 58, id2: 24, rating: 78 },
{ id1: 103, id2: 107, rating: 78 },
{ id1: 65, id2: 239, rating: 78 },
{ id1: 103, id2: 105, rating: 79 },
{ id1: 103, id2: 177, rating: 79 },
{ id1: 38, id2: 53, rating: 82 },
{ id1: 42, id2: 16, rating: 83 },
{ id1: 38, id2: 74, rating: 84 },
{ id1: 103, id2: 108, rating: 84 },
{ id1: 103, id2: 239, rating: 84 },
{ id1: 220, id2: 68, rating: 84 },
{ id1: 58, id2: 109, rating: 89 },
{ id1: 220, id2: 90, rating: 90 },
];
break;
case 4:
this._milkRuns = [
{ id1: 34, id2: 186, rating: 70 },
{ id1: 34, id2: 250, rating: 70 },
{ id1: 66, id2: 58, rating: 70 },
{ id1: 2, id2: 63, rating: 71 },
{ id1: 226, id2: 31, rating: 71 },
{ id1: 130, id2: 250, rating: 72 },
{ id1: 162, id2: 250, rating: 73 },
{ id1: 34, id2: 183, rating: 74 },
{ id1: 162, id2: 183, rating: 74 },
{ id1: 137, id2: 191, rating: 75 },
{ id1: 98, id2: 123, rating: 75 },
{ id1: 130, id2: 108, rating: 76 },
{ id1: 12, id2: 81, rating: 76 },
{ id1: 213, id2: 81, rating: 77 },
{ id1: 115, id2: 150, rating: 78 },
{ id1: 162, id2: 149, rating: 78 },
{ id1: 254, id2: 183, rating: 79 },
{ id1: 212, id2: 46, rating: 80 },
{ id1: 198, id2: 31, rating: 80 },
{ id1: 254, id2: 250, rating: 82 },
{ id1: 130, id2: 149, rating: 82 },
{ id1: 194, id2: 88, rating: 83 },
{ id1: 198, id2: 63, rating: 84 },
{ id1: 99, id2: 91, rating: 84 },
{ id1: 254, id2: 149, rating: 85 },
{ id1: 99, id2: 200, rating: 85 },
{ id1: 184, id2: 150, rating: 86 },
{ id1: 89, id2: 87, rating: 88 },
{ id1: 249, id2: 16, rating: 90 },
];
break;
case 5:
this._milkRuns = [
{ id1: 243, id2: 57, rating: 70 },
{ id1: 243, id2: 228, rating: 71 },
{ id1: 182, id2: 160, rating: 71 },
{ id1: 14, id2: 249, rating: 73 },
{ id1: 240, id2: 30, rating: 75 },
{ id1: 20, id2: 57, rating: 75 },
{ id1: 243, id2: 231, rating: 75 },
{ id1: 243, id2: 101, rating: 75 },
{ id1: 243, id2: 98, rating: 76 },
{ id1: 109, id2: 57, rating: 76 },
{ id1: 243, id2: 103, rating: 77 },
{ id1: 34, id2: 24, rating: 78 },
{ id1: 69, id2: 167, rating: 78 },
{ id1: 144, id2: 61, rating: 79 },
{ id1: 109, id2: 228, rating: 79 },
{ id1: 182, id2: 167, rating: 79 },
{ id1: 240, id2: 234, rating: 80 },
{ id1: 144, id2: 253, rating: 81 },
{ id1: 144, id2: 97, rating: 81 },
{ id1: 109, id2: 98, rating: 81 },
{ id1: 20, id2: 244, rating: 81 },
{ id1: 86, id2: 131, rating: 81 },
{ id1: 109, id2: 101, rating: 82 },
{ id1: 28, id2: 108, rating: 82 },
{ id1: 1, id2: 108, rating: 82 },
{ id1: 115, id2: 215, rating: 83 },
{ id1: 109, id2: 231, rating: 83 },
{ id1: 20, id2: 103, rating: 84 },
{ id1: 1, id2: 181, rating: 86 },
{ id1: 240, id2: 140, rating: 88 },
{ id1: 14, id2: 113, rating: 88 },
{ id1: 144, id2: 13, rating: 88 },
{ id1: 102, id2: 98, rating: 88 },
{ id1: 17, id2: 108, rating: 91 },
{ id1: 6, id2: 181, rating: 92 },
{ id1: 40, id2: 215, rating: 94 },
{ id1: 17, id2: 181, rating: 96 },
{ id1: 50, id2: 232, rating: 98 },
];
break;
case 6:
this._milkRuns = [
{ id1: 170, id2: 105, rating: 75 },
{ id1: 170, id2: 190, rating: 75 },
{ id1: 64, id2: 160, rating: 75 },
{ id1: 13, id2: 160, rating: 76 },
{ id1: 6, id2: 174, rating: 77 },
{ id1: 183, id2: 164, rating: 79 },
{ id1: 28, id2: 223, rating: 79 },
{ id1: 119, id2: 190, rating: 79 },
{ id1: 151, id2: 180, rating: 80 },
{ id1: 64, id2: 81, rating: 80 },
{ id1: 55, id2: 105, rating: 80 },
{ id1: 195, id2: 159, rating: 80 },
{ id1: 55, id2: 190, rating: 80 },
{ id1: 86, id2: 127, rating: 80 },
{ id1: 172, id2: 160, rating: 81 },
{ id1: 199, id2: 233, rating: 82 },
{ id1: 151, id2: 73, rating: 82 },
{ id1: 181, id2: 95, rating: 83 },
{ id1: 103, id2: 58, rating: 83 },
{ id1: 71, id2: 160, rating: 83 },
{ id1: 66, id2: 190, rating: 84 },
{ id1: 135, id2: 80, rating: 84 },
{ id1: 23, id2: 233, rating: 84 },
{ id1: 66, id2: 105, rating: 84 },
{ id1: 215, id2: 95, rating: 86 },
{ id1: 247, id2: 202, rating: 86 },
{ id1: 82, id2: 105, rating: 87 },
{ id1: 82, id2: 190, rating: 87 },
{ id1: 172, id2: 81, rating: 88 },
{ id1: 71, id2: 81, rating: 88 },
{ id1: 67, id2: 209, rating: 88 },
{ id1: 23, id2: 246, rating: 89 },
{ id1: 7, id2: 209, rating: 89 },
{ id1: 215, id2: 133, rating: 91 },
{ id1: 183, id2: 133, rating: 92 },
{ id1: 247, id2: 133, rating: 93 },
{ id1: 151, id2: 5, rating: 95 },
];
break;
case 7:
this._milkRuns = [
{ id1: 56, id2: 240, rating: 70 },
{ id1: 56, id2: 170, rating: 72 },
{ id1: 82, id2: 100, rating: 75 },
{ id1: 31, id2: 25, rating: 77 },
{ id1: 147, id2: 121, rating: 77 },
{ id1: 41, id2: 35, rating: 78 },
{ id1: 244, id2: 138, rating: 78 },
{ id1: 192, id2: 133, rating: 78 },
{ id1: 151, id2: 230, rating: 78 },
{ id1: 137, id2: 121, rating: 80 },
{ id1: 206, id2: 25, rating: 80 },
{ id1: 232, id2: 86, rating: 81 },
{ id1: 93, id2: 185, rating: 81 },
{ id1: 93, id2: 196, rating: 81 },
{ id1: 192, id2: 35, rating: 81 },
{ id1: 161, id2: 255, rating: 82 },
{ id1: 14, id2: 25, rating: 83 },
{ id1: 110, id2: 172, rating: 84 },
{ id1: 82, id2: 179, rating: 84 },
{ id1: 41, id2: 233, rating: 85 },
{ id1: 251, id2: 30, rating: 85 },
{ id1: 218, id2: 71, rating: 89 },
{ id1: 93, id2: 186, rating: 90 },
{ id1: 206, id2: 71, rating: 90 },
{ id1: 251, id2: 233, rating: 90 },
{ id1: 93, id2: 92, rating: 92 },
{ id1: 232, id2: 81, rating: 92 },
{ id1: 110, id2: 177, rating: 93 },
{ id1: 232, id2: 252, rating: 93 },
];
break
}
} |
Scripts/smugglers_equipment.js |
"use strict";
this.name = "Smugglers_Equipment";
this.author = "phkb";
this.description = "Looks after the smuggling compartment functions.";
this.licence = "CC BY-NC-SA 3.0";
/* TODO:
- Add very occasional messages from traders entering system ("Let hope that setting of 234 is worth the money we paid.")
- When docking with a standard contract that will be completed, but the cargo is now illegal, still give the player the opportunity to bribe
- allow non-core commodities to be put in the compartment
ISSUE:
- bribe opportunity not appearing in scenario where player docks at non-main station galcop station, with a scooped escape pod and illegal cargo (not slaves)
*/
this._disabled = false;
this._debug = false;
// array of all possible installed compartment equipment keys
this._equipmentList = ["EQ_SMUGGLING_COMPARTMENT_1", "EQ_SMUGGLING_COMPARTMENT_2", "EQ_SMUGGLING_COMPARTMENT_3", "EQ_SMUGGLING_COMPARTMENT_4",
"EQ_SMUGGLING_COMPARTMENT_5", "EQ_SMUGGLING_COMPARTMENT_6", "EQ_SMUGGLING_COMPARTMENT_7", "EQ_SMUGGLING_COMPARTMENT_8",
"EQ_SMUGGLING_COMPARTMENT_9", "EQ_SMUGGLING_COMPARTMENT_10", "EQ_SMUGGLING_COMPARTMENT_11", "EQ_SMUGGLING_COMPARTMENT_12",
"EQ_SMUGGLING_COMPARTMENT_13", "EQ_SMUGGLING_COMPARTMENT_14", "EQ_SMUGGLING_COMPARTMENT_15", "EQ_SMUGGLING_COMPARTMENT_16",
"EQ_SMUGGLING_COMPARTMENT_17", "EQ_SMUGGLING_COMPARTMENT_18", "EQ_SMUGGLING_COMPARTMENT_19", "EQ_SMUGGLING_COMPARTMENT_20"
];
this._commodityIDList = [];
// station types where the smuggling compartment can be purchased.
this._smugglingAllegiance = ["pirate", "chaotic", "neutral"];
this._maxTonnage = 20; // maximum possible size of the hold
this._doCompartmentCheck = false; // flag to indicate that a compartment check will be performed after docking
this._backdoor = false;
this._sc_Phase = 1; // the current phase setting (value between 1 and 999)
this._sc_TechVersion = 1; // the current tech level of the compartment
this._sc_VisibleAs = "food"; // string (commodity name) that the hold will display as for scanners
this._sc_Cargo = []; // array of commodities in hold (commodity:string, quantity:number, unit:t/kg/g);
this._sc_Days = 0; // number of days since the last tech upgrade
this._phaseUpdateDays = 0;
this._phaseScanDiscovery = []; // array of objects of discovered phase scan settings (from purchase or from phase scanner)
this._smugglingScreen = false; // flag to indicate that a mission screen is open
this._originalCredits = 0; // value to hold the players credits (used to refund the cost of the initial item)
this._display = 0;
this._oldday = 0;
this._phaseScannerAvailable = false; // indicates that this system has the phase scanner available
this._phaseScannerDetected = false; // indicates that the player was caught using the phase scanner
this._systemPhase = []; // array of objects (gov, tl, phase)
this._phaseUpdates = []; // stores list of governments/techLevels that have been updated
this._toRemove = []; // list of source and commodities to be removed
this._removeCompartment = false; // flag to indicate that the smuggling compartment should be removed after docking
this._playerFine = 0; // amount to fine the player
this._menuColor = "orangeColor";
this._itemColor = "yellowColor";
this._disabledColor = "darkGrayColor";
this._galJump = false;
this._policeModel = "";
this._NCInstalled = false;
this._IGTInstalled = false;
this._doCargoCheck = false;
this._dockingWithSlaves = false;
this._dockingWithSlavesCount = 0;
//-------------------------------------------------------------------------------------------------------------
this.startUp = function () {
if (this._disabled) {
delete this.playerWillSaveGame;
delete this.playerBoughtEquipment;
delete this.shipWillDockWithStation;
delete this.shipDockedWithStation;
delete this.missionScreenOpportunity;
delete this.shipExitedWitchspace;
delete this.shipLaunchedEscapePod;
delete this.guiScreenChanged;
delete this.guiScreenWillChange;
delete this.playerEnteredNewGalaxy;
delete this.playerRescuedEscapePod;
delete this.dayChanged;
delete this.equipmentDamaged;
delete this.equipmentRemoved;
delete this.startUpComplete;
delete this.startUp;
return;
}
this.$createSystemDataArray();
if (worldScripts.CargoTypeExtension) this._NCInstalled = true;
}
//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
function compare(a, b) {
if (a.order < b.order) return -1;
if (a.order > b.order) return 1;
return 0;
}
// check for illegal goods tweak
if (worldScripts["illegal_goods_tweak"]) this._IGTInstalled = true;
// build a list of available commodities
var m = null;
// find a station to get market data from
if (system.mainStation) {
m = system.mainStation.market;
} else if (player.ship.dockedStation) {
m = playership.dockedStation.market;
} else if (system.stations.length > 0) {
m = system.stations[0].market;
}
if (m) {
var sbd = worldScripts.Smugglers_DockMaster;
var c = Object.keys(m);
var list = [];
for (var i = 0; i < c.length; i++) {
list.push({
commodity: c[i],
order: (m[c[i]].sort_order ? m[c[i]].sort_order : 0)
});
// add any non-t commodities (kg or g, ie gold, platinum, gemstones) to the dockmaster noswitch list
if (m[c[i]].quantity_unit != 0) sbd._noSwitch.push(c[i]);
}
list.sort(compare);
for (var i = 0; i < list.length; i++) {
this._commodityIDList.push(list[i].commodity);
}
}
var core = worldScripts.Smugglers_CoreFunctions;
this.$padTextRight = core.$padTextRight;
this.$padTextLeft = core.$padTextLeft;
this.$isBigGuiActive = core.$isBigGuiActive;
this.$rand = core.$rand;
if (missionVariables.SmugglingCompartment_Phase) this._sc_Phase = missionVariables.SmugglingCompartment_Phase;
if (missionVariables.SmugglingCompartment_TechVersion) this._sc_TechVersion = missionVariables.SmugglingCompartment_TechVersion;
if (missionVariables.SmugglingCompartment_VisibleAs) this._sc_VisibleAs = missionVariables.SmugglingCompartment_VisibleAs;
if (missionVariables.SmugglingCompartment_Cargo) this._sc_Cargo = JSON.parse(missionVariables.SmugglingCompartment_Cargo);
this.$addExtraField(); // make sure the "extra" property is added if it's not there yet
if (missionVariables.SmugglingCompartment_Days) this._sc_Days = missionVariables.SmugglingCompartment_Days;
if (missionVariables.Smuggling_SystemPhase) this._systemPhase = JSON.parse(missionVariables.Smuggling_SystemPhase);
if (missionVariables.Smuggling_PhaseScannerAvailable) this._phaseScannerAvailable = (missionVariables.Smuggling_PhaseScannerAvailable === 1 ? true : false);
if (missionVariables.Smuggling_PhaseDiscovery) this._phaseScanDiscovery = JSON.parse(missionVariables.Smuggling_PhaseDiscovery);
if (missionVariables.Smuggling_PhaseUpdates) this._phaseUpdates = JSON.parse(missionVariables.Smuggling_PhaseUpdates);
if (missionVariables.Smuggling_PhaseUpdateDays) this._phaseUpdateDays = missionVariables.Smuggling_PhaseUpdateDays;
delete missionVariables.SmugglingCompartment_Phase;
delete missionVariables.SmugglingCompartment_TechVersion;
delete missionVariables.SmugglingCompartment_VisibleAs;
delete missionVariables.SmugglingCompartment_Cargo;
if (this._systemPhase.length === 0) this.$createSystemPhase();
this._policeModel = this.$getPoliceModel();
// set up the interface screen, if required
this.$initInterface(player.ship.dockedStation);
// check that the inflight eq is given to the player if they have a smuggling compartment
if (this.$hasSmugglingCompartment() === true) {
player.ship.awardEquipment("EQ_SMUGGLING_INFLIGHT_STORAGE");
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
if (this.$hasSmugglingCompartment() === true) {
missionVariables.SmugglingCompartment_Phase = this._sc_Phase;
missionVariables.SmugglingCompartment_TechVersion = this._sc_TechVersion;
missionVariables.SmugglingCompartment_VisibleAs = this._sc_VisibleAs;
missionVariables.SmugglingCompartment_Cargo = JSON.stringify(this._sc_Cargo);
missionVariables.SmugglingCompartment_Days = this._sc_Days;
} else {
delete missionVariables.SmugglingCompartment_Phase;
delete missionVariables.SmugglingCompartment_TechVersion;
delete missionVariables.SmugglingCompartment_VisibleAs;
delete missionVariables.SmugglingCompartment_Cargo;
delete missionVariables.SmugglingCompartment_Days;
}
missionVariables.Smuggling_SystemPhase = JSON.stringify(this._systemPhase);
missionVariables.Smuggling_PhaseScannerAvailable = (this._phaseScannerAvailable ? 1 : 0);
missionVariables.Smuggling_PhaseDiscovery = JSON.stringify(this._phaseScanDiscovery);
if (this._phaseUpdates.length > 0) missionVariables.Smuggling_PhaseUpdates = JSON.stringify(this._phaseUpdates);
missionVariables.Smuggling_PhaseUpdateDays = this._phaseUpdateDays;
}
//-------------------------------------------------------------------------------------------------------------
this.playerBoughtEquipment = function (equipmentKey) {
var p = player.ship;
// repairing the phase scanner
if (equipmentKey === "EQ_PHASE_SCANNER_REPAIR") {
p.removeEquipment(equipmentKey);
p.setEquipmentStatus("EQ_PHASE_SCANNER", "EQUIPMENT_OK");
return;
}
// repairing the smuggling compartment
if (equipmentKey.indexOf("EQ_SMUGGLING_COMPARTMENT_REPAIR") >= 0) {
p.removeEquipment(equipmentKey);
var eq = this.$getSmugglingCompartmentEquipment();
p.setEquipmentStatus(eq, "EQUIPMENT_OK");
return;
}
var stn = p.dockedStation;
// removing the phase scanner
if (equipmentKey === "EQ_PHASE_SCANNER_REMOVAL") {
p.removeEquipment(equipmentKey);
if (stn.allegiance != "galcop") {
// give the player a refund if we're not at a galcop station
var tradeinfactor = 1.0;
// less refund for damaged scanner
if (p.equipmentStatus("EQ_PHASE_SCANNER") != "EQUIPMENT_OK") tradinfactor = 0.3;
var oldEqInfo = EquipmentInfo.infoForKey("EQ_PHASE_SCANNER");
player.credits += ((oldEqInfo.price / 10) * stn.equipmentPriceFactor) * tradeinfactor;
}
p.removeEquipment("EQ_PHASE_SCANNER");
}
// removing the smuggling compartment
if (equipmentKey === "EQ_SMUGGLING_COMPARTMENT_REMOVAL") {
p.removeEquipment(equipmentKey);
var eqKey = this.$getSmugglingCompartmentEquipment();
// do a refund, but only if we're not at a galcop station, and only if the existing equipment is undamaged
if (stn.allegiance != "galcop" && eqKey != "") {
var tradeinfactor = 1.0;
// less refund for damaged compartment
if (p.equipmentStatus(eqKey) != "EQUIPMENT_OK") tradinfactor = 0.3;
var oldEqInfo = EquipmentInfo.infoForKey(eqKey);
player.credits += ((oldEqInfo.price / 10) * stn.equipmentPriceFactor) * tradeinfactor;
}
if (p.equipmentStatus("EQ_SMUGGLING_PHASE_ADJUSTMENT") === "EQUIPMENT_OK") {
p.removeEquipment("EQ_SMUGGLING_PHASE_ADJUSTMENT");
}
player.ship.removeEquipment("EQ_SMUGGLING_INFLIGHT_STORAGE");
this._backdoor = true;
if (eqKey != "") p.removeEquipment(eqKey);
this._backdoor = false;
this.$resetCompartmentInfo(stn);
}
// buying a new (or expanding/contracting an existing) smuggling compartment
if (equipmentKey === "EQ_SMUGGLING_COMPARTMENT") {
p.removeEquipment(equipmentKey);
// give the player back the original amount, in case they decide not to purchase
if (this._originalCredits != 0) {
player.credits = this._originalCredits;
this._originalCredits = player.credits;
}
// mission screen to ask how many TC to allocate
this._hudHidden = player.ship.hudHidden;
this.$showPurchasePage();
}
if (equipmentKey === "EQ_SMUGGLING_VERSION_UPGRADE") {
p.removeEquipment(equipmentKey);
this._sc_TechVersion += 1;
this._sc_Days = 0;
}
if (stn.allegiance === "galcop" && equipmentKey === "EQ_RENOVATION") {
// is the phase scanner on board
var msgtype = 0;
if (p.equipmentStatus("EQ_PHASE_SCANNER") === "EQUIPMENT_OK" || p.equipmentStatus("EQ_PHASE_SCANNER") === "EQUIPMENT_DAMAGED") {
// oh dear - caught!
p.setBounty(player.bounty + (this.$rand(10) + 10), "illegal equipment");
msgtype += 1;
}
// is the smuggling compartment installed?
if (this.$hasSmugglingCompartment() === true) {
msgtype += 2;
// increase bounty
p.setBounty(player.bounty + (this.$rand(10) + 10), "illegal equipment");
}
var msgBody = "";
switch (msgtype) {
case 0:
break;
case 1:
msgBody = expandDescription("[illegal-equipment-1]");
break;
case 2:
msgBody = expandDescription("[illegal-equipment-2]", {
size: this.$smugglingCompartmentSize()
});
break;
case 3:
msgBody = expandDescription("[illegal-equipment-3]", {
size: this.$smugglingCompartmentSize()
});
break;
}
if (msgBody != "") {
var curChoices = {};
if (player.credits > 0) {
curChoices["01_BRIBE"] = {
text: "[illegal-attempt-bribe]",
color: this._menuColor
};
}
curChoices["98_ACCEPT"] = {
text: "[illegal-accept-penalty]",
color: this._menuColor
};
this._bribeType = 2;
var opts = {
titleKey: "smuggling_illegal_equipment",
message: msgBody,
model: "[" + this._policeModel + "]",
allowInterrupt: false,
exitScreen: "GUI_SCREEN_EQUIP_SHIP",
choices: curChoices,
initialChoicesKey: "98_ACCEPT"
};
mission.runScreen(opts, this.$bribeScreenHandler, this);
}
}
}
//-------------------------------------------------------------------------------------------------------------
/*this.equipmentRemoved = function(equipmentKey) {
if (this._backdoor === true) return;
if (this._equipmentList.indexOf(equipmentKey) >= 0) {
this.$resetCompartmentInfo(player.ship.dockedStation);
return;
}
}*/
//-------------------------------------------------------------------------------------------------------------
this.shipWillDockWithStation = function (station) {
this._policeModel = this.$getPoliceModel();
this._savedBounty = player.bounty;
// grab a snapshot of the players illegal cargo
this._dockIllegal = [];
this._dockingWithSlaves = false;
// if the player has slaves on board, and IGT is installed, then turn on the flag to indicate we're docking with slaves
var escapePods = 0;
if (worldScripts.EscapePodTweaks) {
// if the _escapePods array have data, what means the escape pod tweaks "shipWillDOckWithStation" function hasn't been executed yet
// in that case we need to know how many slaves to ignore
escapePods = worldScripts.EscapePodTweaks._escapePods.length;
// if its been run already, the value will be 0 anyway
}
if (player.ship.manifest["slaves"] && (player.ship.manifest["slaves"] - escapePods) > 0 && this._IGTInstalled === true) {
this._dockingWithSlaves = true;
// make a note of the slaves count, because if we dock with rescued escape pods, the number will have to be reduced during "playerRescuedEscapePod";
this._dockingWithSlavesCount = (player.ship.manifest["slaves"] - escapePods);
}
this._playerHadIllegals = false;
if (this.$playerHasIllegalCargo(station) === true) {
var p = player.ship;
var m = p.manifest;
this._dockIllegal = [];
for (var i = 0; i < m.list.length; i++) {
if (m.list[i].quantity > 0 && station.market[m.list[i].commodity].legality_import > 0) this._dockIllegal.push({
commodity: m.list[i].commodity,
quantity: m.list[i].quantity
});
}
this._playerHadIllegals = true;
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipDockedWithStation = function (station) {
if (station.allegiance === "galcop") {
if (this._dockingWithSlaves === false) this._doCargoCheck = true;
}
// set up smuggling interface screen
this.$initInterface(station);
}
//-------------------------------------------------------------------------------------------------------------
this.shipLaunchedEscapePod = function (escapepod) {
// clear out smugglers compartment when escape pod is used
this._sc_Cargo = [];
}
//-------------------------------------------------------------------------------------------------------------
this.missionScreenOpportunity = function () {
// if IGT is installed, let it run first. it will call the performCargoCheck when it's finished.
if (this._doCargoCheck === true) {
this.$performCargoCheck();
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerRescuedEscapePod = function (fee, reason, occupant) {
if (this._dockingWithSlavesCount > 0) {
this._dockingWithSlavesCount -= 1;
if (this._dockingWithSlavesCount === 0) this._dockingWithSlaves = false;
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipExitedWitchspace = function () {
if (this._galJump === true) {
this._galJump = false;
this.$createSystemPhase();
this.$createSystemDataArray();
}
this._phaseScannerAvailable = false;
this._phaseScannerDetected = false;
if (system.government === 0 && system.info.techlevel >= 8) {
// will this system provide a phase scanner?
if (system.scrambledPseudoRandomNumber(system.ID) > 0.6) this._phaseScannerAvailable = true;
}
}
//-------------------------------------------------------------------------------------------------------------
this.guiScreenWillChange = function (to, from) {
if (to === "GUI_SCREEN_MANIFEST") this.$updateManifest();
}
//-------------------------------------------------------------------------------------------------------------
this.guiScreenChanged = function (to, from) {
if (guiScreen === "GUI_SCREEN_EQUIP_SHIP") {
this._originalCredits = player.credits;
this._savedBounty = player.bounty;
}
if (from === "GUI_SCREEN_MISSION" && this._smugglingScreen) {
this._smugglingScreen = false;
if (this._hudHidden === false && player.ship.hudHidden === true) player.ship.hudHidden = this._hudHidden;
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerEnteredNewGalaxy = function (galaxyNumber) {
this._systemPhase = [];
this._phaseUpdates = [];
this._phaseScanDiscovery = [];
this._galJump = true;
}
//-------------------------------------------------------------------------------------------------------------
this.dayChanged = function (newday) {
if (newday != this._oldday) {
this._sc_Days += 1;
this._oldday = newday;
this._phaseUpdateDays += 1;
if (this._phaseUpdateDays >= 10) {
this._phaseUpdateDays = 0;
var item = this._systemData[this.$rand(this._systemData.length - 1)];
var gov = parseInt(item / 100);
var tl = item - gov;
var newPhase = this.$rand(999);
// remove from the update list
for (var i = this._phaseUpdates.length - 1; i >= 0; i--) {
if (this._phaseUpdates[i].gov === gov && this._phaseUpdates[i].tl === tl) {
this._phaseUpdates.splice(i, 1);
}
}
this.$updatePhase(gov, tl, newPhase);
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.equipmentDamaged = function (equipment) {
if (this._equipmentList.indexOf(equipment) >= 0) {
// work out how many items will be damaged
var remove = this.$rand(3);
var report = [];
var count = 0;
do {
for (var i = 0; i < this._sc_Cargo.length; i++) {
if (count < remove && this._sc_Cargo[i].quantity > 0) {
// nc checks
if (this._sc_Cargo[i].extra != "") {
var dta = [];
log(this.name, "pre: " + this._sc_Cargo[i].extra);
dta = this._sc_Cargo[i].extra.split("/");
if ((this._sc_Cargo[i].quantity - dta.length) == 0) {
dta.shift();
this._sc_Cargo[i].extra = dta.join("/");
log(this.name, "post: " + this._sc_Cargo[i].extra);
}
}
this._sc_Cargo[i].quantity -= 1;
report.push(this._sc_Cargo[i].displayName + expandMissionText("smuggling_cargo_destroyed"));
count += 1;
}
}
} while (count < remove && this._sc_Cargo.length > 0);
this.$cargoCleanUp();
// give the player the bad news
if (report.length > 0) {
for (var i = 0; i < report.length; i++) {
player.consoleMessage(report[i]);
}
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.$addExtraField = function () {
if (this._sc_Cargo.length == 0) return;
for (var i = 0; i < this._sc_Cargo.length; i++) {
if (!this._sc_Cargo[i].hasOwnProperty("extra")) this._sc_Cargo[i].extra = "";
}
}
//-------------------------------------------------------------------------------------------------------------
this.$performCargoCheck = function $performCargoCheck() {
var msgtype = 0;
var p = player.ship;
this._toRemove = [];
this._removeCompartment = false;
this._playerFine = 0;
if (this._doCargoCheck === true) {
this._doCargoCheck = false;
if (this._phaseScannerDetected === true) {
if (player.credits > 1000) {
this._playerFine += 1000;
} else {
this._playerFine = player.credits;
}
// player has already had a legal penalty when the scan was detected, so we don't need to do it again here
}
// is our compartment damaged (and therefore visible?
if (this.$hasSmugglingCompartment() === true && this.$isCompartmentDamaged() === true) {
msgtype = 1;
this._removeCompartment = true;
// increase bounty
p.setBounty(player.bounty + (this.$rand(10) + 10), "illegal equipment");
if (player.credits > 1000) {
this._playerFine += 1000;
} else {
this._playerFine = player.credits;
}
}
// get the list of illegal goods for this system
var si = worldScripts.Smugglers_Illegal;
var goods = si.$illegalGoodsList(system.ID, true);
// if IGT is installed, add slaves onto the list of illegal goods
if (this._IGTInstalled) {
goods.push({
systemID: system.ID,
commodity: "slaves",
started: 0,
end: 0,
description: "",
permit: 0,
scale: 1
});
}
if (msgtype === 0) {
for (var i = 0; i < goods.length; i++) {
// if the visibleAs property equal to an illegal good on this planet? oh dear...it's not going to matter what the chance is...
if (this.$hasSmugglingCompartment() === true && goods[i].commodity.indexOf(this._sc_VisibleAs) >= 0 && si.$playerHasPermit(system.ID, goods[i].commodity, true) === false) {
msgtype = 2;
this._removeCompartment = true;
// increase bounty
p.setBounty(player.bounty + (this.$rand(10) + 10), "illegal equipment");
// fine player
if (player.credits > 1000) {
this._playerFine += 1000;
} else {
this._playerFine = player.credits;
}
}
}
}
// now, goods in the hold that are illegal to import should now automatically fine the player with a bounty increase.
// so we shouldn't have to worry about bounty from this point on.
// what we will do here is remove cargo and possibly fine the player a monetary amount
// base chance is 26% (for tech level 1), but increasing with a systems tech level, to a max of 40% for a tl 15 system
var base = 25 + system.info.techlevel;
var phase_diff = base;
// work out the chance of detection
// check for phase adjuster
if (p.equipmentStatus("EQ_SMUGGLING_PHASE_ADJUSTMENT") === "EQUIPMENT_OK") {
// if we've got the phase adjuster, there's a small boost the the base value, from 22% to 37%
base = 22 + system.info.techlevel;
phase_diff = Math.abs(this.$getSystemPhase(system.ID) - this._sc_Phase) - 3;
// if we're within +/- 3 then it's good enough
if (phase_diff < 0) phase_diff = 0;
// anything over base is considered inconsequential
if (phase_diff > base) phase_diff = base;
}
var chance = phase_diff / 100;
if (this._debug) log(this.name, "Smuggling compartment init chance: " + chance);
// now apply tech level offset. could be 0 through to an extra 12.5% (30/240 = 0.125)
chance += (this._sc_Days > 30 ? 30 : this._sc_Days) / 240;
if (this._debug) log(this.name, "Smuggling compartment final chance: " + chance);
var s_cargo = this.$getSmugglingCargo();
var msg = "";
var permit_failed = false;
var permit_list = "";
var permit_multi = 0;
var permit_ok = "";
var permit_okcount = 0;
var displaycheck = false;
var removecount = 0;
var successcount = 0;
var successmsg = "";
var smuggling_found = false;
// do this here so we only do it once
if (Math.random() < chance) smuggling_found = true;
for (var i = 0; i < goods.length; i++) {
// are there any illegal goods in our standard hold
// get a list of commodities (handles case where there are multiple commdoties in the illegal goods entry
var cmdtylist = goods[i].commodity.split(",");
var quantity_to_check = 0;
for (var j = 0; j < cmdtylist.length; j++) {
// only check if the good is actually marked as illegal
if (this.$commodityIllegalScale(cmdtylist[j]) > 0) {
if (p.manifest[cmdtylist[j]] > 0) {
quantity_to_check += p.manifest[cmdtylist[j]];
}
var hyper = this.$getHyperCargoQuantity(cmdtylist[j]);
if (hyper > 0) {
quantity_to_check += hyper;
}
for (var k = 0; k < s_cargo.length; k++) {
if (cmdtylist[j] === s_cargo[k].commodity && smuggling_found === true) {
quantity_to_check += s_cargo[k].quantity;
}
}
}
}
if (quantity_to_check > 0) {
if (si.$playerHasPermit(system.ID, goods[i].commodity, true) === false) {
// will get here if the player had a permit but it didn't work, or if they didn't have a permit at all.
// check if a permit permit failed to work
if (si.$playerHasPermit(system.ID, goods[i].commodity, false) === true) {
permit_failed = true;
permit_list += (permit_list === "" ? "" : ", ") + si.$translateCommodityList(goods[i].commodity);
permit_multi += 1;
if (goods[i].commodity.indexOf(",") >= 0) permit_multi += 1;
// remove any permit whether it worked or not
si.$removePermit(system.ID, goods[i].commodity);
}
for (var j = 0; j < cmdtylist.length; j++) {
// check the visible carge
if (p.manifest[cmdtylist[j]] > 0) {
// found!
msg += " - " + p.manifest[cmdtylist[j]] + " " + this.$getCommodityType(cmdtylist[j]) + " × " + displayNameForCommodity(cmdtylist[j]) + "\n";
this._toRemove.push({
source: "hold",
commodity: cmdtylist[j]
});
removecount += 1;
// stanndard slave bounty gets added here, because it's not set to be flagged as illegal to import by default
if (this._IGTInstalled === true && cmdtylist[j] === "slaves") {
p.setBounty(player.bounty + (p.manifest[cmdtylist[j]] * goods[i].scale), "illegal imports");
}
}
// check hypercargo
var hyper = this.$checkHyperCargo(cmdtylist[j]);
if (hyper != "") {
msg += hyper + "\n";
p.setBounty(player.bounty + (this.$getHyperCargoQuantity(cmdtylist[j]) * goods[i].scale), "illegal imports");
this._toRemove.push({
source: "hyper",
commodity: cmdtylist[j]
});
removecount += 1;
}
// try to check the smuggling compartment (but only if it hasn't already been discovered)
if (this._removeCompartment === false) {
for (var k = 0; k < s_cargo.length; k++) {
if (cmdtylist[j] === s_cargo[k].commodity) {
if (smuggling_found === true) {
// found!
msg += " - " + s_cargo[k].quantity + this.$getCommodityType(s_cargo[k].commodity) + " × " + displayNameForCommodity(s_cargo[k].commodity) + "\n";
// apply the bounty here, otherwise it won't get applied
p.setBounty(player.bounty + (s_cargo[k].quantity * goods[i].scale), "illegal imports");
//s_cargo[k].quantity = 0;
this._removeCompartment = true;
removecount += 1;
} else {
successcount += 1;
successmsg += (successmsg === "" ? "" : " and ") + displayNameForCommodity(s_cargo[k].commodity);
}
}
}
}
}
} else {
var found = false;
// for any visible cargo (ie not in the cargo hold) for which the player has a permit, we need to refund the bounty
for (var j = 0; j < cmdtylist.length; j++) {
// do we have any of this commodity in our hold?
if (p.manifest[cmdtylist[j]] > 0) {
p.setBounty(player.bounty - (p.manifest[cmdtylist[j]] * goods[i].scale), "import permit");
found = true;
} else {
// check that this cargo wasn't removed by the contracts system
for (var k = 0; k < this._dockIllegal.length; k++) {
if (this._dockIllegal[k].commodity === cmdtylist[j]) found = true;
}
}
// check hypercargo
var hyper = this.$checkHyperCargo(cmdtylist[j]);
if (hyper != "") {
found = true;
}
if (this._removeCompartment === false) {
for (var k = 0; k < s_cargo.length; k++) {
if (cmdtylist[j] === s_cargo[k].commodity && smuggling_found === true) {
// found
found = true;
}
}
}
}
// if we had permitted cargo,
if (found === true) {
permit_ok += (permit_ok === "" ? "" : ", ") + si.$translateCommodityList(goods[i].commodity);
permit_okcount += 1;
if (goods[i].commodity.indexOf(",") > 0) permit_okcount += 1;
// turn on flat to make sure a mission screen appears if we've adjusted the player's bounty
// otherwise the status screen will show an incorrect value in "Legal Status"
if (msgtype === 0) msgtype = 4;
// remove any permit whether it worked or not
si.$removePermit(system.ID, goods[i].commodity);
}
}
}
}
// special case: where we have illegal cargo just before docking, but don't now, and no permit.
// this would mean the contract system removed the cargo after docking
// we still need to give the player an opportunity to bribe their way to a clean slate.
if (msgtype === 0 && this._playerHadIllegals === true && this.$playerHasIllegalCargo(p.dockedStation) === false) {
msgtype = 6;
}
// found illegal cargo
if (msg != "") msgtype = 3;
// switch to the phase scanner message if that was detected but without any cargo
if (this._phaseScannerDetected === true) {
if (msgtype === 0 || msgtype === 4) msgtype = 5;
}
if (permit_list != "") permit_list = permit_list.replace(", ", expandMissionText("smuggling_and"));
var msgTitle = "";
var msgBody = "";
var bigScreen = false;
switch (msgtype) {
case 0:
if (successcount > 0) {
msgTitle = expandMissionText("smuggling_contraband");
msgBody = expandDescription("[smuggling-success]", {
cargo: successmsg
});
}
break;
case 1: //
msgTitle = expandMissionText("smuggling_galcop_alert");
msgBody = expandDescription("[smuggling-fail-1]", {
size: this.$smugglingCompartmentSize()
}) +
(this._phaseScannerDetected === false ? "" : expandDescription("[phase-scanner-removal]")) +
expandDescription("[end-warning]");
break;
case 2:
msgTitle = expandMissionText("smuggling_galcop_alert");
msgBody = expandDescription("[smuggling-fail-2]", {
size: this.$smugglingCompartmentSize(),
commodity: displayNameForCommodity(this._sc_VisibleAs)
}) +
(this._phaseScannerDetected === false ? "" : expandDescription("[phase-scanner-removal]")) +
expandDescription("[end-warning]");
break;
case 3:
var sections = 0;
if (permit_failed) sections += 1;
if (this._removeCompartment) sections += 1;
if (this._phaseScannerDetected) sections += 1;
if (sections === 3 || (sections === 2 && removecount > 4)) bigScreen = true;
msgTitle = expandMissionText("smuggling_galcop_alert");
msgBody = expandDescription("[smuggling-fail-3]", { insert: msg }) +
(permit_failed === false ? "" :
"\n\n" + expandMissionText("smuggling_invalid_permit", {
permit: (permit_multi > 1 ? expandMissionText("smuggling_permits") : expandMissionText("smuggling_permit")),
list: permit_list,
waswere: (permit_multi === 1 ? expandMissionText("smuggling_was") : expandMissionText("smuggling_were")),
fabrication: (permit_multi > 1 ? expandMissionText("smuggling_fabrications") : expandMissionText("smuggling_fabrication"))
})) +
(this._removeCompartment === false ? "" : expandDescription("[smuggling-compartment-removal]", { size: this.$smugglingCompartmentSize() })) +
(this._phaseScannerDetected === false ? "" : expandDescription("[phase-scanner-removal]")) +
expandDescription("[end-warning]");
break;
case 4:
msgTitle = expandMissionText("smuggling_customs");
msgBody = expandDescription("[smuggling_permit]", {
cargo: permit_ok,
permits: (permit_okcount === 1 ? expandMissionText("smuggling_permit") : expandMissionText("smuggling_permits"))
});
break;
case 5:
msgTitle = expandMissionText("smuggling_galcop_alert");
msgBody = expandDescription("[phase-scanner-removal-main]");
break;
case 6:
msgTitle = expandMissionText("smuggling_galcop_alert");
msgBody = expandDescription("[smuggling-fail-4]");
break;
}
if (msgtype >= 1 && msgtype <= 6 && msgtype != 4) {
this._hudHidden = p.hudHidden;
if (bigScreen === true && this.$isBigGuiActive() === false) {
p.hudHidden = true;
this._smugglingScreen = true;
}
var curChoices = {};
curChoices["01_BRIBE"] = {
text: "[illegal-attempt-bribe]",
color: this._menuColor
};
curChoices["99_ACCEPT"] = {
text: "[illegal-accept-penalty]",
color: this._menuColor
};
this._bribeType = 1;
if (msgtype === 6) this._bribeType = 3;
var opts = {
screenID: "docking_with_illegals",
title: msgTitle,
message: msgBody,
allowInterrupt: false,
model: "[" + this._policeModel + "]",
exitScreen: "GUI_SCREEN_STATUS",
choices: curChoices,
initialChoicesKey: "99_ACCEPT"
};
mission.runScreen(opts, this.$bribeScreenHandler, this);
}
if (msgtype === 4 || (msgtype === 0 && successcount > 0)) {
mission.runScreen({
screenID: "dock_successful",
title: msgTitle,
message: msgBody,
model: "[" + this._policeModel + "]",
exitScreen: "GUI_SCREEN_STATUS"
});
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.$bribeScreenHandler = function $bribeScreenHandler(choice) {
if (!choice) return;
if (choice === "99_ACCEPT") {
this.$processRemovals();
}
if (choice === "98_ACCEPT") {
this.$processEquipmentRemovals();
}
if (choice === "01_BRIBE") {
this.$getBribeAmount()
}
}
//-------------------------------------------------------------------------------------------------------------
// initialise the F4 screen entries
this.$initInterface = function $initInterface(station) {
if (this.$hasSmugglingCompartment() === true) {
station.setInterface(this.name, {
title: expandMissionText("smuggling_compartment_title"),
category: expandDescription("[interfaces-category-ship-systems]"),
summary: expandMissionText("smuggling_compartment_summary"),
callback: this.$showInitialSmugglingConfig.bind(this)
});
} else {
station.setInterface(this.name, null);
}
}
//-------------------------------------------------------------------------------------------------------------
// returns true if the smuggling compartment is damaged
this.$isCompartmentDamaged = function $isCompartmentDamaged() {
var eq = this.$getSmugglingCompartmentEquipment();
if (player.ship.equipmentStatus(eq) === "EQUIPMENT_DAMAGED") return true;
return false;
}
//-------------------------------------------------------------------------------------------------------------
// returns true if the smuggling compartment is installed
this.$hasSmugglingCompartment = function $hasSmugglingCompartment() {
for (var i = 1; i <= this._maxTonnage; i++) {
var check = player.ship.equipmentStatus("EQ_SMUGGLING_COMPARTMENT_" + i.toString());
if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") return true;
}
return false;
}
//-------------------------------------------------------------------------------------------------------------
// returns the equipment key of the installed compartment
this.$getSmugglingCompartmentEquipment = function $getSmugglingCompartmentEquipment() {
for (var i = 1; i <= this._maxTonnage; i++) {
var check = player.ship.equipmentStatus("EQ_SMUGGLING_COMPARTMENT_" + i.toString());
if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") return "EQ_SMUGGLING_COMPARTMENT_" + i.toString();
}
return "";
}
//-------------------------------------------------------------------------------------------------------------
// returns the max size of the current compartment
this.$smugglingCompartmentSize = function $smugglingCompartmentSize() {
for (var i = 1; i <= this._maxTonnage; i++) {
var check = player.ship.equipmentStatus("EQ_SMUGGLING_COMPARTMENT_" + i.toString());
if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") return i;
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------
// returns true if the phase scanner is damaged, otherwise false
this.$isPhaseScannerDamaged = function $isPhaseScannerDamaged() {
if (player.ship.equipmentStatus("EQ_PHASE_SCANNER") === "EQUIPMENT_DAMAGED") return true;
return false;
}
//-------------------------------------------------------------------------------------------------------------
// returns true if the phase scanner is installed (even if damaged), otherwise false
this.$isPhaseScannerInstalled = function $isPhaseScannerInstalled() {
var check = player.ship.equipmentStatus("EQ_PHASE_SCANNER");
if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") return true;
return false;
}
//-------------------------------------------------------------------------------------------------------------
// resets smuggling compartment internal data after a compartment is removed
this.$resetCompartmentInfo = function $resetCompartmentInfo(station) {
var p = player.ship;
// move any cargo into the main hold
if (this._sc_Cargo.length > 0) {
for (var i = 0; i < this._sc_Cargo.length; i++) {
p.manifest[this._sc_Cargo[i].commodity] += this._sc_Cargo[i].quantity;
}
this._sc_Cargo = [];
}
this._sc_VisibleAs = "Food";
this._sc_Phase = 1;
this._sc_TechVersion = 1;
this.$initInterface(station);
}
//-------------------------------------------------------------------------------------------------------------
// returns the amount of used space in the compartment
this.$usedSpace = function $usedSpace() {
var t = 0.0;
for (var i = 0; i < this._sc_Cargo.length; i++) {
switch (this._sc_Cargo[i].unit) {
case "t":
t += this._sc_Cargo[i].quantity;
break;
case "kg":
t += (this._sc_Cargo[i].quantity / 1000);
break;
case "g":
t += (this._sc_Cargo[i].quantity / 1000000);
break;
}
}
return t;
}
//-------------------------------------------------------------------------------------------------------------
// returns the amount of available space in the compartment
this.$availableSpace = function $availableSpace() {
var total = this.$smugglingCompartmentSize();
return (total - this.$usedSpace());
}
//-------------------------------------------------------------------------------------------------------------
// clean up any zero amounts
this.$cargoCleanUp = function $cargoCleanUp() {
for (var i = this._sc_Cargo.length - 1; i >= 0; i--) {
if (this._sc_Cargo[i].quantity === 0) {
this._sc_Cargo.splice(i, 1);
}
}
}
//-------------------------------------------------------------------------------------------------------------
// shows the installation page to select a compartment size
this.$showPurchasePage = function $showPurchasePage() {
var curChoices = {};
var p = player.ship;
var stn = p.dockedStation;
var rowAdjust = 0;
var pagesize = 0;
//this._hudHidden = p.hudHidden;
if (this.$isBigGuiActive() === false) {
p.hudHidden = true;
}
this._smugglingScreen = true;
var text = expandDescription("[purchase-page-header]", {
cash: formatCredits(player.credits, true, true)
});
var curr_size = this.$smugglingCompartmentSize();
// what is the maximum allowed for this vessel (35% of available space, maxing out at 20t)
var shipmax = parseInt((p.cargoSpaceCapacity + curr_size) * 0.35);
// make sure we can get at least 1tc
if ((p.cargoSpaceCapacity + curr_size) > 0 && shipmax === 0) shipmax = 1;
// make sure we don't go over the 20 tc limit
if (shipmax > this._maxTonnage) shipmax = this._maxTonnage;
var max;
var check = (p.cargoSpaceAvailable + curr_size);
if (check < 0) {
max += check;
} else {
max = check;
}
if (max > this._maxTonnage) max = this._maxTonnage;
if (curr_size > 0) {
text += expandDescription("[downgrade-warning]");
rowAdjust += 2;
}
pagesize = 23 - rowAdjust;
var count = 0;
for (var i = 1; i <= this._maxTonnage; i++) {
var eq = EquipmentInfo.infoForKey("EQ_SMUGGLING_COMPARTMENT_" + i.toString());
var inst_time = ((600 + (eq.price * stn.equipmentPriceFactor)) / 60) / 60;
var price = (eq.price / 10) * stn.equipmentPriceFactor;
var menuitem = this.$padTextLeft(expandMissionText("smuggling_compartment_item", { size: i }), 6) +
this.$padTextLeft(formatCredits(price, true, true), 7) +
this.$padTextLeft(expandMissionText("smuggling_compartment_time", { time: inst_time.toFixed(2) }), 15);
if (i <= shipmax) {
count += 1;
if (i != curr_size && i <= max && player.credits >= price) {
curChoices["01_HOLD_" + (i < 10 ? "0" : "") + i + "~" + i] = {
text: menuitem,
alignment: "LEFT",
color: this._menuColor
};
} else {
curChoices["01_HOLD_" + (i < 10 ? "0" : "") + i + "~" + i] = {
text: menuitem,
alignment: "LEFT",
color: this._disabledColor,
unselectable: true
};
}
}
}
curChoices["98_SPACER"] = "";
curChoices["99_EXIT"] = {
text: "[exit-no-change]",
color: this._itemColor
};
var def = "99_EXIT";
if ((count + 1) < pagesize) {
for (var i = (pagesize - (count + 1)); i > 0; i--) {
curChoices["99_SPACER_" + (i < 10 ? "0" : "") + i] = "";
}
}
var opts = {
screenID: "oolite-smuggling-purchase-map",
titleKey: "smuggling_compartment_title",
allowInterrupt: true,
overlay: {
name: "stgu-cupboard.png",
height: 546
},
exitScreen: "GUI_SCREEN_EQUIP_SHIP",
choices: curChoices,
initialChoicesKey: def,
message: text
};
mission.runScreen(opts, this.$purchaseScreenHandler, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$purchaseScreenHandler = function $purchaseScreenHandler(choice) {
if (!choice) return;
if (choice.indexOf("01_HOLD") >= 0) {
var p = player.ship;
var stn = p.dockedStation;
var newsize = parseInt(choice.substring(choice.indexOf("~") + 1));
var newEq = this._equipmentList[newsize - 1];
var oldEq = this.$getSmugglingCompartmentEquipment();
// truncate any existing cargo
if (newsize < this.$usedSpace()) {
var diff = this.$usedSpace - newsize;
do {
for (var i = this._sc_Cargo.length; i >= 0; i--) {
if (diff > 0) {
switch (this._sc_Cargo[i].unit) {
case "t":
this._sc_Cargo[i].quantity -= 1;
diff -= 1;
break;
case "kg":
if (this._sc_Cargo[i].quantity > 1000) {
this._sc_Cargo[i].quantity -= 1000;
diff -= 1;
}
break;
case "g":
if (this._sc_Cargo[i].quantity > 1000000) {
this._sc_Cargo[i].quantity -= 1000000;
diff -= 1;
}
}
}
}
} while (diff > 0);
this.$cargoCleanUp();
}
// remove the old one (if present)
if (oldEq != "") {
this._backdoor = true;
p.removeEquipment(oldEq);
this._backdoor = false;
// refund the price of the old version
var oldEqInfo = EquipmentInfo.infoForKey(oldEq);
player.credits += ((oldEqInfo.price / 10) * stn.equipmentPriceFactor);
}
// install the new one
p.awardEquipment(newEq);
p.awardEquipment("EQ_SMUGGLING_INFLIGHT_STORAGE");
var eq = EquipmentInfo.infoForKey(newEq);
var inst_time = 600 + (eq.price * stn.equipmentPriceFactor);
var price = (eq.price / 10) * stn.equipmentPriceFactor;
// charge the player
player.credits -= price;
// add the smuggler role to the player
player.setPlayerRole("trader-smuggler");
// apply the install time
clock.addSeconds(inst_time);
// if StationDockControl is installed, tell it to check for launched ships and repopulate
var sdc = worldScripts.StationDockControl;
if (sdc && sdc._disable === false) sdc.$checkForLaunchedShips();
this.$initInterface(stn);
this._sc_Days = 0;
// make sure the right email is sent to the player
var email = worldScripts.GalCopAdminServices;
if (email) {
email._boughtKey = newEq;
email.$playerBoughtEquip();
}
}
}
//-------------------------------------------------------------------------------------------------------------
// initial entry point for the smuggling compartment config screen
this.$showInitialSmugglingConfig = function $showInitialSmugglingConfig() {
this._display = 0;
this.$showSmugglingConfig();
}
//-------------------------------------------------------------------------------------------------------------
// main config screen display
this.$showSmugglingConfig = function $showSmugglingConfig() {
function compare(a, b) {
if ((a.gov * 100) + a.tl < (b.gov * 100) + b.tl) return -1;
if ((a.gov * 100) + a.tl > (b.gov * 100) + b.tl) return 1;
return 0;
}
var text = "";
var curChoices = {};
var p = player.ship;
var pagesize = 26;
var phaseSetting = false;
if (p.equipmentStatus("EQ_SMUGGLING_PHASE_ADJUSTMENT") === "EQUIPMENT_OK") phaseSetting = true;
this._hudHidden = p.hudHidden;
if (this.$isBigGuiActive() === false) p.hudHidden = true;
this._smugglingScreen = true;
if (this.$isCompartmentDamaged() === true) this._display = 10;
// main display
if (this._display === 0) {
var lines = 5;
text = expandDescription("[total-capacity-header]") + this.$smugglingCompartmentSize() + "t " + Math.floor(this.$usedSpace()) + "t used.\n";
text += expandDescription("[visible-as-header]") + displayNameForCommodity(this._sc_VisibleAs) + " ";
if (phaseSetting) text += expandMissionText("smuggling_phase", { phase: this._sc_Phase }) + " ";
text += expandDescription("[tech-version-header]") + this._sc_TechVersion + ".0\n";
if (this._sc_Days >= 20) {
text += expandDescription("[tech-version-warning]");
lines += 1;
}
text += "\n";
lines += 6;
if (phaseSetting === false) lines -= 1;
var cargo = this.$getSmugglingCargo();
if (cargo.length > 0) {
text += expandDescription("[smuggling-current-contents]");
lines += 1;
var additem = "";
for (var i = 0; i < this._sc_Cargo.length; i++) {
if (additem === "") {
additem += " " + this.$padTextRight(this._sc_Cargo[i].quantity + this._sc_Cargo[i].unit + " × " + displayNameForCommodity(this._sc_Cargo[i].commodity) + (this._sc_Cargo[i].extra != "" ? "*" : ""), 17);
} else {
additem += this._sc_Cargo[i].quantity + this._sc_Cargo[i].unit + " × " + displayNameForCommodity(this._sc_Cargo[i].commodity) + (this._sc_Cargo[i].extra != "" ? "*" : "");
text += additem + "\n";
lines += 1;
additem = "";
}
}
if (additem != "") {
text += additem + "\n";
lines += 1;
}
} else {
text += expandDescription("[smuggling-no-contents]");
lines += 2;
}
if (phaseSetting) {
curChoices["01_SET_PHASE"] = {
text: "[smuggling-set-phase]",
color: this._menuColor
};
}
curChoices["02_VIEW_DISCOVERED"] = {
text: "[smuggling-view-phase]",
color: this._menuColor
};
curChoices["03_SET_VISIBLE"] = {
text: "[smuggling-set-visible-as]",
color: this._menuColor
};
var avail = this.$availableSpace();
var used = this.$usedSpace();
if (this.$playerHasCargo() === true && avail > 0) {
curChoices["04_MOVE_CARGO_IN"] = {
text: "[smuggling-move-in]",
color: this._menuColor
};
} else {
curChoices["04_MOVE_CARGO_IN"] = {
text: "[smuggling-move-in]",
color: this._disabledColor,
unselectable: true
};
}
if (used > 0) {
curChoices["05_MOVE_CARGO_OUT"] = {
text: "[smuggling-move-out]",
color: this._menuColor
};
} else {
curChoices["05_MOVE_CARGO_OUT"] = {
text: "[smuggling-move-out]",
color: this._disabledColor,
unselectable: true
};
}
if (used > 0) {
curChoices["06_SELL_CARGO"] = {
text: "[smuggling-sell-from]",
color: this._menuColor
};
} else {
curChoices["06_SELL_CARGO"] = {
text: "[smuggling-sell-from]",
color: this._disabledColor,
unselectable: true
};
}
if (avail > 0) {
curChoices["07_BUY_CARGO"] = {
text: "[smuggling-buy-in]",
color: this._menuColor
};
} else {
curChoices["07_BUY_CARGO"] = {
text: "[smuggling-buy-in]",
color: this._disabledColor,
unselectable: true
};
}
//curChoices["70_SPACER"] = "";
curChoices["99_EXIT"] = {
text: "[smuggling-exit-config]",
color: this._itemColor
};
pagesize = 26;
if (lines < pagesize) {
for (var i = (pagesize - lines); i > 0; i--) {
curChoices["99_SPACER_" + (i < 10 ? "0" : "") + i] = "";
}
}
var def = "99_EXIT";
var opts = {
screenID: "oolite-smuggling-config-summary",
titleKey: "smuggling_compartment_config",
allowInterrupt: true,
overlay: {
name: "stgu-cupboard.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// set visible property
if (this._display === 1) {
text = expandDescription("[visible-as-property]", {
commodity: displayNameForCommodity(this._sc_VisibleAs)
});
for (var i = 0; i < this._commodityIDList.length; i++) {
if (this._sc_VisibleAs === this._commodityIDList[i]) {
curChoices["40_" + (i < 10 ? "0" : "") + i + "~" + this._commodityIDList[i]] = {
text: displayNameForCommodity(this._commodityIDList[i]),
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["40_" + (i < 10 ? "0" : "") + i + "~" + this._commodityIDList[i]] = {
text: displayNameForCommodity(this._commodityIDList[i]),
color: this._menuColor
};
}
}
curChoices["97_SPACER"] = "";
curChoices["98_EXIT"] = {
text: "[exit-no-change]",
color: this._itemColor
};
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-config-map",
titleKey: "smuggling_compartment_config",
allowInterrupt: true,
overlay: {
name: "stgu-cupboard.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
if (this._display === 2) { // move cargo in
// todo: deal with new cargoes
var avail = this.$availableSpace();
text = expandDescription("[move-cargo-in]", {
smuggling: Math.floor(avail),
standard: p.cargoSpaceAvailable
});
pagesize = 20;
var cargo = p.manifest.list;
var sdm = worldScripts.Smugglers_DockMaster;
var itemcount = 0;
for (var i = 0; i < cargo.length; i++) {
// only show standard (non-OXP) commodity items
if (this._commodityIDList.indexOf(cargo[i].commodity) >= 0) {
var q = cargo[i].quantity;
// make sure we don't move relabelled cargo
if (sdm._cargoLabelled.length > 0) {
for (var j = 0; j < sdm._cargoLabelled.length; j++) {
if (sdm._cargoLabelled[j].newCommodity === cargo[i].commodity) q -= sdm._cargoLabelled[j].quantity;
}
}
// don't allow scooped escape pods to be moved
if (cargo[i].commodity === "slaves" && cargo[i].quantity > 0 && worldScripts.EscapePodTweaks && worldScripts.EscapePodTweaks._heldPods.length > 0) {
q -= worldScripts.EscapePodTweaks._heldPods;
}
if (q > 0) {
curChoices["50_" + (i < 10 ? "0" : "") + i + "_CARGO~" + cargo[i].commodity] = {
text: cargo[i].displayName + " (" + q + cargo[i].unit + ")" + (this.$calcCTEcargo(cargo[i].commodity) > 0 ? "*" : ""),
color: this._menuColor
};
itemcount += 1;
}
}
}
curChoices["97_SPACER"] = "";
curChoices["98_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
for (var i = 1; i <= (pagesize - itemcount); i++) {
curChoices["99_SPACER_" + (i < 10 ? "0" : "") + i] = "";
}
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-movecargoin-map",
titleKey: "smuggling_compartment_cargo",
allowInterrupt: true,
overlay: {
name: "stgu-cupboard.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
if (this._display === 3) { // move cargo out
// todo: deal with new cargoes
var avail = this.$availableSpace();
text = expandDescription("[move-cargo-out]", {
smuggling: Math.floor(avail),
standard: p.cargoSpaceAvailable
});
pagesize = 20;
var cargo = this.$getSmugglingCargo();
for (var i = 0; i < cargo.length; i++) {
if ((p.cargoSpaceAvailable === 0 && cargo[i].unit != "t") || p.cargoSpaceAvailable > 0) {
curChoices["51_" + (i < 10 ? "0" : "") + i + "_CARGO~" + cargo[i].commodity] = {
text: cargo[i].quantity + " " + cargo[i].unit + " × " + cargo[i].displayName + (cargo[i].extra != "" ? "*" : ""),
color: this._menuColor
};
}
}
curChoices["97_SPACER"] = "";
curChoices["98_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
for (var i = 1; i <= (pagesize - cargo.length); i++) {
curChoices["99_SPACER_" + (i < 10 ? "0" : "") + i] = "";
}
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-movecargoout-map",
titleKey: "smuggling_compartment_cagro",
allowInterrupt: true,
overlay: {
name: "stgu-cupboard.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
if (this._display === 4) { // view discovered phase settings
// look for and remove any TL0 items in the list
// why are we doing this???
//for (var i = this._phaseScanDiscovery.length - 1; i >= 0; i--) {
// if (this._phaseScanDiscovery[i].tl === 0) {
// this._phaseScanDiscovery.splice(i, 1);
// }
//}
// sort the list by government/techlevel
this._phaseScanDiscovery.sort(compare);
var govs = new Array();
for (var i = 0; i < 8; i++)
govs.push(String.fromCharCode(i));
var spc = String.fromCharCode(31);
text = expandDescription("[discovered-phase-scans]");
if (this._phaseScanDiscovery.length === 0) {
text += " None";
} else {
for (var i = 0; i < 24; i++) {
if (this._phaseScanDiscovery.length - 1 >= i && this._phaseScanDiscovery[i].phase != 0) {
text += this.$padTextRight(govs[this._phaseScanDiscovery[i].gov] + spc + "TL" + (this._phaseScanDiscovery[i].tl + 1) + ":", 3.7) + this.$padTextRight(this._phaseScanDiscovery[i].phase, 3);
}
if (this._phaseScanDiscovery.length - 1 >= (i + 24) && this._phaseScanDiscovery[i + 24].phase != 0) {
text += this.$padTextRight(govs[this._phaseScanDiscovery[i + 24].gov] + spc + "TL" + (this._phaseScanDiscovery[i + 24].tl + 1) + ":", 3.7) + this.$padTextRight(this._phaseScanDiscovery[i + 24].phase, 3);
}
if (this._phaseScanDiscovery.length - 1 >= (i + 48) && this._phaseScanDiscovery[i + 48].phase != 0) {
text += this.$padTextRight(govs[this._phaseScanDiscovery[i + 48].gov] + spc + "TL" + (this._phaseScanDiscovery[i + 48].tl + 1) + ":", 3.7) + this.$padTextRight(this._phaseScanDiscovery[i + 48].phase, 3);
}
if (this._phaseScanDiscovery.length - 1 >= (i + 72) && this._phaseScanDiscovery[i + 72].phase != 0) {
text += this.$padTextRight(govs[this._phaseScanDiscovery[i + 72].gov] + spc + "TL" + (this._phaseScanDiscovery[i + 72].tl + 1) + ":", 3.7) + this.$padTextRight(this._phaseScanDiscovery[i + 72].phase, 3);
}
if (this._phaseScanDiscovery.length - 1 >= (i + 96) && this._phaseScanDiscovery[i + 96].phase != 0) {
text += this.$padTextRight(govs[this._phaseScanDiscovery[i + 96].gov] + spc + "TL" + (this._phaseScanDiscovery[i + 96].tl + 1) + ":", 3.7) + this._phaseScanDiscovery[i + 96].phase;
}
text += "\n";
}
}
curChoices["98_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-discovered-map",
titleKey: "smuggling_compartment_config",
allowInterrupt: true,
overlay: {
name: "stgu-cupboard.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// sell cargo from compartment
if (this._display === 5) {
// deal with new cargoes
text = expandDescription("[sell-smuggling-cargo]");
pagesize = 23;
if (this._extraMessage) {
text += "\n(Note: " + this._extraMessage + ")";
pagesize -= 1;
delete this._extraMessage;
}
var cargo = this.$getSmugglingCargo();
var mkt = p.dockedStation.market;
for (var i = 0; i < cargo.length; i++) {
curChoices["52_" + (i < 10 ? "0" : "") + i + "_CARGO~" + cargo[i].commodity] = {
text: this.$padTextRight(cargo[i].quantity + " " + cargo[i].unit + " × " + cargo[i].displayName, 12) +
(cargo[i].extra != "" ? "*" : "") +
this.$padTextLeft(formatCredits((mkt[cargo[i].commodity].price / 10), true, true), 5),
color: this._menuColor
};
}
curChoices["97_SPACER"] = "";
curChoices["98_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
for (var i = 1; i <= (pagesize - cargo.length); i++) {
curChoices["99_SPACER_" + (i < 10 ? "0" : "") + i] = "";
}
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-sellcargo-map",
titleKey: "smuggling_compartment_sell",
allowInterrupt: true,
overlay: {
name: "stgu-cupboard.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// buy cargo directly to compartment
if (this._display === 6) {
text = expandDescription("[buy-smuggling-cargo]");
pagesize = 23;
if (this._insufficientFunds && this._insufficientFunds === true) {
text += "\n" + expandMissionText("smuggling_no_funds", { commodity: displayNameForCommodity(this._tfrCargo) });
pagesize = 22;
}
var mkt = p.dockedStation.market;
var itemorder = 0;
var itemcount = 0;
for (var i in mkt) {
if (this._commodityIDList.indexOf(i) >= 0) {
if (mkt[i].quantity > 0) {
itemorder = parseInt(mkt[i].sort_order / 100);
curChoices["53_" + (itemorder < 10 ? "0" : "") + itemorder + "_CARGO~" + i] = {
text: this.$padTextRight(displayNameForCommodity(i), 8) +
this.$padTextLeft(formatCredits((mkt[i].price / 10), true, true), 4) +
this.$padTextLeft(mkt[i].quantity, 4) + " " +
this.$padTextRight(this.$getCommodityType(i), 2),
color: this._menuColor
};
itemcount += 1;
}
}
}
curChoices["97_SPACER"] = "";
curChoices["98_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
for (var i = 1; i <= (pagesize - itemcount); i++) {
curChoices["99_SPACER_" + (i < 10 ? "0" : "") + i] = "";
}
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-buycargo-map",
titleKey: "smuggling_compartment_buy",
allowInterrupt: true,
overlay: {
name: "stgu-cupboard.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
if (this._display === 10) {
text = expandDescription("[smuggling-compartment-damaged]");
curChoices["99_EXIT"] = {
text: "[smuggling-exit-config]",
color: this._itemColor
};
var opts = {
screenID: "smuggling_compartment_damaged",
titleKey: "smuggling_compartment_config",
message: text,
choices: curChoices,
overlay: {
name: "stgu-lock.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES"
};
}
mission.runScreen(opts, this.$configScreenHandler, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$configScreenHandler = function $configScreenHandler(choice) {
if (!choice) return;
switch (choice) {
case "01_SET_PHASE":
this.$setPhase();
break;
case "02_VIEW_DISCOVERED":
this._display = 4;
break;
case "03_SET_VISIBLE":
this._display = 1;
break;
case "04_MOVE_CARGO_IN":
this._display = 2;
break;
case "05_MOVE_CARGO_OUT":
this._display = 3;
break;
case "06_SELL_CARGO":
this._display = 5;
break;
case "07_BUY_CARGO":
this._display = 6;
break;
case "98_EXIT":
this._display = 0;
break;
}
if (choice.indexOf("40_") >= 0) {
this._sc_VisibleAs = choice.substring(choice.indexOf("~") + 1);
this._display = 0;
}
var showMain = true;
if (choice.indexOf("50_") >= 0) {
showMain = false;
this._tfrCargo = choice.substring(choice.indexOf("~") + 1);
var cargo = player.ship.manifest.list;
var sdm = worldScripts.Smugglers_DockMaster;
for (var i = 0; i < cargo.length; i++) {
if (cargo[i].commodity === this._tfrCargo) {
var q = cargo[i].quantity;
// make sure we don't move relabelled cargo
if (sdm._cargoLabelled.length > 0) {
for (var j = 0; j < sdm._cargoLabelled.length; j++) {
if (sdm._cargoLabelled[j].newCommodity === cargo[i].commodity) q -= sdm._cargoLabelled[j].quantity;
}
}
// don't allow scooped escape pods to be moved
if (cargo[i].commodity === "slaves" && cargo[i].quantity > 0 && worldScripts.EscapePodTweaks && worldScripts.EscapePodTweaks._heldPods.length > 0) {
q -= worldScripts.EscapePodTweaks._heldPods;
}
this._tfrCargoName = cargo[i].displayName;
this._tfrMaxAmount = q;
this._tfrUnit = cargo[i].unit;
this._tfrExtra = this.$calcCTEcargo(cargo[i].commodity).toString();
var avail = this.$smugglingCompartmentSize();
var used = this.$usedSpace();
// make sure our max amount set isn't greater than the cargo space limit
switch (this._tfrUnit) {
case "t":
if (this._tfrMaxAmount > (avail - used)) {
this._tfrMaxAmount = avail - used;
}
break;
case "kg":
var sub_avail = avail * 1000;
var sub_used = used * 1000;
if (this._tfrMaxAmount > (sub_avail - sub_used)) this._tfrMaxAmount = sub_avail - sub_used;
break;
case "g":
var sub_avail = avail * 1000000;
var sub_used = used * 1000000;
if (this._tfrMaxAmount > (sub_avail - sub_used)) this._tfrMaxAmount = sub_avail - sub_used;
break;
}
this.$getTransferAmount(1);
}
}
}
if (choice.indexOf("51_") >= 0) {
showMain = false;
this._tfrCargo = choice.substring(choice.indexOf("~") + 1);
var cargo = this.$getSmugglingCargo();
for (var i = 0; i < cargo.length; i++) {
if (cargo[i].commodity === this._tfrCargo) {
this._tfrCargoName = cargo[i].displayName;
this._tfrMaxAmount = cargo[i].quantity;
this._tfrUnit = cargo[i].unit;
this._tfrExtra = cargo[i].extra.split(";").length.toString();
var avail = player.ship.cargoSpaceAvailable;
// make sure our max amount set isn't greater than the cargo space limit
switch (this._tfrUnit) {
case "t":
if (this._tfrMaxAmount > avail) this._tfrMaxAmount = avail;
break;
case "kg":
var sub_avail = avail * 1000;
if (this._tfrMaxAmount > sub_avail) this._tfrMaxAmount = sub_avail;
break;
case "g":
var sub_avail = avail * 1000000;
if (this._tfrMaxAmount > sub_avail) this._tfrMaxAmount = sub_avail;
break;
}
this.$getTransferAmount(2);
}
}
}
if (choice.indexOf("52_") >= 0) {
showMain = false;
this._tfrCargo = choice.substring(choice.indexOf("~") + 1);
var cargo = this.$getSmugglingCargo();
for (var i = 0; i < cargo.length; i++) {
if (cargo[i].commodity === this._tfrCargo) {
this._tfrCargoName = cargo[i].displayName;
this._tfrMaxAmount = cargo[i].quantity;
this._tfrExtra = cargo[i].extra.split(";").length.toString();
var stn = player.ship.dockedStation;
// limit the max amount by the market capacity
var check = stn.market[this._tfrCargo].capacity - stn.market[this._tfrCargo].quantity;
if (this._tfrMaxAmount > check) this._tfrMaxAmount = check;
// if the max amount we can transfer is zero, return to the previous menu.
if (this._tfrMaxAmount === 0) {
this._extraMessage = expandMissionText("smuggling_market_cap", { commodity: cargo[i].displayName });
this.$showSmugglingConfig();
return;
}
this._tfrUnit = cargo[i].unit;
this.$getTransferAmount(3);
}
}
}
if (choice.indexOf("53_") >= 0) {
showMain = false;
this._insufficientFunds = false;
this._tfrCargo = choice.substring(choice.indexOf("~") + 1);
var cargoItem = player.ship.dockedStation.market[this._tfrCargo];
this._tfrCargoName = displayNameForCommodity(this._tfrCargo);
this._tfrUnit = this.$getCommodityType(this._tfrCargo);
this._tfrMaxAmount = cargoItem.quantity;
this._tfrExtra = "";
var avail = this.$availableSpace();
switch (this._tfrUnit) {
case "t":
if (avail < this._tfrMaxAmount) this._tfrMaxAmount = avail;
break;
case "kg":
var sub_avail = avail * 1000;
if (sub_avail < this._tfrMaxAmount) this._tfrMaxAmount = sub_avail;
break;
case "g":
var sub_avail = avail * 1000000;
if (sub_avail < this._tfrMaxAmount) this._tfrMaxAmount = sub_avail;
break;
}
if ((this._tfrMaxAmount * (cargoItem.price / 10)) > player.credits) {
do {
this._tfrMaxAmount -= 1;
} while ((this._tfrMaxAmount * (cargoItem.price / 10)) > player.credits)
}
if (this._tfrMaxAmount > 0) {
this.$getTransferAmount(4);
} else {
showMain = true;
this._insufficientFunds = true;
}
}
if (choice != "99_EXIT" && choice != "01_SET_PHASE" && showMain === true) {
this.$showSmugglingConfig();
}
}
//-------------------------------------------------------------------------------------------------------------
// returns true if the player has any cargo at all
this.$playerHasCargo = function $playerHasCargo() {
var m = player.ship.manifest;
for (var i = 0; i < m.list.length; i++) {
if (m.list[i].quantity > 0) return true;
}
return false;
}
//-------------------------------------------------------------------------------------------------------------
// returns true if the player has any illegal cargo in the visible cargo hold
this.$playerHasIllegalCargo = function $playerHasIllegalCargo(station) {
var m = player.ship.manifest;
for (var i = 0; i < m.list.length; i++) {
if (m.list[i].quantity > 0 && station.market[m.list[i].commodity].legality_import > 0) {
return true;
}
}
return false;
}
//-------------------------------------------------------------------------------------------------------------
// returns true if the player has any illegal cargo in their smuggling compartment
this.$playerHasHiddenIllegalCargo = function $playerHasHiddenIllegalCargo(station) {
var c = this.$getSmugglingCargo();
var found = false;
for (var i = 0; i < c.length; i++) {
if (station.market[c[i].commodity].legality_import > 0) found = true;
}
return found;
}
//-------------------------------------------------------------------------------------------------------------
// prompts the user for a new phase
this.$setPhase = function $setPhase() {
var text = "";
text = expandDescription("[set-phase]", {
current: this._sc_Phase
});
var opts = {
screenID: "oolite-smuggling-setphase-map",
titleKey: "smuggling_compartment_config",
allowInterrupt: false,
exitScreen: "GUI_SCREEN_INTERFACES",
message: text,
textEntry: true
};
mission.runScreen(opts, this.$getNewPhase, this);
}
//-------------------------------------------------------------------------------------------------------------
// parses the input from the setPhase screen
this.$getNewPhase = function $getNewPhase(param) {
if (parseInt(param) >= 1 && parseInt(param) <= 999) {
this._sc_Phase = parseInt(param);
}
this.$showSmugglingConfig();
}
//-------------------------------------------------------------------------------------------------------------
// prompts the user for the transfer amount
this.$getTransferAmount = function $getTransferAmount(type) {
var text = "";
// don't show a screen when only 1 unit is possible
if (this._tfrMaxAmount === 1) {
switch (type) {
case 1:
this.$getCargoTransferIn(1);
return;
case 2:
this.$getCargoTransferOut(1);
return;
case 3:
this.$getCargoSell(1);
return;
case 4:
this.$getCargoBuy(1);
return;
}
}
switch (type) {
case 1:
text = expandDescription("[enter-quantity-smuggling]", {
commodity: this._tfrCargoName,
quantity: parseInt(this._tfrMaxAmount),
cte_note: (this._tfrExtra != "" ? "\n\n" + expandMissionText("smuggling_newcargoes_note", {extra:this._tfrExtra}) : "")
});
break;
case 2:
text = expandDescription("[enter-quantity-standard]", {
commodity: this._tfrCargoName,
quantity: parseInt(this._tfrMaxAmount),
cte_note: (this._tfrExtra != "" ? "\n\n" + expandMissionText("smuggling_newcargoes_note", {extra:this._tfrExtra}) : "")
});
break;
case 3:
text = expandDescription("[enter-quantity-sell]", {
commodity: this._tfrCargoName,
quantity: parseInt(this._tfrMaxAmount),
cte_note: (this._tfrExtra != "" ? "\n\n" + expandMissionText("smuggling_newcargoes_note", {extra:this._tfrExtra}) : "")
});
break;
case 4:
text = expandDescription("[enter-quantity-buy]", {
commodity: this._tfrCargoName,
quantity: parseInt(this._tfrMaxAmount)
});
break;
}
var opts = {
screenID: "oolite-smuggling-transfer-map",
titleKey: "smuggling_compartment_cargo",
allowInterrupt: false,
exitScreen: "GUI_SCREEN_INTERFACES",
message: text,
textEntry: true
};
switch (type) {
case 1:
mission.runScreen(opts, this.$getCargoTransferIn, this);
break;
case 2:
mission.runScreen(opts, this.$getCargoTransferOut, this);
break;
case 3:
mission.runScreen(opts, this.$getCargoSell, this);
break;
case 4:
mission.runScreen(opts, this.$getCargoBuy, this);
break;
}
}
//-------------------------------------------------------------------------------------------------------------
// parses the input from the getTransferAmount screen
this.$getCargoTransferIn = function $getCargoTransferIn(param) {
if (!param) {
this.$showSmugglingConfig();
return;
}
if (parseInt(param) >= 1 && parseInt(param) <= this._tfrMaxAmount) {
var p = player.ship;
var max = p.manifest[this._tfrCargo];
var amount = parseInt(param);
var extra = "";
if (this._NCInstalled) {
extra = this.$extractCargoFromCTE(this._tfrCargo, amount, max);
}
this.$addCargoToCompartment(this._tfrCargo, this._tfrCargoName, amount, this._tfrUnit, extra);
// take the cargo out of the hold
var p = player.ship;
p.manifest[this._tfrCargo] -= amount;
}
this._display = 2;
if (this.$availableSpace() === 0) this._display = 0;
this.$showSmugglingConfig();
}
//-------------------------------------------------------------------------------------------------------------
this.$calcCTEcargo = function (generic) {
var cte = worldScripts.CargoTypeExtension;
// if there isn't enough generic cargo of a particular type
// throw out special cargo entries of that type until there is
var totalspecial = 0;
for (var j = 0; j < cte.specialCargoCarried[generic].length; j++) {
if (cte.specialCargoRegister[cte.specialCargoCarried[generic][j].type]) {
totalspecial += cte.specialCargoCarried[generic][j].quantity;
}
}
return totalspecial;
}
//-------------------------------------------------------------------------------------------------------------
// parses the input from the getTransferAmount screen
this.$getCargoTransferOut = function $getCargoTransferOut(param) {
if (!param) {
this.$showSmugglingConfig();
return;
}
if (parseInt(param) >= 1 && parseInt(param) <= this._tfrMaxAmount) {
var p = player.ship;
var amount = parseInt(param);
var starting = p.manifest[this._tfrCargo];
// put the cargo into the main hold
p.manifest[this._tfrCargo] += amount;
// check that the hold actually took all the amount
if (p.manifest[this._tfrCargo] != (starting + amount)) {
// if not, adjust the amount of transfer
amount = p.manifest[this._tfrCargo] - starting;
}
for (var i = 0; i < this._sc_Cargo.length; i++) {
if (this._sc_Cargo[i].commodity === this._tfrCargo) {
if (this._NCInstalled) {
var ncmanifest = this.$checkForAndRemoveCTECargo(this._tfrCargo, amount);
if (ncmanifest != "") {
var cte = worldScripts.CargoTypeExtension;
cte.mergePlayerManifest(ncmanifest);
}
}
this._sc_Cargo[i].quantity -= amount;
break;
}
}
this.$cargoCleanUp();
}
this._display = 3;
if (this.$usedSpace() === 0) this._display = 0;
this.$showSmugglingConfig();
}
//-------------------------------------------------------------------------------------------------------------
// parses the input from the getTransferAmount screen
this.$getCargoSell = function $getCargoSell(param) {
if (!param) {
this.$showSmugglingConfig();
return;
}
if (parseInt(param) >= 1 && parseInt(param) <= this._tfrMaxAmount) {
var amount = parseInt(param);
var count = 0;
var check = 0;
var p = player.ship;
var stn = p.dockedStation;
var mkt = stn.market;
for (var i = this._sc_Cargo.length - 1; i >= 0; i--) {
if (this._sc_Cargo[i].commodity === this._tfrCargo) {
check = mkt[this._tfrCargo].quantity;
var newamount = check + amount;
var actual = amount;
// check that we aren't going over the market capacity
if (newamount > mkt[this._tfrCargo].capacity) {
newamount = mkt[this._tfrCargo].capacity;
actual = newamount - check;
}
// only do an sell if the actual amount that can be sold is greater than zero
if (actual > 0) {
stn.setMarketQuantity(this._tfrCargo, newamount);
this.$checkForAndRemoveCTECargo(this._tfrCargo, actual);
this._sc_Cargo[i].quantity -= actual;
count += actual;
player.credits += (mkt[this._tfrCargo].price / 10) * actual;
this.$playSound("sell");
}
break;
}
}
this.$cargoCleanUp();
}
this._display = 5;
if (this.$usedSpace() === 0) this._display = 0;
this.$showSmugglingConfig();
}
//-------------------------------------------------------------------------------------------------------------
// parses the input from the getTransferAmount screen
this.$getCargoBuy = function $getCargoBuy(param) {
if (!param) {
this.$showSmugglingConfig();
return;
}
if (parseInt(param) >= 1 && parseInt(param) <= this._tfrMaxAmount) {
var amount = parseInt(param);
this.$addCargoToCompartment(this._tfrCargo, this._tfrCargoName, amount, this._tfrUnit, "");
// take the cargo out of the market
var stn = player.ship.dockedStation;
var mkt = stn.market;
var newamount = mkt[this._tfrCargo].quantity - amount;
stn.setMarketQuantity(this._tfrCargo, newamount);
player.credits -= (mkt[this._tfrCargo].price / 10) * amount;
this.$playSound("buy");
}
this._display = 6;
if (this.$availableSpace() === 0) this._display = 0;
this.$showSmugglingConfig();
}
//-------------------------------------------------------------------------------------------------------------
// adds cargo to smuggling compartment
this.$addCargoToCompartment = function $addCargoToCompartment(cmdty, name, amount, unit, extra) {
var found = false;
for (var i = 0; i < this._sc_Cargo.length; i++) {
if (this._sc_Cargo[i].commodity === cmdty) {
// found it
found = true;
this._sc_Cargo[i].quantity += amount;
if (extra != "") {
if (this._sc_Cargo[i].extra == "") {
this._sc_Cargo[i].extra = extra;
} else {
this._sc_Cargo[i].extra += ";" + extra;
}
}
}
}
if (found === false) {
this._sc_Cargo.push({
commodity: cmdty,
displayName: name,
quantity: amount,
unit: unit,
extra: extra
});
}
}
//-------------------------------------------------------------------------------------------------------------
// create system phases
this.$createSystemPhase = function $createSystemPhase() {
for (var i = 0; i <= 7; i++) {
for (var j = 1; j <= 15; j++) {
this._systemPhase.push({
gov: i,
tl: j,
phase: this.$rand(999)
});
}
}
}
//-------------------------------------------------------------------------------------------------------------
// updates the phase setting for a particular government/techlevel
this.$updatePhase = function $updatePhase(govType, techlevel, phase) {
for (var i = 0; i < this._systemPhase.length; i++) {
if (this._systemPhase[i].gov === govType && this._systemPhase[i].tl === techlevel) {
this._systemPhase[i].phase = phase;
this._phaseUpdates.push({
gov: govType,
tl: techlevel
});
break;
}
}
for (var i = 0; i < this._phaseScanDiscovery.length; i++) {
if (this._phaseScanDiscovery[i].gov === govType && this._phaseScanDiscovery[i].tl === techlevel && this._phaseScanDiscovery[i].source < 3) this._phaseScanDiscovery[i].source = 4;
}
}
//-------------------------------------------------------------------------------------------------------------
// returns the phase for a given system ID
this.$getSystemPhase = function $getSystemPhase(systemID) {
var sysinfo = System.infoForSystem(galaxyNumber, systemID);
var result = 0;
for (var i = 0; i < this._systemPhase.length; i++) {
if (this._systemPhase[i].gov === sysinfo.government && this._systemPhase[i].tl === sysinfo.techlevel) result = this._systemPhase[i].phase;
}
return result;
}
//-------------------------------------------------------------------------------------------------------------
// removes the current smuggling compartment and empties the cargo stored in it
this.$removeCompartment = function $removeCompartment() {
player.ship.removeEquipment("EQ_SMUGGLING_PHASE_ADJUSTMENT");
player.ship.removeEquipment("EQ_SMUGGLING_INFLIGHT_STORAGE");
var eq = this.$getSmugglingCompartmentEquipment();
if (eq === "") return;
this._backdoor = true;
player.ship.removeEquipment(eq);
this._backdoor = false;
this._sc_Cargo = [];
this._sc_VisibleAs = "Food";
this._sc_Phase = 1;
this._sc_TechVersion = 1;
}
//-------------------------------------------------------------------------------------------------------------
// returns a summarised version of the smuggling compartment cargo
this.$getSmugglingCargo = function $getSmugglingCargo() {
var cargo = [];
for (var i = 0; i < this._sc_Cargo.length; i++) {
var found = false;
for (var j = 0; j < cargo.length; j++) {
if (cargo[j].commodity === this._sc_Cargo[i].commodity) {
cargo[j].quantity += this._sc_Cargo[i].quantity;
found = true;
}
}
if (found === false) {
cargo.push({
commodity: this._sc_Cargo[i].commodity,
displayName: this._sc_Cargo[i].displayName,
quantity: this._sc_Cargo[i].quantity,
unit: this._sc_Cargo[i].unit,
extra: this._sc_Cargo[i].extra
});
}
}
return cargo;
}
//-------------------------------------------------------------------------------------------------------------
// returns how much of a particular commodity is in the smuggling compartment
this.$getCargoQuantity = function $getCargoQuantity(commodity) {
var cargo = this.$getSmugglingCargo();
var result = 0;
for (var i = 0; i < cargo.length; i++) {
if (cargo[i].commodity === commodity) result = cargo[i].quantity;
}
return result;
}
//-------------------------------------------------------------------------------------------------------------
// removes an given amount of a particular commodity
this.$removeCargo = function $removeCargo(commodity, quantity) {
var sum = quantity;
for (var i = this._sc_Cargo.length - 1; i >= 0; i--) {
if (this._sc_Cargo[i].commodity === commodity && sum > 0) {
if (this._sc_Cargo[i].quantity >= sum) {
this.$checkForAndRemoveCTECargo(commodity, sum);
this._sc_Cargo[i].quantity -= sum;
sum = 0;
} else {
sum -= this._sc_Cargo[i].quantity;
this._sc_Cargo[i].quantity = 0;
}
}
}
this.$cargoCleanUp();
// return any remainder
return sum;
}
//-------------------------------------------------------------------------------------------------------------
// extracts an certain amount of a particular commodity from new cargoes
this.$extractCargoFromCTE = function (commodity, amount, max) {
var cte = worldScripts.CargoTypeExtension;
var special = this.$calcCTEcargo(commodity);
var normal = max - special;
if (amount - normal > 0) {
// we're transferring some special cargo
var storage = [];
var ncmanifest = cte.suspendPlayerManifest(commodity);
var nc = ncmanifest.split("|");
var lst = nc[1].split("/");
var counter = 0;
for (var i = 0; i < lst.length; i++) {
if (lst[i] != "") {
var itms = lst[i].split(";");
for (var j = 0; j < itms.length; j++) {
if (itms[j] != "") {
// reduce the original
var sub = itms[j].split("=");
var removed = 0;
while (sub[1] > 0) {
sub[1]--;
counter++;
removed++;
if ((amount - normal) - counter == 0) break;
}
itms[j] = sub.join("=");
//storage.push(sub[0] + "=" + removed + "=" + sub[2]);
// make a copy of what we're taking out
// we'll store them a 1 unit items to make the return process easier
for (var k = 0; k < removed; k++) {
var st = "";
for (var m = 0; m < sub.length; m++) {
st += (st == "" ? "" : "=") + (m == 1 ? 1 : sub[m]);
}
storage.push(st);
}
}
}
lst[i] = itms.join(";");
}
if ((amount - normal) - counter == 0) break;
}
nc[1] = lst.join("/");
ncmanifest = nc.join("|");
// tell NC about what we've done
cte.mergePlayerManifest(ncmanifest);
// pull our storage data together
extra = storage.join(";");
}
return extra;
}
//-------------------------------------------------------------------------------------------------------------
this.$checkForAndRemoveCTECargo = function (commodity, quantity) {
var extra = "";
for (var i = 0; i < this._sc_Cargo.length; i++) {
if (this._sc_Cargo[i].commodity == commodity) {
if (this._sc_Cargo[i].extra != "") {
var dta = [];
dta = this._sc_Cargo[i].extra.split(";");
var normal = this._sc_Cargo[i].quantity - dta.length;
if (quantity - normal > 0) {
var diff = quantity - normal;
// compile a list of the cargo items to re-merge with nc
while (diff > 0) {
extra += (extra == "" ? "" : ";") + dta.shift();
diff--;
}
this._sc_Cargo[i].extra = dta.join(";");
}
}
}
}
// because we store everything as 1 unit items, we need to compile it back into totals so NC has good data
var hold = this.$compileCTEValues(extra);
var ncmanifest = "2|" + this.$buildMergeManifest(commodity, hold);
return ncmanifest;
}
//-------------------------------------------------------------------------------------------------------------
// compile multiple 1 unit items down to one entry with a 1+ unit count
this.$compileCTEValues = function (extra) {
var items = extra.split(";");
var list = {};
for (var i = 0; i < items.length; i++) {
if (!list[items[i]]) {
list[items[i]] = 1;
} else {
list[items[i]] = list[items[i]] + 1;
}
log(this.name, "tracking " + list[items[i]]);
}
var keys = Object.keys(list);
var final = "";
for (var i = 0; i < keys.length; i++) {
var subs = keys[i].split("=");
final = (final == "" ? "" : ";") + subs[0] + "=" + list[keys[i]] + "=" + subs[2];
}
return final;
}
//-------------------------------------------------------------------------------------------------------------
// put the manifest string together
// blank entries in all but the item we are processing the commodity for
this.$buildMergeManifest = function (commodity, extra) {
var cte = worldScripts.CargoTypeExtension;
var goodsList = cte.cargoTypes;
var serial = "";
for (var i = 0; i < goodsList.length; i++) {
if (goodsList[i] == commodity) {
serial += extra;
}
if (i + 1 < goodsList.length) {
serial += "/";
}
}
return serial;
}
//-------------------------------------------------------------------------------------------------------------
// adds a phase scan setting to our discovered list
// source 1 = from phase scanner, 2 = purchased from black market, 3 = overheard in rumours, 4 = updated after scan
this.$addPhaseScan = function $addPhaseScan(phase, systemID, source) {
//log(this.name, "checking " + system.ID);
//log(this.name, "data: " + systemID + ", " + source);
var sysinfo = System.infoForSystem(galaxyNumber, systemID);
var found = false;
for (var i = 0; i < this._phaseScanDiscovery.length; i++) {
if (this._phaseScanDiscovery[i].gov === sysinfo.government && this._phaseScanDiscovery[i].tl === sysinfo.techlevel) {
found = true;
this._phaseScanDiscovery[i].phase = phase;
// if the previous value was just a remour, or changed, update it now
if (this._phaseScanDiscovery[i].source >= 3 && source < 3) this._phaseScanDiscovery[i].source = source;
}
}
if (found === false) {
this._phaseScanDiscovery.push({
gov: sysinfo.government,
tl: sysinfo.techlevel,
phase: phase,
source: source
});
}
}
//-------------------------------------------------------------------------------------------------------------
// returns true if the player has a reliable phase scan for a given system
this.$playerHasPhaseScan = function $playerHasPhaseScan(sysID) {
var sysinfo = System.infoForSystem(galaxyNumber, sysID);
var result = false;
for (var i = 0; i < this._phaseScanDiscovery.length; i++) {
if (this._phaseScanDiscovery[i].gov === sysinfo.government && this._phaseScanDiscovery[i].tl === sysinfo.techlevel && this._phaseScanDiscovery[i].source < 3) result = true;
}
return result;
}
//-------------------------------------------------------------------------------------------------------------
// returns the number of sellable phase scans the player has
this.$sellablePhaseScans = function $sellablePhaseScans() {
var list = this.$getSellablePhaseScans();
return list.length;
}
//-------------------------------------------------------------------------------------------------------------
// get a list of sellable phase scan settings for the black market
// note: will only return scans within 7ly of current system
this.$getSellablePhaseScans = function $getSellablePhaseScans() {
function compare(a, b) {
if ((a.gov * 100) + a.tl < (b.gov * 100) + b.tl) return -1;
if ((a.gov * 100) + a.tl > (b.gov * 100) + b.tl) return 1;
return 0;
}
this._phaseScanDiscovery.sort(compare);
var govs = new Array();
for (var i = 0; i < 8; i++)
govs.push(String.fromCharCode(i));
var spc = String.fromCharCode(31);
var list = [];
var added = [];
// you can only sell phase scans for the local area
var sys = System.infoForSystem(galaxyNumber, system.ID).systemsInRange(7);
for (var i = 0; i < this._phaseScanDiscovery.length; i++) {
if (this._phaseScanDiscovery[i].source === 1) {
for (var j = 0; j < sys.length; j++) {
// does this scan match a local system, and have we already added this variation?
if (sys[j].government === this._phaseScanDiscovery[i].gov && sys[j].techlevel === this._phaseScanDiscovery[i].tl && added.indexOf((sys[j].government * 100) + sys[j].techlevel) === -1) {
list.push({
text: this.$padTextRight(govs[this._phaseScanDiscovery[i].gov] + spc + "TL" + (this._phaseScanDiscovery[i].tl + 1) + ":", 3.7) + this.$padTextRight(this._phaseScanDiscovery[i].phase, 3),
gov: this._phaseScanDiscovery[i].gov,
tl: this._phaseScanDiscovery[i].tl
});
// add the signature to the added list so we can easily check if it's there already
added.push((sys[j].government * 100) + sys[j].techlevel);
}
}
}
}
return list;
}
//-------------------------------------------------------------------------------------------------------------
// switches a source = 1 to source = 0 for a particular phase scan
this.$sellPhaseScan = function $sellPhaseScan(govrn, techlvl) {
for (var i = 0; i < this._phaseScanDiscovery.length; i++) {
if (this._phaseScanDiscovery[i].gov === govrn && this._phaseScanDiscovery[i].tl === techlvl && this._phaseScanDiscovery[i].source === 1) {
this._phaseScanDiscovery[i].source = 0;
}
}
}
//-------------------------------------------------------------------------------------------------------------
// gets the commodity type for a particular commodity (t , kg or g)
this.$getCommodityType = function $getCommodityType(good) {
if (system.isInterstellarSpace) {
var m = player.ship.manifest;
if (m[good] > 0) {
for (var i = 0; i < m.list.length; i++) {
if (m.list[i].commodity == good) return m.list[i].unit;
}
} else {
return "t";
}
}
var types = ["t", "kg", "g"];
return types[system.mainStation.market[good].quantity_unit];
}
//=============================================================================================================
// hypercargo integration routines
//-------------------------------------------------------------------------------------------------------------
// returns a list of commodity items that are illegal, based on a commodity list
this.$checkHyperCargo = function $checkHyperCargo(commodity) {
var returnData = "";
if (missionVariables.hyperCargoMemory === "EMPTY") return "";
if (!worldScripts["HyperCargo"]) return ""; // just in case hypercargo OXP was removed after being installed for a while
var hc = worldScripts["HyperCargo"];
for (var i = 0; i < 14; i++) {
var cargoItem = hc.cargoNameArray[i];
if (commodity === cargoItem && hc.storedArray[i] > 0) {
var cargoCount = hc.storedArray[i];
returnData = " - " + cargoCount + " " + this.$getCommodityType(cargoItem) + " × " + displayNameForCommodity(cargoItem) + expandMissionText("smuggling_hypercargo");
}
}
return returnData;
}
//-------------------------------------------------------------------------------------------------------------
// returns the quantity of a particular commodity
this.$getHyperCargoQuantity = function $getHyperCargoQuantity(commodity) {
var returnData = "";
if (missionVariables.hyperCargoMemory === "EMPTY") return 0;
if (!worldScripts["HyperCargo"]) return 0; // just in case hypercargo OXP was removed after being installed for a while
var hc = worldScripts["HyperCargo"];
for (var i = 0; i < 14; i++) {
var cargoItem = hc.cargoNameArray[i];
if (commodity === cargoItem && hc.storedArray[i] > 0) {
return hc.storedArray[i];
}
}
return -1;
}
//-------------------------------------------------------------------------------------------------------------
// removes illegal cargo from hypercargo and applies a bounty
this.$updateHyperCargo = function $updateHyperCargo(commodity, def) {
if (missionVariables.hyperCargoMemory === "EMPTY") return;
if (!worldScripts["HyperCargo"]) return; // just in case hypercargo OXP was removed after being installed for a while
var hc = worldScripts["HyperCargo"];
var p = player.ship;
for (var i = 0; i < 14; i++) {
var cargoItem = hc.cargoNameArray[i];
if (commodity === cargoItem && hc.storedArray[i]) {
p.setBounty(player.bounty + (hc.storedArray[i] * def.scale), "illegal imports");
hc.storedArray[i] = 0;
}
}
}
//-------------------------------------------------------------------------------------------------------------
// removes an amount of cargo from hypercargo
this.$removeHyperCargo = function $removeHyperCargo(commodity, amount) {
if (missionVariables.hyperCargoMemory === "EMPTY") return 0;
if (!worldScripts["HyperCargo"]) return 0; // just in case hypercargo OXP was removed after being installed for a while
var hc = worldScripts["HyperCargo"];
for (var i = 0; i < 14; i++) {
var cargoItem = hc.cargoNameArray[i];
if (commodity === cargoItem && hc.storedArray[i] > 0) {
if (hc.storedArray[i] >= amount) {
hc.storedArray[i] -= amount;
return 0;
} else {
var remain = amount - hc.storedArray[i];
hc.storedArray[i] = 0;
return remain;
}
}
}
}
//-------------------------------------------------------------------------------------------------------------
// prompts the user for a new phase
this.$getBribeAmount = function $getBribeAmount() {
var text = "";
var sdm = worldScripts.Smugglers_DockMaster;
var inttype = Math.floor((sdm._bribeChance[system.ID] * 4) + 1);
var inttypedesc = expandDescription("[interest-type" + inttype + "]");
var lastBribe = sdm.$previousBribeAmount();
text = expandDescription("[dockmaster-question]", {
interesttype: inttypedesc
}) + "\n\n" +
"(" + expandDescription("[dockmaster-cost]", {
credits: formatCredits(player.credits, false, true)
}) +
(lastBribe > 0 ? expandDescription("[dockmaster-lastbribe]", {
bribeamount: formatCredits(lastBribe, false, true)
}) : "") + ")";
var opts = {
screenID: "smuggling_bribe",
titleKey: "smuggling_bribe_official",
allowInterrupt: false,
model: "[" + this._policeModel + "]",
exitScreen: "GUI_SCREEN_STATUS",
message: text,
textEntry: true
};
mission.runScreen(opts, this.$getBribeAmountInput, this);
}
//-------------------------------------------------------------------------------------------------------------
// parses the input from the getBribeAmount screen
this.$getBribeAmountInput = function $getBribeAmountInput(param) {
var sdm = worldScripts.Smugglers_DockMaster;
var p = player.ship;
sdm._bribeAttempted = true;
if (parseInt(param) >= 1 && parseInt(param) <= player.credits) {
var amount = parseInt(param);
// will this work
var chance = sdm._bribeChance[system.ID];
// higher amounts are more likely to be accepted
// chance of 0.5 would mean you would need to offer them 256 credits
//if (this._debug) log(this.name, "min bribe amount = " + (Math.pow(parseInt(chance * 32), 1.8) * (1 + system.productivity / 56300) * sdm._bribeCount[system.ID]));
if ((Math.pow(parseInt(chance * 32), 1.8) * (1 + system.productivity / 56300) * sdm._bribeCount[system.ID]) <= amount) {
player.credits -= amount;
sdm.$addBribe(system.ID);
sdm._successfulBribes.push({
system: system.ID,
bribeAmount: amount
});
p.setBounty(this._savedBounty, "bribe");
mission.runScreen({
screenID: "smuggling_bribe",
titleKey: "smuggling_bribe_official",
model: "[" + this._policeModel + "]",
message: expandDescription("[dockmaster-complete]"),
exitScreen: "GUI_SCREEN_STATUS"
});
} else {
if (this._bribeType === 1) this.$processRemovals();
if (this._bribeType === 2) this.$processEquipmentRemovals();
if (Math.random() > chance) {
mission.runScreen({
screenID: "smuggling_bribe",
titleKey: "smuggling_bribe_official",
model: "[" + this._policeModel + "]",
message: expandDescription("[dockmaster-angry-nopenalty]"),
exitScreen: "GUI_SCREEN_STATUS"
});
} else {
var penalty = (worldScripts.Smugglers_CoreFunctions.$rand(10) + 3);
p.setBounty(player.bounty + penalty, "attempted bribe");
mission.runScreen({
screenID: "smuggling_bribe",
titleKey: "smuggling_bribe_official",
model: "[" + this._policeModel + "]",
message: expandDescription("[dockmaster-angry-penalty]"),
exitScreen: "GUI_SCREEN_STATUS"
});
// send email (if installed)
var email = worldScripts.EmailSystem;
if (email) {
var ga = worldScripts.GalCopAdminServices;
email.$createEmail({
sender: expandMissionText("smuggling_customs"),
subject: expandMissionText("smuggling_bribe_attempt"),
date: clock.seconds,
message: expandDescription("[smugglers-failed-bribe-email]", {
legal_penalty: penalty,
stationname: player.ship.dockedStation.displayName,
systemname: System.systemNameForID(system.ID)
}),
expiryDays: ga._defaultExpiryDays
});
}
}
}
} else {
if (this._bribeType === 1) this.$processRemovals();
if (this._bribeType === 2) this.$processEquipmentRemovals();
mission.runScreen({
screenID: "smuggling_bribe",
title: "smuggling_bribe_official",
model: "[" + this._policeModel + "]",
message: expandDescription("[dockmaster-skipbribe]"),
exitScreen: "GUI_SCREEN_STATUS"
});
}
}
//-------------------------------------------------------------------------------------------------------------
// processes any cargo and/or smuggling compartment removals after docking
this.$processRemovals = function $processRemovals() {
var emailText = "";
var p = player.ship;
if (this._removeCompartment === true) {
// remove smuggling compartment and contents
emailText += "- " + expandMissionText("smuggling_found_compartment") + "\n";
this.$removeCompartment();
}
if (this._phaseScannerDetected === true) {
emailText += "- " + expandMissionText("smuggling_found_phase_scanner") + ".\n";
p.removeEquipment("EQ_PHASE_SCANNER");
}
for (var i = 0; i < this._toRemove.length; i++) {
if (this._toRemove[i].source === "hold") {
emailText += "- " + expandMissionText("smuggling_found_cargo", {commodity:p.manifest[this._toRemove[i].commodity] + this.$getCommodityType(this._toRemove[i].commodity) + " × " + displayNameForCommodity(this._toRemove[i].commodity)}) + "\n";
p.manifest[this._toRemove[i].commodity] = 0;
}
if (this._toRemove[i].source === "hyper") {
emailText += "- " + expandMissionText("smuggling_found_hypercargo", {commodity:p.manifest[this._toRemove[i].commodity] + this.$getCommodityType(this._toRemove[i].commodity) + " × " + displayNameForCommodity(this._toRemove[i].commodity)}) + "\n";
this.$removeHyperCargo(this._toRemove[i].commodity, this.$getHyperCargoQuantity(this._toRemove[i].commodity));
}
}
if (this._playerFine > 0) {
if (player.credits > this._playerFine) {
emailText += "- " + expandMissionText("smuggling_applied_fine", {fine: formatCredits(this._playerFine, true, true)}) + "\n";
player.credits -= this._playerFine;
} else {
emailText += "- " + expandMissionText("smuggling_applied_fine", {fine:formatCredits(player.credits, true, true)}) + "\n";
player.credits = 0;
}
}
this._removeCompartment = false;
this._phaseScannerDetected = false;
// send email (if installed)
if (emailText != "") {
var email = worldScripts.EmailSystem;
if (email) {
var ga = worldScripts.GalCopAdminServices;
email.$createEmail({
sender: expandMissionText("smuggling_customs"),
subject: expandMissionText("smuggling_contraband_removal"),
date: clock.seconds,
message: expandDescription("[smugglers-removal-email]", {
contraband: emailText,
stationname: player.ship.dockedStation.displayName,
systemname: System.systemNameForID(system.ID)
}),
expiryDays: ga._defaultExpiryDays
});
}
}
}
//-------------------------------------------------------------------------------------------------------------
// processes any equipment removals after a renovation
this.$processEquipmentRemovals = function $processEquipmentRemovals() {
var p = player.ship;
var emailText = "";
if (this.$isPhaseScannerInstalled() === true) {
emailText = "- " + expandMissionText("smuggling_found_phase_scanner") + "\n";
p.removeEquipment("EQ_PHASE_SCANNER");
}
if (this.$hasSmugglingCompartment() === true) {
// remove compartment and contents
emailText += "- " + expandMissionText("smuggling_found_compartment") + "\n";
this.$removeCompartment();
}
// send email (if installed)
if (emailText != "") {
var email = worldScripts.EmailSystem;
if (email) {
var ga = worldScripts.GalCopAdminServices;
email.$createEmail({
sender: expandMissionText("smuggling_customs"),
subject: expandMissionText("smuggling_contraband_removal"),
date: clock.seconds,
message: expandDescription("[smugglers-removal-email]", {
contraband: emailText,
stationname: player.ship.dockedStation.displayName,
systemname: System.systemNameForID(system.ID)
}),
expiryDays: ga._defaultExpiryDays
});
}
}
}
//-------------------------------------------------------------------------------------------------------------
// build up an array of values that can be used to determine how many government/techlevel types exist in the system
this.$createSystemDataArray = function $createSystemDataArray() {
this._systemData = [];
for (var i = 0; i <= 255; i++) {
var sys = System.infoForSystem(galaxyNumber, i);
var item = sys.government * 100 + sys.techlevel;
if (this._systemData.indexOf(item) === -1) this._systemData.push(item);
}
}
//-------------------------------------------------------------------------------------------------------------
// updates the manifest screen entry for the smuggling hold contents
this.$updateManifest = function $updateManifest() {
var list = [];
var cargo_size = this.$smugglingCompartmentSize();
if (cargo_size > 0) {
var damaged = this.$isCompartmentDamaged();
list.push(expandMissionText("smuggling_compartment_manifest", {used:this.$usedSpace().toFixed(0), size:cargo_size}) + (damaged === true ? " " + expandMissionText("smuggling_damaged") : "") + ":");
var additem = "";
for (var i = 0; i < this._sc_Cargo.length; i++) {
if (additem === "") {
additem += this.$padTextRight(this._sc_Cargo[i].quantity + " " + this._sc_Cargo[i].unit + " × " + displayNameForCommodity(this._sc_Cargo[i].commodity), 17);
} else {
additem += this._sc_Cargo[i].quantity + " " + this._sc_Cargo[i].unit + " × " + displayNameForCommodity(this._sc_Cargo[i].commodity);
list.push(additem);
additem = "";
}
}
if (additem != "") list.push(additem);
if (this._sc_Cargo.length > 0) {
mission.setInstructions(list, this.name);
} else {
list.push(expandMissionText("smuggling_no_cargo"));
mission.setInstructions(list, this.name);
}
} else {
mission.setInstructions(null, this.name);
}
}
//-------------------------------------------------------------------------------------------------------------
// play the buy/sell sound effects
this.$playSound = function $playSound(soundtype) {
var mySound = new SoundSource;
switch (soundtype) {
case "buy":
mySound.sound = "[buy-commodity]";
break;
case "sell":
mySound.sound = "[sell-commodity]";
break;
case "mode":
mySound.sound = "[@click]";
break;
case "activate":
mySound.sound = "[@beep]";
break;
case "stop":
mySound.sound = "[@boop]";
break;
}
mySound.loop = false;
mySound.play();
}
//-------------------------------------------------------------------------------------------------------------
// returns the illegal scale factor for a particular commodity at the current docked station
this.$commodityIllegalScale = function $commodityIllegalScale(commodity) {
var p = player.ship;
var stn = p.dockedStation;
var scale = parseInt(stn.market[commodity].legality_import);
if (scale === 0) scale = parseInt(stn.market[commodity].legality_export);
return scale;
}
//-------------------------------------------------------------------------------------------------------------
// gets a list of all police ship models so we can use them consistently on smuggling screens
this.$getPoliceModel = function $getPoliceModel() {
var shipkeys = Ship.keysForRole("police");
if (shipkeys.length === 0) return "viper";
var key = "";
var tries = 0;
do {
key = shipkeys[Math.floor(Math.random() * shipkeys.length)];
if (this.$modelIsAllowed(key) === false) key = "";
tries += 1;
} while (key === "" && tries < 5)
if (key === "") key = "viper";
return key;
}
//-------------------------------------------------------------------------------------------------------------
this.$modelIsAllowed = function $modelIsAllowed(shipkey) {
var shipdata = Ship.shipDataForKey(shipkey);
// are we allowed to include this data key in this system? check the conditions if there are some
var include = true;
if (shipdata.conditions) {
var cond = shipdata.conditions.toString().split(",");
//1,systemGovernment_number equal 4,systemGovernment_number,0,0,4,
//1,systemEconomy_number notequal 4,systemEconomy_number,1,0,4
//1,systemEconomy_number lessthan 4,systemEconomy_number,2,0,4
//1,systemEconomy_number greaterthan 4,systemEconomy_number,3,0,4
var offset = 0;
var finish = false;
var checking = -1;
do {
// get the value we're checking
checking = -1;
if (cond[offset + 2].substring(0, 6) === "mission") {
if (missionVariables[cond[offset + 2].replace("mission_", "")]) {
checking = missionVariables[cond[offset + 2].replace("mission_", "")];
//log(this.name, "field = " + cond[offset + 2] + ", value = " + checking);
} else {
log(this.name, "!!NOTE: Condition value mission variable not set: " + cond[offset + 2]);
}
} else {
switch (cond[offset + 2]) {
case "systemGovernment_number":
checking = system.government;
break;
case "systemEconomy_number":
checking = system.economy;
break;
case "systemTechLevel_number":
checking = system.techLevel;
break;
case "score_number":
checking = player.score;
break;
case "galaxy_number":
checking = galaxyNumber;
break;
case "planet_number":
checking = system.ID;
break;
default:
log(this.name, "!!NOTE: Condition value not catered for: " + cond[offset + 2]);
break;
}
}
// in case a mission variable is a text value of some sort
if (isNaN(parseInt(checking)) && isNaN(parseFloat(checking))) {
switch (cond[offset + 3]) {
case "0": // equals
if (checking != cond[offset + 5]) include = false;
break;
case "1": // not equals
if (checking == cond[offset + 5]) include = false;
break;
default:
log(this.name, "!!NOTE: Condition comparison not catered for: " + cond[offset + 3]);
break;
}
} else {
if (checking >= 0) {
// work out the type of check, but in negative (or opposite)
switch (cond[offset + 3]) {
case "0": // equals
if (checking !== parseInt(cond[offset + 5])) include = false;
break;
case "1": // not equals
if (checking === parseInt(cond[offset + 5])) include = false;
break;
case "2": // lessthan
if (checking >= parseInt(cond[offset + 5])) include = false;
break;
case "3": // greaterthan
if (checking <= parseInt(cond[offset + 5])) include = false;
break;
default:
log(this.name, "!!NOTE: Condition comparison not catered for: " + cond[offset + 3]);
break;
// others?
}
}
}
offset += 6;
if (offset >= cond.length - 1) finish = true;
} while (finish === false);
} else if (shipdata.condition_script) {
// or the condition script
// create a dummy object to attach the script to so it can be executed
if (system.sun && system.mainPlanet) {
var temppos = system.sun.position.cross(system.mainPlanet.position).direction().multiply(4E9).subtract(system.mainPlanet.position);
var tempalloy = system.addShips("alloy", 1, temppos, 0);
tempalloy[0].setScript(shipdata.condition_script);
include = tempalloy[0].script.allowSpawnShip(shipkey);
tempalloy[0].remove(true);
} else {
include = true;
}
} else {
// otherwise we're free to play
include = true;
}
return include;
} |
Scripts/smugglers_illegal.js |
"use strict";
this.name = "Smugglers_Illegal";
this.author = "phkb";
this.description = "Looks after the new illegal goods.";
this.licence = "CC BY-NC-SA 3.0";
/* TODO:
- add more illegal trade items to the possibilities list
*/
this._disabled = false;
this._debug = false;
this._enableMarkedSystems = true;
this._markedSystemRange = 7;
this._IGTInstalled = false;
this._minLength = 100;
/* template: {govTypes:"", commodity:"", properties:"", permit:1, scale:1, period:n, chance:1, description:""},
govTypes: Comma-separated list of goverment types (0-7) this definition can apply to
commodity: Comma-separated list of commodity names this definition will apply to.
properties: Comma-separated list of text search strings to use against the planetary description.
For instance, "civil war" would only select planets that have "civil war" in their description.
"drink|brew" would only select planets that have "drink" or "brew" in their description.
permit: Boolean value (0 or 1) indicating whether a permit can be purchased for this commodity
scale: The legality scale to apply to this commodity. The scale will apply when calculating the bounty to apply to a player caught smuggling illegal goods as a multiplier.
Most illegal goods have a scale of 1. Slaves have 2.
period: The period (in days) this definition will be active for.
chance: A chance factor, between 0 (never) and 1 (very often), to apply when selecting this definition
description: The description to display for this definition.
*/
this._possibilities = [
{ govTypes: "0,1,2", commodity: "firearms", properties: "", permit: 0, scale: 2, period: -1, chance: 0, description: "firearms1" },
{ govTypes: "3,4,5,6,7", commodity: "firearms", properties: "civil war", permit: 0, scale: 1, period: -1, chance: 0, description: "firearms2" },
{ govTypes: "0", commodity: "computers", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "computers1" },
{ govTypes: "0,1", commodity: "radioactives", properties: "", permit: 1, scale: 1, period: 200, chance: 1, description: "radioactives1" },
{ govTypes: "0,1", commodity: "machinery", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "machinery1" },
{ govTypes: "1", commodity: "food", properties: "", permit: 1, scale: 1, period: 60, chance: 1, description: "food1" },
{ govTypes: "1", commodity: "textiles", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "textiles1" },
{ govTypes: "1", commodity: "liquor_wines", properties: "", permit: 1, scale: 1, period: 60, chance: 1, description: "liquor_wines1" },
{ govTypes: "1", commodity: "computers", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "computers2" },
{ govTypes: "1", commodity: "machinery", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "machinery2" },
{ govTypes: "1", commodity: "furs", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "furs1" },
{ govTypes: "1", commodity: "gold,platinum", properties: "", permit: 1, scale: 1, period: 12, chance: 0.5, description: "gold,platinum1" },
{ govTypes: "2", commodity: "computers", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "computers3" },
{ govTypes: "2", commodity: "alien_items", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "alien_items1" },
{ govTypes: "2", commodity: "food", properties: "", permit: 1, scale: 1, period: 60, chance: 1, description: "food2" },
{ govTypes: "2", commodity: "alloys", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "alloys1" },
{ govTypes: "2", commodity: "liquor_wines", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "liquor_wines2" },
{ govTypes: "2", commodity: "machinery", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "machinery3" },
{ govTypes: "2", commodity: "gold,platinum", properties: "", permit: 1, scale: 1, period: 12, chance: 0.5, description: "gold,platinum2" },
{ govTypes: "2", commodity: "firearms", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "firearms3" },
{ govTypes: "3", commodity: "luxuries", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "luxuries1" },
{ govTypes: "3", commodity: "radioactives", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "radioactives2" },
{ govTypes: "0,3", commodity: "food", properties: "", permit: 1, scale: 1, period: 60, chance: 1, description: "food3" },
{ govTypes: "3", commodity: "machinery", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "machinery4" },
{ govTypes: "3", commodity: "computers", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "computers4" },
{ govTypes: "3", commodity: "minerals", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "minerals1" },
{ govTypes: "3", commodity: "alien_items", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "alien_items2" },
{ govTypes: "4", commodity: "minerals", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "minerals2" },
{ govTypes: "4", commodity: "machinery", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "machinery5" },
{ govTypes: "4", commodity: "computers", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "computers5" },
{ govTypes: "4", commodity: "luxuries", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "luxuries2" },
{ govTypes: "4", commodity: "liquor_wines", properties: "", permit: 1, scale: 1, period: 60, chance: 1, description: "liquor_wines3" },
{ govTypes: "4", commodity: "furs", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "furs2" },
{ govTypes: "4", commodity: "food", properties: "", permit: 1, scale: 1, period: 60, chance: 1, description: "food4" },
{ govTypes: "4", commodity: "textiles", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "textiles2" },
{ govTypes: "4", commodity: "gold,platinum,gem_stones", properties: "", permit: 1, scale: 1, period: 12, chance: 0.5, description: "gold,platinum,gem_stones1" },
{ govTypes: "5", commodity: "food", properties: "", permit: 1, scale: 1, period: 60, chance: 1, description: "food5" },
{ govTypes: "5", commodity: "gold,platinum", properties: "", permit: 1, scale: 1, period: 12, chance: 0.5, description: "gold,platinum3" },
{ govTypes: "5", commodity: "computers", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "computers6" },
{ govTypes: "5", commodity: "furs", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "furs3" },
{ govTypes: "5", commodity: "alien_items", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "alien_items3" },
{ govTypes: "5", commodity: "machinery", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "machinery6" },
{ govTypes: "5", commodity: "gem_stones", properties: "", permit: 1, scale: 1, period: 12, chance: 0.5, description: "gem_stones1" },
{ govTypes: "5,6,7", commodity: "food", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "food6" },
{ govTypes: "6", commodity: "alien_items", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "alien_items4" },
{ govTypes: "6", commodity: "furs", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "furs4" },
{ govTypes: "6", commodity: "alloys", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "alloys2" },
{ govTypes: "6", commodity: "liquor_wines", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "liquor_wines4" },
{ govTypes: "6", commodity: "radioactives", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "radioactives3" },
{ govTypes: "6", commodity: "textiles", properties: "", permit: 1, scale: 1, period: 60, chance: 1, description: "textiles3" },
{ govTypes: "6", commodity: "food", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "food7" },
{ govTypes: "6", commodity: "gold,platinum", properties: "", permit: 1, scale: 1, period: 12, chance: 0.5, description: "gold,platinum4" },
{ govTypes: "7", commodity: "alien_items", properties: "", permit: 1, scale: 1, period: 120, chance: 1, description: "alien_items5" },
{ govTypes: "7", commodity: "gold,platinum", properties: "", permit: 1, scale: 1, period: 12, chance: 0.5, description: "gold,platinum5" },
{ govTypes: "7", commodity: "alloys", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "alloys3" },
{ govTypes: "7", commodity: "computers", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "computers7" },
{ govTypes: "7", commodity: "radioactives", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "radioactives4" },
{ govTypes: "7", commodity: "food", properties: "", permit: 1, scale: 1, period: 60, chance: 1, description: "food8" },
{ govTypes: "7", commodity: "furs", properties: "", permit: 1, scale: 1, period: 90, chance: 1, description: "furs5" },
{ govTypes: "6,7", commodity: "gem_stones", properties: "", permit: 1, scale: 1, period: 12, chance: 0.5, description: "gem_stones2" },
{ govTypes: "0,1,2,3,4,5,6,7", commodity: "textiles", properties: "solar", permit: 1, scale: 1, period: 90, chance: 1, description: "textiles4" },
{ govTypes: "0,1,2,3,4,5,6,7", commodity: "liquor_wines", properties: "brandy,brew,gargle blasters", permit: 1, scale: 1, period: 120, chance: 1, description: "liquor_wines5" },
{ govTypes: "0,1,2,3,4,5,6,7", commodity: "food", properties: "cuisine,soup,burgers,meat,cutlet,steak", permit: 1, scale: 1, period: 90, chance: 1, description: "food9" },
{ govTypes: "3,4,5,6,7", commodity: "firearms", properties: "", permit: 1, scale: 1, period: 120, chance: 0.5, description: "firearms4" }
];
// these commodities will be included when checking for illegal imports on docking, but as they are global defaults we won't add them via the normal mechanisms
// slaves are not included here, as they are being kept as illegal to export only. This is (a) because some escape pods get stored as slaves,
// and (b) to keep the Illegal Goods Tweak in the loop
this._defaultAdditions = ["narcotics"];
// extra commodityInfo
// element 0 is permit costs
// element 1 is % over base price when item is illegal
// element 2 is % over base price for the black market price
this._commodityInfo = {
"food": [2500, 6.5, 2.2],
"textiles": [3000, 4.0, 2.0],
"radioactives": [5000, 2.5, 1.3],
"slaves": [4000, 0, 0],
"liquor_wines": [5000, 2.2, 1.1],
"luxuries": [6000, 2.1, 1.1],
"narcotics": [8000, 0, 0],
"computers": [6000, 2.1, 1.1],
"machinery": [5000, 2.2, 1.1],
"alloys": [3000, 2.2, 1.1],
"firearms": [5000, 2.2, 1.1],
"furs": [7000, 2.5, 1.4],
"minerals": [3000, 6.0, 2.1],
"gold": [8000, 1.3, 0.6],
"platinum": [9000, 1.1, 0.6],
"gem_stones": [8000, 1.8, 0.8],
"alien_items": [6000, 2.8, 1.3]
};
// holds all illegal good definitions for this sector
this._illegalGoods = []; // illegal goods currently in play in sector
this._permits = []; // permits currently held by player
this._originalCredits = 0; // value to hold the players credits (used to refund the cost of the initial item)
this._display = 0;
this._curpage = 0;
this._direct = 0;
this._dataLoaded = false; // flag to indicate when data has been loaded
this._initialRun = true; // flag to indicate when the initial data set has been created
this._originating = -1;
this._startUpRunning = true;
this._markedSystems = [];
this._witchspaceDestination = -1;
this._done = false;
this._menuColor = "orangeColor";
this._itemColor = "yellowColor";
this._disabledColor = "darkGrayColor";
this._trueValues = ["yes", "1", 1, "true", true];
this._markerColors = ["whiteColor", "yellowColor", "orangeColor", "greenColor", "redColor", "blueColor", "purpleColor", "cyanColor"];
this._markerShapes = ["MARKER_X", "MARKER_PLUS", "MARKER_SQUARE", "MARKER_DIAMOND"];
this._firearmsColor = 2;
this._firearmsShape = 3;
this._mixedIllegalColor = 1;
this._mixedIllegalShape = 3;
// configuration settings for use in Lib_Config
this._siConfig = {
Name: this.name,
Alias: expandMissionText("smuggling_config_alias"),
Display: expandMissionText("smuggling_config_display"),
Alive: "_siConfig",
Notify: "$markSystems",
Bool: {
B0: { Name: "_enableMarkedSystems", Def: true, Desc: expandMissionText("smuggling_config_marksystems") },
Info: expandMissionText("smuggling_config_bool_info")
},
SInt: {
S0: { Name: "_markedSystemRange", Def: 7, Min: 0, Max: 15, Desc: expandMissionText("smuggling_markedsys_range") },
S1: { Name: "_firearmsColor", Def: 2, Min: 0, Max: 7, Desc: expandMissionText("smuggling_firearms_color") },
S2: { Name: "_mixedIllegalColor", Def: 2, Min: 0, Max: 7, Desc: expandMissionText("smuggling_mixed_color") },
S3: { Name: "_firearmsShape", Def: 3, Min: 0, Max: 3, Desc: expandMissionText("smuggling_firearms_shape") },
S4: { Name: "_mixedIllegalShape", Def: 3, Min: 0, Max: 3, Desc: expandMissionText("smuggling_mixed_shape") },
Info: expandMissionText("smuggling_config_sint_info")
},
};
//-------------------------------------------------------------------------------------------------------------
this.$updateGeneralCommodityDefinition = function (goodDefinition, station, systemID) {
var si = worldScripts.Smugglers_Illegal;
if (goodDefinition.key == "slaves") {
goodDefinition.legality_export = 1;
goodDefinition.legality_import = 0;
return goodDefinition;
}
if (goodDefinition.key == "narcotics") {
goodDefinition.legality_export = 1;
goodDefinition.legality_import = 0;
goodDefinition.comment = expandDescription("[narcotics-legality-description]");
return goodDefinition;
}
if (goodDefinition.key == "firearms") {
goodDefinition.legality_export = 0;
goodDefinition.legality_import = 0;
goodDefinition.comment = expandDescription("[oolite-commodity-no-comment]");
}
if (si) {
// initialise the data if it hasn't been already
if (si._dataLoaded === false) si.$initialiseData();
if ((station === 0 || station == null) && systemID && systemID != -1) {
if (si._dataLoaded === true) {
if (si.$isGoodIllegal(systemID, goodDefinition.key)) {
goodDefinition.legality_import = si.$goodIllegalScale(systemID, goodDefinition.key);
}
}
}
}
return goodDefinition;
}
//-------------------------------------------------------------------------------------------------------------
this.$updateLocalCommodityDefinition = function (goodDefinition, station, systemID) {
var si = worldScripts.Smugglers_Illegal;
if (si && station && station.allegiance === "galcop") {
// apply price boost
if (si.$isGoodIllegal(systemID, goodDefinition.key)) {
// calculate the new price, based on the price limits in _commodityInfo
var newprice = Math.round(goodDefinition.price * (si._commodityInfo[goodDefinition.key][1] + ((system.scrambledPseudoRandomNumber(systemID) * 0.6) - 0.3)), 2);
// adjust the price property
if (si._debug) log(this.name, "changing price on " + goodDefinition.key + " from " + goodDefinition.price + " to " + newprice);
goodDefinition.price = newprice;
}
}
return goodDefinition;
}
//-------------------------------------------------------------------------------------------------------------
this.startUp = function () {
var msi = worldScripts.MarketScriptInterface_Main;
msi.$addMarketInterface("tradegoods_general", "$updateGeneralCommodityDefinition", this.name);
msi.$addMarketInterface("system_local", "$updateLocalCommodityDefinition", this.name, "lowest");
if (this._disabled) {
delete this.shipDockedWithStation;
delete this.playerBoughtEquipment;
delete this.shipWillEnterWitchspace;
delete this.shipExitedWitchspace;
delete this.playerEnteredNewGalaxy;
delete this.playerWillSaveGame;
delete this.guiScreenWillChange;
delete this.guiScreenChanged;
delete this.updateLocalCommodityDefinition;
delete this.dayChanged;
delete this.startUpComplete;
delete this.startUp;
return;
}
var core = worldScripts.Smugglers_CoreFunctions;
this.$padTextRight = core.$padTextRight;
this.$padTextLeft = core.$padTextLeft;
this.$isBigGuiActive = core.$isBigGuiActive;
this.$rand = core.$rand;
if (missionVariables.Smuggling_Permits) {
this._permits = JSON.parse(missionVariables.Smuggling_Permits);
delete missionVariables.Smuggling_Permits;
}
this._originating = system.ID;
delete this.startUp;
}
//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
// register our settings, if Lib_Config is present
if (worldScripts.Lib_Config) worldScripts.Lib_Config._registerSet(this._siConfig);
// check for illegal goods tweak
if (worldScripts["illegal_goods_tweak"]) this._IGTInstalled = true;
// set up the interface screen, if required
this.$initMainInterface(player.ship.dockedStation);
this.$correctStartEndDates();
this._startUpRunning = false;
if (missionVariables.Smuggling_InitialRun) {
this._initialRun = missionVariables.Smuggling_InitialRun;
}
if (missionVariables.Smuggling_MarkedSystems) {
this._markedSystems = JSON.parse(missionVariables.Smuggling_MarkedSystems);
delete missionVariables.Smuggling_MarkedSystems;
}
// add our repair items to the email systems list of repair equipment
var w = worldScripts.EmailSystem;
if (w) {
var ga = worldScripts.GalCopAdminServices;
for (var i = 1; i <= 20; i++) {
ga._maint_repair_equip.push("EQ_SMUGGLING_COMPARTMENT_REPAIR_" + i);
}
}
// only load these settings if Library is installed
if (worldScripts.Lib_Config) {
if (missionVariables.Smugglers_MarkSystems) this._enableMarkedSystems = (this._trueValues.indexOf(missionVariables.Smugglers_MarkSystems) >= 0 ? true : false);
if (missionVariables.Smugglers_MarkSystemsRange) this._markedSystemRange = parseInt(missionVariables.Smugglers_MarkSystemsRange);
if (missionVariables.Smugglers_FirearmsColor) this._firearmsColor = parseInt(missionVariables.Smugglers_FirearmsColor);
if (missionVariables.Smugglers_MixedIllegalColor) this._mixedIllegalColor = parseInt(missionVariables.Smugglers_MixedIllegalColor);
if (missionVariables.Smugglers_FirearmsShape) this._firearmsShape = parseInt(missionVariables.Smugglers_FirearmsShape);
if (missionVariables.Smugglers_MixedIllegalShape) this._mixedIllegalShape = parseInt(missionVariables.Smugglers_MixedIllegalShape);
}
this.$markSystems();
if (oolite.compareVersion("1.91") <= 0) {
setExtraGuiScreenKeys(this.name, {
guiScreen: "GUI_SCREEN_LONG_RANGE_CHART",
registerKeys: { "igkey1": [{ key: "1", mod1: true }], "igkey2": [{ key: "2", mod1: true }] },
callback: this.$jumpToIllegalsLRC.bind(this)
});
setExtraGuiScreenKeys(this.name, {
guiScreen: "GUI_SCREEN_SHORT_RANGE_CHART",
registerKeys: { "igkey1": [{ key: "1", mod1: true }], "igkey2": [{ key: "2", mod1: true }] },
callback: this.$jumpToIllegalsSRC.bind(this)
});
if (worldScripts.ContextualHelp) {
worldScripts.ContextualHelp.$addHelpTextToGuiScreen(this.name, "GUI_SCREEN_LONG_RANGE_CHART", "\n" + expandMissionText("smuggling_key_help"));
worldScripts.ContextualHelp.$addHelpTextToGuiScreen(this.name, "GUI_SCREEN_SHORT_RANGE_CHART", "\n" + expandMissionText("smuggling_key_help"));
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
missionVariables.Smuggling_IllegalGoods = JSON.stringify(this._illegalGoods);
missionVariables.Smuggling_Permits = JSON.stringify(this._permits);
missionVariables.Smuggling_MarkedSystems = JSON.stringify(this._markedSystems);
missionVariables.Smuggling_InitialRun = this._initialRun;
// only save these settings if Library is installed
if (worldScripts.Lib_Config) {
missionVariables.Smugglers_MarkSystems = this._enableMarkedSystems;
missionVariables.Smugglers_MarkSystemsRange = this._markedSystemRange;
missionVariables.Smugglers_FirearmsColor = this._firearmsColor;
missionVariables.Smugglers_MixedIllegalColor = this._mixedIllegalColor;
missionVariables.Smugglers_FirearmsShape = this._firearmsShape;
missionVariables.Smugglers_MixedIllegalShape = this._mixedIllegalShape;
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipDockedWithStation = function (station) {
this.$initMainInterface(station);
}
//-------------------------------------------------------------------------------------------------------------
this.shipWillLaunchFromStation = function (station) {
if (missionVariables.Smuggling_IllegalGoods) delete missionVariables.Smuggling_IllegalGoods;
if (missionVariables.Smuggling_Permits) delete missionVariables.Smuggling_Permits;
if (missionVariables.Smuggling_MarkedSystems) delete missionVariables.Smuggling_MarkedSystems;
}
//-------------------------------------------------------------------------------------------------------------
this.playerBoughtEquipment = function (equipmentKey) {
var p = player.ship;
if (equipmentKey === "EQ_IMPORT_PERMIT" || equipmentKey == "EQ_IMPORT_PERMIT_NC") {
p.removeEquipment(equipmentKey);
// give the player back the original amount, in case they decide not to purchase
if (this._originalCredits != 0) {
player.credits = this._originalCredits;
this._originalCredits = 0;
}
// mission screen to ask how many TC to allocate
this.$showPurchasePage();
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipWillEnterWitchspace = function (cause, destination) {
this._witchspaceDestination = destination;
this._initialRun = true;
}
//-------------------------------------------------------------------------------------------------------------
this.shipExitedWitchspace = function () {
this._originating = system.ID;
this._done = false;
this.$markSystems();
}
//-------------------------------------------------------------------------------------------------------------
this.playerEnteredNewGalaxy = function (galNumber) {
// hopefully this is early enough in the sequence to establish illegal goods for the "smugglers_illegalmarket"
this._illegalGoods = [];
this._dataLoaded = false;
}
//-------------------------------------------------------------------------------------------------------------
this.dayChanged = function (newday) {
this.$cleanup();
}
//-------------------------------------------------------------------------------------------------------------
this.guiScreenWillChange = function (to, from) {
if (to === "GUI_SCREEN_MARKET") this.$updateDescriptions();
}
//-------------------------------------------------------------------------------------------------------------
this.guiScreenChanged = function (to, from) {
if (guiScreen === "GUI_SCREEN_EQUIP_SHIP") this._originalCredits = player.credits;
// This code puts all the illegal goods on the F7 screen. However, with the description in the F8F8 screen this code is possibly unnecessary.
// However, if there is feedback that says it would be useful I'll but it back in.
if (from === "GUI_SCREEN_SYSTEM_DATA" && guiScreen != "GUI_SCREEN_SYSTEM_DATA") {
// unhide the hud, if required
if (player.ship.hudHidden != this._hudHidden) {
player.ship.hudHidden = this._hudHidden;
}
}
if (guiScreen === "GUI_SCREEN_SYSTEM_DATA" && from != "GUI_SCREEN_SYSTEM_DATA") {
if (player.ship.isInSpace === false) {
// hide the hud to give us more room for text
this._hudHidden = player.ship.hudHidden;
if (this.$isBigGuiActive() === false) {
player.ship.hudHidden = true;
// force an update in XenonUI (if installed)
var xui = worldScripts.XenonUI;
if (xui) xui.guiScreenChanged("", "");
var xrui = worldScripts.XenonReduxUI;
if (xrui) xrui.guiScreenChanged("", "");
}
}
}
if (guiScreen === "GUI_SCREEN_SYSTEM_DATA") {
// load data onto screen at the end
if (!this._dataLoadDelay) this._dataLoadDelay = new Timer(this, this.$dataLoadDelay, 0.2, 0);
}
}
//-------------------------------------------------------------------------------------------------------------
this.infoSystemChanged = function (to, from) {
if (guiScreen === "GUI_SCREEN_SYSTEM_DATA") {
// load data onto screen at the end
if (!this._dataLoadDelay) this._dataLoadDelay = new Timer(this, this.$dataLoadDelay, 0.2, 0);
}
}
//-------------------------------------------------------------------------------------------------------------
this.$dataLoadDelay = function $dataLoadDelay() {
delete this._dataLoadDelay;
// append any system-specific illegal goods to the display
if (guiScreen != "GUI_SCREEN_SYSTEM_DATA") return;
var sysID = player.ship.targetSystem;
if (player.ship.hasOwnProperty("infoSystem")) sysID = player.ship.infoSystem;
var concealment = System.infoForSystem(galaxyNumber, sysID).concealment;
// if there is some form of concealment in effect, don't show anything
if (concealment > 0) return;
var goods = this.$illegalGoodsList(sysID);
var dis_list = "";
if (this._IGTInstalled === true) {
dis_list = expandDescription("[illegal-goods-f7-igt" + (player.ship.isInSpace === false ? "" : "-inflight") + "]");
} else {
dis_list = expandDescription("[illegal-goods-f7-std" + (player.ship.isInSpace === false ? "" : "-inflight") + "]");
}
if (player.ship.isInSpace === false) {
for (var i = 0; i < goods.length; i++) {
dis_list += "\n" + expandMissionText("smuggling_illegal_import") + " -- " + this.$translateCommodityList(goods[i].commodity) + ": " + expandDescription("[smuggling-" + goods[i].description + "]");
}
} else {
for (var i = 0; i < goods.length; i++) {
dis_list += ", " + this.$translateCommodityList(goods[i].commodity);
}
}
mission.addMessageText(dis_list);
}
//-------------------------------------------------------------------------------------------------------------
this.$initialiseData = function $initialiseData() {
this._dataLoaded = true;
// if the initial run flag isn't yet stored in the data, but there are other definitions, reset the flag to false
// that should prevent any extreme prices.
if (!missionVariables.Smuggling_InitialRun && missionVariables.Smuggling_IllegalGoods) {
this._initialRun = false;
}
if (missionVariables.Smuggling_IllegalGoods) {
this._illegalGoods = JSON.parse(missionVariables.Smuggling_IllegalGoods);
this.$updateIllegalGoodsDescriptions();
delete missionVariables.Smuggling_IllegalGoods;
}
if (this._illegalGoods.length == 0) {
this.$initialSetup();
this.$markSystems();
}
}
//-------------------------------------------------------------------------------------------------------------
// change descriptions to tokens
this.$updateIllegalGoodsDescriptions = function $updateIllegalGoodsDescriptions() {
if (this._illegalGoods[0].description.indexOf(this._illegalGoods[0].commodity) == 0) {
return;
}
for (var i = 0; i < this._illegalGoods.length; i++) {
var item = this._illegalGoods[i];
for (var j = 1; j <= 10; j++) {
var desc;
try {
desc = expandDescription("[smuggling-" + item.commodity + j.toString() + "]");
} catch (ex) {
break;
}
if (desc.substring(0, this._minLength).toLowerCase() == item.description.substring(0, this._minLength).toLowerCase()) {
item.description = item.commodity + j.toString()
break;
}
}
}
}
//-------------------------------------------------------------------------------------------------------------
// shows the installation page to select a compartment size
this.$showPurchasePage = function $showPurchasePage() {
var curChoices = {};
var p = player.ship;
var stn = p.dockedStation;
var rowAdjust = 0;
var pagesize = 18;
if (this.$isBigGuiActive() === true) pagesize = 24;
var key = "[permit-purchase-header]";
if (worldScripts["CargoTypeExtension"]) key = "[permit-purchase-header-nc]";
var text = expandDescription(key, { cash: formatCredits(player.credits, true, true) });
text += this.$padTextRight("Item", 20) + this.$padTextLeft("Cost", 10);
var goods = this.$illegalGoodsList(system.ID);
// remove any goods for which the player either already has a permit, or that no permit is allowed
for (var i = goods.length - 1; i >= 0; i--) {
if (goods[i].permit === 1) {
// if the player already has a permit for this item, remove it.
if (this.$playerHasPermit(system.ID, goods[i].commodity, false) === true) {
goods.splice(i, 1);
}
} else {
// if the item doesn't allow permits, remove it
goods.splice(i, 1);
}
}
for (var i = 0; i < goods.length; i++) {
var list = goods[i].commodity.split(",");
var cost = 0;
for (var j = 0; j < list.length; j++) {
cost += this._commodityInfo[list[j]][0] * (1 + (system.government + 1) / 8);
}
var menuitem = this.$padTextRight(this.$translateCommodityList(goods[i].commodity), 20) + this.$padTextLeft(formatCredits(cost, true, true), 10);
curChoices["01_PERMIT~" + goods[i].commodity] = {
text: menuitem,
alignment: "LEFT",
color: this._menuColor
};
}
curChoices["97_SPACER"] = "";
curChoices["99_EXIT"] = {
text: "[exit-no-change]",
color: this._itemColor
};
var def = "99_EXIT";
for (var i = 0; i < ((pagesize - 4) - goods.length); i++) {
curChoices["99_SPACER_" + i] = "";
}
var opts = {
screenID: "oolite-smugglers-permit-map",
titleKey: "smuggling_permit_purchase",
allowInterrupt: true,
exitScreen: "GUI_SCREEN_EQUIP_SHIP",
overlay: {
name: "stgu-form.png",
height: 546
},
choices: curChoices,
initialChoicesKey: def,
message: text
};
mission.runScreen(opts, this.$purchaseScreenHandler, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$purchaseScreenHandler = function $purchaseScreenHandler(choice) {
if (!choice) return;
if (choice.indexOf("01_PERMIT") >= 0) {
var cmdty = choice.substring(choice.indexOf("~") + 1);
var list = cmdty.split(",");
var cost = 0;
for (var j = 0; j < list.length; j++) {
cost += this._commodityInfo[list[j]][0] * (1 + (system.government + 1) / 8);
}
this._permits.push({
systemID: system.ID,
commodity: cmdty,
fake: 0
});
// charge the player
player.credits -= cost;
// make sure the right email is sent to the player
var email = worldScripts.EmailSystem;
if (email) {
// send a notification email
var msg = expandDescription("[permit-purchase-email]", {
commodity: this.$translateCommodityList(cmdty).replace(", ", " and "),
amount: formatCredits(cost, true, true)
});
email.$createEmail({
sender: expandMissionText("smuggling_permit_authority"),
subject: expandMissionText("smuggling_permit_subject"),
date: clock.seconds,
message: msg
});
}
// apply the install time (15 minutes)
clock.addSeconds(900);
}
}
//-------------------------------------------------------------------------------------------------------------
// initialise the illegal goods F4 screen entries
this.$initMainInterface = function $initMainInterface(station) {
station.setInterface(this.name, {
title: expandMissionText("smuggling_illegal_goods_title"),
category: expandMissionText("smuggling_interface_category"),
summary: expandMissionText("smuggling_illegal_goods_summary"),
callback: this.$initialIllegalGoodsOptions.bind(this)
});
}
//-------------------------------------------------------------------------------------------------------------
this.$initialIllegalGoodsOptions = function $initialIllegalGoodsOptions() {
this._display = 0;
this._curpage = 0;
this._direct = 0;
this.$illegalGoodsOptions();
}
//-------------------------------------------------------------------------------------------------------------
this.$jumpToIllegalsLRC = function (key) {
switch (key) {
case "igkey1": this._display = 4; break;
case "igkey2": this._display = 2; break;
}
this._curpage = 0;
this._direct = 1;
this.$illegalGoodsOptions();
}
//-------------------------------------------------------------------------------------------------------------
this.$jumpToIllegalsSRC = function (key) {
switch (key) {
case "igkey1": this._display = 4; break;
case "igkey2": this._display = 2; break;
}
this._curpage = 0;
this._direct = 2;
this.$illegalGoodsOptions();
}
//-------------------------------------------------------------------------------------------------------------
this.$illegalGoodsOptions = function $illegalGoodsOptions() {
function compareDate(a, b) {
if (a.started < b.started) return -1;
if (a.started > b.started) return 1;
return 0;
}
function compareSystem(a, b) {
if (a.systemID < b.systemID) return -1;
if (a.systemID > b.systemID) return 1;
return 0;
}
function compareSystemName(a, b) {
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
return 0;
}
var curChoices = {};
var text = "";
var p = player.ship;
var def = "";
var sbm = worldScripts.Smugglers_BlackMarket;
var col1 = 6;
var col2 = 10;
var pagesize = 20;
if (this.$isBigGuiActive() === true) {
pagesize = 26;
}
var govs = new Array();
for (var i = 0; i < 8; i++)
govs.push(String.fromCharCode(i));
var spc = String.fromCharCode(31);
// main menu
if (this._display === 0) {
text = "";
var recent = [];
for (var i = 0; i < this._illegalGoods.length; i++) {
// list all new items (less that 5 days since start
if (this._illegalGoods[i].started != 0 && ((clock.adjustedSeconds - this._illegalGoods[i].started) / 86400) < 7) {
recent.push({
name: System.systemNameForID(this._illegalGoods[i].systemID),
systemID: this._illegalGoods[i].systemID,
commodity: this.$translateCommodityList(this._illegalGoods[i].commodity),
description: this._illegalGoods[i].description,
started: this._illegalGoods[i].started
});
}
}
text = expandDescription("[recent-declarations]");
var lines = 3;
if (recent.length > 0) {
recent.sort(compareDate);
for (var i = 0; i < recent.length; i++) {
var info = System.infoForSystem(galaxyNumber, recent[i].systemID);
var rt = system.info.routeToSystem(info);
if (rt) {
var dist = rt.distance;
} else {
var dist = system.info.distanceToSystem(info);
}
var textitem = recent[i].name + " (" + govs[info.government] + spc + expandMissionText("smuggling_tl") + (info.techlevel + 1) + ", " + expandMissionText("smuggling_dist") + ": " + dist.toFixed(1) + expandMissionText("smuggling_ly") + ") -- " + recent[i].commodity + ": " + expandDescription("[smuggling-" + recent[i].description + "]");
text += textitem + "\n";
var w = defaultFont.measureString(textitem);
lines += Math.ceil(w / 32);
if (lines >= (pagesize - 6)) break;
}
} else {
text += expandDescription("[recent-declarations-none]");
lines += 1;
}
text += expandDescription("[offer-selections]");
curChoices["01_INFO"] = {
text: "[illegal-sector]",
color: this._menuColor
};
curChoices["02_INRANGE"] = {
text: "[illegal-7ly]",
color: this._menuColor
};
curChoices["03_PLOT"] = {
text: "[illegal-course]",
color: this._menuColor
};
if (this._permits.length > 0) {
curChoices["04_PERMITS"] = {
text: "[list-permits]",
color: this._menuColor
};
lines += 1;
}
if (sbm._waypoints.length > 0) {
curChoices["05_WAYPOINTS"] = {
text: "[list-waypoints]",
color: this._menuColor
};
lines += 1;
}
curChoices["99_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
for (var i = 0; i < ((pagesize - 5) - lines); i++) {
curChoices["99_SPACER_" + i] = "";
// text += "\n";
}
this._curpage = 0;
def = "99_EXIT";
var opts = {
screenID: "oolite-smuggling-illegal-map",
titleKey: "smuggling_illegal_goods_title",
allowInterrupt: true,
overlay: {
name: "stgu-warning.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// illegal goods in sector
if (this._display === 1) {
var list = [];
var checking = [];
for (var i = 0; i < this._illegalGoods.length; i++) {
if (checking.indexOf(this._illegalGoods[i].systemID) === -1) {
list.push({
systemID: this._illegalGoods[i].systemID,
name: System.systemNameForID(this._illegalGoods[i].systemID)
});
checking.push(this._illegalGoods[i].systemID);
}
}
list.sort(compareSystemName);
var redux = 6;
var maxpages = Math.ceil(list.length / (pagesize - redux));
var pagestart = this._curpage * (pagesize - redux);
var pageend = this._curpage * (pagesize - redux) + (pagesize - redux);
if (pageend > list.length) pageend = list.length;
text = expandMissionText("smuggling_illegal_notices", { page: (this._curpage + 1), max: (maxpages > 0 ? maxpages : "1") }) + "\n";
if (this._IGTInstalled === true) {
text += expandDescription("[notifications-extra-igt]");
} else {
text += expandDescription("[notifications-extra-std]");
}
for (var i = pagestart; i < pageend; i++) {
var info = System.infoForSystem(galaxyNumber, list[i].systemID);
var rt = system.info.routeToSystem(info);
if (rt) {
var dist = rt.distance;
} else {
var dist = system.info.distanceToSystem(info);
}
text += this.$padTextRight(info.name, col1) + this.$padTextRight("(" + govs[info.government] + spc + expandMissionText("smuggling_tl") + (info.techlevel + 1) + ", " + expandMissionText("smuggling_dist") + ": " + dist.toFixed(1) + expandMissionText("smuggling_ly") + ")", col2);
var iglist = "";
var goods = this.$illegalGoodsList(list[i].systemID);
for (var j = 0; j < goods.length; j++) {
var cmdty = goods[j].commodity;
var subitems = cmdty.split(",");
for (var k = 0; k < subitems.length; k++) {
iglist += (iglist === "" ? "" : ", ") + displayNameForCommodity(subitems[k]);
if (this.$playerHasPermit(list[i].systemID, subitems[k], false) === true) iglist += " (" + expandMissionText("smuggling_permit_mark") + ")";
}
}
text += iglist + "\n";
}
if (this._curpage === maxpages - 1) {
curChoices["10_NEXTPAGE"] = {
text: "[illegal-nextpage]",
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["10_NEXTPAGE"] = {
text: "[illegal-nextpage]",
color: this._menuColor
};
}
if (this._curpage === 0) {
curChoices["11_PREVPAGE"] = {
text: "[illegal-prevpage]",
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["11_PREVPAGE"] = {
text: "[illegal-prevpage]",
color: this._menuColor
};
}
curChoices["98_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-illegal-map",
titleKey: "smuggling_illegal_goods_title",
allowInterrupt: true,
overlay: {
name: "stgu-warning.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: this._lastChoice ? this._lastChoice : def,
message: text
};
}
// illegal goods on course
if (this._display === 2) {
var target = p.targetSystem;
var source = system.ID;
var myRoute = null;
if (source >= 0) {
if (p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY")) {
myRoute = System.infoForSystem(galaxyNumber, source).routeToSystem(System.infoForSystem(galaxyNumber, target), p.routeMode);
} else {
myRoute = {};
myRoute.route = [];
if (source !== target) myRoute.route.push(source);
myRoute.route.push(target);
}
}
if (myRoute != null) {
var list = myRoute.route;
var redux = 6;
var maxpages = Math.ceil(list.length / (pagesize - redux));
var pagestart = this._curpage * (pagesize - redux);
var pageend = this._curpage * (pagesize - redux) + (pagesize - redux);
if (pageend > list.length) pageend = list.length;
text = expandMissionText("smuggling_illegal_on_course", { page: (this._curpage + 1), max: (maxpages == 0 ? "1" : maxpages) }) + "\n";
if (this._IGTInstalled === true) {
text += expandDescription("[notifications-extra-igt]");
} else {
text += expandDescription("[notifications-extra-std]");
}
for (var i = pagestart; i < pageend; i++) {
var info = System.infoForSystem(galaxyNumber, list[i]);
var rt = system.info.routeToSystem(info);
if (rt && p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY")) {
var dist = rt.distance;
} else {
var dist = system.info.distanceToSystem(info);
}
text += this.$padTextRight(info.name, col1) + this.$padTextRight("(" + govs[info.government] + spc + expandMissionText("smuggling_tl") + (info.techlevel + 1) + ", " + expandMissionText("smuggling_dist") + ": " + dist.toFixed(1) + expandMissionText("smuggling_ly") + ")", col2);
var iglist = "";
var goods = this.$illegalGoodsList(list[i]);
if (goods.length > 0) {
for (var j = 0; j < goods.length; j++) {
var cmdty = goods[j].commodity;
var subitems = cmdty.split(",");
for (var k = 0; k < subitems.length; k++) {
iglist += (iglist === "" ? "" : ", ") + displayNameForCommodity(subitems[k]);
if (this.$playerHasPermit(list[i], subitems[k], false) === true) iglist += " (" + expandMissionText("smuggling_permit_mark") + ")";
}
}
text += iglist;
} else {
text += expandMissionText("smuggling_none");
}
text += "\n";
}
} else {
var maxpages = 0;
var list = [];
if (system.ID === -1) {
text = expandMissionText("smuggling_illegal_on_route") + "\n\n" + expandMissionText("smuggling_illegal_int") + "\n";
} else {
text = expandMissionText("smuggling_illegal_on_route") + "\n\n" + expandMissionText("smuggling_illegal_no_route") + "\n";
}
}
if (this._curpage === maxpages - 1 || list.length === 0) {
curChoices["10_NEXTPAGE"] = {
text: "[illegal-nextpage]",
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["10_NEXTPAGE"] = {
text: "[illegal-nextpage]",
color: this._menuColor
};
}
if (this._curpage === 0 || list.length === 0) {
curChoices["11_PREVPAGE"] = {
text: "[illegal-prevpage]",
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["11_PREVPAGE"] = {
text: "[illegal-prevpage]",
color: this._menuColor
};
}
switch (this._direct) {
case 0:
curChoices["98_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
break;
case 1:
case 2:
curChoices["99_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
break;
}
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-illegal-map",
titleKey: "smuggling_illegal_goods_title",
allowInterrupt: true,
overlay: {
name: "stgu-warning.png",
height: 546
},
exitScreen: (this._direct == 0 ? "GUI_SCREEN_INTERFACES" : (this._direct == 1 ? "GUI_SCREEN_LONG_RANGE_CHART" : "GUI_SCREEN_SHORT_RANGE_CHART")),
choices: curChoices,
initialChoicesKey: this._lastChoice ? this._lastChoice : def,
message: text
};
}
// purchased (legal or otherwise) permits
if (this._display === 3) {
var redux = 6;
var maxpages = Math.ceil(this._permits.length / (pagesize - redux));
if (maxpages === 0) maxpages = 1;
text = expandMissionText("smuggling_permits_title", { page: (this._curpage + 1), max: (maxpages == 0 ? "1" : maxpages) }) + "\n\n";
if (this._permits.length > 0) {
var pagestart = this._curpage * (pagesize - redux);
var pageend = this._curpage * (pagesize - redux) + (pagesize - redux);
if (pageend > this._permits.length) pageend = this._permits.length;
for (var i = pagestart; i < pageend; i++) {
var info = System.infoForSystem(galaxyNumber, this._permits[i].systemID);
text += " " + expandMissionText("smuggling_permit_item", { commodity: this.$translateCommodityList(this._permits[i].commodity), sys: info.name }) + "\n";
}
} else {
text += " " + expandMissionText("smuggling_none");
}
if (this._curpage === maxpages - 1 || this._permits.length === 0) {
curChoices["10_NEXTPAGE"] = {
text: "[illegal-nextpage]",
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["10_NEXTPAGE"] = {
text: "[illegal-nextpage]",
color: this._menuColor
};
}
if (this._curpage === 0 || this._permits.length === 0) {
curChoices["11_PREVPAGE"] = {
text: "[illegal-prevpage]",
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["11_PREVPAGE"] = {
text: "[illegal-prevpage]",
color: this._menuColor
};
}
curChoices["98_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-illegal-map",
titleKey: "smuggling_illegal_goods_title",
allowInterrupt: true,
overlay: {
name: "stgu-form.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: this._lastChoice ? this._lastChoice : def,
message: text
};
}
// illegal goods in range
if (this._display === 4) {
var list = system.info.systemsInRange(7);
var redux = 6;
var maxpages = Math.ceil(list.length / (pagesize - redux));
var pagestart = this._curpage * (pagesize - redux);
var pageend = this._curpage * (pagesize - redux) + (pagesize - redux);
if (pageend > list.length) pageend = list.length;
text = expandMissionText("smuggling_illegal_7ly", { page: (this._curpage + 1), max: (maxpages == 0 ? "1" : maxpages) }) + "\n";
if (this._IGTInstalled === true) {
text += expandDescription("[notifications-extra-igt]");
} else {
text += expandDescription("[notifications-extra-std]");
}
for (var i = pagestart; i < pageend; i++) {
var rt = system.info.routeToSystem(list[i]);
if (rt) {
var dist = rt.distance;
} else {
var dist = system.info.distanceToSystem(list[i]);
}
text += this.$padTextRight(list[i].name, col1) + this.$padTextRight("(" + govs[list[i].government] + spc + expandMissionText("smuggling_tl") + (list[i].techlevel + 1) + ", " + expandMissionText("smuggling_dist") + ": " + dist.toFixed(1) + expandMissionText("smuggling_ly") + ")", col2);
var iglist = "";
var goods = this.$illegalGoodsList(list[i].systemID);
if (goods.length > 0) {
for (var j = 0; j < goods.length; j++) {
var cmdty = goods[j].commodity;
var subitems = cmdty.split(",");
for (var k = 0; k < subitems.length; k++) {
iglist += (iglist === "" ? "" : ", ") + displayNameForCommodity(subitems[k]);
if (this.$playerHasPermit(list[i].systemID, subitems[k], false) === true) iglist += " (" + expandMissionText("smuggling_permit_mark") + ")";
}
}
text += iglist;
} else {
text += expandMissionText("smuggling_none");
}
text += "\n";
}
if (this._curpage === maxpages - 1 || list.length === 0) {
curChoices["10_NEXTPAGE"] = {
text: "[illegal-nextpage]",
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["10_NEXTPAGE"] = {
text: "[illegal-nextpage]",
color: this._menuColor
};
}
if (this._curpage === 0 || list.length === 0) {
curChoices["11_PREVPAGE"] = {
text: "[illegal-prevpage]",
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["11_PREVPAGE"] = {
text: "[illegal-prevpage]",
color: this._menuColor
};
}
switch (this._direct) {
case 0:
curChoices["98_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
break;
case 1:
case 2:
curChoices["99_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
break;
}
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-illegal-map",
titleKey: "smuggling_illegal_goods_title",
allowInterrupt: true,
overlay: {
name: "stgu-warning.png",
height: 546
},
exitScreen: (this._direct == 0 ? "GUI_SCREEN_INTERFACES" : (this._direct == 1 ? "GUI_SCREEN_LONG_RANGE_CHART" : "GUI_SCREEN_SHORT_RANGE_CHART")),
choices: curChoices,
initialChoicesKey: this._lastChoice ? this._lastChoice : def,
message: text
};
}
// rock hermit waypoints purchased
if (this._display === 5) {
var redux = 6;
var maxpages = Math.ceil(sbm._waypoints.length / (pagesize - redux));
if (maxpages === 0) maxpages = 1;
text = expandMissionText("smuggling_waypoints", { page: (this._curpage + 1), max: (maxpages == 0 ? "1" : maxpages) }) + "\n\n";
if (sbm._waypoints.length > 0) {
var pagestart = this._curpage * (pagesize - redux);
var pageend = this._curpage * (pagesize - redux) + (pagesize - redux);
if (pageend > sbm._waypoints.length) pageend = sbm._waypoints.length;
for (var i = pagestart; i < pageend; i++) {
var info = System.infoForSystem(galaxyNumber, sbm._waypoints[i]);
var rt = system.info.routeToSystem(info);
if (rt) {
var dist = rt.distance;
} else {
var dist = system.info.distanceToSystem(info);
}
text += info.name + " (" + govs[info.government] + spc + expandMissionText("smuggling_tl") + (info.techlevel + 1) + ", " + expandMissionText("smuggling_dist") + ": " + dist.toFixed(1) + expandMissionText("smuggling_ly") + ")\n";
}
} else {
text += " " + expandMissionText("smuggling_none");
}
if (this._curpage === maxpages - 1 || sbm._waypoints.length === 0) {
curChoices["10_NEXTPAGE"] = {
text: "[illegal-nextpage]",
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["10_NEXTPAGE"] = {
text: "[illegal-nextpage]",
color: this._menuColor
};
}
if (this._curpage === 0 || sbm._waypoints.length === 0) {
curChoices["11_PREVPAGE"] = {
text: "[illegal-prevpage]",
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["11_PREVPAGE"] = {
text: "[illegal-prevpage]",
color: this._menuColor
};
}
curChoices["98_EXIT"] = {
text: "[illegal-return]",
color: this._itemColor
};
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-waypoints-map",
titleKey: "smuggling_rockhermit_waypoints",
allowInterrupt: true,
overlay: {
name: "stgu-map_marker.png",
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: this._lastChoice ? this._lastChoice : def,
message: text
};
}
mission.runScreen(opts, this.$screenHandler, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$screenHandler = function $screenHandler(choice) {
delete this._lastChoice;
switch (choice) {
case "01_INFO":
this._display = 1;
break;
case "02_INRANGE":
this._display = 4;
break;
case "03_PLOT":
this._display = 2;
this._curpage = 0;
break;
case "04_PERMITS":
this._display = 3;
this._curpage = 0;
break;
case "05_WAYPOINTS":
this._display = 5;
this._curpage = 0;
break;
case "10_NEXTPAGE":
this._curpage += 1;
break;
case "11_PREVPAGE":
this._curpage -= 1;
break;
case "98_EXIT":
this._display = 0;
break;
}
this._lastChoice = choice;
if (choice != "99_EXIT") {
this.$illegalGoodsOptions();
}
}
//-------------------------------------------------------------------------------------------------------------
// returns list of illegal goods for system id
this.$illegalGoodsList = function $illegalGoodsList(sysID, include) {
var list = [];
for (var i = 0; i < this._illegalGoods.length; i++) {
if (this._illegalGoods[i].systemID === sysID) list.push(this._illegalGoods[i]);
}
// include default definitions when running a check on docking
if (include && include === true) {
for (var i = 0; i < this._defaultAdditions.length; i++) {
list.push({
systemID: sysID,
commodity: this._defaultAdditions[i],
started: 0,
end: 0,
description: "",
permit: 0,
scale: 2
});
}
}
return list;
}
//-------------------------------------------------------------------------------------------------------------
// returns list of illegal goods for system id, but just the commodity names (split out if necessary)
this.$illegalGoodsListCommodityOnly = function $illegalGoodsListCommodityOnly(sysID, include) {
var list = [];
for (var i = 0; i < this._illegalGoods.length; i++) {
if (this._illegalGoods[i].systemID === sysID) {
var splitlist = this._illegalGoods[i].commodity.split(",");
for (var j = 0; j < splitlist.length; j++) {
list.push(splitlist[j]);
}
}
}
// include default definitions when running a check on docking
if (include && include === true) {
for (var i = 0; i < this._defaultAdditions.length; i++) {
list.push(this._defaultAdditions[i]);
}
}
return list;
}
//-------------------------------------------------------------------------------------------------------------
// returns a particular illegal goods definition
this.$illegalGoodsDefinition = function $illegalGoodsDefinition(sysID, commodity) {
for (var i = 0; i < this._illegalGoods.length; i++) {
if (this._illegalGoods[i].systemID === sysID && this._illegalGoods[i].commodity.indexOf(commodity) >= 0) return this._illegalGoods[i];
}
return null;
}
//-------------------------------------------------------------------------------------------------------------
// returns true if a particular good is illegal in a particular system, otherwise false;
this.$isGoodIllegal = function $isGoodIllegal(sysID, commodity) {
for (var i = 0; i < this._illegalGoods.length; i++) {
if (this._illegalGoods[i].systemID === sysID && this._illegalGoods[i].commodity.indexOf(commodity) >= 0) return true;
}
return false;
}
//-------------------------------------------------------------------------------------------------------------
this.$goodIllegalScale = function $goodIllegalScale(sysID, commodity) {
for (var i = 0; i < this._illegalGoods.length; i++) {
if (this._illegalGoods[i].systemID === sysID && this._illegalGoods[i].commodity.indexOf(commodity) >= 0) return this._illegalGoods[i].scale;
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------
// initial setup of illegal goods in sector
this.$initialSetup = function $initialSetup() {
// first, add all default/permanent items
for (var i = 0; i < this._possibilities.length; i++) {
var item = this._possibilities[i];
// work out the shortest description in all the possibilities
var dl = expandDescription("[smuggling-" + item.description + "]").length;
if (dl < this._minLength) this._minLength = dl;
if (item.period === -1) {
var govs = item.govTypes.split(",");
for (var j = 0; j < govs.length; j++) {
if (govs[j] != "") {
var planetlist = this.$getSystemsByGovernment(parseInt(govs[j]), item.properties);
for (var k = 0; k < planetlist.length; k++) {
if (planetlist[k].sun_gone_nova) continue;
this.$applyDefinition(planetlist[k].systemID, item, 0);
}
}
}
}
}
// next pick a random number of planets and apply an illegal good for them
// add the definitions, between 30 and 60 ** TODO: work out if this is too much or too little
if (!this.$rand) this.$rand = worldScripts.Smugglers_CoreFunctions.$rand; // make sure our rand function is available
for (var i = 1; i <= (this.$rand(30) + 30); i++) {
this.$addNewItem(this.$rand(20));
}
}
//-------------------------------------------------------------------------------------------------------------
// add a new random item to the list
this.$addNewItem = function $addNewItem(startDays, excludeSystem) {
var planetid = -1;
var sys;
var tries = 0;
do {
// pick a random planet
planetid = this.$rand(256) - 1;
sys = System.infoForSystem(galaxyNumber, planetid);
// don't create items in nova systems
if (sys.sun_gone_nova) planetid = -1;
// don't create items in the excluded system
if (planetid === excludeSystem) planetid = -1;
if (planetid >= 0) {
// check if this planet has any existing declarations
var existing = this.$illegalGoodsList(planetid);
var count = 0;
for (var i = 0; i < existing.length; i++) {
// count all the non-default items
if (existing[i].end != 0) count += 1;
}
// if this planet already has an item, skip it.
if (count > 0) planetid = -1;
}
tries += 1;
} while (planetid === -1 && tries < 5);
if (planetid === -1 && this._debug) log(this.name, "attempt to add illegal good failed");
// if we didn't end up finding a planet, exit now
if (planetid === -1) return;
// get a list of possibilities
var poss = this.$getPossibilitiesByGovernment(sys.government, sys.description);
// pick one from the list
var pick = this.$rand(poss.length) - 1;
// add the definition
this.$applyDefinition(planetid, poss[pick], startDays);
}
//-------------------------------------------------------------------------------------------------------------
// get a list of possible illegal goods for a particular government type (0-7)
this.$getPossibilitiesByGovernment = function $getPossibilitiesByGovernment(govType, planetDescription) {
var list = [];
for (var i = 0; i < this._possibilities.length; i++) {
if (this._possibilities[i].period != -1 && this._possibilities[i].govTypes.indexOf(govType.toString()) != -1 &&
(this._possibilities[i].properties === "" || this.$checkPlanetDescription(planetDescription, this._possibilities[i].properties) === true) &&
Math.random() < this._possibilities[i].chance) {
list.push(this._possibilities[i]);
}
}
return list;
}
//-------------------------------------------------------------------------------------------------------------
// checks the planet description to see if the property text is somewhere in it.
// properties can be a single piece of text (eg "something"), or split with a "," character (eg "something,somethingelse")
this.$checkPlanetDescription = function $checkPlanetDescription(descr, properties) {
if (properties.indexOf(",") === -1) {
if (descr.indexOf(properties) >= 0) {
return true;
} else {
return false;
}
} else {
var proplist = properties.split(",");
var result = false;
for (var i = 0; i < proplist.length; i++) {
if (descr.indexOf(proplist[i]) >= 0) result = true;
}
return result;
}
}
//-------------------------------------------------------------------------------------------------------------
// returns a list of planets of a particular government type (0-7) and (optionally) with a description that contains the "option" parameter (eg "civil war")
this.$getSystemsByGovernment = function $getSystemsByGovernment(govType, options) {
var planets = SystemInfo.filteredSystems(this, function (other) {
return (other.government === govType && ((options == null || options === "") || other.description.indexOf(options) >= 0));
});
return planets;
}
//-------------------------------------------------------------------------------------------------------------
// adds a definition to the active list
// sysID = planet ID
// def = illegal goods definition
// startDays = number of days to take off the current date, to start this item in the past. This is to simulate an active galaxy, so everything doesn't start from now.
this.$applyDefinition = function $applyDefinition(sysID, def, startDays) {
//log(this.name, "adding illegal good definition for system " + sysID + " for commodity " + def.commodity);
// does this definition already exist for this planet?
for (var i = 0; i < this._illegalGoods.length; i++) {
if (this._illegalGoods[i].systemID === sysID && this._illegalGoods[i].commodity === def.commodity) return;
}
var stime = 0;
var etime = 0;
// if we haven't been passed a start time, just do it for sometime in the last day
if (def.period != -1) {
if (this._startUpRunning === false) {
if (startDays == null || startDays === 0) {
stime = clock.seconds - this.$rand(86400);
} else {
// otherwise, the starttime is subtracted from the current clock (as days), converted to seconds
stime = clock.seconds - (startDays * 86400);
}
// set up the end point
etime = stime + ((def.period + (this.$rand(10) - 5)) * 86400);
} else {
// if this is running during the startup routine, we need to reapply start and end times after it's completed
if (startDays != 0) stime = (startDays * 86400) * -1;
// set up the end point
etime = ((def.period + (this.$rand(10) - 5)) * 86400);
}
} else {
stime = 0;
etime = 0;
}
if (def.period != -1 && this._debug) log(this.name, "adding illegal good definition for system " + sysID + " for commodity " + def.commodity + ", starting " + clock.clockStringForTime(stime) + ", ending " + clock.clockStringForTime(etime));
this._illegalGoods.push({
systemID: sysID,
commodity: def.commodity,
started: stime,
end: etime,
description: def.description,
permit: def.permit,
scale: def.scale
});
}
//-------------------------------------------------------------------------------------------------------------
// update start/end times created during the startup process
this.$correctStartEndDates = function $correctStartEndDates() {
for (var i = 0; i < this._illegalGoods.length; i++) {
if (this._illegalGoods[i].started < 0) {
var stime = clock.adjustedSeconds + this._illegalGoods[i].started;
var etime = stime + this._illegalGoods[i].end;
this._illegalGoods[i].started = stime;
this._illegalGoods[i].end = etime;
}
}
}
//-------------------------------------------------------------------------------------------------------------
// look for any expired items and remove them from the array, and possibly add a new one
this.$cleanup = function $cleanup() {
// remove expired items
for (var i = this._illegalGoods.length - 1; i >= 0; i--) {
if (this._illegalGoods[i].end != 0 && clock.adjustedSeconds > this._illegalGoods[i].end) {
if (this._debug) log(this.name, "removing item: " + this._illegalGoods[i].systemID + ", " + this._illegalGoods[i].commodity + " ended: " + clock.clockStringForTime(this._illegalGoods[i].end))
// do we have a permit for this one? If so, delete it
for (var j = this._permits.length - 1; j >= 0; j--) {
if (this._permits[j].systemID === this._illegalGoods[i].systemID && this._illegalGoods[i].commodity.indexOf(this._permits[j].commodity) >= 0) {
this._permits.splice(j, 1);
}
}
this._illegalGoods.splice(i, 1);
}
}
// add new items
var total = this.$rand(5) - this.$rand(3);
if (total > 0) {
if (this._debug) log(this.name, "going to try adding " + total + " new items");
for (var i = 1; i <= total; i++) {
// add new items, but not in the current system, because the illegal market script won't pick them up until the game is reloaded
this.$addNewItem(1, system.ID);
}
}
}
//-------------------------------------------------------------------------------------------------------------
// checks if the player has a permit for the system
// todo: add newcargos permit check
this.$playerHasPermit = function $playerHasPermit(sysID, cmdty, check) {
for (var i = 0; i < this._permits.length; i++) {
if (this._permits[i].systemID === sysID && this._permits[i].commodity === cmdty) {
// are we doing a validity check
if (check === true && this._permits[i].fake != 0) {
// did it pass?
if (Math.random() > this._permits[i].fake) {
// oh dear, looks like it was discovered as fake
return false;
} else {
// phew! passed!
return true;
}
} else {
// it's a bought one (or we're not bothering with how fake it is), so it's ok
return true;
}
}
}
return false;
}
//-------------------------------------------------------------------------------------------------------------
// removes a permits from the list
this.$removePermit = function $removePermit(sysID, cmdty) {
for (var i = this._permits.length - 1; i >= 0; i--) {
if (this._permits[i].systemID === sysID && this._permits[i].commodity === cmdty) {
this._permits.splice(i, 1);
}
}
}
//-------------------------------------------------------------------------------------------------------------
// returns display version of commodity list
this.$translateCommodityList = function $translateCommodityList(cmdty_list) {
var list = cmdty_list.split(",");
var ret = "";
for (var i = 0; i < list.length; i++) {
ret += (ret === "" ? "" : ", ") + displayNameForCommodity(list[i]);
}
return ret;
}
//-------------------------------------------------------------------------------------------------------------
// adds the F8F8 comment for illegal goods
this.$updateDescriptions = function $updateDescriptions() {
// note: for some reason descriptions added via the illegal market script are not being displayed. So we're forcing the issue here.
var nocomment = expandDescription("[oolite-commodity-no-comment]");
if (player.ship.docked) {
var sMarket = player.ship.dockedStation.market;
} else {
if (player.ship.target && player.ship.target.isStation) {
var bcMarket = Ship.shipDataForKey(player.ship.target.dataKey)["market_broadcast"];
if (!bcMarket) bcMarket = true;
else {
var trues = ["1", "true", "yes"];
bcMarket = bcMarket.toLowerCase();
if (trues.indexOf(bcMarket) !== -1) bcMarket = true;
else bcMarket = false;
}
if (bcMarket) {
var sMarket = player.ship.target.market;
} else {
var sMarket = system.mainStation.market;
}
} else {
if (system.isInterstellarSpace) return;
var sMarket = system.mainStation.market;
}
}
var goods = [];
if (system.ID != -1) {
goods = this.$illegalGoodsList(system.ID, true);
} else {
return;
}
for (var cmdty in sMarket) {
// work out what the comment should be for this commodity
var cmt = nocomment;
// special cases
if (cmdty === "slaves") cmt = expandDescription("[oolite-commodity-illegal]");
if (this._defaultAdditions.indexOf(cmdty) >= 0) cmt = expandDescription("[" + cmdty + "-legality-description]");
// if this is an illegal commodity at this station go and grab the description for it from our data
if (sMarket[cmdty].legality_import != 0 || sMarket[cmdty].legality_export != 0) {
for (var i = 0; i < goods.length; i++) {
if (goods[i].commodity.indexOf(cmdty) >= 0 && goods[i].description != "") cmt = expandDescription("[smuggling-" + goods[i].description + "]");
}
} else {
// if it's legal here, but not legal at the main station, put up a warning message
if (system.mainStation.market[cmdty].legality_import != 0 || system.mainStation.market[cmdty].legality_export != 0) {
cmt = expandDescription("[main-station-illegal]");
} else {
// otherwise, just use the "no comment" comment.
cmt = nocomment;
}
}
// get the current comment
var orig = manifest.comment(cmdty);
// in most cases that's all we'll need
var curr_cmt = orig;
// but if another OXP has added their own comments, we'll need to get the first line
// if the OXP adds comments without first adding a linebreak this won't work, but it should be good for most circumstances
if (orig.indexOf("\n") >= 0) curr_cmt = orig.substring(0, orig.indexOf("\n"));
// replace the current comment with our new one
orig = orig.replace(curr_cmt, cmt);
// plonk it back into the comment field for this commodity
manifest.setComment(cmdty, orig);
}
}
//-------------------------------------------------------------------------------------------------------------
// mark local systems on the galactic chart that have illegal goods
this.$markSystems = function $markSystems() {
// clear out existing marks
for (var i = 0; i < this._markedSystems.length; i++) {
mission.unmarkSystem({
system: this._markedSystems[i],
name: "illegalgoods"
});
}
// reset the array
this._markedSystems.length = 0;
if (this._enableMarkedSystems === false) return;
// get all systems in 10 ly
var list = system.info.systemsInRange(this._markedSystemRange);
// mark systems that have illegal goods (other than narcs or slaves)
// system: firearms only = orange, everything else yellow
for (var i = 0; i < list.length; i++) {
var goods = this.$illegalGoodsList(list[i].systemID);
if (goods.length > 0) {
this._markedSystems.push(list[i].systemID);
if (goods.length > 1) {
// if there's more than one illegal, mark it with yellow
mission.markSystem({
system: list[i].systemID,
name: "illegalgoods",
markerColor: this._markerColors[this._mixedIllegalColor],
markerShape: this._markerShapes[this._mixedIllegalShape]
});
} else {
// if the only illegal is firearms, mark it with orange
if (goods[0].commodity === "firearms") {
mission.markSystem({
system: list[i].systemID,
name: "illegalgoods",
markerColor: this._markerColors[this._firearmsColor],
markerShape: this._markerShapes[this._firearmsShape]
});
} else {
// otherwise mark it with yellow
mission.markSystem({
system: list[i].systemID,
name: "illegalgoods",
markerColor: this._markerColors[this._mixedIllegalColor],
markerShape: this._markerShapes[this._mixedIllegalShape]
});
}
}
}
}
} |
Scripts/smugglers_movecargo.js |
"use strict";
this.name = "Smugglers_MoveCargo";
this.author = "phkb";
this.description = "Looks after the process of moving cargo into the smuggling compartment during flight.";
this.licence = "CC BY-NC-SA 3.0";
this._scoopedCargo = [];
this._commodityUnits = {};
this._cycleIndex = -1;
this._selected = null;
//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
var m = system.mainStation.market;
if (m) {
var list = Object.keys(m);
for (var i = 0; i < list.length; i++) {
var c = m[list[i]];
this._commodityUnits[c.key] = (c.quantity_unit === "0" ? "t" : (c.quantity_unit === "1" ? "kg" : "g"));
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipDockedAtStation = function (station) {
this._scoopedCargo.length = 0;
}
//-------------------------------------------------------------------------------------------------------------
this.mode = function () {
// cycle through available, non-labelled cargo, including scooped items (but not escape pods)
// group precious items: existing cargo at launch as amounts (eg 15g gemstones), scooped cargo amounts (eg 9kg gold)
var p = player.ship;
var list = [];
var cargo = p.manifest.list;
var sdm = worldScripts.Smugglers_DockMaster;
var sde = worldScripts.Smugglers_Equipment;
var sdmc = worldScripts.Smugglers_MoveCargo;
var itemcount = 0;
// add the scooped items first
for (var i = 0; i < sdmc._scoopedCargo.length; i++) {
var item = sdmc._scoopedCargo[i];
if (item.isValid && item.status === "STATUS_IN_HOLD") {
list.push({
text: expandMissionText("smuggling_move_cargo", { commodity: item.commodityAmount + sdmc._commodityUnits[item.commodity] + " × " + displayNameForCommodity(item.commodity) }) + " " + expandMissionText("smuggling_scooped"),
scoopedItem: item,
commodity: item.commodity,
quantity: item.commodityAmount,
unit: sdmc._commodityUnits[item.commodity]
});
}
}
// then the items in the hold.
var existing = [];
for (var i = 0; i < cargo.length; i++) {
// only show standard (non-OXP) commodity items
if (sde._commodityIDList.indexOf(cargo[i].commodity) >= 0) {
var q = cargo[i].quantity - sdmc.$scoopedCargoAmount(cargo[i].commodity);
// don't allow scooped escape pods to be moved
if (cargo[i].commodity === "slaves" && q > 0 && worldScripts.EscapePodTweaks && worldScripts.EscapePodTweaks._escapePods.length > 0) {
q -= worldScripts.EscapePodTweaks._escapePods;
}
// todo: how to handle scooped escape pods when escape pod tweaks isn't installed
// make sure we don't move relabelled cargo
if (sdm._cargoLabelled.length > 0) {
for (var j = 0; j < sdm._cargoLabelled.length; j++) {
if (sdm._cargoLabelled[j].newCommodity === cargo[i].commodity) q -= sdm._cargoLabelled[j].quantity;
}
}
if (q > 0) {
switch (cargo[i].unit) {
case "t":
if (existing.indexOf(cargo[i].commodity) === -1) {
list.push({
text: expandMissionText("smuggling_move_cargo", { commodity: "1" + cargo[i].unit + " × " + cargo[i].displayName }),
scoopedItem: null,
commodity: cargo[i].commodity,
quantity: 1,
unit: cargo[i].unit
});
existing.push(cargo[i].commodity);
}
break;
case "kg":
var step = 1000;
if (step > q) step = q;
var checktot = q;
for (var k = 1; k <= q; k += step) {
checktot -= step;
if (checktot < 0) {
list.push({
text: expandMissionText("smuggling_move_cargo", { commodity: (step + checktot).toString() + cargo[i].unit + " × " + cargo[i].displayName }),
scoopedItem: null,
commodity: cargo[i].commodity,
quantity: (step + checktot),
unit: cargo[i].unit
});
} else {
if (existing.indexOf(cargo[i].commodity) === -1) {
list.push({
text: expandMissionText("smuggling_move_cargo", { commodity: step.toString() + cargo[i].unit + " × " + cargo[i].displayName }),
scoopedItem: null,
commodity: cargo[i].commodity,
quantity: step,
unit: cargo[i].unit
});
existing.push(cargo[i].commodity);
}
}
}
break;
case "g":
var step = 1000000;
if (step > q) step = q;
var checktot = q;
for (var k = 1; k <= q; k += step) {
checktot -= step;
if (checktot < 0) {
list.push({
text: expandMissionText("smuggling_move_cargo", {commodity:(step + checktot).toString() + cargo[i].unit + " × " + cargo[i].displayName}),
scoopedItem: null,
commodity: cargo[i].commodity,
quantity: (step + checktot),
unit: cargo[i].unit
});
} else {
if (existing.indexOf(cargo[i].commodity) === -1) {
list.push({
text: expandMissionText("smuggling_move_cargo", {commodity:step.toString() + cargo[i].unit + " × " + cargo[i].displayName}),
scoopedItem: null,
commodity: cargo[i].commodity,
quantity: step,
unit: cargo[i].unit
});
existing.push(cargo[i].commodity);
}
}
}
break;
}
}
}
}
if (list.length === 0) return;
sdmc._cycleIndex += 1;
if (sdmc._cycleIndex >= list.length) sdmc._cycleIndex = 0;
sdmc._selected = list[sdmc._cycleIndex];
player.consoleMessage(list[sdmc._cycleIndex].text);
}
//-------------------------------------------------------------------------------------------------------------
this.activated = function () {
// move the selected item
var sde = worldScripts.Smugglers_Equipment;
var sdmc = worldScripts.Smugglers_MoveCargo;
if (sdmc._selected != null) {
var item = sdmc._selected;
// any space left for transfer?
var checkAmount = item.quantity;
if (item.unit === "kg") checkAmount /= 1000;
if (item.unit === "g") checkAmount /= 1000000;
if (sde.$availableSpace() < checkAmount) {
player.consoleMessage(expandMissionText("smuggling_compartment_full"));
return;
}
sde.$addCargoToCompartment(item.commodity, displayNameForCommodity(item.commodity), item.quantity, item.unit);
if (item.scoopedItem != null) {
for (var i = 0; i < sdmc._scoopedCargo.length; i++) {
if (sdmc._scoopedCargo[i] == item.scoopedItem) {
sdmc._scoopedCargo.splice(i, 1);
break;
}
}
item.scoopedItem.remove(true);
}
var p = player.ship;
if (sde._NCInstalled == true) {
var tfr = item.quantity;
var storage = [];
var ncmanifest = cte.suspendPlayerManifest(item.commodity);
var nc = ncmanifest.split("|");
var lst = nc[1].split("/");
for (var i = 0; i < lst.length; i++) {
// reduce the original
var sub = lst[i].split("=");
sub[1]--;
lst[i] = sub.join("=");
// make a copy of what we're taking out
// we'll store this as i unit entries, rather than trying to sum them up here,
// to make it easier at the other end when we're taking stuff out
var st = "";
for (var j = 0; j < sub.length; j++) {
st += (st == "" ? "" : "=") + (j == 1 ? 1 : sub[j]);
}
storage.push(st);
tfr--;
if (tfr == 0) break;
}
nc[1] = lst.join("/");
ncmanifest = nc.join("|");
// tell NC about what we've done
cte.mergePlayerManifest(ncmanifest);
// pull our storage data together
extra = storage.join("/");
}
// the manifest of any "kg" or "g" type commodities can't be reduced (in-flight only)
// so add 1 to the value so Oolite with consider the commodity as being out of the hold
var bugfix = false;
if (item.unit === "kg" || item.unit === "g") {
p.manifest[item.commodity] += 1;
bugfix = true;
}
// if we added one, make sure we add it so we can take it away again.
p.manifest[item.commodity] -= (item.quantity + (bugfix === true ? 1 : 0));
player.consoleMessage(item.quantity + item.unit + " × " + displayNameForCommodity(item.commodity) + " " + expandMissionText("smuggling_transferred"));
sdmc._selected = null;
sdmc._cycleIndex = -1;
// force an update of the manifest MFD, as it won't detect changes in kg or g type commodities
if (item.unit != "t" && worldScripts["manifest_mfd"] && p.equipmentStatus("EQ_MANIFEST_MFD") === "EQUIPMENT_OK") {
worldScripts["manifest_mfd"].$updateManifestMFD();
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipScoopedOther = function (cargo) {
// we don't move escape pods (which will have a crew)
if (cargo.isValid === false) return;
if (cargo.commodity != "slaves" || (!cargo.crew || cargo.crew.length === 0)) {
if (cargo.script.shipWasDumped) cargo.script.$sdmovr_shipWasDumped = cargo.script.shipWasDumped;
cargo.script.shipWasDumped = this.$sdm_shipWasDumped;
this._scoopedCargo.push(cargo);
}
}
//-------------------------------------------------------------------------------------------------------------
this.$sdm_shipWasDumped = function $sdm_shipWasDumped(dumper) {
if (this.ship.script.$sdmovr_shipWasDumped) this.ship.script.$sdmovr_shipWasDumped(dumper);
if (dumper.isPlayer) {
var sdmc = worldScripts.Smugglers_MoveCargo;
for (var i = 0; i < sdmc._scoopedCargo.length; i++) {
if (sdmc._scoopedCargo[i] == this.ship) {
sdmc._scoopedCargo.splice(i, 1);
break;
}
}
}
// detach our custom script
delete this.ship.script.shipWasDumped;
if (this.ship.script.$sdmovr_shipWasDumped) {
this.ship.script.shipWasDumped = this.ship.script.$sdmovr_shipWasDumped;
delete this.ship.script.$sdmovr_shipWasDumped;
}
}
//-------------------------------------------------------------------------------------------------------------
this.$scoopedCargoAmount = function $scoopedCargoAmount(cmdty) {
var sdmc = worldScripts.Smugglers_MoveCargo;
if (sdmc._scoopedCargo.length === 0) return 0;
var amt = 0;
var sc = sdmc._scoopedCargo;
for (var i = 0; i < sc.length; i++) {
if (sc[i].commodity === cmdty) amt += sc[i].commodityAmount;
}
return amt;
} |
Scripts/smugglers_oolite_contracts_fix.js |
"use strict";
this.name = "Smugglers_Oolite_Contracts_Fix";
this.author = "phkb";
this.description = "Fixes the Oolite Cargo contracts system so it doesn't pick illegal commodities.";
this.licence = "CC BY-NC-SA 3.0";
this.startUp = function () {
var w = worldScripts["oolite-contracts-cargo"];
w.$hide = w._initialiseCargoContractsForSystem;
if (w.author.indexOf("Switeck") >= 0) {
w._initialiseCargoContractsForSystem = this.$switech_initialiseCargoContractsForSystem;
} else {
w._initialiseCargoContractsForSystem = this.$core_initialiseCargoContractsForSystem;
}
}
// initialise a new cargo contract list for the current system
this.$core_initialiseCargoContractsForSystem = function $core_initialiseCargoContractsForSystem() {
// clear list
this.$contracts = [];
// this is not the same algorithm as in 1.76, but should give
// similar results with comparable efficiency.
// no point in generating too many, as route-finding is slow
var numContracts = Math.floor(5 * Math.random() + 5 * Math.random() + 5 * Math.random() + (player.contractReputationPrecise * Math.random()));
if (player.contractReputationPrecise >= 0 && numContracts < 5) {
numContracts += 5;
}
if (numContracts > 16) {
numContracts = 16;
} else if (numContracts < 0) {
numContracts = 0;
}
// some of these possible contracts may be discarded later on
for (var i = 0; i < numContracts; i++) {
var cargo = new Object;
// pick a random system to take the goods to
var destination = Math.floor(Math.random() * 256);
// discard if chose the current system
if (destination === system.ID) {
continue;
}
// get the SystemInfo object for the destination
var destinationInfo = System.infoForSystem(galaxyNumber, destination);
if (destinationInfo.sun_gone_nova) {
continue;
}
var daysUntilDeparture = 1 + (Math.random() * (7 + player.contractReputationPrecise - destinationInfo.government));
if (daysUntilDeparture <= 0) {
// loses some more contracts if reputation negative
continue;
}
var si = worldScripts.Smugglers_Illegal;
var illegal = null;
if (si) {
illegal = si.$illegalGoodsListCommodityOnly(destination, true);
// add slaves to the list
illegal.push("slaves");
}
var commodities = Object.keys(system.mainStation.market);
var attempts = 0;
do {
var remotePrice = 0;
attempts++;
var commodity = commodities[Math.floor(Math.random() * commodities.length)];
// sub-tc contracts only available for top rep
if (system.mainStation.market[commodity]["quantity_unit"] != 0 && player.contractReputationPrecise < 6.5) {}
// ignore commodities with 0 availability here
else if (system.mainStation.market[commodity].quantity === 0) {}
// ignore any illegal goods
else if (illegal && illegal.indexOf(commodity) >= 0) {} else {
remotePrice = this._priceForCommodity(commodity, destinationInfo);
}
} while (remotePrice < system.mainStation.market[commodity].price / 20 && attempts < 10);
if (attempts === 10) {
// failed to find a good one.
continue;
}
cargo.commodity = commodity;
var amount = 0;
while (amount < 30) {
var unitsize = 1;
// larger unit sizes for kg/g commodities
if (system.mainStation.market[commodity]["quantity_unit"] === 1) {
unitsize += Math.floor(Math.random() * 6) + Math.floor(Math.random() * 6) + Math.floor(Math.random() * 6);
} else if (system.mainStation.market[commodity]["quantity_unit"] === 2) {
unitsize += Math.floor(Math.random() * 16) + Math.floor(Math.random() * 11) + Math.floor(Math.random() * 6);
}
amount += (1 + Math.floor(Math.random() * 32)) * (1 + Math.floor(Math.random() * 16)) * unitsize;
}
if (amount > 125 && system.mainStation.market[commodity]["quantity_unit"] === 0) {
// reduce the number of contracts only suitable for Anacondas
amount = Math.floor(amount / Math.floor(1 + (Math.random() * 4)));
}
cargo.size = amount;
// adjustment to prices based on quantity (larger = more profitable)
var discount = Math.min(10 + Math.floor(amount / 10), 35);
var unitPrice = system.mainStation.market[commodity].price * (100 - discount) / 1000;
var localValue = Math.floor(unitPrice * amount);
remotePrice = remotePrice * (200 + discount) / 200;
var remoteValue = Math.floor(remotePrice * amount);
var profit = remoteValue - localValue;
// skip if unprofitable
if (profit <= 100) {
continue;
}
// check that a route to the destination exists
// route calculation is expensive so leave this check to last
var routeToDestination = system.info.routeToSystem(destinationInfo);
// if the system cannot be reached, ignore this contract
if (!routeToDestination) {
continue;
}
// we now have a valid destination, so generate the rest of
// the parcel details
cargo.destination = destination;
// we'll need this again later, and route calculation is slow
cargo.route = routeToDestination;
// higher share for transporter for longer routes, less safe systems
var share = 100 + destinationInfo.government - (10 * routeToDestination.route.length);
if (share < 10) {
share = 10;
}
share = 100 - share;
// safety: now multiply the fee by 2 compared with 1.76 contracts
// prevents exploit discovered by Mad Hollander at
// http://bb.oolite.space/viewtopic.php?p=188127
localValue *= 2;
// this may need to be raised further
// absolute value of profit remains the same
var fee = localValue + Math.floor(profit * (share / 100));
fee -= fee % 20; // round to nearest 20 credits;
cargo.payment = fee;
cargo.deposit = localValue - (localValue % 20);
if (cargo.deposit >= cargo.payment) {
// rare but not impossible; last safety check
return;
}
// time allowed for delivery is time taken by "fewest jumps"
// route, plus timer above. Higher reputation makes longer
// times available.
cargo.deadline = clock.adjustedSeconds + Math.floor(daysUntilDeparture * 86400) + (cargo.route.time * 3600);
// add parcel to contract list
this._addCargoContractToSystem(cargo);
}
}
// initialise a new cargo contract list for the current system
this.$switech_initialiseCargoContractsForSystem = function $switech_initialiseCargoContractsForSystem() {
// clear list
this.$contracts = [];
// this is not the same algorithm as in 1.76, but should give similar results with comparable efficiency.
// no point in generating too many, as route-finding is slow
var numContracts = Math.floor(5 * (Math.random() + Math.random()) + (system.government + player.contractReputationPrecise - player.bounty * 0.02) * Math.random());
// I added that bounty can reduce the number of contracts. Corporate state systems can add extra contracts.
if (numContracts < 0) numContracts = 0;
if (player.contractReputationPrecise >= 0 && numContracts < 5) numContracts += 5;
if (numContracts > 18) numContracts = 18;
// some of these possible contracts may be discarded later on
var nearbysystems = system.info.systemsInRange(80 - player.contractReputationPrecise * 7); // 31-80-129 LY range...done here to save recalculations time.
log(this.name, " player.contractReputation= " + player.contractReputationPrecise + " numContracts= " + numContracts + " nearbysystems.length= " + nearbysystems.length);
// log(this.name," player.contractReputation= "+player.contractReputation+" numContracts= "+numContracts+" nearbysystems.length= "+nearbysystems.length+" nearbysystems= "+nearbysystems);
for (var i = 0; i < numContracts; i++) {
var scratchval = 1;
var attempts = 0;
do {
var scratchval = 1;
attempts++;
// pick a random system to take the goods to
// var destination = Math.floor(Math.random()*256); // ORIGINAL -- FOR TESTING ONLY!
var destination = nearbysystems[Math.floor(Math.random() * nearbysystems.length)].systemID;
// log(this.name," destination = "+destination);
// discard if chose the current system
if (destination === system.ID) {
var scratchval = 0;
} else {
// get the SystemInfo object for the destination
var destinationInfo = System.infoForSystem(galaxyNumber, destination);
// Decides firsthand to drop a bad system and choose another one?
if (Math.abs(system.economy - destinationInfo.economy) < (1 + player.contractReputationPrecise * 0.28) && player.contractReputationPrecise < 6.5 && system.economy < 7) {
var scratchval = 0; // Discarded, since identical or "worse" economies leave little opportunity for profitable trading.
} else {
// check that a route to the destination exists
// route calculation is expensive so leave this check to last
var routeToDestination = system.info.routeToSystem(destinationInfo);
//log(this.name," routeToDestination = "+routeToDestination);
// if the system cannot be reached, ignore this contract
if (!routeToDestination) {
var scratchval = 0; // No route, no point trying!
} else {
var daysUntilDeparture = 1 + (Math.random() * (7 + player.contractReputationPrecise - destinationInfo.government)); // NEEDS a better estimate based on time needed to reach target!
if (daysUntilDeparture < 0) var scratchval = 0; // negative reputation can make a contract out-of-time failed before starting.
}
}
}
} while (scratchval === 0 && attempts < 10);
if (attempts > 9) continue; // failed to find a good destination.
// we now have a valid destination, so generate the rest of the cargo contract details
//log(this.name," daysUntilDeparture = "+daysUntilDeparture);
// var commodities = Object.keys(system.mainStation.market);
var attempts = 0;
do {
var unitPrice = 0;
var unitMinPrice = 0;
var unitMaxPrice = 0;
var remotePrice = 0;
var remoteMinPrice = 0;
attempts++;
// if destinationInfo.economy < system.economy means destination is more industrial than start locaction.
// if system.economy <4 then it's "industrial" so choose comp,lux,mach,alloys (+firearms?)
// else it's "agricultural" so choose food,textiles,radioactives,liquor_wines,furs,minerals (+slaves, narcotics?)
// Odds get lowered if offender/fugitive, raised if high reputation...forcing more controlled items if "bad" and more gold/plat/gems if "good".
// var commodities = ["food","textiles","radioactives","slaves","liquor_wines","luxuries","narcotics","computers","machinery","alloys","firearms","furs","minerals","gold","platinum","gem_stones"];
// var commodity = commodities[Math.floor(Math.random()*commodities.length)]; // Chooses random commondity
if (system.economy > destinationInfo.economy || system.economy > 5) {
if (system.economy < destinationInfo.economy + 1 + player.contractReputationPrecise * 0.4) { // Eliminates marginal profit commodities from similar agri economies
var commodities = ["slaves", "narcotics", "liquor_wines", "alloys", "furs", "platinum", "gem_stones"]; // 7 entries, removed Gold!
var preccutoff = 5;
var scratchval = Math.floor(Math.random() * (commodities.length - 3) + 3); // Drops the controlled items and low profit stuff.
} else {
var commodities = ["slaves", "narcotics", "food", "minerals", "textiles", "radioactives", "liquor_wines", "furs", "gold", "platinum", "gem_stones"]; // 11 entries, sorted from worst to best
var preccutoff = 8;
var scratchval = Math.floor(Math.random() * (commodities.length - 5) + 5); // Drops the controlled items and low profit stuff.
}
} else if (system.economy > destinationInfo.economy - Math.max(0, player.contractReputationPrecise * 0.3)) { // Eliminates low-profit commodities when start economy === destination (identical ind economies)
var commodities = ["alloys", "furs", "gold", "platinum", "gem_stones"]; // 5 entries
var preccutoff = 2;
var scratchval = Math.floor(Math.random() * commodities.length);
} else if (system.economy > destinationInfo.economy - 1 - player.contractReputationPrecise * 0.2) { // Eliminates low-profit commodities when start economy is only slightly more industrial than destination.
var commodities = ["narcotics", "firearms", "computers", "alloys", "furs", "platinum", "gem_stones"]; // 7 entries, removed Gold!
var preccutoff = 5;
var scratchval = Math.floor(Math.random() * (commodities.length - 2) + 2); // Drops the controlled items and low profit stuff.
} else {
var commodities = ["narcotics", "firearms", "alloys", "machinery", "luxuries", "computers", "platinum", "gem_stones"]; // 8 entries, sorted from worst to best, removed Gold!
var preccutoff = 6;
var scratchval = Math.floor(Math.random() * (commodities.length - 2) + 2); // Drops the controlled items and low profit stuff.
}
if (player.contractReputationPrecise < 6.5 - Math.random() * 5) { // At rep>2, there's a chance of getting ONLY good contracts. The odds of this are much better by rep>5.
var scratchval = Math.floor(Math.random() * (preccutoff + player.contractReputationPrecise * 0.1 - player.bounty * 0.01));
}
if (scratchval < 0) var scratchval = 0; // If bad rep plus bad bounty pushes off leftside of the chart, give player "worst" contract.
if (scratchval >= preccutoff && player.contractReputationPrecise < 6.5) var scratchval = preccutoff - 1; // Prevents Gold contracts before player.contractReputation === 7
if (scratchval > commodities.length - 1) var scratchval = commodities.length - 1; // If high rep pushes off rightside of the chart, give player "best" contract.
// var commodities = ["gold","platinum","gem_stones"]; // 3 entries, tests only Gold/Plat/Gems!
// var scratchval = Math.floor(Math.random()*commodities.length);
var commodity = commodities[scratchval];
var si = worldScripts.Smugglers_Illegal;
var illegal = null;
if (si) {
illegal = si.$illegalGoodsListCommodityOnly(destination, true);
// add slaves to the list
illegal.push("slaves");
}
if (illegal && illegal.indexOf(commodity) >= 0) { // don't pick commodities illegal at the destination
if (system.mainStation.market[commodity].quantity > 0) { // ignore commodities with 0 availability here
var unitPrice = Number((system.mainStation.market[commodity].price * 0.1).toFixed(1));
var unitMinPrice = Number((this._priceForCommodity(system.mainStation.market[commodity], System.infoForSystem(galaxyNumber, system.ID).economy, 0)).toFixed(1));
var unitMaxPrice = Number((this._priceForCommodity(system.mainStation.market[commodity], System.infoForSystem(galaxyNumber, system.ID).economy, 255)).toFixed(1));
var remoteMinPrice = Number((this._priceForCommodity(system.mainStation.market[commodity], destinationInfo.economy, 0)).toFixed(1)); // ,0 means return smallest value
var remotePrice = Number((this._priceForCommodity(system.mainStation.market[commodity], destinationInfo.economy, 255)).toFixed(1)); // ,255 means return largest value
// var remotePrice = Number((this._priceForCommodity(system.mainStation.market[commodity],destinationInfo.economy,Math.floor(Math.random()*256))).toFixed(1)); // random prices!
// log(this.name," # "+attempts+", "+commodities+", "+preccutoff+", "+commodity+" val1="+scratchval+" Price="+unitPrice+" MinPrice="+unitMinPrice+" MaxPrice="+unitMaxPrice+" remMin="+remoteMinPrice+" remP= "+remotePrice+", "+system.economy+", "+destinationInfo.economy);
// This can happen with narcotics!
if (remotePrice < remoteMinPrice) {
var scratchval = remoteMinPrice;
var remoteMinPrice = remotePrice;
var remotePrice = scratchval;
}
if (unitMaxPrice < unitMinPrice) {
var scratchval = unitMaxPrice;
var unitMaxPrice = unitMinPrice;
var unitMinPrice = scratchval;
}
if (unitPrice < unitMinPrice) unitMinPrice = unitPrice;
if (unitPrice > unitMaxPrice) unitMaxPrice = unitPrice;
}
}
} while ((remotePrice - unitMinPrice) < Math.max(1, player.contractReputationPrecise * 0.5 - system.mainStation.market[commodity].quantityUnit * 3) && attempts < 10); // Allows Gold more often!
if (attempts > 9) continue; // failed to find a good commodity.
var cargo = new Object;
cargo.commodity = commodity;
var amount = 0;
var unitsize = 1;
// larger unit sizes for kg/g commodities
if (system.mainStation.market[commodity].quantityUnit === 1) {
unitsize += Math.ceil((Math.random() + Math.random() + Math.random()) * routeToDestination.route.length); // Adds more if routeToDestination.route.length > 5
} else if (system.mainStation.market[commodity].quantityUnit === 2) {
unitsize += Math.ceil((Math.random() + Math.random() + Math.random()) * routeToDestination.route.length * 2);
}
amount += Math.max(Math.ceil((1 + Math.random() * 32) * (1 + Math.random() * 16)), Math.floor(30 + Math.random() * 6)) * unitsize; // forced minimum amount to always be at least 30-35. Eliminates while-looping here!
if (amount > 125 && amount > player.ship.cargoSpaceCapacity && player.contractReputationPrecise >= 0 && system.mainStation.market[commodity].quantityUnit === 0) { // reduce the number of contracts only suitable for Anacondas
amount = Math.floor(amount / Math.floor(1 + (Math.random() * 4)));
}
cargo.size = amount;
var localValue = Math.floor(unitPrice * amount); // Total cost at Current/Original Price
var remoteValue = Math.floor(remotePrice * amount); // Remote max value
var profitMax = remoteValue - Math.floor(unitMinPrice * amount);
// discount adjustment to prices. Higher reputation and bulk quantities should make this more profitable
var discount = Number((Math.ceil(Math.max(50, Math.min(100, 20 + player.contractReputationPrecise * 10 + routeToDestination.route.length * 10 + amount * 0.1 + 50000 / profitMax - player.bounty * 0.1 - destinationInfo.government - system.government))) * 0.01).toFixed(2));
var profit = Math.ceil(profitMax * discount); // Uses discount directly on max profit to determine profit.
// if (profit < 100 + player.contractReputationPrecise*100 || profit > profitMax) profit = profitMax; // Ensures higher profits if payout would otherwise be too low.
// Formulas to generate ORIGINAL PROFIT AMOUNTS!
/*
var discount = Math.min(10+Math.floor(amount/10),35);
var unitPrice = system.mainStation.market[commodity].price * (100-discount) / 1000;
var localValue = Math.floor(unitPrice * amount);
remotePrice = remotePrice * (200+discount) / 200;
var remoteValue = Math.floor(remotePrice * amount);
var profit = remoteValue-localValue;
*/
var scratchval = this._priceForCommodity(system.mainStation.market[commodity], destinationInfo.economy, Math.floor(Math.random() * 256)); // random prices!
// var scratchval = remotePrice; // max selling price!
var discount2 = Number(Math.min(0.1 + Math.floor(amount * 0.1) * 0.01, 0.35).toFixed(2));
var profitORG = Math.floor(scratchval * (1 + 0.5 * discount2) * amount) - Math.floor(unitPrice * (1 - discount2) * amount); // Original results for profit!
var profitORGmax = Math.floor(remotePrice * (1 + 0.5 * discount2) * amount) - Math.floor(unitMinPrice * (1 - discount2) * amount); // Theoretical MAX Original results for profit!
// higher share for transporter for longer routes, less safe systems, and Higher reputation. lower share for high bounty! 100 bounty = 10% share loss!
var share = 100 + destinationInfo.government - (10 * routeToDestination.route.length);
if (share < 10) share = 10;
if (share > 100) share = 100;
share = 100 - share;
var profitORGmax = Math.floor(profitORGmax * share * 0.01);
// safety: now multiply the fee by 2 compared with 1.76 contracts
// prevents exploit discovered by Mad Hollander at
// http://bb.oolite.space/viewtopic.php?p=188127
// localValue *= 2; // This amount is so high in the event of a failed contract that it's practically PUNATIVE PUNISHMENT for those doing contracts.
// this may need to be raised further
// fee is total selling price.
// This IF-ELSE makes the cargo deposit equal or greater than the current selling value for the commodity.
if (localValue > remoteValue - profit) {
var fee = Math.ceil((localValue + profit) * 0.1) * 10; // round to nearest 10 credits
} else {
var fee = Math.ceil(remoteValue * 0.1) * 10; // round to nearest 10 credits
}
cargo.payment = fee;
cargo.deposit = Math.ceil((fee - profit) * 0.1) * 10; // round to nearest 10 credits
// logs nearly everything
log(this.name,
"Rep=" + player.contractReputationPrecise +
", " + commodity +
" size=" + cargo.size +
" econ=" + system.economy +
" DestEcon=" + destinationInfo.economy +
" jumps=" + routeToDestination.route.length +
" unitPrice=" + unitPrice +
" MinP=" + unitMinPrice +
" MaxP=" + unitMaxPrice +
" remMinP=" + remoteMinPrice +
" remP=" + remotePrice +
" locVal=" + localValue +
" deposit=" + cargo.deposit +
" profit=" + profit +
" pMax=" + profitMax +
" *" + discount +
" pORG=" + profitORG +
" pORGmax=" + profitORGmax +
" share=" + share +
" discount=" + discount2 +
" DestVal=" + remoteValue +
" Total=" + fee
);
cargo.destination = destination;
// we'll need this again later, and route calculation is slow
cargo.route = routeToDestination;
// time allowed for delivery is time taken by "fewest jumps"
// route, plus timer above. Higher reputation makes longer
// times available.
cargo.deadline = clock.adjustedSeconds + Math.floor(daysUntilDeparture * 86400) + (cargo.route.time * 3600);
// add parcel to contract list
if (cargo.deposit < cargo.payment) this._addCargoContractToSystem(cargo);
}
} |
Scripts/smugglers_phasescanner.js |
"use strict";
this.name = "Smugglers_PhaseScanner";
this.author = "phkb";
this.description = "Looks after the new phase scanning equipment activation.";
this.licence = "CC BY-NC-SA 3.0";
this._scanCount = 0; // percentage of scan completed
this._speedCount = 0; // counter for when player ship speed drops below 100 m/s.
this._scanTimer = null; // timer to perform scan
this._energy = null; // timer to deduct energy
this._energyReduction = 4; // amount of energy to deduct each quarter second
//-------------------------------------------------------------------------------------------------------------
this.activated = function () {
var core = worldScripts.Smugglers_CoreFunctions;
this.$rand = core.$rand;
var se = worldScripts.Smugglers_Equipment;
if (this._scanTimer && this._scanTimer.isRunning) {
this._scanTimer.stop();
this._energy.stop();
player.consoleMessage(expandMissionText("smuggling_scanner_stopped"));
se.$playSound("stop");
return;
}
var p = player.ship;
// is the equipment OK?
if (p.equipmentStatus("EQ_PHASE_SCANNER") != "EQUIPMENT_OK") {
se.$playSound("stop");
return;
}
// do we have a station target and is it a main station?
if (p.target != system.mainStation) {
player.consoleMessage(expandMissionText("smuggling_invalid_target"));
se.$playSound("stop");
return;
}
if (p.isCloaked) {
player.consoleMessage(expandMissionText("smuggling_cloaked"));
se.$playSound("stop");
return;
}
player.consoleMessage(expandMissionText("smuggling_scanner_started"));
this._scanCount = 0;
this._speedCount = 0;
if (this._scanTimer && this._scanTimer.isRunning) this._scanTimer.stop();
this._scanTimer = new Timer(this, this.$scanProcess, 3, 3);
if (this._energy && this._energy.isRunning) this._energy.stop();
this._energy = new Timer(this, this.$depleteEnergy, 0.25, 0.25);
se.$playSound("activate");
}
//-------------------------------------------------------------------------------------------------------------
// find all police or main stations within 15500km of of ship
this.$findLawVessels = function $findLawVessels(npc) {
function _ships(entity) {
return entity.isShip && entity.isPolice && !entity.isPlayer && !entity.isStation && !entity.isMainStation;
}
return system.filteredEntities(this, _ships, npc, npc.scannerRange * 0.6);
}
//-------------------------------------------------------------------------------------------------------------
this.$scanProcess = function $scanProcess() {
var p = player.ship;
// do we have a station target and is it a main station?
if (p.target != system.mainStation) {
player.consoleMessage(expandMissionText("smuggling_invalid_target"));
this._scanTimer.stop();
this._energy.stop();
return;
}
if (p.isCloaked) {
player.consoleMessage(expandMissionText("smuggling_cloaked"));
this._scanTimer.stop();
this._energy.stop();
return;
}
var se = worldScripts.Smugglers_Equipment;
// how far away are we?
var penalty = 0;
var msg = "";
var dist = p.position.distanceTo(p.target);
if (dist < (p.scannerRange * 0.78625) && se._phaseScannerDetected === false) {
// too close
msg = expandDescription("[illegal-scan-detected-station]");
p.target.commsMessage(msg, p);
penalty = this.$rand(20) + 10;
p.setBounty(player.bounty + penalty, "seen by police");
this.$sendEmail(penalty);
se._phaseScannerDetected = true;
}
// is there any police vessel in range?
var police = this.$findLawVessels(p);
if (police.length > 0 && se._phaseScannerDetected === false) {
msg = expandDescription("[illegal-scan-detected-police]");
penalty = this.$rand(20) + 10;
p.setBounty(player.bounty + penalty, "seen by police");
this.$sendEmail(penalty);
police[0].commsMessage(msg, p);
se._phaseScannerDetected = true;
}
// are we too far away for a good scan?
if (dist > (p.scannerRange * 0.90242)) {
return;
}
if (p.speed < 100 && this._speedCount > 20) {
// too slow for too long
msg = expandDescription("[illegal-scan-detected-station]");
p.target.commsMessage(msg, p);
penalty = this.$rand(20) + 10;
p.setBounty(player.bounty + penalty, "seen by police");
this.$sendEmail(penalty);
se._phaseScannerDetected = true;
}
// ok, we're close enough, so increase the percentage
this._scanCount += 1;
player.consoleMessage(expandMissionText("smuggling_scan", { amount: (this._scanCount * 10) }), 3);
if (this._scanCount >= 10) {
var phase = se.$getSystemPhase(system.ID);
player.consoleMessage(expandMissionText("smuggling_scan_result", { phase: phase }), 6);
// add it to our discovered list
se.$addPhaseScan(phase, system.ID, 1);
// stop the timer and reset the count
this._scanTimer.stop();
this._energy.stop();
this._scanCount = 0;
}
}
//-------------------------------------------------------------------------------------------------------------
this.$depleteEnergy = function $depleteEnergy() {
var p = player.ship;
p.energy -= this._energyReduction;
if (p.energy < 64) {
this._scanTimer.stop();
this._energy.stop();
player.consoleMessage(expandMissionText("smuggling_insufficient_energy"));
}
if (p.speed < 100) {
this._speedCount += 1;
}
}
//-------------------------------------------------------------------------------------------------------------
this.$sendEmail = function $sendEmail(penalty) {
var email = worldScripts.EmailSystem;
if (email) {
var ga = worldScripts.GalCopAdminServices;
if (ga._galCopBountyOfficer === "") ga._galCopBountyOfficer = expandDescription("%N [nom]");
email.$createEmail({
sender: expandDescription("[galcop-bounty-sender]"),
subject: expandMissionText("smuggling_bounty"),
date: clock.seconds,
message: expandMissionText("galcop-bounty-applied", {
amount: penalty,
systemname: system.info.name,
sender: ga._galCopBountyOfficer
}),
expiryDays: ga._defaultExpiryDays
});
}
} |
Scripts/smugglers_tradeembargo.js |
"use strict";
this.name = "Smugglers_TradeEmbargo";
this.author = "phkb";
this.description = "Looks after the process of applying trade embargoes to systems.";
this.licence = "CC BY-NC-SA 3.0";
/* TODO:
- work out how to actually implement a trade embargo
- idea: work out how to remove a planet from the galactic map
- then get special device that will override embargo witchspace blockage
- witchpoint will be filled with police, arriving will instantly give player a bounty
- Create routine to add trade embargos
- Create more reasons to the list.
*/
this._embargoReasons = [{
govTypes: "0",
name: "",
period: 60,
description: "GalCop is trying to get the system to crack down on pirates, but they have been unwilling. A trade embargo has been put in place to try to make them reconsider."
},
{
govTypes: "7",
name: "",
period: 60,
description: "The system has been attempting to subvert GalCop policies by working outside and around GalCop law. GalCop has imposed a trade embargo to bring them back into line."
}
];
this._core = null; // link to core functions script
//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
this._core = worldScripts.Smugglers_CoreFunctions;
} |