<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.alioth.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Wildeblood</id>
	<title>Elite Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.alioth.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Wildeblood"/>
	<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php/Special:Contributions/Wildeblood"/>
	<updated>2026-06-23T14:23:38Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.12</generator>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89557</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89557"/>
		<updated>2026-06-23T10:56:17Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* What methods might lurk in any damned script? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
[quote=Switeck post_id=306192 time=1782133939 user_id=3036]&lt;br /&gt;
The commodities markets for each add-on station is another issue -- often using fixed scripting instead of borrowing the main station's prices and quantities, or worse...completely broken (0 prices, 0 quantities).&lt;br /&gt;
[/quote]&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== Display on market screens ===&lt;br /&gt;
&lt;br /&gt;
==== name ====&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
==== comment ====&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
==== short_comment ====&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
==== sort_order ====&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== Aboard ship ===&lt;br /&gt;
&lt;br /&gt;
==== quantity_unit ====&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
==== trumble_opinion ====&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. '''If the calculated quantity exceeds the capacity, it will be capped.''' (Is this true? ''cf.'' Thargoidifier)&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, but only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a commodity might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=File:AI_Trading_Backup_Datalogger_3.oxz&amp;diff=89556</id>
		<title>File:AI Trading Backup Datalogger 3.oxz</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=File:AI_Trading_Backup_Datalogger_3.oxz&amp;diff=89556"/>
		<updated>2026-06-23T10:28:59Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Summary */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
For clarification of &amp;quot;What does 3-ish mean?&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 - The data structure Trading Assistant 3 will use will not change.&lt;br /&gt;
 - The script inside this OXZ will not change.&lt;br /&gt;
 - Only the equipment.plist file (to make Trading Assistant harder to acquire)&lt;br /&gt;
   and the manifest.plist file (to list known incompatibilities) will change.&lt;br /&gt;
 - This is safe to use.&lt;br /&gt;
&lt;br /&gt;
I plan to publish Trading Assistant 3 sometime during August, 2026.&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89516</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89516"/>
		<updated>2026-06-19T15:26:12Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Using the trade-goods.plist */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== Display on market screens ===&lt;br /&gt;
&lt;br /&gt;
==== name ====&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
==== comment ====&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
==== short_comment ====&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
==== sort_order ====&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== Aboard ship ===&lt;br /&gt;
&lt;br /&gt;
==== quantity_unit ====&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
==== trumble_opinion ====&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. '''If the calculated quantity exceeds the capacity, it will be capped.''' (Is this true? ''cf.'' Thargoidifier)&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, but only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a commodity might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89515</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89515"/>
		<updated>2026-06-19T15:07:57Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Display on market screens */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== Display on market screens ===&lt;br /&gt;
&lt;br /&gt;
==== name ====&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
==== comment ====&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
==== short_comment ====&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
==== sort_order ====&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== Aboard ship ===&lt;br /&gt;
&lt;br /&gt;
==== quantity_unit ====&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
==== trumble_opinion ====&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. '''If the calculated quantity exceeds the capacity, it will be capped.''' (Is this true? ''cf.'' Thargoidifier)&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89514</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89514"/>
		<updated>2026-06-19T15:06:40Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* trumble_opinion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== Display on market screens ===&lt;br /&gt;
&lt;br /&gt;
==== name ====&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
==== comment ====&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
==== short_comment ====&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
==== sort_order ====&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
==== quantity_unit ====&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
==== trumble_opinion ====&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. '''If the calculated quantity exceeds the capacity, it will be capped.''' (Is this true? ''cf.'' Thargoidifier)&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89513</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89513"/>
		<updated>2026-06-19T15:05:58Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* quantity_unit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== Display on market screens ===&lt;br /&gt;
&lt;br /&gt;
==== name ====&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
==== comment ====&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
==== short_comment ====&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
==== sort_order ====&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
==== quantity_unit ====&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. '''If the calculated quantity exceeds the capacity, it will be capped.''' (Is this true? ''cf.'' Thargoidifier)&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89512</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89512"/>
		<updated>2026-06-19T14:58:26Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Property keys (listed thematically, not alphabetically) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== Display on market screens ===&lt;br /&gt;
&lt;br /&gt;
==== name ====&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
==== comment ====&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
==== short_comment ====&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
==== sort_order ====&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. '''If the calculated quantity exceeds the capacity, it will be capped.''' (Is this true? ''cf.'' Thargoidifier)&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89511</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89511"/>
		<updated>2026-06-19T14:49:51Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* sort_order */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== Display on market screens ===&lt;br /&gt;
&lt;br /&gt;
==== name ====&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
==== comment ====&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
==== short_comment ====&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
==== sort_order ====&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. '''If the calculated quantity exceeds the capacity, it will be capped.''' (Is this true? ''cf.'' Thargoidifier)&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89510</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89510"/>
		<updated>2026-06-19T14:49:22Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* short_comment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== Display on market screens ===&lt;br /&gt;
&lt;br /&gt;
==== name ====&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
==== comment ====&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
==== short_comment ====&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. '''If the calculated quantity exceeds the capacity, it will be capped.''' (Is this true? ''cf.'' Thargoidifier)&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89509</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89509"/>
		<updated>2026-06-19T14:48:57Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* comment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== Display on market screens ===&lt;br /&gt;
&lt;br /&gt;
==== name ====&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
==== comment ====&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. '''If the calculated quantity exceeds the capacity, it will be capped.''' (Is this true? ''cf.'' Thargoidifier)&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89508</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89508"/>
		<updated>2026-06-19T14:48:05Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* name */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== Display on market screens ===&lt;br /&gt;
&lt;br /&gt;
==== name ====&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. '''If the calculated quantity exceeds the capacity, it will be capped.''' (Is this true? ''cf.'' Thargoidifier)&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89507</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89507"/>
		<updated>2026-06-19T14:20:13Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* quantity_average */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. '''If the calculated quantity exceeds the capacity, it will be capped.''' (Is this true? ''cf.'' Thargoidifier)&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89506</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89506"/>
		<updated>2026-06-19T14:17:55Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* capacity */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89505</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89505"/>
		<updated>2026-06-19T14:16:57Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Quantities */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89504</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89504"/>
		<updated>2026-06-19T14:16:13Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* capacity */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89503</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89503"/>
		<updated>2026-06-19T14:04:44Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Property keys (listed thematically, not alphabetically) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overrides.plist , planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Legality ===&lt;br /&gt;
&lt;br /&gt;
==== legality_export ====&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
==== legality_import ====&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== Economic biases ===&lt;br /&gt;
&lt;br /&gt;
==== peak_export ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
==== peak_import ====&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== Prices ===&lt;br /&gt;
&lt;br /&gt;
==== price_average ====&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
==== price_economic ====&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
==== price_random ====&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== Quantities ===&lt;br /&gt;
&lt;br /&gt;
==== quantity_average ====&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
==== quantity_economic ====&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
==== quantity_random ====&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89495</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89495"/>
		<updated>2026-06-19T10:17:33Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Property keys */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys (listed thematically, not alphabetically) ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89494</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89494"/>
		<updated>2026-06-19T10:14:50Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Can we define new properties for commodities */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities? ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
=== Is the economy 0&amp;lt;-&amp;gt;7 dipole set in stone? ===&lt;br /&gt;
&lt;br /&gt;
Does it really require javascript to overcome this?&lt;br /&gt;
&lt;br /&gt;
If so, what is the actual function of the peak_import &amp;amp; peak_export properties?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89493</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89493"/>
		<updated>2026-06-19T09:40:51Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* How will sub-standard OXPs thwart us? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
=== Can we define new properties for commodities ===&lt;br /&gt;
&lt;br /&gt;
Where can we set &amp;quot;aita_image&amp;quot; values?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89492</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89492"/>
		<updated>2026-06-19T09:32:56Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* How will sub-standard OXPs thwart us? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
==== Can we move the world-script in AristoShares OXP into a market script? ====&lt;br /&gt;
&lt;br /&gt;
That would prevent deadbeat scripts from interfering with it. Good idea, research required.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89491</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89491"/>
		<updated>2026-06-19T09:26:06Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
[[File:Distant Riches.png|thumb|right|200px|MORE THAN FIFTY NEW TRADE GOODS]]&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89490</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89490"/>
		<updated>2026-06-19T09:08:41Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* F.A.Q. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
==== Which plists exactly? ====&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist can set '''market definitions''' directly.&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist can set links to '''market scripts'''.&lt;br /&gt;
&lt;br /&gt;
==== Which market scripts exactly? ====&lt;br /&gt;
&lt;br /&gt;
See below.&lt;br /&gt;
&lt;br /&gt;
==== What methods might lurk in ''any damned script''? ====&lt;br /&gt;
&lt;br /&gt;
station.setMarketPrice() or &lt;br /&gt;
station.setMarketQuantity()&lt;br /&gt;
&lt;br /&gt;
=== How do we define a new &amp;quot;trade-good&amp;quot; (commodity) '''non-bogusly?''' ===&lt;br /&gt;
&lt;br /&gt;
With trade-goods.plist &lt;br /&gt;
&lt;br /&gt;
=== How will sub-standard OXPs thwart us? ===&lt;br /&gt;
&lt;br /&gt;
By careless use of &amp;quot;default&amp;quot; in market influences to destroy things they don't even know exist.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89489</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89489"/>
		<updated>2026-06-19T08:48:53Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* classes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
2. Which plists exactly?&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist&lt;br /&gt;
&lt;br /&gt;
3. Which market scripts exactly?&lt;br /&gt;
&lt;br /&gt;
4. What methods?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of commodity class names. Classes can be used by secondary stations (only secondary markets?) to set pricing rules for groups of commodities.&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89488</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89488"/>
		<updated>2026-06-19T08:45:39Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Discussion of classes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
2. Which plists exactly?&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist&lt;br /&gt;
&lt;br /&gt;
3. Which market scripts exactly?&lt;br /&gt;
&lt;br /&gt;
4. What methods?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89487</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89487"/>
		<updated>2026-06-19T08:41:07Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* trumble_opinion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
2. Which plists exactly?&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist&lt;br /&gt;
&lt;br /&gt;
3. Which market scripts exactly?&lt;br /&gt;
&lt;br /&gt;
4. What methods?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
=== Discussion of classes ===&lt;br /&gt;
&lt;br /&gt;
HERE&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89486</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89486"/>
		<updated>2026-06-19T08:31:22Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* F.A.Q. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer the following questions.&lt;br /&gt;
&lt;br /&gt;
=== How many different places can market influences be hiding? ===&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, and in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
2. Which plists exactly?&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist&lt;br /&gt;
&lt;br /&gt;
3. Which market scripts exactly?&lt;br /&gt;
&lt;br /&gt;
4. What methods?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89485</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89485"/>
		<updated>2026-06-19T08:23:46Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== F.A.Q. ==&lt;br /&gt;
&lt;br /&gt;
The goal of this page is to answer these questions:&lt;br /&gt;
&lt;br /&gt;
1. How many different places can market influencers be hiding?&lt;br /&gt;
&lt;br /&gt;
In plists, in market scripts, in station methods in ''any damned script''.&lt;br /&gt;
&lt;br /&gt;
2. Which plists exactly?&lt;br /&gt;
&lt;br /&gt;
At least trade-goods.plist , shipdata.plist , shipdata-overides.plist (sp?), planetinfo.plist&lt;br /&gt;
&lt;br /&gt;
3. Which market scripts exactly?&lt;br /&gt;
&lt;br /&gt;
4. What methods?&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89484</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89484"/>
		<updated>2026-06-19T08:09:35Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Secondary Market Definitions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:SOTL Altmap F8.png|thumb|right|300px|The ''first'' page of commodities from [[SOTL Altmap]], Cim's 2014 experimental scenario]]&lt;br /&gt;
'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The primary market is that of the system's main station (''i.e.'' the javascript object system.mainStation.market ) Secondary markets are other markets, which are influenced by the primary market, ''e.g.'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, '''assuming no market_script is defined''':&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=OXP_howto&amp;diff=89483</id>
		<title>OXP howto</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=OXP_howto&amp;diff=89483"/>
		<updated>2026-06-19T01:57:30Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Asking AI to write a script for you */ Now hopelessly out of date.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;:''Shortcut: EW:OXP and EW:HOWDS redirect here''&amp;lt;/br&amp;gt;&lt;br /&gt;
[[Image:oolite-oxp-icon.png|100px|thumb|right|OXP icon]]&lt;br /&gt;
[[File:Oolite-debug-menu.png|thumb|right|Debug Menu  (From the AppleMac variety of the &amp;quot;Oolite TR&amp;quot; version)]]&lt;br /&gt;
==Overview==&lt;br /&gt;
An '''Oolite Expansion Pack''' can cause many big changes or additions to Oolite's gameplay, or it may represent just a small, subtle alteration. By first appearances, there is no way to tell what is inside, as it's merely a ''folder'' with the added extension '''.oxp'''.&lt;br /&gt;
Oolite Version 1.79 onwards supports also compressed files in ZIP format with extension '''.oxz'''. &lt;br /&gt;
&lt;br /&gt;
To learn starting with a non-compressed version have a look at [[OXP_tutorial]].&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=It's worth saying I think that compared with a lot of game addon architectures, the OXP architecture as designed by Giles is already very good at avoiding conflicts compared with a lot of other games&lt;br /&gt;
- you can save your game, add, remove and upgrade lots of OXPs, load your game, and have it work&lt;br /&gt;
- you can do this repeatedly, while incrementally upgrading the core game, for years&lt;br /&gt;
- as a player you basically never have to care about load order; as an OXP developer, rarely&lt;br /&gt;
&lt;br /&gt;
It's also worth noting that a lot of types of OXP conflicts are inevitable due to resource conflicts - a planet can only have one diffuse map, a ship can only have one AI - or due to conceptual conflicts - OXP A removes all stations from a system; OXP B expects the player to dock there.|Source=([https://bb.oolite.space/viewtopic.php?p=241733#p241733 Cim (3rd Lead Developer)])}}&lt;br /&gt;
&lt;br /&gt;
=== Oolite TR version ===&lt;br /&gt;
The Oolite Developer Release/Test Release version is specially developed for testing out OXPs. It comes with a [[Debug OXP]]/Debug Console allowing one to spawn ships/station on demand, award oneself a test ship, detect the mass of another ship ''etc''.&lt;br /&gt;
&lt;br /&gt;
It is downloaded from the main Oolite website - currently http://www.oolite.space/download/&lt;br /&gt;
&lt;br /&gt;
== OXZ ==&lt;br /&gt;
The new OXZ distribution format is strongly recommended. It makes version control and distribution just so much easier.&lt;br /&gt;
&lt;br /&gt;
To make an OXZ file, use a ZIP program to compress the contents of the OXP folder, so that the [[manifest.plist]] file is in the root of the ZIP file, and the folders (AI, Config, etc) are folders in the ZIP file. Then, rename the ZIP file so that its extension is '''.oxz'''. To inspect an OXZ file, open it with your ZIP program.&lt;br /&gt;
&lt;br /&gt;
Here is a sample: [[Media:X.0.1.oxz]] - just rename all &amp;quot;X&amp;quot; within to the title of your idea and put your name into the author fields. &lt;br /&gt;
&lt;br /&gt;
You can use [http://www.ghisler.com/download.htm Total Commander] or [http://en.wikipedia.org/wiki/Krusader Krusader] to edit files within '''.oxz''' directly, without unpacking.&lt;br /&gt;
&lt;br /&gt;
For more details read [https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=16688 The All-in-One Guide to OXZ Packaging and Distribution].&lt;br /&gt;
&lt;br /&gt;
=== Creating an .oxz on an AppleMac ===&lt;br /&gt;
When you compress the files/folders on the AppleMac to create the .oxz ''do not'' select them with your mouse! This way lies misery!&lt;br /&gt;
&lt;br /&gt;
Rather, ensure the relevant files/folders are inside one overall folder. Then, use '''command-a''' to select all the ''contents'' of this overall folder and then select '''compress''' from the file menu on the finder's menu bar. Finally, rename your newly-created .zip file as an .oxz&lt;br /&gt;
&lt;br /&gt;
==Structure==&lt;br /&gt;
Inside the '''.oxp''' folder, or the '''.oxz''' file, it will at least contain a folder (Config, AIs, Models, Textures, etc...) that holds scripts, plists or other things like textures or models. It is down to the goal of the [[OXP]], which ways to combine elements to the OXP's contents. To get a feeling for it, simply take a look in other oxps. (If they are in .oxz format, any normal unzip program can inspect their contents - many will even let you edit the contents without having to unzip and rezip the file)&lt;br /&gt;
&lt;br /&gt;
The structure for OXPs:&lt;br /&gt;
 AddOns (folder)&lt;br /&gt;
 ~.oxp (really just another folder!) - Holds manifest.plist and the other folders:&lt;br /&gt;
 &lt;br /&gt;
 --&amp;gt; AIs (folder) - Holds AI plists&lt;br /&gt;
 --&amp;gt; Config (folder) - Holds all other plists (and possibly an anonymous &amp;quot;Script.js&amp;quot;)&lt;br /&gt;
 --&amp;gt; Images (folder) - Holds background images&lt;br /&gt;
 --&amp;gt; Models (folder) - Holds the .dat files (special Oolite format)&lt;br /&gt;
 --&amp;gt; Music (folder) - Surprise - holds .ogg music files&lt;br /&gt;
 --&amp;gt; Scenarios (folder) - Holds new game scenarios (v1.79)&lt;br /&gt;
 --&amp;gt; Scripts (folder) - Holds scripts (worldScripts and shipScripts)&lt;br /&gt;
 --&amp;gt; Shaders (folder) - Holds Vertex and Fragment shaders (v1.69)&lt;br /&gt;
 --&amp;gt; Sounds (folder) - Holds sound files&lt;br /&gt;
 --&amp;gt; Textures (folder) - Holds models textures (can be planets, too!)&lt;br /&gt;
 --&amp;gt; [[manifest.plist]] (file) &lt;br /&gt;
     ''the following might also be found in here:''&lt;br /&gt;
 --&amp;gt; [[Misc plists|info.plist]] (file, seems to be a poor duplicate of the Manifest.plist)&lt;br /&gt;
 --&amp;gt; [[Requires.plist]] (file: deprecated - replaced by Manifest.plist)&lt;br /&gt;
&lt;br /&gt;
*If the OXP is in the uncompressed OXP folder format, the .oxp folder must contain a [[requires.plist]] file. If it is in the compressed OXZ single-file format, it must contain a [[manifest.plist]] file.&lt;br /&gt;
&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=13134 Nested OXPs in AddOns folder] (2012) - some OXZ's do this (Station spotter oxp inside [[Stations for Extra Planets]]) &lt;br /&gt;
&lt;br /&gt;
===AIs folder===&lt;br /&gt;
The folder named AIs contains any AI.plist additions the OXP might use. &lt;br /&gt;
&lt;br /&gt;
* [[OXP howto AI|Making Oolite AI]]&lt;br /&gt;
&lt;br /&gt;
In Oolite 1.79 AIs may be written in Javascript using .js files in this folder. A helper library is provided to make writing complex JS AIs simpler.&lt;br /&gt;
&lt;br /&gt;
* [[Oolite PriorityAI Documentation]]&lt;br /&gt;
* [[Oolite PriorityAI Tutorial]]&lt;br /&gt;
&lt;br /&gt;
===Config folder===&lt;br /&gt;
All plist files except for those introducing new AIs, ''[[requires.plist]]'', ''[[manifest.plist]]'' or ''[[Misc plists|info.plist]]'', belong in Config.&lt;br /&gt;
&lt;br /&gt;
In its simplest form, an OXP could contain only a Config with an altering ''script.plist'' or ''planetinfo.plist''.  An OXP that adds a new ship needs a ''shipdata.plist'' entry, and unless it is based entirely on existing Oolite data, would include a model and texture. &lt;br /&gt;
&lt;br /&gt;
* [[OXP howto plist|Making Oolite plists]]&lt;br /&gt;
* Usually irrelevant: The Config folder isn't cached in the same way as the rest of an oxp because usually its contents merge rather than overwriting (See [https://bb.oolite.space/viewtopic.php?f=3&amp;amp;t=16927 here])&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
This folder contains [[Property lists]] such as:&lt;br /&gt;
&lt;br /&gt;
* ''[[characters.plist]]'' that adds non-player characters to Oolite.&lt;br /&gt;
* ''[[crosshairs.plist]]'' that contains the look for your weapons (v1.73).&lt;br /&gt;
* ''[[customsounds.plist]]'' that contains references to ingame used sounds.&lt;br /&gt;
* ''[[descriptions.plist]]'' that adds vocabulary to Oolite texts.&lt;br /&gt;
* ''[[effectdata.plist]]'' defines custom visual effects (v1.77).&lt;br /&gt;
* ''[[equipment.plist]]'' lists upgrades available from the Shipyard.&lt;br /&gt;
* ''[[explosions.plist]]'' customises things blowing up (v1.81)&lt;br /&gt;
* ''[[global-settings.plist]]'' sets a few miscellaneous universal settings (v1.81)&lt;br /&gt;
* ''[[gui-settings.plist]]'' settings for reformatting the GUI screens (v1.81)&lt;br /&gt;
* ''[[hud.plist]]'' and ''[[hud.plist|hud-small.plist]]'' that allows for changes or a radically new ''Head-Up Display''.&lt;br /&gt;
* ''[[Oolite_Keyboard_Controls|keyconfig2.plist]]'' that allows for changes of the keymapping.&lt;br /&gt;
* ''[[missiontext.plist]]'' contains texts for the mission screens.&lt;br /&gt;
* ''[[OXPMessages.plist]]'' adds warnings to testversions of an oxp.&lt;br /&gt;
* ''[[planetinfo.plist]]'' that plots system specific changes from the default. May also contain ''script actions''.&lt;br /&gt;
* ''[[role-categories.plist]]'' for specifying groups of roles (''eg''.: trader, Miner, pirate ''etc''.) with similar properties (v1.79)&lt;br /&gt;
* ''[[scenarios.plist]]'' lists the starting scenarios in the Scenarios folder (v1.79).&lt;br /&gt;
* ''[[screenbackgrounds.plist]]'' that contains references to background images (v1.74).&lt;br /&gt;
* ''[[Scripting Oolite with JavaScript|script.js]]'' is the successor of [[script.plist]] in JavaScript.It will be loaded in preference to script.plist if both exist.&lt;br /&gt;
* ''[[shipdata.plist]]'' that introduces any new entity (ships, stations, objects etc.) to Oolite.&lt;br /&gt;
* ''[[shipdata-overrides.plist]]'' that selectively can replace shipentries in other shipdata.plists&lt;br /&gt;
* ''[[shiplibrary.plist]]'' that gives information for the ship description library viewable from the startup screen (v1.79)&lt;br /&gt;
* ''[[shipyard.plist]]'' that introduces new ships available for player purchase.&lt;br /&gt;
* ''[[shipyard-overrides.plist]]'' that selectively can replace shipentries in other shipyard.plists&lt;br /&gt;
* ''[[speech_pronunciation_guide.plist]]'' is another of the other custom methods.&lt;br /&gt;
* ''[[trade-goods.plist]]'' defines trade goods in 1.81 and later&lt;br /&gt;
* ''[[world-scripts.plist]]'' that contains a list of scripts (if more than one worldScript should be used).&lt;br /&gt;
&lt;br /&gt;
Deprecated:&lt;br /&gt;
* ''[[commodities.plist]]'' that contains information for each commodity in a market in 1.80 or earlier&lt;br /&gt;
* ''[[demoships.plist]]'' that selects demoships to show on startup (replaced - approximately - by shiplibrary.plist in 1.79 and later)&lt;br /&gt;
* ''[[illegal_goods.plist]]'' that contains a list of banned/forbidden items in 1.80 or earlier. GalCop has an eye on that.&lt;br /&gt;
* ''[[Oolite_Keyboard_Controls|keyconfig.plist]]'' that allows for changes of the keymapping. (deprecated in v1.92)&lt;br /&gt;
* ''[[pirate-victim-roles.plist]]'' that defines which roles should act as traders. (deprecated in v1.79)&lt;br /&gt;
* ''[[script.plist]]'' to handle conditional ''script actions''. (deprecated)&lt;br /&gt;
* ''[[script.oos]]'' was briefly introduced during 1.70 development but is now deprecated in favour of JS.)&lt;br /&gt;
&lt;br /&gt;
=== Models folder===&lt;br /&gt;
Oolite models need to be in an Oolite specific format using the the '''.dat''' file extension. There are utilities available that convert models made in Wings 3D (.obj) and Meshwork (.mesh) into this. A .dat file can be opened in a plain text editor to view the object's assigned texture names and see that they correspond with the actual file names in the Textures folder. The .dat file must be named exactly as it is referenced in the shipdata ''model'' entry - case sensitive!!!&lt;br /&gt;
&lt;br /&gt;
* [[OXP howto model|Making Oolite models]] - tutorials for Wings3D &amp;amp; Blender, notes on sub-entities, links ''etc''.&lt;br /&gt;
* [https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=12165 Model Converter utilities] (2012-17)&lt;br /&gt;
* Video: [https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=16123 From scratch to Mamba in under an hour] ([[Dertien]], 2013)&lt;br /&gt;
&lt;br /&gt;
===Scripts folder===&lt;br /&gt;
Scripts are in text format. In this folder you can put both JavaScript scripts as well as legacy scripts. New OXPs should only use JavaScript here.&lt;br /&gt;
* [[Scripting_Oolite_with_JavaScript|Scripting Oolite with Javascript]]&lt;br /&gt;
* [[Oolite_JavaScript_object_model|Scripting reference]]&lt;br /&gt;
&lt;br /&gt;
===Textures folder===&lt;br /&gt;
&lt;br /&gt;
Oolite's textures are in the '''.png''' format, usually at a standard 512x512 size, and must be named exactly as they are named in the .dat file. &lt;br /&gt;
&lt;br /&gt;
* [[OXP howto texture|Making Oolite textures]]&lt;br /&gt;
&lt;br /&gt;
* [[Smivs'_texture_tutorial|Smivs' guide to making Oolite textures]]&lt;br /&gt;
&lt;br /&gt;
* [[Texturing tips and tricks by Theta Seven]]&lt;br /&gt;
&lt;br /&gt;
Viewing a specific texture and / or model in Oolite.&lt;br /&gt;
&amp;quot;I made one. How do I proof it?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* [[Viewing a Texture or Model]]&lt;br /&gt;
&lt;br /&gt;
==Tool: OXP Verifier==&lt;br /&gt;
&lt;br /&gt;
Oolite has what amounts to a spell checker for shipdata.plist and some other plists, called the OXP verifier. &lt;br /&gt;
&lt;br /&gt;
*It does not work with OXZ's (so convert your OXP's to OXZ's later!).&lt;br /&gt;
*Nor does it work on the standard game release version of Oolite (v.1.90, v.1.92 ''etc''). Only on the Test Release/Developer's Release version ''and'' on the Nightlies/Pre-Releases (v.1.91, v.1.93 ''etc''.)&lt;br /&gt;
&lt;br /&gt;
The verifier detects unknown keys or wrong use of keys ''etc''. It can currently only be invoked from the command line. &lt;br /&gt;
&lt;br /&gt;
On Windows or Linux: &lt;br /&gt;
Code: &lt;br /&gt;
'''oolite.app/oolite --verify-oxp &amp;lt;path to OXP&amp;gt; '''&lt;br /&gt;
&lt;br /&gt;
On Mac OS X: &lt;br /&gt;
Code: &lt;br /&gt;
'''Oolite.app/Contents/MacOS/Oolite --verify-oxp &amp;lt;path to OXP&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
Most Mac users will not be familiar with using the command line. Look inside your application folder for a '''utilities folder'''. Inside that you will find a program called [https://en.wikipedia.org/wiki/Terminal_(macOS) Terminal]. &amp;lt;br&amp;gt;&lt;br /&gt;
Run it to open a terminal window. Now drop the oolite application on that window. That will generate the path to oolite on the command line. Delete the trailing space and paste the following text - including the trailing space- behind it: &amp;quot;/Contents/MacOS/Oolite --verify-oxp &amp;quot;.  Now drop the oxp you want to verify on the window. That will again create the path to the oxp behind the last entry. &amp;lt;br&amp;gt;&lt;br /&gt;
When you select the window and hit the &amp;lt;return&amp;gt; key, the verification will start. It should now open the Console program, showing the results. &amp;lt;br&amp;gt;&lt;br /&gt;
'''Console''' is a log viewer developed by Apple Inc. and included with macOS, also in the utilities folder. It allows users to search through all of the system's logged messages, and can alert the user when certain types of messages are logged. The Console is generally used for troubleshooting when there is a problem with the computer. MacOS itself, as well as any applications that are used, send a constant stream of messages to the system in the form of log files. The console allows you to read the system logs, help find certain ones, monitor them, and filter their contents. See [[Debug OXP]] for more information.&lt;br /&gt;
&lt;br /&gt;
There is a lengthy file - '''OXP verifier design.txt''' tucked inside your Oolite installation with more information about it&lt;br /&gt;
&lt;br /&gt;
Note that it is possible to [https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21443 obtain graphical output] from Graphviz for OXP Verifier.&lt;br /&gt;
&lt;br /&gt;
=== Verifier BB threads ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=8&amp;amp;t=13400 plist Editor Pro for Windows] (2013 - full of relevant Red Herrings)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=3&amp;amp;t=16865 lite --verify-oxp fails when path has spaces in it] (2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=21359 OXP Develoopment and Plist files] (2023 - quick introduction)&lt;br /&gt;
&lt;br /&gt;
=== Correcting with plutil (Apple Macintosh Terminal utility) ===&lt;br /&gt;
Since a very small mistake is enough to stop a .plist from being accepted, it's important to be exact about every letter and sign. The Mac Terminal utility has a very practical tool for catching parser errors. After opening Terminal, simply type plutil, add one space, and drag and drop the plist in question onto the Terminal window. This will cause the 'address' of the plist to be shown. Hit return, and Terminal will reveal whether or not the plist is OK. If it's not, you might be given a clue to what is wrong, and the line number of the error - or just a general note that &amp;quot;Unexpected character { at line 1&amp;quot;!&lt;br /&gt;
&lt;br /&gt;
==Need for unique names==&lt;br /&gt;
On loading the oxps, Oolite will add all files in the AIs, Models, Sound and Scripts folders in one big folder for its own use. That means that all files need unique names or one file will overwrite another with the same name. Files in Textures are not pre-loaded, but when looking for a specific texture Oolite looks in all Texture folders until it finds a texture file with a matching name. If another oxp contains a texture with identical name, Oolite could use that texture.&lt;br /&gt;
&lt;br /&gt;
For the Config folder something similar happens. Here the plists all have the same name, but the content  of all oxp plists is loaded per type in one big plist. e.g. all individual shipData.plist go in one big shipData.plist file. And within a single plist, all keys must be unique. When two plists use the same key, the later loading key will overwrite the former.&lt;br /&gt;
&lt;br /&gt;
Generally it is a good habit to precede your chosen filenames and keys with the name of the oxp, or another unique prefix, to make sure the names stay unique and no other oxp will use the same names.&lt;br /&gt;
&lt;br /&gt;
==Scripting with JavaScript==&lt;br /&gt;
Older OXPs (from [[User:Aegidian|Aegidian]]'s day were written in Legacy Script: see [[Methods]]. Modern OXPs are written in JavaScript. Specifically oolite.jsVersion 185, an Oolite specific variant of '''ECMAv5'''. It is the same Spidermonkey version that Firefox 4 shipped with many years ago, but it is a special build for Oolite. This is the version that we have almost always had and it has not changed between versions of the game. [https://bb.oolite.space/viewtopic.php?p=256623#p256623 It is unlikely to change] in the future.&lt;br /&gt;
&lt;br /&gt;
JavaScript is the preferred scripting interface for worldScripts and shipScripts. The legacy scripting interface (see [[script.plist]]) still works, but is not supported. See [[Scripting Oolite with JavaScript]] for more information.&lt;br /&gt;
&lt;br /&gt;
Note that most of the [[Legacy Scripting]] still works perfectly well (XML &amp;amp; OpenStep)!&lt;br /&gt;
&lt;br /&gt;
==Hidden settings==&lt;br /&gt;
There are several [[Hidden_Settings_in_Oolite]] that make life for an oxp creator easier. One of them is the setting '''always-flush-cache'''. It makes every startup a bit slower, but it prevents Oolite working with cached data instead of your newly changed file. For someone that only does occasional oxp changes it will be enough to flush the cache by holding the shift key when starting Oolite but if you are writing oxps, this is the way to prevent frustrations.&lt;br /&gt;
&lt;br /&gt;
==Cookbook==&lt;br /&gt;
* How to add dials to a HUD: https://bb.oolite.space/viewtopic.php?p=290352#p290352&lt;br /&gt;
* How to limit a station's shipyard to only offer a defined set of ships: https://bb.oolite.space/viewtopic.php?p=293174#p293174&lt;br /&gt;
* Ship/Station design with external docking ports: https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=21574&amp;amp;p=293777&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
*'''Context''': [https://bb.oolite.space/viewtopic.php?p=275434#p275434 What can OXP's ''not'' change?] (2021)&lt;br /&gt;
*It is often helpful to dip one's toes (claws?) in the water by experimenting with tweaking oxp's first: see [[How to tweak OXZ's]]&lt;br /&gt;
*[[:Category:Oolite scripting]]&lt;br /&gt;
*[[Javascript Operators]]&lt;br /&gt;
*[[:Category:Oolite JavaScript Reference‎]]&lt;br /&gt;
*[[:Category:Oolite Development]]&lt;br /&gt;
*[[User:Montana05|Montana05]] recommends https://www.w3schools.com/js/js_array_sort.asp for better knowledge of the js on Oolite.&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=12149 OXP Development Best Practices] (2012-7)&lt;br /&gt;
*Some older oxp's are written in [[Legacy Scripting]]&lt;br /&gt;
*[https://github.com/OoliteProject/oolite/find/master Github] vanilla game code repository - the resources section at the bottom of the page contains possibly useful parts of vanilla game coding, with occasional annotations.&lt;br /&gt;
=== Tools ===&lt;br /&gt;
*[[List of software]] that is helpful for creating OXPs (eg. editorial packages for javascript or 3D model creators)&lt;br /&gt;
*[[List of Planets used in OXPs]] for planets already used by other OXPs. Helps authors avoid overlapping with or breaking other OXPs.&lt;br /&gt;
*[[OXP_howto_Game_Balance|OXP howto Game Balance]] to avoid conflicts from accidental gameplay changes.&lt;br /&gt;
*[[Long Range Scanner]] is an OXP which allows you to jump around the star system to objects you have placed there - or to jump around within the galaxy. A &amp;quot;cheat&amp;quot; for players, but a useful tool for some OXP designers.&lt;br /&gt;
&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=13422 What Tools Are Good For Windows OXP Programming?] (2013)&lt;br /&gt;
&lt;br /&gt;
==== Tutorials for Tools ====&lt;br /&gt;
*[https://web.archive.org/web/20050317033938/http://oolite.aegidian.org/cyoship/ Oolite Tutorial - Meshwork Shipbuilding (OSX only)] via WayBack Machine&lt;br /&gt;
*[https://web.archive.org/web/20060621211940/http://oolite.aegidian.org/cyoship2/ Oolite Tutorial - Wings 3D Shipbuilding (Cross-platform)] via WayBack Machine&lt;br /&gt;
&lt;br /&gt;
=== OXP tutorials ===&lt;br /&gt;
Oolite changes affecting different varieties of OXPs happened with v.1.76 (2011), v.1.80 (2014) &amp;amp; v1.82 (2015).&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20937 MasterClass: How to OXP (updating SoThisTC)] by [[User:Spara|Spara]] who teaches computing in Helsinki! (2021)&lt;br /&gt;
*[https://archive.org/details/GettingStartedWithOoliteOXZDevelopment Getting started with OXZ Development] ''An .odt for Open Office'': By Bugbear (2012). 2 example OXPs: a pirate-ridden solar systems warning tool &amp;amp; Witchspace Blockades [https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17731 BB Thread (2015)]&lt;br /&gt;
*[[OXP_tutorial|OXP Tutorial]] creating a new spaceship - and then tweaking it in different ways (2007-13)&lt;br /&gt;
*[[OXP howto dockable stations|Creating a dockable station]] (2009-10)&lt;br /&gt;
*[[User:Shipbuilder|Shipbuilder]] wrote a Shaders tutorial with resource packs (2013)&lt;br /&gt;
&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=18837 OXP Performance] BB thread (mostly 2017-8): improving your OXP (speed, ''etc'')&lt;br /&gt;
&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=18284 The bare minimum for a game-recognizable ship OXP] (thread: 2016)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=14135 How to make a simple OXP?] (thread: 2013) 3 OXPs - pop-up message at docking, set only Pythons for sale at Lave shipyard, create a new ship. &lt;br /&gt;
&lt;br /&gt;
*[[Escape Pod Locator OXP]] has notes on programming on the bottom of the page regarding beacon transmission &amp;amp; location&lt;br /&gt;
&lt;br /&gt;
=== Helpful OXPs for your OXP===&lt;br /&gt;
There are a number of OXPs which have been specifically written to allow your OXP to use them:&lt;br /&gt;
*[[Library OXP|Library]]: a collection of useful snippets and helpers. Its main purpose is to simplify or unify some common tasks used by OXPers. &lt;br /&gt;
:*It can add dynamic maps, music &amp;amp; animation. &lt;br /&gt;
:*It adds a Personal Assistant Device for the player with details of people met, medals awarded, Guild rankings, ''etc''.&lt;br /&gt;
:*It allows in-game configuration of an oxp by the player.&lt;br /&gt;
:*Add-on modules allows inspection of models and materials for creation of ship &amp;amp; station oxps.&lt;br /&gt;
*[[GalCop Missions]] introduces many new pieces of equipment with wide varieties of use (Cargo Stoppers, Ejection Dampers, Range Finders, Solar Radiation Disrupter Missiles, Seismic Resonance Scanners, Patient Transport Modules ''etc''). It can also help with managing missions.&lt;br /&gt;
*[[Diplomancy]] can be used to make states of war impact personally on the player&lt;br /&gt;
*[[System Data Config]] helps re-organise the F7 screen to squeeze more information onto it&lt;br /&gt;
&lt;br /&gt;
==== While docked/stations ====&lt;br /&gt;
*[[HD Backgrounds]] can provide a High Definition screenshot of a station lobby or other such for interaction with the player&lt;br /&gt;
*[[BGS]] can help organise a customised docking or launching sequence (see the [[Riredi OXP]] or the [[Kiota Stations]]).&lt;br /&gt;
*[[GNN]] can broadcast your news alerts (see how [[Diplomancy]] uses it for war &amp;amp; peace declarations). GNN also contains '''PhraseGen''' which can be used for randomizing text descriptions.&lt;br /&gt;
*[[Station Validator]] will remember that a station has been destroyed and stop Oolite automatically replacing it on the next visit to the system&lt;br /&gt;
*[[Station Dock Control]] can help interraction with other ships docked at the station&lt;br /&gt;
*[[Bulletin Board System]] can help manage interractions at the station&lt;br /&gt;
*[[Email System OXP]] can also help manage interractions at the station&lt;br /&gt;
*[[Ship Storage Helper]] allows storage of the player's ship whilst doing other things (such as flying another ship!)&lt;br /&gt;
*[[Equipment Storage OXP]]  allows storage of equipment/goods whilst doing other things&lt;br /&gt;
*[[Ship's Library]] allows reading documents with illustrations while docked (see the included Ship's Manual)&lt;br /&gt;
*[[Station Options]] allows complex configurations of equipment, but could potentially also be used for managing dialogue with NPCs&lt;br /&gt;
*[[Life in the Frontier]] was being expanded to cover more stations (Dodo/Ico/Rock Hermits and potentially OXP stations), but is currently mothballed. &lt;br /&gt;
&lt;br /&gt;
==== In-flight ====&lt;br /&gt;
*[[MFD - Broadcast Comms]] can be used for in-flight interaction with NPC's&lt;br /&gt;
*[[Bigships]] can be used to help with the AI for massive space ships which cannot dock at orbital stations&lt;br /&gt;
*[[Montanas Resource Pack 01]] contains a number of resources for use (treasures, containers, escape/survival equipment)&lt;br /&gt;
*[[Star System Lane Indicator]] - the older version contains a very graphical dynamic display (does not function properly, but boy! does it look good!)&lt;br /&gt;
*[[SOTL Exploration]] contains exploration equipment and a non-automatic hyperspace jump&lt;br /&gt;
*[[SOTL Altmap]] contains different politics, markets and NPCs with Torus Drives.&lt;br /&gt;
*[[Resistance Commander]] &amp;amp; [[EscortDeck]] contain mechanisms for &amp;quot;managing&amp;quot; allied ships.&lt;br /&gt;
&lt;br /&gt;
==== Planet Surfaces ====&lt;br /&gt;
*[[Planetfall OXP]] allows landing on the planet (used by [[Feudal States]] for access to the Royal Court, and by [[Astronaut]] for space-jumping)&lt;br /&gt;
*[[Lave is Earth 8k]] contains night-time city lighting&lt;br /&gt;
&lt;br /&gt;
=== Packaging and distribution ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=16688 The All-in-One Guide to OXZ Packaging and Distribution].&lt;br /&gt;
::And see [https://bb.oolite.space/viewtopic.php?p=279034#p279034 this post] for AppleMac issues with the above.&lt;br /&gt;
* Cim created [https://github.com/cim--/oxp-build-scripts some scripts to ease packaging] a project.&lt;br /&gt;
*[[OXP Distribution]] The All-in-One Guide to OXP Packaging and Distribution (and [[OXP_standards]] for advice on which ways of doing things are supported and which are not).&lt;br /&gt;
* Since the domain change to [https://oolite.space] the distribution of expansions has changed slightly. The new version is still subject to discussions and might change again. Here is a [[Publishing Procedure Comparison]].&lt;br /&gt;
*[[Gameplay_and_Balance_Indicator|Gameplay Balance Indicator]] and [[OXP_Levelindicators|Difficulty Indicator]]. Add these to your wiki page to show effects on Game Balance and the Difficulty Level of your OXP/OXZ. The '''first''' indicates the impact on play (equipment making the game easier/more difficult), the '''second''' indicates the suggested [[Elite Rating]] needed to attempt the mission/defeat the ship ''etc''.&lt;br /&gt;
&lt;br /&gt;
[[Category:Oolite]]&lt;br /&gt;
[[Category:Oolite scripting]]&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89462</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89462"/>
		<updated>2026-06-18T16:21:09Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Using the new Trade-goods.plist */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:SOTL Altmap F8.png|thumb|right|300px|The ''first'' page of commodities from [[SOTL Altmap]], Cim's 2014 experimental scenario]]&lt;br /&gt;
'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The Primary market is that of the main orbital station of the system. The Secondary markets are other station/dockable markets (which are influenced by the primary market), ''eg'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, assuming no market_script is defined:&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89461</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89461"/>
		<updated>2026-06-18T16:17:17Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:SOTL Altmap F8.png|thumb|right|300px|The ''first'' page of commodities from [[SOTL Altmap]], Cim's 2014 experimental scenario]]&lt;br /&gt;
'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The Primary market is that of the main orbital station of the system. The Secondary markets are other station/dockable markets (which are influenced by the primary market), ''eg'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, assuming no market_script is defined:&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the new Trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89460</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89460"/>
		<updated>2026-06-18T15:57:35Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* A new commodity (from the Trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:SOTL Altmap F8.png|thumb|right|300px|The ''first'' page of commodities from [[SOTL Altmap]], Cim's 2014 experimental scenario]]&lt;br /&gt;
'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The Primary market is that of the main orbital station of the system. The Secondary markets are other station/dockable markets (which are influenced by the primary market), ''eg'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, assuming no market_script is defined:&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the new Trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Trade-goods.plist]] which combined the following two .plists:&lt;br /&gt;
:*Legacy script: [[Commodities.plist]]&lt;br /&gt;
:*Legacy script: [[Misc_plists#illegal_goods.plist|illegal goods.plist]]&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89458</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89458"/>
		<updated>2026-06-18T15:42:53Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Overview */ Definition corrected.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The '''trade-goods.plist''' file is a dictionary of dictionaries, with (canonical) commodity names as keys to dictionaries of key-value pairs defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The Primary market is that of the main orbital station of the system. The Secondary markets are other station/dockable markets (which are influenced by the primary market), ''eg'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, assuming no market_script is defined:&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the Trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the new Trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Trade-goods.plist]] which combined the following two .plists:&lt;br /&gt;
:*Legacy script: [[Commodities.plist]]&lt;br /&gt;
:*Legacy script: [[Misc_plists#illegal_goods.plist|illegal goods.plist]]&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89446</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89446"/>
		<updated>2026-06-18T11:34:24Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Using the Trade-goods.plist */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The Trade-goods.plist file is a dictionary, with keys as commodity keys, and values defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The Primary market is that of the main orbital station of the system. The Secondary markets are other station/dockable markets (which are influenced by the primary market), ''eg'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, assuming no market_script is defined:&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the Trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the new Trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
To tweak the pricing/availability of commodities in (''eg''.) a station, you need to define the market inside the station's Shipdata.plist - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript Oolite Market Script (which allows more complex definitions). &lt;br /&gt;
&lt;br /&gt;
From Oolite 1.81 it is possible for Javascript to be used to modify station, system and trade good prices. It is possible that a single trade good price/quantity calculation may be affected by more than one script. The order of events in the calculation is as follows:&lt;br /&gt;
&lt;br /&gt;
# Firstly, the primary system market is calculated&lt;br /&gt;
## The trade good price and quantity are generated from the values in [[trade-goods.plist]]&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called to set primary market data for the trade good&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the system's [[Planetinfo.plist#market_script|market_script]] will be called to modify primary market data for the trade good.&lt;br /&gt;
# Secondary markets are then calculated for each non-main station&lt;br /&gt;
## The primary system market is copied into the secondary market, and then quantities are scaled to the station's market capacity&lt;br /&gt;
## If the station does not have a market script, the rules in its [[shipdata.plist#market_definition|market_definition]] are applied.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateGeneralCommodityDefinition&amp;lt;/code&amp;gt; handler of the commodity's [[Trade-goods.plist#market_script|market_script]] will be called again to set secondary market data for the trade good.&lt;br /&gt;
## The &amp;lt;code&amp;gt;updateLocalCommodityDefinition&amp;lt;/code&amp;gt; handler of the station's [[shipdata.plist#market_script|market_script]] will be called to modify secondary market data for the trade good.&lt;br /&gt;
&lt;br /&gt;
== Handlers ==&lt;br /&gt;
&lt;br /&gt;
=== updateGeneralCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateGeneralCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the trade good, and is applied once for each market that good appears at. It may be called twice for the same good - once with station = &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to set the primary market, and once with station = (Station) for each secondary market. In general distinguishing between these two cases and performing different modifications will be necessary.&lt;br /&gt;
&lt;br /&gt;
=== updateLocalCommodityDefinition ===&lt;br /&gt;
{{oolite-method-added|1.81}}&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition : Object, station : [[Oolite_JavaScript_Reference:_Station|Station]], system : Int) : Object&lt;br /&gt;
This method takes an object containing the current good definition (keys as in [[trade-goods.plist]], with an additional &amp;quot;price&amp;quot; key for the current price, &amp;quot;quantity&amp;quot; for the current quantity, and &amp;quot;key&amp;quot; for the identifier of the trade good in the plist), carries out modifications to it based on the station and system, and returns the object in the same format.&lt;br /&gt;
&lt;br /&gt;
In general this method should only modify the &amp;quot;price&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;capacity&amp;quot;, &amp;quot;legality_export&amp;quot; and &amp;quot;legality_import&amp;quot; keys of the goodDefinition object. Modifying other keys is possible but significant caution should be used when doing so.&lt;br /&gt;
&lt;br /&gt;
This method is called for scripts defined for the system or station, and is called once for each good in that market. To allow the same script to be applied to multiple systems or stations, the station and system parameters will give the current context.&lt;br /&gt;
&lt;br /&gt;
[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17621#p239979 Here is an example] of how to use this method.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Trade-goods.plist]] which combined the following two .plists:&lt;br /&gt;
:*Legacy script: [[Commodities.plist]]&lt;br /&gt;
:*Legacy script: [[Misc_plists#illegal_goods.plist|illegal goods.plist]]&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
*Phkb's update of [[SW_Economy]] (v.3.10) creates new economies for &amp;quot;mining worlds&amp;quot; (hewn out from some low tech poor agricultural worlds) with utterly different price scales for mineral, agricultural &amp;amp; industrial goods, as well as medicine.&lt;br /&gt;
&lt;br /&gt;
''These others will be found at the bottom of the wiki page on the'' [[Trade-goods.plist]]. &lt;br /&gt;
*Setting an orbital main station's slaves on sale to zero&lt;br /&gt;
*Creating an invariant market independent of the local system economy (agricultural/industrial)&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89444</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89444"/>
		<updated>2026-06-18T10:26:06Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Using the new Trade-goods.plist */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The Trade-goods.plist file is a dictionary, with keys as commodity keys, and values defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The Primary market is that of the main orbital station of the system. The Secondary markets are other station/dockable markets (which are influenced by the primary market), ''eg'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, assuming no market_script is defined:&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the Trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the new Trade-goods.plist ==&lt;br /&gt;
The trade-goods.plist was designed to make commodities simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Oolite]]&lt;br /&gt;
[[Category:Oolite scripting]]&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89443</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89443"/>
		<updated>2026-06-18T09:44:33Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Preamble */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|market script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The Trade-goods.plist file is a dictionary, with keys as commodity keys, and values defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The Primary market is that of the main orbital station of the system. The Secondary markets are other station/dockable markets (which are influenced by the primary market), ''eg'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, assuming no market_script is defined:&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the Trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the new Trade-goods.plist ==&lt;br /&gt;
The original commodities.plist was really not very good - it was based very strongly on the original Elite 84 pricing algorithm, which was written to use peculiarities of 8-bit Maths to its advantage. So one ended up with a series of fairly incomprehensible integers defining each market.&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist was designed to make that simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Oolite]]&lt;br /&gt;
[[Category:Oolite scripting]]&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89442</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89442"/>
		<updated>2026-06-18T09:43:08Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Preamble */  Improved.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file defines &amp;quot;trade goods&amp;quot; (commodities/cargo). But, it does not ''e.g.'' remove slaves from a particular station or make them cost twice as much as they do at the main orbital station. To do such things, ''i.e.'' to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station, either within its [[Shipdata.plist]] or within a [[Oolite_Market_Scripts|Oolite Market Script]] linked from its shipdata.plist.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The Trade-goods.plist file is a dictionary, with keys as commodity keys, and values defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The Primary market is that of the main orbital station of the system. The Secondary markets are other station/dockable markets (which are influenced by the primary market), ''eg'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, assuming no market_script is defined:&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the Trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the new Trade-goods.plist ==&lt;br /&gt;
The original commodities.plist was really not very good - it was based very strongly on the original Elite 84 pricing algorithm, which was written to use peculiarities of 8-bit Maths to its advantage. So one ended up with a series of fairly incomprehensible integers defining each market.&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist was designed to make that simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Oolite]]&lt;br /&gt;
[[Category:Oolite scripting]]&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89441</id>
		<title>Trade-goods (abridged)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Trade-goods_(abridged)&amp;diff=89441"/>
		<updated>2026-06-18T08:22:49Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: Starting page created.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''You are probably looking for [[Trade-goods.plist]]''', rather than this page.&lt;br /&gt;
&lt;br /&gt;
== Preamble ==&lt;br /&gt;
This merely re-defines the trade commodities in the game (''eg'' introducing new ones, or changing elements of the vanilla game ones). See [[SW Economy]] for an example of what can be done. &lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist file replaces and extends the old [[commodities.plist]] and [[illegal_goods.plist]] files from Oolite 1.81 onwards to allow greater flexibility in trade good definitions, including defining entirely new goods. But it does not remove slaves from a particular station or make them cost twice as much as they do at the main orbital station.&lt;br /&gt;
&lt;br /&gt;
To do other things, ''eg''. to tweak the pricing/availability of commodities in a particular station, you need to define the market inside that station's [[Shipdata.plist]] - or include a &amp;quot;hook&amp;quot; inside that shipdata.plist to a javascript [[Oolite_Market_Scripts|Oolite Market Script]] (which allows more complex definitions).&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The Trade-goods.plist file is a dictionary, with keys as commodity keys, and values defining the quantities, prices and other properties of those commodities.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name food]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-edible&amp;quot;,&amp;quot;oolite-farming&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 0;  // 0=t&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7; // Poor Ag&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0; // Rich Ind&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 50; // decicredits&lt;br /&gt;
 		// fraction of average ~= 2.75 credits&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.55;&lt;br /&gt;
 		// fraction of average ~= 0.2 credits&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 13.5; // gets rounded&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 0.52;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 0.04;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 100;&lt;br /&gt;
 	};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The following keys are accepted within a commodity definition&lt;br /&gt;
&lt;br /&gt;
== Property keys ==&lt;br /&gt;
&lt;br /&gt;
=== capacity ===&lt;br /&gt;
The maximum amount of this good which can be held at a main station market. The default is 127 units.&lt;br /&gt;
&lt;br /&gt;
=== classes ===&lt;br /&gt;
An array of good class names. Good classes can be used by secondary stations to set pricing rules for groups of goods.&lt;br /&gt;
&lt;br /&gt;
The following classes are defined by Oolite, with the core goods in those classes also listed. OXPs should usually add these classes as appropriate to custom trade goods they create, and may also define their own classes (which should be given an OXP-specific prefix). Some built-in classes only contain one built-in good, to allow for easier sub-typing by OXPs.&lt;br /&gt;
&lt;br /&gt;
* '''oolite-alien''': goods which were not made by a Cooperative species (Alien Items)&lt;br /&gt;
* '''oolite-animalproduct''': goods which are obtained from animals but are not themselves animals (Furs)&lt;br /&gt;
* '''oolite-business''': goods which are usually obtained for industrial or other corporate use (Computers, Machinery, Alloys, Minerals, Gold, Platinum)&lt;br /&gt;
* '''oolite-consumer''': goods often obtained for personal use (Food, Textiles, Liquor/Wines, Luxuries, Narcotics, Furs, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-dangerous''': goods which may be hazardous (Radioactives, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-edible''': goods which can be eaten reasonably safely (Food, Liquor/Wines)&lt;br /&gt;
* '''oolite-farming''': goods which are produced by farming or similar agricultural processes (Food, Textiles, Liquor/Wines, Furs)&lt;br /&gt;
* '''oolite-living''': goods which contain living creatures (Slaves)&lt;br /&gt;
* '''oolite-luxury''': goods which are luxuries, usually a subset of oolite-consumer (Luxuries)&lt;br /&gt;
* '''oolite-machinery''': goods which are industrial machinery (Machinery)&lt;br /&gt;
* '''oolite-medical''': goods which may have a medical purpose (Narcotics)&lt;br /&gt;
* '''oolite-metals''': goods which are largely or entirely made of metal (Alloys, Gold, Platinum)&lt;br /&gt;
* '''oolite-military''': goods which are of interest to the military (Firearms, Alien Items)&lt;br /&gt;
* '''oolite-mining''': goods which are produced by mining operations or similar extraction processes (Radioactives, Minerals, Gold, Platinum, Gem Stones)&lt;br /&gt;
* '''oolite-rawmaterials''': goods which are raw materials needing refining to be used further (Minerals)&lt;br /&gt;
* '''oolite-restricted''': goods which are subject to restrictions on trade (Slaves, Narcotics, Firearms)&lt;br /&gt;
* '''oolite-salvage''': goods which are often retrieved from space battles (Slaves, Alloys)&lt;br /&gt;
* '''oolite-shipyard''': goods used in the production of space ships (Computers, Alloys)&lt;br /&gt;
* '''oolite-slaves''': goods which are slaves (Slaves)&lt;br /&gt;
* '''oolite-technological''': goods requiring a high-tech process to produce (Computers, Machinery)&lt;br /&gt;
* '''oolite-thargoid''': goods of Thargoid origin (Alien Items)&lt;br /&gt;
* '''oolite-weapons''': goods which are weapons (Firearms)&lt;br /&gt;
* '''oolite-wearable''': goods which are or can be used to make clothes (Textiles, Furs)&lt;br /&gt;
&lt;br /&gt;
=== comment ===&lt;br /&gt;
A string that will be displayed on the F8 F8 commodity detail screen to describe the commodity. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setComment|manifest.setComment()]]&lt;br /&gt;
&lt;br /&gt;
=== legality_export ===&lt;br /&gt;
This number will be multiplied by the number of units carried when leaving a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
=== legality_import ===&lt;br /&gt;
This number will be multiplied by the number of units carried when entering a main station (or another station which enforces Cooperative market laws). This value will be ORed with the player's bounty.&lt;br /&gt;
&lt;br /&gt;
No core game good is illegal to import.&lt;br /&gt;
&lt;br /&gt;
=== market_script ===&lt;br /&gt;
The name of a Javascript file to use as a [[Oolite Market Scripts|market script]] for this trade good when calculating main station quantities and prices.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' [https://bb.oolite.space/viewtopic.php?p=235837#p235837 What's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist?] (2015)&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
A string containing the name of the trade good. This may contain [keys]s for [[descriptions.plist]] expansion.&lt;br /&gt;
&lt;br /&gt;
=== peak_export ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for buying this good. Economies closer to this economy than the peak_import will also have below-average prices.&lt;br /&gt;
&lt;br /&gt;
=== peak_import ===&lt;br /&gt;
A number from 0 to 7 identifying the economy which will give the best price for selling this good. Economies closer to this economy than the peak_export will also have above-average prices.&lt;br /&gt;
&lt;br /&gt;
=== price_average ===&lt;br /&gt;
The average price of this trade good at a main system station which neither imports nor exports, in decicredits.&lt;br /&gt;
&lt;br /&gt;
=== price_economic ===&lt;br /&gt;
The proportion of the price affected by the system economy. A value of 0 means that this good does not change in price depending on system economy. A value of 0.3 means that the good would be 0.7 times price_average in an ideal exporting system, and 1.3 times price_average in an ideal importing system. While values greater than 1 may be used, in general much lower values are better.&lt;br /&gt;
&lt;br /&gt;
=== price_random ===&lt;br /&gt;
The proportion of the price affected by random factors. A value of 0.6 means that the actual price of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the price_average.&lt;br /&gt;
&lt;br /&gt;
If this value is larger than price_economic, this means that even an ideal trade run from the best exporter to the best importer is not guaranteed to make a profit.&lt;br /&gt;
&lt;br /&gt;
=== quantity_average ===&lt;br /&gt;
The average quantity of this trade good at a main system station which neither imports nor exports, in decicredits. If the calculated quantity exceeds the capacity, it will be capped.&lt;br /&gt;
&lt;br /&gt;
=== quantity_economic ===&lt;br /&gt;
The proportion of the quantity affected by the system economy. A value of 0 means that this good does not change in quantity depending on system economy. A value of 0.3 means that the good would be 0.7 times as frequent in an ideal importing system, and 1.3 times as frequent in an ideal exporting system. A value of 1 or greater will make the good never or rarely (depending on quantity_random) available in systems which import the good.&lt;br /&gt;
&lt;br /&gt;
=== quantity_random ===&lt;br /&gt;
The proportion of the quantity affected by random factors. A value of 0.6 means that the actual quantity of the good in a system which neither imports nor exports may be between 0.4 and 1.6 times the quantity_average.&lt;br /&gt;
&lt;br /&gt;
If this value is greater than 1, then systems may often entirely lack this good. If this value is greater than 1 + quantity_economic, then even an ideal exporter may not have any in stock.&lt;br /&gt;
&lt;br /&gt;
=== quantity_unit ===&lt;br /&gt;
The size of container one unit of this good represents. 0 = tonne; 1 = kilogram; 2 = gram. The default is zero.&lt;br /&gt;
&lt;br /&gt;
=== short_comment ===&lt;br /&gt;
A string that will be displayed on the F8 commodity list screen in the optional extra column. This can be modified later by [[Oolite_JavaScript_Reference:_Manifest#setShortComment|manifest.setShortComment()]]. As the meaning of this value will depend on the OXPs installed, it is unlikely to be useful to specify an initial value in the plist.&lt;br /&gt;
&lt;br /&gt;
=== sort_order ===&lt;br /&gt;
A number positioning the item on the F8 screen when goods are sorted in the default order. The core goods have values 100 to 1700 in steps of 100.&lt;br /&gt;
&lt;br /&gt;
=== trumble_opinion ===&lt;br /&gt;
How likely is a hungry trumble to consider eating this good? Goods with a value of 0 for this will never be eaten by trumbles; other goods may be eaten depending on the value of this parameter and the values for other goods on board.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Secondary Market Definitions ==&lt;br /&gt;
&lt;br /&gt;
The Primary market is that of the main orbital station of the system. The Secondary markets are other station/dockable markets (which are influenced by the primary market), ''eg'' that of a local Rock Hermit, or a visiting liner or another orbital station. Both quantities and prices will be influenced by those of the primary market. Needless to say, the primary market is randomly recalculated each time the system is visited.&lt;br /&gt;
&lt;br /&gt;
Secondary market definitions are entered in the [[shipdata.plist#market_definition|market_definition]] key in shipdata.plist, which is an array of dictionaries, each defining rules which modify the prices and quantities from the main station market, and possibly adjust the market capacity and legality of the good. The following modifications are applied for each trade good, assuming no market_script is defined:&lt;br /&gt;
&lt;br /&gt;
# The market definition array is searched from top to bottom for the first element matching the trade good&lt;br /&gt;
# The market quantity is scaled in proportion to the relative capacities for that good in the two markets.&lt;br /&gt;
# Otherwise, the price and quantity modifications defined in the plist are used.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Matching ===&lt;br /&gt;
&lt;br /&gt;
This uses the 'type' and 'name' properties. Type has three possible values&lt;br /&gt;
&lt;br /&gt;
* type = 'good': the good with the key in trade-goods.plist exactly matching the name property&lt;br /&gt;
* type = 'class': any good in trade-goods.plist with an entry in its [[#classes|classes]] list exactly matching the name property&lt;br /&gt;
* type = 'default': any good. The name property is ignored if present.&lt;br /&gt;
&lt;br /&gt;
'default' should generally only be used for the last entry in the market definition.&lt;br /&gt;
&lt;br /&gt;
=== Secondary Market Modifications ===&lt;br /&gt;
&lt;br /&gt;
The following keys in the chosen market definition are then used to modify the good&lt;br /&gt;
&lt;br /&gt;
==== capacity ====&lt;br /&gt;
The market capacity for this good or set of goods. If omitted, the [[shipdata.plist#market_capacity|default capacity for the station]] will be used.&lt;br /&gt;
&lt;br /&gt;
==== legality_import, legality_export ====&lt;br /&gt;
If present, these keys override the keys of the same name in the basic trade good definition. If omitted, the station will use the same rules as the main station, provided that [[shipdata.plist#market_monitored|its market is monitored at all]]&lt;br /&gt;
&lt;br /&gt;
==== price_adder, price_multiplier, price_randomiser ====&lt;br /&gt;
These keys modify the price in the secondary market. The formula is (in decicredits):&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 secondary_price = MAX(1, (primary_price + price_adder) * (price_multiplier + (price_randomiser * rnd)))&lt;br /&gt;
As an exception, if price_adder and price_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of price_random.&lt;br /&gt;
&lt;br /&gt;
==== quantity_adder, quantity_multiplier, quantity_randomiser ====&lt;br /&gt;
These keys together with the capacity modify the quantity in the secondary market. The formula is:&lt;br /&gt;
 rnd = -1..1 // random number in range -1 to +1, slightly biased towards zero&lt;br /&gt;
 adjusted_quantity = (local_capacity / primary_capacity) * primary_quantity;&lt;br /&gt;
 secondary_quantity = (adjusted_quantity + quantity_adder) * (quantity_multiplier + (quantity_randomiser * rnd)))&lt;br /&gt;
As an exception, if quantity_adder and quantity_multiplier are both &amp;lt;= 0, then the result is always 0 regardless of quantity_random.&lt;br /&gt;
&lt;br /&gt;
=== Links ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=21512 Secondary Market Definitions Defined] (2023)&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Hardly anybody ended up using this! And cim never even put it into his [[New Cargoes]] oxp! Spara wrote a conversion script for the old commodities.plist, and everybody seems to have used that instead for determining markets for new stations.&lt;br /&gt;
&lt;br /&gt;
=== From the vanilla game: Rock Hermits ===&lt;br /&gt;
The &amp;quot;market_definition&amp;quot; from the shipdata.plist in the config folder&lt;br /&gt;
&lt;br /&gt;
 	&amp;quot;oolite_template_rock-hermit&amp;quot; = &lt;br /&gt;
 	{	....&lt;br /&gt;
 		is_carrier = 1;&lt;br /&gt;
 		is_template = 1;&lt;br /&gt;
 		&amp;quot;market_capacity&amp;quot; = 31; // maximum capacity for any good&lt;br /&gt;
 		&amp;quot;market_definition&amp;quot; = (&lt;br /&gt;
 			{&lt;br /&gt;
 				// export cheap mining products&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-mining&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.1;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 3.5;&lt;br /&gt;
 				&amp;quot;quantity_randomiser&amp;quot; = 3.0;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// import supplies a bit&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-edible&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 1.05;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.05;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 15;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need clothes, but usually have enough already&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-wearable&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// sometimes need new mining equipment&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;class&amp;quot;;&lt;br /&gt;
 				&amp;quot;name&amp;quot; = &amp;quot;oolite-machinery&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.8;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.4;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 7;&lt;br /&gt;
 			},&lt;br /&gt;
 			{&lt;br /&gt;
 				// not really interested&lt;br /&gt;
 				&amp;quot;type&amp;quot; = &amp;quot;default&amp;quot;;&lt;br /&gt;
 				&amp;quot;price_multiplier&amp;quot; = 0.55;&lt;br /&gt;
 				&amp;quot;price_randomiser&amp;quot; = 0.25;&lt;br /&gt;
 				&amp;quot;quantity_multiplier&amp;quot; = 0.0;&lt;br /&gt;
 				&amp;quot;capacity&amp;quot; = 3;&lt;br /&gt;
 			}&lt;br /&gt;
 		);&lt;br /&gt;
 		&amp;quot;market_monitored&amp;quot; = no;&lt;br /&gt;
 		....&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== From Cim's oxp: Risk-based Economy (v.2.0: the Trade-goods.plist updated from the original commodities.plist) ===&lt;br /&gt;
 {&lt;br /&gt;
 	&amp;quot;food&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;radioactives&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;liquor_wines&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 	};&lt;br /&gt;
 	&lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;luxuries&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.08;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;computers&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.12;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;machinery&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.05;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alloys&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 158;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.10;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.06;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;firearms&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.20;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;furs&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.25;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 	&amp;quot;alien_items&amp;quot; = {&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.05;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.45;&lt;br /&gt;
 	};&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
=== A new commodity (from the Trade-goods.plist inside &amp;quot;SW Economy&amp;quot;) ===&lt;br /&gt;
 	&amp;quot;medicine&amp;quot; = {&lt;br /&gt;
 		&amp;quot;name&amp;quot; = &amp;quot;[commodity-name medicine]&amp;quot;;&lt;br /&gt;
 		&amp;quot;classes&amp;quot; = (&amp;quot;oolite-consumer&amp;quot;,&amp;quot;oolite-medical&amp;quot;);&lt;br /&gt;
 		&amp;quot;quantity_unit&amp;quot; = 1;&lt;br /&gt;
 		&amp;quot;peak_export&amp;quot; = 7;&lt;br /&gt;
 		&amp;quot;peak_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;price_average&amp;quot; = 640;&lt;br /&gt;
 		&amp;quot;price_economic&amp;quot; = 0.25;&lt;br /&gt;
 		&amp;quot;price_random&amp;quot; = 0.15;&lt;br /&gt;
 		&amp;quot;quantity_average&amp;quot; = 5;&lt;br /&gt;
 		&amp;quot;quantity_economic&amp;quot; = 1.5;&lt;br /&gt;
 		&amp;quot;quantity_random&amp;quot; = 1.0;&lt;br /&gt;
 		&amp;quot;legality_export&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;legality_import&amp;quot; = 0;&lt;br /&gt;
 		&amp;quot;trumble_opinion&amp;quot; = 0.50;&lt;br /&gt;
 		&amp;quot;sort_order&amp;quot; = 500;&lt;br /&gt;
        &amp;quot;comment&amp;quot; = &amp;quot;[oolite-commodity-medicine]&amp;quot;;&lt;br /&gt;
 	};&lt;br /&gt;
&lt;br /&gt;
=== Setting an orbital main station's slaves on sale to zero ===&lt;br /&gt;
[[User:Phkb|Phkb]] provided this example which requires a ''planetinfo.plist'' &amp;amp; a new ''.js file'' - there are other ways to achieve the same result&lt;br /&gt;
====  1) planetinfo.plist (to invoke the market script) ====&lt;br /&gt;
(in the &amp;quot;Config&amp;quot; folder) &lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;0 96&amp;quot; = {market_script = &amp;quot;digebiti_noslaves.js&amp;quot;;};&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== 2) Market script: digebiti_noslaves.js ====&lt;br /&gt;
(in the &amp;quot;Scripts&amp;quot; folder) - note the complex name, which prevents confusion with other snippets of script&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 this.name           = &amp;quot;digebiti_noslaves&amp;quot;;&lt;br /&gt;
 this.author         = &amp;quot;Phkb&amp;quot;;&lt;br /&gt;
 this.copyright      = &amp;quot;(C) 2022 Phkb&amp;quot;;&lt;br /&gt;
 this.licence        = &amp;quot;CC-NC-by-SA 4.0&amp;quot;;&lt;br /&gt;
 this.description    = &amp;quot;Removes slaves for sale in Digebiti&amp;quot;;&lt;br /&gt;
 this.version        = &amp;quot;1.0&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 this.updateLocalCommodityDefinition = function(goodDefinition, station, systemID) {&lt;br /&gt;
     if (goodDefinition.key == &amp;quot;slaves&amp;quot; &amp;amp;&amp;amp; station &amp;amp;&amp;amp; station.isMainStation) {&lt;br /&gt;
         goodDefinition.quantity = 0;&lt;br /&gt;
     }&lt;br /&gt;
     return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This method will work, so long as no other OXP changes the market_script property of the Digebiti system in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Creating an invariant market independent of the local system economy (agricultural/industrial) ===&lt;br /&gt;
If you just use a market_definition in shipdata.plist for the station, then you're merely setting variations on the primary system market.&lt;br /&gt;
&lt;br /&gt;
If you want the station prices to be independent of (or more loosely tied to) the system it's in, then you need to use a [[Oolite_Market_Scripts|market script]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So what you'd have is something like this - let's say it's a hydroponics station, so it always sells food and nothing else, regardless of whether the general system economy is industrial or agricultural:&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
   	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.key == &amp;quot;food&amp;quot;) {&lt;br /&gt;
                // are we calculating the basic Oolite &amp;quot;food&amp;quot; trade good right now? If yes, set our own static prices&lt;br /&gt;
        	goodDefinition.price = 25; // 2.5 credits&lt;br /&gt;
        	goodDefinition.quantity = 80; // lots of food&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now ... the reason that market definitions are preferred to be mutators of the system economy is for two reasons.&lt;br /&gt;
1) it means you can avoid the situation where you end up with two adjacent stations with wildly different prices ... but you can of course handle that in other ways too, station positioning, restricted access, ''etc''.&lt;br /&gt;
2) it makes it easier to handle OXP trade goods:&lt;br /&gt;
 - other OXPs might have added more &amp;quot;food&amp;quot; type goods, ''e.g.'' &amp;quot;Meat&amp;quot; or &amp;quot;Cheese&amp;quot;&lt;br /&gt;
 - you can learn about those and handle them specifically&lt;br /&gt;
&lt;br /&gt;
 } else if (goodDefinition.key == &amp;quot;bobsfoodoxp_cheese&amp;quot;) {&lt;br /&gt;
   // set price and quantity here&lt;br /&gt;
&lt;br /&gt;
... but that means a lot of keeping up with what everyone else is doing with custom goods.&lt;br /&gt;
&lt;br /&gt;
The idea was that for your hydroponics station what you might do instead is something like this&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else {&lt;br /&gt;
                // if not, don't buy or sell any other commodity&lt;br /&gt;
                // TODO: work out what we should import&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So now if another OXP adds Cheese, provided they declare it as &amp;quot;edible&amp;quot;, your station will sell it in high quantities at a big discount, but you don't need to know exactly what the baseline price or quantity was set - so if a food-focused OXP was to add &amp;quot;Wine&amp;quot;, &amp;quot;Fine Wine&amp;quot; and &amp;quot;Vintage Wine&amp;quot; at a range of prices and quantities, you'd be automatically handling those in reasonable line with a combination of the Wine OXP's basic pricing structure and your station OXP's &amp;quot;food primary source market&amp;quot; style, without necessarily needing to know about every future Wine OXP there might be and explicitly set compatibility.&lt;br /&gt;
&lt;br /&gt;
Note in this example we're still zeroing out all non-food goods - OXP included! - regardless of the local economy. Maybe at this point we'd want to include and document a &amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot; trade good class that other OXPs could use, which this station would buy up at higher demand and prices than normal.&lt;br /&gt;
&lt;br /&gt;
 // this is going to get called once for each trade good on the market&lt;br /&gt;
 function updateLocalCommodityDefinition (goodDefinition, station, system) {&lt;br /&gt;
  	// at this point, goodDefinition will contain the trade-goods.plist information on the commodity itself&lt;br /&gt;
 	// and a price and quantity key to say what the processing so far has done in mutating the default system market&lt;br /&gt;
 	// so that might say &amp;quot;price&amp;quot; = 35; &amp;quot;quantity&amp;quot; = 50;&lt;br /&gt;
        // the important thing is that we can just ignore that entirely if we want&lt;br /&gt;
        if (goodDefinition.classes.indexOf(&amp;quot;oolite-edible&amp;quot;) &amp;gt;= 0) {&lt;br /&gt;
                // has this commodity been declared either by Oolite Core or by the OXP that added it as&lt;br /&gt;
                // some sort of food?&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 0.6; // big discount for buying at source&lt;br /&gt;
        	goodDefinition.quantity = 10 + (goodDefinition.quantity * 2); // lots of it, and at least 10t even in heavily industrial systems&lt;br /&gt;
        } else if (goodDefinition.classes.indexOf(&amp;quot;hydroponicsoxp-agriculturalequipment&amp;quot;) &amp;gt;= 0) {     	&lt;br /&gt;
        	// custom class for other OXPs to add specific agricultural equipment e.g. combine harvesters, compost, fertiliser&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.capacity = 16; // buy a small amount only // TODO: raise capacity if price per tonne is low&lt;br /&gt;
         	goodDefinition.quantity = 0; // not selling this&lt;br /&gt;
        } else if (goodDefinition.key == &amp;quot;machinery&amp;quot;) {&lt;br /&gt;
        	// the basic Oolite Machinery commodity isn't in the custom class but we need to buy something if&lt;br /&gt;
        	// no OXPs adding it are installed&lt;br /&gt;
        	goodDefinition.price = goodDefinition.price * 1.3; // better prices here&lt;br /&gt;
        	goodDefinition.quantity = 0; // not selling&lt;br /&gt;
        	goodDefinition.capacity = 16; // small capacity to buy&lt;br /&gt;
        } else {&lt;br /&gt;
                // don't buy or sell any other commodity&lt;br /&gt;
        	goodDefinition.price = 0;&lt;br /&gt;
        	goodDefinition.quantity = 0;&lt;br /&gt;
        	goodDefinition.capacity = 0;&lt;br /&gt;
        }&lt;br /&gt;
        return goodDefinition;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So you can see this one has a mix of using, mutating and overruling the definitions set by the system market and OXP commodity definitions ... with this method you could have a whole bunch of OXPs setting up themed stations, and a whole different bunch adding their own custom commodities, and they'd barely have to know about each other to ensure reasonable consistency and compatibility from someone installing any combination of them. (- by [[User:Cim|Cim]], 2023)&lt;br /&gt;
&lt;br /&gt;
Note: this gives examples for 1 commodity at a time, but not how to easily do that for ALL the commodities on ALL the extra stations in a system.&lt;br /&gt;
&lt;br /&gt;
== Using the new Trade-goods.plist ==&lt;br /&gt;
The original commodities.plist was really not very good - it was based very strongly on the original Elite 84 pricing algorithm, which was written to use peculiarities of 8-bit Maths to its advantage. So one ended up with a series of fairly incomprehensible integers defining each market.&lt;br /&gt;
&lt;br /&gt;
The trade-goods.plist was designed to make that simpler, by:&lt;br /&gt;
:1) Making it a dictionary rather than an unlabelled array so one could tell which parameter was which&lt;br /&gt;
:2) Making the price range for a trade good dependent on more sensible variables, so rather than setting the price range with a bitmask, one set the price and quantity variations dependent on the economy and on random chance.&lt;br /&gt;
&lt;br /&gt;
Compare the v.1.81 trade-goods.plist with a v.1.80 commodities.plist - they were designed to give near-identical market behaviour for the built-in trade goods.&lt;br /&gt;
&lt;br /&gt;
But - that only made it more comprehensible. It didn't really let one do anything particularly different to Elite 84 markets - mostly including the &amp;quot;Rich Industrial -&amp;gt; Poor Agricultural&amp;quot; single spectrum. One can tweak that a bit with peak_export and peak_import to get slightly different shapes (so a good might peak at Poor Industrial rather than Rich Industrial) but it doesn't really give one the option of a third economy type still.&lt;br /&gt;
&lt;br /&gt;
''So how does one introduce a new economic pole, such as a mining industry?''&lt;br /&gt;
&lt;br /&gt;
For that, one needs the scripting support. [[Oolite JavaScript Reference: Market Scripts]]. &amp;lt;br&amp;gt;&lt;br /&gt;
One can quite literally do whatever one likes with the prices that way. One could have every *system* have its own separate economy, which varied over time according to events, what the player had previously traded, ''etc. etc.'' to produce something comparable to Elite Dangerous' economic sim, if that's the route one wanted to go down. Obviously the more complexity one adds the harder it gets to script up, but it's now all possible.&lt;br /&gt;
&lt;br /&gt;
[[File:SOTL Altmap F8.png|thumb|right|200px|SOTL Altmap F8 commodities market]]&lt;br /&gt;
[[SOTL Altmap]] does have an example of it, which basically throws out the original Elite-like algorithm of trade-goods.plist and starts over. It goes *way* beyond just adding a third economy, too.&lt;br /&gt;
&lt;br /&gt;
Basically in SOTL every trade good is tagged in the trade-goods.plist with a bunch of classes&lt;br /&gt;
''e.g.''&lt;br /&gt;
 classes = (&amp;quot;sotl-ex-salvage&amp;quot;,&amp;quot;sotl-im-refining&amp;quot;,&amp;quot;sotl-quantity-high&amp;quot;,&amp;quot;sotl-priceband-3&amp;quot;,&amp;quot;sotl-demand-medium&amp;quot;,&amp;quot;sotl-supply-medium&amp;quot;,&amp;quot;sotl-volatility-low&amp;quot;);&lt;br /&gt;
So that means:&lt;br /&gt;
 - exported by salvage economies&lt;br /&gt;
 - imported by refining economies&lt;br /&gt;
 - high quantity, moderate price, low price volatility&lt;br /&gt;
&lt;br /&gt;
Then the market script uses those classes, rather than the standard pricing variables, to define the economic behaviour.&lt;br /&gt;
:So line 69-74ish: get the current economy description, convert that to the format used in the class name&lt;br /&gt;
:...line 85-90: check for the import and export classes for that economy and see if it's imported or exported&lt;br /&gt;
:...lines 100-120: apply various special conditions, so e.g. the sotl-ims-radiation class checks the planet surface radiation levels (custom property in sysinfo) and if the radiation level is high, imports these goods even if the basic economy isn't interested (e.g. &amp;quot;sotl-ceramics-ind&amp;quot; in the plist)&lt;br /&gt;
:...and then it uses those calculations (and a bunch more of the classes) in the rest of the script to set the price and quantity depending on whether it's an import, an export, or neither&lt;br /&gt;
&lt;br /&gt;
That's massive overkill for just adding a third mining economy, but one would need to work on a similar principle.&lt;br /&gt;
&lt;br /&gt;
:1) Tag every commodity with classes for (import|export|none)-(agricultural|industrial|mining) as appropriate&lt;br /&gt;
:2) Adjust the economy names (there are a few different ways one could do that) so that the 8 economy IDs were allocated to agricultural, industrial and mining economies&lt;br /&gt;
:3) Have a price script which like the SOTL one gets the current economy, looks at the classes list to find out if the commodity is imported or exported or neither, and sets the price and quantity accordingly. One could use the standard price_economic, price_average, price_random properties in the plist to give baseline data to the script if one was not planning to do anything too weird.&lt;br /&gt;
&lt;br /&gt;
{Technically one doesn't need the classes - just have the price script contain a list of goods internally for each economy - but this way if other people add extra trade goods in their own OXPs, they can tag them up for mining economy support too}&lt;br /&gt;
&lt;br /&gt;
All fairly straightforward theoretically.&lt;br /&gt;
&lt;br /&gt;
''The biggest impediment to doing a wholesale reworking of the economic system, is just how incompatible it makes lots and lots of OXP's. In order to override the vanilla commodities as in SOTL, requires setting a script for each in trade-goods.plist. Which is fine if it's the only OXP that wants to play around with commodity prices. As soon as two OXP's try to do the same thing, one gets a conflict and no longer knows which OXP pricing model is in play.''&lt;br /&gt;
&lt;br /&gt;
''For SOTL it's fine, because it uses the scenario system to forcibly eject all other OXP's from use while it's running. But if one wants the OXP to go in the general playing pool set of OXP's, it becomes much more complicated. [[User:Phkb|Phkb]] spent a long time trying to work out why his market script wasn't running, only to find that [[UPS Courier]] was quietly adjusting the markets in certain systems via the planetinfo.plist file. And there are a lot of OXP's that want to play in this space, tweaking prices up or down.''&lt;br /&gt;
&lt;br /&gt;
''Hence one usually abandons using any of the script options, and just tweaks the price after all the scripts have finished playing, ''eg'' in [[Smugglers]]. It was the only way to guarantee getting some sort of bump in a price when wanted.''&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[[Oolite JavaScript Reference: Market Scripts]]&lt;br /&gt;
*[[Commodities.plist]] - the precursor (which still mostly works!). If it doesn't see [https://bb.oolite.space/viewtopic.php?p=246145#p246145 here] (2015)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16828 Proposal for 1.82: support for economic changes] ([[User:Cim|Cim]], 2014)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=2&amp;amp;t=16735 Cim on introducing the Trade-goods.plist and deprecating the commodities.plist] (2014)&lt;br /&gt;
{{QuoteText|Text=Trade goods work is coming along fairly well. As well as plist-coded prices for trade goods, which should handle the simple cases (including a few things not possible with commodities.plist), you can now specify a &amp;quot;market script&amp;quot; which allows you to set prices per trade-good, per station, or per system. If you try to do all three, the following happens: &amp;lt;br&amp;gt;&lt;br /&gt;
1) The per-trade good script sets a standard price and quantity for the system's economy and any other data it considers &amp;lt;br&amp;gt;&lt;br /&gt;
2) The per-system script can then modify this price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
3) The station takes the price and quantity from the system, and scales the quantity to the capacity of the station market &amp;lt;br&amp;gt;&lt;br /&gt;
4) The per-trade good script runs again in &amp;quot;secondary station&amp;quot; mode, to modify the price and quantity again &amp;lt;br&amp;gt;&lt;br /&gt;
5) The per-station script runs to make final adjustments to price and quantity &amp;lt;br&amp;gt;&lt;br /&gt;
Generally one OXP wouldn't do all three, though.|Source=([https://bb.oolite.space/viewtopic.php?p=226722#p226722 Cim in Progress Thread (2014)])}}&lt;br /&gt;
=== Using the Trade-goods.plist ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=20576 How to get the displayName for a commodity in the Main Station Market?] (2020)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Thinking about Planet Income classification] (2015)&lt;br /&gt;
&lt;br /&gt;
{{QuoteText|Text=&lt;br /&gt;
In 1.81 this is a lot easier to OXP - you can introduce as many economies as you like, though you are limited to eight economy symbols (so if you wanted lots of economy types, you might end up with Poor Industrial, Avg Industrial and Rich Industrial sharing a symbol on the map). The trade good pricing scripts can then be used to set up different price categories in different economies (and introduce additional trade goods, or split an existing good into multiple categories, which may be necessary if you're adding more economies).&lt;br /&gt;
&lt;br /&gt;
Resetting economies across the planets is a big change in terms of lines of code, but is also very easy to automate. If OXPers are looking for a scripting tool to use for this sort of automation, then NodeJS or io.js is free and also uses Javascript as its language, so you don't need to learn a new one - and may even be able to share code between your build scripts and your OXP, though I haven't tried that yet.|Source=([https://bb.oolite.space/viewtopic.php?f=6&amp;amp;t=17269 Cim in Planet Income thread (2015)])}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Oolite]]&lt;br /&gt;
[[Category:Oolite scripting]]&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=File:Distant_Riches.png&amp;diff=89433</id>
		<title>File:Distant Riches.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=File:Distant_Riches.png&amp;diff=89433"/>
		<updated>2026-06-16T15:58:14Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: OXP cover art&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
OXP cover art&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Docked_HUDs&amp;diff=89421</id>
		<title>Docked HUDs</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Docked_HUDs&amp;diff=89421"/>
		<updated>2026-06-16T13:27:28Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Sleek, minimalist HUD design when docked. If you use a HUD expansion pack, instead of the standard HUD, check the forum for compatibility notes. The newest version (see at bottom) also acts as an immersive introduction to the complexities of Oolite for new players.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Replaces the HUD of your choice while docked with a minimal HUD showing only &lt;br /&gt;
*fuel gauge (in case you need to refuel) &lt;br /&gt;
*missile display (in case you need to buy more)&lt;br /&gt;
The rest is banished until you launch!&lt;br /&gt;
&lt;br /&gt;
Note: some HUDs do this automatically without the need for this OXP.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
=== Modularized version ===&lt;br /&gt;
&lt;br /&gt;
Version 1.5 will come in 3 components:&lt;br /&gt;
&lt;br /&gt;
 Svelte original: [[File:Docked HUDs.oxz]]&lt;br /&gt;
 Function labels: [[File:Docked HUDs data sources.oxz]]&lt;br /&gt;
 Special effects: [[File:Docked HUDs extras.oxz]]&lt;br /&gt;
&lt;br /&gt;
=== Version 1.4 ===&lt;br /&gt;
&lt;br /&gt;
Recent bloatware: [[File:Docked HUDs.oxz]]&lt;br /&gt;
&lt;br /&gt;
=== Version 1.1 ===&lt;br /&gt;
&lt;br /&gt;
Svelte original: [[File:Wildefire Docked HUDs 1.1.oxz]]&lt;br /&gt;
&lt;br /&gt;
== License ==&lt;br /&gt;
*License: CC-BY-NC-SA 4.0&lt;br /&gt;
*Author: [[User:Wildeblood|Wildeblood]]&lt;br /&gt;
*Version: 1.4.3&lt;br /&gt;
*Required Oolite Version: 1.80&lt;br /&gt;
&lt;br /&gt;
== Tweaking ==&lt;br /&gt;
{{QuoteText|Text=You'll find the fuel bar helpful. I used to have a Docked HUDs OXP with three HUD files. One had the fuel bar, one the missile display, and the last the missile display, very faint (opacity 20% IIRC). There was nothing else on them except the clock, and in later versions the commlog position.&lt;br /&gt;
... Anyway, becoming relevant, I used guiScreenChanged &amp;amp; playerBoughtEquipment, rather than shipDockedWithStation &amp;amp; shipWillLaunchFromStation (which were used by my main HUD), so it was immune to interference by my main HUD script. It first checked player.ship.docked (Do I really need to say that?), then the fuel and, if necessary, missile count and selected need-fuel-hud.plist, need-missiles-hud.plist or missiles-full-hud.plist (a.k.a. need nothing).&lt;br /&gt;
&lt;br /&gt;
To any non-forum-members reading along, I recommend this as a ''my first OXP'' exercise. The script is simple, the HUD files are ridiculously simple, the result looks fairly slick, and putting it all together is just tedious enough to leave you feeling satisfied when you finish!|Source=([https://bb.oolite.space/viewtopic.php?p=231734#p231734 Wildeblood])}}&lt;br /&gt;
&lt;br /&gt;
*See [[How to tweak OXZ's]] for more information on general tweaking&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17217 BB Thread] (2015+)&lt;br /&gt;
*[[HUD]]&lt;br /&gt;
&lt;br /&gt;
== Gameplay and Balance Indicator ==&lt;br /&gt;
[[File:Tag-colour-green.png|right]]&lt;br /&gt;
Great for the aesthetics - but less relevant for gameplay balance!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{HUD-OXP}}&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Docked_HUDs&amp;diff=89420</id>
		<title>Docked HUDs</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Docked_HUDs&amp;diff=89420"/>
		<updated>2026-06-16T13:18:08Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* License */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Sleek, minimalist HUD design when docked. If you use a HUD expansion pack, instead of the standard HUD, check the forum for compatibility notes.&lt;br /&gt;
&lt;br /&gt;
the newest version (see at bottom) also acts as an immersive introduction to the complexities of Oolite for new players.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Replaces the HUD of your choice while docked with a minimal HUD showing only &lt;br /&gt;
*fuel gauge (in case you need to refuel) &lt;br /&gt;
*missile display (in case you need to buy more)&lt;br /&gt;
The rest is banished until you launch!&lt;br /&gt;
&lt;br /&gt;
Note: some HUDs do this automatically without the need for this OXP.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
=== Modularized version ===&lt;br /&gt;
&lt;br /&gt;
Version 1.5 will come in 3 components:&lt;br /&gt;
&lt;br /&gt;
 Svelte original: [[File:Docked HUDs.oxz]]&lt;br /&gt;
 Function labels: [[File:Docked HUDs data sources.oxz]]&lt;br /&gt;
 Special effects: [[File:Docked HUDs extras.oxz]]&lt;br /&gt;
&lt;br /&gt;
=== Version 1.4 ===&lt;br /&gt;
&lt;br /&gt;
Recent bloatware: [[File:Docked HUDs.oxz]]&lt;br /&gt;
&lt;br /&gt;
=== Version 1.1 ===&lt;br /&gt;
&lt;br /&gt;
Svelte original: [[File:Wildefire Docked HUDs 1.1.oxz]]&lt;br /&gt;
&lt;br /&gt;
== License ==&lt;br /&gt;
*License: CC-BY-NC-SA 4.0&lt;br /&gt;
*Author: [[User:Wildeblood|Wildeblood]]&lt;br /&gt;
*Version: 1.4.3&lt;br /&gt;
*Required Oolite Version: 1.80&lt;br /&gt;
&lt;br /&gt;
== Tweaking ==&lt;br /&gt;
{{QuoteText|Text=You'll find the fuel bar helpful. I used to have a Docked HUDs OXP with three HUD files. One had the fuel bar, one the missile display, and the last the missile display, very faint (opacity 20% IIRC). There was nothing else on them except the clock, and in later versions the commlog position.&lt;br /&gt;
... Anyway, becoming relevant, I used guiScreenChanged &amp;amp; playerBoughtEquipment, rather than shipDockedWithStation &amp;amp; shipWillLaunchFromStation (which were used by my main HUD), so it was immune to interference by my main HUD script. It first checked player.ship.docked (Do I really need to say that?), then the fuel and, if necessary, missile count and selected need-fuel-hud.plist, need-missiles-hud.plist or missiles-full-hud.plist (a.k.a. need nothing).&lt;br /&gt;
&lt;br /&gt;
To any non-forum-members reading along, I recommend this as a ''my first OXP'' exercise. The script is simple, the HUD files are ridiculously simple, the result looks fairly slick, and putting it all together is just tedious enough to leave you feeling satisfied when you finish!|Source=([https://bb.oolite.space/viewtopic.php?p=231734#p231734 Wildeblood])}}&lt;br /&gt;
&lt;br /&gt;
*See [[How to tweak OXZ's]] for more information on general tweaking&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17217 BB Thread] (2015+)&lt;br /&gt;
*[[HUD]]&lt;br /&gt;
&lt;br /&gt;
== Gameplay and Balance Indicator ==&lt;br /&gt;
[[File:Tag-colour-green.png|right]]&lt;br /&gt;
Great for the aesthetics - but less relevant for gameplay balance!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{HUD-OXP}}&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=Docked_HUDs&amp;diff=89419</id>
		<title>Docked HUDs</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=Docked_HUDs&amp;diff=89419"/>
		<updated>2026-06-16T13:17:20Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Downloads */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Sleek, minimalist HUD design when docked. If you use a HUD expansion pack, instead of the standard HUD, check the forum for compatibility notes.&lt;br /&gt;
&lt;br /&gt;
the newest version (see at bottom) also acts as an immersive introduction to the complexities of Oolite for new players.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Replaces the HUD of your choice while docked with a minimal HUD showing only &lt;br /&gt;
*fuel gauge (in case you need to refuel) &lt;br /&gt;
*missile display (in case you need to buy more)&lt;br /&gt;
The rest is banished until you launch!&lt;br /&gt;
&lt;br /&gt;
Note: some HUDs do this automatically without the need for this OXP.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
=== Modularized version ===&lt;br /&gt;
&lt;br /&gt;
Version 1.5 will come in 3 components:&lt;br /&gt;
&lt;br /&gt;
 Svelte original: [[File:Docked HUDs.oxz]]&lt;br /&gt;
 Function labels: [[File:Docked HUDs data sources.oxz]]&lt;br /&gt;
 Special effects: [[File:Docked HUDs extras.oxz]]&lt;br /&gt;
&lt;br /&gt;
=== Version 1.4 ===&lt;br /&gt;
&lt;br /&gt;
Recent bloatware: [[File:Docked HUDs.oxz]]&lt;br /&gt;
&lt;br /&gt;
=== Version 1.1 ===&lt;br /&gt;
&lt;br /&gt;
Svelte original: [[File:Wildefire Docked HUDs 1.1.oxz]]&lt;br /&gt;
&lt;br /&gt;
== License ==&lt;br /&gt;
*License: CC-BY-NC-SA 3.0&lt;br /&gt;
*Author: [[User:Wildeblood|Wildeblood]]&lt;br /&gt;
*Version: 1.4.2&lt;br /&gt;
*Required Oolite Version: 1.80&lt;br /&gt;
&lt;br /&gt;
== Tweaking ==&lt;br /&gt;
{{QuoteText|Text=You'll find the fuel bar helpful. I used to have a Docked HUDs OXP with three HUD files. One had the fuel bar, one the missile display, and the last the missile display, very faint (opacity 20% IIRC). There was nothing else on them except the clock, and in later versions the commlog position.&lt;br /&gt;
... Anyway, becoming relevant, I used guiScreenChanged &amp;amp; playerBoughtEquipment, rather than shipDockedWithStation &amp;amp; shipWillLaunchFromStation (which were used by my main HUD), so it was immune to interference by my main HUD script. It first checked player.ship.docked (Do I really need to say that?), then the fuel and, if necessary, missile count and selected need-fuel-hud.plist, need-missiles-hud.plist or missiles-full-hud.plist (a.k.a. need nothing).&lt;br /&gt;
&lt;br /&gt;
To any non-forum-members reading along, I recommend this as a ''my first OXP'' exercise. The script is simple, the HUD files are ridiculously simple, the result looks fairly slick, and putting it all together is just tedious enough to leave you feeling satisfied when you finish!|Source=([https://bb.oolite.space/viewtopic.php?p=231734#p231734 Wildeblood])}}&lt;br /&gt;
&lt;br /&gt;
*See [[How to tweak OXZ's]] for more information on general tweaking&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17217 BB Thread] (2015+)&lt;br /&gt;
*[[HUD]]&lt;br /&gt;
&lt;br /&gt;
== Gameplay and Balance Indicator ==&lt;br /&gt;
[[File:Tag-colour-green.png|right]]&lt;br /&gt;
Great for the aesthetics - but less relevant for gameplay balance!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{HUD-OXP}}&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=AI_Trading_Backup_Datalogger&amp;diff=89418</id>
		<title>AI Trading Backup Datalogger</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=AI_Trading_Backup_Datalogger&amp;diff=89418"/>
		<updated>2026-06-16T12:51:01Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Summary */ Yes, summary.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This OXP records your transactions on the F8 screen for later use by the [[AI Trading Assistant]]&lt;br /&gt;
&lt;br /&gt;
Does what it says - quietly logs data, while being invisible in-game. You install this alongside the main OXP, then forget about it. When you want to try out Market Observer OXP, you remove AI Trading Assistant OXP, but leave the backup logger. When you realize you've made a horrible mistake, you put AI Trading Assistant OXP back, remove Market Observer OXP, and (like magic!) there's no gap in your data. Everything carries on as though you had never strayed. (&amp;quot;It's alright, Pam, it was just a dream.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Author: [[User:Wildeblood]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download: [[File:AI Trading Backup Datalogger 3.oxz]] (June 2026)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Links: [https://bb.oolite.space/viewtopic.php?p=293796#p293796 Discussion (2024)]&lt;br /&gt;
&lt;br /&gt;
{{misc-OXP}}&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=User:Wildeblood&amp;diff=89415</id>
		<title>User:Wildeblood</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=User:Wildeblood&amp;diff=89415"/>
		<updated>2026-06-16T01:22:57Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
[[File:Distant Thunder album cover.png|thumb|right|500px|Miss Sexy Voice announces goings on, and thunderous hyperspace sound.]]&lt;br /&gt;
[[File:Very Advanced Space Compass album cover.png|thumb|right|500px|It's the space compass, Jim, but not as we know it.]]&lt;br /&gt;
[[File:World Builder cover art.png|thumb|right|500px|Rule the Ooniverse your way!]]&lt;br /&gt;
[[File:Galactic_Hyperdrive_icon.png|thumb|right|500px|Galactic Hyperdrive programmers, because knowing where you're going...]]&lt;br /&gt;
[[File:Retro-Encabulator album cover.png|thumb|right|500px|You know it makes sense!]]&lt;br /&gt;
[[File:Distant Suns album cover.png|thumb|right|500px|The original Distant Suns OXP.]]&lt;br /&gt;
[[File:Trading Assistant album cover.png|thumb|right|500px|The original and genuine!]]&lt;br /&gt;
[[File:Distant Voyages cover art.png|thumb|right|500px|Rediscover the Galaxy]]&lt;br /&gt;
[[File:SE-X Drive album cover.png|thumb|right|500px|Special Equipment (Experimental)]]&lt;br /&gt;
[[File:Polarity_Reverser_cover_art.png|thumb|right|500px|Plasma conduits are especially reversible.]]&lt;br /&gt;
[[File:Distant Realms cover art.png|thumb|right|500px|Who's in charge around here?]]&lt;br /&gt;
[[File:Psionic Broadcaster.png|thumb|right|500px|Dynooverse Research really want to know how you feel.]]&lt;br /&gt;
[[File:Witch Bank.png|thumb|right|500px|More trustworthy than Westpac.]]&lt;br /&gt;
[[File:AristoShares_cover_art.png|thumb|right|500px|Stockbroker to the Stars]]&lt;br /&gt;
&lt;br /&gt;
== Trinkets ==&lt;br /&gt;
==== Latest (A.D. 2026) trinkets ====&lt;br /&gt;
 [[File:AristoShares.oxz]]&lt;br /&gt;
 [[File:Docked_HUDs.oxz]]&lt;br /&gt;
 [[File:Docked HUDs data sources.oxz]]&lt;br /&gt;
 [[File:Polarity_Reverser.oxz]]&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2025 trinkets ====&lt;br /&gt;
 [[File:AI_Trading_Backup_Datalogger_3.oxz]]&lt;br /&gt;
 [[File:DistantSpace.oxz]]                  (Meta-OXZ, downloads the [[Distant Space]] series)&lt;br /&gt;
 [[File:Distant_Locales.oxz]]               (Fills in all the other systems, not covered by Distant Realms)&lt;br /&gt;
 [[File:Distant_Realms_US.oxz]]             (See [[Distant Realms]]. Apparently they spell centre 'center')&lt;br /&gt;
 [[File:Distant Space.oxz]]                 (Red backgrounds on the start screens)&lt;br /&gt;
 [[File:Distant Thunder.oxz]]               (Sound set)&lt;br /&gt;
 [[File:Dynooverse.oxz]]                    ([[Dynooverse]] slowly changes the Ooniverse as you play the game)&lt;br /&gt;
 [[File:Lost_In_Space.oxz]]                 ([[Lost In Space]] makes random changes to the galactic charts each time the Galactic hyperdrive is used. When you return to chart 1, it looks like chart 9 and so on)&lt;br /&gt;
 [[File:Retro-Encabulator.oxz]]             (With help from GLM-4.5)&lt;br /&gt;
 [[File:Smart_Home_Control.oxz]]            (Boil your &amp;quot;smart kettle&amp;quot; while playing Oolite)&lt;br /&gt;
 [[File:Thargoidifier.oxz]]&lt;br /&gt;
 [[File:Throbtastic_Crosshairs.oxz]]        (Crosshairs throb while weapons are on-line)&lt;br /&gt;
 [[File:Very_Advanced_Space_Compass.oxz]]   (Turns your ship to face the ASC target)&lt;br /&gt;
 [[File:Visits.oxz]]                        (System Visits Counter, an alternative to Explorers' Club)&lt;br /&gt;
 [[File:Wildeblood_Manor.oxz]]              (Puts picture backdrop on the F7 screen when G1 Vetitice is selected)&lt;br /&gt;
 [[File:Witch_Bank.oxz]] (WIP/preview)      ([[Witch Bank]] Savings Bank)&lt;br /&gt;
 [[File:World_Builder.oxz]]                 ([[World Builder]] Alter the stats of a solar system)&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2024 trinkets ====&lt;br /&gt;
 [[File:Demo_Screen_Backgrounds.oxz]]       (setScreenBackground and setScreenBackgroundForKey JavaScript methods)&lt;br /&gt;
 [[File:Distant_Realms.oxz]]                (Updated 2025) ([[Distant Realms]] names regions on the F6 screen)&lt;br /&gt;
 [https://bb.oolite.space/viewtopic.php?p=298353#p298353 Docked_HUDs.oxz]                      ([[Docked HUDs]] - originally just a minimalist docked HUD, but now brimming with information for new players)&lt;br /&gt;
 [[File:Free_the_Slaves.oxz]]               (Now secretly funding the [[Free The Slaves! NGO]])&lt;br /&gt;
 [[File:SEX_Drive.oxz]]                     (It's even got a wiki page, so it must be good: [[SE-X Drive]])&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2015 trinkets ====&lt;br /&gt;
 [[File:Contracted_Goods_Reminder.oxz]]     (Updated 2025) (While I was away, Cholmondely made a wiki page for [[Contracted Goods Reminder]].)&lt;br /&gt;
 [[File:Station_Self-Destruction_Codes.oxz]](While I was away, Cholmondely made a wiki page for [[Station Self-Destruction Codes]].)&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2014 trinkets ====&lt;br /&gt;
 [[File:Display_Reputation.oxz]]            (Updated 2025 [[Display Reputation]])&lt;br /&gt;
 [[File:Explorers_Club_1.4.4.oxz]]          (Updated 2024 [[Explorers' Club]])&lt;br /&gt;
 [[File:Untrumbled.oxz]]                    (Updated 2026 [[Untrumbled]])&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2012 trinkets ====&lt;br /&gt;
 [[File:Bullet_Drive_1.0.3.oxz]]            (Updated 2013) (While I was away, Cholmondely made a wiki page for [[Bullet Drive]].)&lt;br /&gt;
&lt;br /&gt;
== Current Interests ==&lt;br /&gt;
=== Album Covers ===&lt;br /&gt;
Check out my growing collection of OXP album covers floating to the right, '''over there -&amp;gt;'''&amp;lt;br/&amp;gt;&lt;br /&gt;
I am unclear what purpose they'll eventually serve. But, I'm pretty sure I'm ahead of the curve with this trend, but everyone else will catch on soon.&lt;br /&gt;
&lt;br /&gt;
=== A.I. Assistance ===&lt;br /&gt;
My current favourite AI assistants, for use with Oolite, are [https://chat.z.ai/ GLM-5.1] and [https://chat.qwen.ai/ Qwen3-Coder]. Avoid Google's Gemini, it will just waste your time.&lt;br /&gt;
&lt;br /&gt;
=== Trinkets To-do ===&lt;br /&gt;
&lt;br /&gt;
== A few comments ==&lt;br /&gt;
 Wildeblood has produced some very innovative OXPs: have a good look at the now-broken [[AI Trading Assistant]], and his [[Alternative Ooniverses OXP]], [[Docked HUDs]], [[Galactic Hyperdrive OXP|Galactic Hyperdrive]], [[MilHUD 4000]], [[WEBS System‎]] &amp;amp; [[Wide-Screen HUD]]. His work on HUDs seems to have been very influential - many of his ideas were taken up by others, later, and most of the &amp;quot;modern HUDs&amp;quot; include several of his ideas. ''Cholmondeley 2021''&lt;br /&gt;
&lt;br /&gt;
== My &amp;quot;How-to&amp;quot; OXPs ==&lt;br /&gt;
&lt;br /&gt;
A collection of micro-OXPs, each demonstrating a particular Oolite javaScript technique, which might be helpful to others seeking an example to copy.&lt;br /&gt;
&lt;br /&gt;
*How to use the planetary &amp;quot;concealment&amp;quot; property, introduced in Oolite 1.84:&lt;br /&gt;
::[[Tachyona]] is the fastest orbiting world in the co-operative. It orbits so quickly, you can see it move on the long-range chart.&lt;br /&gt;
*How to start (And, stop and clean up!) a timer, and how to randomize timer intervals:&lt;br /&gt;
::[[File:Noisy Passengers 0.1.oxz]]&lt;br /&gt;
*How to start (And, stop and clean up!) a frame callback while in flight:&lt;br /&gt;
::[[Bullet Drive]] makes the Torus Drive work somewhat more like [[classic Elite]] - no manoeuvring during flight&lt;br /&gt;
*How to set a station interface on the F4 screen:&lt;br /&gt;
::[[Station Self-Destruction Codes]] self-declared winner of the [https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17178 competition] for unbalanced oxp-uber-mega-weapons&lt;br /&gt;
*How to change the crosshairs, without changing the whole HUD file:&lt;br /&gt;
::[[Crosshairs - Alerting]] shape of crosshairs depends on alert level (green/yellow/red)&lt;br /&gt;
*How to create the data source for a customized HUD dial:&lt;br /&gt;
::[[Data - Ship Name]] displays the name of your ship on your in-flight [[HUD]] (needs compatible HUD)&lt;br /&gt;
*How to use the player buying equipment to cause an immediate reaction (in this case, changing the HUD) unrelated to the equipment:&lt;br /&gt;
::[[Docked HUDs]] &lt;br /&gt;
*How to completely remove a worldScript which has outstayed its welcome:&lt;br /&gt;
::[[Untrumbled]] does not cure existing infestations but prevents future ones&lt;br /&gt;
*The proper way to add a new visit recording option to Explorers' Club:&lt;br /&gt;
::[[Serial Killer OXP]] the club will not record your visit to a system until you kill something&lt;br /&gt;
&lt;br /&gt;
== My OXPs ==&lt;br /&gt;
&lt;br /&gt;
In alphabetical order: &lt;br /&gt;
*[[File:Aaaa aaron.oxz|Aaron Aarts' Amazing Adventures]]. Some dutch guy tilts at windmills. (2024)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=12248 AI Combat Assistant OXP]: ''Withdrawn''&lt;br /&gt;
*[[AI Trading Assistant]] an autotrader - put your feet up and have a gin &amp;amp; tonic: '''Broke with Oolite v.1.82'''&lt;br /&gt;
*[[Auto Crosshairs]] crosshairs change shape when target is centred&lt;br /&gt;
*[[Contracted Goods Reminder]] A reminder pops up if you mistakenly sell contracted goods on the F8 market screen&lt;br /&gt;
*[[Crosshairs - Laser-ific]] circular dial shows laser temperature&lt;br /&gt;
*[[Crosshairs - Shield-tastic]] two semi-circular dials show shield levels&lt;br /&gt;
*[[Destination ETA]] updates the ETA - and adds a spectroscope to analyse Distant Suns&lt;br /&gt;
*[[Distant Locales]] retitles all F7 screen page headings with region name or co-ordinates (2025).&lt;br /&gt;
*[[Distant Realms]] incorporates regional titles to the F6 chart (Old Worlds/Xexedi cluster/Pulsar worlds ''etc'')&lt;br /&gt;
*[[Distant Suns]] moves suns further away from planets (can combine with Sensible Sun below), and changes spectroscopic qualities&lt;br /&gt;
*[[Dockside Services]] de-nerdifies the F4 screen&lt;br /&gt;
*[[Dynooverse]] - a dynamic ooniverse where the politics/economy/population of systems changes over time. (2025)&lt;br /&gt;
*[[Free The Slaves! NGO]] - an activist non-Galcop organization (NGO) which will nag you if you accidentally buy slaves at a Galcop station. &lt;br /&gt;
*[[Galactic Hyperdrive OXP|Galactic Hyperdrive]] choose your destination in the next galaxy ('''comes with 3rd chart of next galaxy''')&lt;br /&gt;
*[[Galaxy Names OXP|Galaxy Names]] replaces Galaxy numbers with the Acorn Archimedes Galaxy names (Santaari, Colesque ''etc'').&lt;br /&gt;
*[[Glare Clarifier]] cuts solar glare when close to the sun&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?p=155952#p155952 HUD Vanisher] banishes the HUD in external &amp;quot;v&amp;quot;-views: [https://app.box.com/s/3nouit5vnhawea3yoz3n Download v.1.1]&lt;br /&gt;
*[[MilHUD 4000]] has variable brightness, de-emphasises police vessels and has a sniper-sight attached&lt;br /&gt;
*[[Sensible Sun]] moves suns further away from planets (can combine with Distant Suns below)&lt;br /&gt;
*[[Serial Killer OXP]] records systems where you killed something (a modification of the Explorer's Club OXP, 2024)&lt;br /&gt;
*[[Sniper Sight]] &lt;br /&gt;
*[[Undocumented Launch]] does this really need explaining?&lt;br /&gt;
*[[WEBS System‎]] defense for when your shields are down&lt;br /&gt;
*[[Wide-Screen HUD]] does this really need explaining?&lt;br /&gt;
*[[Wildeblood Manor]]: Traditional, mountain-top, fortress-yurt-dome house on Vetitice illustrated on F7 screen. (2025).&lt;br /&gt;
*[[World Builder]] - edit a solar system's F7 description to what you want! (2025)&lt;br /&gt;
&lt;br /&gt;
=== In this vein ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?p=174714#p174714 Template for a Galactic Hyperdrive XG] to reach more galaxies (2012). Probably only works with [[Oolite#Downloading_Earlier_versions|pre-v.1.80 versions of Oolite]]. You need to know how to manipulate the [[Galaxy Seeds]], and rejig all sorts of gubbins.&lt;br /&gt;
&lt;br /&gt;
== Works in Progress (in 2015) ==&lt;br /&gt;
&lt;br /&gt;
*[[Alternative Ooniverses OXP|Alternative Ooniverses]]&lt;br /&gt;
*[[Save and Jump OXP|Save and Jump]]&lt;br /&gt;
*[[OXP List (Test)]]&lt;br /&gt;
&lt;br /&gt;
== List of OXPs clobbered with System 1.80's changes ==&lt;br /&gt;
See [https://bb.oolite.space/viewtopic.php?p=223260#p223260 here] for list, links, and a little explanation of WEBS, Alternative Ooniverse ''etc''.&lt;br /&gt;
&lt;br /&gt;
== Wildeblood ==&lt;br /&gt;
*Exhibits a morbid fascination in the [https://bb.oolite.space/viewtopic.php?f=7&amp;amp;t=17793 Australian flag]&lt;br /&gt;
*Wildeblood removed all his OXPs from circulation as he updated them for Oolite v.1.77 (''c''. 2012). A few were updated and re-released, but not all.&lt;br /&gt;
*Wildeblood did not provide licenses for many of his oxp's.&lt;br /&gt;
&lt;br /&gt;
== Version Archive ==&lt;br /&gt;
''Note that the handful of mirror sites are listed under the individual wiki pages for the relevant oxp's.''&lt;br /&gt;
=== AI Trading ===&lt;br /&gt;
*Download AI Trading Assistant 2.15.1 [[Media:Wildeblood.ai trading 2.15.1.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:Wildeblood.ai trading 2.15.1.oxz}} times).&lt;br /&gt;
*Download AI Trading Assistant 2.15 [[Media:AI_Trading_Assistant_2.15.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Assistant_2.15.oxz}} times).&lt;br /&gt;
*Download AI Trading Assistant 2.13.1 [[Media:AI_Trading_Assistant_2.13.1.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Assistant 2.13 [[Media:AI_Trading_Assistant_2.13.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Assistant_2.13.oxz}} times).&lt;br /&gt;
*Download AI Trading Assistant 2.12.4 [[Media:AI_Trading_Assistant_2.12.4.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Assistant_2.12.4.oxz}} times).&lt;br /&gt;
*Download AI Trading Assistant 2.12.3 [[Media:AI_Trading_Assistant_2.12.3.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Assistant 2.12.2 [[Media:AI_Trading_Assistant_2.12.2.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Assistant 2.12.1 [[Media:AI_Trading_Assistant_2.12.1.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Autotrade Report 0.5.3 [[Media:Autotrade_Report_Screen.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Autotrade_Report_Screen.oxz‎}} - 232 times).&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*Download AI Trading Autotrade Report 0.4 [[Media:Autotrade_Report_Email.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Autotrade_Report_Email.oxz‎}} times). --&amp;gt;&lt;br /&gt;
*Download AI Trading Backup Datalogger 2.12.3 [[Media:AI_Trading_Backup_Datalogger_2.12.3.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Backup_Datalogger_2.12.3.oxz}} times).&lt;br /&gt;
*Download AI Trading Backup Datalogger 2.12.1 [[Media:AI_Trading_Backup_Datalogger_2.12.1.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Legality Reminder 1.0 [[Media:AI_Trading_Legality.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Legality.oxz}} times).&lt;br /&gt;
*Download AI Trading Purchase Book 2.12 [[Media:AI_Trading_Purchase_Book_2.12.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Purchase_Book_2.12.oxz}} times).&lt;br /&gt;
*Download AI Trading Turbotrader 1.0 [[Media:AI_Trading_Turbotrader.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Turbotrader.oxz}} times).&lt;br /&gt;
*Download AI Trading with Yoda 1.0 [[Media:AI_Trading_with_Yoda.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_with_Yoda.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
=== Distant Space ===&lt;br /&gt;
&lt;br /&gt;
Download Distant Realms [[Media:Distant_Space.oxz|here]], for Oolite 1.81 or later (downloaded {{#downloads:Distant_Space.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Distant Suns 0.5.1 [[Media:Distant_Suns_0.5.1.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:Distant_Suns_0.5.1.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
=== Explorers' Club ===&lt;br /&gt;
&lt;br /&gt;
Download 1.4.4 in OXZ format [[Media:Explorers_Club_1.4.4.oxz|here]] for Oolite 1.80 or later (downloaded {{#downloads:Explorers_Club_1.4.4.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download 1.4.3 in OXZ format [[Media:Explorers_Club_1.4.3.oxz|here]] for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download 1.4.2 in OXZ format [[Media:Explorers_Club_1.4.2.oxz|here]] for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download 1.4.1 in OXZ format [[Media:ExplorersClub_1.4.1.oxz|here]] for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
=== Animated Cross-hairs ===&lt;br /&gt;
&lt;br /&gt;
Download Active Crosshairs [[Media:Active_Crosshairs.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:Active_Crosshairs.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Alerting Crosshairs 1.0 [[Media:Alerting Crosshairs 1.0.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:Alerting Crosshairs 1.0.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Auto Crosshairs 1.1.1 [[Media:AutoCrosshairs 1.1.1.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:AutoCrosshairs 1.1.1.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Auto Crosshairs 1.1 [[Media:AutoCrosshairs 1.1.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Auto Crosshairs 1.0 [[Media:AutoCrosshairs.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Laser-ific Crosshairs 1.3 [[Media:LaserificCrosshairs1.3.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:LaserificCrosshairs1.3.oxz}}).&lt;br /&gt;
&lt;br /&gt;
Download Laser-ific Crosshairs 1.2 [[Media:LaserificCrosshairs1.2.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Laser-ific Crosshairs 1.1 [[Media:LaserificCrosshairs1.1.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Laser-ific Crosshairs 1.0 [[Media:LaserificCrosshairs.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Shield-tastic Crosshairs 1.0 [[Media:ShieldtasticCrosshairs_1.0.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:ShieldtasticCrosshairs_1.0.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Selecto-o-matic Crosshairs 1.0.1 [[Media:Selecto-o-matic Crosshairs 1.0.1.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:Selecto-o-matic Crosshairs 1.0.1.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Coluber HUD Auto Crosshairs patch [[Media:Coluber CH-01 Auto Crosshairs patch.oxp.oxz|here]], (downloaded {{#downloads:Coluber CH-01 Auto Crosshairs patch.oxp.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
===Sensible Tweaks &amp;amp; Miscellaney===&lt;br /&gt;
&lt;br /&gt;
Download Bullet Drive 1.0.3 [[Media:Bullet_Drive_1.0.3.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Bullet_Drive_1.0.3.oxz‎}} times).&lt;br /&gt;
&lt;br /&gt;
Download Contracted Goods Reminder [[Media:Contracted Goods Reminder.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Contracted Goods Reminder.oxz‎}} times).&lt;br /&gt;
&lt;br /&gt;
Download Dockside Services 1.0 [[Media:Dockside Services 1.0.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Dockside Services 1.0.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Galaxy Names 1.0 [[Media:Galaxy Names 1.0.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Galaxy Names 1.0.oxz‎}} times).&lt;br /&gt;
&lt;br /&gt;
Download Glare Clarifier [[Media:GlareClarifier.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:GlareClarifier.oxz‎}} times).&lt;br /&gt;
&lt;br /&gt;
Download Station Self-Destruction Codes [[Media:Station Self-Destruction Codes.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:Station Self-Destruction Codes.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Undocumented Launch [[Media:UndocumentedLaunch.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:UndocumentedLaunch.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Untrumbled [[Media:Untrumbled.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:Untrumbled.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Wildefire Docked HUDs 1.1 [[Media:Wildefire Docked HUDs 1.1.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:Wildefire Docked HUDs 1.1.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Wildefire Docked HUDs 1.0 [[Media:Wildefire Docked HUDs.oxz|here]], for Oolite 1.80.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== For Oolite 1.81 ===&lt;br /&gt;
&lt;br /&gt;
Download HUD Data - Ship Name [[Media:HUDDataShipName.oxz|here]], for Oolite 1.81 (downloaded {{#downloads:HUDDataShipName.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Display Reputation 1.3, for Oolite 1.81 (downloaded {{#downloads:DisplayReputation1.3.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:OXP authors]]&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=User:Wildeblood&amp;diff=89414</id>
		<title>User:Wildeblood</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=User:Wildeblood&amp;diff=89414"/>
		<updated>2026-06-12T14:13:44Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Latest (A.D. 2026) trinkets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Distant Space album cover.png|thumb|right|500px|Distant Space series of OXPs.]]&lt;br /&gt;
[[File:Thargoidifier album cover.png|thumb|right|500px|Thargoids! The Musical ([https://bb.oolite.space/viewtopic.php?p=302336#p302336 Original soundtrack album] by Thargoidifier)]]&lt;br /&gt;
[[File:Distant Thunder album cover.png|thumb|right|500px|Miss Sexy Voice announces goings on, and thunderous hyperspace sound.]]&lt;br /&gt;
[[File:Very Advanced Space Compass album cover.png|thumb|right|500px|It's the space compass, Jim, but not as we know it.]]&lt;br /&gt;
[[File:World Builder cover art.png|thumb|right|500px|Rule the Ooniverse your way!]]&lt;br /&gt;
[[File:Galactic_Hyperdrive_icon.png|thumb|right|500px|Galactic Hyperdrive programmers, because knowing where you're going...]]&lt;br /&gt;
[[File:Retro-Encabulator album cover.png|thumb|right|500px|You know it makes sense!]]&lt;br /&gt;
[[File:Distant Suns album cover.png|thumb|right|500px|The original Distant Suns OXP.]]&lt;br /&gt;
[[File:Trading Assistant album cover.png|thumb|right|500px|The original and genuine!]]&lt;br /&gt;
[[File:Distant Voyages cover art.png|thumb|right|500px|Rediscover the Galaxy]]&lt;br /&gt;
[[File:SE-X Drive album cover.png|thumb|right|500px|Special Equipment (Experimental)]]&lt;br /&gt;
[[File:Polarity_Reverser_cover_art.png|thumb|right|500px|Plasma conduits are especially reversible.]]&lt;br /&gt;
[[File:Distant Realms cover art.png|thumb|right|500px|Who's in charge around here?]]&lt;br /&gt;
[[File:Psionic Broadcaster.png|thumb|right|500px|Dynooverse Research really want to know how you feel.]]&lt;br /&gt;
[[File:Witch Bank.png|thumb|right|500px|More trustworthy than Westpac.]]&lt;br /&gt;
[[File:AristoShares_cover_art.png|thumb|right|500px|Stockbroker to the Stars]]&lt;br /&gt;
&lt;br /&gt;
== Trinkets ==&lt;br /&gt;
==== Latest (A.D. 2026) trinkets ====&lt;br /&gt;
 [[File:AristoShares.oxz]]&lt;br /&gt;
 [[File:Docked_HUDs.oxz]]&lt;br /&gt;
 [[File:Docked HUDs data sources.oxz]]&lt;br /&gt;
 [[File:Polarity_Reverser.oxz]]&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2025 trinkets ====&lt;br /&gt;
 [[File:AI_Trading_Backup_Datalogger_3.oxz]]&lt;br /&gt;
 [[File:DistantSpace.oxz]]                  (Meta-OXZ, downloads the [[Distant Space]] series)&lt;br /&gt;
 [[File:Distant_Locales.oxz]]               (Fills in all the other systems, not covered by Distant Realms)&lt;br /&gt;
 [[File:Distant_Realms_US.oxz]]             (See [[Distant Realms]]. Apparently they spell centre 'center')&lt;br /&gt;
 [[File:Distant Space.oxz]]                 (Red backgrounds on the start screens)&lt;br /&gt;
 [[File:Distant Thunder.oxz]]               (Sound set)&lt;br /&gt;
 [[File:Dynooverse.oxz]]                    ([[Dynooverse]] slowly changes the Ooniverse as you play the game)&lt;br /&gt;
 [[File:Lost_In_Space.oxz]]                 ([[Lost In Space]] makes random changes to the galactic charts each time the Galactic hyperdrive is used. When you return to chart 1, it looks like chart 9 and so on)&lt;br /&gt;
 [[File:Retro-Encabulator.oxz]]             (With help from GLM-4.5)&lt;br /&gt;
 [[File:Smart_Home_Control.oxz]]            (Boil your &amp;quot;smart kettle&amp;quot; while playing Oolite)&lt;br /&gt;
 [[File:Thargoidifier.oxz]]&lt;br /&gt;
 [[File:Throbtastic_Crosshairs.oxz]]        (Crosshairs throb while weapons are on-line)&lt;br /&gt;
 [[File:Very_Advanced_Space_Compass.oxz]]   (Turns your ship to face the ASC target)&lt;br /&gt;
 [[File:Visits.oxz]]                        (System Visits Counter, an alternative to Explorers' Club)&lt;br /&gt;
 [[File:Wildeblood_Manor.oxz]]              (Puts picture backdrop on the F7 screen when G1 Vetitice is selected)&lt;br /&gt;
 [[File:Witch_Bank.oxz]] (WIP/preview)      ([[Witch Bank]] Savings Bank)&lt;br /&gt;
 [[File:World_Builder.oxz]]                 ([[World Builder]] Alter the stats of a solar system)&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2024 trinkets ====&lt;br /&gt;
 [[File:Demo_Screen_Backgrounds.oxz]]       (setScreenBackground and setScreenBackgroundForKey JavaScript methods)&lt;br /&gt;
 [[File:Distant_Realms.oxz]]                (Updated 2025) ([[Distant Realms]] names regions on the F6 screen)&lt;br /&gt;
 [https://bb.oolite.space/viewtopic.php?p=298353#p298353 Docked_HUDs.oxz]                      ([[Docked HUDs]] - originally just a minimalist docked HUD, but now brimming with information for new players)&lt;br /&gt;
 [[File:Free_the_Slaves.oxz]]               (Now secretly funding the [[Free The Slaves! NGO]])&lt;br /&gt;
 [[File:SEX_Drive.oxz]]                     (It's even got a wiki page, so it must be good: [[SE-X Drive]])&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2015 trinkets ====&lt;br /&gt;
 [[File:Contracted_Goods_Reminder.oxz]]     (Updated 2025) (While I was away, Cholmondely made a wiki page for [[Contracted Goods Reminder]].)&lt;br /&gt;
 [[File:Station_Self-Destruction_Codes.oxz]](While I was away, Cholmondely made a wiki page for [[Station Self-Destruction Codes]].)&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2014 trinkets ====&lt;br /&gt;
 [[File:Display_Reputation.oxz]]            (Updated 2025 [[Display Reputation]])&lt;br /&gt;
 [[File:Explorers_Club_1.4.4.oxz]]          (Updated 2024 [[Explorers' Club]])&lt;br /&gt;
 [[File:Untrumbled.oxz]]                    (Updated 2026 [[Untrumbled]])&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2012 trinkets ====&lt;br /&gt;
 [[File:Bullet_Drive_1.0.3.oxz]]            (Updated 2013) (While I was away, Cholmondely made a wiki page for [[Bullet Drive]].)&lt;br /&gt;
&lt;br /&gt;
== Current Interests ==&lt;br /&gt;
=== Album Covers ===&lt;br /&gt;
Check out my growing collection of OXP album covers floating to the right, '''over there -&amp;gt;'''&amp;lt;br/&amp;gt;&lt;br /&gt;
I am unclear what purpose they'll eventually serve. But, I'm pretty sure I'm ahead of the curve with this trend, but everyone else will catch on soon.&lt;br /&gt;
&lt;br /&gt;
=== A.I. Assistance ===&lt;br /&gt;
My current favourite AI assistants, for use with Oolite, are [https://chat.z.ai/ GLM-5.1] and [https://chat.qwen.ai/ Qwen3-Coder]. Avoid Google's Gemini, it will just waste your time.&lt;br /&gt;
&lt;br /&gt;
=== Trinkets To-do ===&lt;br /&gt;
&lt;br /&gt;
== A few comments ==&lt;br /&gt;
 Wildeblood has produced some very innovative OXPs: have a good look at the now-broken [[AI Trading Assistant]], and his [[Alternative Ooniverses OXP]], [[Docked HUDs]], [[Galactic Hyperdrive OXP|Galactic Hyperdrive]], [[MilHUD 4000]], [[WEBS System‎]] &amp;amp; [[Wide-Screen HUD]]. His work on HUDs seems to have been very influential - many of his ideas were taken up by others, later, and most of the &amp;quot;modern HUDs&amp;quot; include several of his ideas. ''Cholmondeley 2021''&lt;br /&gt;
&lt;br /&gt;
== My &amp;quot;How-to&amp;quot; OXPs ==&lt;br /&gt;
&lt;br /&gt;
A collection of micro-OXPs, each demonstrating a particular Oolite javaScript technique, which might be helpful to others seeking an example to copy.&lt;br /&gt;
&lt;br /&gt;
*How to use the planetary &amp;quot;concealment&amp;quot; property, introduced in Oolite 1.84:&lt;br /&gt;
::[[Tachyona]] is the fastest orbiting world in the co-operative. It orbits so quickly, you can see it move on the long-range chart.&lt;br /&gt;
*How to start (And, stop and clean up!) a timer, and how to randomize timer intervals:&lt;br /&gt;
::[[File:Noisy Passengers 0.1.oxz]]&lt;br /&gt;
*How to start (And, stop and clean up!) a frame callback while in flight:&lt;br /&gt;
::[[Bullet Drive]] makes the Torus Drive work somewhat more like [[classic Elite]] - no manoeuvring during flight&lt;br /&gt;
*How to set a station interface on the F4 screen:&lt;br /&gt;
::[[Station Self-Destruction Codes]] self-declared winner of the [https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17178 competition] for unbalanced oxp-uber-mega-weapons&lt;br /&gt;
*How to change the crosshairs, without changing the whole HUD file:&lt;br /&gt;
::[[Crosshairs - Alerting]] shape of crosshairs depends on alert level (green/yellow/red)&lt;br /&gt;
*How to create the data source for a customized HUD dial:&lt;br /&gt;
::[[Data - Ship Name]] displays the name of your ship on your in-flight [[HUD]] (needs compatible HUD)&lt;br /&gt;
*How to use the player buying equipment to cause an immediate reaction (in this case, changing the HUD) unrelated to the equipment:&lt;br /&gt;
::[[Docked HUDs]] &lt;br /&gt;
*How to completely remove a worldScript which has outstayed its welcome:&lt;br /&gt;
::[[Untrumbled]] does not cure existing infestations but prevents future ones&lt;br /&gt;
*The proper way to add a new visit recording option to Explorers' Club:&lt;br /&gt;
::[[Serial Killer OXP]] the club will not record your visit to a system until you kill something&lt;br /&gt;
&lt;br /&gt;
== My OXPs ==&lt;br /&gt;
&lt;br /&gt;
In alphabetical order: &lt;br /&gt;
*[[File:Aaaa aaron.oxz|Aaron Aarts' Amazing Adventures]]. Some dutch guy tilts at windmills. (2024)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=12248 AI Combat Assistant OXP]: ''Withdrawn''&lt;br /&gt;
*[[AI Trading Assistant]] an autotrader - put your feet up and have a gin &amp;amp; tonic: '''Broke with Oolite v.1.82'''&lt;br /&gt;
*[[Auto Crosshairs]] crosshairs change shape when target is centred&lt;br /&gt;
*[[Contracted Goods Reminder]] A reminder pops up if you mistakenly sell contracted goods on the F8 market screen&lt;br /&gt;
*[[Crosshairs - Laser-ific]] circular dial shows laser temperature&lt;br /&gt;
*[[Crosshairs - Shield-tastic]] two semi-circular dials show shield levels&lt;br /&gt;
*[[Destination ETA]] updates the ETA - and adds a spectroscope to analyse Distant Suns&lt;br /&gt;
*[[Distant Locales]] retitles all F7 screen page headings with region name or co-ordinates (2025).&lt;br /&gt;
*[[Distant Realms]] incorporates regional titles to the F6 chart (Old Worlds/Xexedi cluster/Pulsar worlds ''etc'')&lt;br /&gt;
*[[Distant Suns]] moves suns further away from planets (can combine with Sensible Sun below), and changes spectroscopic qualities&lt;br /&gt;
*[[Dockside Services]] de-nerdifies the F4 screen&lt;br /&gt;
*[[Dynooverse]] - a dynamic ooniverse where the politics/economy/population of systems changes over time. (2025)&lt;br /&gt;
*[[Free The Slaves! NGO]] - an activist non-Galcop organization (NGO) which will nag you if you accidentally buy slaves at a Galcop station. &lt;br /&gt;
*[[Galactic Hyperdrive OXP|Galactic Hyperdrive]] choose your destination in the next galaxy ('''comes with 3rd chart of next galaxy''')&lt;br /&gt;
*[[Galaxy Names OXP|Galaxy Names]] replaces Galaxy numbers with the Acorn Archimedes Galaxy names (Santaari, Colesque ''etc'').&lt;br /&gt;
*[[Glare Clarifier]] cuts solar glare when close to the sun&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?p=155952#p155952 HUD Vanisher] banishes the HUD in external &amp;quot;v&amp;quot;-views: [https://app.box.com/s/3nouit5vnhawea3yoz3n Download v.1.1]&lt;br /&gt;
*[[MilHUD 4000]] has variable brightness, de-emphasises police vessels and has a sniper-sight attached&lt;br /&gt;
*[[Sensible Sun]] moves suns further away from planets (can combine with Distant Suns below)&lt;br /&gt;
*[[Serial Killer OXP]] records systems where you killed something (a modification of the Explorer's Club OXP, 2024)&lt;br /&gt;
*[[Sniper Sight]] &lt;br /&gt;
*[[Undocumented Launch]] does this really need explaining?&lt;br /&gt;
*[[WEBS System‎]] defense for when your shields are down&lt;br /&gt;
*[[Wide-Screen HUD]] does this really need explaining?&lt;br /&gt;
*[[Wildeblood Manor]]: Traditional, mountain-top, fortress-yurt-dome house on Vetitice illustrated on F7 screen. (2025).&lt;br /&gt;
*[[World Builder]] - edit a solar system's F7 description to what you want! (2025)&lt;br /&gt;
&lt;br /&gt;
=== In this vein ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?p=174714#p174714 Template for a Galactic Hyperdrive XG] to reach more galaxies (2012). Probably only works with [[Oolite#Downloading_Earlier_versions|pre-v.1.80 versions of Oolite]]. You need to know how to manipulate the [[Galaxy Seeds]], and rejig all sorts of gubbins.&lt;br /&gt;
&lt;br /&gt;
== Works in Progress (in 2015) ==&lt;br /&gt;
&lt;br /&gt;
*[[Alternative Ooniverses OXP|Alternative Ooniverses]]&lt;br /&gt;
*[[Save and Jump OXP|Save and Jump]]&lt;br /&gt;
*[[OXP List (Test)]]&lt;br /&gt;
&lt;br /&gt;
== List of OXPs clobbered with System 1.80's changes ==&lt;br /&gt;
See [https://bb.oolite.space/viewtopic.php?p=223260#p223260 here] for list, links, and a little explanation of WEBS, Alternative Ooniverse ''etc''.&lt;br /&gt;
&lt;br /&gt;
== Wildeblood ==&lt;br /&gt;
*Exhibits a morbid fascination in the [https://bb.oolite.space/viewtopic.php?f=7&amp;amp;t=17793 Australian flag]&lt;br /&gt;
*Wildeblood removed all his OXPs from circulation as he updated them for Oolite v.1.77 (''c''. 2012). A few were updated and re-released, but not all.&lt;br /&gt;
*Wildeblood did not provide licenses for many of his oxp's.&lt;br /&gt;
&lt;br /&gt;
== Version Archive ==&lt;br /&gt;
''Note that the handful of mirror sites are listed under the individual wiki pages for the relevant oxp's.''&lt;br /&gt;
=== AI Trading ===&lt;br /&gt;
*Download AI Trading Assistant 2.15.1 [[Media:Wildeblood.ai trading 2.15.1.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:Wildeblood.ai trading 2.15.1.oxz}} times).&lt;br /&gt;
*Download AI Trading Assistant 2.15 [[Media:AI_Trading_Assistant_2.15.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Assistant_2.15.oxz}} times).&lt;br /&gt;
*Download AI Trading Assistant 2.13.1 [[Media:AI_Trading_Assistant_2.13.1.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Assistant 2.13 [[Media:AI_Trading_Assistant_2.13.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Assistant_2.13.oxz}} times).&lt;br /&gt;
*Download AI Trading Assistant 2.12.4 [[Media:AI_Trading_Assistant_2.12.4.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Assistant_2.12.4.oxz}} times).&lt;br /&gt;
*Download AI Trading Assistant 2.12.3 [[Media:AI_Trading_Assistant_2.12.3.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Assistant 2.12.2 [[Media:AI_Trading_Assistant_2.12.2.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Assistant 2.12.1 [[Media:AI_Trading_Assistant_2.12.1.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Autotrade Report 0.5.3 [[Media:Autotrade_Report_Screen.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Autotrade_Report_Screen.oxz‎}} - 232 times).&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*Download AI Trading Autotrade Report 0.4 [[Media:Autotrade_Report_Email.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Autotrade_Report_Email.oxz‎}} times). --&amp;gt;&lt;br /&gt;
*Download AI Trading Backup Datalogger 2.12.3 [[Media:AI_Trading_Backup_Datalogger_2.12.3.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Backup_Datalogger_2.12.3.oxz}} times).&lt;br /&gt;
*Download AI Trading Backup Datalogger 2.12.1 [[Media:AI_Trading_Backup_Datalogger_2.12.1.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Legality Reminder 1.0 [[Media:AI_Trading_Legality.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Legality.oxz}} times).&lt;br /&gt;
*Download AI Trading Purchase Book 2.12 [[Media:AI_Trading_Purchase_Book_2.12.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Purchase_Book_2.12.oxz}} times).&lt;br /&gt;
*Download AI Trading Turbotrader 1.0 [[Media:AI_Trading_Turbotrader.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Turbotrader.oxz}} times).&lt;br /&gt;
*Download AI Trading with Yoda 1.0 [[Media:AI_Trading_with_Yoda.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_with_Yoda.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
=== Distant Space ===&lt;br /&gt;
&lt;br /&gt;
Download Distant Realms [[Media:Distant_Space.oxz|here]], for Oolite 1.81 or later (downloaded {{#downloads:Distant_Space.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Distant Suns 0.5.1 [[Media:Distant_Suns_0.5.1.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:Distant_Suns_0.5.1.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
=== Explorers' Club ===&lt;br /&gt;
&lt;br /&gt;
Download 1.4.4 in OXZ format [[Media:Explorers_Club_1.4.4.oxz|here]] for Oolite 1.80 or later (downloaded {{#downloads:Explorers_Club_1.4.4.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download 1.4.3 in OXZ format [[Media:Explorers_Club_1.4.3.oxz|here]] for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download 1.4.2 in OXZ format [[Media:Explorers_Club_1.4.2.oxz|here]] for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download 1.4.1 in OXZ format [[Media:ExplorersClub_1.4.1.oxz|here]] for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
=== Animated Cross-hairs ===&lt;br /&gt;
&lt;br /&gt;
Download Active Crosshairs [[Media:Active_Crosshairs.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:Active_Crosshairs.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Alerting Crosshairs 1.0 [[Media:Alerting Crosshairs 1.0.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:Alerting Crosshairs 1.0.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Auto Crosshairs 1.1.1 [[Media:AutoCrosshairs 1.1.1.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:AutoCrosshairs 1.1.1.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Auto Crosshairs 1.1 [[Media:AutoCrosshairs 1.1.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Auto Crosshairs 1.0 [[Media:AutoCrosshairs.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Laser-ific Crosshairs 1.3 [[Media:LaserificCrosshairs1.3.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:LaserificCrosshairs1.3.oxz}}).&lt;br /&gt;
&lt;br /&gt;
Download Laser-ific Crosshairs 1.2 [[Media:LaserificCrosshairs1.2.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Laser-ific Crosshairs 1.1 [[Media:LaserificCrosshairs1.1.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Laser-ific Crosshairs 1.0 [[Media:LaserificCrosshairs.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Shield-tastic Crosshairs 1.0 [[Media:ShieldtasticCrosshairs_1.0.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:ShieldtasticCrosshairs_1.0.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Selecto-o-matic Crosshairs 1.0.1 [[Media:Selecto-o-matic Crosshairs 1.0.1.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:Selecto-o-matic Crosshairs 1.0.1.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Coluber HUD Auto Crosshairs patch [[Media:Coluber CH-01 Auto Crosshairs patch.oxp.oxz|here]], (downloaded {{#downloads:Coluber CH-01 Auto Crosshairs patch.oxp.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
===Sensible Tweaks &amp;amp; Miscellaney===&lt;br /&gt;
&lt;br /&gt;
Download Bullet Drive 1.0.3 [[Media:Bullet_Drive_1.0.3.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Bullet_Drive_1.0.3.oxz‎}} times).&lt;br /&gt;
&lt;br /&gt;
Download Contracted Goods Reminder [[Media:Contracted Goods Reminder.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Contracted Goods Reminder.oxz‎}} times).&lt;br /&gt;
&lt;br /&gt;
Download Dockside Services 1.0 [[Media:Dockside Services 1.0.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Dockside Services 1.0.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Galaxy Names 1.0 [[Media:Galaxy Names 1.0.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Galaxy Names 1.0.oxz‎}} times).&lt;br /&gt;
&lt;br /&gt;
Download Glare Clarifier [[Media:GlareClarifier.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:GlareClarifier.oxz‎}} times).&lt;br /&gt;
&lt;br /&gt;
Download Station Self-Destruction Codes [[Media:Station Self-Destruction Codes.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:Station Self-Destruction Codes.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Undocumented Launch [[Media:UndocumentedLaunch.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:UndocumentedLaunch.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Untrumbled [[Media:Untrumbled.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:Untrumbled.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Wildefire Docked HUDs 1.1 [[Media:Wildefire Docked HUDs 1.1.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:Wildefire Docked HUDs 1.1.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Wildefire Docked HUDs 1.0 [[Media:Wildefire Docked HUDs.oxz|here]], for Oolite 1.80.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== For Oolite 1.81 ===&lt;br /&gt;
&lt;br /&gt;
Download HUD Data - Ship Name [[Media:HUDDataShipName.oxz|here]], for Oolite 1.81 (downloaded {{#downloads:HUDDataShipName.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Display Reputation 1.3, for Oolite 1.81 (downloaded {{#downloads:DisplayReputation1.3.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:OXP authors]]&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=File:Docked_HUDs_data_sources.oxz&amp;diff=89412</id>
		<title>File:Docked HUDs data sources.oxz</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=File:Docked_HUDs_data_sources.oxz&amp;diff=89412"/>
		<updated>2026-06-12T14:05:43Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* Summary */  Hey!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Version 1.5&lt;br /&gt;
&lt;br /&gt;
This is the script that provides the function labels for Docked HUDs. If you have Docked HUDs, version 1.4, you can delete the file Scripts/docked_huds_button_data.js from within it, and this OXZ will take over. &lt;br /&gt;
&lt;br /&gt;
Here is an actual manifest of the contents of this OXZ.&lt;br /&gt;
There are no &amp;quot;strings&amp;quot; of text whatsoever in the javascript. &lt;br /&gt;
If you wish to change the words that appear, &lt;br /&gt;
edit the configuration file, &amp;quot;descriptions.plist&amp;quot;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Docked_HUDs_data_sources.oxz/&lt;br /&gt;
├── manifest.plist&lt;br /&gt;
├── README.txt&lt;br /&gt;
├── Backup/&lt;br /&gt;
│   └── descriptions.plist.txt&lt;br /&gt;
├── Config/&lt;br /&gt;
│   ├── descriptions.plist&lt;br /&gt;
│   └── world-scripts.plist&lt;br /&gt;
└── Scripts/&lt;br /&gt;
    └── docked_huds_button_data.js&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=File:Docked_HUDs_data_sources.oxz&amp;diff=89411</id>
		<title>File:Docked HUDs data sources.oxz</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=File:Docked_HUDs_data_sources.oxz&amp;diff=89411"/>
		<updated>2026-06-12T13:39:18Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: Version 1.5&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Version 1.5&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=File:Untrumbled.oxz&amp;diff=89407</id>
		<title>File:Untrumbled.oxz</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=File:Untrumbled.oxz&amp;diff=89407"/>
		<updated>2026-06-11T08:52:57Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: Wildeblood uploaded a new version of File:Untrumbled.oxz&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=User:Wildeblood&amp;diff=89403</id>
		<title>User:Wildeblood</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=User:Wildeblood&amp;diff=89403"/>
		<updated>2026-06-11T08:01:35Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: /* A.D. 2014 trinkets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Distant Space album cover.png|thumb|right|500px|Distant Space series of OXPs.]]&lt;br /&gt;
[[File:Thargoidifier album cover.png|thumb|right|500px|Thargoids! The Musical ([https://bb.oolite.space/viewtopic.php?p=302336#p302336 Original soundtrack album] by Thargoidifier)]]&lt;br /&gt;
[[File:Distant Thunder album cover.png|thumb|right|500px|Miss Sexy Voice announces goings on, and thunderous hyperspace sound.]]&lt;br /&gt;
[[File:Very Advanced Space Compass album cover.png|thumb|right|500px|It's the space compass, Jim, but not as we know it.]]&lt;br /&gt;
[[File:World Builder cover art.png|thumb|right|500px|Rule the Ooniverse your way!]]&lt;br /&gt;
[[File:Galactic_Hyperdrive_icon.png|thumb|right|500px|Galactic Hyperdrive programmers, because knowing where you're going...]]&lt;br /&gt;
[[File:Retro-Encabulator album cover.png|thumb|right|500px|You know it makes sense!]]&lt;br /&gt;
[[File:Distant Suns album cover.png|thumb|right|500px|The original Distant Suns OXP.]]&lt;br /&gt;
[[File:Trading Assistant album cover.png|thumb|right|500px|The original and genuine!]]&lt;br /&gt;
[[File:Distant Voyages cover art.png|thumb|right|500px|Rediscover the Galaxy]]&lt;br /&gt;
[[File:SE-X Drive album cover.png|thumb|right|500px|Special Equipment (Experimental)]]&lt;br /&gt;
[[File:Polarity_Reverser_cover_art.png|thumb|right|500px|Plasma conduits are especially reversible.]]&lt;br /&gt;
[[File:Distant Realms cover art.png|thumb|right|500px|Who's in charge around here?]]&lt;br /&gt;
[[File:Psionic Broadcaster.png|thumb|right|500px|Dynooverse Research really want to know how you feel.]]&lt;br /&gt;
[[File:Witch Bank.png|thumb|right|500px|More trustworthy than Westpac.]]&lt;br /&gt;
[[File:AristoShares_cover_art.png|thumb|right|500px|Stockbroker to the Stars]]&lt;br /&gt;
&lt;br /&gt;
== Trinkets ==&lt;br /&gt;
==== Latest (A.D. 2026) trinkets ====&lt;br /&gt;
 [[File:AristoShares.oxz]]&lt;br /&gt;
 [[File:Docked_HUDs.oxz]]&lt;br /&gt;
 [[File:Polarity_Reverser.oxz]]&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2025 trinkets ====&lt;br /&gt;
 [[File:AI_Trading_Backup_Datalogger_3.oxz]]&lt;br /&gt;
 [[File:DistantSpace.oxz]]                  (Meta-OXZ, downloads the [[Distant Space]] series)&lt;br /&gt;
 [[File:Distant_Locales.oxz]]               (Fills in all the other systems, not covered by Distant Realms)&lt;br /&gt;
 [[File:Distant_Realms_US.oxz]]             (See [[Distant Realms]]. Apparently they spell centre 'center')&lt;br /&gt;
 [[File:Distant Space.oxz]]                 (Red backgrounds on the start screens)&lt;br /&gt;
 [[File:Distant Thunder.oxz]]               (Sound set)&lt;br /&gt;
 [[File:Dynooverse.oxz]]                    ([[Dynooverse]] slowly changes the Ooniverse as you play the game)&lt;br /&gt;
 [[File:Lost_In_Space.oxz]]                 ([[Lost In Space]] makes random changes to the galactic charts each time the Galactic hyperdrive is used. When you return to chart 1, it looks like chart 9 and so on)&lt;br /&gt;
 [[File:Retro-Encabulator.oxz]]             (With help from GLM-4.5)&lt;br /&gt;
 [[File:Smart_Home_Control.oxz]]            (Boil your &amp;quot;smart kettle&amp;quot; while playing Oolite)&lt;br /&gt;
 [[File:Thargoidifier.oxz]]&lt;br /&gt;
 [[File:Throbtastic_Crosshairs.oxz]]        (Crosshairs throb while weapons are on-line)&lt;br /&gt;
 [[File:Very_Advanced_Space_Compass.oxz]]   (Turns your ship to face the ASC target)&lt;br /&gt;
 [[File:Visits.oxz]]                        (System Visits Counter, an alternative to Explorers' Club)&lt;br /&gt;
 [[File:Wildeblood_Manor.oxz]]              (Puts picture backdrop on the F7 screen when G1 Vetitice is selected)&lt;br /&gt;
 [[File:Witch_Bank.oxz]] (WIP/preview)      ([[Witch Bank]] Savings Bank)&lt;br /&gt;
 [[File:World_Builder.oxz]]                 ([[World Builder]] Alter the stats of a solar system)&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2024 trinkets ====&lt;br /&gt;
 [[File:Demo_Screen_Backgrounds.oxz]]       (setScreenBackground and setScreenBackgroundForKey JavaScript methods)&lt;br /&gt;
 [[File:Distant_Realms.oxz]]                (Updated 2025) ([[Distant Realms]] names regions on the F6 screen)&lt;br /&gt;
 [https://bb.oolite.space/viewtopic.php?p=298353#p298353 Docked_HUDs.oxz]                      ([[Docked HUDs]] - originally just a minimalist docked HUD, but now brimming with information for new players)&lt;br /&gt;
 [[File:Free_the_Slaves.oxz]]               (Now secretly funding the [[Free The Slaves! NGO]])&lt;br /&gt;
 [[File:SEX_Drive.oxz]]                     (It's even got a wiki page, so it must be good: [[SE-X Drive]])&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2015 trinkets ====&lt;br /&gt;
 [[File:Contracted_Goods_Reminder.oxz]]     (Updated 2025) (While I was away, Cholmondely made a wiki page for [[Contracted Goods Reminder]].)&lt;br /&gt;
 [[File:Station_Self-Destruction_Codes.oxz]](While I was away, Cholmondely made a wiki page for [[Station Self-Destruction Codes]].)&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2014 trinkets ====&lt;br /&gt;
 [[File:Display_Reputation.oxz]]            (Updated 2025 [[Display Reputation]])&lt;br /&gt;
 [[File:Explorers_Club_1.4.4.oxz]]          (Updated 2024 [[Explorers' Club]])&lt;br /&gt;
 [[File:Untrumbled.oxz]]                    (Updated 2026 [[Untrumbled]])&lt;br /&gt;
&lt;br /&gt;
==== A.D. 2012 trinkets ====&lt;br /&gt;
 [[File:Bullet_Drive_1.0.3.oxz]]            (Updated 2013) (While I was away, Cholmondely made a wiki page for [[Bullet Drive]].)&lt;br /&gt;
&lt;br /&gt;
== Current Interests ==&lt;br /&gt;
=== Album Covers ===&lt;br /&gt;
Check out my growing collection of OXP album covers floating to the right, '''over there -&amp;gt;'''&amp;lt;br/&amp;gt;&lt;br /&gt;
I am unclear what purpose they'll eventually serve. But, I'm pretty sure I'm ahead of the curve with this trend, but everyone else will catch on soon.&lt;br /&gt;
&lt;br /&gt;
=== A.I. Assistance ===&lt;br /&gt;
My current favourite AI assistants, for use with Oolite, are [https://chat.z.ai/ GLM-5.1] and [https://chat.qwen.ai/ Qwen3-Coder]. Avoid Google's Gemini, it will just waste your time.&lt;br /&gt;
&lt;br /&gt;
=== Trinkets To-do ===&lt;br /&gt;
&lt;br /&gt;
== A few comments ==&lt;br /&gt;
 Wildeblood has produced some very innovative OXPs: have a good look at the now-broken [[AI Trading Assistant]], and his [[Alternative Ooniverses OXP]], [[Docked HUDs]], [[Galactic Hyperdrive OXP|Galactic Hyperdrive]], [[MilHUD 4000]], [[WEBS System‎]] &amp;amp; [[Wide-Screen HUD]]. His work on HUDs seems to have been very influential - many of his ideas were taken up by others, later, and most of the &amp;quot;modern HUDs&amp;quot; include several of his ideas. ''Cholmondeley 2021''&lt;br /&gt;
&lt;br /&gt;
== My &amp;quot;How-to&amp;quot; OXPs ==&lt;br /&gt;
&lt;br /&gt;
A collection of micro-OXPs, each demonstrating a particular Oolite javaScript technique, which might be helpful to others seeking an example to copy.&lt;br /&gt;
&lt;br /&gt;
*How to use the planetary &amp;quot;concealment&amp;quot; property, introduced in Oolite 1.84:&lt;br /&gt;
::[[Tachyona]] is the fastest orbiting world in the co-operative. It orbits so quickly, you can see it move on the long-range chart.&lt;br /&gt;
*How to start (And, stop and clean up!) a timer, and how to randomize timer intervals:&lt;br /&gt;
::[[File:Noisy Passengers 0.1.oxz]]&lt;br /&gt;
*How to start (And, stop and clean up!) a frame callback while in flight:&lt;br /&gt;
::[[Bullet Drive]] makes the Torus Drive work somewhat more like [[classic Elite]] - no manoeuvring during flight&lt;br /&gt;
*How to set a station interface on the F4 screen:&lt;br /&gt;
::[[Station Self-Destruction Codes]] self-declared winner of the [https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=17178 competition] for unbalanced oxp-uber-mega-weapons&lt;br /&gt;
*How to change the crosshairs, without changing the whole HUD file:&lt;br /&gt;
::[[Crosshairs - Alerting]] shape of crosshairs depends on alert level (green/yellow/red)&lt;br /&gt;
*How to create the data source for a customized HUD dial:&lt;br /&gt;
::[[Data - Ship Name]] displays the name of your ship on your in-flight [[HUD]] (needs compatible HUD)&lt;br /&gt;
*How to use the player buying equipment to cause an immediate reaction (in this case, changing the HUD) unrelated to the equipment:&lt;br /&gt;
::[[Docked HUDs]] &lt;br /&gt;
*How to completely remove a worldScript which has outstayed its welcome:&lt;br /&gt;
::[[Untrumbled]] does not cure existing infestations but prevents future ones&lt;br /&gt;
*The proper way to add a new visit recording option to Explorers' Club:&lt;br /&gt;
::[[Serial Killer OXP]] the club will not record your visit to a system until you kill something&lt;br /&gt;
&lt;br /&gt;
== My OXPs ==&lt;br /&gt;
&lt;br /&gt;
In alphabetical order: &lt;br /&gt;
*[[File:Aaaa aaron.oxz|Aaron Aarts' Amazing Adventures]]. Some dutch guy tilts at windmills. (2024)&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?f=4&amp;amp;t=12248 AI Combat Assistant OXP]: ''Withdrawn''&lt;br /&gt;
*[[AI Trading Assistant]] an autotrader - put your feet up and have a gin &amp;amp; tonic: '''Broke with Oolite v.1.82'''&lt;br /&gt;
*[[Auto Crosshairs]] crosshairs change shape when target is centred&lt;br /&gt;
*[[Contracted Goods Reminder]] A reminder pops up if you mistakenly sell contracted goods on the F8 market screen&lt;br /&gt;
*[[Crosshairs - Laser-ific]] circular dial shows laser temperature&lt;br /&gt;
*[[Crosshairs - Shield-tastic]] two semi-circular dials show shield levels&lt;br /&gt;
*[[Destination ETA]] updates the ETA - and adds a spectroscope to analyse Distant Suns&lt;br /&gt;
*[[Distant Locales]] retitles all F7 screen page headings with region name or co-ordinates (2025).&lt;br /&gt;
*[[Distant Realms]] incorporates regional titles to the F6 chart (Old Worlds/Xexedi cluster/Pulsar worlds ''etc'')&lt;br /&gt;
*[[Distant Suns]] moves suns further away from planets (can combine with Sensible Sun below), and changes spectroscopic qualities&lt;br /&gt;
*[[Dockside Services]] de-nerdifies the F4 screen&lt;br /&gt;
*[[Dynooverse]] - a dynamic ooniverse where the politics/economy/population of systems changes over time. (2025)&lt;br /&gt;
*[[Free The Slaves! NGO]] - an activist non-Galcop organization (NGO) which will nag you if you accidentally buy slaves at a Galcop station. &lt;br /&gt;
*[[Galactic Hyperdrive OXP|Galactic Hyperdrive]] choose your destination in the next galaxy ('''comes with 3rd chart of next galaxy''')&lt;br /&gt;
*[[Galaxy Names OXP|Galaxy Names]] replaces Galaxy numbers with the Acorn Archimedes Galaxy names (Santaari, Colesque ''etc'').&lt;br /&gt;
*[[Glare Clarifier]] cuts solar glare when close to the sun&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?p=155952#p155952 HUD Vanisher] banishes the HUD in external &amp;quot;v&amp;quot;-views: [https://app.box.com/s/3nouit5vnhawea3yoz3n Download v.1.1]&lt;br /&gt;
*[[MilHUD 4000]] has variable brightness, de-emphasises police vessels and has a sniper-sight attached&lt;br /&gt;
*[[Sensible Sun]] moves suns further away from planets (can combine with Distant Suns below)&lt;br /&gt;
*[[Serial Killer OXP]] records systems where you killed something (a modification of the Explorer's Club OXP, 2024)&lt;br /&gt;
*[[Sniper Sight]] &lt;br /&gt;
*[[Undocumented Launch]] does this really need explaining?&lt;br /&gt;
*[[WEBS System‎]] defense for when your shields are down&lt;br /&gt;
*[[Wide-Screen HUD]] does this really need explaining?&lt;br /&gt;
*[[Wildeblood Manor]]: Traditional, mountain-top, fortress-yurt-dome house on Vetitice illustrated on F7 screen. (2025).&lt;br /&gt;
*[[World Builder]] - edit a solar system's F7 description to what you want! (2025)&lt;br /&gt;
&lt;br /&gt;
=== In this vein ===&lt;br /&gt;
*[https://bb.oolite.space/viewtopic.php?p=174714#p174714 Template for a Galactic Hyperdrive XG] to reach more galaxies (2012). Probably only works with [[Oolite#Downloading_Earlier_versions|pre-v.1.80 versions of Oolite]]. You need to know how to manipulate the [[Galaxy Seeds]], and rejig all sorts of gubbins.&lt;br /&gt;
&lt;br /&gt;
== Works in Progress (in 2015) ==&lt;br /&gt;
&lt;br /&gt;
*[[Alternative Ooniverses OXP|Alternative Ooniverses]]&lt;br /&gt;
*[[Save and Jump OXP|Save and Jump]]&lt;br /&gt;
*[[OXP List (Test)]]&lt;br /&gt;
&lt;br /&gt;
== List of OXPs clobbered with System 1.80's changes ==&lt;br /&gt;
See [https://bb.oolite.space/viewtopic.php?p=223260#p223260 here] for list, links, and a little explanation of WEBS, Alternative Ooniverse ''etc''.&lt;br /&gt;
&lt;br /&gt;
== Wildeblood ==&lt;br /&gt;
*Exhibits a morbid fascination in the [https://bb.oolite.space/viewtopic.php?f=7&amp;amp;t=17793 Australian flag]&lt;br /&gt;
*Wildeblood removed all his OXPs from circulation as he updated them for Oolite v.1.77 (''c''. 2012). A few were updated and re-released, but not all.&lt;br /&gt;
*Wildeblood did not provide licenses for many of his oxp's.&lt;br /&gt;
&lt;br /&gt;
== Version Archive ==&lt;br /&gt;
''Note that the handful of mirror sites are listed under the individual wiki pages for the relevant oxp's.''&lt;br /&gt;
=== AI Trading ===&lt;br /&gt;
*Download AI Trading Assistant 2.15.1 [[Media:Wildeblood.ai trading 2.15.1.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:Wildeblood.ai trading 2.15.1.oxz}} times).&lt;br /&gt;
*Download AI Trading Assistant 2.15 [[Media:AI_Trading_Assistant_2.15.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Assistant_2.15.oxz}} times).&lt;br /&gt;
*Download AI Trading Assistant 2.13.1 [[Media:AI_Trading_Assistant_2.13.1.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Assistant 2.13 [[Media:AI_Trading_Assistant_2.13.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Assistant_2.13.oxz}} times).&lt;br /&gt;
*Download AI Trading Assistant 2.12.4 [[Media:AI_Trading_Assistant_2.12.4.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Assistant_2.12.4.oxz}} times).&lt;br /&gt;
*Download AI Trading Assistant 2.12.3 [[Media:AI_Trading_Assistant_2.12.3.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Assistant 2.12.2 [[Media:AI_Trading_Assistant_2.12.2.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Assistant 2.12.1 [[Media:AI_Trading_Assistant_2.12.1.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Autotrade Report 0.5.3 [[Media:Autotrade_Report_Screen.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Autotrade_Report_Screen.oxz‎}} - 232 times).&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*Download AI Trading Autotrade Report 0.4 [[Media:Autotrade_Report_Email.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Autotrade_Report_Email.oxz‎}} times). --&amp;gt;&lt;br /&gt;
*Download AI Trading Backup Datalogger 2.12.3 [[Media:AI_Trading_Backup_Datalogger_2.12.3.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Backup_Datalogger_2.12.3.oxz}} times).&lt;br /&gt;
*Download AI Trading Backup Datalogger 2.12.1 [[Media:AI_Trading_Backup_Datalogger_2.12.1.oxz|here]], for Oolite 1.80.&lt;br /&gt;
*Download AI Trading Legality Reminder 1.0 [[Media:AI_Trading_Legality.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Legality.oxz}} times).&lt;br /&gt;
*Download AI Trading Purchase Book 2.12 [[Media:AI_Trading_Purchase_Book_2.12.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Purchase_Book_2.12.oxz}} times).&lt;br /&gt;
*Download AI Trading Turbotrader 1.0 [[Media:AI_Trading_Turbotrader.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_Turbotrader.oxz}} times).&lt;br /&gt;
*Download AI Trading with Yoda 1.0 [[Media:AI_Trading_with_Yoda.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:AI_Trading_with_Yoda.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
=== Distant Space ===&lt;br /&gt;
&lt;br /&gt;
Download Distant Realms [[Media:Distant_Space.oxz|here]], for Oolite 1.81 or later (downloaded {{#downloads:Distant_Space.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Distant Suns 0.5.1 [[Media:Distant_Suns_0.5.1.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:Distant_Suns_0.5.1.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
=== Explorers' Club ===&lt;br /&gt;
&lt;br /&gt;
Download 1.4.4 in OXZ format [[Media:Explorers_Club_1.4.4.oxz|here]] for Oolite 1.80 or later (downloaded {{#downloads:Explorers_Club_1.4.4.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download 1.4.3 in OXZ format [[Media:Explorers_Club_1.4.3.oxz|here]] for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download 1.4.2 in OXZ format [[Media:Explorers_Club_1.4.2.oxz|here]] for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download 1.4.1 in OXZ format [[Media:ExplorersClub_1.4.1.oxz|here]] for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
=== Animated Cross-hairs ===&lt;br /&gt;
&lt;br /&gt;
Download Active Crosshairs [[Media:Active_Crosshairs.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:Active_Crosshairs.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Alerting Crosshairs 1.0 [[Media:Alerting Crosshairs 1.0.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:Alerting Crosshairs 1.0.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Auto Crosshairs 1.1.1 [[Media:AutoCrosshairs 1.1.1.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:AutoCrosshairs 1.1.1.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Auto Crosshairs 1.1 [[Media:AutoCrosshairs 1.1.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Auto Crosshairs 1.0 [[Media:AutoCrosshairs.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Laser-ific Crosshairs 1.3 [[Media:LaserificCrosshairs1.3.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:LaserificCrosshairs1.3.oxz}}).&lt;br /&gt;
&lt;br /&gt;
Download Laser-ific Crosshairs 1.2 [[Media:LaserificCrosshairs1.2.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Laser-ific Crosshairs 1.1 [[Media:LaserificCrosshairs1.1.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Laser-ific Crosshairs 1.0 [[Media:LaserificCrosshairs.oxz|here]], for Oolite 1.80 or later.&lt;br /&gt;
&lt;br /&gt;
Download Shield-tastic Crosshairs 1.0 [[Media:ShieldtasticCrosshairs_1.0.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:ShieldtasticCrosshairs_1.0.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Selecto-o-matic Crosshairs 1.0.1 [[Media:Selecto-o-matic Crosshairs 1.0.1.oxz|here]], for Oolite 1.80 or later (downloaded {{#downloads:Selecto-o-matic Crosshairs 1.0.1.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Coluber HUD Auto Crosshairs patch [[Media:Coluber CH-01 Auto Crosshairs patch.oxp.oxz|here]], (downloaded {{#downloads:Coluber CH-01 Auto Crosshairs patch.oxp.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
===Sensible Tweaks &amp;amp; Miscellaney===&lt;br /&gt;
&lt;br /&gt;
Download Bullet Drive 1.0.3 [[Media:Bullet_Drive_1.0.3.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Bullet_Drive_1.0.3.oxz‎}} times).&lt;br /&gt;
&lt;br /&gt;
Download Contracted Goods Reminder [[Media:Contracted Goods Reminder.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Contracted Goods Reminder.oxz‎}} times).&lt;br /&gt;
&lt;br /&gt;
Download Dockside Services 1.0 [[Media:Dockside Services 1.0.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Dockside Services 1.0.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Galaxy Names 1.0 [[Media:Galaxy Names 1.0.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:Galaxy Names 1.0.oxz‎}} times).&lt;br /&gt;
&lt;br /&gt;
Download Glare Clarifier [[Media:GlareClarifier.oxz‎|here]], for Oolite 1.80 (downloaded {{#downloads:GlareClarifier.oxz‎}} times).&lt;br /&gt;
&lt;br /&gt;
Download Station Self-Destruction Codes [[Media:Station Self-Destruction Codes.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:Station Self-Destruction Codes.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Undocumented Launch [[Media:UndocumentedLaunch.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:UndocumentedLaunch.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Untrumbled [[Media:Untrumbled.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:Untrumbled.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Wildefire Docked HUDs 1.1 [[Media:Wildefire Docked HUDs 1.1.oxz|here]], for Oolite 1.80 (downloaded {{#downloads:Wildefire Docked HUDs 1.1.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Download Wildefire Docked HUDs 1.0 [[Media:Wildefire Docked HUDs.oxz|here]], for Oolite 1.80.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== For Oolite 1.81 ===&lt;br /&gt;
&lt;br /&gt;
Download HUD Data - Ship Name [[Media:HUDDataShipName.oxz|here]], for Oolite 1.81 (downloaded {{#downloads:HUDDataShipName.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
Display Reputation 1.3, for Oolite 1.81 (downloaded {{#downloads:DisplayReputation1.3.oxz}} times).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:OXP authors]]&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alioth.net/index.php?title=File:Untrumbled.oxz&amp;diff=89402</id>
		<title>File:Untrumbled.oxz</title>
		<link rel="alternate" type="text/html" href="https://wiki.alioth.net/index.php?title=File:Untrumbled.oxz&amp;diff=89402"/>
		<updated>2026-06-11T07:45:17Z</updated>

		<summary type="html">&lt;p&gt;Wildeblood: Wildeblood uploaded a new version of File:Untrumbled.oxz&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wildeblood</name></author>
		
	</entry>
</feed>