diff --git a/code/__DEFINES/cargo.dm b/code/__DEFINES/cargo.dm index e3228ba06258..87bf7b32ce3f 100644 --- a/code/__DEFINES/cargo.dm +++ b/code/__DEFINES/cargo.dm @@ -50,3 +50,5 @@ GLOBAL_LIST_INIT(podstyles, list(\ list(POD_SHAPE_OTHER, "gondola", FALSE, FALSE, FALSE, RUBBLE_NONE, "gondola", "The silent walker. This one seems to be part of a delivery agency."),\ list(POD_SHAPE_OTHER, FALSE, FALSE, FALSE, FALSE, RUBBLE_NONE, FALSE, FALSE, "rl_click", "give_po")\ )) + +GLOBAL_LIST_INIT(junkmail_messages, world.file2list("strings/junkmail.txt")) \ No newline at end of file diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 1953651125f0..4410f8dd5e52 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -29,6 +29,7 @@ #define COLOR_MAGENTA "#FF00FF" #define COLOR_PURPLE "#800080" #define COLOR_ORANGE "#FF9900" +#define COLOR_PALE_ORANGE "#FFBE9D" #define COLOR_BEIGE "#CEB689" #define COLOR_BLUE_GRAY "#75A2BB" #define COLOR_BROWN "#BA9F6D" diff --git a/code/__DEFINES/economy.dm b/code/__DEFINES/economy.dm index 804967111f0c..741cc4259b33 100644 --- a/code/__DEFINES/economy.dm +++ b/code/__DEFINES/economy.dm @@ -1,4 +1,8 @@ #define STARTING_PAYCHECKS 5 +/// How much mail the Economy SS will create per minute, regardless of firing time. +#define MAX_MAIL_PER_MINUTE 3 +/// Probability of using letters of envelope sprites on all letters. +#define FULL_CRATE_LETTER_ODDS 70 #define PAYCHECK_ASSISTANT 5 #define PAYCHECK_MINIMAL 5 diff --git a/code/controllers/subsystem/economy.dm b/code/controllers/subsystem/economy.dm index c3ed6d466df7..11b2f6ed6278 100644 --- a/code/controllers/subsystem/economy.dm +++ b/code/controllers/subsystem/economy.dm @@ -53,9 +53,15 @@ SUBSYSTEM_DEF(economy) var/bounty_modifier = 1 ///The modifier multiplied to the value of cargo pack prices. var/pack_price_modifier = 1 + /// Number of mail items generated. + var/mail_waiting = 0 + /// Mail Holiday: AKA does mail arrive today? Always blocked on Sundays. + var/mail_blocked = FALSE /datum/controller/subsystem/economy/Initialize(timeofday) var/budget_to_hand_out = round(budget_pool / department_accounts.len) + if(time2text(world.timeofday, "DDD") == SUNDAY) + mail_blocked = TRUE for(var/A in department_accounts) if(A == ACCOUNT_SEC) new /datum/bank_account/department(A, STARTING_SEC_BUDGET) @@ -69,6 +75,7 @@ SUBSYSTEM_DEF(economy) secmedsrv_payout() // Payout based on crew safety, health, and mood. civ_payout() // Payout based on ??? Profit car_payout() // Cargo's natural gain in the cash moneys. + var/delta_time = wait / (5 MINUTES) var/list/dictionary = list() for(var/datum/corporation/c in GLOB.corporations) dictionary[c] = list() @@ -80,6 +87,8 @@ SUBSYSTEM_DEF(economy) if(B.account_holder in dictionary[c]) B.payday(c.paymodifier, TRUE) B.payday(1) + var/effective_mailcount = living_player_count() + mail_waiting += clamp(effective_mailcount, 1, MAX_MAIL_PER_MINUTE * 5 * delta_time) /datum/controller/subsystem/economy/proc/get_dep_account(dep_id) for(var/datum/bank_account/department/D in generated_accounts) diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index 56dd8d33adcf..472266ae7a9b 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -10,7 +10,6 @@ /obj/effect/spawner/lootdrop/Initialize(mapload) ..() if(loot && loot.len) - var/turf/T = get_turf(src) var/loot_spawned = 0 while((lootcount-loot_spawned) && loot.len) var/lootspawn = pickweight(loot) @@ -18,7 +17,7 @@ loot.Remove(lootspawn) if(lootspawn) - var/atom/movable/spawned_loot = new lootspawn(T) + var/atom/movable/spawned_loot = new lootspawn(loc) if (!fan_out_items) if (pixel_x != 0) spawned_loot.pixel_x = pixel_x @@ -30,6 +29,48 @@ loot_spawned++ return INITIALIZE_HINT_QDEL +/obj/effect/spawner/lootdrop/surgery_tool_advanced + name = "Advanced surgery tool spawner" + loot = list( // Mail loot spawner. Drop pool of advanced medical tools typically from research. Not endgame content. + /obj/item/scalpel/advanced, + /obj/item/retractor/advanced, + /obj/item/cautery/advanced, + ) + +/obj/effect/spawner/lootdrop/surgery_tool_alien + name = "Rare surgery tool spawner" + loot = list( // Mail loot spawner. Some sort of random and rare surgical tool. Alien tech found here. + /obj/item/scalpel/alien, + /obj/item/hemostat/alien, + /obj/item/retractor/alien, + /obj/item/circular_saw/alien, + /obj/item/surgicaldrill/alien, + /obj/item/cautery/alien, + ) + +/obj/effect/spawner/lootdrop/memeorgans + name = "meme organ spawner" + lootcount = 5 + loot = list( + /obj/item/organ/ears/penguin, + /obj/item/organ/ears/cat, + /obj/item/organ/eyes/moth, + /obj/item/organ/eyes/snail, + /obj/item/organ/tongue/bone, + /obj/item/organ/tongue/fly, + /obj/item/organ/tongue/snail, + /obj/item/organ/tongue/lizard, + /obj/item/organ/tongue/alien, + ///obj/item/organ/tongue/ethereal, + /obj/item/organ/tongue/robot, + /obj/item/organ/tongue/zombie, + /obj/item/organ/appendix, + /obj/item/organ/liver/fly, + /obj/item/organ/lungs/plasmaman, + /obj/item/organ/tail/cat, + /obj/item/organ/tail/lizard, + ) + /obj/effect/spawner/lootdrop/armory_contraband name = "armory contraband gun spawner" lootdoubles = FALSE @@ -56,6 +97,26 @@ /obj/item/toy/cards/deck/syndicate = 2 ) +/obj/effect/spawner/lootdrop/seed_rare + name = "rare seed" + lootcount = 5 + loot = list( // /obj/item/seeds/random is not a random seed, but an exotic seed. + /obj/item/seeds/random = 30, + /obj/item/seeds/liberty = 5, + /obj/item/seeds/replicapod = 5, + /obj/item/seeds/reishi = 5, + /obj/item/seeds/nettle/death = 1, + /obj/item/seeds/plump/walkingmushroom = 1, + /obj/item/seeds/cannabis/rainbow = 1, + /obj/item/seeds/cannabis/death = 1, + /obj/item/seeds/cannabis/white = 1, + /obj/item/seeds/cannabis/ultimate = 1, + /obj/item/seeds/kudzu = 1, + /obj/item/seeds/angel = 1, + /obj/item/seeds/glowshroom/glowcap = 1, + /obj/item/seeds/glowshroom/shadowshroom = 1, + ) + /obj/effect/spawner/lootdrop/grille_or_trash name = "maint grille or trash spawner" loot = list(/obj/structure/grille = 5, diff --git a/code/game/objects/items/grenades/atmos_grenades.dm b/code/game/objects/items/grenades/atmos_grenades.dm index 5c626d8397d1..f991213215b6 100644 --- a/code/game/objects/items/grenades/atmos_grenades.dm +++ b/code/game/objects/items/grenades/atmos_grenades.dm @@ -18,6 +18,29 @@ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', volume, TRUE) addtimer(CALLBACK(src, .proc/prime), isnull(delayoverride)? det_time : delayoverride) +/obj/item/grenade/gas_crystal/proto_nitrate_crystal + name = "Proto Nitrate crystal" + desc = "A crystal made from the Proto Nitrate gas, you can see the liquid gases inside." + icon_state = "proto_nitrate_crystal" + ///Range of the grenade air refilling + var/refill_range = 5 + ///Amount of Nitrogen gas released (close to the grenade) + var/n2_gas_amount = 80 + ///Amount of Oxygen gas released (close to the grenade) + var/o2_gas_amount = 30 + +/obj/item/grenade/gas_crystal/proto_nitrate_crystal/prime(mob/living/lanced_by) + . = ..() + update_mob() + playsound(src, 'sound/effects/spray2.ogg', 100, TRUE) + for(var/turf/turf_loc in view(refill_range, loc)) + if(!isopenturf(turf_loc)) + continue + var/distance_from_center = max(get_dist(turf_loc, loc), 1) + var/turf/open/floor_loc = turf_loc + floor_loc.atmos_spawn_air("n2=[n2_gas_amount / distance_from_center];o2=[o2_gas_amount / distance_from_center];TEMP=273") + qdel(src) + /obj/item/grenade/gas_crystal/healium_crystal name = "Healium crystal" desc = "A crystal made from the Healium gas, it's cold to the touch." @@ -94,3 +117,33 @@ var/turf/open/floor_loc = turf_loc floor_loc.atmos_spawn_air("n2o=[n2o_gas_amount / distance_from_center];TEMP=273") qdel(src) + +/obj/item/grenade/gas_crystal/crystal_foam + name = "crystal foam" + desc = "A crystal with a foggy inside" + icon_state = "crystal_foam" + var/breach_range = 7 + +/obj/item/grenade/gas_crystal/crystal_foam/prime(mob/living/lanced_by) + . = ..() + + var/datum/reagents/first_batch = new + var/datum/reagents/second_batch = new + var/list/datum/reagents/reactants = list() + + first_batch.add_reagent(/datum/reagent/aluminium, 75) + second_batch.add_reagent(/datum/reagent/smart_foaming_agent, 25) + second_batch.add_reagent(/datum/reagent/toxin/acid/fluacid, 25) + reactants += first_batch + reactants += second_batch + + var/turf/detonation_turf = get_turf(src) + + chem_splash(detonation_turf, breach_range, reactants) + + playsound(src, 'sound/effects/spray2.ogg', 100, TRUE) + log_game("A grenade detonated at [AREACOORD(detonation_turf)]") + + update_mob() + + qdel(src) diff --git a/code/game/objects/items/mail.dm b/code/game/objects/items/mail.dm new file mode 100644 index 000000000000..c5321159ad94 --- /dev/null +++ b/code/game/objects/items/mail.dm @@ -0,0 +1,313 @@ +/// Mail is tamper-evident and unresealable, postmarked by CentCom for an individual recepient. +/obj/item/mail + name = "mail" + gender = NEUTER + desc = "An officially postmarked, tamper-evident parcel regulated by CentCom and made of high-quality materials." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "mail_small" + item_flags = NOBLUDGEON + w_class = WEIGHT_CLASS_SMALL + //drop_sound = 'sound/items/handling/paper_drop.ogg' + //pickup_sound = 'sound/items/handling/paper_pickup.ogg' + mouse_drag_pointer = MOUSE_ACTIVE_POINTER + /// Destination tagging for the mail sorter. + var/sort_tag = NONE + /// 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. + var/list/generic_goodies = list( + /obj/item/stack/spacecash/c50 = 10, + /obj/item/stack/spacecash/c100 = 25, + /obj/item/stack/spacecash/c200 = 15, + /obj/item/stack/spacecash/c500 = 5, + /obj/item/stack/spacecash/c1000 = 1, + ) + // Overlays (pure fluff) + /// Does the letter have the postmark overlay? + var/postmarked = TRUE + /// Does the letter have a stamp overlay? + var/stamped = TRUE + /// List of all stamp overlays on the letter. + var/list/stamps = list() + /// Maximum number of stamps on the letter. + var/stamp_max = 1 + /// Physical offset of stamps on the object. X direction. + var/stamp_offset_x = 0 + /// Physical offset of stamps on the object. Y direction. + var/stamp_offset_y = 2 + + ///mail will have the color of the department the recipient is in. + var/static/list/department_colors + +/obj/item/mail/envelope + name = "envelope" + icon_state = "mail_large" + goodie_count = 2 + stamp_max = 2 + stamp_offset_y = 5 + +/obj/item/mail/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_MOVABLE_DISPOSING, .proc/disposal_handling) + //AddElement(/datum/element/item_scaling, 0.75, 1) + if(isnull(department_colors)) + department_colors = list( + ACCOUNT_CIV = COLOR_WHITE, + ACCOUNT_ENG = COLOR_PALE_ORANGE, + ACCOUNT_SCI = COLOR_PALE_PURPLE_GRAY, + ACCOUNT_MED = COLOR_PALE_BLUE_GRAY, + ACCOUNT_SRV = COLOR_PALE_GREEN_GRAY, + ACCOUNT_CAR = COLOR_BEIGE, + ACCOUNT_SEC = COLOR_PALE_RED_GRAY, + ) + + // Icons + // Add some random stamps. + if(stamped == TRUE) + var/stamp_count = rand(1, stamp_max) + for(var/i in 1 to stamp_count) + stamps += list("stamp_[rand(2, 6)]") + update_icon() + +/obj/item/mail/update_icon() + . = ..() + var/bonus_stamp_offset = 0 + for(var/stamp in stamps) + var/image/stamp_image = image( + icon = icon, + icon_state = stamp, + pixel_x = stamp_offset_x, + pixel_y = stamp_offset_y + bonus_stamp_offset + ) + stamp_image.appearance_flags |= RESET_COLOR + add_overlay(stamp_image) + bonus_stamp_offset -= 5 + + if(postmarked == TRUE) + var/image/postmark_image = image( + icon = icon, + icon_state = "postmark", + pixel_x = stamp_offset_x + rand(-3, 1), + pixel_y = stamp_offset_y + rand(bonus_stamp_offset + 3, 1) + ) + postmark_image.appearance_flags |= RESET_COLOR + add_overlay(postmark_image) + +/obj/item/mail/attackby(obj/item/W, mob/user, params) + // Destination tagging + if(istype(W, /obj/item/destTagger)) + var/obj/item/destTagger/destination_tag = W + + if(sort_tag != destination_tag.currTag) + var/tag = uppertext(GLOB.TAGGERLOCATIONS[destination_tag.currTag]) + to_chat(user, span_notice("*[tag]*")) + sort_tag = destination_tag.currTag + playsound(loc, 'sound/machines/twobeep_high.ogg', 100, TRUE) + +/obj/item/mail/attack_self(mob/user) + 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)) + return + user.temporarilyRemoveItemFromInventory(src, TRUE) + for (var/content in contents) + user.put_in_hands(content) + playsound(loc, 'sound/items/poster_ripped.ogg', 50, TRUE) + qdel(src) + +/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 + msg += "\t[span_info("Certified mail for [GLOB.station_name].")]" + msg += "\t[span_info("Distribute by hand or via destination tagger using the certified NT disposal system.")]" + return msg + +/// 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.GetJob(recipient.assigned_role) + if(this_job) + if(this_job.paycheck_department && department_colors[this_job.paycheck_department]) + color = department_colors[this_job.paycheck_department] + var/list/job_goodies = this_job.get_mail_goodies() + if(LAZYLEN(job_goodies)) + // certain roles and jobs (prisoner) do not receive generic gifts. + if(this_job.exclusive_mail_goodies) + goodies = job_goodies + else + goodies += job_goodies + + for(var/iterator in 1 to goodie_count) + var/target_good = pickweight(goodies) + 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 + +/// Alternate setup, just complete garbage inside and anyone can open +/obj/item/mail/proc/junk_mail() + sort_tag = 1 // Default sort for junk mail is the trash + + var/obj/junk = /obj/item/paper/fluff/junkmail_generic + var/special_name = FALSE + + if(prob(25)) + special_name = TRUE + junk = pick(list(/obj/item/paper/pamphlet/gateway, /obj/item/paper/pamphlet/centcom/visitor_info, /obj/item/paper/fluff/junkmail_redpill, /obj/effect/decal/cleanable/ash)) + + var/list/junk_names = list( + /obj/item/paper/pamphlet/gateway = "[initial(name)] for [pick(GLOB.adjectives)] adventurers", + /obj/item/paper/pamphlet/centcom/visitor_info = "[initial(name)] for info about visiting nanotrasen space stations", + /obj/item/paper/fluff/junkmail_redpill = "[initial(name)] for those feeling [pick(GLOB.adjectives)] working at Nanotrasen", + /obj/effect/decal/cleanable/ash = "[initial(name)] with INCREDIBLY IMPORTANT ARTIFACT- DELIVER TO SCIENCE DIVISION. HANDLE WITH CARE.", + ) + + color = pick(department_colors) //eh, who gives a shit. + name = special_name ? junk_names[junk] : "important [initial(name)]" + + junk = new junk(src) + return TRUE + +/obj/item/mail/proc/disposal_handling(disposal_source, obj/structure/disposalholder/disposal_holder, obj/machinery/disposal/disposal_machine, hasmob) + if(!hasmob) + disposal_holder.destinationTag = sort_tag + +/// Subtype that's always junkmail +/obj/item/mail/junkmail/Initialize(mapload) + . = ..() + junk_mail() + +/// Crate for mail from CentCom. +/obj/structure/closet/crate/mail + name = "mail crate" + desc = "A certified post crate from CentCom." + icon_state = "mail" + +/obj/structure/closet/crate/mail/update_icon() + . = ..() + if(opened) + icon_state = "[initial(icon_state)]open" + if(locate(/obj/item/mail) in src) + icon_state = initial(icon_state) + else + icon_state = "[initial(icon_state)]sealed" + +/// 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 in GLOB.player_list) + if(human.stat == DEAD || !human.mind) + continue + // Skip wizards, nuke ops, cyborgs; Centcom does not send them mail + var/datum/job/this_job = SSjob.GetJob(human.mind.assigned_role) + if(!this_job || this_job.faction != "Station") + 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/datum/mind/recipient = pick_n_take(mail_recipients) + if(recipient) + new_mail.initialize_for_recipient(recipient) + else + new_mail.junk_mail() + + update_icon() + + return mail_count + +/// Crate for mail that automatically depletes the economy subsystem's pending mail counter. +/obj/structure/closet/crate/mail/economy/Initialize(mapload) + . = ..() + var/mail_handled = populate(SSeconomy.mail_waiting) + SSeconomy.mail_waiting -= mail_handled + +/// 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(mapload) + . = ..() + populate(INFINITY) + + +/// Mailbag. +/obj/item/storage/bag/mail + name = "mail bag" + desc = "A bag for letters, envelopes, and other postage." + icon = 'icons/obj/library.dmi' + icon_state = "bookbag" + //worn_icon_state = "bookbag" + resistance_flags = FLAMMABLE + +/obj/item/storage/bag/mail/ComponentInitialize() + . = ..() + var/datum/component/storage/storage = GetComponent(/datum/component/storage) + storage.max_w_class = WEIGHT_CLASS_NORMAL + storage.max_combined_w_class = 42 + storage.max_items = 21 + storage.display_numerical_stacking = FALSE + storage.set_holdable(list( + /obj/item/mail, + /obj/item/smallDelivery, + /obj/item/paper + )) + +/obj/item/paper/fluff/junkmail_redpill + name = "smudged paper" + icon_state = "scrap" + var/nuclear_option_odds = 0.1 + +/obj/item/paper/fluff/junkmail_redpill/Initialize(mapload) + . = ..() + if(!prob(nuclear_option_odds)) // 1 in 1000 chance of getting 2 random nuke code characters. + info = "You need to escape the simulation. Don't forget the numbers, they help you remember: '[rand(0,9)][rand(0,9)]...'" + return + var/obj/machinery/nuclearbomb/selfdestruct/nuke = locate() in GLOB.nuke_list + var/code = random_nukecode() + if(nuke) + if(nuke.r_code == "ADMIN") + nuke.r_code = code + else + code = nuke.r_code + message_admins("Through junkmail, the self-destruct code was set to \"[code]\".") + info = "You need to escape the simulation. Don't forget the numbers, they help you remember: '[code[rand(1,5)]][code[rand(1,5)]]...'" + +/obj/item/paper/fluff/junkmail_redpill/true //admin letter enabling players to brute force their way through the nuke code if they're so inclined. + nuclear_option_odds = 100 + +/obj/item/paper/fluff/junkmail_generic + name = "important document" + icon_state = "paper_words" + +/obj/item/paper/fluff/junkmail_generic/Initialize(mapload) + . = ..() + info = pick(GLOB.junkmail_messages) diff --git a/code/modules/cargo/exports/large_objects.dm b/code/modules/cargo/exports/large_objects.dm index 5311e8e1fc82..350a38f1db9e 100644 --- a/code/modules/cargo/exports/large_objects.dm +++ b/code/modules/cargo/exports/large_objects.dm @@ -2,7 +2,7 @@ cost = 500 unit_name = "crate" export_types = list(/obj/structure/closet/crate) - exclude_types = list(/obj/structure/closet/crate/large, /obj/structure/closet/crate/wooden, /obj/structure/closet/crate/secure/cheap, /obj/structure/closet/crate/secure/owned) + exclude_types = list(/obj/structure/closet/crate/large, /obj/structure/closet/crate/wooden, /obj/structure/closet/crate/secure/cheap, /obj/structure/closet/crate/secure/owned, /obj/structure/closet/crate/mail) /datum/export/large/crate/total_printout(datum/export_report/ex, notes = TRUE) // That's why a goddamn metal crate costs that much. . = ..() diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index 1de1adc8ab75..1f6133cc1889 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -60,6 +60,19 @@ cold_protection = HEAD min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT +/obj/item/clothing/head/hardhat/red/upgraded + name = "workplace-ready firefighter helmet" + desc = "By applying state of the art lighting technology to a fire helmet, and using photo-chemical hardening methods, this hardhat will protect you from robust workplace hazards." + icon_state = "hardhat0_purple" + item_state = "hardhat0_purple" + brightness_on = 5 + heat_protection = HEAD + max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT + cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT + custom_materials = list(/datum/material/iron = 4000, /datum/material/glass = 1000, /datum/material/plastic = 3000, /datum/material/silver = 500) + item_color = "purple" + /obj/item/clothing/head/hardhat/white icon_state = "hardhat0_white" item_state = "hardhat0_white" diff --git a/code/modules/food_and_drinks/food/snacks_meat.dm b/code/modules/food_and_drinks/food/snacks_meat.dm index 5a9bdd4bc4f7..e95b96a6fb5b 100644 --- a/code/modules/food_and_drinks/food/snacks_meat.dm +++ b/code/modules/food_and_drinks/food/snacks_meat.dm @@ -546,6 +546,14 @@ tastes = list("the jungle" = 1, "bananas" = 1, "jimmies" = 1) spawned_mob = /mob/living/simple_animal/hostile/gorilla +/obj/item/reagent_containers/food/snacks/monkeycube/bee + name = "bee cube" + desc = "We were sure it was a good idea. Just add water." + bitesize = 20 + list_reagents = list(/datum/reagent/consumable/honey = 10, /datum/reagent/toxin = 5, /datum/reagent/medicine/strange_reagent = 1) + tastes = list("buzzing" = 1, "honey" = 1, "regret" = 1) + spawned_mob = /mob/living/simple_animal/hostile/poison/bees/toxin + /obj/item/reagent_containers/food/snacks/monkeycube/sheep name = "sheep cube" desc = "A Farm Town brand sheep cube. Just add water!" diff --git a/code/modules/holiday/holidays.dm b/code/modules/holiday/holidays.dm index 90f6ca7c4476..f8143f95c886 100644 --- a/code/modules/holiday/holidays.dm +++ b/code/modules/holiday/holidays.dm @@ -11,9 +11,13 @@ var/current_year = 0 var/year_offset = 0 var/obj/item/drone_hat //If this is defined, drones without a default hat will spawn with this one during the holiday; check drones_as_items.dm to see this used + ///When this holiday is active, does this prevent mail from arriving to cargo? Try not to use this for longer holidays. + var/mail_holiday = FALSE // This proc gets run before the game starts when the holiday is activated. Do festive shit here. /datum/holiday/proc/celebrate() + if(mail_holiday) + SSeconomy.mail_blocked = TRUE return // When the round starts, this proc is ran to get a text message to display to everyone to wish them a happy holiday @@ -71,6 +75,7 @@ end_day = 2 end_month = JANUARY drone_hat = /obj/item/clothing/head/festive + mail_holiday = TRUE /datum/holiday/new_year/getStationPrefix() return pick("Party","New","Hangover","Resolution","Auld") @@ -237,6 +242,7 @@ begin_day = 1 begin_month = MAY drone_hat = /obj/item/clothing/head/hardhat + mail_holiday = TRUE /datum/holiday/labor/getStationPrefix() return pick("Union","Labor","Worker","Trade") @@ -306,6 +312,7 @@ "https://www.youtube.com/watch?v=FAVQsnr4uYg", // Lone Star - Tony Marcus "https://www.youtube.com/watch?v=kQzdJUiALBk" // wyoming - In the Shadow of the Valley - Don Burnham ) + mail_holiday = TRUE /datum/holiday/USA/getStationPrefix() return pick("Independent","American","Burger","Bald Eagle","Star-Spangled", "Fireworks") @@ -326,6 +333,7 @@ "https://www.youtube.com/watch?v=o3wivTC1gOw", // Bonjour mon vieux Paris "https://www.youtube.com/watch?v=8KdTChn-pEA" // Maréchal, nous voilà ) + mail_holiday = TRUE /datum/holiday/france/getStationPrefix() return pick("Francais","Fromage", "Zut", "Merde") @@ -587,6 +595,7 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and "https://www.youtube.com/watch?v=KGEfBop0nkI", // Julia Ecklar - "Christmastime in Sector 5" - "Little Drummer Boy" "https://www.youtube.com/watch?v=1twga61Kd14" // Julia Ecklar - #1 - Christmas Time ) + mail_holiday = TRUE /datum/holiday/xmas/greet() return "Have a merry Christmas!" diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index 23e2a3f08e1d..75b3990a124d 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -68,6 +68,14 @@ var/display_order = JOB_DISPLAY_ORDER_DEFAULT + /// Goodies that can be received via the mail system. + // this is a weighted list. + /// Keep the _job definition for this empty and use /obj/item/mail to define general gifts. + var/list/mail_goodies = list() + + /// If this job's mail goodies compete with generic goodies. + var/exclusive_mail_goodies = FALSE + var/list/changed_maps = list() // Maps on which the job is changed. Should use the same name as the mapping config /* @@ -303,6 +311,10 @@ types += duffelbag return types +/// An overridable getter for more dynamic goodies. +/datum/job/proc/get_mail_goodies(mob/recipient) + return mail_goodies + //Warden and regular officers add this result to their get_access() /datum/job/proc/check_config_for_sec_maint() if(CONFIG_GET(flag/security_has_maint_access)) diff --git a/code/modules/jobs/job_types/assistant.dm b/code/modules/jobs/job_types/assistant.dm index 2a7e98f08823..c4c112554f03 100644 --- a/code/modules/jobs/job_types/assistant.dm +++ b/code/modules/jobs/job_types/assistant.dm @@ -18,6 +18,15 @@ Assistant paycheck_department = ACCOUNT_CIV display_order = JOB_DISPLAY_ORDER_ASSISTANT + mail_goodies = list( + /obj/item/reagent_containers/food/snacks/donkpocket = 10, + /obj/item/clothing/mask/gas = 10, + /obj/item/clothing/gloves/color/fyellow = 7, + /obj/item/choice_beacon/music = 5, + /obj/item/toy/crayon/spraycan = 3, + /obj/item/crowbar/large = 1 + ) + alt_titles = list("Intern", "Apprentice", "Subordinate", "Temporary Worker", "Associate") /datum/job/assistant/get_access() diff --git a/code/modules/jobs/job_types/atmospheric_technician.dm b/code/modules/jobs/job_types/atmospheric_technician.dm index d708fcce4d2c..eb85c68811df 100644 --- a/code/modules/jobs/job_types/atmospheric_technician.dm +++ b/code/modules/jobs/job_types/atmospheric_technician.dm @@ -21,6 +21,14 @@ paycheck_department = ACCOUNT_ENG display_order = JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN + mail_goodies = list( + ///obj/item/rpd_upgrade/unwrench = 30, + /obj/item/grenade/gas_crystal/crystal_foam = 10, + /obj/item/grenade/gas_crystal/proto_nitrate_crystal = 10, + /obj/item/grenade/gas_crystal/healium_crystal = 10, + /obj/item/grenade/gas_crystal/nitrous_oxide_crystal = 5, + ) + changed_maps = list("OmegaStation", "EclipseStation") /datum/job/atmos/proc/OmegaStationChanges() diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm index dfed18dd2430..654dbedff83c 100644 --- a/code/modules/jobs/job_types/bartender.dm +++ b/code/modules/jobs/job_types/bartender.dm @@ -20,6 +20,13 @@ paycheck_department = ACCOUNT_SRV display_order = JOB_DISPLAY_ORDER_BARTENDER + mail_goodies = list( + /obj/item/storage/box/rubbershot = 30, + /obj/item/reagent_containers/glass/bottle/clownstears = 10, + /obj/item/stack/sheet/mineral/plasma = 10, + /obj/item/stack/sheet/mineral/uranium = 10, + ) + changed_maps = list("OmegaStation") /datum/job/bartender/proc/OmegaStationChanges() diff --git a/code/modules/jobs/job_types/botanist.dm b/code/modules/jobs/job_types/botanist.dm index 9ed71fb575be..7f905147fcbf 100644 --- a/code/modules/jobs/job_types/botanist.dm +++ b/code/modules/jobs/job_types/botanist.dm @@ -19,6 +19,15 @@ paycheck_department = ACCOUNT_SRV display_order = JOB_DISPLAY_ORDER_BOTANIST + mail_goodies = list( + /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/seed_rare = 5,// These are strong, rare seeds, so use sparingly. + /obj/item/reagent_containers/food/snacks/monkeycube/bee = 2 + ) + changed_maps = list("OmegaStation", "EclipseStation") /datum/job/hydro/proc/OmegaStationChanges() diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm index cd2dcb17767f..eee46ee51b5d 100755 --- a/code/modules/jobs/job_types/captain.dm +++ b/code/modules/jobs/job_types/captain.dm @@ -26,6 +26,12 @@ mind_traits = list(TRAIT_DISK_VERIFIER) + mail_goodies = list( + /obj/item/clothing/mask/cigarette/cigar/havana = 20, + ///obj/item/storage/fancy/cigarettes/cigars/havana = 15, + /obj/item/reagent_containers/food/drinks/bottle/champagne = 10 + ) + display_order = JOB_DISPLAY_ORDER_CAPTAIN /datum/job/captain/get_access() diff --git a/code/modules/jobs/job_types/cargo_technician.dm b/code/modules/jobs/job_types/cargo_technician.dm index 46bd98c8898a..1d479d4c800b 100644 --- a/code/modules/jobs/job_types/cargo_technician.dm +++ b/code/modules/jobs/job_types/cargo_technician.dm @@ -20,6 +20,14 @@ display_order = JOB_DISPLAY_ORDER_CARGO_TECHNICIAN + mail_goodies = list( + /obj/item/pizzabox = 10, + /obj/item/stack/sheet/mineral/gold = 5, + /obj/item/stack/sheet/mineral/uranium = 4, + /obj/item/stack/sheet/mineral/diamond = 3, + /obj/item/gun/ballistic/rifle/boltaction = 1 + ) + changed_maps = list("EclipseStation", "OmegaStation") /datum/job/cargo_tech/proc/EclipseStationChanges() diff --git a/code/modules/jobs/job_types/chaplain.dm b/code/modules/jobs/job_types/chaplain.dm index cd921a35b619..f62853b362b1 100644 --- a/code/modules/jobs/job_types/chaplain.dm +++ b/code/modules/jobs/job_types/chaplain.dm @@ -20,6 +20,14 @@ display_order = JOB_DISPLAY_ORDER_CHAPLAIN + mail_goodies = list( + /obj/item/reagent_containers/food/drinks/bottle/holywater = 30, + /obj/item/toy/plush/awakenedplushie = 10, + /obj/item/grenade/chem_grenade/holy = 5, + /obj/item/toy/plush/narplush = 2, + /obj/item/toy/plush/plushvar = 1 + ) + /datum/job/chaplain/after_spawn(mob/living/H, mob/M) . = ..() diff --git a/code/modules/jobs/job_types/chemist.dm b/code/modules/jobs/job_types/chemist.dm index d88bb37fa69f..47ce09bf68a5 100644 --- a/code/modules/jobs/job_types/chemist.dm +++ b/code/modules/jobs/job_types/chemist.dm @@ -25,6 +25,13 @@ changed_maps = list("OmegaStation", "EclipseStation") + mail_goodies = list( + /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 + ) + /datum/job/chemist/proc/OmegaStationChanges() return TRUE diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm index 16223004efa7..5bc23929e3f3 100644 --- a/code/modules/jobs/job_types/chief_engineer.dm +++ b/code/modules/jobs/job_types/chief_engineer.dm @@ -32,6 +32,15 @@ display_order = JOB_DISPLAY_ORDER_CHIEF_ENGINEER + mail_goodies = list( + /obj/item/reagent_containers/food/snacks/cracker = 25, //you know. for poly + /obj/item/stack/sheet/mineral/diamond = 15, + ///obj/item/stack/sheet/mineral/uranium/five = 15, + ///obj/item/stack/sheet/mineral/plasma/five = 15, + /obj/item/stack/sheet/mineral/gold = 15 + ///obj/effect/spawner/random/engineering/tool_advanced = 3 + ) + /datum/outfit/job/ce name = "Chief Engineer" jobtype = /datum/job/chief_engineer diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm index 0e770f465b7d..cac1945715ec 100644 --- a/code/modules/jobs/job_types/chief_medical_officer.dm +++ b/code/modules/jobs/job_types/chief_medical_officer.dm @@ -32,6 +32,13 @@ changed_maps = list("OmegaStation") + mail_goodies = list( + /obj/effect/spawner/lootdrop/organ_spawner = 10, + /obj/effect/spawner/lootdrop/memeorgans = 8, + /obj/effect/spawner/lootdrop/surgery_tool_advanced = 4, + /obj/effect/spawner/lootdrop/surgery_tool_alien = 1 + ) + /datum/job/cmo/proc/OmegaStationChanges() return TRUE diff --git a/code/modules/jobs/job_types/clown.dm b/code/modules/jobs/job_types/clown.dm index 36f43b0504b0..08c244bb0887 100644 --- a/code/modules/jobs/job_types/clown.dm +++ b/code/modules/jobs/job_types/clown.dm @@ -20,6 +20,14 @@ display_order = JOB_DISPLAY_ORDER_CLOWN + mail_goodies = list( + /obj/item/reagent_containers/food/snacks/grown/banana = 100, + /obj/item/reagent_containers/food/snacks/pie/cream = 50, + /obj/item/clothing/shoes/clown_shoes/combat = 10, + /obj/item/reagent_containers/spray/waterflower/lube = 20 // lube + ///obj/item/reagent_containers/spray/waterflower/superlube = 1 // Superlube, good lord. + ) + /datum/job/clown/after_spawn(mob/living/carbon/human/H, mob/M) . = ..() diff --git a/code/modules/jobs/job_types/cook.dm b/code/modules/jobs/job_types/cook.dm index a654e5706a2a..69a76a2d8fd8 100644 --- a/code/modules/jobs/job_types/cook.dm +++ b/code/modules/jobs/job_types/cook.dm @@ -23,6 +23,17 @@ changed_maps = list("OmegaStation", "EclipseStation") + mail_goodies = list( + ///obj/item/storage/box/ingredients/random = 80, + /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, + /obj/item/reagent_containers/food/condiment/soymilk = 15, + /obj/item/kitchen/knife = 4, + /obj/item/kitchen/knife/butcher = 2 + ) + /datum/job/cook/proc/OmegaStationChanges() access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE) minimal_access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE) diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm index fa776183d3db..d9fce41ad354 100644 --- a/code/modules/jobs/job_types/detective.dm +++ b/code/modules/jobs/job_types/detective.dm @@ -25,6 +25,17 @@ display_order = JOB_DISPLAY_ORDER_DETECTIVE + mail_goodies = list( + ///obj/item/storage/fancy/cigarettes = 25, + /obj/item/ammo_box/c38 = 25, + ///obj/item/ammo_box/c38/dumdum = 5, + /obj/item/ammo_box/c38/hotshot = 5, + /obj/item/ammo_box/c38/iceblox = 5, + ///obj/item/ammo_box/c38/match = 5, + /obj/item/ammo_box/c38/trac = 5, + ///obj/item/storage/belt/holster/detective/full = 1 + ) + changed_maps = list("EclipseStation", "OmegaStation") /datum/job/detective/proc/EclipseStationChanges() diff --git a/code/modules/jobs/job_types/geneticist.dm b/code/modules/jobs/job_types/geneticist.dm index dc306bb16b70..b7ab910685a0 100644 --- a/code/modules/jobs/job_types/geneticist.dm +++ b/code/modules/jobs/job_types/geneticist.dm @@ -21,6 +21,10 @@ display_order = JOB_DISPLAY_ORDER_GENETICIST + mail_goodies = list( + /obj/item/storage/box/monkeycubes = 10 + ) + changed_maps = list("OmegaStation", "EclipseStation") /datum/job/geneticist/proc/OmegaStationChanges() diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm index 360e1a5eca7b..abb64293c8f8 100644 --- a/code/modules/jobs/job_types/head_of_personnel.dm +++ b/code/modules/jobs/job_types/head_of_personnel.dm @@ -40,10 +40,23 @@ changed_maps = list("OmegaStation") + mail_goodies = list( + /obj/item/card/id/silver = 10, + /obj/item/stack/sheet/bone = 5 + ) + /datum/job/hop/proc/OmegaStationChanges() access = get_all_accesses() minimal_access = get_all_accesses() +//only pet worth reviving +/datum/job/hop/get_mail_goodies(mob/recipient) + . = ..() + // Strange Reagent if the pet is dead. + for(var/mob/living/simple_animal/pet/dog/corgi/Ian/staff_pet in GLOB.dead_mob_list) + . += list(/datum/reagent/medicine/strange_reagent = 20) + break + /datum/outfit/job/hop name = "Head of Personnel" jobtype = /datum/job/hop diff --git a/code/modules/jobs/job_types/janitor.dm b/code/modules/jobs/job_types/janitor.dm index 1ad1521c74e6..f59e7589f87b 100644 --- a/code/modules/jobs/job_types/janitor.dm +++ b/code/modules/jobs/job_types/janitor.dm @@ -22,6 +22,12 @@ changed_maps = list("OmegaStation", "EclipseStation") + mail_goodies = list( + /obj/item/grenade/chem_grenade/cleaner = 30, + /obj/item/storage/box/lights/mixed = 20, + /obj/item/lightreplacer = 10 + ) + /datum/job/janitor/proc/OmegaStationChanges() access = list(ACCESS_JANITOR, ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS) minimal_access = list(ACCESS_JANITOR, ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS) diff --git a/code/modules/jobs/job_types/medical_doctor.dm b/code/modules/jobs/job_types/medical_doctor.dm index fe16b429edc1..72667718caa6 100644 --- a/code/modules/jobs/job_types/medical_doctor.dm +++ b/code/modules/jobs/job_types/medical_doctor.dm @@ -23,6 +23,16 @@ changed_maps = list("EclipseStation", "OmegaStation") + mail_goodies = list( + /obj/item/healthanalyzer/advanced = 15, + /obj/item/scalpel/advanced = 6, + /obj/item/retractor/advanced = 6, + /obj/item/cautery/advanced = 6, + /obj/item/reagent_containers/glass/bottle/formaldehyde = 6, + /obj/effect/spawner/lootdrop/organ_spawner = 5 + ///obj/effect/spawner/random/medical/memeorgans = 1 + ) + /datum/job/doctor/proc/EclipseStationChanges() total_positions = 6 spawn_positions = 5 diff --git a/code/modules/jobs/job_types/mime.dm b/code/modules/jobs/job_types/mime.dm index 9ef61ae72d5b..2a853a4928a8 100644 --- a/code/modules/jobs/job_types/mime.dm +++ b/code/modules/jobs/job_types/mime.dm @@ -20,6 +20,13 @@ display_order = JOB_DISPLAY_ORDER_MIME + mail_goodies = list( + /obj/item/reagent_containers/food/snacks/baguette = 15, + /obj/item/reagent_containers/food/snacks/store/cheesewheel = 10, + /obj/item/reagent_containers/food/drinks/bottle/bottleofnothing = 10, + /obj/item/book/mimery = 1, + ) + /datum/job/mime/after_spawn(mob/living/carbon/human/H, mob/M) H.apply_pref_name("mime", M.client) diff --git a/code/modules/jobs/job_types/quartermaster.dm b/code/modules/jobs/job_types/quartermaster.dm index 194c35926270..dad66ad3a0f0 100644 --- a/code/modules/jobs/job_types/quartermaster.dm +++ b/code/modules/jobs/job_types/quartermaster.dm @@ -22,6 +22,10 @@ changed_maps = list("OmegaStation") + mail_goodies = list( + /obj/item/circuitboard/machine/emitter = 3 + ) + /datum/job/qm/proc/OmegaStationChanges() return TRUE diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm index 5059d98b01a1..0ffec56997fd 100644 --- a/code/modules/jobs/job_types/research_director.dm +++ b/code/modules/jobs/job_types/research_director.dm @@ -37,6 +37,12 @@ changed_maps = list("OmegaStation") + mail_goodies = list( + /obj/item/storage/box/monkeycubes = 30, + ///obj/item/circuitboard/machine/sleeper/party = 3, + /obj/item/borg/upgrade/ai = 2 + ) + /datum/job/rd/proc/OmegaStationChanges() return TRUE diff --git a/code/modules/jobs/job_types/roboticist.dm b/code/modules/jobs/job_types/roboticist.dm index 5dacf5f61f25..f00f025c1ee7 100644 --- a/code/modules/jobs/job_types/roboticist.dm +++ b/code/modules/jobs/job_types/roboticist.dm @@ -23,6 +23,12 @@ changed_maps = list("OmegaStation") + mail_goodies = list( + /obj/item/storage/box/flashes = 20, + /obj/item/stack/sheet/metal/twenty = 15, + /obj/item/modular_computer/tablet/preset/advanced = 5 + ) + /datum/job/roboticist/proc/OmegaStationChanges() supervisors = "the captain and the head of personnel" diff --git a/code/modules/jobs/job_types/scientist.dm b/code/modules/jobs/job_types/scientist.dm index ad2b55c088e1..190d23eb3063 100644 --- a/code/modules/jobs/job_types/scientist.dm +++ b/code/modules/jobs/job_types/scientist.dm @@ -23,6 +23,12 @@ changed_maps = list("EclipseStation", "OmegaStation") + mail_goodies = list( + ///obj/item/raw_anomaly_core/random = 10, + ///obj/item/disk/tech_disk/spaceloot = 2, + /obj/item/camera_bug = 1 + ) + /datum/job/scientist/proc/EclipseStationChanges() total_positions = 6 spawn_positions = 5 diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm index b6db42902600..9947a0c656e5 100644 --- a/code/modules/jobs/job_types/security_officer.dm +++ b/code/modules/jobs/job_types/security_officer.dm @@ -27,6 +27,14 @@ changed_maps = list("EclipseStation", "YogsPubby", "OmegaStation") + mail_goodies = list( + /obj/item/reagent_containers/food/snacks/donut/jelly = 10, + /obj/item/reagent_containers/food/snacks/donut/meat = 10, + /obj/item/reagent_containers/food/snacks/donut/spaghetti = 5 + ///obj/item/clothing/mask/whistle = 5, + ///obj/item/melee/baton/security/boomerang/loaded = 1 + ) + /datum/job/officer/proc/EclipseStationChanges() total_positions = 14 spawn_positions = 10 diff --git a/code/modules/jobs/job_types/station_engineer.dm b/code/modules/jobs/job_types/station_engineer.dm index 24ab3ae55c77..fa1876f53a92 100644 --- a/code/modules/jobs/job_types/station_engineer.dm +++ b/code/modules/jobs/job_types/station_engineer.dm @@ -25,6 +25,13 @@ changed_maps = list("EclipseStation", "OmegaStation") + mail_goodies = list( + /obj/item/storage/box/lights/mixed = 20, + /obj/item/lightreplacer = 10, + /obj/item/holosign_creator/engineering = 8, + /obj/item/clothing/head/hardhat/red/upgraded = 1 + ) + /datum/job/engineer/proc/EclipseStationChanges() total_positions = 6 spawn_positions = 5 diff --git a/code/modules/jobs/job_types/virologist.dm b/code/modules/jobs/job_types/virologist.dm index aec2e2868f64..20290516131f 100644 --- a/code/modules/jobs/job_types/virologist.dm +++ b/code/modules/jobs/job_types/virologist.dm @@ -25,6 +25,14 @@ changed_maps = list("OmegaStation") + mail_goodies = list( + /obj/item/reagent_containers/glass/bottle/random_virus = 15, + /obj/item/reagent_containers/glass/bottle/formaldehyde = 10, + /obj/item/reagent_containers/glass/bottle/synaptizine = 10, + /obj/item/stack/sheet/mineral/plasma = 10, + /obj/item/stack/sheet/mineral/uranium = 5, + ) + /datum/job/virologist/proc/OmegaStationChanges() return TRUE diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm index 85e36ac9ed29..1728d7ad87e5 100644 --- a/code/modules/jobs/job_types/warden.dm +++ b/code/modules/jobs/job_types/warden.dm @@ -28,6 +28,15 @@ changed_maps = list("YogsPubby", "OmegaStation") + mail_goodies = list( + /obj/item/storage/box/fancy/cigarettes = 15, + /obj/item/storage/box/handcuffs = 10, + /obj/item/storage/box/teargas = 10, + /obj/item/storage/box/flashbangs = 10, + /obj/item/storage/box/rubbershot = 10, + /obj/item/storage/box/lethalshot = 5 + ) + /datum/job/warden/proc/YogsPubbyChanges() access += ACCESS_CREMATORIUM minimal_access += ACCESS_CREMATORIUM diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm index 891f2d247526..3f65e6446518 100644 --- a/code/modules/reagents/reagent_containers/bottle.dm +++ b/code/modules/reagents/reagent_containers/bottle.dm @@ -457,3 +457,36 @@ name = "Flu virion culture vial" desc = "A small vial for holding small amounts of reagents. Contains H13N1 flu virion culture in synthblood medium." spawned_disease = /datum/disease/advance/flu + + +// 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/recycling/disposal/holder.dm b/code/modules/recycling/disposal/holder.dm index efa8d9a5e3a8..bcde0f844c4c 100644 --- a/code/modules/recycling/disposal/holder.dm +++ b/code/modules/recycling/disposal/holder.dm @@ -41,21 +41,15 @@ // now everything inside the disposal gets put into the holder // note AM since can contain mobs or objs for(var/A in D) - var/atom/movable/AM = A - if(AM == src) + var/atom/movable/atom_in_transit = A + if(atom_in_transit == src) continue - SEND_SIGNAL(AM, COMSIG_MOVABLE_DISPOSING, src, D) - AM.forceMove(src) - if(istype(AM, /obj/structure/bigDelivery) && !hasmob) - var/obj/structure/bigDelivery/T = AM - src.destinationTag = T.sortTag - else if(istype(AM, /obj/item/smallDelivery) && !hasmob) - var/obj/item/smallDelivery/T = AM - src.destinationTag = T.sortTag - else if(istype(AM, /mob/living/silicon/robot)) - var/obj/item/destTagger/borg/tagger = locate() in AM - if (tagger) - src.destinationTag = tagger.currTag + SEND_SIGNAL(atom_in_transit, COMSIG_MOVABLE_DISPOSING, src, D, hasmob) + atom_in_transit.forceMove(src) + if(iscyborg(atom_in_transit)) + var/obj/item/destTagger/borg/tagger = locate() in atom_in_transit + if(tagger) + destinationTag = tagger.currTag // start the movement process diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index 60616cf5e7ad..b05c5b758db9 100644 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -8,6 +8,10 @@ var/giftwrapped = FALSE var/sortTag = 0 +/obj/structure/bigDelivery/Initialize() + . = ..() + RegisterSignal(src, COMSIG_MOVABLE_DISPOSING, .proc/disposal_handling) + /obj/structure/bigDelivery/interact(mob/user) playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1) qdel(src) @@ -79,6 +83,9 @@ if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded. to_chat(user, span_warning("You fail to remove [O]'s wrapping!")) +/obj/structure/bigDelivery/proc/disposal_handling(disposal_source, obj/structure/disposalholder/disposal_holder, obj/machinery/disposal/disposal_machine, hasmob) + if(!hasmob) + disposal_holder.destinationTag = sortTag /obj/item/smallDelivery name = "parcel" @@ -89,6 +96,14 @@ var/giftwrapped = 0 var/sortTag = 0 +/obj/item/smallDelivery/Initialize() + . = ..() + RegisterSignal(src, COMSIG_MOVABLE_DISPOSING, .proc/disposal_handling) + +/obj/item/smallDelivery/proc/disposal_handling(disposal_source, obj/structure/disposalholder/disposal_holder, obj/machinery/disposal/disposal_machine, hasmob) + if(!hasmob) + disposal_holder.destinationTag = sortTag + /obj/item/smallDelivery/contents_explosion(severity, target) for(var/thing in contents) switch(severity) diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index 195eab781672..6e2a14607135 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -22,6 +22,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( /obj/machinery/autolathe, //same /obj/item/projectile/beam/wormhole, /obj/effect/portal, + /obj/item/mail, /obj/item/shared_storage, /obj/structure/extraction_point, /obj/machinery/syndicatebomb, @@ -73,6 +74,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( /obj/docking_port/mobile/supply/initiate_docking() if(getDockedId() == "supply_away") // Buy when we leave home. buy() + create_mail() . = ..() // Fly/enter transit. if(. != DOCKING_SUCCESS) return @@ -197,3 +199,23 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( SSshuttle.centcom_message = msg investigate_log("Shuttle contents sold for [D.account_balance - presale_points] credits. Contents: [ex.exported_atoms ? ex.exported_atoms.Join(",") + "." : "none."] Message: [SSshuttle.centcom_message || "none."]", INVESTIGATE_CARGO) + +/* + Generates a box of mail depending on our exports and imports. + Applied in the cargo shuttle sending/arriving, by building the crate if the round is ready to introduce mail based on the economy subsystem. + Then, fills the mail crate with mail, by picking applicable crew who can recieve mail at the time to sending. +*/ +/obj/docking_port/mobile/supply/proc/create_mail() + //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) + var/area/shuttle/shuttle_area = place + for(var/turf/open/floor/shuttle_floor in shuttle_area) + if(is_blocked_turf(shuttle_floor)) + continue + empty_turfs += shuttle_floor + + new /obj/structure/closet/crate/mail/economy(pick(empty_turfs)) \ No newline at end of file diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi index 98fe0024c4df..e6d8f1b8ec87 100644 Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index 3798b1ad7a1c..cc83a3d7bafb 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/crates.dmi b/icons/obj/crates.dmi index d2c7ba8ad73a..650e693438a3 100644 Binary files a/icons/obj/crates.dmi and b/icons/obj/crates.dmi differ diff --git a/strings/junkmail.txt b/strings/junkmail.txt new file mode 100644 index 000000000000..db916907d8aa --- /dev/null +++ b/strings/junkmail.txt @@ -0,0 +1,14 @@ +Hello! I am executive at Nanotrasen Nigel Takall. Due to accounting error all of my salary is stored in an account unreachable. In order to withdraw I am required to utilize your account to make a deposit to confirm my reality situation. In exchange for a temporary deposit I will give you a payment 1000 credits. All I need is access to your account. Will you be assistant please? +WE NEED YOUR BLOOD! WE ARE AN ANARCHO-COMMUNIST VAMPIRE COMMUNE. BLOOD ONLY LASTS 42 DAYS BEFORE IT GOES BAD! WE DO NOT HAVE NANOTRASEN STASIS! PLEASE, SEND BLOOD! THANK YOU! OR WE KILL YOU! +Triple deposits are waiting for you at MaxBet Online when you register to play with us. You can qualify for a 200% Welcome Bonus at MaxBet Online when you sign up today. Once you are a player with MaxBet, you will also receive lucrative weekly and monthly promotions. You will be able to enjoy over 450 top-flight casino games at MaxBet. +Hello !, I'm the former HoS of your deerest station accused by the Nanotrasen of being a traitor . I was the best we had to offer but it seems that nanotramsen has turned their back on me. I need 2000 credits to pay for my bail and then we can restore order on space station 14! +Hello, I noticed you riding in a 2555 Ripley and wondered if you'd be interested in selling. Low mileage mechs sell very well in our current market. Please call 223-334-3245 if you're interested +Resign Now. I’m on you now. You are fucking with me now Let’s see who you are. Watch your back , bitch. Call me. Don’t be afraid, you piece of shit. Stand up. If you don’t call, you’re just afraid. And later: I already know where you live, I’m on you. You might as well call me. You will see me. I promise. Bro. +Clown Planet Is Going To Become Awesome Possum Again! If This Wasn't Sent To A Clown, Disregard. If This Was Sent To A Mime, Blow It Out Your Ass, Space Frenchie! Anyway! We Make Big Progress On Clown Planet After Stupid Mimes BLOW IT ALL TO SAM HELL!!!!! Sorry I Am Mad.. Anyway Come And Visit, Honkles! We Thought You Were Dead Long Time :^() +MONTHPEOPLE ARE REAL, THE NANOTRASEN DEEP STATE DOESN'T WANT YOU TO SEE THIS! I'VE SEEN THEM IN REAL LIFE, THEY HAVE HUGE EYEBALLS AND NO HEAD. THEY'RE SENTIENT CALENDARS. I'M NOT CRAZY. SEARCH THE CALENDAR INCIDENT ON NTNET. USE A PROXY! #BIGTRUTHS #WAKEYWAKEYSPACEMEN #21STOFSEPTEMBER +hello 👋👋 nanotrasens! fuck 👈👌 the syndicate! they 👵 got ☄ me 😍😰 questioning my 🤰 loyalty to nanotraben! so 👌💯 please 😫 lets ⛔👀 gather our 📸💩 energy 😎 and 💰🔣 QUICK. 😲 send this 🗑👈 to 💦💊 10 😂😂 other loyal 💯 nanotraysens to 💦🤔 show we 🐶 dont 🙅🚫 take 🛍 nothing from 😂 the ✝ syndicate!! bless your 👉🏼 heart 😍💔 +Hello, my name is Immigration officer Mimi Sashimi from the American-Felinid Homeworld consulate. It appears your current documents are either inaccurate if not entirely fraudulent. This action in it's current state is a federal offense as listed in the United Earth Commission charter section NY-4. Please pay a fine of 300,000 Space credits or $3000 United States Dollars or face deportation +Hi %name%, We are unable to validate your billing information for the next billing cycle of your subscription to HONK Weekly therefore we'll suspend your membership if we do not receive a response from you within 48 hours. Obviously we'd love to have you back, simply mail %address% to update your details and continue to enjoy all the best pranks & gags without interruption. +Loyal customer, DonkCo Customer Service. We appreciate your brand loyalty support. As such, it is our responsibility and pleasure to inform you of the status of your package. Your package for one "Moth-Fuzz Parka" has been delayed. Due to local political tensions, an animal rights group has seized and eaten your package. We appreciate the patience, DonkCo +MESSAGE FROM CENTCOM HIGH COMMAND: DO NOT ACCEPT THE FRIEND REQUEST OF TICKLEBALLS THE CLOWN. HE IS NOT FUNNY AND ON TOP OF THAT HE WILL HACK YOUR NTNET ACCOUNT AND MAKE YOU UNFUNNY TOO. YOU WILL LOSE ALL YOUR SPACECREDITS!!!!! SPREAD THE WORD. ANYONE WHO BECOMES FRIENDS WITH TINKLEBALLS THE CLOWN IS GOING TO LOSE ALL OF THEIR SPACECREDITS AND LOOK LIKE A HUGE IDIOT. +i WAS A NORMAL BOY AND I CAME HOME FROM SCHOOL AND I WANTED TO PLAY SOME ORION TRAIL WHICH IS A VERY FUN GAME BUT WHEN WENT TO ARCADE MACHINE SOMETHING WAS WEIRD TEH LOGO HASD BLOD IN IT AND I BECAME VERY SCARE AND I CHECK OPTIONS AND TEHRES ONLY 1 "GO BACK" I CKLICK IT AND I SEE CHAT SI EMPTY THERE'S ONLY ONE CHARACTER CALLED "CLOSE TEH GAME " AND I GO TO ANOTHER MACHINE AND PLAY THERE BUT WHEN I PLAY GAME IS FULL OF BLOOD AND DEAD BODIES FROM SPACEMAN LOOK CLOSER AND SEE CLOWN AND CLOWN COMES CLOSER AND LOOKS AT ME AND SAYS "DON'T SAY I DIKDNT' WWARN YOU" AND CLOWN CLOSEUP APPEARS WITH BLOOD-RED HYPERREALISTIC EYES AND HE TELLS ME "YOU WILL BE THE NEXT ONE" AND ARCADE MACHINE POWER SHUT OFF AND THAT NITE CLOWN APPEAR AT MY WINDOW AND KILL ME AT 3 AM AND NOW IM DEAD AND YOU WILL BE TRHNE NEXT OEN UNLESS YOU PASTE THIS STORY TO 10 NTNET FRIENDS diff --git a/yogstation.dme b/yogstation.dme index a191936836b9..ccc5ceb4489b 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -966,6 +966,7 @@ #include "code\game\objects\items\inducer.dm" #include "code\game\objects\items\kitchen.dm" #include "code\game\objects\items\latexballoon.dm" +#include "code\game\objects\items\mail.dm" #include "code\game\objects\items\mantis.dm" #include "code\game\objects\items\manuals.dm" #include "code\game\objects\items\miscellaneous.dm"