Scripts/InSystemTrader_worldscript.js |
"use strict";
this.name = "In_System_Trader";
this.author = "Dr.Tripsa";
this.copyright = "2013 Rob Hess";
this.licence = "cc by-nc-sa 4.0";
this.description = "In system trader support";
this.version = "1.5.2";
this.contributers = {
author: "Dr.Tripsa",
coauthors: [
"Neal",
"ocz",
"phkb"
]
}
this.IN_SYSTEM_TRADER_REP = {};
this._current_IN_SYSTEM_TRADER_REP = 0;
this._parcelReputationCounter = 0;
this._shipValue = 0;
this.versionlog = {
"1.0": {
changes: [{
description:
"Basic changes, re-calculate prices/quantities when player leaves main station.", by: ["Dr.Tripsa"]
}]
},
"1.01": {
changes: [{
description:
"added remaining items, no illegals, capped item stock at 63.", by: ["Dr.Tripsa"]
}]
},
"1.05": {
changes: [{
description:
"Added IN_SYSTEM_TRADER_REP property, will be used for tracking w/ mission variables.", by: ["Dr.Tripsa"]
}, {
description:
"Repeatdly redocking now increases the chance you will get the attention of a pirate wing!", by: ["Dr.Tripsa"]
}, {
description:
"Well meaning but medlesome friends now will try to set you up with good parcel deals to get you out more!", by: ["Dr.Tripsa"]
}]
},
"1.10": {
changes: [{
description:
"Moved Chatter to external plist", by: ["Dr.Tripsa"]
}, {
description:
"Stock now only cycled if it has been more than one hour (game time) since your last debark with a fresh market!", by: ["Dr.Tripsa"]
}, {
description:
"Pirates make crude, and embarrasing, threats!", by: ["Dr.Tripsa"]
}]
},
"1.11": {
changes: [{
description:
"Bugfix, refactored plist values", by: ["Dr.Tripsa"]
}]
},
"1.20": {
changes: [{
description:
"Ambush and greetings (when they make no sense) fixed", by: ["Dr.Tripsa"]
}, {
description:
"Code cleanup and timer use (as suggested by spara)", by: ["Dr.Tripsa", "spara"]
}, {
description:
"Debark timer remover, in favor of 1.77 timer function!", by: ["Dr.Tripsa"]
}, {
description:
"cycleMarket now explicitly mainStation", by: ["Dr.Tripsa"]
}]
},
"1.21": {
changes: [{
description:
"Fixed a code redundancy", by: ["Dr.Tripsa"]
}]
},
"1.22": {
changes: [{
description:
"Fixed something I broke when fixing things... ", by: ["Dr.Tripsa"]
}]
},
"1.30": {
changes: [{
description:
"Added A.M.W. Unit Equipment and notification", by: ["Dr.Tripsa"]
}]
},
"1.35": {
changes: [{
description:
"Refactored pirate attack, now I use them to impeade traders", by: ["Dr.Tripsa"]
}, {
description:
"rather than attack player directly", by: ["Dr.Tripsa"]
}, {
description:
"-Much rarer as well (multiplier removed)", by: ["Dr.Tripsa"]
}, {
description:
"Pirate taunts, while fun, have also been removed, as they make less sense now.", by: ["Dr.Tripsa"]
}, {
description:
"Friendly com traffic reduced (multiplier removed)", by: ["Dr.Tripsa"]
}, {
description:
"Fixed a bug that was causing Market updates while docked!", by: ["Dr.Tripsa"]
}]
},
"1.4": {
changes: [{
description:
"By popular demand, returned ambush and taunt", by: ["Dr.Tripsa"]
}, {
description:
"Although in Modified format", by: ["Dr.Tripsa"]
}, {
description:
"Ambushes now happen where the player is", by: ["Dr.Tripsa"]
}]
},
"1.5": {
date: "2016/02/08", changes: [{
description:
"OXP hijacked by ocz (at least for version 1.5)", by: ["ocz"]
}, {
description:
"License changes form ''cc by 3.0'' to ''cc by-nc-sa 4.0''", by: ["ocz"]
}, {
description:
"Fixed for new commodity markets since oolite ver. 1.81 (pre 1.81 backward compatibility is broken now. Can be restored if demanded in http://www.aegidian.org/bb/viewtopic.php?f=4&t=13702 )", by: ["Neil", "ocz"]
}, {
description:
"Deepened reputation system by saving reputation per system and recalculating it when returning in dependance on absence time.", by: ["ocz"]
}, {
description:
"Bonus increase in parcel reputation now is also bound to the systems.", by: ["ocz"]
}, {
description:
"Commodity cycling happens for all stations in the system on base of their own market properties. (Same commodity, same time.)", by: ["ocz"]
}, {
description:
"Fixed ambush pirate fleets attack behaviour. Before they stayed inactive, now they should attack.", by: ["ocz"]
}, {
description:
"The ambush pirate fleets now appear somewhere in front of the player, at the edge of the scanner range.", by: ["ocz"]
}, {
description:
"The ambush pirate fleets sizes are now also dependant on the worth of the player's ship. A Transporter shouldn't have to face 16 ships.", by: ["ocz"]
}, {
description:
"New version log as object. (I know I'm being a kid here, but I wanted to test this new idea.)", by: ["ocz"]
}]
},
"1.5.1": {
date: "2016/03/12", changes: [{
description:
"Bugfix: Some OXP-Station's markets are missing the capacity property for commodities. In this case 127 is now assumed.", by: ["ocz"]
}]
},
"1.5.2": {
date: "2016/03/17", changes: [{
description:
"Bugfix: A.M.W. message displays commodity name", by: ["ocz"]
}, {
description:
"Bugfix: Caught another bug, that has risen from the bugfix in v1.5.1", by: ["ocz"]
}, {
description:
"Bugfix+Feature: New values of commodities look now more random.", by: ["ocz"]
}]
},
"1.5.3": {
date: "2025/05/15", changes: [{
description:
"Bugfix: Spelling corrections.", by: ["phkb"]
},{
description:
"Switched format of descriptions.plist file to OpenStep.", by: ["phkb"]
}]
}
};
/*Version log:
1.0 Basic changes, re-calculate prices/quantities when player leaves main station.
1.01 added remaining items, no illegals, capped item stock at 63.
1.05 Added IN_SYSTEM_TRADER_REP property, will be used for tracking w/ mission variables.
Repeatdly redocking now increases the chance you will get the attention of a pirate wing!
Well meaning but medlesome friends now will try to set you up with good parcel deals to get you out more!
1.10 Moved Chatter to external plist
Stock now only cycled if it has been more than one hour (game time) since your last debark with a fresh market!
Pirates make crude, and embarrasing, threats!
1.11 Bugfix, refactored plist values
1.20 Ambush and greetings (when they make no sense) fixed
Code cleanup and timer use (as suggested by spara)
Debark timer remover, in favor of 1.77 timer function!
cycleMarket now explicitly mainStation
1.21 Fixed a code redundancy
1.22 Fixed something I broke when fixing things...
1.30 Added A.M.W. Unit Equipment and notification
1.35 Refactored pirate attack, now I use them to impeade traders
rather than attack player directly
-Much rarer as well (multiplier removed)
Pirate taunts, while fun, have also been removed, as they make less sense now.
Friendly com traffic reduced (multiplier removed)
Fixed a bug that was causing Market updates while docked!
1.4 By popular demand, returned ambush and taunt
Although in Modified format
Ambushes now happen where the player is
1.5 2016/02/08
OXP hijacked by ocz (at least for version 1.5)
License changes form "cc by 3.0" to "cc by-nc-sa 4.0"
Fixed for new commodity markets since oolite ver. 1.81 (pre 1.81 backward compatibility is broken now. Can be restored if demanded in http://www.aegidian.org/bb/viewtopic.php?f=4&t=13702 )
Deepened reputation system by saving reputation per system and recalculating it when returning in dependence on absence time.
Bonus increase in parcel reputation now is also bound to the systems.
Commodity cycling happens for all stations in the system on base of their own market properties. (Same commodity, same time.)
Fixed ambush pirate fleets attack behaviour. Before they stayed inactive, now they should attack.
The ambush pirate fleets now appear somewhere in front of the player, at the edge of the scanner range.
The ambush pirate fleets sizes are now also dependant on the worth of the player's ship. A Transporter shouldn't have to face 16 ships.
New version log as object. (I know I'm being a kid here, but I wanted to test this new idea.)
1.5.1 2016/03/12
Bugfix: Some OXP-Station's markets are missing the capacity property for commodities. In this case 127 is now assumed.
1.5.2 2016/03/17
Bugfix: A.M.W. message displays commodity name
Bugfix: Caught another bug, that has risen from the bugfix in v1.5.1
Bugfix+Feature: New values of commodities look now more random.
1.5.3 2025/05/15
Bug fix: Spelling corrections.
Switched format of descriptions.plist file to OpenStep.
*/
this.startUp = function () {
//Handle first use of oxp, if we have no rep we set it to 0 for the first time!
var IN_SYSTEM_TRADER_REP_String = "";
if (missionVariables.IN_SYSTEM_TRADER_REP) {
IN_SYSTEM_TRADER_REP_String = missionVariables.IN_SYSTEM_TRADER_REP;//JSON.parse(, function(k,v){log(k+":"+v);return v;});
// Alternative saving format
var version = IN_SYSTEM_TRADER_REP_String.slice(0, 4);
if (version === "v001") {
IN_SYSTEM_TRADER_REP_String = IN_SYSTEM_TRADER_REP_String.slice(4);
this.IN_SYSTEM_TRADER_REP = JSON.parse(IN_SYSTEM_TRADER_REP_String);
for (var systemName in this.IN_SYSTEM_TRADER_REP) {
var arr = this.IN_SYSTEM_TRADER_REP[systemName];
this.IN_SYSTEM_TRADER_REP[systemName] = {
"reputation": arr[0],
"parcelRepCounter": arr[1],
"departure": arr[2]
};
}
}
else { this.IN_SYSTEM_TRADER_REP = JSON.parse(IN_SYSTEM_TRADER_REP_String); }
}
else this.IN_SYSTEM_TRADER_REP = {};
this._loadSystemsReputation();
this._shipValue = player.ship.price;
this.timer = new Timer(this, this.cycleMarket, 300, 300);
//initially this is a 300 second timer delay, to prevent changes While docked.
//We will check docked status in the cycleMarket and do nothing if docked or if there is no MainStation!
}
// Start of economicBiasForGood method.
// This method has been converted by hand from the oolite source code ver 1.82
// (OOCommodities.m : economicBiasForGood) and is being
// published in this form under cc by-nc-sa 4.0 with kind permission from cim.
// Copyright (C) 2004-2014 Giles C Williams and contributors
this.economicBiasForGood = function (good, economy) {
var exporter = good.peak_export;
var importer = good.peak_import;
// *2 and /2 to work in ints at this stage
var exDiff = Math.abs(economy - exporter) * 2;
var imDiff = Math.abs(economy - importer) * 2;
var distance = (exDiff + imDiff) / 2;
if (exDiff == imDiff) {
// neutral economy
return 0.0;
}
else if (exDiff > imDiff) {
// closer to the importer, so return -ve
return -(1.0 - (imDiff / distance));
}
else {
// closer to the exporter, so return +ve
return 1.0 - (exDiff / distance);
}
return 0.0;
}
// End of economicBiasForGood method.
this.positionInfrontPlayer = function (distance, focus) {
var rDirection;
if (!distance) distance = 25600;
if (!focus) focus = 1.4;
var pDirection = player.ship.heading.direction();
for (var i = 0; i < 10; i++) {
rDirection = Vector3D.randomDirection();
if (pDirection.subtract(rDirection).magnitude() < focus)
return player.ship.position.add(rDirection.multiply(distance));
}
return player.ship.position.add(pDirection.multiply(distance));
}
this.ambushFleet = function () {
var RAND_MULTB = (Math.random() * 255);
//yes, we have a new RAND_MULT for this, separate of the clock
if ((this.IN_SYSTEM_TRADER_REP >= RAND_MULTB) && (this.IN_SYSTEM_TRADER_REP >= 2) && this._shipValue > 35000) {
//Ambush redux, the bitwise and caps the number of pirates at 16
//and comparing RAND_MULTB in the if keeps the players IN_SYSTEM_TRADER_REP relevant
//as the number of pirates will never be more than the players IN_SYSTEM_TRADER_REP
//I also removed the multiplier but kept the 'Rep must be at least 2' factor
//Dr.Tripsa, pre 1.5
//Also the if-clause makes sure no ship worth less than 35kCr are ambushed and
//shipPriceFactor makes sure that the pirate fleets don't get too tough for smaller
//ships. An ambush always at least involves 2 pirate ships.
//ocz, 1.5
var shipPriceFactor = (this._shipValue - 35000) / 100000;
if (shipPriceFactor > 1) shipPriceFactor = 1;
var shipsAmount = Math.ceil(((RAND_MULTB & 15) + 1) * shipPriceFactor);
if (shipsAmount < 2) shipsAmount = 2;
var ambush = system.addShips("pirate", shipsAmount, this.positionInfrontPlayer(25000, 1.2));
//var ambush = system.addGroup("pirate",shipsAmount, this.positionInfrontPlayer(25000));
//Returning taunts
ambush[0].commsMessage(expandDescription("[in_system_trader_pgreet] [in_system_trader_ptaunt]"));
//Create ShipGroup
var ambushG = new ShipGroup("Pirate ambush");
for (var i = 0; i < ambush.length; i++) ambush[i].group = ambushG;
ambushG.leader = ambush[0];
//And let it attack
ambushG.leader.target = player.ship;
ambushG.leader.performAttack();
return ambushG;
}
return [];
}
this.cycleMarket = function () {
//var ChoiceName = "nothing";
// "I'm a moron, me. This needed to be an AND", quote Dr.Tripsa. ;)
if ((!system.isInterstellarSpace) && (!player.ship.docked)) {
//we will only allow the market to change when there IS a market and we are not docked!
var CommList = []
var count = 0;
// Use the main station as reference to get a list of all commodities
for (comm in system.mainStation.market) {
CommList[count] = comm;
count++;
}
// Choose random commodity
var Choice = Math.floor(system.scrambledPseudoRandomNumber(clock.minutes) * CommList.length);
if (system.mainStation.market[CommList[Choice]].legality_export == 0) {
var ChoiceCom = CommList[Choice];
var randomizeSeed = Math.floor(clock.seconds / 5);
// The chosen commodity will be cycled on every station in the system
for (var i = 0; i < system.stations.length; i++) {
randomizeSeed = Math.floor(clock.seconds / 5) + (Math.floor(clock.seconds / 500) * i) //Feature v1.5.2: For more randomness
if (system.stations[i].market[ChoiceCom]) this.cycleStationMarket(system.stations[i], ChoiceCom, randomizeSeed);
}
//If the player has the EQ_SYSTEM_MARKET_WATCH, let us inform them of a change!
if (player.ship.equipmentStatus("EQ_SYSTEM_MARKET_WATCH") == "EQUIPMENT_OK") {
var mySound = new SoundSource;
mySound.sound = "beep.ogg";
mySound.play();
player.consoleMessage("A.M.W.: Stock rotation detected on commodity: " + displayNameForCommodity(ChoiceCom) + ". See market datascreen (F8) for details.", 8);
}
}
else {
//Move pirate ambush code here as well, to be triggered when an invalid commodity is chosen
var fleet = this.ambushFleet();
//old behaviour
/*var RAND_MULTB = (Math.random() * 255);
//yes, we have a new RAND_MULT for this, separate of the clock
if((this.IN_SYSTEM_TRADER_REP >= RAND_MULTB) && (this.IN_SYSTEM_TRADER_REP >= 2)) {
//Ambush redux, the bitwise and caps the number of pirates at 16
//and comparing RAND_MULTB in the if keeps the players IN_SYSTEM_TRADER_REP relevant
//as the number of pirates will never be more than the players IN_SYSTEM_TRADER_REP
//I also removed the multiplier but kept the 'Rep must be at least 2' factor
var ambush = system.addShips("pirate",((RAND_MULTB & 15) +1), player.ship.position);
//Returning taunts
ambush[0].commsMessage(expandDescription("[in_system_trader_pgreet] [in_system_trader_ptaunt]"));
}
*/
}
//Change the timer.interval, based on system activity, TY Spara!
var traders = system.countShipsWithPrimaryRole("trader");
if (traders > 0) {
// 1/traders * (30 + [0 - 30]) mins till next price and restock check
this.timer.interval = Math.round((1 / traders) * (1800 + (Math.random() * 1800)));
}
}
}
this.cycleStationMarket = function (station, commodity, randomizeSeed) {
// If no seed value is given, the method chooses one by itself
if (!randomizeSeed) var randomizeSeed = Math.floor(clock.seconds / 5);
// Start of cycleStationMarket sub-algorithm.
// This sub-algorithm is based on program code from the oolite source code ver. 1.82
// (OOCommodities.m : generatePriceForGood & generateQuantityForGood) and is being
// published in this form under cc by-nc-sa 4.0 with kind permission from cim
// Copyright (C) 2004-2014 Giles C Williams and contributors
var bias = this.economicBiasForGood(station.market[commodity], system.economy);
var pBase = parseFloat(station.market[commodity].price_average);
var pEcon = pBase * station.market[commodity].price_economic * -1 * bias;
var pRandom = pBase * station.market[commodity].price_random * (system.scrambledPseudoRandomNumber(randomizeSeed) - system.scrambledPseudoRandomNumber(Math.floor(system.scrambledPseudoRandomNumber(randomizeSeed + 1) * 1000)));
//Bugfix v1.5.2: Subtracting two values of scrambledPseudoRandomNumber(seed) with seed numbers, those difference have the value as another pair of seed numbers tend to yield the same result value. (3 and 4, and 10 and 11, for example, yield 0.7274143758695573)
//Therefore the pRandom and qRandom (see code below) had to be complicated.
pBase += pEcon + pRandom;
if (pBase < 0.0) pBase = 0;
var qBase = parseFloat(station.market[commodity].quantity_average);
var qEcon = qBase * station.market[commodity].quantity_economic * -1 * bias;
var qRandom = qBase * station.market[commodity].quantity_random * (system.scrambledPseudoRandomNumber(randomizeSeed + 2) - system.scrambledPseudoRandomNumber(Math.floor(system.scrambledPseudoRandomNumber(randomizeSeed + 3) * 1000)));
//Bugfix v1.5.2: Same bugfix as above.
qBase += qEcon + qRandom;
// End of cycleStationMarket sub-algorithm.
//Bugfix 1.5.1: Sometimes the commodity properties of station markets seem to be mission a capacity property. In this case 127 will be assumed.
var capacity;
if (station.market[commodity].hasOwnProperty("capacity")) capacity = station.market[commodity].capacity;
else capacity = 127;
// Scale quantity to match the capacity of the station
qBase = (qBase / 127) * capacity;
// Make sure quantity DOES really match stations capacity
if (qBase > capacity) qBase = capacity;
if (qBase < 0.0) qBase = 0;
//log(station.name + " " + commodity + ": " + Math.round(pBase)/10 + "Cr ," + Math.round(qBase) + "Units");
station.setMarketPrice(commodity, pBase);
station.setMarketQuantity(commodity, qBase);
}
// As player.ship.price is not available in-flight, it has to be stored before.
this.shipDockedWithStation = function (station) {
this._shipValue = player.ship.price;
}
this.shipLaunchedFromStation = function (station) {
// Here we will give the _current_IN_SYSTEM_TRADER_REP a boost
// We used to limit this to main station, now any station in system
// will boost _current_IN_SYSTEM_TRADER_REP!
this._current_IN_SYSTEM_TRADER_REP++;
this._parcelReputationCounter++;
// If our _parcelReputationCounter has crossed a threshhold of 16, we give a parcel Reputation bonus for knowing "the right" people!
// Note this probably will not have any effect until the player witches out and a new set of parcels is generated!
if (this._parcelReputationCounter > 15) {
player.increaseParcelReputation();
this._parcelReputationCounter = 0;
};
}
this.shipWillEnterWitchspace = function () {
this._repDataToSystemObj();
}
this.shipExitedWitchspace = function () {
this._loadSystemsReputation();
}
this._loadSystemsReputation = function () {
//This will cause decrease as the once system bound player explores the Ooniverse
var tempReputation = 0;
if (this.IN_SYSTEM_TRADER_REP[system.name]) {
if (!this.IN_SYSTEM_TRADER_REP[system.name].reputation) this.IN_SYSTEM_TRADER_REP[system.name].reputation = 0;
if (!this.IN_SYSTEM_TRADER_REP[system.name].parcelRepCounter) this.IN_SYSTEM_TRADER_REP[system.name].parcelRepCounter = 0;
this._parcelReputationCounter = this.IN_SYSTEM_TRADER_REP[system.name].parcelRepCounter;
var timeSinceLastVisit = clock.seconds - this.IN_SYSTEM_TRADER_REP[system.name].departure;
// If last visits was within last week, decrease reputation by 1 for each day;
if (timeSinceLastVisit < 604800) {
tempReputation = this.IN_SYSTEM_TRADER_REP[system.name].reputation - (Math.floor(timeSinceLastVisit / 86400))
if (tempReputation < 0) tempReputation = 0;
}
// else decrease it by 7 for the first week and cut it by half for each passing week of the next 8 weeks
else if (timeSinceLastVisit < 5443200) {
timeSinceLastVisit -= 604800;
tempReputation = this.IN_SYSTEM_TRADER_REP[system.name].reputation - 7;
tempReputation /= (2 ^ (Math.floor(timeSinceLastVisit / 604800) - 1));
}
// and if it's been longer then 9 weeks the players system reputation is gone
}
else {
this.IN_SYSTEM_TRADER_REP[system.name] = {
reputation: 0,
parcelRepCounter: 0,
departure: clock.seconds
};
this._current_IN_SYSTEM_TRADER_REP = 0;
this._parcelReputationCounter = 0;
}
// Divide _current_IN_SYSTEM_TRADER_REP (player's reputation from the system before) by 2
this._current_IN_SYSTEM_TRADER_REP /= 2;
// and see, if the player's old reputation in the systems is higher
if (this._current_IN_SYSTEM_TRADER_REP < tempReputation) this._current_IN_SYSTEM_TRADER_REP = tempReputation;
this.IN_SYSTEM_TRADER_REP[system.name].departure = clock.seconds;
}
this._cleanReputationSystemObj = function () {
var timeCutOff = clock.seconds - 5443200;
for (var repSystem in this.IN_SYSTEM_TRADER_REP) {
//delete every entry older than 9 weeks
if (this.IN_SYSTEM_TRADER_REP[repSystem].departure < timeCutOff) { delete this.IN_SYSTEM_TRADER_REP[repSystem];/*log("Delete system (too old): "+repSystem);*/ }
else if (this.IN_SYSTEM_TRADER_REP[repSystem].reputation < 8) {
//delete every entry older than a week with 7 or less reputation points
if (this.IN_SYSTEM_TRADER_REP[repSystem].departure < clock.seconds - 604800 || this.IN_SYSTEM_TRADER_REP[repSystem].reputation == 0) { delete this.IN_SYSTEM_TRADER_REP[repSystem];/*log("Delete system (too small rep): "+repSystem);*/ }
}
//if (repSystem.reputation == 0) {delete this.IN_SYSTEM_TRADER_REP[repSystem];log("Delete system (too small rep): "+repSystem);}
}
}
this._repDataToSystemObj = function () {
this.IN_SYSTEM_TRADER_REP[system.name] = {
reputation: this._current_IN_SYSTEM_TRADER_REP,
parcelRepCounter: this._parcelReputationCounter,
departure: clock.seconds
};
}
this.playerWillSaveGame = function (message) {
//Here we move the property back to mission variable for save.
this._cleanReputationSystemObj();
this._repDataToSystemObj();
missionVariables.IN_SYSTEM_TRADER_REP = JSON.stringify(this.IN_SYSTEM_TRADER_REP);
/*var saveString = "v001";
var IN_SYSTEM_TRADER_REP_temp = this.IN_SYSTEM_TRADER_REP;
for (var systemName in IN_SYSTEM_TRADER_REP_temp) {
var obj = IN_SYSTEM_TRADER_REP_temp[systemName];
IN_SYSTEM_TRADER_REP_temp[systemName] = [ obj.reputation,
obj.parcelRepCounter,
obj.departure];
}
saveString+=JSON.stringify(IN_SYSTEM_TRADER_REP_temp);
missionVariables.IN_SYSTEM_TRADER_REP2 = saveString;*/
}
this.shipEnteredStationAegis = function (station) {
//Give player a hint that the friends they have made might have deals for them
var RAND_MULT = (Math.random() * 255);
// this is independent of the clock
if ((this.IN_SYSTEM_TRADER_REP >= RAND_MULT) && (this.IN_SYSTEM_TRADER_REP >= 2)) {
//periodically we give the player a hint... friend of a friend etc
//This too has had it's multiplier removed to make it less predictable[
player.commsMessage(system.name + " traffic control: " + expandDescription("[in_system_trader_greet] [in_system_trader_invite] [in_system_trader_relation] [nom]. [in_system_trader_offer]"));
}
} |