diff --git a/code/__DEFINES/blackmarket.dm b/code/__DEFINES/blackmarket.dm
new file mode 100644
index 0000000000..3ec45a3a99
--- /dev/null
+++ b/code/__DEFINES/blackmarket.dm
@@ -0,0 +1,5 @@
+// Shipping methods
+
+#define SHIPPING_METHOD_LTSRBT "LTSRBT" // The BEST way of shipping items: accurate, "undetectable"
+#define SHIPPING_METHOD_TELEPORT "Teleport" // Picks a random area to teleport the item to and gives you a minute to get there before it is sent.
+#define SHIPPING_METHOD_LAUNCH "Launch" // Throws the item from somewhere at the station.
diff --git a/code/controllers/subsystem/blackmarket.dm b/code/controllers/subsystem/blackmarket.dm
new file mode 100644
index 0000000000..c26a030e0a
--- /dev/null
+++ b/code/controllers/subsystem/blackmarket.dm
@@ -0,0 +1,89 @@
+SUBSYSTEM_DEF(blackmarket)
+ name = "Blackmarket"
+ flags = SS_BACKGROUND
+ init_order = INIT_ORDER_DEFAULT
+
+ // Descriptions for each shipping method.
+ var/shipping_method_descriptions = list(
+ SHIPPING_METHOD_LAUNCH="Launches the item at the station from space, cheap but you might not recieve your item at all.",
+ 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.",
+ SHIPPING_METHOD_TELEPORT="Teleports the item in a random area in the station, you get 60 seconds to get there first though."
+ )
+
+ var/list/datum/blackmarket_market/markets = list() // List of all existing markets.
+ var/list/obj/machinery/ltsrbt/telepads = list() // List of existing ltsrbts.
+ var/list/queued_purchases = list() // Currently queued purchases.
+
+/datum/controller/subsystem/blackmarket/Initialize(timeofday)
+ for(var/market in subtypesof(/datum/blackmarket_market))
+ markets[market] += new market
+ for(var/item in subtypesof(/datum/blackmarket_item))
+ var/datum/blackmarket_item/I = new item()
+ if(!I.item)
+ continue
+ for(var/M in I.markets)
+ if(!markets[M])
+ stack_trace("SSblackmarket: Item [I] available in market that does not exist.")
+ continue
+ markets[M].add_item(item)
+ qdel(I)
+ . = ..()
+
+/datum/controller/subsystem/blackmarket/fire(resumed)
+ while(length(queued_purchases))
+ var/datum/blackmarket_purchase/purchase = queued_purchases[1]
+ queued_purchases.Cut(1,2)
+ if(!purchase.uplink || QDELETED(purchase.uplink)) // Uh oh, uplink is gone. We will just keep the money and you will not get your order.
+ queued_purchases -= purchase
+ qdel(purchase)
+ continue
+ switch(purchase.method)
+ if(SHIPPING_METHOD_LTSRBT) // Find a ltsrbt pad and make it handle the shipping.
+ if(!telepads.len)
+ continue
+ var/free_pad_found = FALSE // Prioritize pads that don't have a cooldown active.
+ for(var/obj/machinery/ltsrbt/pad in telepads)
+ if(pad.recharge_cooldown)
+ continue
+ pad.add_to_queue(purchase)
+ queued_purchases -= purchase
+ free_pad_found = TRUE
+ break
+ if(free_pad_found)
+ continue
+ var/obj/machinery/ltsrbt/pad = pick(telepads)
+ to_chat(recursive_loc_check(purchase.uplink.loc, /mob), "[purchase.uplink] flashes a message noting that the order is being processed by [pad].")
+ queued_purchases -= purchase
+ pad.add_to_queue(purchase)
+ if(SHIPPING_METHOD_TELEPORT) // Get random area, throw it somewhere there.
+ var/turf/targetturf = get_safe_random_station_turf()
+ if (!targetturf) // This shouldn't happen.
+ continue
+ to_chat(recursive_loc_check(purchase.uplink.loc, /mob), "[purchase.uplink] flashes a message noting that the order is being teleported to [get_area(targetturf)] in 60 seconds.")
+ addtimer(CALLBACK(src, /datum/controller/subsystem/blackmarket/proc/fake_teleport, purchase.entry.spawn_item(), targetturf), 60 SECONDS) // do_teleport does not want to teleport items from nullspace, so it just forceMoves and does sparks.
+ queued_purchases -= purchase
+ qdel(purchase)
+ if(SHIPPING_METHOD_LAUNCH) // Get the current location of the uplink if it exists, then throws the item from space at the station from a random direction.
+ var/startSide = pick(GLOB.cardinals)
+ var/turf/T = get_turf(purchase.uplink)
+ var/pickedloc = spaceDebrisStartLoc(startSide, T.z)
+ var/atom/movable/item = purchase.entry.spawn_item(pickedloc)
+ item.throw_at(purchase.uplink, 3, 3, spin = FALSE)
+ to_chat(recursive_loc_check(purchase.uplink.loc, /mob), "[purchase.uplink] flashes a message noting the order is being launched at the station from [dir2text(startSide)].")
+ queued_purchases -= purchase
+ qdel(purchase)
+ if(MC_TICK_CHECK)
+ break
+
+/datum/controller/subsystem/blackmarket/proc/fake_teleport(atom/movable/item, turf/target) // Used to make a teleportation effect as do_teleport does not like moving items from nullspace.
+ item.forceMove(target)
+ var/datum/effect_system/spark_spread/sparks = new
+ sparks.set_up(5, 1, target)
+ sparks.attach(item)
+ sparks.start()
+
+/datum/controller/subsystem/blackmarket/proc/queue_item(datum/blackmarket_purchase/P) // Used to add /datum/blackmarket_purchase to queued_purchases var. Returns TRUE when queued.
+ if(P.method == SHIPPING_METHOD_LTSRBT && !telepads.len)
+ return FALSE
+ queued_purchases += P
+ return TRUE
diff --git a/code/modules/cargo/blackmarket/blackmarket_item.dm b/code/modules/cargo/blackmarket/blackmarket_item.dm
new file mode 100644
index 0000000000..53c0004a7f
--- /dev/null
+++ b/code/modules/cargo/blackmarket/blackmarket_item.dm
@@ -0,0 +1,51 @@
+/datum/blackmarket_item
+ var/name // Name for the item entry used in the uplink.
+ var/desc // Description for the item entry used in the uplink.
+ var/category // The category this item belongs to, should be already declared in the market that this item is accessible in.
+ var/list/markets = list(/datum/blackmarket_market/blackmarket) // "/datum/blackmarket_market"s that this item should be in, used by SSblackmarket on init.
+
+ var/price // Price for the item, if not set creates a price according to the *_min and *_max vars.
+ var/stock // How many of this type of item is available, if not set creates a price according to the *_min and *_max vars.
+
+ var/item // 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.
+
+ var/price_min = 0 // Minimum price for the item if generated randomly.
+ var/price_max = 0 // Maximum price for the item if generated randomly.
+ var/stock_min = 1 // 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.
+ var/stock_max = 0 // Maximum amount that there should be of this item in the market if generated randomly.
+ var/availability_prob = 0 // Probability for this item to be available. Used by SSblackmarket on init.
+
+/datum/blackmarket_item/New()
+ if(isnull(price))
+ price = rand(price_min, price_max)
+ if(isnull(stock))
+ stock = rand(stock_min, stock_max)
+
+/datum/blackmarket_item/proc/spawn_item(loc) // Used for spawning the wanted item, override if you need to do something special with the item.
+ return new item(loc)
+
+/datum/blackmarket_item/proc/buy(obj/item/blackmarket_uplink/uplink, mob/buyer, shipping_method) // Buys the item and makes SSblackmarket handle it.
+ // Sanity
+ if(!istype(uplink) || !istype(buyer))
+ return FALSE
+ if(!item || stock <= 0) // This shouldn't be able to happen unless there was some manipulation or admin fuckery.
+ return FALSE
+ var/datum/blackmarket_purchase/purchase = new(src, uplink, shipping_method) // Alright, the item has been purchased.
+ if(SSblackmarket.queue_item(purchase)) // SSblackmarket takes care of the shipping.
+ stock--
+ log_game("[key_name(buyer)] has succesfully purchased [name] using [shipping_method] for shipping.")
+ return TRUE
+ return FALSE
+
+/datum/blackmarket_purchase // This exists because it is easier to keep track of all the vars this way.
+ var/datum/blackmarket_item/entry // The entry being purchased.
+ var/item // Instance of the item being sent.
+ var/obj/item/blackmarket_uplink/uplink // The uplink where this purchase was done from.
+ var/method // Shipping method used to buy this item.
+
+/datum/blackmarket_purchase/New(_entry, _uplink, _method)
+ entry = _entry
+ if(!ispath(entry.item))
+ item = entry.item
+ uplink = _uplink
+ method = _method
diff --git a/code/modules/cargo/blackmarket/blackmarket_items/clothing.dm b/code/modules/cargo/blackmarket/blackmarket_items/clothing.dm
new file mode 100644
index 0000000000..a6ee19e38d
--- /dev/null
+++ b/code/modules/cargo/blackmarket/blackmarket_items/clothing.dm
@@ -0,0 +1,55 @@
+/datum/blackmarket_item/clothing
+ category = "Clothing"
+
+/datum/blackmarket_item/clothing/ninja_mask
+ name = "Space Ninja Mask"
+ desc = "Apart from being acid, lava, fireproof and being hard to take off someone it does nothing special on it's own."
+ item = /obj/item/clothing/mask/gas/space_ninja
+ price_min = 200
+ price_max = 500
+ stock_max = 3
+ availability_prob = 40
+
+/datum/blackmarket_item/clothing/durathread_vest
+ name = "Durathread Vest"
+ 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."
+ item = /obj/item/clothing/suit/armor/vest/durathread
+ price_min = 200
+ price_max = 400
+ stock_max = 4
+ availability_prob = 50
+
+/datum/blackmarket_item/clothing/durathread_helmet
+ name = "Durathread Helmet"
+ 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."
+ item = /obj/item/clothing/head/helmet/durathread
+ price_min = 100
+ price_max = 200
+ stock_max = 4
+ availability_prob = 50
+
+/datum/blackmarket_item/clothing/full_spacesuit_set
+ name = "Nanotrasen Branded Spacesuit Box"
+ desc = "A few boxes of \"Old Style\" space suits fell off the back of a space truck."
+ item = /obj/item/storage/box
+ price_min = 1500
+ price_max = 4000
+ stock_max = 3
+ availability_prob = 30
+
+/datum/blackmarket_item/clothing/full_spacesuit_set/spawn_item(loc)
+ var/obj/item/storage/box/B = ..()
+ B.name = "Spacesuit Box"
+ B.desc = "It has a NT logo on it."
+ new /obj/item/clothing/suit/space(B)
+ new /obj/item/clothing/head/helmet/space(B)
+ return B
+
+/datum/blackmarket_item/clothing/chameleon_hat
+ name = "Chameleon Hat"
+ desc = "Pick any hat you want with this Handy device. Not Quality Tested."
+ item = /obj/item/clothing/head/chameleon/broken
+ price_min = 100
+ price_max = 200
+ stock_max = 2
+ availability_prob = 70
diff --git a/code/modules/cargo/blackmarket/blackmarket_items/consumables.dm b/code/modules/cargo/blackmarket/blackmarket_items/consumables.dm
new file mode 100644
index 0000000000..fd836e760d
--- /dev/null
+++ b/code/modules/cargo/blackmarket/blackmarket_items/consumables.dm
@@ -0,0 +1,58 @@
+/datum/blackmarket_item/consumable
+ category = "Consumables"
+
+/datum/blackmarket_item/consumable/clown_tears
+ name = "Bowl of Clown's Tears"
+ desc = "Guaranteed fresh from Weepy Boggins Tragic Kitchen"
+ item = /obj/item/reagent_containers/food/snacks/soup/clownstears
+ stock = 1
+ price_min = 520
+ price_max = 600
+ availability_prob = 10
+
+/datum/blackmarket_item/consumable/donk_pocket_box
+ name = "Box of Donk Pockets"
+ desc = "A well packaged box containing the favourite snack of every spacefarer."
+ item = /obj/item/storage/box/donkpockets
+ stock_min = 2
+ stock_max = 5
+ price_min = 325
+ price_max = 400
+ availability_prob = 80
+
+/datum/blackmarket_item/consumable/suspicious_pills
+ name = "Bottle of Suspicious Pills"
+ desc = "A random cocktail of luxury drugs that are sure to put a smile on your face!"
+ item = /obj/item/storage/pill_bottle
+ stock_min = 2
+ stock_max = 3
+ price_min = 400
+ price_max = 700
+ availability_prob = 50
+
+/datum/blackmarket_item/consumable/suspicious_pills/spawn_item(loc)
+ var/pillbottle = pick(list(/obj/item/storage/pill_bottle/zoom,
+ /obj/item/storage/pill_bottle/happy,
+ /obj/item/storage/pill_bottle/lsd,
+ /obj/item/storage/pill_bottle/aranesp,
+ /obj/item/storage/pill_bottle/stimulant))
+ return new pillbottle(loc)
+
+/datum/blackmarket_item/consumable/floor_pill
+ name = "Strange Pill"
+ desc = "The Russian Roulette of the Maintenance Tunnels."
+ item = /obj/item/reagent_containers/pill/floorpill
+ stock_min = 5
+ stock_max = 35
+ price_min = 10
+ price_max = 60
+ availability_prob = 50
+
+/datum/blackmarket_item/consumable/pumpup
+ name = "Shoddy Stimulants"
+ desc = "Feel the energy inside each needle!"
+ /obj/item/reagent_containers/hypospray/medipen/stimpack
+ stock_max = 5
+ price_min = 50
+ price_max = 150
+ availability_prob = 90
diff --git a/code/modules/cargo/blackmarket/blackmarket_items/misc.dm b/code/modules/cargo/blackmarket/blackmarket_items/misc.dm
new file mode 100644
index 0000000000..474be8d29c
--- /dev/null
+++ b/code/modules/cargo/blackmarket/blackmarket_items/misc.dm
@@ -0,0 +1,53 @@
+/datum/blackmarket_item/misc
+ category = "Miscellaneous"
+
+/datum/blackmarket_item/misc/cap_gun
+ name = "Cap Gun"
+ desc = "Prank your friends with this harmless gun! Harmlessness guranteed."
+ item = /obj/item/toy/gun
+ price_min = 50
+ price_max = 200
+ stock_max = 6
+ availability_prob = 80
+
+/datum/blackmarket_item/misc/shoulder_holster
+ name = "Shoulder holster"
+ desc = "Yeehaw, hardboiled friends! This holster is the first step in your dream of becoming a detective and being allowed to shoot real guns!"
+ item = /obj/item/storage/belt/holster
+ price_min = 400
+ price_max = 800
+ stock_max = 8
+ availability_prob = 60
+
+/datum/blackmarket_item/misc/holywater
+ name = "Flask of holy water"
+ desc = "Father Lootius' own brand of ready-made holy water."
+ item = /obj/item/reagent_containers/food/drinks/bottle/holywater
+ price_min = 400
+ price_max = 600
+ stock_max = 3
+ availability_prob = 40
+
+/datum/blackmarket_item/misc/holywater/spawn_item(loc)
+ if (prob(6.66))
+ return new /obj/item/reagent_containers/glass/beaker/unholywater(loc)
+ return ..()
+
+/datum/blackmarket_item/misc/strange_seed
+ name = "Strange Seeds"
+ desc = "An Exotic Variety of seed that can contain anything from glow to acid."
+ item = /obj/item/seeds/random
+ price_min = 320
+ price_max = 360
+ stock_min = 2
+ stock_max = 5
+ availability_prob = 50
+
+/datum/blackmarket_item/misc/smugglers_satchel
+ name = "Smuggler's Satchel"
+ desc = "This easily hidden satchel can become a versatile tool to anybody with the desire to keep certain items out of sight and out of mind."
+ item = /obj/item/storage/backpack/satchel/flat
+ price_min = 750
+ price_max = 1000
+ stock_max = 2
+ availability_prob = 30
diff --git a/code/modules/cargo/blackmarket/blackmarket_items/tools.dm b/code/modules/cargo/blackmarket/blackmarket_items/tools.dm
new file mode 100644
index 0000000000..3da10b16fd
--- /dev/null
+++ b/code/modules/cargo/blackmarket/blackmarket_items/tools.dm
@@ -0,0 +1,74 @@
+/datum/blackmarket_item/tool
+ category = "Tools"
+
+/datum/blackmarket_item/tool/caravan_wrench
+ name = "Experimental Wrench"
+ desc = "The extra fast and handy wrench you always wanted!"
+ item = /obj/item/wrench/caravan
+ stock = 1
+ price_min = 400
+ price_max = 800
+ availability_prob = 20
+
+/datum/blackmarket_item/tool/caravan_wirecutters
+ name = "Experimental Wirecutters"
+ desc = "The extra fast and handy wirecutters you always wanted!"
+ item = /obj/item/wirecutters/caravan
+ stock = 1
+ price_min = 400
+ price_max = 800
+ availability_prob = 20
+
+/datum/blackmarket_item/tool/caravan_screwdriver
+ name = "Experimental Screwdriver"
+ desc = "The extra fast and handy screwdriver you always wanted!"
+ item = /obj/item/screwdriver/caravan
+ stock = 1
+ price_min = 400
+ price_max = 800
+ availability_prob = 20
+
+/datum/blackmarket_item/tool/caravan_crowbar
+ name = "Experimental Crowbar"
+ desc = "The extra fast and handy crowbar you always wanted!"
+ item = /obj/item/crowbar/red/caravan
+ stock = 1
+ price_min = 400
+ price_max = 800
+ availability_prob = 20
+
+/datum/blackmarket_item/tool/binoculars
+ name = "Binoculars"
+ desc = "Increase your sight by 150% with this handy tool!"
+ item = /obj/item/binoculars
+ stock = 1
+ price_min = 400
+ price_max = 960
+ availability_prob = 30
+
+/datum/blackmarket_item/tool/riot_shield
+ name = "Riot Shield"
+ desc = "Protect yourself from an unexpected riot at your local police department!"
+ item = /obj/item/shield/riot
+ price_min = 450
+ price_max = 650
+ stock_max = 2
+ availability_prob = 50
+
+/datum/blackmarket_item/tool/thermite_bottle
+ name = "Thermite Bottle"
+ desc = "30 units of Thermite to assist in creating a quick access point or get away!"
+ item = /obj/item/reagent_containers/glass/bottle/thermite
+ price_min = 500
+ price_max = 1500
+ stock_max = 3
+ availability_prob = 30
+
+/datum/blackmarket_item/tool/science_goggles
+ name = "Science Goggles"
+ desc = "These glasses scan the contents of containers and projects their contents to the user in an easy-to-read format."
+ item = /obj/item/clothing/glasses/science
+ price_min = 150
+ price_max = 200
+ stock_max = 3
+ availability_prob = 50
diff --git a/code/modules/cargo/blackmarket/blackmarket_items/weapons.dm b/code/modules/cargo/blackmarket/blackmarket_items/weapons.dm
new file mode 100644
index 0000000000..4978d688ae
--- /dev/null
+++ b/code/modules/cargo/blackmarket/blackmarket_items/weapons.dm
@@ -0,0 +1,41 @@
+/datum/blackmarket_item/weapon
+ category = "Weapons"
+
+/datum/blackmarket_item/weapon/bear_trap
+ name = "Bear Trap"
+ desc = "Get the janitor back at his own game with this affordable prank kit."
+ item = /obj/item/restraints/legcuffs/beartrap
+ price_min = 300
+ price_max = 550
+ stock_max = 3
+ availability_prob = 40
+
+/datum/blackmarket_item/weapon/shotgun_dart
+ name = "Shotgun Dart"
+ desc = "These handy darts can be filled up with any chemical and be shot with a shotgun! \
+ Prank your friends by shooting them with laughter! \
+ Not recommended for commercial use."
+ item = /obj/item/ammo_casing/shotgun/dart
+ price_min = 10
+ price_max = 50
+ stock_min = 5
+ stock_max = 30
+ availability_prob = 40
+
+/datum/blackmarket_item/weapon/bone_spear
+ name = "Bone Spear"
+ desc = "Authentic tribal spear, made from real bones! A steal at any price, especially if you're a caveman."
+ item = /obj/item/spear/bonespear
+ price_min = 200
+ price_max = 300
+ stock_max = 3
+ availability_prob = 60
+
+/datum/blackmarket_item/weapon/emp_grenade
+ name = "EMP Grenade"
+ desc = "Use this grenade for SHOCKING results!"
+ item = /obj/item/grenade/empgrenade
+ price_min = 100
+ price_max = 400
+ stock_max = 2
+ availability_prob = 50
diff --git a/code/modules/cargo/blackmarket/blackmarket_market.dm b/code/modules/cargo/blackmarket/blackmarket_market.dm
new file mode 100644
index 0000000000..ee95c82d77
--- /dev/null
+++ b/code/modules/cargo/blackmarket/blackmarket_market.dm
@@ -0,0 +1,40 @@
+/datum/blackmarket_market
+ var/name = "huh?" // Name for the market.
+
+ var/list/shipping // Available shipping methods and prices, just leave the shipping method out that you don't want to have.
+
+ // Automatic vars, do not touch these.
+ var/list/available_items = list() // Items available from this market, populated by SSblackmarket on initialization.
+ var/list/categories = list() // Item categories available from this market, only items which are in these categories can be gotten from this market.
+
+/datum/blackmarket_market/proc/add_item(datum/blackmarket_item/item) // Adds item to the available items and add it's category if it is not in categories yet.
+ if(!prob(initial(item.availability_prob)))
+ return FALSE
+ if(ispath(item))
+ item = new item()
+ if(!(item.category in categories))
+ categories += item.category
+ available_items[item.category] = list()
+ available_items[item.category] += item
+ return TRUE
+
+/datum/blackmarket_market/proc/purchase(item, category, method, obj/item/blackmarket_uplink/uplink, user) // Handles buying the item, this is mainly for future use and moving the code away from the uplink.
+ if(!istype(uplink) || !(method in shipping))
+ return FALSE
+ for(var/datum/blackmarket_item/I in available_items[category])
+ if(I.type != item)
+ continue
+ var/price = I.price + shipping[method]
+ if(uplink.money < price) // I can't get the price of the item and shipping in a clean way to the UI, so I have to do this.
+ to_chat("You don't have enough credits in [uplink] for [I] with [method] shipping.")
+ return FALSE
+ if(I.buy(uplink, user, method))
+ uplink.money -= price
+ return TRUE
+ return FALSE
+
+/datum/blackmarket_market/blackmarket
+ name = "Black Market"
+ shipping = list(SHIPPING_METHOD_LTSRBT =50,
+ SHIPPING_METHOD_LAUNCH =10,
+ SHIPPING_METHOD_TELEPORT=75)
diff --git a/code/modules/cargo/blackmarket/blackmarket_telepad.dm b/code/modules/cargo/blackmarket/blackmarket_telepad.dm
new file mode 100644
index 0000000000..546a20addb
--- /dev/null
+++ b/code/modules/cargo/blackmarket/blackmarket_telepad.dm
@@ -0,0 +1,92 @@
+/obj/item/circuitboard/machine/ltsrbt
+ name = "LTSRBT (Machine Board)"
+ icon_state = "bluespacearray"
+ build_path = /obj/machinery/ltsrbt
+ req_components = list(
+ /obj/item/stack/ore/bluespace_crystal = 2,
+ /obj/item/stock_parts/subspace/ansible = 1,
+ /obj/item/stock_parts/micro_laser = 1,
+ /obj/item/stock_parts/scanning_module = 2)
+ def_components = list(/obj/item/stack/ore/bluespace_crystal = /obj/item/stack/ore/bluespace_crystal/artificial)
+
+/obj/machinery/ltsrbt
+ name = "Long-To-Short-Range-Bluespace-Transciever"
+ desc = "The LTSRBT is a compact teleportation machine for recieving and sending items outside the station and inside the station.\nUsing teleportation frequencies stolen from NT it is near undetectable.\nEssential for any illegal market operations on NT stations.\n"
+ icon_state = "exonet_node"
+ circuit = /obj/item/circuitboard/machine/ltsrbt
+ density = TRUE
+ idle_power_usage = 200
+ var/power_efficiency = 1 // Divider for power_usage_per_teleport.
+ var/power_usage_per_teleport = 10000 // Power used per teleported which gets divided by power_efficiency.
+ var/recharge_time = 0 // The time it takes for the machine to recharge before being able to send or recieve items.
+ var/recharge_cooldown = 0 // Current recharge progress.
+ var/base_recharge_time = 100 // Base recharge time which is used to get recharge_time.
+ var/recieving // Current /datum/blackmarket_purchase being recieved.
+ var/transmitting // Current /datum/blackmarket_purchase being sent to the target uplink.
+ var/list/datum/blackmarket_purchase/queue = list() // Queue for purchases that the machine should recieve and send.
+
+/obj/machinery/ltsrbt/Initialize()
+ . = ..()
+ SSblackmarket.telepads += src
+
+/obj/machinery/ltsrbt/Destroy()
+ SSblackmarket.telepads -= src
+ if(SSblackmarket.telepads.len) // Bye bye orders.
+ for(var/datum/blackmarket_purchase/P in queue)
+ SSblackmarket.queue_item(P)
+ . = ..()
+
+/obj/machinery/ltsrbt/RefreshParts()
+ recharge_time = base_recharge_time
+ for(var/obj/item/stock_parts/scanning_module/scan in component_parts) // On tier 4 recharge_time should be 20 and by default it is 80 as scanning modules should be tier 1.
+ recharge_time -= scan.rating * 10
+ recharge_cooldown = recharge_time
+ power_efficiency = 0
+ for(var/obj/item/stock_parts/micro_laser/laser in component_parts)
+ power_efficiency += laser.rating
+ if(!power_efficiency) // Shouldn't happen but you never know.
+ power_efficiency = 1
+
+/obj/machinery/ltsrbt/proc/add_to_queue(datum/blackmarket_purchase/purchase) // Adds /datum/blackmarket_purchase to queue unless the machine is free, then it sets the purchase to be instantly recieved
+ if(!recharge_cooldown && !recieving && !transmitting)
+ recieving = purchase
+ return
+ queue += purchase
+
+/obj/machinery/ltsrbt/process()
+ if(stat & NOPOWER)
+ return
+ if(recharge_cooldown)
+ recharge_cooldown--
+ return
+ var/turf/T = get_turf(src)
+ if(recieving)
+ var/datum/blackmarket_purchase/P = recieving
+ if(!P.item || ispath(P.item))
+ P.item = P.entry.spawn_item(T)
+ else
+ var/atom/movable/M = P.item
+ M.forceMove(T)
+ use_power(power_usage_per_teleport / power_efficiency)
+ var/datum/effect_system/spark_spread/sparks = new
+ sparks.set_up(5, 1, get_turf(src))
+ sparks.attach(P.item)
+ sparks.start()
+ recieving = null
+ transmitting = P
+ recharge_cooldown = recharge_time
+ return
+ else if(transmitting)
+ var/datum/blackmarket_purchase/P = transmitting
+ if(!P.item)
+ QDEL_NULL(transmitting)
+ if(!P.item in T.contents)
+ QDEL_NULL(transmitting)
+ return
+ do_teleport(P.item, get_turf(P.uplink))
+ use_power(power_usage_per_teleport / power_efficiency)
+ QDEL_NULL(transmitting)
+ recharge_cooldown = recharge_time
+ return
+ if(queue.len)
+ recieving = pick_n_take(queue)
diff --git a/code/modules/cargo/blackmarket/blackmarket_uplink.dm b/code/modules/cargo/blackmarket/blackmarket_uplink.dm
new file mode 100644
index 0000000000..a1f94629f1
--- /dev/null
+++ b/code/modules/cargo/blackmarket/blackmarket_uplink.dm
@@ -0,0 +1,152 @@
+/obj/item/blackmarket_uplink
+ name = "Black Market Uplink"
+ icon = 'icons/obj/blackmarket.dmi'
+ icon_state = "uplink"
+ // UI variables.
+ var/ui_x = 720
+ var/ui_y = 480
+ var/viewing_category
+ var/viewing_market
+ var/selected_item
+ var/buying
+ var/money = 0 // How much money is inserted into the uplink.
+ var/list/accessible_markets = list(/datum/blackmarket_market/blackmarket) // List of typepaths for "/datum/blackmarket_market"s that this uplink can access.
+
+/obj/item/blackmarket_uplink/Initialize()
+ . = ..()
+ if(accessible_markets.len)
+ viewing_market = accessible_markets[1]
+ var/list/categories = SSblackmarket.markets[viewing_market].categories
+ if(categories && categories.len)
+ viewing_category = categories[1]
+
+/obj/item/blackmarket_uplink/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/holochip) || istype(I, /obj/item/stack/spacecash) || istype(I, /obj/item/coin))
+ var/worth = I.get_item_credit_value()
+ if(!worth)
+ to_chat(user, "[I] doesn't seem to be worth anything!")
+ money += worth
+ to_chat(user, "You slot [I] into [src] and it reports a total of [money] credits inserted.")
+ qdel(I)
+ return
+ . = ..()
+
+/obj/item/blackmarket_uplink/AltClick(mob/user)
+ if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
+ return
+ var/amount_to_remove = FLOOR(input(user, "How much do you want to withdraw? Current Amount: [money]", "Withdraw Funds", 5) as num|null, 1)
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
+ return
+ if(!amount_to_remove || amount_to_remove < 0)
+ return
+ if(amount_to_remove > money)
+ to_chat(user, "There is only [money] credits in [src]")
+ return
+ var/obj/item/holochip/holochip = new (user.drop_location(), amount_to_remove)
+ money -= amount_to_remove
+ holochip.name = "washed " + holochip.name
+ user.put_in_hands(holochip)
+ to_chat(user, "You withdraw [amount_to_remove] credits into a holochip.")
+
+/obj/item/blackmarket_uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
+ ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "blackmarket_uplink", name, ui_x, ui_y, master_ui, state)
+ ui.open()
+
+/obj/item/blackmarket_uplink/ui_data(mob/user)
+ var/list/data = list()
+ var/datum/blackmarket_market/market = viewing_market ? SSblackmarket.markets[viewing_market] : null
+ data["categories"] = market ? market.categories : null
+ data["delivery_methods"] = list()
+ if(market)
+ for(var/delivery in market.shipping)
+ data["delivery_methods"] += list(list("name" = delivery, "price" = market.shipping[delivery]))
+ data["money"] = money
+ data["buying"] = buying
+ data["items"] = list()
+ data["viewing_category"] = viewing_category
+ data["viewing_market"] = viewing_market
+ if(viewing_category && market)
+ if(market.available_items[viewing_category])
+ for(var/datum/blackmarket_item/I in market.available_items[viewing_category])
+ data["items"] += list(list(
+ "id" = I.type,
+ "name" = I.name,
+ "cost" = I.price,
+ "amount" = I.stock,
+ "desc" = I.desc || I.name
+ ))
+ return data
+
+/obj/item/blackmarket_uplink/ui_static_data(mob/user)
+ var/list/data = list()
+ data["delivery_method_description"] = SSblackmarket.shipping_method_descriptions
+ data["ltsrbt_built"] = SSblackmarket.telepads.len
+ data["markets"] = list()
+ for(var/M in accessible_markets)
+ var/datum/blackmarket_market/BM = SSblackmarket.markets[M]
+ data["markets"] += list(list(
+ "id" = M,
+ "name" = BM.name
+ ))
+ return data
+
+/obj/item/blackmarket_uplink/ui_act(action, params)
+ if(..())
+ return
+ switch(action)
+ if("set_category")
+ if(isnull(params["category"]))
+ return
+ if(isnull(viewing_market))
+ return
+ if(!(params["category"] in SSblackmarket.markets[viewing_market].categories))
+ return
+ viewing_category = params["category"]
+ . = TRUE
+ if("set_market")
+ if(isnull(params["market"]))
+ return
+ var/market = text2path(params["market"])
+ if(!(market in accessible_markets))
+ return
+ viewing_market = market
+ var/list/categories = SSblackmarket.markets[viewing_market].categories
+ if(categories && categories.len)
+ viewing_category = categories[1]
+ else
+ viewing_category = null
+ . = TRUE
+ if("select")
+ if(isnull(params["item"]))
+ return
+ var/item = text2path(params["item"])
+ selected_item = item
+ buying = TRUE
+ . = TRUE
+ if("cancel")
+ selected_item = null
+ buying = FALSE
+ . = TRUE
+ if("buy")
+ if(isnull(params["method"]))
+ return
+ if(isnull(selected_item))
+ buying = FALSE
+ return
+ var/datum/blackmarket_market/market = SSblackmarket.markets[viewing_market]
+ market.purchase(selected_item, viewing_category, params["method"], src, usr)
+ buying = FALSE
+ selected_item = null
+
+/datum/crafting_recipe/blackmarket_uplink
+ name = "Black Market Uplink"
+ result = /obj/item/blackmarket_uplink
+ time = 30
+ tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER, TOOL_MULTITOOL)
+ reqs = list(/obj/item/stock_parts/subspace/amplifier = 1,
+ /obj/item/stack/cable_coil = 15,
+ /obj/item/radio = 1,
+ /obj/item/analyzer = 1)
+ category = CAT_MISC
diff --git a/code/modules/cargo/packs/misc.dm b/code/modules/cargo/packs/misc.dm
index a158f0f1c1..985c827e65 100644
--- a/code/modules/cargo/packs/misc.dm
+++ b/code/modules/cargo/packs/misc.dm
@@ -434,6 +434,17 @@
/obj/item/stack/tile/noslip/thirty)
crate_name = "high-traction floor tiles crate"
+/datum/supply_pack/misc/blackmarket_telepad
+ name = "Black Market LTSRBT"
+ desc = "Need a faster and better way of transporting your illegal goods from and to the station? Fear not, the Long-To-Short-Range-Bluespace-Transceiver (LTSRBT for short) is here to help. Contains a LTSRBT circuit, two bluespace crystals, and one ansible."
+ cost = 8000
+ contraband = TRUE
+ contains = list(/obj/item/circuitboard/machine/ltsrbt,
+ /obj/item/stack/ore/bluespace_crystal/artificial,
+ /obj/item/stack/ore/bluespace_crystal/artificial,
+ /obj/item/stock_parts/subspace/ansible)
+ crate_name = "crate"
+
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////// Lewd Supplies ///////////////////////////////
//////////////////////////////////////////////////////////////////////////////
diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm
index 76b08c7cdf..5d68d00200 100644
--- a/code/modules/reagents/reagent_containers/bottle.dm
+++ b/code/modules/reagents/reagent_containers/bottle.dm
@@ -453,3 +453,8 @@
/obj/item/reagent_containers/glass/bottle/ichor/green
name = "green potion"
list_reagents = list(/datum/reagent/green_ichor = 1)
+
+/obj/item/reagent_containers/glass/bottle/thermite
+ name = "thermite bottle"
+ list_reagents = list(/datum/reagent/thermite = 30)
+
diff --git a/icons/obj/blackmarket.dmi b/icons/obj/blackmarket.dmi
new file mode 100644
index 0000000000..99f4811ea6
Binary files /dev/null and b/icons/obj/blackmarket.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index ac160fb9d3..dbf539c11e 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -28,6 +28,7 @@
#include "code\__DEFINES\antagonists.dm"
#include "code\__DEFINES\atmospherics.dm"
#include "code\__DEFINES\atom_hud.dm"
+#include "code\__DEFINES\blackmarket.dm"
#include "code\__DEFINES\botany.dm"
#include "code\__DEFINES\callbacks.dm"
#include "code\__DEFINES\cargo.dm"
@@ -310,6 +311,7 @@
#include "code\controllers\subsystem\augury.dm"
#include "code\controllers\subsystem\autotransfer.dm"
#include "code\controllers\subsystem\blackbox.dm"
+#include "code\controllers\subsystem\blackmarket.dm"
#include "code\controllers\subsystem\chat.dm"
#include "code\controllers\subsystem\communications.dm"
#include "code\controllers\subsystem\dbcore.dm"
@@ -1869,6 +1871,15 @@
#include "code\modules\cargo\packs.dm"
#include "code\modules\cargo\supplypod.dm"
#include "code\modules\cargo\supplypod_beacon.dm"
+#include "code\modules\cargo\blackmarket\blackmarket_item.dm"
+#include "code\modules\cargo\blackmarket\blackmarket_market.dm"
+#include "code\modules\cargo\blackmarket\blackmarket_telepad.dm"
+#include "code\modules\cargo\blackmarket\blackmarket_uplink.dm"
+#include "code\modules\cargo\blackmarket\blackmarket_items\clothing.dm"
+#include "code\modules\cargo\blackmarket\blackmarket_items\consumables.dm"
+#include "code\modules\cargo\blackmarket\blackmarket_items\misc.dm"
+#include "code\modules\cargo\blackmarket\blackmarket_items\tools.dm"
+#include "code\modules\cargo\blackmarket\blackmarket_items\weapons.dm"
#include "code\modules\cargo\bounties\assistant.dm"
#include "code\modules\cargo\bounties\botany.dm"
#include "code\modules\cargo\bounties\chef.dm"