diff --git a/__DEFINES/global.dm b/__DEFINES/global.dm
index 2fe0887490c..2aa21af2d61 100644
--- a/__DEFINES/global.dm
+++ b/__DEFINES/global.dm
@@ -233,7 +233,8 @@ var/recall_time_limit = 72000
//NO FUCKING EXCUSE FOR THE ATROCITY THAT WAS
var/list/score=list(
"crewscore" = 0, //This is the overall var/score for the whole round
- "stuffshipped" = 0, //How many useful items have cargo shipped out? Currently broken
+ "plasmashipped" = 0,//How much plasma has been sent to centcom?
+ "stuffshipped" = 0, //How many centcom orders have cargo fulfilled?
"stuffharvested" = 0, //How many harvests have hydroponics done (per crop)?
"oremined" = 0, //How many chunks of ore were smelted
"eventsendured" = 0, //How many random events did the station endure?
diff --git a/__DEFINES/setup.dm b/__DEFINES/setup.dm
index c91d9d0d059..ffb719969bf 100644
--- a/__DEFINES/setup.dm
+++ b/__DEFINES/setup.dm
@@ -1605,6 +1605,11 @@ var/proccalls = 1
#define HUMAN_DNA 1
#define XENO_DNA 2
+// Buffer datatype flags.
+#define DNA2_BUF_UI 1
+#define DNA2_BUF_UE 2
+#define DNA2_BUF_SE 4
+
#define DEFAULT_BLOOD "#A10808"
#define DEFAULT_FLESH "#FFC896"
#define ALIEN_BLOOD "#05EE05"
diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm
index 48f78305579..143a0a88691 100644
--- a/code/controllers/shuttle_controller.dm
+++ b/code/controllers/shuttle_controller.dm
@@ -285,6 +285,27 @@ datum/emergency_shuttle/proc/shuttle_phase(var/phase, var/casual = 1)
vote_preload()
location = 2
+ //if the crew brought items ordered by centcom with them, they get paid for those as if it were the supply shuttle
+ for(var/atom/movable/MA in shuttle.linked_area)
+ if(MA.anchored && !ismecha(MA))
+ continue
+
+ if(istype(MA,/obj/structure/closet/crate))
+ for(var/obj/A in MA)
+ SSsupply_shuttle.SellObjToOrders(A,1,TRUE)
+ else
+ SSsupply_shuttle.SellObjToOrders(MA,0,TRUE)
+
+ for(var/datum/centcomm_order/O in SSsupply_shuttle.centcomm_orders)
+ O.cargo_contribution = 0//Cargo doesn't get their 10% bonus when items are shipped this way.
+ if(O.CheckFulfilled())
+ if (!istype(O, /datum/centcomm_order/per_unit))
+ O.Pay()//per_unit payments are handled by CheckFulfilled()
+ SSsupply_shuttle.centcomm_orders.Remove(O)
+ for(var/obj/machinery/computer/supplycomp/S in SSsupply_shuttle.supply_consoles)//juiciness!
+ S.say("Central Command request fulfilled!")
+ playsound(S, 'sound/machines/info.ogg', 50, 1)
+
if(ticker)
ticker.mode.ShuttleDocked(2)
diff --git a/code/controllers/subsystem/supply_shuttle.dm b/code/controllers/subsystem/supply_shuttle.dm
index 557956520e7..224d8a7c691 100644
--- a/code/controllers/subsystem/supply_shuttle.dm
+++ b/code/controllers/subsystem/supply_shuttle.dm
@@ -7,6 +7,9 @@
#define REASON_LEN 140 // max length for reason message, nanoui appears to not like long strings.
+#define CENTCOMM_ORDER_DELAY_MIN (20 MINUTES)
+#define CENTCOMM_ORDER_DELAY_MAX (40 MINUTES)
+
var/datum/subsystem/supply_shuttle/SSsupply_shuttle
/datum/subsystem/supply_shuttle
@@ -34,6 +37,8 @@ var/datum/subsystem/supply_shuttle/SSsupply_shuttle
var/datum/materials/materials_list
var/restriction = 1 //Who can approve orders? 0 = autoapprove; 1 = has access; 2 = has an ID (omits silicons); 3 = actions require PIN
var/requisition = 0 //Are orders being paid for by the department? 0 = no; 1 = auto; possible future: allow with pin?
+ var/centcomm_order_cooldown = 9999
+ var/centcomm_last_order = 0
/datum/subsystem/supply_shuttle/New()
NEW_SS_GLOBAL(SSsupply_shuttle)
@@ -47,6 +52,10 @@ var/datum/subsystem/supply_shuttle/SSsupply_shuttle
var/datum/supply_packs/P = new typepath
supply_packs[P.name] = P
+ add_centcomm_order(new /datum/centcomm_order/per_unit/plasma)
+
+ centcomm_last_order = world.time
+ centcomm_order_cooldown = rand(CENTCOMM_ORDER_DELAY_MIN,CENTCOMM_ORDER_DELAY_MAX)
..()
/datum/subsystem/supply_shuttle/fire(resumed = FALSE)
@@ -59,6 +68,27 @@ var/datum/subsystem/supply_shuttle/SSsupply_shuttle
eta = 0
send()
+ if (world.time > (centcomm_last_order + centcomm_order_cooldown))
+
+
+ //1 more simultaneous order for every 10 players.
+ //Centcomm uses the crew manifest to determine how many people actually are on the station.
+ var/new_orders = 1 + round(data_core.general.len / 10)
+ for (var/i = 1 to new_orders)
+ create_weighted_order()
+
+ //If the are less than 1 order per 5 crew members, the next order will come sooner, otherwise later.
+ var/new_cooldown = 1 + round(data_core.general.len / 5)
+ var/modified_min = CENTCOMM_ORDER_DELAY_MIN
+ var/modified_max = CENTCOMM_ORDER_DELAY_MAX
+
+ var/delta = (centcomm_orders.len - new_cooldown)// Sign tells us if we need to add or substract time
+ new_cooldown = centcomm_orders.len
+ modified_max = max(modified_min, modified_max - 5 * delta MINUTES)
+
+ centcomm_last_order = world.time
+ centcomm_order_cooldown = rand(modified_min,modified_max)
+
/datum/supply_order
var/ordernum
var/datum/supply_packs/object = null
@@ -108,19 +138,22 @@ var/datum/subsystem/supply_shuttle/SSsupply_shuttle
return 1
-/datum/subsystem/supply_shuttle/proc/SellObjToOrders(var/atom/A,var/in_crate)
+/datum/subsystem/supply_shuttle/proc/SellObjToOrders(var/atom/A,var/in_crate,var/preserve = FALSE)
+ if (istype(A,/obj/item/weapon/storage/lockbox))
+ for (var/atom/A2 in A)
+ SellObjToOrders(A2, 1)
+ if(A2 && !preserve)
+ qdel(A2)
// Per-unit orders run last so they don't steal shit.
- var/list/deferred_order_checks=list()
- var/order_idx=0
+ var/list/deferred_orders = list()
for(var/datum/centcomm_order/O in centcomm_orders)
- order_idx++
if(istype(O,/datum/centcomm_order/per_unit))
- deferred_order_checks += order_idx
- if(O.CheckShuttleObject(A,in_crate))
+ deferred_orders += O
+ continue
+ if(O.CheckShuttleObject(A,in_crate,preserve))
return
- for(var/oid in deferred_order_checks)
- var/datum/centcomm_order/O = centcomm_orders[oid]
- if(O.CheckShuttleObject(A,in_crate))
+ for(var/datum/centcomm_order/O in deferred_orders)
+ if(O.CheckShuttleObject(A,in_crate,preserve))
return
/datum/subsystem/supply_shuttle/proc/sell()
@@ -131,51 +164,22 @@ var/datum/subsystem/supply_shuttle/SSsupply_shuttle
var/datum/money_account/cargo_acct = department_accounts["Cargo"]
+ var/recycled_crates = 0
for(var/atom/movable/MA in shuttle)
- if(MA.anchored)
+ if(MA.anchored && !ismecha(MA))
continue
- if(istype(MA, /obj/item/stack/sheet/mineral/plasma))
- var/obj/item/stack/sheet/mineral/plasma/P = MA
- if(P.redeemed)
- continue
- var/datum/material/mat = materials_list.getMaterial(P.mat_type)
- var/amount = (mat.value * 10) * P.amount
- cargo_acct.money += amount
- var/datum/transaction/T = new()
- T.target_name = cargo_acct.owner_name
- T.purpose = "Central Command Plasma sale"
- T.amount = amount
- T.date = current_date_string
- T.time = worldtime2text()
- cargo_acct.transaction_log.Add(T)
- // Must be in a crate!
- else if(istype(MA,/obj/structure/closet/crate))
- cargo_acct.money += credits_per_crate
- var/find_slip = 1
+ if(istype(MA,/obj/structure/closet/crate))
+ recycled_crates++
+ var/find_slip = 1
for(var/obj/A in MA)
- if(istype(A, /obj/item/stack/sheet/mineral/plasma))
- var/obj/item/stack/sheet/mineral/plasma/P = A
- if(P.redeemed)
- continue
- var/datum/material/mat = materials_list.getMaterial(P.mat_type)
- var/amount = (mat.value * 10) * P.amount
- cargo_acct.money += amount
- var/datum/transaction/T = new()
- T.target_name = cargo_acct.owner_name
- T.purpose = "Central Command Plasma sale"
- T.amount = amount
- T.date = current_date_string
- T.time = worldtime2text()
- cargo_acct.transaction_log.Add(T)
- continue
if(find_slip && istype(A,/obj/item/weapon/paper/manifest))
var/obj/item/weapon/paper/slip = A
if(slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense
var/datum/transaction/T = new()
- T.target_name = cargo_acct.owner_name
- T.purpose = "Central Command purchase confirmation (Stamped Slip) [A]"
+ T.target_name = "Central Command Administration"
+ T.purpose = "Purchase confirmation (Stamped Slip) [A]"
T.amount = credits_per_slip
T.date = current_date_string
T.time = worldtime2text()
@@ -195,10 +199,24 @@ var/datum/subsystem/supply_shuttle/SSsupply_shuttle
// PAY UP BITCHES
for(var/datum/centcomm_order/O in centcomm_orders)
if(O.CheckFulfilled())
- O.Pay()
+ if (!istype(O, /datum/centcomm_order/per_unit))
+ O.Pay()//per_unit payments are handled by CheckFulfilled()
centcomm_orders.Remove(O)
- qdel(MA)
+ for(var/obj/machinery/computer/supplycomp/S in supply_consoles)//juiciness!
+ S.say("Central Command request fulfilled!")
+ playsound(S, 'sound/machines/info.ogg', 50, 1)
+ if(MA)
+ qdel(MA)
+ if (recycled_crates)
+ var/datum/transaction/T = new()
+ T.target_name = "Central Command Recycling"
+ T.purpose = "[recycled_crates] recycled crate[recycled_crates > 1 ? "s" : ""]"
+ T.amount = credits_per_crate*recycled_crates
+ T.date = current_date_string
+ T.time = worldtime2text()
+ cargo_acct.transaction_log.Add(T)
+ cargo_acct.money += credits_per_crate*recycled_crates
/datum/subsystem/supply_shuttle/proc/buy()
if(!shoppinglist.len)
@@ -333,7 +351,7 @@ var/datum/subsystem/supply_shuttle/SSsupply_shuttle
/datum/subsystem/supply_shuttle/proc/add_centcomm_order(var/datum/centcomm_order/C)
centcomm_orders.Add(C)
var/name = "External order form - [C.name] order number [C.id]"
- var/info = {"
Central command supply requisition form
+ var/info = {"Central Command supply requisition form
INDEX: #[C.id]
REQUESTED BY: [C.name]
MUST BE IN CRATE: [C.must_be_in_crate ? "YES" : "NO"]
@@ -341,9 +359,30 @@ var/datum/subsystem/supply_shuttle/SSsupply_shuttle
[C.getRequestsByName(1)]
WORTH: [C.worth] credits TO [C.acct_by_string]
"}
+ if (C.silent)
+ return
for(var/obj/machinery/computer/supplycomp/S in supply_consoles)
var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(S.loc)
reqform.name = name
reqform.info = info
reqform.update_icon()
- S.say("New central command request available")
+ S.say("New Central Command request available!")
+ playsound(S, 'sound/machines/twobeep.ogg', 50, 1)
+
+ for (var/obj/machinery/message_server/MS in message_servers)
+ if(MS.is_functioning())
+ for (var/obj/machinery/requests_console/Console in requests_consoles)
+ if (Console.department in C.request_consoles_to_notify)
+ Console.screen = 8
+ if(Console.newmessagepriority < 1)
+ Console.newmessagepriority = 1
+ Console.icon_state = "req_comp2"
+ if(!Console.silent)
+ playsound(Console.loc, 'sound/machines/request.ogg', 50, 1)
+ Console.visible_message("The [src] beeps; New Order from [C.name]")
+ Console.messages += "[name]
[info]"
+ Console.set_light(2)
+
+
+#undef CENTCOMM_ORDER_DELAY_MIN
+#undef CENTCOMM_ORDER_DELAY_MAX
diff --git a/code/game/centcomm_orders.dm b/code/game/centcomm_orders.dm
deleted file mode 100644
index 4bad6d69d60..00000000000
--- a/code/game/centcomm_orders.dm
+++ /dev/null
@@ -1,303 +0,0 @@
-/********************
-* Track orders made by centcomm
-*
-* Used for the new cargo system
-*********************/
-var/global/current_centcomm_order_id=124901
-
-/datum/centcomm_order
- var/id = 0 // Some bullshit ID we use for fluff.
- var/name = "CentComm" // Name of the ordering entity. Fluff.
- var/datum/money_account/acct // account we pay to
- var/acct_by_string = "unknown"
-
- // Amount decided upon
- var/worth = 0
-
- var/must_be_in_crate = 1
- var/recurring = 0
-
- // /type = amount
- var/list/requested=list()
- var/list/fulfilled=list()
-
-/datum/centcomm_order/New()
- ..()
- id = current_centcomm_order_id++
- name = command_name()
-
-/datum/centcomm_order/proc/CheckShuttleObject(var/obj/O, var/in_crate)
- if(must_be_in_crate && !in_crate)
- return 0
- if(!O)
- return 0
- if(O.type in requested)
- var/amount = 1
- if(istype(O, /obj/item/stack))
- var/obj/item/stack/S = O
- amount = S.amount
- if(!(O.type in fulfilled))
- fulfilled[O.type]=0
- // Don't claim stuff that other orders may want.
- if(fulfilled[O.type]==requested[O.type])
- return 0
- fulfilled[O.type]+=amount
- qdel(O)
- return 1
-
-/datum/centcomm_order/proc/CheckFulfilled(var/obj/O, var/in_crate)
- for(var/typepath in requested)
- if(!(typepath in fulfilled) || fulfilled[typepath] < requested[typepath])
- return 0
- return 1
-
-/datum/centcomm_order/proc/Pay()
- acct.charge(-worth,null,"Payment for order #[id]",dest_name = name)
-
-/datum/centcomm_order/proc/getRequestsByName(var/html_format = 0)
- var/manifest = ""
- if(html_format)
- manifest = ""
- for(var/path in requested)
- if(!path)
- continue
- var/atom/movable/AM = path
- if(html_format)
- manifest += "- [initial(AM.name)], amount: [requested[path]]
"
- else
- manifest += "[initial(AM.name)], amount: [requested[path]]"
- if(html_format)
- manifest += "
"
- return manifest
-
-/datum/centcomm_order/proc/getFulfilledByName(var/html_format = 0)
- var/manifest = ""
- if(html_format)
- manifest = ""
- for(var/path in fulfilled)
- if(!path)
- continue
- var/atom/movable/AM = path
- if(html_format)
- manifest += "- [initial(AM.name)], amount: [fulfilled[path]]
"
- else
- manifest += "[initial(AM.name)], amount: [fulfilled[path]]"
- if(html_format)
- manifest += "
"
- return manifest
-
-/datum/centcomm_order/proc/OnPostUnload()
- return
-
-// These run *last*.
-/datum/centcomm_order/per_unit
- recurring=1
- var/list/unit_prices=list()
-
-// Same as normal, but will take every last bit of what you provided.
-/datum/centcomm_order/per_unit/CheckShuttleObject(var/obj/O, var/in_crate)
- if(must_be_in_crate && !in_crate)
- return 0
- if(!O)
- return 0
- if(O.type in requested)
- if(!(O.type in fulfilled))
- fulfilled[O.type]=0
- fulfilled[O.type]=fulfilled[O.type]+1
-
- qdel(O)
- return 1
-
-/datum/centcomm_order/per_unit/CheckFulfilled()
- var/toPay=0
- for(var/typepath in fulfilled)
- var/worth_per_unit = unit_prices[typepath]
- var/amount = fulfilled[typepath]
- toPay += amount * worth_per_unit
- if(requested[typepath]!=INFINITY)
- requested[typepath] = max(0,requested[typepath] - fulfilled[typepath])
- fulfilled[typepath]=0
- if(toPay)
- acct.charge(-toPay,null,"Payment for order #[id]",dest_name = name)
- return
-
-//////////////////////////////////////////////
-// ORDERS START HERE
-//////////////////////////////////////////////
-/datum/centcomm_order/per_unit/plasma
- name = "Nanotrasen"
- recurring = 1
- requested = list(
- /obj/item/stack/sheet/mineral/plasma = INFINITY
- )
- unit_prices=list(
- /obj/item/stack/sheet/mineral/plasma = 0.5 // 1 credit per two plasma sheets.
- )
-
-/datum/centcomm_order/department/New()
- ..()
- acct = department_accounts[acct_by_string]
-
-/datum/centcomm_order/department/cargo //Orders that cargo can manage
- acct_by_string = "Cargo"
-
-/datum/centcomm_order/department/cargo/diamonds/New()
- ..()
- requested = list(
- /obj/item/stack/sheet/mineral/diamond = rand(5,50)
- )
- worth = (VALUE_DIAMOND+rand(1,3))*requested[requested[1]]
-
-/datum/centcomm_order/department/cargo/uranium/New()
- ..()
- requested = list(
- /obj/item/stack/sheet/mineral/uranium = rand(5,50)
- )
- worth = (VALUE_URANIUM*rand(1,3))*requested[requested[1]]
-
-/datum/centcomm_order/department/cargo/gold/New()
- ..()
- requested = list(
- /obj/item/stack/sheet/mineral/gold = rand(5,50)
- )
- worth = (VALUE_GOLD*rand(1,3))*requested[requested[1]]
-
-/datum/centcomm_order/department/cargo/silver/New()
- ..()
- requested = list(
- /obj/item/stack/sheet/mineral/silver = rand(5,50)
- )
- worth = (VALUE_SILVER*rand(1,3))*requested[requested[1]]
-
-/datum/centcomm_order/department/cargo/phazon/New()
- ..()
- requested = list(
- /obj/item/stack/sheet/mineral/phazon = rand(1,10)
- )
- worth = (VALUE_PHAZON*rand(1,3))*requested[requested[1]]
-
-/datum/centcomm_order/department/cargo/clown/New()
- ..()
- requested = list(
- /obj/item/stack/sheet/mineral/clown = rand(1,10)
- )
- worth = (VALUE_CLOWN*rand(1,3))*requested[requested[1]]
-
-
-/datum/centcomm_order/department/science //Orders that science can manage
- acct_by_string = "Science"
-
-/datum/centcomm_order/department/science/nuclear_gun/New()
- ..()
- requested = list(
- /obj/item/weapon/gun/energy/gun/nuclear = rand(1,5)
- )
- worth = rand(350,750)*requested[requested[1]]
-
-/datum/centcomm_order/department/science/subspace_tunnel/New()
- ..()
- requested = list(
- /obj/item/weapon/subspacetunneler = rand(1,3)
- )
- worth = rand(350,750)*requested[requested[1]]
-
-/datum/centcomm_order/department/medical
- acct_by_string = "Medical"
-
-/datum/centcomm_order/department/medical/kidneys/New()
- ..()
- requested = list(
- /obj/item/organ/internal/kidneys = rand(1,3)
- )
- worth = rand(100,300)*requested[requested[1]]
-
-/datum/centcomm_order/department/civilian
- acct_by_string = "Civilian"
-
-/datum/centcomm_order/department/civilian/pie/New()
- ..()
- requested = list(
- /obj/item/weapon/reagent_containers/food/snacks/pie = rand(3,12)
- )
- worth = rand(15,30)*requested[requested[1]]
- name = "Clown Federation" //honk
-
-/datum/centcomm_order/department/civilian/poutinecitadel/New()
- ..()
- requested = list(
- /obj/structure/poutineocean/poutinecitadel = 1
- )
- must_be_in_crate = 0
- worth = rand(1000,3000)*requested[requested[1]]
-
-/datum/centcomm_order/department/civilian/sweetsundaeramen/New()
- ..()
- requested = list(
- /obj/item/weapon/reagent_containers/food/snacks/sweetsundaeramen = rand(1,3)
- )
- worth = rand(150,300)*requested[requested[1]]
-
-/datum/centcomm_order/department/civilian/superburger/New()
- ..()
- requested = list(
- /obj/item/weapon/reagent_containers/food/snacks/superbiteburger = rand(1,3)
- )
- worth = rand(250,500)*requested[requested[1]]
-
-/datum/centcomm_order/department/civilian/turkey/New()
- ..()
- requested = list(
- /obj/item/weapon/reagent_containers/food/snacks/sliceable/turkey = rand(1,2)
- )
- worth = rand(200,400)*requested[requested[1]]
-
-/datum/centcomm_order/department/civilian/popcake/New()
- ..()
- requested = list(
- /obj/structure/popout_cake = 1
- )
- must_be_in_crate = 0
- worth = rand(600,1200)*requested[requested[1]]
-
-/datum/centcomm_order/department/civilian/bkipper/New()
- ..()
- requested = list(
- /obj/item/weapon/reagent_containers/food/snacks/bleachkipper = rand(2,5)
- )
- worth = rand(120,500)*requested[requested[1]]
-
-/datum/centcomm_order/department/civilian/potentham/New()
- ..()
- requested = list(
- /obj/item/weapon/reagent_containers/food/snacks/potentham = rand(1,2)
- )
- worth = rand(400,2001)*requested[requested[1]]
-
-/datum/centcomm_order/department/civilian/sundayroast/New()
- ..()
- requested = list(
- /obj/item/weapon/reagent_containers/food/snacks/sundayroast = rand(1,2)
- )
- worth = rand(400,900)*requested[requested[1]]
-
-/proc/create_centcomm_order(var/datum/centcomm_order/C)
- SSsupply_shuttle.add_centcomm_order(C)
-
-/proc/get_potential_orders()
- var/list/orders = list()
- orders.Add(subtypesof(/datum/centcomm_order/department/cargo))
- orders.Add(subtypesof(/datum/centcomm_order/department/science))
- orders.Add(subtypesof(/datum/centcomm_order/department/medical))
- orders.Add(subtypesof(/datum/centcomm_order/department/civilian))
-
- return orders
-
-/proc/create_random_order()
- var/choice = pick(get_potential_orders())
- create_centcomm_order(new choice)
-
-/proc/create_random_orders(var/num_orders)
- var/list/choices = get_potential_orders()
- for(var/i = 1 to num_orders)
- var/choice = pick_n_take(choices)
- create_centcomm_order(new choice)
\ No newline at end of file
diff --git a/code/game/centcomm_orders/centcomm_orders.dm b/code/game/centcomm_orders/centcomm_orders.dm
new file mode 100644
index 00000000000..b8f44b729c5
--- /dev/null
+++ b/code/game/centcomm_orders/centcomm_orders.dm
@@ -0,0 +1,377 @@
+/********************
+* Track orders made by centcomm
+*
+* Used for the new cargo system
+*********************/
+var/global/current_centcomm_order_id=124901
+
+/datum/centcomm_order
+ var/id = 0 // Some bullshit ID we use for fluff.
+ var/name = "Central Command" // Name of the ordering entity. Fluff.
+ var/datum/money_account/acct // account we pay to
+ var/acct_by_string = ""
+ var/silent = 0
+
+ // Amount decided upon
+ var/worth = 0
+
+ var/cargo_contribution = 0.1
+
+ var/must_be_in_crate = 1
+
+ var/extra_requirements = ""//specify when you want the items to have been modified in a certain way or have certain properties.
+ //then use ExtraChecks() to verify that the shipped item has those requested properties
+ //for example: to verify that a shipped organ is still alive.
+
+ // /type = amount
+ var/list/requested=list()
+ var/list/fulfilled=list()
+
+ var/list/name_override=list()//use when you want the requested to appear with a different name, useful when you want to be more descriptive
+ //for example: "vials of infected blood"
+
+ var/list/request_consoles_to_notify=list()//when the order is created, Request Consoles in this list will immediately
+
+ var/hidden = FALSE //orders that we don't want to see randomly appear
+
+/* list of all request consoles "department" vars currently used in our maps.
+ Engineering
+ "Chief Engineer's Desk"
+ "Atmospherics"
+ "Engineering"
+ "Pod Bay"
+ "Mechanics"
+
+ Medbay
+ "Chief Medical Officer's Desk"
+ "Medbay"
+ "Chemistry"
+ "Genetics"
+ "Virology"
+
+ Security
+ "Head of Security's Desk"
+ "Security"
+
+ Service
+ "Head of Personnel's Desk"
+ "Kitchen"
+ "Bar"
+ "Hydroponics"
+ "Cargo Bay"
+ "Janitorial"
+ "Chapel"
+
+ Science
+ "Research Director's Desk"
+ "Science"
+ "Robotics"
+ "Telecoms Admin"
+
+ probably won't even need to notify need those
+ "AI"
+ "Bridge"
+ "Captain's Desk"
+ "Locker Room"
+ "Tool Storage"
+ "Arrival Shuttle"
+ "EVA"
+*/
+
+/datum/centcomm_order/New()
+ ..()
+ id = current_centcomm_order_id++
+
+ if (acct_by_string)
+ acct = department_accounts[acct_by_string]
+ else
+ acct = station_account
+ acct_by_string = station_name()
+
+/datum/centcomm_order/Destroy()
+ acct = null
+ ..()
+
+/datum/centcomm_order/proc/ExtraChecks(var/atom/movable/AM)
+ return 1
+
+/datum/centcomm_order/proc/CheckShuttleObject(var/obj/O, var/in_crate, var/preserve = FALSE)
+ if(must_be_in_crate && !in_crate)
+ return 0
+ if(!O)
+ return 0
+ if(is_type_in_list(O, requested))
+ var/amount = 1
+ if(istype(O, /obj/item/stack))
+ var/obj/item/stack/S = O
+ amount = S.amount
+ if(!is_type_in_list(O, fulfilled))
+ fulfilled[O.type] = 0
+ // Don't claim stuff that other orders may want.
+ if(fulfilled[O.type] == requested[O.type])
+ return 0
+ if (!ExtraChecks(O))
+ return 0
+ fulfilled[O.type] += amount
+ if (!preserve)
+ qdel(O)
+ return 1
+ return 0
+
+/datum/centcomm_order/proc/CheckFulfilled()
+ for(var/typepath in requested)
+ if(!(typepath in fulfilled) || fulfilled[typepath] < requested[typepath])
+ return FALSE
+ score["stuffshipped"]++
+ return TRUE
+
+/datum/centcomm_order/proc/Pay(var/complete = TRUE)
+ acct.charge(-worth,null,"Payment for order #[id]",dest_name = name)
+
+ if (cargo_contribution > 0 && acct_by_string != "Cargo")//cargo gets some extra coin from every order shipped
+ var/datum/money_account/cargo_acct = department_accounts["Cargo"]
+ cargo_acct.charge(round(-worth/10),null,"Contribution for order #[id]",dest_name = name)
+
+
+/datum/centcomm_order/proc/getRequestsByName(var/html_format = 0)
+ var/manifest = ""
+ if(html_format)
+ manifest = ""
+ for(var/path in requested)
+ if(!path)
+ continue
+ var/atom_name
+ if (path in name_override)
+ atom_name = name_override[path]
+ else
+ var/atom/movable/AM = path
+ atom_name = initial(AM.name)
+ var/amount = "[requested[path]]"
+ if (requested[path]==INFINITY)
+ amount = "Just keep it comin'"
+ if(html_format)
+ manifest += "- [atom_name], amount: [amount]
"
+ else
+ manifest += "[atom_name], amount: [amount]"
+ if(html_format)
+ manifest += "
"
+ if (extra_requirements)
+ if(html_format)
+ manifest += "[extra_requirements]
"
+ return manifest
+
+/datum/centcomm_order/proc/getFulfilledByName(var/html_format = 0)
+ var/manifest = ""
+ if(html_format)
+ manifest = ""
+ for(var/path in fulfilled)
+ if(!path)
+ continue
+ var/atom_name
+ if (path in name_override)
+ atom_name = name_override[path]
+ else
+ var/atom/movable/AM = path
+ atom_name = initial(AM.name)
+ if(html_format)
+ manifest += "- [atom_name], amount: [fulfilled[path]]
"
+ else
+ manifest += "[atom_name], amount: [fulfilled[path]]"
+ if(html_format)
+ manifest += "
"
+ return manifest
+
+/datum/centcomm_order/proc/OnPostUnload()
+ return
+
+// These run *last*.
+/datum/centcomm_order/per_unit
+ var/list/unit_prices = list()
+ var/left_to_check = list()
+ var/toPay = 0
+
+
+/datum/centcomm_order/per_unit/Pay(var/complete = TRUE)
+ if(toPay)
+ if(complete)
+ acct.charge(-toPay,null,"Complete payment for per-unit order #[id]",dest_name = name)
+ score["stuffshipped"]++
+ else
+ acct.charge(-toPay,null,"Partial payment for per-unit order #[id]",dest_name = name)
+
+ if (cargo_contribution > 0 && acct_by_string != "Cargo")//cargo gets some extra coin from every order shipped
+ var/datum/money_account/cargo_acct = department_accounts["Cargo"]
+ cargo_acct.charge(round(-worth * cargo_contribution),null,"Contribution for partial order #[id]",dest_name = name)
+ toPay = 0
+
+// Same as normal, but will take every last bit of what you provided.
+/datum/centcomm_order/per_unit/CheckShuttleObject(var/obj/O, var/in_crate, var/preserve = FALSE)
+ if(must_be_in_crate && !in_crate)
+ return 0
+ if(!O)
+ return 0
+ if(is_type_in_list(O, requested))
+ var/amount = 1
+ if(istype(O, /obj/item/stack))
+ var/obj/item/stack/S = O
+ amount = S.amount
+ if(!is_type_in_list(O, left_to_check))
+ left_to_check[O.type]=0
+ if (!ExtraChecks(O))
+ return 0
+ left_to_check[O.type] += amount
+ if (!preserve)
+ qdel(O)
+ return 1
+ return 0
+
+/datum/centcomm_order/per_unit/CheckFulfilled()
+ toPay = 0
+ for(var/typepath in left_to_check)
+ var/worth_per_unit = unit_prices[typepath]
+ var/amount = left_to_check[typepath]
+ toPay += amount * worth_per_unit
+ if(requested[typepath] != INFINITY)
+ requested[typepath] = max(0,requested[typepath] - left_to_check[typepath])
+ if(!(typepath in fulfilled))
+ fulfilled[typepath] = 0
+ fulfilled[typepath] += left_to_check[typepath]
+ left_to_check[typepath] = 0
+ . = ..()
+ Pay(.)
+
+///////////////////////////////
+
+/proc/create_random_orders(var/num_orders)//This one is used at roundstart to add a couple random orders immediately
+ var/list/choices = get_all_orders()
+ for(var/i = 1 to num_orders)
+ var/choice = pick_n_take(choices)
+ var/datum/centcomm_order/new_order = new choice
+ SSsupply_shuttle.add_centcomm_order(new_order)
+
+/proc/get_all_orders()
+ var/list/orders = list()
+ orders.Add(subtypesof(/datum/centcomm_order/per_unit/department/cargo))
+ orders.Add(subtypesof(/datum/centcomm_order/department/science))
+ orders.Add(subtypesof(/datum/centcomm_order/department/medical))
+ orders.Add(subtypesof(/datum/centcomm_order/department/engineering))
+ orders.Add(subtypesof(/datum/centcomm_order/department/civilian))
+ orders.Add(subtypesof(/datum/centcomm_order/per_unit/department/civilian))
+ return orders
+
+
+///////////////////////////////////////
+
+/proc/create_weighted_order()
+ var/list/active_with_role = get_dept_pop()
+
+ var/list/department_weights = list(
+ "Cargo" = 3,
+ "Civilian" = 5,
+ "Medical" = 5,
+ "Science" = 5,
+ "Engineering" = 5,
+ )
+
+ for(var/dept in department_weights)
+ if(active_with_role[dept] < 1)
+ department_weights[dept] = 1//departments with no employees are very unlikely to receive an order
+
+ var/list/order_exists = list(
+ "Cargo" = 0,
+ "Civilian" = 0,
+ "Medical" = 0,
+ "Science" = 0,
+ "Engineering" = 0,
+ )
+
+ for(var/datum/centcomm_order/O in SSsupply_shuttle.centcomm_orders)
+ if (O.acct_by_string in order_exists)
+ order_exists[O.acct_by_string] += 1
+
+ for(var/dept in order_exists)
+ department_weights[dept] = max(1, department_weights[dept] - order_exists[dept])//the more active orders a department has, the less likely it'll get another one
+
+ var/chosen_dept = pick(
+ department_weights["Cargo"];"Cargo",
+ department_weights["Civilian"];"Civilian",
+ department_weights["Medical"];"Medical",
+ department_weights["Science"];"Science",
+ department_weights["Engineering"];"Engineering")
+
+ var/list/orders = list()
+ switch(chosen_dept)
+ if ("Cargo")
+ orders.Add(subtypesof(/datum/centcomm_order/per_unit/department/cargo))
+ if ("Civilian")
+ orders.Add(subtypesof(/datum/centcomm_order/department/civilian))
+ orders.Add(subtypesof(/datum/centcomm_order/per_unit/department/civilian))
+ if ("Medical")
+ orders.Add(subtypesof(/datum/centcomm_order/department/medical))
+ if ("Science")
+ orders.Add(subtypesof(/datum/centcomm_order/department/science))
+ if ("Engineering")
+ orders.Add(subtypesof(/datum/centcomm_order/department/engineering))
+
+ orders -= SSsupply_shuttle.centcomm_orders//we don't want a duplicate order
+
+ for (var/O in orders)//removing hidden orders
+ var/datum/centcomm_order/CO = O
+ if (initial(CO.hidden))
+ orders -= O
+
+ if (!orders.len)
+ return
+
+ var/chosen_order = pick(orders)
+ SSsupply_shuttle.add_centcomm_order(new chosen_order)
+
+
+/proc/get_dept_pop()
+ var/list/active_with_role = list()
+ active_with_role["Cargo"] = 0
+ active_with_role["Service"] = 0
+ active_with_role["Medical"] = 0
+ active_with_role["Science"] = 0
+ active_with_role["Engineering"] = 0
+
+ for(var/mob/M in player_list)
+ if(!M.mind || !M.client || M.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive
+ continue
+
+ if(M.mind.assigned_role in engineering_positions)
+ active_with_role["Engineer"]++
+
+ if(M.mind.assigned_role in medical_positions)
+ active_with_role["Medical"]++
+
+ if(M.mind.assigned_role in science_positions)
+ active_with_role["Scientist"]++
+
+ if(M.mind.assigned_role in (service_positions - "Head of Personnel"))//HoP has stuff to do
+ active_with_role["Service"]++
+
+ /* Since Cargo orders are mining only, we'll exclusively check the miner count for now
+ if(M.mind.assigned_role in (cargo_positions - "Head of Personnel"))
+ active_with_role["Cargo"]++
+ */
+ if(M.mind.assigned_role == "Shaft Miner")
+ active_with_role["Cargo"]++
+
+ return active_with_role
+
+/proc/get_dept_leaderboard()
+ var/list/dept_leaderboard = list()
+ var/list/depts = list(
+ "Cargo",
+ "Science",
+ "Medical",
+ "Civilian",
+ "Engineering")
+ for (var/dept in depts)
+ var/datum/money_account/acct = department_accounts[dept]
+ dept_leaderboard[dept] = acct.money
+ for (var/i = dept_leaderboard.len, i > 1, i--)
+ if (dept_leaderboard[dept_leaderboard[i]] > dept_leaderboard[dept_leaderboard[i-1]])
+ dept_leaderboard.Swap(i,i-1)
+ return dept_leaderboard
diff --git a/code/game/centcomm_orders/orders_cargo.dm b/code/game/centcomm_orders/orders_cargo.dm
new file mode 100644
index 00000000000..c02ffef2424
--- /dev/null
+++ b/code/game/centcomm_orders/orders_cargo.dm
@@ -0,0 +1,101 @@
+
+/datum/centcomm_order/per_unit/plasma//Centcom always wants plasma
+ name = "Nanotrasen"
+ worth = "1$ per sheet"
+ silent = 1//so we don't hear the announcement at every round start
+ requested = list(
+ /obj/item/stack/sheet/mineral/plasma = INFINITY
+ )
+ unit_prices=list(
+ /obj/item/stack/sheet/mineral/plasma = VALUE_PLASMA * 2
+ )
+
+/datum/centcomm_order/per_unit/plasma/CheckShuttleObject(var/obj/O, var/in_crate)
+ if(!in_crate)
+ return 0
+ if(!O)
+ return 0
+ if(istype(O, /obj/item/stack/sheet/mineral/plasma))
+ var/obj/item/stack/sheet/mineral/plasma/P = O
+ if(!(O.type in left_to_check))
+ left_to_check[O.type] = 0
+ left_to_check[O.type] += P.amount
+ score["plasmashipped"] += P.amount
+ qdel(O)
+ return 1
+ return 0
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// //
+// MINING ORDERS //
+// //
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//6 orders
+
+/datum/centcomm_order/per_unit/department/cargo
+ name = "Nanotrasen Industries Inc."
+ acct_by_string = "Cargo"
+ request_consoles_to_notify = list(
+ "Cargo Bay",
+ )
+
+/datum/centcomm_order/per_unit/department/cargo/diamonds/New()
+ ..()
+ requested = list(
+ /obj/item/stack/sheet/mineral/diamond = rand (8,12)
+ )
+ unit_prices=list(
+ /obj/item/stack/sheet/mineral/diamond = VALUE_DIAMOND * 3
+ )
+ worth = "[VALUE_DIAMOND+3]$ per sheet"
+
+/datum/centcomm_order/per_unit/department/cargo/uranium/New()
+ ..()
+ requested = list(
+ /obj/item/stack/sheet/mineral/uranium = rand (40,60)
+ )
+ unit_prices=list(
+ /obj/item/stack/sheet/mineral/uranium = VALUE_URANIUM * 3
+ )
+ worth = "[VALUE_URANIUM*3]$ per sheet"
+
+/datum/centcomm_order/per_unit/department/cargo/gold/New()
+ ..()
+ requested = list(
+ /obj/item/stack/sheet/mineral/gold = rand (40,60)
+ )
+ unit_prices=list(
+ /obj/item/stack/sheet/mineral/gold = VALUE_GOLD * 3
+ )
+ worth = "[VALUE_GOLD*3]$ per sheet"
+
+/datum/centcomm_order/per_unit/department/cargo/silver/New()
+ ..()
+ requested = list(
+ /obj/item/stack/sheet/mineral/silver = rand (40,60)
+ )
+ unit_prices=list(
+ /obj/item/stack/sheet/mineral/silver = VALUE_SILVER * 3
+ )
+ worth = "[VALUE_SILVER*3]$ per sheet"
+
+/datum/centcomm_order/per_unit/department/cargo/phazon/New()
+ ..()
+ requested = list(
+ /obj/item/stack/sheet/mineral/phazon = rand (8,12)
+ )
+ unit_prices=list(
+ /obj/item/stack/sheet/mineral/phazon = VALUE_PHAZON * 3
+ )
+ worth = "[VALUE_PHAZON*3]$ per sheet"
+
+/datum/centcomm_order/per_unit/department/cargo/clown/New()
+ ..()
+ requested = list(
+ /obj/item/stack/sheet/mineral/clown = rand (8,12)
+ )
+ unit_prices=list(
+ /obj/item/stack/sheet/mineral/clown = VALUE_CLOWN * 3
+ )
+ worth = "[VALUE_CLOWN*3]$ per sheet"
diff --git a/code/game/centcomm_orders/orders_engineering.dm b/code/game/centcomm_orders/orders_engineering.dm
new file mode 100644
index 00000000000..be98731bc78
--- /dev/null
+++ b/code/game/centcomm_orders/orders_engineering.dm
@@ -0,0 +1,69 @@
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// //
+// ENGINEERING ORDERS //
+// //
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//2 orders
+
+/datum/centcomm_order/department/engineering
+ acct_by_string = "Engineering"
+ request_consoles_to_notify = list(
+ "Chief Engineer's Desk",
+ "Engineering",
+ )
+
+//----------------------------------------------Engineering----------------------------------------------------
+
+
+/datum/centcomm_order/department/engineering/portable_smes/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Chief Engineer's Desk",
+ "Engineering",
+ "Mechanics",
+ )
+ must_be_in_crate = 0
+ requested = list(
+ /obj/machinery/power/battery/portable = 1
+ )
+ name_override = list(
+ /obj/machinery/power/battery/portable = "Portable Power Storage Unit"
+ )
+ extra_requirements = "The battery must be filled to full capacity."
+ worth = 800
+
+/datum/centcomm_order/department/engineering/portable_smes/ExtraChecks(var/obj/machinery/power/battery/portable/P)
+ if (!istype(P))
+ return 0
+ if (P.charge < P.capacity)
+ return 0
+ return 1
+
+
+//----------------------------------------------Atmospherics----------------------------------------------------
+
+
+/datum/centcomm_order/department/engineering/cold_canister/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Chief Engineer's Desk",
+ "Atmospherics",
+ )
+ must_be_in_crate = 0
+ requested = list(
+ /obj/machinery/portable_atmospherics/canister = 1
+ )
+ name_override = list(
+ /obj/machinery/portable_atmospherics/canister = "Cold Plasma Canister"
+ )
+ extra_requirements = "Filled with over 1000 kPa of plasma bellow 2K."
+ worth = 1300
+
+/datum/centcomm_order/department/engineering/cold_canister/ExtraChecks(var/obj/machinery/portable_atmospherics/canister/C)
+ if (!istype(C))
+ return 0
+ var/datum/gas_mixture/GM = C.return_air()
+ if ((GM.gas?.len == 1) && (GAS_PLASMA in GM.gas) && (GM.return_temperature() < 2) && (GM.pressure > 1000))
+ return 1
+ return 0
diff --git a/code/game/centcomm_orders/orders_medical.dm b/code/game/centcomm_orders/orders_medical.dm
new file mode 100644
index 00000000000..33b738f9ff0
--- /dev/null
+++ b/code/game/centcomm_orders/orders_medical.dm
@@ -0,0 +1,319 @@
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// //
+// MEDICAL ORDERS //
+// //
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//9 orders
+
+//----------------------------------------------Surgery----------------------------------------------------
+
+/datum/centcomm_order/department/medical
+ request_consoles_to_notify = list(
+ "Chief Medical Officer's Desk",
+ "Medbay",
+ )
+ acct_by_string = "Medical"
+
+/datum/centcomm_order/department/medical/kidneys/New()
+ ..()
+ requested = list(
+ /obj/item/organ/internal/kidneys = rand(1,2)
+ )
+ name_override = list(
+ /obj/item/organ/internal/kidneys = "human kidneys"
+ )
+ extra_requirements = "The organs needs to be fresh, use a medical crate or a freezer."
+ worth = 200*requested[requested[1]]
+
+/datum/centcomm_order/department/medical/kidneys/ExtraChecks(var/obj/item/organ/internal/kidneys/I)
+ if (!istype(I))
+ return 0
+ if (I.health > 0)
+ return 1
+ return 0
+
+/datum/centcomm_order/department/medical/heart/New()
+ ..()
+ requested = list(
+ /obj/item/organ/internal/heart = 1
+ )
+ name_override = list(
+ /obj/item/organ/internal/heart = "human heart"
+ )
+ extra_requirements = "The organ needs to be fresh, use a medical crate or a freezer."
+ worth = 400
+
+/datum/centcomm_order/department/medical/heart/ExtraChecks(var/obj/item/organ/internal/heart/I)
+ if (!istype(I))
+ return 0
+ if (I.health > 0)
+ return 1
+ return 0
+
+//----------------------------------------------Virology----------------------------------------------------
+
+//Vaccine
+/datum/centcomm_order/department/medical/vaccine
+ request_consoles_to_notify = list(
+ "Chief Medical Officer's Desk",
+ "Virology",
+ )
+ var/required_vac
+
+/datum/centcomm_order/department/medical/vaccine/New()
+ ..()
+ requested = list(
+ /obj/item/weapon/reagent_containers/glass/beaker/vial = 1
+ )
+ name_override = list(
+ /obj/item/weapon/reagent_containers/glass/beaker/vial = "Vial of Vaccine"
+ )
+ var/difficulty = rand(1,4)
+ switch (difficulty)
+ if (1)
+ required_vac = pick(blood_antigens)
+ worth = 200
+ if (2)
+ required_vac = pick(common_antigens)
+ worth = 400
+ if (3)
+ required_vac = pick(rare_antigens)
+ worth = 800
+ if (4)
+ required_vac = pick(alien_antigens)
+ worth = 1600
+ extra_requirements = "Must contain [required_vac] antibodies."
+
+/datum/centcomm_order/department/medical/vaccine/ExtraChecks(var/obj/item/weapon/reagent_containers/glass/beaker/vial/V)
+ if (!istype(V))
+ return 0
+ for(var/datum/reagent/vaccine/vaccine in V.reagents?.reagent_list)
+ for (var/A in vaccine.data["antigen"])
+ if (A == required_vac)
+ return 1
+ return 0
+
+//Dangerous Disease Vial
+/datum/centcomm_order/department/medical/harmful_disease/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Chief Medical Officer's Desk",
+ "Virology",
+ )
+ requested = list(
+ /obj/item/weapon/reagent_containers/glass/beaker/vial = 1
+ )
+ name_override = list(
+ /obj/item/weapon/reagent_containers/glass/beaker/vial = "Vial of Infected Blood"
+ )
+
+ extra_requirements = "Must contain a dangerous disease with a combined Effect Danger level of at least 13, and a Strength of at least 80."
+ worth = 600
+
+/datum/centcomm_order/department/medical/harmful_disease/ExtraChecks(var/obj/item/weapon/reagent_containers/glass/beaker/vial/V)
+ if (!istype(V))
+ return 0
+ var/datum/reagent/blood/blood = locate() in V.reagents.reagent_list
+ if (blood?.data["virus2"])
+ var/list/blood_viruses = blood.data["virus2"]
+ for (var/ID in blood_viruses)
+ var/datum/disease2/disease/D = blood_viruses[ID]
+ if (D.strength >= 80)
+ var/total_badness = 0
+ for(var/datum/disease2/effect/e in D.effects)
+ total_badness += e.badness
+ if (total_badness >= 13)
+ return 1
+
+ return 0
+
+//Beneficial Disease Vial
+/datum/centcomm_order/department/medical/beneficial_disease/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Chief Medical Officer's Desk",
+ "Virology",
+ )
+ requested = list(
+ /obj/item/weapon/reagent_containers/glass/beaker/vial = 1
+ )
+ name_override = list(
+ /obj/item/weapon/reagent_containers/glass/beaker/vial = "Vial of Infected Blood"
+ )
+
+ extra_requirements = "Must contain a beneficial disease with a combined Effect Danger level of at most 2."
+ worth = 1000
+
+/datum/centcomm_order/department/medical/beneficial_disease/ExtraChecks(var/obj/item/weapon/reagent_containers/glass/beaker/vial/V)
+ if (!istype(V))
+ return 0
+ var/datum/reagent/blood/blood = locate() in V.reagents.reagent_list
+ if (blood?.data["virus2"])
+ var/list/blood_viruses = blood.data["virus2"]
+ for (var/ID in blood_viruses)
+ var/datum/disease2/disease/D = blood_viruses[ID]
+ var/total_badness = 0
+ for(var/datum/disease2/effect/e in D.effects)
+ total_badness += e.badness
+ if (total_badness <= 2)
+ return 1
+
+ return 0
+
+//Specific GNA Disks
+/datum/centcomm_order/department/medical/gna_disk
+ var/already_goten = list()
+ var/req_stage
+ request_consoles_to_notify = list(
+ "Chief Medical Officer's Desk",
+ "Virology",
+ )
+
+/datum/centcomm_order/department/medical/gna_disk/New()
+ ..()
+ req_stage = rand(1,4)
+ requested = list(
+ /obj/item/weapon/disk/disease = rand (2,5)
+ )
+ name_override = list(
+ /obj/item/weapon/disk/disease = "GNA Disks"
+ )
+
+ extra_requirements = "Each must contain a different Stage [req_stage] symptom."
+ worth = 300 * requested[requested[1]]
+
+/datum/centcomm_order/department/medical/gna_disk/ExtraChecks(var/obj/item/weapon/disk/disease/Disk)
+ if (!istype(Disk))
+ return 0
+ if ((Disk.stage == req_stage) && Disk.effect && !(Disk.effect.type in already_goten))
+ already_goten += Disk.effect.type
+ return 1
+ return 0
+
+//----------------------------------------------Genetics----------------------------------------------------
+
+//Clean SE
+/datum/centcomm_order/department/medical/clean_se/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Chief Medical Officer's Desk",
+ "Genetics",
+ )
+ requested = list(
+ /obj/item/weapon/dnainjector = rand (1,5)
+ )
+ name_override = list(
+ /obj/item/weapon/dnainjector = "Clean SE Injector"
+ )
+ worth = 100 * requested[requested[1]]
+
+/datum/centcomm_order/department/medical/vaccine/ExtraChecks(var/obj/item/weapon/dnainjector/I)
+ if (!istype(I))
+ return 0
+ if (!I.block && I.buf)//Not a block injector
+ var/datum/dna2/record/R = I.buf
+ if (R.types & DNA2_BUF_SE)//SE Injector
+ for (var/block in R.dna.SE)
+ if (I.buf.dna.SE >= 2050)
+ return 0
+ return 1
+ return 0
+
+//Specific Superpowers
+/datum/centcomm_order/department/medical/xray/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Chief Medical Officer's Desk",
+ "Genetics",
+ )
+ requested = list(
+ /obj/item/weapon/dnainjector = rand (1,3)
+ )
+ name_override = list(
+ /obj/item/weapon/dnainjector = "X-Ray SE Block Injector"
+ )
+ worth = 200 * requested[requested[1]]
+
+/datum/centcomm_order/department/medical/xray/ExtraChecks(var/obj/item/weapon/dnainjector/I)
+ if (!istype(I))
+ return 0
+ if (I.block == XRAYBLOCK && I.buf)//Block Injector
+ var/datum/dna2/record/R = I.buf
+ if (R.types & DNA2_BUF_SE)//SE Injector
+ var/bstate = R.dna.GetSEState(XRAYBLOCK)
+ return bstate
+ return 0
+
+/datum/centcomm_order/department/medical/hulk/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Chief Medical Officer's Desk",
+ "Genetics",
+ )
+ requested = list(
+ /obj/item/weapon/dnainjector = rand (1,3)
+ )
+ name_override = list(
+ /obj/item/weapon/dnainjector = "Hulk SE Block Injector"
+ )
+ worth = 300 * requested[requested[1]]
+
+/datum/centcomm_order/department/medical/hulk/ExtraChecks(var/obj/item/weapon/dnainjector/I)
+ if (!istype(I))
+ return 0
+ if (I.block == HULKBLOCK && I.buf)//Block Injector
+ var/datum/dna2/record/R = I.buf
+ if (R.types & DNA2_BUF_SE)//SE Injector
+ var/bstate = R.dna.GetSEState(HULKBLOCK)
+ return bstate
+ return 0
+
+/datum/centcomm_order/department/medical/telepathy/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Chief Medical Officer's Desk",
+ "Genetics",
+ )
+ requested = list(
+ /obj/item/weapon/dnainjector = rand (1,3)
+ )
+ name_override = list(
+ /obj/item/weapon/dnainjector = "Telepathy SE Block Injector"
+ )
+ worth = 300 * requested[requested[1]]
+
+/datum/centcomm_order/department/medical/telepathy/ExtraChecks(var/obj/item/weapon/dnainjector/I)
+ if (!istype(I))
+ return 0
+ if (I.block == REMOTETALKBLOCK && I.buf)//Block Injector
+ var/datum/dna2/record/R = I.buf
+ if (R.types & 4)//SE Injector
+ var/bstate = R.dna.GetSEState(REMOTETALKBLOCK)
+ return bstate
+ return 0
+
+/datum/centcomm_order/department/medical/remoteview/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Chief Medical Officer's Desk",
+ "Genetics",
+ )
+ requested = list(
+ /obj/item/weapon/dnainjector = rand (1,3)
+ )
+ name_override = list(
+ /obj/item/weapon/dnainjector = "Remote View SE Block Injector"
+ )
+ worth = 300 * requested[requested[1]]
+
+/datum/centcomm_order/department/medical/remoteview/ExtraChecks(var/obj/item/weapon/dnainjector/I)
+ if (!istype(I))
+ return 0
+ if (I.block == REMOTEVIEWBLOCK && I.buf)//Block Injector
+ var/datum/dna2/record/R = I.buf
+ if (R.types & DNA2_BUF_SE)//SE Injector
+ var/bstate = R.dna.GetSEState(REMOTEVIEWBLOCK)
+ return bstate
+ return 0
+
diff --git a/code/game/centcomm_orders/orders_science.dm b/code/game/centcomm_orders/orders_science.dm
new file mode 100644
index 00000000000..27aff6b5afc
--- /dev/null
+++ b/code/game/centcomm_orders/orders_science.dm
@@ -0,0 +1,464 @@
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// //
+// SCIENCE ORDERS //
+// //
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//30 orders
+
+/datum/centcomm_order/department/science
+ acct_by_string = "Science"
+ request_consoles_to_notify = list(
+ "Research Director's Desk",
+ "Science",
+ )
+
+//--------------------------------------------R&D stuff----------------------------------------------------
+
+
+/datum/centcomm_order/department/science/technology
+ var/required_tech
+ var/required_level
+ var/tech
+
+//Technology Data Disk, with a set tech and level required
+/datum/centcomm_order/department/science/technology/New()
+ ..()
+ name = "Nanotrasen R&D"
+ tech = rand(1,4)
+ switch(tech)
+ if (1)
+ required_tech = /datum/tech/materials
+ required_level = 8
+ if (2)
+ required_tech = /datum/tech/bluespace
+ required_level = 4
+ if (3)
+ required_tech = /datum/tech/combat
+ required_level = 5
+ if (4)
+ required_tech = /datum/tech/magnets
+ required_level = 5
+ requested = list(
+ /obj/item/weapon/disk/tech_disk = 1
+ )
+ name_override = list(
+ /obj/item/weapon/disk/tech_disk = "Technology Data Disk"
+ )
+ var/datum/tech/DT = required_tech
+ extra_requirements = "tech required: [initial(DT.name)] (Level [required_level])"
+ worth = 750
+
+/datum/centcomm_order/department/science/technology/ExtraChecks(var/obj/item/weapon/disk/tech_disk/TD)
+ if (!istype(TD))
+ return 0
+ if (istype(TD.stored, required_tech))
+ var/datum/tech/DT = TD.stored
+ if (DT.level >= required_level)
+ return 1
+ return 0
+
+
+//Component Design Disk, with a set blueprint required
+/datum/centcomm_order/department/science/design
+ var/required_comp
+ var/comp
+
+/datum/centcomm_order/department/science/design/New()
+ ..()
+ name = "Nanotrasen R&D"
+ var/comp = rand(1,5)
+ switch(comp)
+ if (1)
+ required_comp = /datum/design/rad_cell
+ worth = 800
+ if (2)
+ required_comp = /datum/design/night_vision_goggles
+ worth = 500
+ if (3)
+ required_comp = /datum/design/plasmabeaker
+ worth = 500
+ if (4)
+ required_comp = /datum/design/bag_holding
+ worth = 700
+ if (5)
+ required_comp = /datum/design/gravitywell
+ worth = 1000
+ requested = list(
+ /obj/item/weapon/disk/design_disk = 1
+ )
+ name_override = list(
+ /obj/item/weapon/disk/design_disk = "Component Design Disk"
+ )
+ var/obj/item/I = required_comp
+ extra_requirements = "blueprint required: [initial(I.name)]"
+
+/datum/centcomm_order/department/science/design/ExtraChecks(var/obj/item/weapon/disk/design_disk/DD)
+ if (!istype(DD))
+ return 0
+ if (istype(DD.blueprint, required_comp))
+ return 1
+ return 0
+
+//Protolathe orders
+/datum/centcomm_order/department/science/nuclear_gun/New()
+ ..()
+ name = "CentComm's ERT"
+ requested = list(
+ /obj/item/weapon/gun/energy/gun/nuclear = rand(1,5)
+ )
+ worth = 750*requested[requested[1]]
+
+/datum/centcomm_order/department/science/plasmacutter/New()
+ ..()
+ requested = list(
+ /obj/item/weapon/pickaxe/plasmacutter/accelerator = rand(1,5)
+ )
+ worth = 500*requested[requested[1]]
+
+/datum/centcomm_order/department/science/lasercannon/New()
+ ..()
+ requested = list(
+ /obj/item/weapon/gun/energy/laser/cannon = rand(1,5)
+ )
+ worth = 500*requested[requested[1]]
+
+/datum/centcomm_order/department/science/assaultrifle/New()
+ ..()
+ requested = list(
+ /obj/item/weapon/gun/projectile/automatic/xcom = rand(1,5)
+ )
+ worth = 500*requested[requested[1]]
+
+//Circuit Printer orders
+/datum/centcomm_order/department/science/long_range_ai_upload/New()
+ ..()
+ requested = list(
+ /obj/item/weapon/circuitboard/aiupload/longrange = 1
+ )
+ worth = 500
+
+/datum/centcomm_order/department/science/supermatter_board/New()
+ ..()
+ requested = list(
+ /obj/item/weapon/circuitboard/supermatter = 1
+ )
+ worth = 500
+
+/datum/centcomm_order/department/science/telestation/New()
+ ..()
+ requested = list(
+ /obj/item/weapon/circuitboard/telestation = 1
+ )
+ worth = 500
+
+/datum/centcomm_order/department/science/rust_core/New()
+ ..()
+ requested = list(
+ /obj/item/weapon/circuitboard/rust_core = 1
+ )
+ worth = 500
+
+
+//----------------------------------------------Robotics----------------------------------------------------
+
+//So that means we either let cargo pilot the mechas and trust that they're not gonna steal them
+//Or have the roboticist pilot them all the way to the supply shuttle
+//We should find some other way to displace mechas later
+
+/datum/centcomm_order/department/science/phazon/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Research Director's Desk",
+ "Robotics",
+ )
+ must_be_in_crate = 0
+ requested = list(
+ /obj/mecha/combat/phazon = 1
+ )
+ worth = 1200
+
+/datum/centcomm_order/department/science/phazon/ExtraChecks(var/obj/mecha/M)
+ if (!istype(M))
+ return 0
+ M.wreckage = null
+ return 1
+
+/datum/centcomm_order/department/science/durand/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Research Director's Desk",
+ "Robotics",
+ )
+ must_be_in_crate = 0
+ requested = list(
+ /obj/mecha/combat/durand = 1
+ )
+ worth = 900
+
+/datum/centcomm_order/department/science/durand/ExtraChecks(var/obj/mecha/M)
+ if (!istype(M))
+ return 0
+ M.wreckage = null
+ return 1
+
+/datum/centcomm_order/department/science/gygax/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Research Director's Desk",
+ "Robotics",
+ )
+ must_be_in_crate = 0
+ requested = list(
+ /obj/mecha/combat/gygax = 1
+ )
+ worth = 700
+
+/datum/centcomm_order/department/science/gygax/ExtraChecks(var/obj/mecha/M)
+ if (!istype(M))
+ return 0
+ M.wreckage = null
+ return 1
+
+/datum/centcomm_order/department/science/odysseus/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Research Director's Desk",
+ "Robotics",
+ )
+ must_be_in_crate = 0
+ requested = list(
+ /obj/mecha/medical/odysseus = 1
+ )
+ worth = 600
+
+/datum/centcomm_order/department/science/odysseus/ExtraChecks(var/obj/mecha/M)
+ if (!istype(M))
+ return 0
+ M.wreckage = null
+ return 1
+
+/datum/centcomm_order/department/science/ripley/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Research Director's Desk",
+ "Robotics",
+ )
+ must_be_in_crate = 0
+ requested = list(
+ /obj/mecha/working/ripley = 1
+ )
+ worth = 500
+
+/datum/centcomm_order/department/science/ripley/ExtraChecks(var/obj/mecha/M)
+ if (!istype(M))
+ return 0
+ M.wreckage = null
+ return 1
+
+/datum/centcomm_order/department/science/clarke/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Research Director's Desk",
+ "Robotics",
+ )
+ must_be_in_crate = 0
+ requested = list(
+ /obj/mecha/working/clarke = 1
+ )
+ worth = 500
+
+/datum/centcomm_order/department/science/clarke/ExtraChecks(var/obj/mecha/M)
+ if (!istype(M))
+ return 0
+ M.wreckage = null
+ return 1
+
+/datum/centcomm_order/department/science/robot/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Research Director's Desk",
+ "Robotics",
+ )
+ must_be_in_crate = 0
+ requested = list(
+ /obj/item/robot_parts/robot_suit = 1
+ )
+ name_override = list(
+ /obj/item/robot_parts/robot_suit = "Assembled Robot Chassis"
+ )
+ extra_requirements = "A robot endoskeleton with arms, legs, head and torso assembled."
+ worth = 500
+
+/datum/centcomm_order/department/science/robot/ExtraChecks(var/obj/item/robot_parts/robot_suit/RS)
+ if (!istype(RS))
+ return 0
+ if (RS.l_arm && RS.r_arm && RS.l_leg && RS.r_leg && RS.chest && RS.head)
+ return 1
+ return 0
+
+//-------------------------------------------Plasma Research------------------------------------------------
+
+//what, you mean there's a reason for non-antags to make bombs now? and send them to cargo? oh boy this will be fun.
+
+/datum/centcomm_order/department/science/bomb
+ name = "CentComm Armory"
+ extra_requirements = "Epicenter Radius has to be X or more."
+ var/required_dev = 0
+
+/datum/centcomm_order/department/science/bomb/New()
+ ..()
+ requested = list(
+ /obj/item/device/transfer_valve = 1
+ )
+ name_override = list(
+ /obj/item/device/transfer_valve = "TTV Explosive"
+ )
+ required_dev = rand(2,5)
+ worth = required_dev * 500 - 500
+ extra_requirements = "Epicenter Radius has to be [required_dev] or more."
+
+/datum/centcomm_order/department/science/bomb/ExtraChecks(var/obj/item/device/transfer_valve/TTV)
+ if (!istype(TTV))
+ return 0
+ if (TTV.simulate_merge() < required_dev)
+ return 0
+ return 1
+
+//----------------------------------------------Xenobiology----------------------------------------------------
+
+//High-tier slime cores
+/datum/centcomm_order/department/science/pyrite/New()
+ ..()
+ must_be_in_crate = 0
+ requested = list(
+ /obj/item/slime_extract/pyrite = rand(1,3)
+ )
+ worth = 600*requested[requested[1]]
+
+/datum/centcomm_order/department/science/cerulean/New()
+ ..()
+ must_be_in_crate = 0
+ requested = list(
+ /obj/item/slime_extract/cerulean = rand(1,3)
+ )
+ worth = 600*requested[requested[1]]
+
+/datum/centcomm_order/department/science/sepia/New()
+ ..()
+ must_be_in_crate = 0
+ requested = list(
+ /obj/item/slime_extract/sepia = rand(1,3)
+ )
+ worth = 600*requested[requested[1]]
+
+/datum/centcomm_order/department/science/bluespace/New()
+ ..()
+ must_be_in_crate = 0
+ requested = list(
+ /obj/item/slime_extract/bluespace = rand(1,3)
+ )
+ worth = 600*requested[requested[1]]
+
+/datum/centcomm_order/department/science/adamantine/New()
+ ..()
+ must_be_in_crate = 0
+ requested = list(
+ /obj/item/slime_extract/adamantine = rand(1,3)
+ )
+ worth = 600*requested[requested[1]]
+
+/datum/centcomm_order/department/science/oil/New()
+ ..()
+ must_be_in_crate = 0
+ requested = list(
+ /obj/item/slime_extract/oil = rand(1,3)
+ )
+ worth = 600*requested[requested[1]]
+
+/datum/centcomm_order/department/science/black/New()
+ ..()
+ must_be_in_crate = 0
+ requested = list(
+ /obj/item/slime_extract/black = rand(1,3)
+ )
+ worth = 600*requested[requested[1]]
+
+/datum/centcomm_order/department/science/lightpink/New()
+ ..()
+ must_be_in_crate = 0
+ requested = list(
+ /obj/item/slime_extract/lightpink = rand(1,3)
+ )
+ worth = 600*requested[requested[1]]
+
+
+//----------------------------------------------Xenoarchaeology----------------------------------------------------
+
+//Contained Large Artifacts
+/datum/centcomm_order/department/science/artifact/New()
+ ..()
+ name = "Nanotrasen's Secure Containment Precinct"
+ must_be_in_crate = 0
+ requested = list(
+ /obj/structure/anomaly_container = 1
+ )
+ name_override = list(
+ /obj/structure/anomaly_container = "Contained Large Anomaly"
+ )
+ worth = 1500
+ extra_requirements = "Must be shipped in an Anomaly Container, stamped with its Analysis Report, and after having been activated at least once."
+
+/datum/centcomm_order/department/science/artifact/ExtraChecks(var/obj/structure/anomaly_container/AC)
+ if (!istype(AC))
+ return 0
+ if (istype(AC.contained) && istype(AC.report))
+ var/obj/machinery/artifact/contained = AC.contained
+ var/obj/item/weapon/paper/anomaly/report = AC.report
+ if ((report.artifact == contained) && contained.primary_effect?.triggered)
+ return 1
+ return 0
+
+//Full Supermatter. yes, the round-ending one.
+/datum/centcomm_order/department/science/supermatter
+ hidden = TRUE
+
+/datum/centcomm_order/department/science/supermatter/New()
+ ..()
+ name = "Nanotrasen"
+ must_be_in_crate = 0
+ requested = list(
+ /obj/machinery/power/supermatter = 1
+ )
+ worth = 5000
+ extra_requirements = "A single of those can produce enough shards to power countless stations. Though extremely rare, Nanotrasen would be most grateful if you found one."
+
+//Large Crystals
+/datum/centcomm_order/department/science/crystal/New()
+ ..()
+ name = "CentComm Beautification Department"
+ must_be_in_crate = 0
+ requested = list(
+ /obj/structure/crystal = 1
+ )
+ worth = 300
+
+//Assembled Alien Skeleton
+/datum/centcomm_order/department/science/skeleton/New()
+ ..()
+ must_be_in_crate = 0
+ requested = list(
+ /obj/structure/skeleton = 1
+ )
+ name_override = list(
+ /obj/structure/skeleton = "Complete Alien Skeleton"
+ )
+ worth = 900
+ extra_requirements = "The alien skeleton display needs to feature all its bones."
+
+/datum/centcomm_order/department/science/skeleton/ExtraChecks(var/obj/structure/skeleton/S)
+ if (!istype(S))
+ return 0
+ if (S.bstate)
+ return 1
+ return 0
diff --git a/code/game/centcomm_orders/orders_service.dm b/code/game/centcomm_orders/orders_service.dm
new file mode 100644
index 00000000000..a9cfa8e01a4
--- /dev/null
+++ b/code/game/centcomm_orders/orders_service.dm
@@ -0,0 +1,291 @@
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// //
+// SERVICE ORDERS //
+// //
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//8 orders
+
+//-------------------------------------------------Chef----------------------------------------------------
+
+/datum/centcomm_order/department/civilian
+ acct_by_string = "Civilian"
+
+/datum/centcomm_order/per_unit/department/civilian
+ name = "Nanotrasen Farmers United"
+ acct_by_string = "Civilian"
+
+/datum/centcomm_order/department/civilian/food
+ var/sauce = 0//I SAID I WANTED KETCHUP
+ request_consoles_to_notify = list(
+ "Kitchen",
+ "Hydroponics",
+ )
+
+/datum/centcomm_order/department/civilian/food/New()
+ ..()
+ var/chosen_food = rand(1,7)
+ switch(chosen_food)
+ if (1)
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/snacks/pie = rand(3,12)
+ )
+ worth = 30*requested[requested[1]]
+ name = "Clown Federation" //honk
+ //no sauce for those, we know they're not gonna eat them
+ if (2)
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/snacks/sweetsundaeramen = rand(1,3)
+ )
+ worth = 200*requested[requested[1]]
+ sauce = 1
+ if (3)
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/snacks/superbiteburger = rand(1,3)
+ )
+ worth = 300*requested[requested[1]]
+ sauce = 2
+ if (4)
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/turkey = rand(1,2)
+ )
+ worth = 400*requested[requested[1]]
+ sauce = 2
+ if (5)
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/snacks/bleachkipper = rand(2,5)
+ )
+ worth = 300*requested[requested[1]]
+ if (6)
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/snacks/potentham = rand(1,2)
+ )
+ worth = 1000*requested[requested[1]]
+ if (7)
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/snacks/sundayroast = rand(1,2)
+ )
+ worth = 700*requested[requested[1]]
+ sauce = 2
+ if (sauce && prob(60))
+ worth += 100
+ switch (sauce)
+ if (1)//sweet
+ sauce = pick(
+ /datum/reagent/sugar,
+ /datum/reagent/caramel,
+ /datum/reagent/honey,
+ /datum/reagent/honey/royal_jelly,
+ /datum/reagent/cinnamon,
+ /datum/reagent/coco)
+ else//salty
+ sauce = pick(
+ /datum/reagent/mayo,
+ /datum/reagent/ketchup,
+ /datum/reagent/mustard,
+ /datum/reagent/capsaicin,
+ /datum/reagent/soysauce,
+ /datum/reagent/vinegar)
+ var/datum/reagent/R = sauce
+ extra_requirements = "With some [initial(R.name)] as well. Don't forget the sauce or the dish won't be accepted."
+
+
+/datum/centcomm_order/department/civilian/food/ExtraChecks(var/obj/item/weapon/reagent_containers/food/snacks/F)
+ if (!istype(F))
+ return 0
+ if (!sauce)
+ return 1
+ if (F.reagents?.has_reagent_type(sauce, amount = -1, strict = 1))
+ return 1
+ return 0
+
+
+/datum/centcomm_order/department/civilian/poutinecitadel/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Kitchen",
+ )
+ requested = list(
+ /obj/structure/poutineocean/poutinecitadel = 1
+ )
+ must_be_in_crate = 0
+ worth = 1200
+
+/datum/centcomm_order/department/civilian/popcake/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Kitchen",
+ )
+ requested = list(
+ /obj/structure/popout_cake = 1
+ )
+ must_be_in_crate = 0
+ worth = 1000
+
+//-------------------------------------------------Botany----------------------------------------------------
+
+
+/datum/centcomm_order/department/civilian/novaflower/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Hydroponics",
+ )
+ requested = list(
+ /obj/item/weapon/grown/novaflower = rand(3,8)
+ )
+ worth = 70*requested[requested[1]]
+
+
+/datum/centcomm_order/per_unit/department/civilian/potato/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Hydroponics",
+ )
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/snacks/grown/potato = rand(50,200)
+ )
+ unit_prices=list(
+ /obj/item/weapon/reagent_containers/food/snacks/grown/potato = 5
+ )
+ worth = "5$ per potato"
+
+
+/datum/centcomm_order/per_unit/department/civilian/honeycomb
+ var/flavor
+ request_consoles_to_notify = list(
+ "Hydroponics",
+ )
+
+/datum/centcomm_order/per_unit/department/civilian/honeycomb/New()
+ ..()
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/snacks/honeycomb = rand(4,20)
+ )
+ if (prob(50))
+ unit_prices=list(
+ /obj/item/weapon/reagent_containers/food/snacks/honeycomb = 20
+ )
+ worth = "20$ per honeycomb"
+ flavor = pick(
+ /datum/reagent/drink/applejuice,
+ /datum/reagent/drink/grapejuice,
+ /datum/reagent/drink/banana,
+ )
+ else
+ unit_prices=list(
+ /obj/item/weapon/reagent_containers/food/snacks/honeycomb = 60
+ )
+ worth = "60$ per honeycomb"
+ flavor = pick(
+ /datum/reagent/blood,
+ /datum/reagent/psilocybin,
+ /datum/reagent/hyperzine/cocaine,
+ )//we've got some interesting honey enthusiasts over at Central Command
+
+ var/datum/reagent/F = flavor
+ name_override = list(
+ /obj/item/weapon/reagent_containers/food/snacks/honeycomb = "[initial(F.name)]-flavored Honeycombs"
+ )
+ extra_requirements = "The flavor has to be natural, and not injected into the honeycomb."
+
+/datum/centcomm_order/per_unit/department/civilian/honeycomb/ExtraChecks(var/obj/item/weapon/reagent_containers/food/snacks/honeycomb/H)
+ if (!istype(H))
+ return 0
+ if (!flavor)
+ return 1
+ if (!H.verify())
+ return 0
+ if (H.reagents?.has_reagent_type(flavor, amount = -1, strict = 1))
+ return 1
+ return 0
+
+/datum/centcomm_order/department/civilian/salmon/New()
+ ..()
+ request_consoles_to_notify = list(
+ "Hydroponics",
+ )
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/snacks/salmonmeat = rand(3,8)
+ )
+ worth = 130*requested[requested[1]]
+
+
+//---------------------------------------------------Bar----------------------------------------------------
+
+
+/datum/centcomm_order/department/civilian/custom_drink
+ var/grown
+ request_consoles_to_notify = list(
+ "Bar",
+ )
+
+/datum/centcomm_order/department/civilian/custom_drink/New()
+ ..()
+ grown = pick(
+ /obj/item/weapon/reagent_containers/food/snacks/grown/apple,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/goldapple,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/grapes,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/lime,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/lemon,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/orange,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/banana,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/killertomato,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/pear,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/aloe,
+ )
+ var/obj/item/weapon/reagent_containers/food/snacks/grown/G = grown
+ var/chosen_drink = rand(1,5)
+ switch(chosen_drink)
+ if (1)
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/customizable/wine = rand(1,6)
+ )
+ name_override = list(
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/customizable/wine = "[initial(G.name)] wine"
+ )
+ if (2)
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/customizable/whiskey = rand(1,6)
+ )
+ name_override = list(
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/customizable/whiskey = "[initial(G.name)] whiskey"
+ )
+ if (3)
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/customizable/vermouth = rand(1,6)
+ )
+ name_override = list(
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/customizable/vermouth = "[initial(G.name)] vermouth"
+ )
+ if (4)
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/customizable/vodka = rand(1,6)
+ )
+ name_override = list(
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/customizable/vodka = "[initial(G.name)] vodka"
+ )
+ if (5)
+ requested = list(
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/customizable/ale = rand(1,6)
+ )
+ name_override = list(
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/customizable/ale = "[initial(G.name)] ale"
+ )
+ worth = 100*requested[requested[1]]
+
+/datum/centcomm_order/department/civilian/custom_drink/ExtraChecks(var/obj/item/weapon/reagent_containers/food/drinks/bottle/customizable/C)
+ if (!istype(C))
+ return 0
+ if (!grown)
+ return 1
+ for(var/obj/item/weapon/reagent_containers/food/snacks/S in C.ingredients)
+ var/ok = 0
+ var/ruined = 0
+ if (istype(S, grown))
+ ok = 1
+ else
+ ruined = 1
+ if (ok && !ruined)
+ return 1
+ return 0
diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm
index 422918e3246..028b3b668e2 100644
--- a/code/game/dna/dna_modifier.dm
+++ b/code/game/dna/dna_modifier.dm
@@ -1,10 +1,5 @@
#define DNA_BLOCK_SIZE 3
-// Buffer datatype flags.
-#define DNA2_BUF_UI 1
-#define DNA2_BUF_UE 2
-#define DNA2_BUF_SE 4
-
#define MAX_RADIATION_DURATION 20
#define MAX_RADIATION_INTENSITY 10
diff --git a/code/game/gamemodes/scoreboard.dm b/code/game/gamemodes/scoreboard.dm
index 73e42b4e02a..0f94f9bf089 100644
--- a/code/game/gamemodes/scoreboard.dm
+++ b/code/game/gamemodes/scoreboard.dm
@@ -273,7 +273,8 @@
messpoints = score["mess"] //If there are any messes, let's count them
//--Supply--
- //var/shipping = score["stuffshipped"] * 5 //Does not work currently
+ var/shipping = score["stuffshipped"] * 100 //Centcom Orders fulfilled
+ var/plasmashipped = score["plasmashipped"] * 0.5 //Plasma Sheets shipped
var/mining = score["oremined"] * 1 //Not actually counted at mining, but at processing. One ore smelted is one point
//--Engineering--
@@ -331,7 +332,8 @@
score["crewscore"] -= comdeadpts*/
//Good Things
- //score["crewscore"] += shipping
+ score["crewscore"] += plasmashipped
+ score["crewscore"] += shipping
score["crewscore"] += harvests
score["crewscore"] += mining
score["crewscore"] += eventpoints
@@ -518,6 +520,8 @@
Meals Prepared: [score["meals"]] ([score["meals"] * 5] Points)
Hydroponics Harvests: [score["stuffharvested"]] ([score["stuffharvested"] * 1] Points)
Ultra-Clean Station: [score["messbonus"] ? "Yes" : "No"] ([score["messbonus"] * 10000] Points)
+ Plasma Shipped: [score["plasmashipped"]] ([score["plasmashipped"] * 0.5] Points)
+ Centcom Orders Fulfilled: [score["stuffshipped"]] ([score["stuffshipped"] * 100] Points)
Ore Smelted: [score["oremined"]] ([score["oremined"] * 1] Points)
Whole Station Powered: [score["powerbonus"] ? "Yes" : "No"] ([score["powerbonus"] * 2500] Points)
Isolated Vaccines: [score["disease_vaccine"]] ([score["disease_vaccine_score"]] Points)
@@ -602,9 +606,15 @@
if(score["dmgestdamage"])
dat += "Most Battered Escapee: [score["dmgestname"]], [score["dmgestjob"]]: [score["dmgestdamage"]] damage ([score["dmgestkey"]])
"
if(score["richestcash"])
- dat += "Richest Escapee: [score["richestname"]], [score["richestjob"]]: [score["richestcash"]] space credits ([score["richestkey"]])
"
+ dat += "Richest Escapee: [score["richestname"]], [score["richestjob"]]: $[score["richestcash"]] ([score["richestkey"]])
"
else
dat += "The station wasn't evacuated or there were no survivors!
"
+
+ dat += "Department Leaderboard:
"
+ var/list/dept_leaderboard = get_dept_leaderboard()
+ for (var/i = 1 to dept_leaderboard.len)
+ dat += "#[i] - [dept_leaderboard[i]] ($[dept_leaderboard[dept_leaderboard[i]]])
"
+
dat += {"
FINAL SCORE: [score["crewscore"]]
"}
diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm
index 20f0a09fe23..754ec57b362 100644
--- a/code/game/jobs/jobs.dm
+++ b/code/game/jobs/jobs.dm
@@ -95,6 +95,12 @@ var/list/civilian_positions = list(
"Assistant"
)
+var/list/service_positions = list(
+ "Bartender",
+ "Botanist",
+ "Chef",
+)
+
var/list/cargo_positions = list(
"Head of Personnel",
"Quartermaster",
diff --git a/code/game/machinery/bees_apiary.dm b/code/game/machinery/bees_apiary.dm
index a397654fbb0..3d0fa99533c 100644
--- a/code/game/machinery/bees_apiary.dm
+++ b/code/game/machinery/bees_apiary.dm
@@ -331,6 +331,7 @@ var/list/apiaries_list = list()
H.icon_state = "[species.prefix]honeycomb-base"
H.overlays += I
reagents.trans_to(H,reagents_per_honeycomb)
+ H.authentify()
return 1
diff --git a/code/game/machinery/computer/cargo.dm b/code/game/machinery/computer/cargo.dm
index 3dedcee0c3b..a6d6cb8b717 100644
--- a/code/game/machinery/computer/cargo.dm
+++ b/code/game/machinery/computer/cargo.dm
@@ -269,7 +269,10 @@ For vending packs, see vending_packs.dm*/
var/centcomm_list[0]
for(var/datum/centcomm_order/O in SSsupply_shuttle.centcomm_orders)
- centcomm_list.Add(list(list("id" = O.id, "requested" = O.getRequestsByName(), "fulfilled" = O.getFulfilledByName(), "name" = O.name, "worth" = O.worth, "to" = O.acct_by_string)))
+ var/displayworth = O.worth
+ if (isnum(O.worth))
+ displayworth = "[O.worth]$"
+ centcomm_list.Add(list(list("id" = O.id, "requested" = O.getRequestsByName(), "extra" = O.extra_requirements, "fulfilled" = O.getFulfilledByName(), "name" = O.name, "worth" = displayworth, "to" = O.acct_by_string)))
data["centcomm_orders"] = centcomm_list
var/datum/money_account/account = current_acct["account"]
diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm
index 02b80bb20c5..bb1bc9362c6 100644
--- a/code/game/objects/items/devices/transfer_valve.dm
+++ b/code/game/objects/items/devices/transfer_valve.dm
@@ -162,6 +162,35 @@
temp = tank_one.air_contents.remove_ratio(1)
tank_two.air_contents.merge(temp)
+/obj/item/device/transfer_valve/proc/simulate_merge()
+ //This proc basically reproduces step by step the gas changes that would lead to an explosion
+ //And returns said explosion's Epicenter radius (aka Devastation radius, or "Dev")
+
+ var/datum/gas_mixture/temp_first = new (tank_one.air_contents)
+ var/datum/gas_mixture/temp_second = new (tank_two.air_contents)
+
+ temp_first.merge(temp_second)
+
+ temp_first.react()
+
+ var/pressure = temp_first.return_pressure()/2
+
+ if(pressure <= TANK_FRAGMENT_PRESSURE)
+ return 0
+
+ temp_first.react()
+ temp_first.react()
+ temp_first.react()
+
+ pressure = temp_first.return_pressure()/2
+
+ var/range = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE
+
+ var/dev = round(range*0.25)
+
+ return dev
+
+
/obj/item/device/transfer_valve/proc/split_gases()
if (!valve_open || !tank_one || !tank_two)
return
diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm
index 06f59bd50d9..29dde71f009 100644
--- a/code/game/objects/items/weapons/storage/lockbox.dm
+++ b/code/game/objects/items/weapons/storage/lockbox.dm
@@ -342,6 +342,7 @@
icon_state = "map_diskbox"
item_state = "diskbox"
can_only_hold = list("/obj/item/weapon/disk")
+ cant_hold = list("/obj/item/weapon/disk/harddiskdrive")
fits_max_w_class = 3
w_class = W_CLASS_MEDIUM
max_combined_w_class = 14 //The sum of the w_classes of all the items in this storage item.
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index 0631fc8a07f..30278d2017e 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -247,7 +247,9 @@
return 0
var/pressure = air_contents.return_pressure()
+
if(pressure > TANK_FRAGMENT_PRESSURE)
+
if(!istype(src.loc,/obj/item/device/transfer_valve))
message_admins("Explosive tank rupture! last key to touch the tank was [src.fingerprintslast].")
log_game("Explosive tank rupture! last key to touch the tank was [src.fingerprintslast].")
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 952899f0c97..60ba9c3c446 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -131,6 +131,7 @@ var/list/admin_verbs_fun = list(
/client/proc/set_teleport_pref,
/client/proc/deadchat_singularity,
/client/proc/view_all_rods,
+ /client/proc/add_centcomm_order,
)
var/list/admin_verbs_spawn = list(
/datum/admins/proc/spawn_atom, // Allows us to spawn instances
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 213c1b6550a..36f3ee43142 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -1319,6 +1319,18 @@ client/proc/check_convertables()
error_cache.show_to(src)
+/client/proc/add_centcomm_order()
+ set category = "Fun"
+ set name = "Central Command Request"
+ set desc = "Send a Central Command Request"
+
+ if (!check_rights(R_FUN))
+ return
+
+ var/ordertype = input("Select a Request.","Central Command Request",1) as null|anything in (subtypesof(/datum/centcomm_order) - /datum/centcomm_order/per_unit)
+ if (ordertype)
+ SSsupply_shuttle.add_centcomm_order(new ordertype)
+
/client/proc/emergency_shuttle_panel()
set name = "Emergency Shuttle Panel"
set category = "Debug"
diff --git a/code/modules/events/centcomm_order.dm b/code/modules/events/centcomm_order.dm
deleted file mode 100644
index e1d6460e8d1..00000000000
--- a/code/modules/events/centcomm_order.dm
+++ /dev/null
@@ -1,9 +0,0 @@
-//Refer to game/centcomm_orders.dm
-
-/datum/event/centcomm_order
-
-/datum/event/centcomm_order/can_start()
- return 25
-
-/datum/event/centcomm_order/start()
- create_random_order()
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/bees/bees_items.dm b/code/modules/mob/living/simple_animal/bees/bees_items.dm
index 3adcdd1e230..f322d332f55 100644
--- a/code/modules/mob/living/simple_animal/bees/bees_items.dm
+++ b/code/modules/mob/living/simple_animal/bees/bees_items.dm
@@ -170,6 +170,7 @@
name = "honeycomb"
icon_state = "honeycomb"
desc = "Dripping with sugary sweetness. Grind it to separate the honey."
+ var/list/authentic = list()
/obj/item/weapon/reagent_containers/food/snacks/honeycomb/New()
. = ..()
@@ -200,6 +201,22 @@
icon_state = "chill_honeycomb-base"
overlays += I
+/obj/item/weapon/reagent_containers/food/snacks/honeycomb/proc/authentify()
+ authentic = list()
+ for (var/datum/reagent/R in reagents.reagent_list)
+ authentic[R.id] = R.volume
+
+/obj/item/weapon/reagent_containers/food/snacks/honeycomb/proc/verify()
+ for (var/datum/reagent/R in reagents.reagent_list)
+ if (!(R.id in authentic) || (authentic[R.id] != R.volume))//making sure that no reagent has been added or changed
+ return FALSE
+ else
+ authentic -= R.id
+
+ if (authentic.len <= 0)//are we sure no reagent has been removed shomehow
+ return TRUE
+ return FALSE
+
/obj/item/weapon/book/manual/hydroponics_beekeeping
name = "The Ins and Outs of Apiculture - A Precise Art"
icon_state ="bookHydroponicsBees"
diff --git a/code/modules/organs/organ_objects.dm b/code/modules/organs/organ_objects.dm
index 79a792dd5fc..e13d2534f8f 100644
--- a/code/modules/organs/organ_objects.dm
+++ b/code/modules/organs/organ_objects.dm
@@ -29,6 +29,14 @@
"immunity" = null,
)
+ var/static/list/safe_containers = list(
+ /obj/item/device/mmi,
+ /obj/item/bodybag/cryobag,
+ /obj/structure/closet/crate/freezer,
+ /obj/structure/closet/crate/medical,
+ /obj/structure/closet/crate/secure/medsec,
+ )
+
/obj/item/organ/internal/attack_self(mob/user as mob)
// Convert it to an edible form, yum yum.
@@ -69,11 +77,10 @@
processing_objects -= src
return
- // Don't process if we're in a freezer, an MMI or a stasis bag. //TODO: ambient temperature?
- if(istype(loc,/obj/item/device/mmi) || istype(loc,/obj/item/bodybag/cryobag) || istype(loc,/obj/structure/closet/crate/freezer))
+ //TODO: ambient temperature?
+ if(is_type_in_list(loc,safe_containers))
return
-
if(istype(loc,/obj/item/weapon/reagent_containers/glass/jar))
var/obj/item/weapon/reagent_containers/glass/jar/J = loc
if(J.safe_holder())
diff --git a/code/modules/research/xenoarchaeology/artifact/artifact.dm b/code/modules/research/xenoarchaeology/artifact/artifact.dm
index 8be985fa3bc..7093e7ec793 100644
--- a/code/modules/research/xenoarchaeology/artifact/artifact.dm
+++ b/code/modules/research/xenoarchaeology/artifact/artifact.dm
@@ -140,6 +140,11 @@ var/list/boulders = list()
var/spawn_type = artifact_find.artifact_find_type
if (spawn_type == /obj/machinery/artifact)
new spawn_type(get_turf(src), artifact_find.artifact_id)
+ else if (spawn_type == /obj/machinery/power/supermatter)
+ spawn(rand(10 MINUTES, 30 MINUTES))//The time it takes for Nanotrasen to detect it and make the Science dept an offer they cannot refuse.
+ if (!(locate(/datum/centcomm_order/department/science/supermatter) in SSsupply_shuttle.centcomm_orders))
+ SSsupply_shuttle.add_centcomm_order(new /datum/centcomm_order/department/science/supermatter)
+ new spawn_type(get_turf(src))
else
var/atom/movable/AM = new spawn_type(get_turf(src))
excavated_large_artifacts[artifact_find.artifact_id] = AM
diff --git a/nano/templates/supply_console.tmpl b/nano/templates/supply_console.tmpl
index 6aa4a23a478..8438da0529e 100644
--- a/nano/templates/supply_console.tmpl
+++ b/nano/templates/supply_console.tmpl
@@ -160,9 +160,14 @@ Used In File(s): \code\game\supplyshuttle.dm
#{{:value.id}}
Requested:
{{:value.requested}}
+ {{if value.extra}}
+ {{:value.extra}}
+ {{/if}}
Fulfilled:
- {{:value.fulfilled}}
- for {{:value.name}}: worth {{:value.worth}} to {{:value.to}}
+ {{if value.fulfilled}}
+ {{:value.fulfilled}}
+ {{/if}}
+ for {{:value.name}}: worth {{:value.worth}} to {{:value.to}}
{{empty}}
No active requests.
diff --git a/vgstation13.dme b/vgstation13.dme
index 0deba680659..f1be4edd6a1 100644
--- a/vgstation13.dme
+++ b/vgstation13.dme
@@ -515,7 +515,6 @@
#include "code\game\asteroid.dm"
#include "code\game\atoms.dm"
#include "code\game\atoms_movable.dm"
-#include "code\game\centcomm_orders.dm"
#include "code\game\communications.dm"
#include "code\game\data_huds.dm"
#include "code\game\say.dm"
@@ -528,6 +527,12 @@
#include "code\game\area\areas.dm"
#include "code\game\area\shadows.dm"
#include "code\game\area\Space Station 13 areas.dm"
+#include "code\game\centcomm_orders\centcomm_orders.dm"
+#include "code\game\centcomm_orders\orders_cargo.dm"
+#include "code\game\centcomm_orders\orders_engineering.dm"
+#include "code\game\centcomm_orders\orders_medical.dm"
+#include "code\game\centcomm_orders\orders_science.dm"
+#include "code\game\centcomm_orders\orders_service.dm"
#include "code\game\dna\dna2.dm"
#include "code\game\dna\dna2_domutcheck.dm"
#include "code\game\dna\dna2_helpers.dm"
@@ -1505,7 +1510,6 @@
#include "code\modules\events\bluespaceanomaly.dm"
#include "code\modules\events\brand_intelligence.dm"
#include "code\modules\events\carp_migration.dm"
-#include "code\modules\events\centcomm_order.dm"
#include "code\modules\events\communications_blackout.dm"
#include "code\modules\events\disease_outbreak.dm"
#include "code\modules\events\electrical_storm.dm"