From 7b8efd3daa7ea75129db5dce0717809bf539cf10 Mon Sep 17 00:00:00 2001 From: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com> Date: Wed, 22 Apr 2026 16:50:02 -0400 Subject: [PATCH] Stock Market UI Tweaks and improvements (#95564) ## About The Pull Request This PR pulls forward some UI tweaks that I made in #93183, but cleaned up and with some additional adjustments. This adjusts a bit of the GMM Ui, cutting out the horizontal quantity measurement and rolling that into the supply/order information in the middle. image Adds a hit of color as well to show what materials are currently being ordered. Adds a bit of tooltip text in order to showcase the range of prices that a mineral can be bought and sold at, in order to showcase why lower value minerals like glass/iron can be bought and sold from. In addition to this, also tweaks the logic on the disabling of buttons to better reflect these thresholds, so you can buy and sell when sitting on those thresholds. ## Why It's Good For The Game The market UI needs to exist in a sort of "spreadsheet" format, in order to see all the values, all the costs, and make decisions about what you what to buy and how many. That said, it's clunky, and there's a lot of complexity related to buying and selling materials already that I would love to cut down on. This helps trim the UI, makes it a bit smaller, but adds in some missing information that even I don't have memorized for the purposes of regular gameplay. ## Changelog :cl: qol: The GMM Ui can now tell you the minimum and maximum price ranges that a material will sell for. qol: You can now sell materials on the edge of their buying and selling thresholds. (This really only effects iron and glass, practically) /:cl: --- code/modules/cargo/materials_market.dm | 6 +- tgui/packages/tgui/interfaces/MatMarket.tsx | 117 +++++++++++++------- 2 files changed, 83 insertions(+), 40 deletions(-) diff --git a/code/modules/cargo/materials_market.dm b/code/modules/cargo/materials_market.dm index 390ac1d0ee9..207a47ae0c6 100644 --- a/code/modules/cargo/materials_market.dm +++ b/code/modules/cargo/materials_market.dm @@ -130,6 +130,7 @@ var/sheet_to_buy var/requested_amount var/minimum_value_threshold = 0 + var/maximum_value_threshold = 0 var/elastic_mult = 1 for(var/datum/material/traded_mat as anything in SSstock_market.materials_prices) //convert trend into text @@ -168,6 +169,8 @@ else minimum_value_threshold = round(initial(traded_mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 0.5) + maximum_value_threshold = round(initial(traded_mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 3) + //Pulling elastic modifier into data. for(var/datum/export/material/market/export_est in GLOB.exports_list) if(export_est.material_id == traded_mat) @@ -177,7 +180,8 @@ "name" = initial(traded_mat.name), "price" = SSstock_market.materials_prices[traded_mat], "rarity" = initial(traded_mat.value_per_unit), - "threshold" = minimum_value_threshold, + "min_threshold" = minimum_value_threshold, + "max_threshold" = maximum_value_threshold, "quantity" = SSstock_market.materials_quantity[traded_mat], "trend" = trend_string, "color" = color_string, diff --git a/tgui/packages/tgui/interfaces/MatMarket.tsx b/tgui/packages/tgui/interfaces/MatMarket.tsx index f87a788c2fe..516df55d06e 100644 --- a/tgui/packages/tgui/interfaces/MatMarket.tsx +++ b/tgui/packages/tgui/interfaces/MatMarket.tsx @@ -1,11 +1,13 @@ import { sortBy } from 'es-toolkit'; import { + Box, Button, Collapsible, Modal, NoticeBox, Section, Stack, + Tooltip, } from 'tgui-core/components'; import { formatMoney } from 'tgui-core/format'; import type { BooleanLike } from 'tgui-core/react'; @@ -20,7 +22,8 @@ type Material = { rarity: number; trend: string; price: number; - threshold: number; + min_threshold: number; + max_threshold: number; color: string; requested: number; elastic: number; @@ -56,17 +59,18 @@ export const MatMarket = (props) => { const multiplier = orderingPrive ? 1.1 : 1; return ( - + {!!catastrophe && }
{ ) } > - - - 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 - a scaling value decrease per material, but this will recover over - time. To prevent market manipulation, all registered traders can - buy a total of 10 full stacks of materials at a time. -

- When selling materials, prices will be decreased based on the - elastic modifier of the material, which will recover over time. -

- All new purchases will include the cost of the shipped crate, - which may be recycled afterwards. -
-
@@ -127,7 +113,7 @@ export const MatMarket = (props) => { (material, i) => (
- + { Elasticity: {Math.round(material.elastic)}% - - Trading at {formatMoney(material.price)} cr. + + + Trading at
{formatMoney(material.price)} cr.
+
+
- {material.price < material.threshold ? ( + {material.price < material.min_threshold ? ( Material price critical!
Trading temporarily suspended.
) : ( - {material.quantity || 'Zero'} sheets of{' '} - {material.name} trading.{' '} - {material.requested || 'Zero'} sheets ordered. + + {material.quantity || 'Zero'} sheets of{' '} + {material.name} trading.{' '} + + 0 ? 'lightblue' : 'white'} + > + {material.requested || 'Zero'} sheets ordered. + )} { - {material.requested > 0 && ( - x {material.requested} - )}
), )} + + + 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 + a scaling value decrease per material, but this will recover over + time. To prevent market manipulation, all registered traders can + buy a total of 10 full stacks of materials at a time. +

+ When selling materials, prices will be decreased based on the + elastic modifier of the material, which will recover over time. +

+ All new purchases will include the cost of the shipped crate, + which may be recycled afterwards. +
+
); @@ -299,3 +325,16 @@ const MarketCrashModal = (props) => { ); }; + +type rangeTextProps = { + minPrice: number; + maxPrice: number; +} + +function rangeText(props: rangeTextProps) { + const {minPrice, maxPrice} = props; + return ( + "This material can be bought and sold between " + formatMoney(minPrice) + + " - " + formatMoney(maxPrice) + " cr." + ) +}