diff --git a/code/__DEFINES/construction/material.dm b/code/__DEFINES/construction/material.dm
index 24ab2eb3303..55c6d496e0c 100644
--- a/code/__DEFINES/construction/material.dm
+++ b/code/__DEFINES/construction/material.dm
@@ -68,13 +68,13 @@
//Stock market stock values.
/// How much quantity of a material stock exists for common materials like iron & glass.
-#define MATERIAL_QUANTITY_COMMON 25000
+#define MATERIAL_QUANTITY_COMMON 5000
/// How much quantity of a material stock exists for uncommon materials like silver & titanium.
-#define MATERIAL_QUANTITY_UNCOMMON 10000
+#define MATERIAL_QUANTITY_UNCOMMON 1000
/// How much quantity of a material stock exists for rare materials like gold, uranium, & diamond.
-#define MATERIAL_QUANTITY_RARE 2500
+#define MATERIAL_QUANTITY_RARE 200
/// How much quantity of a material stock exists for exotic materials like diamond & bluespace crystals.
-#define MATERIAL_QUANTITY_EXOTIC 500
+#define MATERIAL_QUANTITY_EXOTIC 50
// The number of ore vents that will spawn boulders with this material.
/// Is this material going to spawn often in ore vents? (80% of vents on lavaland)
diff --git a/code/__DEFINES/economy.dm b/code/__DEFINES/economy.dm
index 93b0678581a..7b619b274f5 100644
--- a/code/__DEFINES/economy.dm
+++ b/code/__DEFINES/economy.dm
@@ -75,7 +75,7 @@
#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_EVENT_PROBABILITY 8 //Probability of a market event firing, in percent. Fires once per material, every stock market tick.
#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
diff --git a/code/controllers/subsystem/stock_market.dm b/code/controllers/subsystem/stock_market.dm
index c9f632c7faf..6c4341adc8d 100644
--- a/code/controllers/subsystem/stock_market.dm
+++ b/code/controllers/subsystem/stock_market.dm
@@ -1,7 +1,7 @@
SUBSYSTEM_DEF(stock_market)
name = "Stock Market"
- wait = 20 SECONDS
+ wait = 60 SECONDS
init_order = INIT_ORDER_DEFAULT
runlevels = RUNLEVEL_GAME
@@ -28,7 +28,7 @@ SUBSYSTEM_DEF(stock_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_trend_life[possible_market] = rand(1,3)
materials_quantity += possible_market
materials_quantity[possible_market] = possible_market.tradable_base_quantity + (rand(-(possible_market.tradable_base_quantity) * 0.5, possible_market.tradable_base_quantity * 0.5))
@@ -80,7 +80,7 @@ SUBSYSTEM_DEF(stock_market)
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 fires of the subsystem
+ materials_trend_life[mat] = rand(1,3) // Change our trend life for x number of fires of the subsystem
else
materials_trend_life[mat] -= 1
@@ -88,14 +88,14 @@ SUBSYSTEM_DEF(stock_market)
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(quantity_baseline * 0.05, quantity_baseline * 0.05))
+ price_change = ROUND_UP(gaussian(price_units * 0.30, price_baseline * 0.15)) //If we don't ceil, small numbers will get trapped at low values
+ quantity_change = -round(gaussian(quantity_baseline * 0.15, quantity_baseline * 0.15))
if(MARKET_TREND_STABLE)
price_change = round(gaussian(0, price_baseline * 0.01))
- quantity_change = round(gaussian(0, quantity_baseline * 0.01))
+ quantity_change = round(gaussian(0, quantity_baseline * 0.5))
if(MARKET_TREND_DOWNWARD)
- price_change = -ROUND_UP(gaussian(price_units * 0.1, price_baseline * 0.05))
- quantity_change = round(gaussian(quantity_baseline * 0.05, quantity_baseline * 0.05))
+ price_change = -ROUND_UP(gaussian(price_units * 0.3, price_baseline * 0.15))
+ quantity_change = round(gaussian(quantity_baseline * 0.15, quantity_baseline * 0.15))
materials_prices[mat] = round(clamp(price_units + price_change, price_minimum, price_maximum))
materials_quantity[mat] = round(clamp(stock_quantity + quantity_change, 0, quantity_baseline * 2))
diff --git a/code/datums/stock_market_events.dm b/code/datums/stock_market_events.dm
index 81142d23002..4907bf784f6 100644
--- a/code/datums/stock_market_events.dm
+++ b/code/datums/stock_market_events.dm
@@ -83,7 +83,7 @@
/datum/stock_market_event/large_boost
name = "Large Boost!"
trend_value = MARKET_TREND_UPWARD
- trend_duration = 3
+ trend_duration = 4
circumstance = list(
"has just released a new product that raised the price of ",
"discovered a new valuable use for ",
@@ -93,14 +93,14 @@
/datum/stock_market_event/large_boost/start_event()
. = ..()
var/price_units = SSstock_market.materials_prices[mat]
- SSstock_market.materials_prices[mat] += round(gaussian(price_units * 0.5, price_units * 0.1))
+ SSstock_market.materials_prices[mat] += round(gaussian(price_units, price_units * 0.15))
SSstock_market.materials_prices[mat] = clamp(SSstock_market.materials_prices[mat], price_minimum * mat.value_per_unit, price_maximum * mat.value_per_unit)
create_news()
/datum/stock_market_event/large_drop
name = "Large Drop!"
trend_value = MARKET_TREND_DOWNWARD
- trend_duration = 5
+ trend_duration = 4
circumstance = list(
"'s latest product has seen major controversy, and resulted in a price drop for ",
"has been hit with a major lawsuit, resulting in a price drop for ",
@@ -110,6 +110,42 @@
/datum/stock_market_event/large_drop/start_event()
. = ..()
var/price_units = SSstock_market.materials_prices[mat]
- SSstock_market.materials_prices[mat] -= round(gaussian(price_units * 1.5, price_units * 0.1))
+ SSstock_market.materials_prices[mat] -= round(gaussian(price_units * 1.5, price_units * 0.15))
SSstock_market.materials_prices[mat] = clamp(SSstock_market.materials_prices[mat], price_minimum * mat.value_per_unit, price_maximum * mat.value_per_unit)
create_news()
+
+/datum/stock_market_event/hotcakes
+ name = "Selling like Hotcakes!"
+ trend_value = MARKET_TREND_UPWARD
+ trend_duration = 1
+ circumstance = list(
+ "has just released a new product that is dominating the market for ",
+ "is hitting it big! Dramatically stocking and raising the price of ",
+ ", in a surprise move, monopolized supply and has raised the price of ",
+ )
+
+/datum/stock_market_event/hotcakes/start_event()
+ . = ..()
+ SSstock_market.materials_prices[mat] = round(price_maximum * mat.value_per_unit)
+ create_news()
+
+/datum/stock_market_event/lockdown
+ name = "Lockdown!"
+ trend_value = MARKET_TREND_DOWNWARD
+ trend_duration = 2
+ circumstance = list(
+ "is being investigated by the Galactic Trade Commission, resulting in a halt of trade for ",
+ ", in a stunning move, has been embargoed by TerraGov, resulting in a halt of trade of ",
+ )
+
+/datum/stock_market_event/lockdown/handle()
+ . = ..()
+ SSstock_market.materials_quantity[mat] = 0 //Force the material to be unavailable.
+
+/datum/stock_market_event/lockdown/end_event()
+ . = ..()
+ SSstock_market.materials_quantity[mat] = initial(mat.tradable_base_quantity) //Force the material to be available again.
+ SSstock_market.materials_prices[mat] = initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT //Force the price to be reset once the lockdown is over.
+ create_news()
+
+
diff --git a/code/modules/cargo/materials_market.dm b/code/modules/cargo/materials_market.dm
index 92d83d5d0a1..947197d16f2 100644
--- a/code/modules/cargo/materials_market.dm
+++ b/code/modules/cargo/materials_market.dm
@@ -166,12 +166,14 @@
var/min_value_override = initial(traded_mat.minimum_value_override)
if(min_value_override)
minimum_value_threshold = min_value_override
-
+ else
+ minimum_value_threshold = round(initial(traded_mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 0.5)
//send data
material_data += list(list(
"name" = initial(traded_mat.name),
"price" = SSstock_market.materials_prices[traded_mat],
+ "rarity" = initial(traded_mat.value_per_unit),
"threshold" = minimum_value_threshold,
"quantity" = SSstock_market.materials_quantity[traded_mat],
"trend" = trend_string,
@@ -205,6 +207,7 @@
.["orderBalance"] = current_cost
.["orderingPrive"] = ordering_private
.["canOrderCargo"] = can_buy_via_budget
+ .["updateTime"] = SSstock_market.next_fire - world.time
/obj/machinery/materials_market/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
. = ..()
@@ -348,8 +351,8 @@
/obj/item/stock_block/Initialize(mapload)
. = ..()
- addtimer(CALLBACK(src, PROC_REF(value_warning)), 2.5 MINUTES, TIMER_DELETE_ME)
- addtimer(CALLBACK(src, PROC_REF(update_value)), 5 MINUTES, TIMER_DELETE_ME)
+ addtimer(CALLBACK(src, PROC_REF(value_warning)), 1.5 MINUTES, TIMER_DELETE_ME)
+ addtimer(CALLBACK(src, PROC_REF(update_value)), 3 MINUTES, TIMER_DELETE_ME)
/obj/item/stock_block/examine(mob/user)
. = ..()
diff --git a/tgui/packages/tgui/interfaces/MatMarket.tsx b/tgui/packages/tgui/interfaces/MatMarket.tsx
index 41b25dedb00..1f6d69c8d69 100644
--- a/tgui/packages/tgui/interfaces/MatMarket.tsx
+++ b/tgui/packages/tgui/interfaces/MatMarket.tsx
@@ -1,14 +1,23 @@
+import { sortBy } from 'common/collections';
import { BooleanLike } from 'common/react';
import { toTitleCase } from 'common/string';
import { useBackend } from '../backend';
-import { Button, Modal, Section, Stack } from '../components';
+import {
+ Button,
+ Collapsible,
+ Modal,
+ NoticeBox,
+ Section,
+ Stack,
+} from '../components';
import { formatMoney } from '../format';
import { Window } from '../layouts';
type Material = {
name: string;
quantity: number;
+ rarity: number;
trend: string;
price: number;
threshold: number;
@@ -24,6 +33,7 @@ type Data = {
materials: Material[];
catastrophe: BooleanLike;
CARGO_CRATE_VALUE: number;
+ updateTime: number;
};
export const MatMarket = (props) => {
@@ -66,24 +76,35 @@ export const MatMarket = (props) => {
)
}
>
- Buy orders for material sheets placed here will be ordered on the next
- cargo shipment.
-
- To sell materials, please insert sheets or similar stacks of
- materials. All minerals sold on the market directly are subject to an
- 20% market fee. To prevent market manipulation, all registered traders
- can buy a total of 10 full stacks of materials at a time.
-
- All new purchases will include the cost of the shipped crate,
- which may be recycled afterwards.
+
+
+ Buy orders for material sheets placed here will be ordered on the
+ next cargo shipment.
+
+ To sell materials, please insert sheets or similar stacks of
+ materials. All minerals sold on the market directly are subject to
+ an 20% market fee. To prevent market manipulation, all registered
+ traders can buy a total of 10 full stacks of materials at a time.
+