From b39953ebce800008280f0379727a43441e0d83f5 Mon Sep 17 00:00:00 2001 From: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Date: Sun, 19 Nov 2023 03:49:35 +0530 Subject: [PATCH] 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 :cl: fix: selling large amount of mats in cargo should not give you infinite credits fix: runtime when adjusting material market after buying /:cl: --- code/modules/cargo/exports/materials.dm | 17 ++++++++++--- code/modules/cargo/packs/_packs.dm | 32 ++++++++++++++++++------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/code/modules/cargo/exports/materials.dm b/code/modules/cargo/exports/materials.dm index c9a88a6edfb..3a5c7f975ed 100644 --- a/code/modules/cargo/exports/materials.dm +++ b/code/modules/cargo/exports/materials.dm @@ -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. diff --git a/code/modules/cargo/packs/_packs.dm b/code/modules/cargo/packs/_packs.dm index 51ec71649dd..2adec36584a 100644 --- a/code/modules/cargo/packs/_packs.dm +++ b/code/modules/cargo/packs/_packs.dm @@ -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