Files
Alexis 21b4095dfd [MDB IGNORE] [IDB IGNORE] Upstream Sync - 04/17/2026 (#5453)
Upstream 04/17/2026

fixes https://github.com/Bubberstation/Bubberstation/issues/5549

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com>
Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Rhials <28870487+Rhials@users.noreply.github.com>
Co-authored-by: rageguy505 <54517726+rageguy505@users.noreply.github.com>
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
Co-authored-by: Aliceee2ch <160794176+Aliceee2ch@users.noreply.github.com>
Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com>
Co-authored-by: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com>
Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
Co-authored-by: Maxipat <108554989+Maxipat112@users.noreply.github.com>
Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: SimplyLogan <47579821+loganuk@users.noreply.github.com>
Co-authored-by: loganuk <fakeemail123@aol.com>
Co-authored-by: Leland Kemble <70413276+lelandkemble@users.noreply.github.com>
Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com>
Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com>
Co-authored-by: Lucy <lucy@absolucy.moe>
Co-authored-by: siliconOpossum <138069572+siliconOpossum@users.noreply.github.com>
Co-authored-by: Isratosh <Isratosh@hotmail.com>
Co-authored-by: TheRyeGuyWhoWillNowDie <70169560+TheRyeGuyWhoWillNowDie@users.noreply.github.com>
Co-authored-by: Neocloudy <88008002+Neocloudy@users.noreply.github.com>
Co-authored-by: Alexander V. <volas@ya.ru>
Co-authored-by: ElGitificador <168473461+ElGitificador@users.noreply.github.com>
Co-authored-by: Twaticus <46540570+Twaticus@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
Co-authored-by: Tim <timothymtorres@gmail.com>
Co-authored-by: Iamgoofball <iamgoofball@gmail.com>
Co-authored-by: Layzu666 <121319428+Layzu666@users.noreply.github.com>
Co-authored-by: Arturlang <24881678+Arturlang@users.noreply.github.com>
Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com>
Co-authored-by: mrmanlikesbt <99309552+mrmanlikesbt@users.noreply.github.com>
Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
Co-authored-by: John F. Kennedy <54908920+MacaroniCritter@users.noreply.github.com>
Co-authored-by: Cursor <102828457+theselfish@users.noreply.github.com>
Co-authored-by: Josh <josh.adam.powell@gmail.com>
Co-authored-by: Josh Powell <josh.powell@softwire.com>
Co-authored-by: Yobrocharlie <Charliemiller5617@gmail.com>
Co-authored-by: Hardly3D <66234359+Hardly3D@users.noreply.github.com>
Co-authored-by: shayoki <96078776+shayoki@users.noreply.github.com>
Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
2026-05-16 00:56:00 +02:00

198 lines
8.1 KiB
Plaintext

/datum/supply_pack
/// The name of the supply pack, as listed on th cargo purchasing UI.
var/name = "Crate"
/// The group that the supply pack is sorted into within the cargo purchasing UI.
var/group = ""
// BUBBER EDIT START
/// Whether this ORDER_GOODY pack can be purchased with non-private accounts.
var/allow_non_private_purchase = FALSE
// BUBBER EDIT END
// BUBBER EDIT START
/// Optional subcategory shown as a subsection header within a group in the cargo UI.
var/subcategory = ""
// BUBBER EDIT END
/// Cost of the crate. DO NOT GO ANY LOWER THAN X1.4 the "CARGO_CRATE_VALUE" value if using regular crates, or infinite profit will be possible!
var/cost = CARGO_CRATE_VALUE * 1.4
/// What access is required to open the crate when spawned?
var/access = FALSE
/// Who can view this supply_pack and with what access.
var/access_view = FALSE
/// If someone with any of the following accesses in a list can open this cargo pack crate.
var/access_any = FALSE
/// A list of items that are spawned in the crate of the supply pack.
var/list/contains = null
/// What is the name of the crate that is spawned with the crate's contents??
var/crate_name = "crate"
/// When spawning a gas canistor, what kind of gas type are we spawning?
var/id
/// The description shown on the cargo purchasing UI. No desc by default.
var/desc = ""
/// What typepath of crate do you spawn?
var/crate_type = /obj/structure/closet/crate
/// If we're not going to use a crate, then what would we like to use as a container for the order/manifest?
var/storage_override
/// If this pack comes shipped in a specific pod when launched from the express console
var/special_pod
/// Can coupons target this pack? If so, how rarely?
var/discountable = SUPPLY_PACK_NOT_DISCOUNTABLE
/// Is this supply pack considered unpredictable for the purposes of testing unit testing? Examples include the stock market, or miner supply crates. If true, exempts from unit testing
var/test_ignored = FALSE
/// Various properties for cargo order mostly used to determine which consoles can see it
var/order_flags = NONE
/datum/supply_pack/New()
id = type
/// Returns data used for cargo purchasing UI
/datum/supply_pack/proc/get_contents_ui_data()
var/list/data = list()
for(var/obj/item/item as anything in contains)
var/list/item_data = list(
"name" = item.name,
"icon" = item.greyscale_config ? null : item.icon,
"icon_state" = item.greyscale_config ? null : item.icon_state,
"amount" = contains[item]
)
UNTYPED_LIST_ADD(data, item_data)
return data
/**
* Proc that takes a given supply_pack, and attempts to create a crate containing the pack's contents as determined by fill()
*
* @ atom/A: The location or turf that the pack is being generated onto. Cargo shuttle provides an empty turf, other generate()s call this either null or otherwise.
* @ datum/bank_account/paying_account: The account to associate the supply pack with when going and generating the crate. Only the paying account can open said secure crate/case.
* @ crate_override: If defined, we will fill our supply pack with this object. This is used for when we need to spawn a random crate but the contents are goodies or we don't need a full crate.
*/
/datum/supply_pack/proc/generate(atom/A, datum/bank_account/paying_account, crate_override)
var/obj/structure/closet/crate/C
if(paying_account)
C = new /obj/structure/closet/crate/secure/owned(A, paying_account)
C.name = "[crate_name] - Purchased by [paying_account.account_holder]"
else if(!crate_type && !crate_override)
CRASH("tried to generate a supply pack without a valid crate type")
else if(crate_override)
var/obj/unique_container = new crate_override(A)
fill(unique_container)
return unique_container
else
C = new crate_type(A)
C.name = crate_name
if(access)
C.req_access = list(access)
if(access_any)
C.req_one_access = access_any
fill(C)
return C
/datum/supply_pack/proc/get_cost()
. = cost
. *= SSeconomy.pack_price_modifier
/**
* Takes a provided container, iterates, and spawns the full quantity of items within it, and applies and necessary status effects when the crate is populated.
* @ container: The container holding the contents of the supply pack. Most typically a obj/structure/closet/crate, but can technically be anything.
*/
/datum/supply_pack/proc/fill(obj/container)
for(var/item in contains)
if(!contains[item])
contains[item] = 1
for(var/iteration = 1 to contains[item])
var/atom/A = new item(container)
if(!(order_flags & ORDER_ADMIN_SPAWNED))
continue
A.flags_1 |= ADMIN_SPAWNED_1
/// For generating supply packs at runtime. Returns a list of supply packs to use instead of this one.
/datum/supply_pack/proc/generate_supply_packs()
return
///Easily send a supplypod to an area
/proc/send_supply_pod_to_area(contents, area_type, pod_type = /obj/structure/closet/supplypod)
var/list/areas = get_areas(area_type)
if(!LAZYLEN(areas))
return FALSE
var/list/open_turfs = list()
for(var/turf/open/floor/found_turf in get_area_turfs(pick(areas), subtypes = TRUE))
open_turfs += found_turf
if(!length(open_turfs))
return FALSE
new /obj/effect/pod_landingzone (pick(open_turfs), new pod_type (), contents)
return TRUE
/**
* Custom supply pack
* The contents are given on New rather than being static
* This is for adding custom orders to the Cargo console (like order consoles)
*/
/datum/supply_pack/custom
name = "mining order"
order_flags = ORDER_INVISIBLE
crate_name = "shaft mining delivery crate"
access = ACCESS_MINING
test_ignored = TRUE
/datum/supply_pack/custom/New(purchaser, cost, list/contains)
. = ..()
name = "[purchaser]'s Mining Order"
src.cost = cost
src.contains = contains
/datum/supply_pack/custom/minerals
name = "materials order"
crate_name = "galactic materials market delivery crate"
access = FALSE
crate_type = /obj/structure/closet/crate/cargo/mining
/datum/supply_pack/custom/minerals/New(purchaser, cost, list/contains)
. = ..()
name = "[purchaser]'s Materials Order"
src.cost = cost
src.contains = contains
///Alters material amrkey & adjust order quantities if they exceed whats on the market
/datum/supply_pack/custom/minerals/proc/adjust_market()
. = list()
for(var/obj/item/stack/sheet/possible_stack as anything in contains)
var/material_type = 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 = contains[possible_stack]
if(available_quantity > market_quantity)
var/message = "[possible_stack::singular_name]: requested=[available_quantity] sheets, available=[market_quantity] sheets, adjusted=[market_quantity - available_quantity] sheets."
available_quantity = market_quantity
if(!available_quantity)
. += "[possible_stack::singular_name]: order cancelled due to insufficient sheets in the market."
contains -= possible_stack
continue
. += message
//adjust the order based ont the available quantity
contains[possible_stack] = available_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.adjust_material_price(material_type, SSstock_market.materials_prices[material_type] * fraction)
//We decrease the quantity only after adjusting our prices for accurate values
SSstock_market.adjust_material_quantity(material_type, -available_quantity)
/datum/supply_pack/custom/minerals/fill(obj/container)
for(var/obj/item/stack/sheet/possible_stack as anything in contains)
//spawn the ordered stack inside the crate
var/sheets_to_spawn = contains[possible_stack]
while(sheets_to_spawn)
var/spawn_quantity = min(sheets_to_spawn, MAX_STACK_SIZE)
var/obj/item/stack/sheet/ordered_stack = new possible_stack(container, spawn_quantity)
if(order_flags & ORDER_ADMIN_SPAWNED)
ordered_stack.flags_1 |= ADMIN_SPAWNED_1
sheets_to_spawn -= spawn_quantity