diff --git a/code/__DEFINES/cargo.dm b/code/__DEFINES/cargo.dm
index 0cbd0420f69..22217ab33fc 100644
--- a/code/__DEFINES/cargo.dm
+++ b/code/__DEFINES/cargo.dm
@@ -40,6 +40,17 @@
/// The baseline unit for cargo crates. Adjusting this will change the cost of all in-game shuttles, crate export values, bounty rewards, and all supply pack import values, as they use this as their unit of measurement.
#define CARGO_CRATE_VALUE 200
+#define QM_STAMP_SET list("stamp-qm" = JOB_QUARTERMASTER, "stamp-hop" = JOB_HEAD_OF_PERSONNEL, "stamp-cap" = JOB_CAPTAIN, "stamp-centcom" = JOB_CENTCOM_OFFICIAL)
+#define HOP_STAMP_SET list("stamp-hop" = JOB_HEAD_OF_PERSONNEL, "stamp-cap" = JOB_CAPTAIN, "stamp-centcom" = JOB_CENTCOM_OFFICIAL)
+#define HOS_STAMP_SET list("stamp-hos" = JOB_HEAD_OF_SECURITY, "stamp-cap" = JOB_CAPTAIN, "stamp-centcom" = JOB_CENTCOM_OFFICIAL)
+#define CE_STAMP_SET list("stamp-ce" = JOB_CHIEF_ENGINEER, "stamp-cap" = JOB_CAPTAIN, "stamp-centcom" = JOB_CENTCOM_OFFICIAL)
+#define RD_STAMP_SET list("stamp-rd" = JOB_RESEARCH_DIRECTOR, "stamp-cap" = JOB_CAPTAIN, "stamp-centcom" = JOB_CENTCOM_OFFICIAL)
+#define CMO_STAMP_SET list("stamp-cmo" = JOB_CHIEF_MEDICAL_OFFICER, "stamp-cap" = JOB_CAPTAIN, "stamp-centcom" = JOB_CENTCOM_OFFICIAL)
+#define CAP_STAMP_SET list("stamp-cap" = JOB_CAPTAIN, "stamp-centcom" = JOB_CENTCOM_OFFICIAL)
+#define HONK_STAMP_SET list("stamp-clown" = JOB_CLOWN, "stamp-mime" = JOB_MIME)
+#define NOTARY_STAMP_SET list("stamp-law" = JOB_LAWYER, "stamp-chap" = JOB_CHAPLAIN)
+#define ILLEGAL_STAMP_SET list("stamp-syndicate" = "Syndicate Official", "stamp-centcom" = JOB_CENTCOM_OFFICIAL)
+
GLOBAL_LIST_EMPTY(supplypod_loading_bays)
GLOBAL_LIST_INIT(podstyles, list(\
diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm
index ba66019052d..d5caa01e6b7 100644
--- a/code/controllers/subsystem/shuttle.dm
+++ b/code/controllers/subsystem/shuttle.dm
@@ -95,6 +95,9 @@ SUBSYSTEM_DEF(shuttle)
/// A listing of previously delivered supply packs.
var/list/order_history = list()
+ /// A listing of previously delivered supply packs by order id
+ var/list/order_history_by_id = list()
+
/// A list of job accesses that are able to purchase any shuttles.
var/list/has_purchase_shuttle_access
@@ -634,6 +637,8 @@ SUBSYSTEM_DEF(shuttle)
request_list = SSshuttle.request_list
if (istype(SSshuttle.order_history))
order_history = SSshuttle.order_history
+ if (istype(SSshuttle.order_history_by_id))
+ order_history_by_id = SSshuttle.order_history_by_id
if (istype(SSshuttle.shuttle_loan))
shuttle_loan = SSshuttle.shuttle_loan
diff --git a/code/modules/cargo/exports/manifest.dm b/code/modules/cargo/exports/manifest.dm
index f08dd1745e3..7b709674aa2 100644
--- a/code/modules/cargo/exports/manifest.dm
+++ b/code/modules/cargo/exports/manifest.dm
@@ -1,7 +1,7 @@
// Approved manifest.
-// +80 credits flat.
+// +70 credits flat.
/datum/export/manifest_correct
- cost = CARGO_CRATE_VALUE * 0.4
+ cost = CARGO_CRATE_VALUE * 0.35
k_elasticity = 0
unit_name = "approved manifest"
export_types = list(/obj/item/paper/fluff/jobs/cargo/manifest)
@@ -36,7 +36,6 @@
var/obj/item/paper/fluff/jobs/cargo/manifest/M = O
return ..() + M.order_cost
-
// Erroneously approved manifest.
// Substracts the package cost.
/datum/export/manifest_error
@@ -57,7 +56,6 @@
var/obj/item/paper/fluff/jobs/cargo/manifest/M = O
return -M.order_cost
-
// Erroneously denied manifest.
// Substracts the package cost minus the cost of crate.
/datum/export/manifest_correct_denied
diff --git a/code/modules/cargo/exports/requisition.dm b/code/modules/cargo/exports/requisition.dm
new file mode 100644
index 00000000000..b9519a898c7
--- /dev/null
+++ b/code/modules/cargo/exports/requisition.dm
@@ -0,0 +1,21 @@
+// Approved requisition.
+// +30 credits flat
+/datum/export/requisition
+ cost = CARGO_CRATE_VALUE * 0.15
+ k_elasticity = 0
+ unit_name = "approved requisition"
+ export_types = list(/obj/item/paper/fluff/jobs/cargo/requisition)
+
+/datum/export/requisition/applies_to(obj/item/paper/fluff/jobs/cargo/requisition/paperwork)
+ if(!..() || !istype(paperwork))
+ return FALSE
+
+ var/crate_not_ordered = !SSshuttle.order_history_by_id[paperwork.order_id]
+ // we don't want to give points unless the crate order was approved
+ if(crate_not_ordered)
+ return FALSE
+
+ for(var/stamp_icon in paperwork.authorization_stamps)
+ if(paperwork.is_approved(stamp_icon))
+ return TRUE
+ return FALSE
diff --git a/code/modules/cargo/order.dm b/code/modules/cargo/order.dm
index 70261c1a89b..1967187ea8b 100644
--- a/code/modules/cargo/order.dm
+++ b/code/modules/cargo/order.dm
@@ -1,4 +1,4 @@
-/// The chance for a manifest or crate to be created with errors
+/// The chance for a manifest or crate to be created with errors
#define MANIFEST_ERROR_CHANCE 5
// MANIFEST BITFLAGS
@@ -6,7 +6,7 @@
#define MANIFEST_ERROR_NAME (1 << 0)
/// Determines if contents will be deleted from the manifest but still be present in the crate
#define MANIFEST_ERROR_CONTENTS (1 << 1)
-/// Determines if contents will be deleted from the crate but still be present in the manifest
+/// Determines if contents will be deleted from the crate but still be present in the manifest
#define MANIFEST_ERROR_ITEM (1 << 2)
/obj/item/paper/fluff/jobs/cargo/manifest
@@ -29,11 +29,14 @@
errors |= MANIFEST_ERROR_ITEM
investigate_log("Supply order #[order_id] generated with incorrect contents shipped.", INVESTIGATE_CARGO)
-/obj/item/paper/fluff/jobs/cargo/manifest/proc/is_approved()
- return stamped?.len && !is_denied()
+/obj/item/paper/fluff/jobs/cargo/requisition
+ var/authorization_stamps
+ var/order_id = 0
-/obj/item/paper/fluff/jobs/cargo/manifest/proc/is_denied()
- return stamped && ("stamp-deny" in stamped)
+/obj/item/paper/fluff/jobs/cargo/requisition/Initialize(mapload, id, authorization_stamps)
+ . = ..()
+ src.authorization_stamps = authorization_stamps
+ order_id = id
/datum/supply_order
var/id
@@ -47,6 +50,8 @@
var/datum/supply_pack/pack
var/datum/bank_account/paying_account
var/obj/item/coupon/applied_coupon
+ /// list of stamps that can approve this requisition for bonus credits
+ var/authorization_stamps
/datum/supply_order/New(datum/supply_pack/pack, orderer, orderer_rank, orderer_ckey, reason, paying_account, department_destination, coupon)
id = SSshuttle.order_number++
@@ -60,70 +65,76 @@
src.applied_coupon = coupon
/datum/supply_order/proc/generateRequisition(turf/T)
- var/obj/item/paper/P = new(T)
+ var/obj/item/paper/fluff/jobs/cargo/requisition/requisition = new(T, id, pack.authorization_stamps)
- P.name = "requisition form - #[id] ([pack.name])"
- P.info += "
[station_name()] Supply Requisition
"
- P.info += "
"
- P.info += "Order #[id]
"
- P.info += "Time of Order: [station_time_timestamp()]
"
- P.info += "Item: [pack.name]
"
- P.info += "Access Restrictions: [SSid_access.get_access_desc(pack.access)]
"
- P.info += "Requested by: [orderer]
"
+ var/jobs_that_can_approve = list()
+ for(var/stamp in pack.authorization_stamps)
+ jobs_that_can_approve += pack.authorization_stamps[stamp]
+ jobs_that_can_approve = english_list(jobs_that_can_approve, and_text = " or ")
+
+ requisition.name = "requisition form - #[id] ([pack.name])"
+ requisition.info += "[station_name()] Supply Requisition
"
+ requisition.info += "
"
+ requisition.info += "Order #[id]
"
+ requisition.info += "Time of Order: [station_time_timestamp()]
"
+ requisition.info += "Item: [pack.name]
"
+ requisition.info += "Access Restrictions: [SSid_access.get_access_desc(pack.access)]
"
+ requisition.info += "Authorization Required: [jobs_that_can_approve]
"
+ requisition.info += "Requested by: [orderer]
"
if(paying_account)
- P.info += "Paid by: [paying_account.account_holder]
"
- P.info += "Rank: [orderer_rank]
"
- P.info += "Comment: [reason]
"
+ requisition.info += "Paid by: [paying_account.account_holder]
"
+ requisition.info += "Rank: [orderer_rank]
"
+ requisition.info += "Comment: [reason]
"
- P.update_appearance()
- return P
+ requisition.update_appearance()
+ return requisition
/datum/supply_order/proc/generateManifest(obj/container, owner, packname, cost) //generates-the-manifests.
- var/obj/item/paper/fluff/jobs/cargo/manifest/P = new(null, id, cost)
+ var/obj/item/paper/fluff/jobs/cargo/manifest/manifest = new(null, id, cost)
- var/station_name = (P.errors & MANIFEST_ERROR_NAME) ? new_station_name() : station_name()
+ var/station_name = (manifest.errors & MANIFEST_ERROR_NAME) ? new_station_name() : station_name()
- P.name = "shipping manifest - [packname?"#[id] ([pack.name])":"(Grouped Item Crate)"]"
- P.info += "[command_name()] Shipping Manifest
"
- P.info += "
"
+ manifest.name = "shipping manifest - [packname?"#[id] ([pack.name])":"(Grouped Item Crate)"]"
+ manifest.info += "[command_name()] Shipping Manifest
"
+ manifest.info += "
"
if(owner && !(owner == "Cargo"))
- P.info += "Direct purchase from [owner]
"
- P.name += " - Purchased by [owner]"
- P.info += "Order[packname?"":"s"]: [id]
"
- P.info += "Destination: [station_name]
"
+ manifest.info += "Direct purchase from [owner]
"
+ manifest.name += " - Purchased by [owner]"
+ manifest.info += "Order[packname?"":"s"]: [id]
"
+ manifest.info += "Destination: [station_name]
"
if(packname)
- P.info += "Item: [packname]
"
- P.info += "Contents:
"
- P.info += ""
- for(var/atom/movable/AM in container.contents - P)
- if((P.errors & MANIFEST_ERROR_CONTENTS))
+ manifest.info += "Item: [packname]
"
+ manifest.info += "Contents:
"
+ manifest.info += ""
+ for(var/atom/movable/AM in container.contents - manifest)
+ if((manifest.errors & MANIFEST_ERROR_CONTENTS))
if(prob(50))
- P.info += "- [AM.name]
"
+ manifest.info += "- [AM.name]
"
else
continue
- P.info += "- [AM.name]
"
- P.info += "
"
- P.info += "Stamp below to confirm receipt of goods:
"
+ manifest.info += "- [AM.name]
"
+ manifest.info += "
"
+ manifest.info += "Stamp below to confirm receipt of goods:
"
- if(P.errors & MANIFEST_ERROR_ITEM)
+ if(manifest.errors & MANIFEST_ERROR_ITEM)
if(istype(container, /obj/structure/closet/crate/secure) || istype(container, /obj/structure/closet/crate/large))
- P.errors &= ~MANIFEST_ERROR_ITEM
+ manifest.errors &= ~MANIFEST_ERROR_ITEM
else
var/lost = max(round(container.contents.len / 10), 1)
while(--lost >= 0)
qdel(pick(container.contents))
- P.update_appearance()
- P.forceMove(container)
+ manifest.update_appearance()
+ manifest.forceMove(container)
if(istype(container, /obj/structure/closet/crate))
- var/obj/structure/closet/crate/C = container
- C.manifest = P
- C.update_appearance()
+ var/obj/structure/closet/crate/crate = container
+ crate.manifest = manifest
+ crate.update_appearance()
else
- container.contents += P
+ container.contents += manifest
- return P
+ return manifest
/datum/supply_order/proc/generate(atom/A)
var/account_holder
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index ab3c51db1d1..f5fe17c6e53 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -20,6 +20,8 @@
var/special_pod //If this pack comes shipped in a specific pod when launched from the express console
var/admin_spawned = FALSE
var/goody = FALSE //Goodies can only be purchased by private accounts and can have coupons apply to them. They also come in a lockbox instead of a full crate, so the 700 min doesn't apply
+ /// If the requisition paper is stamped by a stamp in the list it gives bonus points for crate returns
+ var/list/authorization_stamps = QM_STAMP_SET
/datum/supply_pack/New()
id = type
@@ -65,6 +67,7 @@
/datum/supply_pack/emergency
group = "Emergency"
+ authorization_stamps = QM_STAMP_SET
/datum/supply_pack/emergency/vehicle
name = "Biker Gang Kit" //TUNNEL SNAKES OWN THIS TOWN
@@ -248,6 +251,7 @@
/obj/item/grenade/chem_grenade/incendiary)
crate_name = "emergency crate"
crate_type = /obj/structure/closet/crate/internals
+ authorization_stamps = ILLEGAL_STAMP_SET
/datum/supply_pack/emergency/weedcontrol
name = "Weed Control Crate"
@@ -279,6 +283,7 @@
group = "Security"
access = ACCESS_SECURITY
crate_type = /obj/structure/closet/crate/secure/gear
+ authorization_stamps = HOS_STAMP_SET
/datum/supply_pack/security/ammo
name = "Ammo Crate"
@@ -464,6 +469,7 @@
access = ACCESS_ARMORY
access_view = ACCESS_ARMORY
crate_type = /obj/structure/closet/crate/secure/weapon
+ authorization_stamps = HOS_STAMP_SET
/datum/supply_pack/security/armory/bulletarmor
name = "Bulletproof Armor Crate"
@@ -654,6 +660,7 @@
/datum/supply_pack/engineering
group = "Engineering"
crate_type = /obj/structure/closet/crate/engineering
+ authorization_stamps = CE_STAMP_SET
/datum/supply_pack/engineering/shieldgen
name = "Anti-breach Shield Projector Crate"
@@ -886,6 +893,7 @@
group = "Engine Construction"
access_view = ACCESS_ENGINE
crate_type = /obj/structure/closet/crate/engineering
+ authorization_stamps = CE_STAMP_SET
/datum/supply_pack/engine/emitter
name = "Emitter Crate"
@@ -993,6 +1001,7 @@
/datum/supply_pack/materials
group = "Canisters & Materials"
+ authorization_stamps = QM_STAMP_SET
/datum/supply_pack/materials/cardboard50
name = "50 Cardboard Sheets"
@@ -1145,6 +1154,7 @@
group = "Medical"
access_view = ACCESS_MEDICAL
crate_type = /obj/structure/closet/crate/medical
+ authorization_stamps = CMO_STAMP_SET
/datum/supply_pack/medical/bloodpacks
name = "Blood Pack Variety Crate"
@@ -1307,6 +1317,7 @@
group = "Science"
access_view = ACCESS_RESEARCH
crate_type = /obj/structure/closet/crate/science
+ authorization_stamps = RD_STAMP_SET
/datum/supply_pack/science/plasma
name = "Plasma Assembly Crate"
@@ -1483,6 +1494,7 @@
/datum/supply_pack/service
group = "Service"
+ authorization_stamps = QM_STAMP_SET
/datum/supply_pack/service/cargo_supples
name = "Cargo Supplies Crate"
@@ -1503,6 +1515,7 @@
access_view = ACCESS_JANITOR
contains = list(/obj/item/stack/tile/noslip/thirty)
crate_name = "high-traction floor tiles crate"
+ authorization_stamps = HONK_STAMP_SET
/datum/supply_pack/service/janitor
name = "Janitorial Supplies Crate"
@@ -1679,6 +1692,7 @@
/obj/item/bouquet/poppy,
/obj/item/reagent_containers/food/drinks/bottle/champagne)
crate_name = "wedding crate"
+ authorization_stamps = NOTARY_STAMP_SET
/// Box of 7 grey IDs.
/datum/supply_pack/service/greyidbox
@@ -1687,6 +1701,7 @@
cost = CARGO_CRATE_VALUE * 3
contains = list(/obj/item/storage/box/ids)
crate_name = "basic id card crate"
+ authorization_stamps = HOP_STAMP_SET
/// Single silver ID.
/datum/supply_pack/service/silverid
@@ -1695,6 +1710,7 @@
cost = CARGO_CRATE_VALUE * 7
contains = list(/obj/item/card/id/advanced/silver)
crate_name = "silver id card crate"
+ authorization_stamps = HOP_STAMP_SET
/datum/supply_pack/service/emptycrate
name = "Empty Crate"
@@ -1740,6 +1756,7 @@
/datum/supply_pack/organic
group = "Food & Hydroponics"
crate_type = /obj/structure/closet/crate/freezer
+ authorization_stamps = QM_STAMP_SET
/datum/supply_pack/organic/hydroponics
access_view = ACCESS_HYDROPONICS
@@ -1852,6 +1869,7 @@
access = ACCESS_THEATRE
access_view = ACCESS_THEATRE
crate_type = /obj/structure/closet/crate/secure
+ authorization_stamps = HONK_STAMP_SET
/datum/supply_pack/organic/hydroponics
name = "Hydroponics Crate"
@@ -2038,6 +2056,7 @@
/datum/supply_pack/critter
group = "Livestock"
crate_type = /obj/structure/closet/crate/critter
+ authorization_stamps = NOTARY_STAMP_SET
/datum/supply_pack/critter/parrot
name = "Bird Crate"
@@ -2195,6 +2214,7 @@
/datum/supply_pack/costumes_toys
group = "Costumes & Toys"
+ authorization_stamps = HONK_STAMP_SET
/datum/supply_pack/costumes_toys/randomised
name = "Collectable Hats Crate"
@@ -2251,6 +2271,7 @@
/obj/item/clothing/neck/necklace/dope,
/obj/item/vending_refill/donksoft)
crate_name = "crate"
+ authorization_stamps = ILLEGAL_STAMP_SET
/datum/supply_pack/costumes_toys/foamforce
name = "Foam Force Crate"
@@ -2309,6 +2330,7 @@
/obj/item/lipstick/random)
crate_name = "formalwear crate"
crate_type = /obj/structure/closet/crate/wooden
+ authorization_stamps = NOTARY_STAMP_SET
/datum/supply_pack/costumes_toys/clownpin
name = "Hilarious Firing Pin Crate"
@@ -2473,6 +2495,7 @@
/datum/supply_pack/misc
group = "Miscellaneous Supplies"
+ authorization_stamps = QM_STAMP_SET
/datum/supply_pack/misc/artsupply
name = "Art Supplies"
@@ -2488,6 +2511,7 @@
/obj/item/toy/crayon/rainbow)
crate_name = "art supply crate"
crate_type = /obj/structure/closet/crate/wooden
+ authorization_stamps = HONK_STAMP_SET
/datum/supply_pack/misc
group = "Miscellaneous Supplies"
@@ -2558,6 +2582,7 @@
contains = list(/obj/vehicle/ridden/bicycle)
crate_name = "bicycle crate"
crate_type = /obj/structure/closet/crate/large
+ authorization_stamps = ILLEGAL_STAMP_SET
/datum/supply_pack/misc/bigband
name = "Big Band Instrument Collection"
@@ -2574,6 +2599,7 @@
/obj/item/instrument/harmonica,
/obj/structure/musician/piano/unanchored)
crate_type = /obj/structure/closet/crate/wooden
+ authorization_stamps = HONK_STAMP_SET
/datum/supply_pack/misc/book_crate
name = "Book Crate"
@@ -2588,6 +2614,7 @@
/obj/item/book/random,
/obj/item/book/random)
crate_type = /obj/structure/closet/crate/wooden
+ authorization_stamps = NOTARY_STAMP_SET
/datum/supply_pack/misc/commandkeys
name = "Command Encryption Key Crate"
@@ -2649,6 +2676,7 @@
contains = list(/obj/item/storage/box/fountainpens)
crate_type = /obj/structure/closet/crate/wooden
crate_name = "calligraphy crate"
+ authorization_stamps = CAP_STAMP_SET
/datum/supply_pack/misc/wrapping_paper
name = "Festive Wrapping Paper Crate"
@@ -2658,7 +2686,6 @@
crate_type = /obj/structure/closet/crate/wooden
crate_name = "festive wrapping paper crate"
-
/datum/supply_pack/misc/funeral
name = "Funeral Supply crate"
desc = "At the end of the day, someone's gonna want someone dead. Give them a proper send-off with these funeral supplies! Contains a coffin with burial garmets and flowers."
@@ -2669,6 +2696,7 @@
/obj/item/food/grown/poppy/geranium)
crate_name = "coffin"
crate_type = /obj/structure/closet/crate/coffin
+ authorization_stamps = NOTARY_STAMP_SET
/datum/supply_pack/misc/empty
name = "Empty Supplypod"
@@ -2694,6 +2722,7 @@
/obj/item/clothing/under/misc/burial,
)
crate_name = "religious supplies crate"
+ authorization_stamps = NOTARY_STAMP_SET
/datum/supply_pack/misc/toner
name = "Toner Crate"
@@ -2740,6 +2769,7 @@
/obj/item/stock_parts/subspace/ansible
)
crate_name = "crate"
+ authorization_stamps = ILLEGAL_STAMP_SET
///Special supply crate that generates random syndicate gear up to a determined TC value
/datum/supply_pack/misc/syndicate
@@ -2749,6 +2779,7 @@
contains = list()
crate_name = "syndicate gear crate"
crate_type = /obj/structure/closet/crate
+ authorization_stamps = ILLEGAL_STAMP_SET
var/crate_value = 30 ///Total TC worth of contained uplink items
var/uplink_flag = UPLINK_TRAITORS
@@ -2775,6 +2806,7 @@
/datum/supply_pack/vending
group = "Vending Restocks"
+ authorization_stamps = QM_STAMP_SET
/datum/supply_pack/vending/bartending
name = "Booze-o-mat and Coffee Supply Crate"
@@ -2970,6 +3002,7 @@
/datum/supply_pack/exploration
special = TRUE
group = "Outsourced"
+ authorization_stamps = QM_STAMP_SET
/datum/supply_pack/exploration/scrapyard
name = "Scrapyard Crate"
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 3faee2819e9..e3839c8d74f 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -63,7 +63,6 @@
/obj/item/paper/Destroy()
stamps = null
- stamped = null
form_fields = null
stamped = null
. = ..()
@@ -398,6 +397,29 @@
to_chat(usr, pick("You try to stamp but you miss!", "There is no where else you can stamp!"))
return FALSE
+/**
+ * is_approved
+ *
+ * To determine if a paper has the correct stamp. If no department stamp is specified then the
+ * regular granted stamp (/obj/item/stamp) is checked
+ *
+ * Arguments:
+ * * department (optional) - The department stamp we are checking for
+ */
+/obj/item/paper/proc/is_approved(department_stamp)
+ if(department_stamp)
+ return stamped && (department_stamp in stamped)
+ else
+ return stamped && ("stamp-ok" in stamped)
+
+/**
+ * is_denied
+ *
+ * To determine if a paper has the DENIED stamp
+ */
+/obj/item/paper/proc/is_denied()
+ return stamped && ("stamp-deny" in stamped)
+
/obj/item/paper/ui_act(action, params, datum/tgui/ui)
. = ..()
if(.)
diff --git a/code/modules/paperwork/stamps.dm b/code/modules/paperwork/stamps.dm
index 2d61ca83c19..d98d49fc47b 100644
--- a/code/modules/paperwork/stamps.dm
+++ b/code/modules/paperwork/stamps.dm
@@ -17,6 +17,10 @@
user.visible_message(span_suicide("[user] stamps 'VOID' on [user.p_their()] forehead, then promptly falls over, dead."))
return (OXYLOSS)
+/obj/item/stamp/denied
+ name = "\improper DENIED rubber stamp"
+ icon_state = "stamp-deny"
+
/obj/item/stamp/qm
name = "quartermaster's rubber stamp"
icon_state = "stamp-qm"
@@ -57,11 +61,6 @@
icon_state = "stamp-cmo"
dye_color = DYE_CMO
-/obj/item/stamp/denied
- name = "\improper DENIED rubber stamp"
- icon_state = "stamp-deny"
- dye_color = DYE_REDCOAT
-
/obj/item/stamp/clown
name = "clown's rubber stamp"
icon_state = "stamp-clown"
diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm
index 926cf0798c3..88890ea6354 100644
--- a/code/modules/shuttle/supply.dm
+++ b/code/modules/shuttle/supply.dm
@@ -161,6 +161,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
value += spawning_order.pack.get_cost()
SSshuttle.shopping_list -= spawning_order
SSshuttle.order_history += spawning_order
+ SSshuttle.order_history_by_id[spawning_order.id] = TRUE
QDEL_NULL(spawning_order.applied_coupon)
if(!spawning_order.pack.goody) //we handle goody crates below
diff --git a/strings/tips.txt b/strings/tips.txt
index bf057da3e9c..7b128eecc4e 100644
--- a/strings/tips.txt
+++ b/strings/tips.txt
@@ -162,6 +162,7 @@ As a Cargo Technician, you can hack MULEbots to make them faster, run over peopl
As a Cargo Technician, you can order contraband items from the supply shuttle console by de-constructing it and using a multitool on the circuit board, the re-assembling it.
As a Cargo Technician, you can earn more cargo points by shipping back crates from maintenance, liquid containers, plasma sheets, rare seeds from hydroponics, and more!
As the Quartermaster, be sure to check the manifests on crates you receive to make sure all the info is correct. If there's a mistake, stamp the manifest DENIED and send it back in a crate with the items untouched for a refund!
+As the Quartermaster, be sure to get requisition forms stamped by someone with the required authorization and ship it back to gain bonus credits.
As the Quartermaster, you can construct an express supply console that instantly delivers crates by drop pod. The impact will cause a small explosion as well.
As a Shaft Miner, the northern side of Lavaland has a lot more rare minerals than on the south.
As a Shaft Miner, every monster on Lavaland has a pattern you can exploit to minimize damage from the encounters.
diff --git a/tgstation.dme b/tgstation.dme
index 25a3fddbb5c..1f3203f065b 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2455,6 +2455,7 @@
#include "code\modules\cargo\exports\materials.dm"
#include "code\modules\cargo\exports\organs.dm"
#include "code\modules\cargo\exports\parts.dm"
+#include "code\modules\cargo\exports\requisition.dm"
#include "code\modules\cargo\exports\seeds.dm"
#include "code\modules\cargo\exports\sheets.dm"
#include "code\modules\cargo\exports\tools.dm"