diff --git a/code/game/objects/items/mail.dm b/code/game/objects/items/mail.dm
index f4663ff4fd1..63e972468f6 100644
--- a/code/game/objects/items/mail.dm
+++ b/code/game/objects/items/mail.dm
@@ -14,8 +14,8 @@
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
/// Destination tagging for the mail sorter.
var/sort_tag = 0
- /// Who this mail is for and who can open it.
- var/datum/weakref/recipient
+ /// Weak reference to who this mail is for and who can open it.
+ var/datum/weakref/recipient_ref
/// How many goodies this mail contains.
var/goodie_count = 1
/// Goodies which can be given to anyone. The base weight for cash is 56. For there to be a 50/50 chance of getting a department item, they need 56 weight as well.
@@ -109,9 +109,13 @@
playsound(loc, 'sound/machines/twobeep_high.ogg', 100, TRUE)
/obj/item/mail/attack_self(mob/user)
- if(recipient && user != recipient)
- to_chat(user, span_notice("You can't open somebody else's mail! That's illegal!"))
- return
+ if(recipient_ref)
+ var/datum/mind/recipient = recipient_ref.resolve()
+ // If the recipient's mind has gone, then anyone can open their mail
+ // whether a mind can actually be qdel'd is an exercise for the reader
+ if(recipient && recipient != user?.mind)
+ to_chat(user, span_notice("You can't open somebody else's mail! That's illegal!"))
+ return
to_chat(user, span_notice("You start to unwrap the package..."))
if(!do_after(user, 1.5 SECONDS, target = user))
@@ -125,6 +129,7 @@
/obj/item/mail/examine_more(mob/user)
. = ..()
var/list/msg = list(span_notice("You notice the postmarking on the front of the mail..."))
+ var/datum/mind/recipient = recipient_ref.resolve()
if(recipient)
msg += "\t[span_info("Certified NT mail for [recipient].")]"
else
@@ -132,13 +137,15 @@
msg += "\t[span_info("Distribute by hand or via destination tagger using the certified NT disposal system.")]"
return msg
-/// Accepts a mob to initialize goodies for a piece of mail.
-/obj/item/mail/proc/initialize_for_recipient(mob/new_recipient)
- recipient = new_recipient
- name = "[initial(name)] for [new_recipient.real_name] ([new_recipient.job])"
+/// Accepts a mind to initialize goodies for a piece of mail.
+/obj/item/mail/proc/initialize_for_recipient(datum/mind/recipient)
+ name = "[initial(name)] for [recipient.name] ([recipient.assigned_role])"
+ recipient_ref = WEAKREF(recipient)
+
+ var/mob/living/body = recipient.current
var/list/goodies = generic_goodies
- var/datum/job/this_job = SSjob.name_occupations[new_recipient.job]
+ var/datum/job/this_job = SSjob.name_occupations[recipient.assigned_role]
if(this_job)
if(this_job.paycheck_department && department_colors[this_job.paycheck_department])
color = department_colors[this_job.paycheck_department]
@@ -152,14 +159,8 @@
for(var/iterator = 0, iterator < goodie_count, iterator++)
var/target_good = pickweight(goodies)
- if(ispath(target_good, /datum/reagent))
- var/obj/item/reagent_containers/target_container = new /obj/item/reagent_containers/glass/bottle(src)
- target_container.reagents.add_reagent(target_good, target_container.volume)
- target_container.name = "[target_container.reagents.reagent_list[1].name] bottle"
- new_recipient.log_message("[key_name(new_recipient)] received reagent container [target_container.name] in the mail ([target_good])", LOG_GAME)
- else
- var/atom/movable/target_atom = new target_good(src)
- new_recipient.log_message("[key_name(new_recipient)] received [target_atom.name] in the mail ([target_good])", LOG_GAME)
+ var/atom/movable/target_atom = new target_good(src)
+ body.log_message("[key_name(body)] received [target_atom.name] in the mail ([target_good])", LOG_GAME)
return TRUE
@@ -202,11 +203,6 @@
desc = "A certified post crate from CentCom."
icon_state = "mail"
-/// Crate for mail that automatically generates a lot of mail. Usually only normal mail, but on lowpop it may end up just being junk.
-/obj/structure/closet/crate/mail/full
- name = "brimming mail crate"
- desc = "A certified post crate from CentCom. Looks stuffed to the gills."
-
/obj/structure/closet/crate/mail/update_icon_state()
. = ..()
if(opened)
@@ -216,26 +212,51 @@
else
icon_state = "[initial(icon_state)]sealed"
-/obj/structure/closet/crate/mail/full/Initialize()
- . = ..()
+/// Fills this mail crate with N pieces of mail, where N is the lower of the amount var passed, and the maximum capacity of this crate. If N is larger than the number of alive human players, the excess will be junkmail.
+/obj/structure/closet/crate/mail/proc/populate(amount)
+ var/mail_count = min(amount, storage_capacity)
+ // Fills the
var/list/mail_recipients = list()
- for(var/mob/living/carbon/human/alive in GLOB.player_list)
- if(alive.stat != DEAD)
- mail_recipients += alive
- for(var/iterator in 1 to storage_capacity)
+
+ for(var/mob/living/carbon/human/human in GLOB.player_list)
+ if(human.stat == DEAD || !human.mind)
+ continue
+ // Skip wizards, nuke ops, cyborgs; Centcom does not send them mail
+ if(!SSjob.GetJob(human.mind.assigned_role) || (human.mind.assigned_role in GLOB.nonhuman_positions))
+ continue
+
+ mail_recipients += human.mind
+
+ for(var/i in 1 to mail_count)
var/obj/item/mail/new_mail
if(prob(FULL_CRATE_LETTER_ODDS))
new_mail = new /obj/item/mail(src)
else
new_mail = new /obj/item/mail/envelope(src)
- var/mob/living/carbon/human/mail_to
- mail_to = pick(mail_recipients)
- if(mail_to)
- new_mail.initialize_for_recipient(mail_to)
- mail_recipients -= mail_to //Once picked, the mail crate will need a new recipient.
+
+ var/datum/mind/recipient = pick_n_take(mail_recipients)
+ if(recipient)
+ new_mail.initialize_for_recipient(recipient)
else
new_mail.junk_mail()
+ update_icon()
+
+/// Crate for mail that automatically depletes the economy subsystem's pending mail counter.
+/obj/structure/closet/crate/mail/economy/Initialize()
+ . = ..()
+ populate(SSeconomy.mail_waiting)
+ SSeconomy.mail_waiting = 0
+
+/// Crate for mail that automatically generates a lot of mail. Usually only normal mail, but on lowpop it may end up just being junk.
+/obj/structure/closet/crate/mail/full
+ name = "brimming mail crate"
+ desc = "A certified post crate from CentCom. Looks stuffed to the gills."
+
+/obj/structure/closet/crate/mail/full/Initialize()
+ . = ..()
+ populate(INFINITY)
+
/// Mailbag.
/obj/item/storage/bag/mail
diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm
index 8f82f57a338..fd06f8c7ccc 100644
--- a/code/modules/jobs/job_types/bartender.dm
+++ b/code/modules/jobs/job_types/bartender.dm
@@ -20,7 +20,7 @@
mail_goodies = list(
/obj/item/storage/box/rubbershot = 30,
- /datum/reagent/consumable/clownstears = 10,
+ /obj/item/reagent_containers/glass/bottle/clownstears = 10,
/obj/item/stack/sheet/mineral/plasma = 10,
/obj/item/stack/sheet/mineral/uranium = 10,
)
diff --git a/code/modules/jobs/job_types/botanist.dm b/code/modules/jobs/job_types/botanist.dm
index 128a2329515..ea6de611f4a 100644
--- a/code/modules/jobs/job_types/botanist.dm
+++ b/code/modules/jobs/job_types/botanist.dm
@@ -19,9 +19,9 @@
family_heirlooms = list(/obj/item/cultivator, /obj/item/reagent_containers/glass/bucket, /obj/item/toy/plush/beeplushie)
mail_goodies = list(
- /datum/reagent/toxin/mutagen = 20,
- /datum/reagent/saltpetre = 20,
- /datum/reagent/diethylamine = 20,
+ /obj/item/reagent_containers/glass/bottle/mutagen = 20,
+ /obj/item/reagent_containers/glass/bottle/saltpetre = 20,
+ /obj/item/reagent_containers/glass/bottle/diethylamine = 20,
/obj/item/gun/energy/floragun = 10,
/obj/effect/spawner/lootdrop/space/rareseed = 5,// These are strong, rare seeds, so use sparingly.
/obj/item/food/monkeycube/bee = 2
diff --git a/code/modules/jobs/job_types/chemist.dm b/code/modules/jobs/job_types/chemist.dm
index 4c099fa77ce..257f4591ad6 100644
--- a/code/modules/jobs/job_types/chemist.dm
+++ b/code/modules/jobs/job_types/chemist.dm
@@ -24,9 +24,9 @@
family_heirlooms = list(/obj/item/book/manual/wiki/chemistry, /obj/item/ph_booklet)
mail_goodies = list(
- /datum/reagent/flash_powder = 15,
- /datum/reagent/exotic_stabilizer = 5,
- /datum/reagent/toxin/leadacetate = 5,
+ /obj/item/reagent_containers/glass/bottle/flash_powder = 15,
+ /obj/item/reagent_containers/glass/bottle/exotic_stabilizer = 5,
+ /obj/item/reagent_containers/glass/bottle/leadacetate = 5,
/obj/item/paper/secretrecipe = 1
)
diff --git a/code/modules/jobs/job_types/cook.dm b/code/modules/jobs/job_types/cook.dm
index 2fd055572a2..f1cb63a7ab7 100644
--- a/code/modules/jobs/job_types/cook.dm
+++ b/code/modules/jobs/job_types/cook.dm
@@ -55,7 +55,7 @@
mail_goodies = list(
/obj/item/storage/box/ingredients/random = 80,
- /datum/reagent/consumable/caramel = 20,
+ /obj/item/reagent_containers/glass/bottle/caramel = 20,
/obj/item/reagent_containers/food/condiment/flour = 20,
/obj/item/reagent_containers/food/condiment/rice = 20,
/obj/item/reagent_containers/food/condiment/enzyme = 15,
diff --git a/code/modules/jobs/job_types/medical_doctor.dm b/code/modules/jobs/job_types/medical_doctor.dm
index db593b9b2f6..257f8c280cc 100644
--- a/code/modules/jobs/job_types/medical_doctor.dm
+++ b/code/modules/jobs/job_types/medical_doctor.dm
@@ -26,7 +26,7 @@
/obj/item/scalpel/advanced = 6,
/obj/item/retractor/advanced = 6,
/obj/item/cautery/advanced = 6,
- /datum/reagent/toxin/formaldehyde = 6,
+ /obj/item/reagent_containers/glass/bottle/formaldehyde = 6,
/obj/effect/spawner/lootdrop/organ_spawner = 5,
/obj/effect/spawner/lootdrop/memeorgans = 1
)
diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm
index 6b656f345d7..4432211b560 100644
--- a/code/modules/reagents/reagent_containers/bottle.dm
+++ b/code/modules/reagents/reagent_containers/bottle.dm
@@ -420,3 +420,35 @@
/obj/item/reagent_containers/glass/bottle/thermite
name = "thermite bottle"
list_reagents = list(/datum/reagent/thermite = 30)
+
+// Bottles for mail goodies.
+
+/obj/item/reagent_containers/glass/bottle/clownstears
+ name = "bottle of distilled clown misery"
+ desc = "A small bottle. Contains a mythical liquid used by sublime bartenders; made from the unhappiness of clowns."
+ list_reagents = list(/datum/reagent/consumable/clownstears = 30)
+
+/obj/item/reagent_containers/glass/bottle/saltpetre
+ name = "saltpetre bottle"
+ desc = "A small bottle. Contains saltpetre."
+ list_reagents = list(/datum/reagent/saltpetre = 30)
+
+/obj/item/reagent_containers/glass/bottle/flash_powder
+ name = "flash powder bottle"
+ desc = "A small bottle. Contains flash powder."
+ list_reagents = list(/datum/reagent/flash_powder = 30)
+
+/obj/item/reagent_containers/glass/bottle/exotic_stabilizer
+ name = "exotic stabilizer bottle"
+ desc = "A small bottle. Contains exotic stabilizer."
+ list_reagents = list(/datum/reagent/exotic_stabilizer = 30)
+
+/obj/item/reagent_containers/glass/bottle/leadacetate
+ name = "lead acetate bottle"
+ desc = "A small bottle. Contains lead acetate."
+ list_reagents = list(/datum/reagent/toxin/leadacetate = 30)
+
+/obj/item/reagent_containers/glass/bottle/caramel
+ name = "bottle of caramel"
+ desc = "A bottle containing caramalized sugar, also known as caramel. Do not lick."
+ list_reagents = list(/datum/reagent/consumable/caramel = 30)
diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm
index bfcc60c8f3a..7835b8cc2f8 100644
--- a/code/modules/shuttle/supply.dm
+++ b/code/modules/shuttle/supply.dm
@@ -246,6 +246,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
//Early return if there's no mail waiting to prevent taking up a slot. We also don't send mails on sundays or holidays.
if(!SSeconomy.mail_waiting || SSeconomy.mail_blocked)
return
+
//spawn crate
var/list/empty_turfs = list()
for(var/place as anything in shuttle_areas)
@@ -254,35 +255,8 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
if(shuttle_floor.is_blocked_turf())
continue
empty_turfs += shuttle_floor
- var/obj/structure/closet/crate/mail/mailcrate = new(pick(empty_turfs))
- //collect recipients
- var/list/mail_recipients = list()
- for(var/mob/living/carbon/human/player_human in shuffle(GLOB.player_list))
- if(player_human.stat == DEAD)
- continue
- if(!SSjob.GetJob(player_human.mind.assigned_role) || (player_human.mind.assigned_role in GLOB.nonhuman_positions))
- continue //this check stops wizards and nuke ops from getting mail, which is hilarious but should definitely not happen
- mail_recipients += player_human
-
- //Creates mail for all the mail waiting to arrive, if there's nobody to recieve it it's just junkmail.
- for(var/mail_iterator in 1 to SSeconomy.mail_waiting)
- var/obj/item/mail/new_mail
- if(prob(FULL_CRATE_LETTER_ODDS))
- new_mail = new /obj/item/mail(mailcrate)
- else
- new_mail = new /obj/item/mail/envelope(mailcrate)
- var/mob/living/carbon/human/mail_to
- if(mail_recipients.len)
- mail_to = pick(mail_recipients)
- new_mail.initialize_for_recipient(mail_to)
- mail_recipients -= mail_to
- else
- new_mail.junk_mail()
- if(new_mail)
- SSeconomy.mail_waiting -= 1
- mailcrate.update_icon()
- return mailcrate
+ new /obj/structure/closet/crate/mail/economy(pick(empty_turfs))
#undef GOODY_FREE_SHIPPING_MAX
#undef CRATE_TAX