Skip to content

Commit

Permalink
[MIRROR] [MDB IGNORE] ArCargo: Adds the Galactic Materials Stock Mark…
Browse files Browse the repository at this point in the history
…et V1.2 (Free Market Edition) (#7983)

Original PR: tgstation/tgstation#78500
-----

## About The Pull Request

**This PR is a rerelease of #78164, with some bells and whistles.** As
such, most of the core functionality is the same, but with some tweaks
to balance the gameplay and prevent bike levels of profit. I've tried to
bold the new additions to make it easier to read for those coming back
for the second pass.


![image](https://github.com/tgstation/tgstation/assets/41715314/ff9bf038-524d-44fc-81bb-c6ff97fef6dd)
This PR adds a new machine that can be bought called the **Galactic
Mineral Market** (GMM). The Galactic Mineral Market (GMM) allows you to
buy and sell minerals wholesale from the market machine. It goes
something like this:

### 1. Getting the Machine:
The GMM can be bought as an un-assembled machine for 600 credits from
cargo. It's a low cost, but its not mapped in standard, so if you're
confident in your miners, you shouldn't necessarily need one for the
department. Otherwise, it's available for other crewmembers to buy for
cost.

The cargo pack comes will all supplies necessary to finish the machine.
Tools not included.

### 2. Buying Low
Using the machine's UI, you can see all traded minerals and their
associated prices. Buy prices are played straight, and can be bought for
material price, times the quantity. The order is then instantly placed
on the cargo shuttle, and will be deducted from the buyer's account on
shuttle send. **A single order can only have 10 different stacks of
materials in it. So, that can be 100 sheets of iron and 1 of everything
else, or 500 sheets of iron. After that you're blocked from buying more
sheets until you've sent the order.**

Cargo staff with standard cargo access may toggle the machine to order
directly from the cargo budget. Otherwise, materials are only purchased
from private accounts.

All purchases are treated as private and must be opened by the recipient
like private orders.

### 3. Selling High

It's stocks time. To sell minerals on the market, simply insert any
relevant metal stock into the machine. This produces a totally original
and not-a-bounty-cube stock block, which can be sold on the cargo
shuttle for cargo funds. Stock blocks can also be price-tagged as well
following their standard process.

**Stock blocks start out a bright pink and are worth the value of that
material at that time, but over time their color will degrade. After a
full 5 minutes, stock blocks will switch over to a purple hue, and their
value will once again become liquid, subject to the current market
value. This encourages players to be a bit more fast on their feet than
before instead of just waiting forever for all of their investments to
arrive at the perfect value, before the inevitable "rest of the game"
tries to upend your investing.**

Sold cargo stocks are subject at a 20% processing fee as part of the
galactic mineral market.
### 4. Outside Factors

**In-game events like the Crab-17 or the Market crash event will cause
stocks to bottom out completely, and for the market to become
unavailable until the market stabilizes. Thankfully, once the market has
crashed, typically stocks will recovery and gain back some value,
allowing for fast acting market movers to capitalize on rough markets.**

**Additionally, low value materials like iron and glass have an extra
stipulation, as their value goes all the way down to 0 credits. In that
case, you are unable to buy them at that value as a market protection.
Be careful that you don't see a reset or crash when you're planning on
selling your horde of iron and glass stocks!**

Additionally, market events can occur during the round that can more
sharply adjust a single stock's price and completely rebound it's
trajectory. These events are always mentioned in the station
announcement's economics report.

### Other notes:
The market does not cover all minerals, partially for consistency
purposes as well as for balance reasons. Plasma, being a unique material
that only Nanotrasen has their hands on, is the sole exporter of plasma
in the system, so it stands to reason that it's not on the market, and
remains a solo export. Bananium, as it has a rare and expensive
conversion rate, works the opposite way, and as such isn't listed on the
market either, with the sole source being single cargo sales. All others
just don't make much sense to include into the market at this second, so
I left them out for now.

**Alright now below I'm going to cover the math and shit so if that's
not what you care about then please scroll past.**
<details>
  <summary>Warning: Arcane is about to talk about the math</summary>
Alright.
So this adds a new stock_market subsystem, which fires once every 20
seconds. I'm still fairly new to subsystem design so I'm probably going
to need some feedback on cleaning this up to make it look nicer and run
smoother.

So we have 4 associated lists, each attached to the relevant traded
datum; this tracks prices, market trends, how long that trend is going
to last in SS fires, and market quantity.

Prices fluctuate between 0.5x and 3x the material's single sheet value.
This could be tweaked even farther in the future, but for now I'm
keeping it at this nice clean margin. Prices fluctuate based on a
gaussian normal distribution that is centered on different points based
on their **trend**. Upward trending materials are centered in such a way
that they'll almost certainly go upwards, but being that it's based on a
random chance, not always. Vis versa, downward trends should tend to
lose value at about the same rate. We also change our rounding based on
this trend data, in order to prevent low price values like iron and
glass from getting stuck in the same value or freefall drop over time
just because of rounding down. Similarly, neutral trending materials
will not change nearly as much, and will generally stay at around the
same amount.

When buying or selling a material, the quantity of that material will
change on the market. The magnitude of that change depends on how much
of that material currently exists on the market. Buying a low quantity
material like diamond for example will tangibly increase that material's
cost, while buying stacks and stacks of iron and glass won't do much
damage to the price of iron as there's usually around 500 full stacks on
the market to start with. It's applied at a relative percentage of
(qty_changed / new_total_on_market) * price of goods bought/sold at.

In addition to that, there are random "market events" that can occur
randomly, which you might miss if you don't follow the newscaster
economy news. These three events are fairly barebones now, but in
general they have a 1% chance of happening per material, and can more
dramatically increase, decrease, or fully reset the value of a material
on the market back to it's standard value. This opens up for doing more
with it in the future, but that's a later problem.
</details>


## Why It's Good For The Game

This independently resolves some issues related to #78040, that being
that lowpop stations, or shifts with few miners would have a new way to
be able to still get some access to minerals in a given round. This also
provides a unique minigame and alternative way to acquire money in a
given shift, using minerals.

**"But Arcane,** I hear you ask. **"Isn't this just the same thing you
tried doing way back when and then reverted in #50537?**
Well, fuck man, how you doing I haven't see you around in forever also
no you're completely wrong and here's why

**This PR is no longer contingent on the rest of ArcMining in it's
current iteration.** I have introduced some extra factors into the
gameplay as well to try and curb the creation of bikes within gameplay.
This also provides a massive benefit to round progression and gives the
QM and the cargo members the ability to prevent round progress from
stalling by buying round-critical resources.

Not to mention, as the GMM is not cargo required, more cargo integrated,
it also functions as economy content for the rest of the crew.

## Changelog
:cl:
add: A new export has arrived in the imports section, the Galactic
Materials Market! You can use this to buy and sell minerals for profit
or cost, as well as stock your station when you don't have any miners.
add: Insert sheets of minerals into the Galactic Materials Market to
convert them into a stock block, allowing you to lock in your price for
5 minutes. Wait too long and it'll be subject to market value again!
add: Minerals can be bought on the market either using the station's
cargo budget by cargo crew, or privately by everyone else.
del: Any material stacks that can be bought and sold on the market
before have been removed from the cargo catalog.
/:cl:

---------

Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com>
Co-authored-by: Jeremiah <42397676+jlsnow301@users.noreply.github.com>
Co-authored-by: Zephyr <12817816+ZephyrTFA@users.noreply.github.com>
  • Loading branch information
4 people committed Oct 2, 2023
1 parent 08c5347 commit be30513
Show file tree
Hide file tree
Showing 17 changed files with 842 additions and 83 deletions.
27 changes: 27 additions & 0 deletions code/__DEFINES/economy.dm
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,30 @@
#define PAYMENT_CLINICAL "clinical"
#define PAYMENT_FRIENDLY "friendly"
#define PAYMENT_ANGRY "angry"

#define MARKET_TREND_UPWARD 1
#define MARKET_TREND_DOWNWARD -1
#define MARKET_TREND_STABLE 0

#define MARKET_EVENT_PROBABILITY 1 //Probability of a market event firing, in percent. Fires once per material, every 20 seconds.

#define MARKET_PROFIT_MODIFIER 0.8 //We don't make every sale a 1-1 of the actual buy price value, like with real life taxes and to encourage more smart trades

/// Create quantity subtypes for stock market datums.
#define MARKET_QUANTITY_HELPERS(path) ##path/one {\
amount = 1; \
} \
##path/five {\
amount = 5; \
} \
##path/ten {\
amount = 10; \
} \
##path/twenty_five {\
amount = 25; \
} \
##path/fifty {\
amount = 50; \
}


10 changes: 10 additions & 0 deletions code/__DEFINES/materials.dm
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,13 @@
#define MATERIAL_SLOWDOWN_PLASTEEL (0.05)
/// The slowdown value of one [SHEET_MATERIAL_AMOUNT] of alien alloy.
#define MATERIAL_SLOWDOWN_ALIEN_ALLOY (0.1)

//Stock market stock values.
/// How much quantity of a material stock exists for common materials like iron & glass.
#define MATERIAL_QUANTITY_COMMON 25000
/// How much quantity of a material stock exists for uncommon materials like silver & titanium.
#define MATERIAL_QUANTITY_UNCOMMON 10000
/// How much quantity of a material stock exists for rare materials like gold, uranium, & diamond.
#define MATERIAL_QUANTITY_RARE 2500
/// How much quantity of a material stock exists for exotic materials like diamond & bluespace crystals.
#define MATERIAL_QUANTITY_EXOTIC 500
4 changes: 3 additions & 1 deletion code/controllers/subsystem/economy.dm
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ SUBSYSTEM_DEF(economy)
var/effective_mailcount = round(living_player_count()/(inflation_value - 0.5)) //More mail at low inflation, and vis versa.
mail_waiting += clamp(effective_mailcount, 1, MAX_MAIL_PER_MINUTE * seconds_per_tick)

SSstock_market.news_string = ""

/**
* Handy proc for obtaining a department's bank account, given the department ID, AKA the define assigned for what department they're under.
*/
Expand Down Expand Up @@ -172,7 +174,7 @@ SUBSYSTEM_DEF(economy)
fluff_string = ", but company countermeasures protect <b>YOU</b> from being affected!"
else
fluff_string = ", and company countermeasures are failing to protect <b>YOU</b> from being affected. We're all doomed!"
earning_report = "<b>Sector Economic Report</b><br><br> Sector vendor prices is currently at <b>[SSeconomy.inflation_value()*100]%</b>[fluff_string]<br><br> The station spending power is currently <b>[station_total] Credits</b>, and the crew's targeted allowance is at <b>[station_target] Credits</b>.<br><br> That's all from the <i>Nanotrasen Economist Division</i>."
earning_report = "<b>Sector Economic Report</b><br><br> Sector vendor prices is currently at <b>[SSeconomy.inflation_value()*100]%</b>[fluff_string]<br><br> The station spending power is currently <b>[station_total] Credits</b>, and the crew's targeted allowance is at <b>[station_target] Credits</b>.<br><br>[SSstock_market.news_string] That's all from the <i>Nanotrasen Economist Division</i>."
GLOB.news_network.submit_article(earning_report, "Station Earnings Report", "Station Announcements", null, update_alert = FALSE)
return TRUE

Expand Down
154 changes: 154 additions & 0 deletions code/controllers/subsystem/stock_market.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@

SUBSYSTEM_DEF(stock_market)
name = "Stock Market"
wait = 20 SECONDS
init_order = INIT_ORDER_DEFAULT
runlevels = RUNLEVEL_GAME

/// Associated list of materials and their prices at the given time.
var/list/materials_prices = list()
/// Associated list of materials alongside their market trends. 1 is up, 0 is stable, -1 is down.
var/list/materials_trends = list()
/// Associated list of materials alongside the life of it's current trend. After it's life is up, it will change to a new trend.
var/list/materials_trend_life = list()
/// Associated list of materials alongside their available quantity. This is used to determine how much of a material is available to buy, and how much buying and selling affects the price.
var/list/materials_quantity = list()
/// HTML string that is used to display the market events to the player.
var/news_string = ""

/datum/controller/subsystem/stock_market/Initialize()
for(var/datum/material/possible_market as anything in subtypesof(/datum/material)) // I need to make this work like this, but lets hardcode it for now
if(initial(possible_market.tradable))
materials_prices += possible_market
materials_prices[possible_market] = initial(possible_market.value_per_unit) * SHEET_MATERIAL_AMOUNT

materials_trends += possible_market
materials_trends[possible_market] = rand(MARKET_TREND_DOWNWARD,MARKET_TREND_UPWARD) //aka -1 to 1

materials_trend_life += possible_market
materials_trend_life[possible_market] = rand(1,10)

materials_quantity += possible_market
materials_quantity[possible_market] = initial(possible_market.tradable_base_quantity) + (rand(-initial(possible_market.tradable_base_quantity) * 0.5, initial(possible_market.tradable_base_quantity) * 0.5))
return SS_INIT_SUCCESS
/datum/controller/subsystem/stock_market/fire(resumed)
for(var/datum/material/market as anything in materials_prices)
handle_trends_and_price(market)

/**
* Handles shifts in the cost of materials, and in what direction the material is most likely to move.
*/
/datum/controller/subsystem/stock_market/proc/handle_trends_and_price(datum/material/mat)
if(prob(MARKET_EVENT_PROBABILITY))
handle_market_event(mat)
return
var/trend = materials_trends[mat]
var/trend_life = materials_trend_life[mat]

var/price_units = materials_prices[mat]
var/price_minimum = round(initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 0.5)
if(!isnull(initial(mat.minimum_value_override)))
price_minimum = round(initial(mat.minimum_value_override) * SHEET_MATERIAL_AMOUNT)
var/price_maximum = round(initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 3)
var/price_baseline = initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT

var/stock_quantity = materials_quantity[mat]

if(HAS_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING)) //We hardset to the worst possible price and lowest possible impact if sold
materials_prices[mat] = price_minimum
materials_quantity[mat] = stock_quantity * 2
materials_trends[mat] = MARKET_TREND_DOWNWARD
trend_life = materials_trend_life[mat] = 1
return

if(trend_life == 0)
///We want to scale our trend so that if we're closer to our minimum or maximum price, we're more likely to trend the other way.
if((price_units < price_baseline))
var/chance_swap = 100 - ((clamp((price_units - price_minimum), 1, 1000) / (price_baseline - price_minimum))*100)
if(prob(chance_swap))
materials_trends[mat] = MARKET_TREND_UPWARD
else
materials_trends[mat] = MARKET_TREND_STABLE
else if((price_units > price_baseline))
var/chance_swap = 100 - ((clamp((price_units - price_maximum), 1, 1000) / (price_maximum - price_baseline))*100)
if(prob(chance_swap))
materials_trends[mat] = MARKET_TREND_DOWNWARD
else
materials_trends[mat] = MARKET_TREND_STABLE
materials_trend_life[mat] = rand(3,10) // Change our trend life for x number of cycles
else
materials_trend_life[mat] -= 1

var/price_change = 0
var/quantity_change = 0
switch(trend)
if(MARKET_TREND_UPWARD)
price_change = ROUND_UP(gaussian(price_units * 0.1, price_baseline * 0.05)) //If we don't ceil, small numbers will get trapped at low values
quantity_change = -round(gaussian(stock_quantity * 0.1, stock_quantity * 0.05))
if(MARKET_TREND_STABLE)
price_change = round(gaussian(0, price_baseline * 0.01))
quantity_change = round(gaussian(0, stock_quantity * 0.01))
if(MARKET_TREND_DOWNWARD)
price_change = -ROUND_UP(gaussian(price_units * 0.1, price_baseline * 0.05))
quantity_change = round(gaussian(stock_quantity * 0.1, stock_quantity * 0.05))
materials_prices[mat] = round(clamp(price_units + price_change, price_minimum, price_maximum))
materials_quantity[mat] = round(clamp(stock_quantity + quantity_change, 0, initial(mat.tradable_base_quantity) * 2))

/**
* Market events are a way to spice up the market and make it more interesting.
* Randomly one will occur to a random material, and it will change the price of that material more drastically, or reset it to a stable price.
* Events are also broadcast to the newscaster as a fun little fluff piece. Good way to tell some lore as well, or just make a joke.
*/
/datum/controller/subsystem/stock_market/proc/handle_market_event(datum/material/mat)

var/company_name = list( // Pick a random company name from the list, I let copilot make a few up for me which is why some suck
"Nakamura Engineering",
"Robust Industries, LLC",
"MODular Solutions",
"SolGov",
"Australicus Industrial Mining",
"Vey-Medical",
"Aussec Armory",
"Dreamland Robotics"
)
var/circumstance
var/event = rand(1,3)

var/price_units = materials_prices[mat]
var/price_minimum = round(initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 0.5)
if(!isnull(initial(mat.minimum_value_override)))
price_minimum = round(initial(mat.minimum_value_override) * SHEET_MATERIAL_AMOUNT)
var/price_maximum = round(initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 3)
var/price_baseline = initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT

switch(event)
if(1) //Reset to stable
materials_prices[mat] = price_baseline
materials_trends[mat] = MARKET_TREND_STABLE
materials_trend_life[mat] = 1
circumstance = pick(list(
"[pick(company_name)] has been bought out by a private investment firm. As a result, <b>[initial(mat.name)]</b> is now stable at <b>[materials_prices[mat]] cr</b>.",
"Due to a corporate restructuring, the largest supplier of <b>[initial(mat.name)]</b> has had the price changed to <b>[materials_prices[mat]] cr</b>.",
"<b>[initial(mat.name)]</b> is now under a monopoly by [pick(company_name)]. The price has been changed to <b>[materials_prices[mat]] cr</b> accordingly."
))
if(2) //Big boost
materials_prices[mat] += round(gaussian(price_units * 0.5, price_units * 0.1))
materials_prices[mat] = clamp(materials_prices[mat], price_minimum, price_maximum)
materials_trends[mat] = MARKET_TREND_UPWARD
materials_trend_life[mat] = rand(1,5)
circumstance = pick(list(
"[pick(company_name)] has just released a new product that uses <b>[initial(mat.name)]</b>! As a result, the price has been raised to <b>[materials_prices[mat]] cr</b>.",
"Due to [pick(company_name)] finding a new property of <b>[initial(mat.name)]</b>, its price has been raised to <b>[materials_prices[mat]] cr</b>.",
"A study has found that <b>[initial(mat.name)]</b> may run out within the next 100 years. The price has raised to <b>[materials_prices[mat]] cr</b> due to panic."
))
if(3) //Big drop
materials_prices[mat] -= round(gaussian(price_units * 1.5, price_units * 0.1))
materials_prices[mat] = clamp(materials_prices[mat], price_minimum, price_maximum)
materials_trends[mat] = MARKET_TREND_DOWNWARD
materials_trend_life[mat] = rand(1,5)
circumstance = pick(list(
"[pick(company_name)]'s latest product has seen major controversy, and as a result, the price of <b>[initial(mat.name)]</b> has dropped to <b>[materials_prices[mat]] cr</b>.",
"Due to a new competitor, the price of <b>[initial(mat.name)]</b> has dropped to <b>[materials_prices[mat]] cr</b>.",
"<b>[initial(mat.name)]</b> has been found to be a carcinogen. The price has dropped to <b>[materials_prices[mat]] cr</b> due to panic."
))
news_string += circumstance + "<br>" // Add the event to the news_string, formatted for newscasters.
8 changes: 8 additions & 0 deletions code/datums/materials/_material.dm
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,16 @@ Simple datum which is instanced once per type and is used for every object of sa
var/strength_modifier = 1
///This is a modifier for integrity, and resembles the strength of the material
var/integrity_modifier = 1

///This is the amount of value per 1 unit of the material
var/value_per_unit = 0
///This is the minimum value of the material, used in the stock market for any mat that isn't set to null
var/minimum_value_override = null
///Is this material traded on the stock market?
var/tradable = FALSE
///If this material is tradable, what is the base quantity of the material on the stock market?
var/tradable_base_quantity = 0

///Armor modifiers, multiplies an items normal armor vars by these amounts.
var/armor_modifiers = list(MELEE = 1, BULLET = 1, LASER = 1, ENERGY = 1, BOMB = 1, BIO = 1, FIRE = 1, ACID = 1)
///How beautiful is this material per unit.
Expand Down
18 changes: 18 additions & 0 deletions code/datums/materials/basemats.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/iron
value_per_unit = 5 / SHEET_MATERIAL_AMOUNT
minimum_value_override = 0
tradable = TRUE
tradable_base_quantity = MATERIAL_QUANTITY_COMMON

/datum/material/iron/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5)
Expand All @@ -25,6 +28,9 @@
shard_type = /obj/item/shard
debris_type = /obj/effect/decal/cleanable/glass
value_per_unit = 5 / SHEET_MATERIAL_AMOUNT
minimum_value_override = 0
tradable = TRUE
tradable_base_quantity = MATERIAL_QUANTITY_COMMON
beauty_modifier = 0.05
armor_modifiers = list(MELEE = 0.2, BULLET = 0.2, ENERGY = 1, BIO = 0.2, FIRE = 1, ACID = 0.2)

Expand Down Expand Up @@ -56,6 +62,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/silver
value_per_unit = 50 / SHEET_MATERIAL_AMOUNT
tradable = TRUE
tradable_base_quantity = MATERIAL_QUANTITY_UNCOMMON
beauty_modifier = 0.075

/datum/material/silver/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
Expand All @@ -72,6 +80,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/gold
value_per_unit = 125 / SHEET_MATERIAL_AMOUNT
tradable = TRUE
tradable_base_quantity = MATERIAL_QUANTITY_RARE
beauty_modifier = 0.15
armor_modifiers = list(MELEE = 1.1, BULLET = 1.1, LASER = 1.15, ENERGY = 1.15, BOMB = 1, BIO = 1, FIRE = 0.7, ACID = 1.1)

Expand All @@ -90,6 +100,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
alpha = 132
starlight_color = COLOR_BLUE_LIGHT
value_per_unit = 500 / SHEET_MATERIAL_AMOUNT
tradable = TRUE
tradable_base_quantity = MATERIAL_QUANTITY_EXOTIC
beauty_modifier = 0.3
armor_modifiers = list(MELEE = 1.3, BULLET = 1.3, LASER = 0.6, ENERGY = 1, BOMB = 1.2, BIO = 1, FIRE = 1, ACID = 1)

Expand All @@ -106,6 +118,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/uranium
value_per_unit = 100 / SHEET_MATERIAL_AMOUNT
tradable = TRUE
tradable_base_quantity = MATERIAL_QUANTITY_RARE
beauty_modifier = 0.3 //It shines so beautiful
armor_modifiers = list(MELEE = 1.5, BULLET = 1.4, LASER = 0.5, ENERGY = 0.5, FIRE = 1, ACID = 1)

Expand Down Expand Up @@ -173,6 +187,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
beauty_modifier = 0.5
sheet_type = /obj/item/stack/sheet/bluespace_crystal
value_per_unit = 300 / SHEET_MATERIAL_AMOUNT
tradable = TRUE
tradable_base_quantity = MATERIAL_QUANTITY_EXOTIC

/datum/material/bluespace/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.reagents.add_reagent(/datum/reagent/bluespace, rand(5, 8))
Expand Down Expand Up @@ -216,6 +232,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/titanium
value_per_unit = 125 / SHEET_MATERIAL_AMOUNT
tradable = TRUE
tradable_base_quantity = MATERIAL_QUANTITY_UNCOMMON
beauty_modifier = 0.05
armor_modifiers = list(MELEE = 1.35, BULLET = 1.3, LASER = 1.3, ENERGY = 1.25, BOMB = 1.25, BIO = 1, FIRE = 0.7, ACID = 1)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,15 @@
greyscale_colors = CIRCUIT_COLOR_SUPPLY
build_path = /obj/machinery/rnd/production/techfab/department/cargo

/obj/item/circuitboard/machine/materials_market
name = "Galactic Materials Market"
greyscale_colors = CIRCUIT_COLOR_SUPPLY
build_path = /obj/machinery/materials_market
req_components = list(
/obj/item/stack/cable_coil = 5,
/datum/stock_part/scanning_module = 1,
/datum/stock_part/card_reader = 1)

//Misc
/obj/item/circuitboard/machine/sheetifier
name = "Sheet-meister 2000"
Expand Down

0 comments on commit be30513

Please sign in to comment.