Fixes material market prices going negative & runtime when buying materials (#79732)

## About The Pull Request
- Fixes #79114
- Fixes #79245

The hope is that it should fix these 2 issues because looking at the
math is seems solid. This PR ensures 2 things
- If the current market price of a material is 0 then neither the market
quantity nor its price is changed because the material is worthless at
that point so adding more is just meaningless
- Corrects the formulae to calculate the new price so we get the right
rate of change

For more details on how this bug occurs refer to
https://github.com/tgstation/tgstation/issues/79114#issuecomment-1790757814

Mentioning @Iajret in the changelog cause credits(no pun intended) goes
to them for discovering said bug

This also corrects a runtime that went unresolved in
- #79307

I could not get my code suggestion there in time so i'm just carrying it
over here

## Changelog
SyncIt21, Iajret
🆑
fix: selling large amount of mats in cargo should not give you infinite
credits
fix: runtime when adjusting material market after buying 
/🆑
This commit is contained in:
SyncIt21
2023-11-18 23:19:35 +01:00
committed by GitHub
parent 44fbc61c3c
commit b39953ebce
2 changed files with 37 additions and 12 deletions
+14 -3
View File
@@ -134,13 +134,24 @@
/datum/export/material/market/sell_object(obj/sold_item, datum/export_report/report, dry_run, apply_elastic)
. = ..()
var/amount = get_amount(sold_item)
var/price = get_cost(sold_item)
if(!amount)
return
//This formula should impact lower quantity materials greater, and higher quantity materials less. Still, it's a bit rough. Tweaking may be needed.
if(!dry_run)
//this material is worthless. no point adding more to the stock
var/market_price = SSstock_market.materials_prices[material_id]
if(!market_price)
return
//decrease the market price
market_price -= round((market_price) * (amount / (amount + SSstock_market.materials_quantity[material_id])))
if(market_price < 0)
market_price = 0
SSstock_market.materials_prices[material_id] = market_price
//increase the stock
SSstock_market.materials_quantity[material_id] += amount
SSstock_market.materials_prices[material_id] -= round((price) * (amount / (amount + SSstock_market.materials_quantity[material_id])))
//This formula should impact lower quantity materials greater, and higher quantity materials less. Still, it's a bit rough. Tweaking may be needed.
// Stock blocks are a special type of export that can be used to sell a quantity of materials at a specific price on the market.
+23 -9
View File
@@ -124,14 +124,28 @@
src.contains = contains
/datum/supply_pack/custom/minerals/fill(obj/structure/closet/crate/C)
. = ..()
//Remove our material sheets from SSstock_market's materials_quantity equal to the quantity within the crate.
for(var/obj/item/stack/sheet/possible_stack as anything in contains)
if(!ispath(possible_stack, /obj/item/stack/sheet))
var/material_type = initial(possible_stack.material_type)
//in case we ordered more than what's in the market at the time due to market fluctuations
//we find the min of what was ordered & what's actually available in the market at this point of time
var/market_quantity = SSstock_market.materials_quantity[material_type]
var/available_quantity = min(contains[possible_stack], market_quantity)
if(!available_quantity)
continue
if(!possible_stack.material_type)
continue
if(!SSstock_market.materials_quantity[possible_stack.material_type])
continue
SSstock_market.materials_quantity[possible_stack.material_type] -= contains[possible_stack]
SSstock_market.materials_prices[possible_stack.material_type] += round((SSstock_market.materials_prices[possible_stack.material_type]) * (contains[possible_stack] / (SSstock_market.materials_quantity[possible_stack.material_type] - contains[possible_stack])))
//spawn the ordered stack inside the crate
var/sheets_to_spawn = available_quantity
while(sheets_to_spawn)
var/spawn_quantity = min(sheets_to_spawn, MAX_STACK_SIZE)
var/obj/item/stack/sheet/ordered_stack = new possible_stack(C, spawn_quantity)
if(admin_spawned)
ordered_stack.flags_1 |= ADMIN_SPAWNED_1
sheets_to_spawn -= spawn_quantity
//Prices go up as material quantity becomes scarce
var/fraction = available_quantity
if(market_quantity != available_quantity) //to avoid division by zero error
fraction /= (market_quantity - available_quantity)
SSstock_market.materials_prices[material_type] += round(SSstock_market.materials_prices[material_type] * fraction)
//We decrease the quantity only after adjusting our prices for accurate values
SSstock_market.materials_quantity[material_type] -= available_quantity