Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit 8e37f03

Browse files
authored
Ports black market uplinks (#22986)
* Long-To-Short-Range-Bluespace-Transceiver? Never heard of it. * Turns out the LTSRBT exists * Lints really didn't like that * Yet again lints finds something wrong * Remove random icon included in the dmi * Uplink category fix
1 parent 4402405 commit 8e37f03

File tree

17 files changed

+922
-24
lines changed

17 files changed

+922
-24
lines changed

code/__DEFINES/blackmarket.dm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
// Shipping methods
3+
4+
// The BEST way of shipping items: accurate, "undetectable"
5+
#define SHIPPING_METHOD_LTSRBT "LTSRBT"
6+
// Picks a random area to teleport the item to and gives you a minute to get there before it is sent.
7+
#define SHIPPING_METHOD_TELEPORT "Teleport"
8+
// Throws the item from somewhere at the station.
9+
#define SHIPPING_METHOD_LAUNCH "Launch"

code/_globalvars/lists/maintenance_loot.dm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,8 @@ GLOBAL_LIST_INIT(maintenance_loot_makeshift,list(
620620
/obj/item/stack/spacecash/c200 = W_RARE,
621621
/obj/item/stack/spacecash/c50 = W_UNCOMMON,
622622
/obj/item/stack/spacecash/c500 = W_MYTHICAL,
623-
/obj/item/stock_parts/cell/potato = W_UNCOMMON
623+
/obj/item/stock_parts/cell/potato = W_UNCOMMON,
624+
/obj/item/blackmarket_uplink = W_UNCOMMON
624625
))
625626

626627
//Has minor mechanical usage; stuff you'd usually only find in a lathe, through crafting, or through a vendor.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
SUBSYSTEM_DEF(blackmarket)
2+
name = "Blackmarket"
3+
flags = SS_BACKGROUND
4+
init_order = INIT_ORDER_DEFAULT
5+
6+
/// Descriptions for each shipping methods.
7+
var/shipping_method_descriptions = list(
8+
SHIPPING_METHOD_LAUNCH="Launches the item at the station from space, cheap but you might not recieve your item at all.",
9+
SHIPPING_METHOD_LTSRBT="Long-To-Short-Range-Bluespace-Transceiver, a machine that recieves items outside the station and then teleports them to the location of the uplink.",
10+
SHIPPING_METHOD_TELEPORT="Teleports the item in a random area in the station, you get 60 seconds to get there first though."
11+
)
12+
13+
/// List of all existing markets.
14+
var/list/datum/blackmarket_market/markets = list()
15+
/// List of existing ltsrbts.
16+
var/list/obj/machinery/ltsrbt/telepads = list()
17+
/// Currently queued purchases.
18+
var/list/queued_purchases = list()
19+
20+
/datum/controller/subsystem/blackmarket/Initialize(timeofday)
21+
for(var/market in subtypesof(/datum/blackmarket_market))
22+
markets[market] += new market
23+
24+
for(var/item in subtypesof(/datum/blackmarket_item))
25+
var/datum/blackmarket_item/I = new item()
26+
if(!I.item)
27+
continue
28+
29+
for(var/M in I.markets)
30+
if(!markets[M])
31+
stack_trace("SSblackmarket: Item [I] available in market that does not exist.")
32+
continue
33+
markets[M].add_item(item)
34+
qdel(I)
35+
. = ..()
36+
return SS_INIT_SUCCESS
37+
38+
/datum/controller/subsystem/blackmarket/fire(resumed)
39+
while(length(queued_purchases))
40+
var/datum/blackmarket_purchase/purchase = queued_purchases[1]
41+
queued_purchases.Cut(1,2)
42+
43+
// Uh oh, uplink is gone. We will just keep the money and you will not get your order.
44+
if(!purchase.uplink || QDELETED(purchase.uplink))
45+
queued_purchases -= purchase
46+
qdel(purchase)
47+
continue
48+
49+
switch(purchase.method)
50+
// Find a ltsrbt pad and make it handle the shipping.
51+
if(SHIPPING_METHOD_LTSRBT)
52+
if(!telepads.len)
53+
continue
54+
// Prioritize pads that don't have a cooldown active.
55+
var/free_pad_found = FALSE
56+
for(var/obj/machinery/ltsrbt/pad in telepads)
57+
if(pad.recharge_cooldown)
58+
continue
59+
pad.add_to_queue(purchase)
60+
queued_purchases -= purchase
61+
free_pad_found = TRUE
62+
break
63+
64+
if(free_pad_found)
65+
continue
66+
67+
var/obj/machinery/ltsrbt/pad = pick(telepads)
68+
69+
to_chat(recursive_loc_check(purchase.uplink.loc, /mob), span_notice("[purchase.uplink] flashes a message noting that the order is being processed by [pad]."))
70+
71+
queued_purchases -= purchase
72+
pad.add_to_queue(purchase)
73+
// Get random area, throw it somewhere there.
74+
if(SHIPPING_METHOD_TELEPORT)
75+
var/turf/targetturf = get_safe_random_station_turf()
76+
// This shouldn't happen.
77+
if (!targetturf)
78+
continue
79+
80+
to_chat(recursive_loc_check(purchase.uplink.loc, /mob), span_notice("<span class='notice'>[purchase.uplink] flashes a message noting that the order is being teleported to [get_area(targetturf)] in 60 seconds."))
81+
82+
// do_teleport does not want to teleport items from nullspace, so it just forceMoves and does sparks.
83+
addtimer(CALLBACK(src, /datum/controller/subsystem/blackmarket/proc/fake_teleport, purchase.entry.spawn_item(), targetturf), 60 SECONDS)
84+
queued_purchases -= purchase
85+
qdel(purchase)
86+
// Get the current location of the uplink if it exists, then throws the item from space at the station from a random direction.
87+
if(SHIPPING_METHOD_LAUNCH)
88+
var/startSide = pick(GLOB.cardinals)
89+
var/turf/T = get_turf(purchase.uplink)
90+
var/pickedloc = spaceDebrisStartLoc(startSide, T.z)
91+
92+
var/atom/movable/item = purchase.entry.spawn_item(pickedloc)
93+
item.throw_at(purchase.uplink, 3, 3, spin = FALSE)
94+
95+
to_chat(recursive_loc_check(purchase.uplink.loc, /mob), span_notice("[purchase.uplink] flashes a message noting the order is being launched at the station from [dir2text(startSide)].</span>"))
96+
97+
queued_purchases -= purchase
98+
qdel(purchase)
99+
100+
if(MC_TICK_CHECK)
101+
break
102+
103+
/// Used to make a teleportation effect as do_teleport does not like moving items from nullspace.
104+
/datum/controller/subsystem/blackmarket/proc/fake_teleport(atom/movable/item, turf/target)
105+
item.forceMove(target)
106+
var/datum/effect_system/spark_spread/sparks = new
107+
sparks.set_up(5, 1, target)
108+
sparks.attach(item)
109+
sparks.start()
110+
111+
/// Used to add /datum/blackmarket_purchase to queued_purchases var. Returns TRUE when queued.
112+
/datum/controller/subsystem/blackmarket/proc/queue_item(datum/blackmarket_purchase/P)
113+
if(P.method == SHIPPING_METHOD_LTSRBT && !telepads.len)
114+
return FALSE
115+
queued_purchases += P
116+
return TRUE
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/datum/blackmarket_item
2+
/// Name for the item entry used in the uplink.
3+
var/name
4+
/// Description for the item entry used in the uplink.
5+
var/desc
6+
/// The category this item belongs to, should be already declared in the market that this item is accessible in.
7+
var/category
8+
/// "/datum/blackmarket_market"s that this item should be in, used by SSblackmarket on init.
9+
var/list/markets = list(/datum/blackmarket_market/blackmarket)
10+
11+
/// Price for the item, if not set creates a price according to the *_min and *_max vars.
12+
var/price
13+
/// How many of this type of item is available, if not set creates a price according to the *_min and *_max vars.
14+
var/stock
15+
16+
/// Path to or the item itself what this entry is for, this should be set even if you override spawn_item to spawn your item.
17+
var/item
18+
19+
/// Minimum price for the item if generated randomly.
20+
var/price_min = 0
21+
/// Maximum price for the item if generated randomly.
22+
var/price_max = 0
23+
/// Minimum amount that there should be of this item in the market if generated randomly. This defaults to 1 as most items will have it as 1.
24+
var/stock_min = 1
25+
/// Maximum amount that there should be of this item in the market if generated randomly.
26+
var/stock_max = 0
27+
/// Probability for this item to be available. Used by SSblackmarket on init.
28+
var/availability_prob = 0
29+
30+
/datum/blackmarket_item/New()
31+
if(isnull(price))
32+
price = rand(price_min, price_max)
33+
if(isnull(stock))
34+
stock = rand(stock_min, stock_max)
35+
36+
/// Used for spawning the wanted item, override if you need to do something special with the item.
37+
/datum/blackmarket_item/proc/spawn_item(loc)
38+
return new item(loc)
39+
40+
/// Buys the item and makes SSblackmarket handle it.
41+
/datum/blackmarket_item/proc/buy(obj/item/blackmarket_uplink/uplink, mob/buyer, shipping_method)
42+
// Sanity
43+
if(!istype(uplink) || !istype(buyer))
44+
return FALSE
45+
46+
// This shouldn't be able to happen unless there was some manipulation or admin fuckery.
47+
if(!item || stock <= 0)
48+
return FALSE
49+
50+
// Alright, the item has been purchased.
51+
var/datum/blackmarket_purchase/purchase = new(src, uplink, shipping_method)
52+
53+
// SSblackmarket takes care of the shipping.
54+
if(SSblackmarket.queue_item(purchase))
55+
stock--
56+
log_game("[ADMIN_LOOKUPFLW(buyer)] has successfully purchased [name] using [shipping_method] for shipping.")
57+
return TRUE
58+
return FALSE
59+
60+
// This exists because it is easier to keep track of all the vars this way.
61+
/datum/blackmarket_purchase
62+
/// The entry being purchased.
63+
var/datum/blackmarket_item/entry
64+
/// Instance of the item being sent.
65+
var/item
66+
/// The uplink where this purchase was done from.
67+
var/obj/item/blackmarket_uplink/uplink
68+
/// Shipping method used to buy this item.
69+
var/method
70+
71+
/datum/blackmarket_purchase/New(_entry, _uplink, _method)
72+
entry = _entry
73+
if(!ispath(entry.item))
74+
item = entry.item
75+
uplink = _uplink
76+
method = _method
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/datum/blackmarket_item/clothing
2+
category = "Clothing"
3+
4+
/datum/blackmarket_item/clothing/ninja_mask
5+
name = "Space Ninja Mask"
6+
desc = "Apart from being acid, lava, fireproof and being hard to take off someone it does nothing special on it's own."
7+
item = /obj/item/clothing/mask/gas/space_ninja
8+
9+
price_min = 200
10+
price_max = 500
11+
stock_max = 3
12+
availability_prob = 40
13+
14+
/datum/blackmarket_item/clothing/durathread_vest
15+
name = "Durathread Vest"
16+
desc = "Dont let them tell you this stuff is \"Like asbestos\" or \"Pulled from the market for safety concerns\". It could be the difference between a robusting and a retaliation."
17+
item = /obj/item/clothing/suit/armor/vest/durathread
18+
19+
price_min = 200
20+
price_max = 400
21+
stock_max = 4
22+
availability_prob = 50
23+
24+
/datum/blackmarket_item/clothing/durathread_helmet
25+
name = "Durathread Helmet"
26+
desc = "Customers ask why it's called a helmet when it's just made from armoured fabric and I always say the same thing: No refunds."
27+
item = /obj/item/clothing/head/helmet/durathread
28+
29+
price_min = 100
30+
price_max = 200
31+
stock_max = 4
32+
availability_prob = 50
33+
34+
/datum/blackmarket_item/clothing/full_spacesuit_set
35+
name = "Nanotrasen Branded Spacesuit Box"
36+
desc = "A few boxes of \"Old Style\" space suits fell off the back of a space truck."
37+
item = /obj/item/storage/box
38+
price_min = 1500
39+
price_max = 4000
40+
stock_max = 3
41+
availability_prob = 30
42+
43+
/datum/blackmarket_item/clothing/full_spacesuit_set/spawn_item(loc)
44+
var/obj/item/storage/box/B = ..()
45+
B.name = "Spacesuit Box"
46+
B.desc = "It has a NT logo on it."
47+
new /obj/item/clothing/suit/space(B)
48+
new /obj/item/clothing/head/helmet/space(B)
49+
return B
50+
51+
/datum/blackmarket_item/clothing/chameleon_hat
52+
name = "Chameleon Hat"
53+
desc = "Pick any hat you want with this Handy device. Not Quality Tested."
54+
item = /obj/item/clothing/head/chameleon/broken
55+
56+
price_min = 100
57+
price_max = 200
58+
stock_max = 2
59+
availability_prob = 70
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/datum/blackmarket_item/consumable
2+
category = "Consumables"
3+
4+
/datum/blackmarket_item/consumable/clown_tears
5+
name = "Bowl of Clown's Tears"
6+
desc = "Guaranteed fresh from Weepy Boggins Tragic Kitchen"
7+
item = /obj/item/reagent_containers/food/snacks/soup/clownstears
8+
stock = 1
9+
10+
price_min = 520
11+
price_max = 600
12+
availability_prob = 10
13+
14+
/datum/blackmarket_item/consumable/donk_pocket_box
15+
name = "Box of Donk Pockets"
16+
desc = "A well packaged box containing the favourite snack of every spacefarer."
17+
item = /obj/item/storage/box/donkpockets
18+
19+
stock_min = 2
20+
stock_max = 5
21+
price_min = 325
22+
price_max = 400
23+
availability_prob = 80
24+
25+
/datum/blackmarket_item/consumable/suspicious_pills
26+
name = "Bottle of Suspicious Pills"
27+
desc = "A random cocktail of luxury drugs that are sure to put a smile on your face!"
28+
item = /obj/item/storage/pill_bottle
29+
30+
stock_min = 2
31+
stock_max = 3
32+
price_min = 400
33+
price_max = 700
34+
availability_prob = 50
35+
36+
/datum/blackmarket_item/consumable/suspicious_pills/spawn_item(loc)
37+
var/pillbottle = pick(list(/obj/item/storage/pill_bottle/zoom,
38+
/obj/item/storage/pill_bottle/happy,
39+
/obj/item/storage/pill_bottle/lsd,
40+
/obj/item/storage/pill_bottle/aranesp,
41+
/obj/item/storage/pill_bottle/stimulant))
42+
return new pillbottle(loc)
43+
44+
/datum/blackmarket_item/consumable/floor_pill
45+
name = "Strange Pill"
46+
desc = "The Russian Roulette of the Maintenance Tunnels."
47+
item = /obj/item/reagent_containers/pill/floorpill
48+
49+
stock_min = 5
50+
stock_max = 35
51+
price_min = 10
52+
price_max = 60
53+
availability_prob = 50
54+
55+
/datum/blackmarket_item/consumable/pumpup
56+
name = "Maintenance Pump-Up"
57+
desc = "Resist any Baton stun with this handy device!"
58+
item = /obj/item/reagent_containers/autoinjector/medipen/pumpup
59+
stock_max = 3
60+
price_min = 50
61+
price_max = 150
62+
availability_prob = 90

0 commit comments

Comments
 (0)