Config/script.js |
"use strict";
this.name = "Smugglers_BlackMarket";
this.author = "phkb";
this.description = "Looks after the Black Market interface screen.";
this.licence = "CC BY-NC-SA 3.0";
/*
Ideas:
- Add an equipment selling facility, so players can try to sell equipment for a profit
- add interface into SDC to "board ship" then "steal equipment" from NPC ships
- need ships created by SDC to include default equipment from SC
- Add notes to bulletin board about where you might be able to find the phase scanner, then increase chance at that destination
*/
this._disabled = false;
this._debug = false;
this._smugglingAllegiance = ["pirate", "chaotic"];
this._includeRoles = ["rockhermit", "rockhermit-chaotic", "rockhermit-pirate", "random_hits_any_spacebar"]; // make sure these stations have a Black Market
this._excludeRoles = ["slaver_base", "rrs_slaverbase"]; // stations with these roles won't have a Black Market
this._fakePermits = []; // list of systems where fake permits can be bought, plus the rating of each
// value of 0 means no fake permits can be bought in that system
// value of 0.5 to 0.99 reliability of permits bought (0.99 means almost perfect)
this._display = 0;
this._noticeboard = [];
this._selectedIndex = 0;
this._waypoints = [];
this._fakePermitCost = 120;
this._waypointCost = 20;
this._phaseScanCost = 450;
this._blackMarketSalesPerson = "";
this._sellCommodity = "";
this._sellQuantity = 0;
this._sellType = "";
this._offerQuantity = 0;
this._offerPrice = 0.0;
this._menuColor = "orangeColor";
this._itemColor = "yellowColor";
this._disabledColor = "darkGrayColor";
this._blackMarketSales = [];
this._blackMarketContacts = [];
this._blackMarketShutdown = [];
this._blackMarketWelcome = "";
this._sting = false;
this._stingShip = null;
this._stingStation = null;
this._stingShipChance = 0.3;
this._noBribe = false;
this._lastChoice = ["", "", "", "", "", "", "", "", "", "", ""];
this._additionalSaleItems = [];
this._systemFactor = -1;
this._stationIncludeScriptKey = [];
this._stationExcludeScriptKey = [];
this._bribeChance = 0;
this._stash = [];
this._stashLocation = null;
this._pirates = [];
this._curpage = 0;
//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
if (this._disabled) {
delete this.playerWillSaveGame;
delete this.playerEnteredNewGalaxy;
delete this.shipExitedWitchspace;
delete this.shipDockedWithStation;
delete this.shipLaunchedFromStation;
delete this.startUpComplete;
return;
}
if (worldScripts.Smugglers_Illegal) this._smugglers = true;
if (missionVariables.Smuggling_Noticeboard) {
this._noticeboard = JSON.parse(missionVariables.Smuggling_Noticeboard);
} else {
this._rebuildTimer = new Timer(this, this.$buildNoticeboard, 2, 0);
}
if (this._smugglers) {
if (missionVariables.Smuggling_FakePermits) {
this._fakePermits = JSON.parse(missionVariables.Smuggling_FakePermits);
} else {
this.$buildFakePermitArray();
}
}
if (missionVariables.Smuggling_Waypoints) this._waypoints = JSON.parse(missionVariables.Smuggling_Waypoints);
if (missionVariables.Smuggling_BlackMarketSales) {
this._blackMarketSales = JSON.parse(missionVariables.Smuggling_BlackMarketSales);
delete missionVariables.Smuggling_BlackMarketSales;
}
if (missionVariables.Smuggling_BlackMarketContacts) this._blackMarketContacts = JSON.parse(missionVariables.Smuggling_BlackMarketContacts);
if (missionVariables.Smuggling_BlackMarketShutdown) this._blackMarketShutdown = JSON.parse(missionVariables.Smuggling_BlackMarketShutdown);
if (missionVariables.Smuggling_BlackMarketSting) this._sting = missionVariables.Smuggling_BlackMarketSting;
if (missionVariables.Smuggling_BlackMarketStingShipChance) this._stingShipChance = missionVariables.Smuggling_BlackMarketStingShipChance;
if (missionVariables.Smuggling_BlackMarketAdditional) this._additionalSaleItems = JSON.parse(missionVariables.Smuggling_BlackMarketAdditional);
if (missionVariables.Smuggling_BlackMarketSystemFactor) this._systemFactor = missionVariables.Smuggling_BlackMarketSystemFactor;
if (this._systemFactor === -1) this.$setupSystemFactor();
if (missionVariables.Smuggling_BlackMarketStashes) this._stash = JSON.parse(missionVariables.Smuggling_BlackMarketStashes);
for (var i = this._stash.length - 1; i >= 0; i--) {
if (this._stash[i].systemID == system.ID && (clock.adjustedSeconds - this._stash[i].created) / 86400 < 5) {
this.$setupCargoStash();
}
if ((clock.adjustedSeconds - this._stash[i].created) / 86400 >= 5) {
this._stash.splice(i, 1);
}
}
// because stations display name may not be populated at this point, create a timer to set up the sting
if (this._sting) this._delayStingSetup = new Timer(this, this.$setupStingAfterLoad, 2, 0);
// set up the interface screen, if required
this.$initMainInterface(player.ship.dockedStation);
this.$addCoreEquipmentToBlackMarket();
}
//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
missionVariables.Smuggling_Noticeboard = JSON.stringify(this._noticeboard);
if (this._smugglers) missionVariables.Smuggling_FakePermits = JSON.stringify(this._fakePermits);
missionVariables.Smuggling_Waypoints = JSON.stringify(this._waypoints);
missionVariables.Smuggling_BlackMarketStingShipChance = this._stingShipChance;
if (this._blackMarketSales.length > 0) missionVariables.Smuggling_BlackMarketSales = JSON.stringify(this._blackMarketSales);
if (this._blackMarketContacts.length > 0) missionVariables.Smuggling_BlackMarketContacts = JSON.stringify(this._blackMarketContacts);
if (this._blackMarketShutdown.length > 0) missionVariables.Smuggling_BlackMarketShutdown = JSON.stringify(this._blackMarketShutdown);
if (this._additionalSaleItems.length > 0) missionVariables.Smuggling_BlackMarketAdditional = JSON.stringify(this._additionalSaleItems);
missionVariables.Smuggling_BlackMarketSystemFactor = this._systemFactor;
if (this._sting) {
missionVariables.Smuggling_BlackMarketSting = this._sting;
missionVariables.Smuggling_BlackMarketStingStation = this._stingStation.displayName;
if (this._stingShip) missionVariables.Smuggling_BlackMarketStingShip = true;
}
if (this._stash.length > 0) {
missionVariables.Smuggling_BlackMarketStashes = JSON.stringify(this._stash);
} else {
if (missionVariables.Smuggling_BlackMarketStashes) {
delete missionVariables.Smuggling_BlackMarketStashes;
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerEnteredNewGalaxy = function (galaxyNumber) {
if (this._smugglers) this.$buildFakePermitArray();
this._waypoints = [];
this._blackMarketShutdown = [];
this._stash.length = 0;
}
//-------------------------------------------------------------------------------------------------------------
this.shipExitedWitchspace = function () {
this._bribeChance = Math.random();
this._additionalSaleItems = [];
this.$setupSystemFactor();
// rebuild the notice board a few seconds after entering a new system
// that should give the other systems a chance to finish
this._rebuildTimer = new Timer(this, this.$buildNoticeboard, 5, 0);
this.$addRHWaypoint();
this._blackMarketSales = [];
// reset any sting info
this._sting = false;
this._stingStation = null;
this._stingShip = null;
// find a station with a black market
var stns = system.stations;
for (var i = 0; i < stns.length; i++) {
if (this.$doesStationHaveBlackMarket(stns[i]) === true) {
var hasVisited = this.$playerHasBeenToBlackMarket(stns[i]);
// there's a small chance of a black market sting if the player has visited the station, and an even smaller chance if they haven't
if ((hasVisited === true && Math.random() > 0.9) || (hasVisited === false && Math.random() > 0.98)) {
// set up the sting
this.$setupSting(stns[i]);
// don't set up more than one sting operation, so break here when we're done.
break;
}
}
}
// clean up any shutdowns that have expired
if (this._blackMarketShutdown.length > 0) {
for (var i = this._blackMarketShutdown.length - 1; i >= 0; i--) {
if (clock.adjustedSeconds - this._blackMarketShutdown[i].date > 2592000) this._blackMarketShutdown.splice(i, 1);
}
}
// cargo stash
for (var i = this._stash.length - 1; i >= 0; i--) {
if (this._stash[i].systemID == system.ID && (clock.adjustedSeconds - this._stash[i].created) / 86400 < 5) {
this.$setupCargoStash();
}
if ((clock.adjustedSeconds - this._stash[i].created) / 86400 >= 5) {
this._stash.splice(i, 1);
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipDockedWithStation = function (station) {
this.$addCoreEquipmentToBlackMarket();
this.$initMainInterface(station);
this._blackMarketSalesPerson = "";
this._blackMarketWelcome = "";
// remove the sting ship after we dock, if it's still there
if (this._sting === true && this._stingStation === station && this._stingShip && this._stingShip.isValid) {
this._stingShip.remove(true);
this._stingShip = null;
}
}
//-------------------------------------------------------------------------------------------------------------
this.shipLaunchedFromStation = function (station) {
this.$addRHWaypoint();
// remove the sale items when we launch
this.$removeSaleItem("EQ_CLOAKING_DEVICE");
var eq = player.ship.equipment;
for (var i = 0; i < eq.length; i++) {
if (eq[i].equipmentKey.indexOf("NAVAL") >= 0 || eq[i].equipmentKey.indexOf("MILITARY") >= 0) {
var item = EquipmentInfo.infoForKey(eq[i].equipmentKey);
this.$removeSaleItem(eq[i].equipmentKey);
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.guiScreenChanged = function (to, from) {
if (guiScreen === "GUI_SCREEN_SYSTEM_DATA") {
this.$checkForWaypoints();
}
}
//-------------------------------------------------------------------------------------------------------------
this.infoSystemChanged = function (to, from) {
if (guiScreen === "GUI_SCREEN_SYSTEM_DATA") {
this.$checkForWaypoints();
}
}
//-------------------------------------------------------------------------------------------------------------
this.$checkForWaypoints = function() {
if (this._waypoints.length > 0) {
var sysID = player.ship.targetSystem;
if (player.ship.hasOwnProperty("infoSystem")) sysID = player.ship.infoSystem;
if (this._waypoints.indexOf(sysID) >= 0) {
mission.addMessageText(expandDescription("[blackmarket-waypoint-here]"));
}
}
}
//-------------------------------------------------------------------------------------------------------------
/* adds an item to the Black Market additional sale items
passed object must have:
key: (required) text to be sent back to the calling OXP to identify the sale item
text: (required) text to be displayed on the sale screen
cost: (required) cost of the item to be sold. must be greater than 0
worldScript: (required) name of the calling worldScript
sellCallback: (required) name of the function to call if the item is sold
*/
this.$addSaleItem = function $addSaleItem(obj) {
if (obj.hasOwnProperty("key") === false || obj.key == "") {
throw "Invalid sale item properties: 'key' must be supplied";
}
if (obj.hasOwnProperty("text") === false || obj.text == "") {
throw "Invalid sale item properties: 'text' must be supplied";
}
if (obj.hasOwnProperty("cost") === false) {
throw "Invalid sale item properties: 'cost' must be supplied";
}
if (parseInt(obj.cost) === 0) {
throw "Invalid sale item properties: 'cost' must be greater than 0";
}
if (obj.hasOwnProperty("worldScript") === false || obj.worldScript == "") {
throw "Invalid sale item properties: 'worldScript' must be supplied";
}
if (obj.hasOwnProperty("sellCallback") === false || obj.sellCallback == "") {
throw "Invalid sale item properties: 'sellCallback' must be supplied";
}
for (var i = 0; i < this._additionalSaleItems.length; i++) {
if (this._additionalSaleItems[i].key === obj.key) {
throw "Invalid sale item properties: 'key' of " + obj.key + " is already in use.";
}
}
this._additionalSaleItems.push(obj);
}
//-------------------------------------------------------------------------------------------------------------
// removes all items from the sale list linked to a particular worldScript
this.$removeWorldScriptItems = function $removeWorldScriptItems(ws) {
for (var i = this._additionalSaleItems.length - 1; i >= 0; i--) {
if (this._additionalSaleItems[i].worldScript === ws) {
this._additionalSaleItems.splice(i, 1);
}
}
}
//-------------------------------------------------------------------------------------------------------------
// removes an item from the sale list with the specific key value
this.$removeSaleItem = function $removeSaleItem(key) {
for (var i = 0; i < this._additionalSaleItems.length; i++) {
if (this._additionalSaleItems[i].key === key) {
this._additionalSaleItems.splice(i, 1);
break;
}
}
}
//-------------------------------------------------------------------------------------------------------------
// add a noticeboard item, with a callback for when it is viewed
this.$addNoticeboardItem = function(msg, ws, fn) {
function compare(a, b) {
if (a.idx < b.idx) return -1;
if (a.idx > b.idx) return 1;
return 0;
}
var item = {
idx: this.$rand(100),
message: msg,
};
if (ws && ws != "" && fn && fn != "") {
item["worldscript"] = ws;
item["function"] = fn;
}
this._noticeboard.push(item);
// sort the list, based on the random index, so the items are mixed up.
this._noticeboard.sort(compare);
}
//-------------------------------------------------------------------------------------------------------------
// initialise the illegal goods F4 screen entries
this.$initMainInterface = function $initMainInterface(station) {
// only at pirate or chaotic stations, all rock hermits, and selected main stations
if (this._debug === true || (this.$doesStationHaveBlackMarket(station) === true)) {
station.setInterface(this.name, {
title: "Black market",
category: "Station Interfaces",
summary: "Access to the Black Market of the Galactic Underworld.",
callback: this.$initialBlackMarket.bind(this)
});
} else {
station.setInterface(this.name, null);
}
}
//-------------------------------------------------------------------------------------------------------------
this.$isStationIncluded = function $isStationIncluded(station) {
for (var i = 0; i < this._includeRoles.length; i++) {
if (station.hasRole(this._includeRoles[i]) === true) return true;
}
if (this._stationIncludeScriptKey.length > 0) {
for (var i = 0; i < this._stationIncludeScriptKey.length; i++) {
var item = this._stationIncludeScriptKey[i].key;
var value = this._stationIncludeScriptKey[i].value;
if (station.script.hasOwnProperty(item) === true && station.script[item] == value) return true;
}
}
return false;
}
//-------------------------------------------------------------------------------------------------------------
this.$isStationExcluded = function $isStationExcluded(station) {
for (var i = 0; i < this._excludeRoles.length; i++) {
if (station.hasRole(this._excludeRoles[i]) === true) return true;
}
if (this._stationExcludeScriptKey.length > 0) {
for (var i = 0; i < this._stationExcludeScriptKey.length; i++) {
var item = this._stationExcludeScriptKey[i].key;
var value = this._stationExcludeScriptKey[i].value;
if (station.script.hasOwnProperty(item) === true && station.script[item] == value) return true;
}
}
return false;
}
//-------------------------------------------------------------------------------------------------------------
this.$initialBlackMarket = function $initialBlackMarket() {
this._display = 0;
this._selectedIndex = 0;
this._curpage = 0;
this.$blackMarketOptions();
}
//-------------------------------------------------------------------------------------------------------------
this.$blackMarketOptions = function $blackMarketOptions() {
var curChoices = {};
var text = "";
var p = player.ship;
var stn = p.dockedStation;
var def = "";
var si = worldScripts.Smugglers_Illegal;
var se = worldScripts.Smugglers_Equipment;
var sc = worldScripts.Smugglers_Contracts;
var pagesize = 20;
var image = "blackmarket-skull.png";
if (this.$isBigGuiActive() === true) {
pagesize = 26;
}
if (this._smugglers) {
sc._smugglingPageOverlay = image;
sc._smugglingPageOverlayHeight = 546;
}
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) {
// if we haven't shown the initial welcome, get one now
if (this._blackMarketWelcome === "") {
// use one of the standard welcomes, but if it's a sting use the alternate ones. Also, there's a chance of the alternate ones anyway, so it's not a complete give-away
this._blackMarketWelcome = expandDescription("[blackmarket-welcome" + (this._sting === true || Math.random() > 0.8 ? "-sting" : "") + "]", {
contactname: this.$getBlackMarketContact(p.dockedStation)
});
}
// add this to the text
text = this._blackMarketWelcome
// reset the welcome text for the next time we show the main menu, so that the welcome text is only displayed once.
this._blackMarketWelcome = "Black Market services available:";
var itemcount = 2;
curChoices["01_NOTICEBOARD"] = {
text: "[blackmarket-noticeboard]",
color: this._menuColor
};
if (this._waypoints.length > 0) {
curChoices["01A_CURRENT_WAYPOINTS"] = {
text: "[blackmarket-list-waypoints]",
color: this._menuColor
};
itemcount += 1;
}
if (!worldScripts.ContractsOnBB && this._smugglers == true) {
// contracts only available at rock hermits
if ((this._debug === true ||
(Ship.roleIsInCategory(p.dockedStation.primaryRole, "oolite-rockhermits") && p.dockedStation.hasRole("slaver_base") === false && p.dockedStation.hasRole("rrs_slaverbase") === false)) &&
sc._contracts.length > 0) {
//if ((this._debug === true || this._smugglingAllegiance.indexOf(p.dockedStation.allegiance) >= 0) && sc._contracts.length > 0) { // alternate logic for non-galcop stations
curChoices["02_CONTRACTS"] = {
text: "View any smuggling contracts on offer (" + sc._contracts.length + " available)",
color: this._menuColor
};
itemcount += 1;
}
}
curChoices["03_PURCHASE"] = {
text: "[blackmarket-purchasing]",
color: this._menuColor
};
if (this._smuggling) {
if (se.$playerHasIllegalCargo(system.mainStation) === true || se.$playerHasHiddenIllegalCargo(system.mainStation) === true) {
var saleitems = 0;
var viscargo = p.manifest.list;
for (var i = 0; i < viscargo.length; i++) {
if (system.mainStation.market[viscargo[i].commodity].legality_import > 0 && this._blackMarketSales.indexOf(viscargo[i].commodity) === -1) saleitems += 1;
}
var smuggle = se.$getSmugglingCargo();
for (var i = 0; i < smuggle.length; i++) {
if (system.mainStation.market[smuggle[i].commodity].legality_import > 0 && this._blackMarketSales.indexOf(smuggle[i].commodity) === -1) saleitems += 1;
}
if (saleitems > 0) {
curChoices["04_SELL_ILLEGAL"] = {
text: "[blackmarket-sellcargo-menu]",
color: this._menuColor
};
itemcount += 1;
}
}
if (se.$sellablePhaseScans() > 0) {
curChoices["07_SELLSCAN"] = {
text: "[blackmarket-sellphasescan-menu]",
color: this._menuColor
};
itemcount += 1;
}
}
if (this._additionalSaleItems.length > 0) {
curChoices["08_SELLADDITIONAL"] = {
text: "Sell additional items",
color: this._menuColor
}
itemcount += 1;
}
curChoices["99_EXIT"] = {
text: "[blackmarket-return]",
color: this._itemColor
};
for (var i = 0; i < ((pagesize - 4) - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
def = "99_EXIT";
if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
var opts = {
screenID: "oolite-smuggling-blackmarket-map",
title: "Black Market Main Menu",
overlay: {
name: image,
height: 546
},
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// display noticeboard item
if (this._display === 2) {
if (this._selectedIndex < this._noticeboard.length - 1) {
curChoices["20_NEXTITEM"] = {
text: "[blackmarket-nextitem]",
color: this._menuColor
};
curChoices["30_LASTITEM"] = {
text: "[blackmarket-lastitem]",
color: this._menuColor
};
} else {
curChoices["20_NEXTITEM"] = {
text: "[blackmarket-nextitem]",
unselectable: true,
color: this._disabledColor
};
curChoices["30_LASTITEM"] = {
text: "[blackmarket-lastitem]",
unselectable: true,
color: this._disabledColor
};
}
if (this._selectedIndex > 0) {
curChoices["21_PREVITEM"] = {
text: "[blackmarket-previtem]",
color: this._menuColor
};
curChoices["31_FIRSTITEM"] = {
text: "[blackmarket-firstitem]",
color: this._menuColor
};
} else {
curChoices["21_PREVITEM"] = {
text: "[blackmarket-previtem]",
unselectable: true,
color: this._disabledColor
};
curChoices["31_FIRSTITEM"] = {
text: "[blackmarket-firstitem]",
unselectable: true,
color: this._disabledColor
};
}
curChoices["98_EXIT"] = {
text: "[blackmarket-return]",
color: this._itemColor
};
for (var i = 0; i < (pagesize - 10); i++) {
curChoices["99_SPACER_" + i] = "";
}
if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
var opts = {
screenID: "oolite-smuggling-blackmarket-map",
title: "Noticeboard Item (" + (this._selectedIndex + 1) + " of " + (this._noticeboard.length) + ")",
overlay: {
name: image,
height: 546
},
allowInterrupt: true,
choices: curChoices,
initialChoicesKey: def,
exitScreen: "GUI_SCREEN_INTERFACES",
message: this._noticeboard[this._selectedIndex].message
};
// call the callback, if present
if (this._noticeboard[this._selectedIndex].hasOwnProperty("worldscript") && this._noticeboard[this._selectedIndex].hasOwnProperty("function")) {
var ws = this._noticeboard[this._selectedIndex].hasOwnProperty("worldscript");
var fn = this._noticeboard[this._selectedIndex].hasOwnProperty("function");
if (worldScripts[ws][fn]) {
worldScripts[ws][fn]();
}
}
}
// purchase items
if (this._display === 3) {
text = expandDescription("[blackmarket-purchaseheader]");
var itemcount = 0;
if (this._smuggling && this._fakePermits[system.ID] > 0) {
curChoices["04_FAKEPERMITS"] = {
text: "[blackmarket-buypermits-menu]",
color: this._menuColor
};
itemcount += 1;
}
curChoices["05_WAYPOINTS"] = {
text: "[blackmarket-buywaypoints-menu]",
color: this._menuColor
};
itemcount += 1;
if (this._smuggling) {
curChoices["06_PHASESCAN"] = {
text: "[blackmarket-buyphasescan-menu]",
color: this._menuColor
};
itemcount += 1;
}
curChoices["98_EXIT"] = {
text: "[blackmarket-return]",
color: this._itemColor
};
for (var i = 0; i < ((pagesize - 1) - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
def = "98_EXIT";
if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
var opts = {
screenID: "oolite-smuggling-blackmarket-map",
title: "Black Market Shop",
allowInterrupt: true,
overlay: {
name: image,
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// purchase fake permits
if (this._display === 4) {
text = expandDescription("[blackmarket-buypermits]", {
cash: formatCredits(player.credits, true, true)
});
text += this.$padTextRight("Item", 20) + this.$padTextLeft("Cost", 10);
// get list of local planets
var sys = system.info.systemsInRange(15);
var itemcount = 0;
// loop through list
for (var i = 0; i < sys.length; i++) {
// for any that have illegal goods that can have permits, add the planet name + permit type to the list
var goods = si.$illegalGoodsList(sys[i].systemID);
if (goods.length > 0) {
for (var j = 0; j < goods.length; j++) {
if (goods[j].permit === 1 && system.scrambledPseudoRandomNumber(j) > 0.6 && si.$playerHasPermit(sys[i].systemID, goods[j].commodity, false) === false) {
curChoices["60_PERMIT~" + sys[i].systemID + "|" + goods[j].commodity] = {
text: this.$padTextRight(sys[i].name + " (" + govs[sys[i].government] + spc + "TL" + (sys[i].techlevel + 1) + ") -- " + si.$translateCommodityList(goods[j].commodity), 20) +
this.$padTextLeft(formatCredits(this._fakePermitCost * stn.equipmentPriceFactor, true, true), 10),
alignment: "LEFT",
color: this._menuColor
};
itemcount += 1;
}
}
}
}
if (itemcount === 0) text += expandDescription("[blackmarket-none-available]");
curChoices["96_SPACER"] = "";
itemcount += 1;
// display the list of options
curChoices["97_EXIT"] = {
text: "[blackmarket-return]",
color: this._itemColor
};
for (var i = 0; i < ((pagesize - 4) - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
def = "97_EXIT";
if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
var opts = {
screenID: "oolite-smuggling-blackmarket-map",
title: "Black Market Shop",
overlay: {
name: image,
height: 546
},
allowInterrupt: true,
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// purchase rock hermit waypoints
if (this._display === 5) {
text = expandDescription("[blackmarket-buywaypoints]", {
cash: formatCredits(player.credits, true, true)
});
text += this.$padTextRight("Item", 20) + this.$padTextLeft("Cost", 10);
var sys = system.info.systemsInRange(7);
var itemcount = 0;
for (var i = 0; i < sys.length; i++) {
if (this._waypoints.indexOf(sys[i].systemID) === -1 && system.scrambledPseudoRandomNumber(sys[i].systemID) > 0.7) {
curChoices["61_WAYPOINT_" + (i < 10 ? "0" : "") + i + "~" + sys[i].systemID] = {
text: this.$padTextRight(sys[i].name + " (" + govs[sys[i].government] + spc + "TL" + (sys[i].techlevel + 1) + ")", 20) +
this.$padTextLeft(formatCredits(this._waypointCost * stn.equipmentPriceFactor, true, true), 10),
alignment: "LEFT",
color: this._menuColor
};
itemcount += 1;
}
}
if (itemcount === 0) text += expandDescription("[blackmarket-none-available]");
curChoices["96_SPACER"] = "";
itemcount += 1;
// display the list of options
curChoices["97_EXIT"] = {
text: "[blackmarket-return]",
color: this._itemColor
};
for (var i = 0; i < ((pagesize - 4) - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
def = "97_EXIT";
if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
var opts = {
screenID: "oolite-smuggling-blackmarket-map",
title: "Black Market Shop",
allowInterrupt: true,
overlay: {
name: image,
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// purchase phase scan settings
if (this._display === 6) {
text = expandDescription("[blackmarket-buyphasescan]", {
cash: formatCredits(player.credits, true, true)
});
text += this.$padTextRight("Item", 20) + this.$padTextLeft("Cost", 10);
// there won't be many of these
// get a list of all planets with illegal goods
var sys = system.info.systemsInRange(7);
var itemcount = 0;
for (var i = 0; i < sys.length; i++) {
var goods = si.$illegalGoodsList(sys[i].systemID);
if (se.$playerHasPhaseScan(sys[i].systemID) === false && system.scrambledPseudoRandomNumber(sys[i].systemID) > 0.5) {
curChoices["62_PHASESCAN~" + sys[i].systemID] = {
text: this.$padTextRight(sys[i].name + " (" + govs[sys[i].government] + spc + "TL" + (sys[i].techlevel + 1) + ")", 20) +
this.$padTextLeft(formatCredits(this._phaseScanCost * stn.equipmentPriceFactor, true, true), 10),
alignment: "LEFT",
color: this._menuColor
};
itemcount += 1;
}
}
if (itemcount === 0) text += expandDescription("[blackmarket-none-available]");
curChoices["96_SPACER"] = "";
itemcount += 1;
// display the list of options
curChoices["97_EXIT"] = {
text: "[blackmarket-return]",
color: this._itemColor
};
for (var i = 0; i < ((pagesize - 4) - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
def = "97_EXIT";
if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
var opts = {
screenID: "oolite-smuggling-blackmarket-map",
title: "Black Market Shop",
allowInterrupt: true,
overlay: {
name: image,
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// sell phase scan
if (this._display === 7) {
text = expandDescription("[blackmarket-sellphasescan]", {
cash: formatCredits(player.credits, true, true)
});
text += this.$padTextRight("Item", 20) + this.$padTextLeft("Cost", 10);
var list = se.$getSellablePhaseScans();
for (var i = 0; i < list.length; i++) {
curChoices["63_PHASESCAN~" + (i < 10 ? "0" : "") + i] = {
text: this.$padTextRight(list[i].text, 20) +
this.$padTextLeft(formatCredits(((this._phaseScanCost * stn.equipmentPriceFactor) * 0.8), true, true), 10),
alignment: "LEFT",
color: this._menuColor
};
}
curChoices["96_SPACER"] = "";
// display the list of options
curChoices["97_EXIT"] = {
text: "[blackmarket-return]",
color: this._itemColor
};
for (var i = 0; i < ((pagesize - 4) - list.length); i++) {
curChoices["99_SPACER_" + i] = "";
}
def = "97_EXIT";
if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
var opts = {
screenID: "oolite-smuggling-blackmarket-map",
title: "Sell Discovered Phase Scan",
allowInterrupt: true,
overlay: {
name: image,
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// sell illegal cargo on black market
if (this._display === 8) {
text = expandDescription("[blackmarket-sellcargo]", {
cash: formatCredits(player.credits, true, true)
});
var sdm = worldScripts.Smugglers_DockMaster;
var heading = false;
var itemcount = 0;
var viscargo = p.manifest.list;
for (var i = 0; i < viscargo.length; i++) {
if (system.mainStation.market[viscargo[i].commodity].legality_import > 0 && this._blackMarketSales.indexOf(viscargo[i].commodity) === -1) {
if (heading === false) {
curChoices["73_HEADING"] = {
text: "[blackmarket-standard-hold]",
alignment: "LEFT",
color: this._itemColor,
unselectable: true
};
heading = true;
itemcount += 1;
}
var q = viscargo[i].quantity;
// remove any relabelled cargo from sale
if (sdm && sdm.$getTotalRelabelled(viscargo[i].commodity) > 0) q = q - sdm.$getTotalRelabelled(viscargo[i].commodity);
if (q > 0) {
curChoices["73_SELL~" + viscargo[i].commodity] = {
text: viscargo[i].displayName + " (" + q + viscargo[i].unit + ")",
alignment: "LEFT",
color: this._menuColor
};
itemcount += 1;
}
}
}
heading = false;
if (this._smuggling) {
var smuggle = se.$getSmugglingCargo();
for (var i = 0; i < smuggle.length; i++) {
if (system.mainStation.market[smuggle[i].commodity].legality_import > 0 && this._blackMarketSales.indexOf(smuggle[i].commodity) === -1) {
if (heading === false) {
curChoices["74_HEADING"] = {
text: "[blackmarket-smuggling-compartment]",
alignment: "LEFT",
color: this._itemColor,
unselectable: true
};
heading = true;
itemcount += 1;
}
curChoices["74_SELL~" + smuggle[i].commodity] = {
text: smuggle[i].quantity + " " + smuggle[i].unit + " × " + smuggle[i].displayName,
alignment: "LEFT",
color: this._menuColor
};
itemcount += 1;
}
}
}
if (itemcount === 0) {
text += expandDescription("[blackmarket-sellcargo-none]");
itemcount += 1;
}
curChoices["96_SPACER"] = "";
// display the list of options
curChoices["98_EXIT"] = {
text: "[blackmarket-return]",
color: this._itemColor
};
for (var i = 0; i < ((pagesize - 4) - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
def = "98_EXIT";
if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
var opts = {
screenID: "oolite-smuggling-blackmarket-map",
title: "Sell Illegal Cargo",
allowInterrupt: true,
overlay: {
name: image,
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// accept/reject black market sell offer
if (this._display === 9) {
// work out if there is a buyer for this commodity
var itemcount = 1;
var ci = si._commodityInfo[this._sellCommodity];
var main_markup = ci[1];
if (main_markup === 0) main_markup = 1; // default to 1 for commodities we have no data for
var bm_markup = ci[2];
if (bm_markup === 0) bm_markup = 1.1; // default to 75% of main for commodities we have no data for.
if (system.scrambledPseudoRandomNumber(bm_markup) < ((28 - system.info.economy) / 7)) {
// work out how much of this cargo the market is willing to buy
this._offerQuantity = parseInt(this._sellQuantity * ((7 - system.info.economy) + 1) / 8);
// there is still a chance there will be a buyer for all the amount
if (this._offerQuantity < this._sellQuantity && system.scrambledPseudoRandomNumber(this._sellQuantity) > 0.8) {
this._offerQuantity = this._sellQuantity;
}
// better prices if player's smuggling reputation is higher
this._offerPrice = (system.info.samplePrice(this._sellCommodity) * (bm_markup +
((system.scrambledPseudoRandomNumber(main_markup) * (sc.$getSmugglingReputationPrecise() / 7))) -
(0.5 * (1 - sc.$getSmugglingReputationPrecise() / 7))) / 10);
text = expandDescription("[blackmarket-buyer]", {
quantity: this._offerQuantity + " " + se.$getCommodityType(this._sellCommodity),
commodity: displayNameForCommodity(this._sellCommodity),
price: formatCredits(this._offerPrice, false, true),
total: formatCredits(this._offerQuantity * this._offerPrice, false, true)
});
curChoices["80_ACCEPTOFFER"] = {
text: "[blackmarket-accept]",
color: this._menuColor
};
curChoices["81_REJECTOFFER"] = {
text: "[blackmarket-reject]",
color: this._menuColor
};
def = "80_ACCEPTOFFER";
itemcount += 2;
} else {
// no buyer found
text = expandDescription("[blackmarket-nobuyer]", {
commodity: this._sellCommodity
});
def = "98_EXIT";
curChoices["98_EXIT"] = {
text: "[blackmarket-return]",
color: this._itemColor
};
}
if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
for (var i = 0; i < ((pagesize - 6) - itemcount); i++) {
curChoices["99_SPACER_" + i] = "";
}
var opts = {
screenID: "oolite-smuggling-blackmarket-map",
title: "Sell Illegal Cargo",
allowInterrupt: true,
overlay: {
name: image,
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
if (this._display === 10) {
text = expandDescription("[blackmarket-sellotheritems]", {
cash: formatCredits(player.credits, true, true)
});
text += this.$padTextRight("Item", 20) + this.$padTextLeft("Cost", 10);
var list = this._additionalSaleItems;
for (var i = 0; i < list.length; i++) {
curChoices["50_OTHERITEM~" + (i < 10 ? "0" : "") + i] = {
text: this.$padTextRight(list[i].text, 20) +
this.$padTextLeft(formatCredits(list[i].cost * this._systemFactor, true, true), 10),
alignment: "LEFT",
color: this._menuColor
};
}
curChoices["96_SPACER"] = "";
// display the list of options
curChoices["98_EXIT"] = {
text: "[blackmarket-return]",
color: this._itemColor
};
for (var i = 0; i < ((pagesize - 4) - list.length); i++) {
curChoices["99_SPACER_" + i] = "";
}
def = "98_EXIT";
if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
var opts = {
screenID: "oolite-smuggling-blackmarket-map",
title: "Sell Other Items",
allowInterrupt: true,
overlay: {
name: image,
height: 546
},
exitScreen: "GUI_SCREEN_INTERFACES",
choices: curChoices,
initialChoicesKey: def,
message: text
};
}
// rock hermit waypoints purchased
if (this._display === 11) {
var redux = 6;
var maxpages = Math.ceil(this._waypoints.length / (pagesize - redux));
if (maxpages === 0) maxpages = 1;
text = "Rock Hermit waypoints acquired" + (this._waypoints.length > 0 ? " - Page " + (this._curpage + 1) + " of " + maxpages : "") + "\n\n";
if (this._waypoints.length > 0) {
var pagestart = this._curpage * (pagesize - redux);
var pageend = this._curpage * (pagesize - redux) + (pagesize - redux);
if (pageend > this._waypoints.length) pageend = this._waypoints.length;
for (var i = pagestart; i < pageend; i++) {
var info = System.infoForSystem(galaxyNumber, this._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 + "TL" + (info.techlevel + 1) + ", dist: " + dist.toFixed(1) + "ly)\n";
}
} else {
text += " None";
}
if (this._curpage === maxpages - 1 || this._waypoints.length === 0) {
curChoices["10_NEXTPAGE"] = {
text: "[blackmarket-nextpage]",
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["10_NEXTPAGE"] = {
text: "[blackmarket-nextpage]",
color: this._menuColor
};
}
if (this._curpage === 0 || this._waypoints.length === 0) {
curChoices["11_PREVPAGE"] = {
text: "[blackmarket-prevpage]",
color: this._disabledColor,
unselectable: true
};
} else {
curChoices["11_PREVPAGE"] = {
text: "[blackmarket-prevpage]",
color: this._menuColor
};
}
curChoices["98_EXIT"] = {
text: "[blackmarket-return]",
color: this._itemColor
};
def = "98_EXIT";
var opts = {
screenID: "oolite-smuggling-waypoints-map",
title: "Rock Hermit Waypoints",
allowInterrupt: true,
overlay: {
name: "blackmarket-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) {
if (choice == null) {
this.$blackMarketOptions();
return;
}
this._lastChoice[this._display] = choice;
var p = player.ship;
var stn = p.dockedStation;
var se = worldScripts.Smugglers_Equipment;
switch (choice) {
case "01_NOTICEBOARD":
this._display = 2;
this._selectedIndex = 0;
break;
case "02_CONTRACTS":
var sc = worldScripts.Smugglers_Contracts;
sc.$smugglingContractsScreens();
break;
case "03_PURCHASE":
this._display = 3;
break;
case "04_SELL_ILLEGAL":
this._display = 8;
break;
case "04_FAKEPERMITS":
this._display = 4;
break;
case "05_WAYPOINTS":
this._display = 5;
break;
case "06_PHASESCAN":
this._display = 6;
break;
case "07_SELLSCAN":
this._display = 7;
break;
case "97_EXIT":
this._display = 3;
break;
case "08_SELLADDITIONAL":
this._display = 10;
break;
case "01A_CURRENT_WAYPOINTS":
this._display = 11;
break;
case "10_NEXTPAGE":
this._curpage += 1;
break;
case "11_PREVPAGE":
this._curpage -= 1;
break;
case "20_NEXTITEM":
this._selectedIndex += 1;
break;
case "21_PREVITEM":
this._selectedIndex -= 1;
break;
case "30_LASTITEM":
this._selectedIndex = this._noticeboard.length - 1;
break;
case "31_FIRSTITEM":
this._selectedIndex = 0;
break;
case "80_ACCEPTOFFER":
if (this._sting && p.dockedStation === this._stingStation) {
this.$stingOperation();
return;
}
// pay the player
player.credits += this._offerQuantity * this._offerPrice;
// remove the cargo, but because this is a black market sale, it doesn't appear on the stations market. just remove it.
switch (this._sellType) {
case 1: // standard hold
p.manifest[this._sellCommodity] -= this._offerQuantity;
break;
case 2: // smuggling compartment
if (se) se.$removeCargo(this._offerCommodity, this._offerQuantity);
break;
}
this._blackMarketSales.push(this._sellCommodity);
se.$playSound("sell");
player.consoleMessage("You have been credited " + formatCredits(this._offerQuantity * this._offerPrice, true, true) + ".");
this._sellCommodity = "";
this._sellQuantity = 0;
this._sellType = 0;
this._offerQuantity = 0;
this._offerPrice = 0;
this._display = 8;
break;
case "81_REJECTOFFER":
this._sellCommodity = "";
this._sellQuantity = 0;
this._sellType = 0;
this._offerQuantity = 0;
this._offerPrice = 0;
this._display = 8;
break;
case "98_EXIT":
this._display = 0;
break;
}
if (choice.indexOf("60_") >= 0) {
if (this._sting && p.dockedStation === this._stingStation) {
this.$stingOperation();
return;
}
if (player.credits >= (this._fakePermitCost * stn.equipmentPriceFactor)) {
var data = choice.substring(choice.indexOf("~") + 1);
var subdata = data.split("|");
var sysID = parseInt(subdata[0]);
var si = worldScripts.Smugglers_Illegal;
si._permits.push({
systemID: sysID,
commodity: subdata[1],
fake: this._fakePermits[system.ID]
});
player.credits -= this._fakePermitCost * stn.equipmentPriceFactor;
this.$sendPurchasingEmail("Fake import permit for " + si.$translateCommodityList(subdata[1]) + " to " + System.infoForSystem(galaxyNumber, sysID).name,
this._fakePermitCost * stn.equipmentPriceFactor);
} else {
player.consoleMessage("Insufficient funds to purchase item.");
}
}
if (choice.indexOf("61_") >= 0) {
if (player.credits >= (this._waypointCost * stn.equipmentPriceFactor)) {
var sysID = parseInt(choice.substring(choice.indexOf("~") + 1));
this._waypoints.push(sysID);
player.credits -= this._waypointCost * stn.equipmentPriceFactor;
this.$sendPurchasingEmail("Rock Hermit waypoint for " + System.infoForSystem(galaxyNumber, sysID).name,
this._waypointCost * stn.equipmentPriceFactor);
} else {
player.consoleMessage("Insufficient funds to purchase item.");
}
}
if (choice.indexOf("62_") >= 0) {
if (this._sting && p.dockedStation === this._stingStation) {
this.$stingOperation();
return;
}
if (player.credits >= this._phaseScanCost * stn.equipmentPriceFactor) {
var sysID = parseInt(choice.substring(choice.indexOf("~") + 1));
var phase = se.$getSystemPhase(sysID);
se.$addPhaseScan(phase, sysID, 2);
player.credits -= this._phaseScanCost * stn.equipmentPriceFactor;
this.$sendPurchasingEmail("Phase scan setting for " + System.infoForSystem(galaxyNumber, sysID).name,
this._phaseScanCost * stn.equipmentPriceFactor);
} else {
player.consoleMessage("Insufficient funds to purchase item.");
}
}
if (choice.indexOf("63_") >= 0) {
if (this._sting && p.dockedStation === this._stingStation) {
this.$stingOperation();
return;
}
var idx = parseInt(choice.substring(choice.indexOf("~") + 1));
var list = se.$getSellablePhaseScans();
se.$sellPhaseScan(list[idx].gov, list[idx].tl);
player.credits += (this._phaseScanCost * stn.equipmentPriceFactor) * 0.8;
this.$sendSaleEmail("Phase scan setting for " + this.$governmentDescription(list[idx].gov) + " systems of tech level " + (list[idx].tl + 1), (this._phaseScanCost * stn.equipmentPriceFactor) * 0.8);
}
if (choice.indexOf("74_SELL") >= 0) { // sell cargo from smuggling compartment
this._sellCommodity = choice.substring(choice.indexOf("~") + 1);
this._sellQuantity = se.$getCargoQuantity(this._sellCommodity);
this._sellType = 2; // smuggling compartment
this._display = 9;
}
if (choice.indexOf("73_SELL") >= 0) { // sell cargo from standard hold
var sdm = worldScripts.Smugglers_DockMaster;
this._sellCommodity = choice.substring(choice.indexOf("~") + 1);
this._sellQuantity = p.manifest[this._sellCommodity];
// remove any relabelled cargo
if (sdm && sdm.$getTotalRelabelled(this._sellCommodity) > 0) this._sellQuantity = this._sellQuantity - sdm.$getTotalRelabelled(viscargo[i].commodity);
this._sellType = 1; // standard hold
this._display = 9;
}
if (choice.indexOf("50_OTHERITEM") >= 0) {
// todo: make it possible for the player to not find a buyer
var idx = parseInt(choice.substring(choice.indexOf("~") + 1));
// tell the calling script the item was sold, passing back the item key and the sell price
worldScripts[this._additionalSaleItems[idx].worldScript][this._additionalSaleItems[idx].sellCallback](this._additionalSaleItems[idx].key, parseInt((this._additionalSaleItems[idx].cost * this._systemFactor) * 10) / 10);
// remove the item from the list
player.credits += parseInt((this._additionalSaleItems[idx].cost * this._systemFactor) * 10) / 10;
this._additionalSaleItems.splice(idx, 1);
}
if (choice != "99_EXIT" && choice != "02_CONTRACTS") {
this.$blackMarketOptions();
}
}
//-------------------------------------------------------------------------------------------------------------
// sends an email confirming black market purchase
this.$sendPurchasingEmail = function $sendPurchasingEmail(itemText, cost) {
var email = worldScripts.EmailSystem;
if (email) {
var ga = worldScripts.GalCopAdminServices;
if (this._blackMarketSalesPerson === "") {
this._blackMarketSalesPerson = expandDescription("%N [nom]");
}
email.$createEmail({
sender: "Black Market",
subject: "Purchasing",
date: clock.seconds,
message: expandDescription("[blackmarket-purchasing]", {
item: itemText,
itemcost: cost.toFixed(2),
sender: this._blackMarketSalesPerson
}),
expiryDays: ga._defaultExpiryDays
});
}
}
//-------------------------------------------------------------------------------------------------------------
// sends an email confirming black market sale
this.$sendSaleEmail = function $sendSaleEmail(itemText, cost) {
var email = worldScripts.EmailSystem;
if (email) {
var ga = worldScripts.GalCopAdminServices;
if (this._blackMarketSalesPerson === "") {
this._blackMarketSalesPerson = expandDescription("%N [nom]");
}
email.$createEmail({
sender: "Black Market",
subject: "Sale",
date: clock.seconds,
message: expandDescription("[blackmarket-sale]", {
item: itemText,
itemcost: cost.toFixed(2),
sender: this._blackMarketSalesPerson
}),
expiryDays: ga._defaultExpiryDays
});
}
}
//-------------------------------------------------------------------------------------------------------------
this.$buildNoticeboard = function $buildNoticeboard() {
function compare(a, b) {
if (a.idx < b.idx) return -1;
if (a.idx > b.idx) return 1;
return 0;
}
this._noticeboard = [];
// type 1: dock master bribe mesages
// type 2: suggested phase settings
// type 3: where to get good fake permits
// type 4: random chatter
// type 5: cargo stash (or not, maybe)
var sdm = worldScripts.Smugglers_DockMaster;
var si = worldScripts.Smugglers_Illegal;
var se = worldScripts.Smugglers_Equipment;
var finalcount = 0;
// type 1: bribe messages
// get all systems within 15ly
if (this._smugglers) {
var sys = system.info.systemsInRange(15);
var list = [];
// look for any with a low bribe chance (< 500cr)
for (var i = 0; i < sys.length; i++) {
if (sys[i].hasOwnProperty("sun_gone_nova") === false || sys[i].sun_gone_nova === false) {
var chance = sdm._bribeChance[sys[i].systemID];
if (chance <= 0.22) {
// decide whether or not to show it (max 2)
if (list.length < 2 && Math.random() > 0.6) {
var amount = parseInt(parseInt(((chance + 0.1) * 32) ^ 2) * 100) / 100;
list.push({
system: sys[i].name,
amount: amount
});
}
}
}
}
for (var i = 0; i < list.length; i++) {
var msg = expandDescription("[noticeboard-dmbribe]", {
planet: list[i].system,
amount: list[i].amount
});
this._noticeboard.push({
idx: this.$rand(100),
message: msg
});
}
// type 3: fake permits
finalcount = 0 + (Math.random() > 0.5 ? 1 : 0);
for (var i = 0; i < sys.length; i++) {
if (this._fakePermits[sys[i].systemID] >= 0.8) {
if (Math.random() > 0.7) {
var msg = expandDescription("[noticeboard-fakepermit]", {
planet: sys[i].name
});
this._noticeboard.push({
idx: this.$rand(100),
message: msg
});
finalcount += 1;
}
// break out if we hit the limit
if (finalcount >= 2) break;
}
}
// type 2: phase settings
// will never be super accurate, but will be better than nothing.
// get all systems with 25ly with illegal goods
sys = system.info.systemsInRange(25);
list = [];
var count = 0;
for (var i = sys.length - 1; i >= 0; i--) {
var goods = si.$illegalGoodsList(sys[i].systemID);
var suggest_phase = se.$getSystemPhase(sys[i].systemID) + (this.$rand(50) * (Math.random() > 0.5 ? 1 : -1));
// make sure we have a positive number
if (suggest_phase < 0) suggest_phase = se.$getSystemPhase(sys[i].systemID) + (this.$rand(20) + 20);
// make sure we don't go over the limit
if (suggest_phase >= 1000) suggest_phase = se.$getSystemPhase(sys[i].systemID) + ((this.$rand(20) + 20) * -1);
if (goods.length >= 0) {
list.push({
system: sys[i].name,
phase: suggest_phase,
hasIllegal: true
});
count += 1;
} else {
list.push({
system: sys[i].name,
phase: suggest_phase,
hasIllegal: false
});
}
}
// pick 1 or (at most) 2
finalcount = 0 + (Math.random() > 0.5 ? 1 : 0);
if (count > 0) {
// pick the ones with illegal goods
for (var i = 0; i < list.length; i++) {
if (list[i].hasIllegal === true && Math.random() > 0.7) {
var msg = expandDescription("[noticeboard-phasescan]", {
planet: list[i].system,
phase: list[i].phase
});
this._noticeboard.push({
idx: this.$rand(100),
message: msg
});
finalcount += 1;
}
// break out if we hit the limit
if (finalcount >= 2) break;
}
} else {
// pick the ones with illegal goods
for (var i = 0; i < list.length; i++) {
if (Math.random() > 0.7) {
var msg = expandDescription("[noticeboard-phasescan]", {
planet: list[i].system,
phase: list[i].phase
});
this._noticeboard.push({
idx: this.$rand(100),
message: msg
});
finalcount += 1;
}
// break out if we hit the limit
if (finalcount >= 2) break;
}
}
// type 5: phase updates
finalcount = 0;
if (se._phaseUpdates.length > 0) {
// get a list of planets in 25 LY that have had a setting change.
for (var i = 0; i < sys.length; i++) {
for (var j = 0; j < se._phaseUpdates.length; j++) {
if (sys[i].government === se._phaseUpdates[j].gov && sys[i].techlevel === se._phaseUpdates[j].tl) {
finalcount += 1;
var msg = expandDescription("[noticeboard-phaseupdate]", {
planetname: sys[i].name
});
this._noticeboard.push({
idx: this.$rand(100),
message: msg
});
}
}
}
}
}
// type 4: random chatter
finalcount = 0;
var randomchatter = this.$rand(3);
var checking = [];
missionVariables.randomphone = (this.$rand(899999) + 100000) + "-" + (this.$rand(899) + 100) + "-" + (this.$rand(89999) + 10000);
for (var i = 1; i <= randomchatter; i++) {
var msg = expandDescription("[noticeboard-randomchatter]");
if (checking.indexOf(msg) === -1) {
this._noticeboard.push({
idx: this.$rand(100),
message: msg
});
checking.push(msg);
}
}
delete missionVariables.randomphone;
// type 5: cargo stash
var stash = this.$rand(3) - 1; // between 0 and 2
var sys = system.info.systemsInRange(10);
for (var i = 0; i < stash; i++) {
var s = sys[Math.floor(Math.random() * sys.length)];
// make sure we don't add two stashes in the same system
var found = false;
for (var i = 0; i < this._stash.length; i++) {
if (this._stash[i].systemID == s.systemID) found = true;
}
if (found == true) continue;
this._stash.push({systemID:s.systemID, created:clock.adjustedSeconds});
missionVariables.stashdist = parseInt(system.info.distanceToSystem(s) * 10) / 10;
var msg = expandDescription("[noticeboard-cargo-stash]");
this._noticeboard.push({
idx: this.$rand(100),
message: msg
});
delete missionVariables.stashdist;
}
// sort the list, based on the random index, so the items are mixed up.
this._noticeboard.sort(compare);
}
//-------------------------------------------------------------------------------------------------------------
// builds the fake permit array
this.$buildFakePermitArray = function $buildFakePermitArray() {
this._fakePermits = [];
for (var i = 0; i <= 255; i++) {
// fake permits can have, at best, a 40% chance of success
var chance = (Math.random() * 40) / 100;
if (chance > 0.5) {
this._fakePermits.push(chance);
} else {
this._fakePermits.push(0);
}
}
}
//-------------------------------------------------------------------------------------------------------------
// adds a waypoint to the first rock hermit if the player has purchased a waypoint for this system
this.$addRHWaypoint = function $addRHWaypoint() {
// add a waypoint to the rock hermit, if the player has one
if (this._waypoints.indexOf(system.ID) >= 0) {
if (this._debug) log(this.name, "A Rock Hermit waypoint has been found for the current system");
var stns = system.stations;
for (var i = 0; i < stns.length; i++) {
// is this a rockhermit?
//log(this.name, "station " + stns[i].name);
if (Ship.roleIsInCategory(stns[i].primaryRole, "oolite-rockhermits") && stns[i].hasRole("slaver_base") === false && stns[i].hasRole("rrs_slaverbase") === false) {
if (this._debug) log(this.name, "A Rock Hermit has been found in the current system -- adding waypoint");
// is the waypoint already set?
if (!system.waypoints[this.name]) {
system.setWaypoint(
this.name, stns[i].position, stns[i].orientation, {
size: 100,
beaconCode: "H",
beaconLabel: "Rock Hermit"
}
);
break;
}
}
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.$doesStationHaveBlackMarket = function $doesStationHaveBlackMarket(station) {
if (this.$isBlackMarketShutdown(station) === true) return false;
var alleg = station.allegiance;
if (alleg == null) alleg = "neutral";
if (((this._smugglingAllegiance.indexOf(alleg) >= 0 || this.$isStationIncluded(station) === true) && this.$isStationExcluded(station) === false) ||
(station.isMainStation && this.$mainStationHasBlackMarket() === true)) return true;
return false;
}
//-------------------------------------------------------------------------------------------------------------
// determines whether the black market will be visible in certain systems at the main station
this.$mainStationHasBlackMarket = function $mainStationHasBlackMarket() {
// for tl 4 and below, at Anarchies, Feudals, Multi-Gov, Communists, Dictatorships, there's a 70% chance
if (system.info.techlevel <= 3 && system.government <= 4 && system.pseudoRandomNumber > 0.3) return true;
// for tl 5/6, at Anarchies, Feudals, Multi-Gov, there's a 50% chance
if (system.info.techlevel >= 4 && system.info.techlevel <= 6 && system.government <= 2 && system.pseudoRandomNumber > 0.5) return true;
// for tl 7+, at Anarchies only, have a reducing chance
if (system.info.techlevel > 6 && system.government === 0 && system.pseudoRandomNumber > (system.info.techlevel / 10)) return true
// otherwise false
return false;
}
//-------------------------------------------------------------------------------------------------------------
this.$governmentDescription = function $governmentDescription(gov) {
switch (gov) {
case 0: return "Anarchy";
case 1: return "Feudal";
case 2: return "Multi-Government";
case 3: return "Dictatorship";
case 4: return "Communist";
case 5: return "Confederacy";
case 6: return "Democracy";
case 7: return "Corporate State";
}
}
//-------------------------------------------------------------------------------------------------------------
this.$setupSting = function $setupSting(station) {
this._stingStation = station;
this._sting = true;
// there's a chance that there'll be a police ship at the edge of scanner range at station where sting operation is in progress
// if the player has never been to the black market, though, we need a clue other than the name of the agent. So we must include the ship in that case
if (Math.random() > this._stingShipChance || this.$playerHasBeenToBlackMarket(station) === false) {
this.$addStingShip(station);
}
if (this._debug) {
//log(this.name, "Sting Operation In Progress at " + this._stingStation.displayName);
//if (this._stingShip) log(this.name, "Added police ship clue");
// flag the station so we can easily find it for testing
if (!this._stingStation.beaconCode || this._stingStation.beaconCode === "") {
this._stingStation.beaconCode = "S";
this._stingStation.beaconLabel = "Sting operation in progress";
}
}
}
//-------------------------------------------------------------------------------------------------------------
// adds the sting ship to the station
this.$addStingShip = function $addStingShip(station) {
if (!station || station.isValid === false) return;
// reduce the chance we'll get another sting ship each time we get one.
if (this._stingShipChance < 0.9) this._stingShipChance += 0.1;
// work out the position of the rh dock
var dock = null;
var dockpos = null;
// find the dock object of the station so we can position launched ships
for (var i = 0; i < station.subEntities.length; i++) {
if (station.subEntities[i].isDock) {
dock = station.subEntities[i];
dockpos = station.position.add( //better formula for non-centered docks
Vector3D(
station.heading.direction().multiply(dock.position.z),
station.vectorUp.direction().multiply(dock.position.y),
station.vectorRight.direction().multiply(dock.position.x)
)
);
break;
}
}
// move away from dock in straight line, but backwards, towards the edge of scanner range...
var pos = dockpos.add(station.vectorForward.multiply(-(player.ship.scannerRange * 0.92)));
// add a police ship at that position, but switch it to null AI so it will just sit there
this._stingShip = system.addShips("police", 1, pos, 1000)[0];
if (this._stingShip) {
this._stingShip.switchAI("nullAI.plist");
// set up the ship so if it's attacked it doesn't just sit there.
// monkeypatch if necessary
if (this._stingShip.script.shipBeingAttacked) this._stingShip.script.$sbm_ovr_shipBeingAttacked = this._stingShip.script.shipBeingAttacked;
this._stingShip.script.shipBeingAttacked = this.$policeSting_shipBeingAttacked;
if (this._stingShip.script.shipBeingAttackedByCloaked) this._stingShip.script.$sbm_ovr_shipBeingAttackedByCloaked = this._stingShip.script.shipBeingAttackedByCloaked;
this._stingShip.script.shipBeingAttackedByCloaked = this.$policeSting_shipBeingAttackedByCloaked;
this._stingShipTimer = new Timer(this, this.$checkForPlayerProximity, 5, 5);
}
}
//-------------------------------------------------------------------------------------------------------------
this.$policeSting_shipBeingAttacked = function $policeSting_shipBeingAttacked(whom) {
// run monkey patch, if required
if (this.ship.script.$sbm_ovr_shipBeingAttacked) this.ship.script.$sbm_ovr_shipBeingAttacked(whom);
// under attack, so revert to police AI
var sbm = worldScripts.Smugglers_BlackMarket;
sbm._stingShipTimer.stop();
this.ship.switchAI("oolite-policeAI.js");
this.ship.target = whom;
// if the attacker is anyone but the player, then the sting is a bust
if (whom.isPlayer === false) {
sbm._stingStation = null;
sbm._sting = false;
}
sbm._stingShip = null;
sbm.$policeSting_removeMonkeyPatches(this.ship);
}
//-------------------------------------------------------------------------------------------------------------
this.$policeSting_shipBeingAttackedByCloaked = function $policeSting_shipBeingAttackedByCloaked() {
// run monkey patch, if required
if (this.ship.script.$sbm_ovr_shipBeingAttackedByCloaked) this.ship.script.$sbm_ovr_shipBeingAttackedByCloaked();
// under attack, so revert to police AI
var sbm = worldScripts.Smugglers_BlackMarket;
sbm._stingShipTimer.stop();
this.ship.switchAI("oolite-policeAI.js");
sbm._stingStation = null;
sbm._sting = false;
sbm._stingShip = null;
sbm.$policeSting_removeMonkeyPatches(this.ship);
}
//-------------------------------------------------------------------------------------------------------------
this.$policeSting_removeMonkeyPatches = function $policeSting_removeMonkeyPatches(ship) {
// remove monkey patches
if (!ship) return;
delete ship.script.shipBeingAttacked;
if (ship.script.$sbm_ovr_shipBeingAttacked) {
ship.script.shipBeingAttacked = ship.script.$sbm_ovr_shipBeingAttacked;
delete ship.script.$sbm_ovr_shipBeingAttacked;
}
delete ship.script.shipBeingAttackedByCloaked;
if (ship.script.$sbm_ovr_shipBeingAttackedByCloaked) {
ship.script.shipBeingAttackedByCloaked = ship.script.$sbm_ovr_shipBeingAttackedByCloaked;
delete ship.script.$sbm_ovr_shipBeingAttackedByCloaked;
}
}
//-------------------------------------------------------------------------------------------------------------
// timer deatination to check if the player has moved within 10km of sting ship
this.$checkForPlayerProximity = function $checkForPlayerProximity() {
if (this._stingShip == null || this._stingShip.isValid === false || this._stingShip.isInSpace === false) {
this._stingShipTimer.stop();
return;
}
// if the player comes in range, switch back to police mode
if (player.ship && player.ship.isValid && player.ship.isInSpace && this._stingShip.position.distanceTo(player.ship) < 10000) {
this._stingShipTimer.stop();
delete this._stingShip.script.shipBeingAttacked;
this._stingShip.switchAI("oolite-policeAI.js");
this._stingShip = null;
}
}
//-------------------------------------------------------------------------------------------------------------
this.$playerHasBeenToBlackMarket = function $playerHasBeenToBlackMarket(station) {
for (var i = 0; i < this._blackMarketContacts.length; i++) {
var contact = this._blackMarketContacts[i];
if (contact.galaxy === galaxyNumber && contact.systemID === system.ID && contact.stationName === station.displayName) return true;
}
return false;
}
//-------------------------------------------------------------------------------------------------------------
this.$getBlackMarketContact = function $getBlackMarketContact(station) {
// check if a sting is in progress at this station
if (this._sting && station === this._stingStation) return expandDescription("%N [nom]");
// see if we already have a contact for this station
var contactName = "";
for (var i = 0; i < this._blackMarketContacts.length; i++) {
var contact = this._blackMarketContacts[i];
if (contact.galaxy === galaxyNumber && contact.systemID === system.ID && contact.stationName === station.displayName) {
contactName = contact.name;
break;
}
}
if (contactName === "") {
contactName = expandDescription("%N [nom]");
this._blackMarketContacts.push({
galaxy: galaxyNumber,
systemID: system.ID,
stationName: station.displayName,
name: contactName
});
}
return contactName;
}
//-------------------------------------------------------------------------------------------------------------
this.$stingOperation = function $stingOperation() {
var p = player.ship;
this._newBounty = player.bounty + (parseInt(Math.random() * 10) + 20);
this._blackMarketShutdown.push({
galaxy: galaxyNumber,
system: system.ID,
stationName: p.dockedStation.displayName,
date: clock.seconds
});
p.dockedStation.setInterface(this.name, null);
this._noBribe = false;
this.$runStingScreen();
this._caughtDate = clock.seconds;
}
//-------------------------------------------------------------------------------------------------------------
this.$runStingScreen = function $runStingScreen() {
if (player.credits > 2000) {
var pct = 0.1;
for (var i = 0; i < 4; i++) {
if (player.credits * pct < 100000) pct += 0.1;
}
this._newPenalty = Math.floor(player.credits * pct);
if (this._newPenalty > 100000) this._newPenalty = 100000;
var curChoices = {};
if (player.credits > 0) {
if (this._noBribe === false) {
curChoices["03_BRIBE"] = {
text: "[blackmarket-attempt-bribe]",
color: this._menuColor
};
}
curChoices["01_CREDIT_ACCEPT"] = {
text: "[blackmarket-credits-accept-penalty]",
color: this._menuColor
};
}
curChoices["02_LEGAL_ACCEPT"] = {
text: "[blackmarket-legal-accept-penalty]",
color: this._menuColor
};
mission.runScreen({
screenID: "blackmarket-sting",
title: "GalCop Security",
model: "[viper]",
message: expandDescription("[blackmarket-sting]", {
penalty: formatCredits(this._newPenalty, false, true)
}),
exitScreen: "GUI_SCREEN_STATUS",
allowInterrupt: false,
choices: curChoices,
initialChoicesKey: "01_CREDIT_ACCEPT"
}, this.$stingScreenHandler, this);
} else {
mission.runScreen({
screenID: "blackmarket-sting",
title: "GalCop Security",
model: "[viper]",
message: expandDescription("[blackmarket-sting-no-credits]"),
exitScreen: "GUI_SCREEN_INTERFACES",
}, this.$stingScreenHandler, this);
player.ship.setBounty(this._newBounty, "underworld activity");
this.$sendStingNotificationEmail("legal");
this._newBounty = 0;
}
}
//-------------------------------------------------------------------------------------------------------------
this.$stingScreenHandler = function $stingScreenHandler(choice) {
if (choice === "03_BRIBE") {
this.$getBribeAmount();
return;
}
if (choice === "01_CREDIT_ACCEPT") {
player.credits -= this._newPenalty;
this.$sendStingNotificationEmail("credits");
this._newPenalty = 0;
return;
}
if (choice === "02_LEGAL_ACCEPT") {
player.ship.setBounty(this._newBounty, "underworld activity");
this.$sendStingNotificationEmail("legal");
this._newBounty = 0;
return;
}
if (choice === "01_RETURN") {
this.$runStingScreen();
}
}
//-------------------------------------------------------------------------------------------------------------
this.$isBlackMarketShutdown = function $isBlackMarketShutdown(station) {
for (var i = 0; i < this._blackMarketShutdown.length; i++) {
var item = this._blackMarketShutdown[i];
// 2592000 = 30 days in seconds
if (item.galaxy === galaxyNumber && item.systemID === system.ID && item.stationName === station.displayName && (clock.seconds - item.date) < 2592000) return true;
}
return false;
}
//-------------------------------------------------------------------------------------------------------------
this.$setupStingAfterLoad = function $setupStingAfterLoad() {
// configure the sting op from saved data
var stnName = missionVariables.Smuggling_BlackMarketStingStation;
var stns = system.stations;
var found = false;
for (var i = 0; i < stns.length; i++) {
if (stns[i].displayName === stnName) {
this._stingStation = stns[i];
found = true;
break;
}
}
if (found) {
if (missionVariables.BlackMarketStingShip) this.$addStingShip(this._stingStation);
} else {
// couldn't find the same station, so turn off the sting
this._sting = false;
}
delete missionVariables.Smuggling_BlackMarketSting;
delete missionVariables.Smuggling_BlackMarketStingStation;
delete missionVariables.Smuggling_BlackMarketStingShip;
}
//-------------------------------------------------------------------------------------------------------------
// calculates a number between 0.2 and 1.7 (approx)
this.$setupSystemFactor = function $setupSystemFactor() {
// low tech, anarchic, low economy worlds will pay a premium, hitech worlds not so much
var eco = system.economy; // 0 to 7 (7 = poor ag)
var tl = 15 - system.techLevel; // 0 to 14; we're inverting this so that low tech worlds are rated higher
var gov = (8 - system.government) * 2; // 0 - 7 (0 = anarchic) we're inverting this so that anarchic worlds are rated higher. we're also giving more weight to this number
// convert this numbers into a factor with a random element as well
var factor = ((eco + tl + gov) / 21) * (system.scrambledPseudoRandomNumber(clock.days) * 0.4) + 0.5;;
if (factor < 0.2) factor = 0.2
this._systemFactor = factor;
}
//-------------------------------------------------------------------------------------------------------------
this.$sellItemCallback = function $sellItemCallback(key) {
if (player.ship.equipmentStatus(key) === "EQUIPMENT_OK") player.ship.removeEquipment(key);
}
//-------------------------------------------------------------------------------------------------------------
this.$addCoreEquipmentToBlackMarket = function $addCoreEquipmentToBlackMarket() {
// make sure the list is clear for this worldscript
this.$removeWorldScriptItems("Smugglers_BlackMarket");
// add some rare equipment to the sale item list, if they're still functioning anyway - can't sell damaged equipment!
if (player.ship.equipmentStatus("EQ_CLOAKING_DEVICE") === "EQUIPMENT_OK") {
var item = EquipmentInfo.infoForKey("EQ_CLOAKING_DEVICE");
this.$addSaleItem({
key: "EQ_CLOAKING_DEVICE",
text: item.name,
cost: parseInt(item.price / 10),
worldScript: "Smugglers_BlackMarket",
sellCallback: "$sellItemCallback"
});
}
var eq = player.ship.equipment;
for (var i = 0; i < eq.length; i++) {
if (eq[i].equipmentKey.indexOf("NAVAL") >= 0 || eq[i].equipmentKey.indexOf("MILITARY") >= 0) {
var item = EquipmentInfo.infoForKey(eq[i].equipmentKey);
this.$addSaleItem({
key: eq[i].equipmentKey,
text: item.name,
cost: parseInt(item.price / 10),
worldScript: "Smugglers_BlackMarket",
sellCallback: "$sellItemCallback"
});
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.$getBribeAmount = function $getBribeAmount() {
var text = "";
var inttype = Math.floor((this._bribeChance * 4) + 1);
var inttypedesc = expandDescription("[bribe-interest-type" + inttype + "]");
text = expandDescription("[bribe-question]", {
interesttype: inttypedesc
}) + "\n\n" +
"(" + expandDescription("[bribe-cost]", {
credits: formatCredits(player.credits, false, true)
}) + ")";
var opts = {
screenID: "smuggling_sting_bribe",
title: "Bribing Official",
allowInterrupt: false,
model: "[viper]",
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 p = player.ship;
if (parseInt(param) >= 1 && parseInt(param) <= player.credits) {
var amount = parseInt(param);
// will this work
var chance = this._bribeChance;
// higher amounts are more likely to be accepted
if (this._debug) log(this.name, "min bribe amount = " + (Math.pow(parseInt(chance * 50), 2.5) * (1 + system.productivity / 56300)));
if ((Math.pow(parseInt(chance * 50), 2.5) * (1 + system.productivity / 56300)) <= amount) {
player.credits -= amount;
mission.runScreen({
screenID: "sting_bribe",
title: "Bribing Official",
model: "[viper]",
message: expandDescription("[bribe-complete]"),
exitScreen: "GUI_SCREEN_STATUS"
});
} else {
// a failed bribe will result in the legal penalty being applied
p.setBounty(this._newBounty, "underworld activity");
this.$sendStingNotificationEmail("legal");
this._newBounty = 0;
if (Math.random() > chance) {
mission.runScreen({
screenID: "sting_bribe",
title: "Bribing Official",
model: "[viper]",
message: expandDescription("[bribe-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: "sting_bribe",
title: "Bribing Official",
model: "[viper]",
message: expandDescription("[bribe-angry-penalty]"),
exitScreen: "GUI_SCREEN_STATUS"
});
// 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("[failed-bribe-email]", {
legal_penalty: penalty,
stationname: player.ship.dockedStation.displayName,
systemname: System.systemNameForID(system.ID)
}),
expiryDays: ga._defaultExpiryDays
});
}
}
}
} else {
this._noBribe = true;
mission.runScreen({
screenID: "smuggling_bribe",
title: "Bribing Official",
model: "[viper]",
message: expandDescription("[blackmarket-sting-skipbribe]"),
exitScreen: "GUI_SCREEN_STATUS",
choices: {
"01_RETURN": {
text: "Press Enter to Continue"
}
},
}, this.$stingScreenHandler, this);
}
}
//-------------------------------------------------------------------------------------------------------------
this.$sendStingNotificationEmail = function $sendStingNotificationEmail(type) {
// send email (if installed)
var email = worldScripts.EmailSystem;
if (email) {
var ga = worldScripts.GalCopAdminServices;
email.$createEmail({
sender: "GalCop Customs",
subject: "Illegal Activities",
date: clock.seconds,
message: expandDescription("[blackmarket-sting-email-" + type + "]", {
legal_penalty: this.newBounty,
credit_penalty: formatCredits(this._newPenalty, false, true),
date: clock.clockStringForTime(this._caughtDate),
stationname: player.ship.dockedStation.displayName,
systemname: System.systemNameForID(system.ID)
}),
expiryDays: ga._defaultExpiryDays
});
}
}
//-------------------------------------------------------------------------------------------------------------
this.$setupCargoStash = function() {
var z = -0.4;
if (system.shipsWithRole("constore").length > 0) z = -0.5;
var pos = Vector3D(0, 0, z).fromCoordinateSystem("wpu");
// add the cargo
var count = this.$rand(5) + 3;
var cargo = system.addShips("[barrel]", count, pos, 500);
this._cargoStashCount = cargo.length;
var cmdties = ["gold", "platinum", "gem_stones"];
for (var i = 0; i < cargo.length; i++) {
cargo[i].setCargo(cmdties[this.$rand(3) - 1], this.$rand(10) + 5);
cargo[i].script.shipDied = this.$cargoDied;
}
var type = this.$rand(3);
if (type == 1 && this.$rand(2) == 1) type = 2; // slightly less of a chance of a pure cargo drop
switch (type) {
case 1: // just cargo
break;
case 2: // proximity mines p.position.add(p.vectorForward.multiply(10000))
system.addShips("bm_proximity_mine", 15, pos, 3000);
break;
case 3: // proximity qbomb
var qbomb = system.addShips("bm_proximity_mine", 1, pos, 1);
qbomb[0]["is_cascade_weapon"] = true;
break;
case 4: // pirate trap
this.$createPirateTrap(this.$rand(3) + 2, pos, 10000);
break;
}
// things to possibly add
// asteroids
if (Math.random() > 0.3) {
system.addShips("asteroid", this.$rand(30) + 20, pos, 30600);
}
// derelict ship with some alloys (but not if there's proximity mines)
if (Math.random() > 0.8 && type != 2 && type != 3) {
this.$addDerelictShip(pos);
}
this._stashLocation = pos;
this._stashTimer = new Timer(this, this.$checkPlayerLocationToStash, 3, 3);
}
//-------------------------------------------------------------------------------------------------------------
this.$cargoDied = function(whom, why) {
var sbm = worldScripts.Smugglers_BlackMarket;
sbm._cargoStashCount - 1;
if (sbm._cargoStashCount <= 0) {
sbm.$removeStashSystem();
}
}
//-------------------------------------------------------------------------------------------------------------
this.$checkPlayerLocationToStash = function $checkPlayerLocationToStash() {
var p = player.ship;
if (!p || !p.isValid) {
this._stashTimer.stop();
return;
}
if (p.position.distanceTo(this._stashLocation) < 26500) {
this._stashTimer.stop();
this.$removeStashSystem();
}
}
//-------------------------------------------------------------------------------------------------------------
this.$removeStashSystem = function() {
for (var i = this._stash.length - 1; i >= 0; i--) {
if (this._stash[i].systemID == system.ID) {
this._stash.splice(i, 1);
break;
}
}
}
//-------------------------------------------------------------------------------------------------------------
this.$addDerelictShip = function(pos) {
// add derelict ship
// derelict ship creation code from Eric Walsh's DeepSpaceDredger OXP
var derelict = null;
var checkShips = system.addShips("trader", 1, pos, 5000);
if (checkShips) derelict = checkShips[0];
if (derelict) {
derelict.bounty = 0;
// set script to default, to avoid a special script for the trader doing stuff. (like setting a new AI)
derelict.setScript("oolite-default-ship-script.js");
derelict.switchAI("oolite-nullAI.js");
// remove any escorts that came with the ship
if (derelict.escorts) {
for (var j = derelict.escorts.length - 1; j >= 0; j--) derelict.escorts[j].remove(true);
}
derelict.script.shipLaunchedEscapePod = this.$bm_derelict_shipLaunchedEscapePod; // function to remove the escapepod after launch.
if (derelict.equipmentStatus("EQ_ESCAPE_POD") === "EQUIPMENT_UNAVAILABLE") derelict.awardEquipment("EQ_ESCAPE_POD");
derelict.abandonShip(); // make sure no pilot is left behind and this command turns the ship into cargo.
derelict.primaryRole = "bm_derelict"; // to avoid pirate attacks
derelict.displayName = derelict.displayName + " (derelict)";
derelict.lightsActive = false;
// add some alloys as well
system.addShips("alloys", 5, derelict.position, 1000);
}
}
//-------------------------------------------------------------------------------------------------------------
this.$bm_derelict_shipLaunchedEscapePod = function $bm_derelict_shipLaunchedEscapePod(pod, passengers) {
pod.remove(true); // we don't want floating escapepods around but need them initially to create the derelict.
}
//-------------------------------------------------------------------------------------------------------------
this.$createPirateTrap = function $createPirateTrap(count, pos, spread) {
var pop = worldScripts["oolite-populator"];
var grp = system.addGroup("pirate", count, pos, spread);
var gn = grp.ships;
if (gn && gn.length > 0) {
for (var j = 0; j < gn.length; j++) {
// configure our pirates
gn[j].setBounty(20 + system.info.government + count + Math.floor(Math.random() * 8), "setup actions");
// make sure the pilot has a bounty
gn[j].setCrew({
name: randomName() + " " + randomName(),
bounty: gn[j].bounty,
insurance: 0
});
if (gn[j].hasHyperspaceMotor) {
pop._setWeapons(gn[j], 1.75); // bigger ones sometimes well-armed
} else {
pop._setWeapons(gn[j], 1.3); // rarely well-armed
}
// in the safer systems, rarely highly skilled (the skilled ones go elsewhere)
pop._setSkill(gn[j], 4 - system.info.government);
if (Math.random() * 16 < system.info.government) {
pop._setMissiles(gn[j], -1);
}
// make sure the AI is switched
gn[j].switchAI("bm_pirateAI.js");
}
this._pirates.push({
group: grp,
position: pos
});
} else {
log(this.name, "!!ERROR: Pirate trap group not spawned!");
}
}
//-------------------------------------------------------------------------------------------------------------
// makes the pirates lurk in a particular position
this.$givePiratesLurkPosition = function $givePiratesLurkPosition() {
var retry = false;
for (var i = 0; i < this._pirates.length; i++) {
var grp = this._pirates[i].group;
var pos = this._pirates[i].position;
if (grp.leader) {
if (grp.leader.AIScript.oolite_priorityai) {
grp.leader.AIScript.oolite_priorityai.setParameter("oolite_pirateLurk", pos);
grp.leader.AIScript.oolite_priorityai.reconsiderNow();
for (var j = 0; j < grp.ships.length; j++) {
if (grp.leader !== grp.ships[j]) {
var shp = grp.ships[j];
if (shp.AIScript.oolite_priorityai) {
shp.AIScript.oolite_priorityai.setParameter("oolite_pirateLurk", pos);
shp.AIScript.oolite_priorityai.reconsiderNow();
} else {
retry = true;
break;
}
}
}
} else {
retry = true;
break;
}
}
if (retry === true) break;
}
if (retry === true) {
this._pirateSetup = new Timer(this, this.$givePiratesLurkPosition, 1, 0);
} else {
this._pirates.length = 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)
} |