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