diff --git a/code/__defines/_reagents.dm b/code/__defines/_reagents.dm index 29d652daa74..bb5da52505c 100644 --- a/code/__defines/_reagents.dm +++ b/code/__defines/_reagents.dm @@ -681,6 +681,8 @@ #define REAGENT_ID_CAPSAICIN "capsaicin" #define REAGENT_CONDENSEDCAPSAICIN "Condensed Capsaicin" #define REAGENT_ID_CONDENSEDCAPSAICIN "condensedcapsaicin" +#define REAGENT_GELATIN "Gelatin" +#define REAGENT_ID_GELATIN "gelatin" #define REAGENT_DRINK "Drink" #define REAGENT_ID_DRINK "drink" @@ -1244,7 +1246,8 @@ #define REAGENT_ID_KOMPOT "kompot" #define REAGENT_KVASS "Kvass" #define REAGENT_ID_KVASS "kvass" - +#define REAGENT_CINNAMONPOWDER "Cinnamon powder" +#define REAGENT_ID_CINNAMONPOWDER "cinnamonpowder" // Toxins #define REAGENT_TOXIN "Toxin" diff --git a/code/__defines/jobs.dm b/code/__defines/jobs.dm index a4560b36dff..5d68cd30113 100644 --- a/code/__defines/jobs.dm +++ b/code/__defines/jobs.dm @@ -107,6 +107,7 @@ #define JOB_ALT_CARGO_HANDLER "Cargo Handler" #define JOB_ALT_SUPPLY_COURIER "Supply Courier" #define JOB_ALT_DISPOSALS_SORTER "Disposals Sorter" + #define JOB_ALT_MAILMAN "Mailman" #define JOB_SHAFT_MINER "Shaft Miner" // Shaft Miner alt titles diff --git a/code/controllers/subsystems/mail.dm b/code/controllers/subsystems/mail.dm new file mode 100644 index 00000000000..d2b5ce84ffd --- /dev/null +++ b/code/controllers/subsystems/mail.dm @@ -0,0 +1,52 @@ +SUBSYSTEM_DEF(mail) + name = "Mail" + wait = 60 SECONDS + priority = FIRE_PRIORITY_SUPPLY + + flags = SS_NO_TICK_CHECK | SS_NO_INIT + + var/mail_waiting = 0 // Pending mail + var/mail_per_process = 0.55 // Mail to be generated + var/admin_mail = list() // Mail added by Spawn Mail + +/datum/controller/subsystem/mail/fire() + mail_waiting += mail_per_process + +/* Generates a box of mail. Depending on the time that has passed between shuttles being called, it will send more or less mail and dependant on a small random number to simulate inflation + Whenever the cargo shuttle gets sent back to the station, it will add the mail crate if there's any mail to be sent to the station. + + Only alive, active and NT employeers should be getting mail. +*/ + +/datum/controller/subsystem/mail/proc/create_mail() + // Spawn crate + var/obj/structure/closet/crate/mail/mailcrate = new(pick(SSsupply.get_clear_turfs())) + // Collect recipients + var/list/mail_recipients = list() + for(var/mob/living/carbon/human/player_human in player_list) + if(player_human.stat != DEAD && player_human.client && player_human.client.inactivity <= 10 MINUTES && !player_is_antag(player_human.mind)) // Only alive, active and NT employeers should be getting mail. + mail_recipients += player_human + + // Creates mail for all the mail waiting to arrive, if there's nobody to receive it, it will be a chance of junk mail. + for(var/mail_iterator in 1 to mail_waiting) + if(!mail_recipients.len && prob(60)) // Oh, no mail for our Employees? Well don't just sent them all the junk. + continue + var/obj/item/mail/new_mail + if(prob(70)) + 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() + // Admin mail + if(admin_mail) + for(var/obj/item/mail/ad_mail in admin_mail) + ad_mail.loc = mailcrate + clearlist(admin_mail) + mail_waiting = 0 + return mailcrate diff --git a/code/datums/outfits/jobs/cargo.dm b/code/datums/outfits/jobs/cargo.dm index bed1308f398..8bfb269012a 100644 --- a/code/datums/outfits/jobs/cargo.dm +++ b/code/datums/outfits/jobs/cargo.dm @@ -37,3 +37,10 @@ headset = /obj/item/radio/headset/miner headset_alt = /obj/item/radio/headset/miner headset_earbud = /obj/item/radio/headset/miner + +/decl/hierarchy/outfit/job/cargo/cargo_tech/mailman + name = OUTFIT_JOB_NAME(JOB_ALT_MAILMAN) + uniform = /obj/item/clothing/under/rank/mailman2 + head = /obj/item/clothing/head/mailman2 + pda_slot = slot_l_store + backpack_contents = list(/obj/item/storage/bag/mail = 1, /obj/item/mail_scanner = 1) diff --git a/code/datums/supplypacks/supply.dm b/code/datums/supplypacks/supply.dm index a0b818d0b26..40e166a4f63 100644 --- a/code/datums/supplypacks/supply.dm +++ b/code/datums/supplypacks/supply.dm @@ -258,3 +258,16 @@ containertype = /obj/structure/closet/crate/secure/xion containername = JOB_PATHFINDER + " equipment" access = list(access_explorer) + +/datum/supply_pack/supply/postal_service + name = "Postal Service Supplies" + contains = list( + /obj/item/mail/blank = 10, + /obj/item/pen/fountain, + /obj/item/pen/multi, + /obj/item/destTagger, + /obj/item/storage/bag/mail + ) + cost = 15 + containertype = /obj/structure/closet/crate/nanotrasen + containername = "Postal Service crate" diff --git a/code/game/jobs/job/_alt_title.dm b/code/game/jobs/job/_alt_title.dm index 1cb7fde6b6c..7a1b75c7ab8 100644 --- a/code/game/jobs/job/_alt_title.dm +++ b/code/game/jobs/job/_alt_title.dm @@ -5,4 +5,6 @@ /datum/alt_title var/title = "GENERIC ALT TITLE" // What the Alt-Title is called var/title_blurb = null // What's amended to the job description for this Job title. If nothing's added, leave null. - var/title_outfit = null // The outfit used by the alt-title. If it's the same as the base job, leave this null. \ No newline at end of file + var/title_outfit = null // The outfit used by the alt-title. If it's the same as the base job, leave this null. + var/list/mail_goodies = null + var/exclusive_mail_goodies = FALSE diff --git a/code/game/jobs/job/cargo.dm b/code/game/jobs/job/cargo.dm index ad56749de66..7ab0f66e027 100644 --- a/code/game/jobs/job/cargo.dm +++ b/code/game/jobs/job/cargo.dm @@ -62,7 +62,7 @@ because Central Command gives a partial refund." alt_titles = list(JOB_ALT_CARGO_LOADER = /datum/alt_title/cargo_loader, JOB_ALT_CARGO_HANDLER = /datum/alt_title/cargo_handler, JOB_ALT_SUPPLY_COURIER = /datum/alt_title/supply_courier, - JOB_ALT_DISPOSALS_SORTER = /datum/alt_title/disposal_sorter) + JOB_ALT_DISPOSALS_SORTER = /datum/alt_title/disposal_sorter, JOB_ALT_MAILMAN = /datum/alt_title/mailman) /datum/alt_title/supply_courier title = JOB_ALT_SUPPLY_COURIER @@ -80,6 +80,11 @@ title = JOB_ALT_DISPOSALS_SORTER title_blurb = "A " + JOB_ALT_DISPOSALS_SORTER + " is usually tasked with operating disposals delivery system, sorting the trash and tagging parcels for delivery." +/datum/alt_title/mailman + title = JOB_ALT_MAILMAN + title_blurb = "A Mail Carrier is tasked with delivering packages or mail to whoever it might adress." + title_outfit = /decl/hierarchy/outfit/job/cargo/cargo_tech/mailman + ////////////////////////////////// // Shaft Miner ////////////////////////////////// diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index d01d60e4be9..70ef6a26cda 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -62,6 +62,10 @@ var/requestable = TRUE + VAR_PROTECTED/list/mail_goodies = null // Goodies that can be received via the mail system + VAR_PROTECTED/exclusive_mail_goodies = FALSE // If this job's mail goodies compete with generic goodies. + VAR_PROTECTED/mail_color = "#FFF" + /datum/job/New() . = ..() department_accounts = department_accounts || departments_managed diff --git a/code/game/jobs/job/job_goodies.dm b/code/game/jobs/job/job_goodies.dm new file mode 100644 index 00000000000..7b44ec299e7 --- /dev/null +++ b/code/game/jobs/job/job_goodies.dm @@ -0,0 +1,706 @@ +// Get mail goodies +/datum/job/proc/get_mail_goodies(mob/recipient) + return mail_goodies + +// Get mail colour +/datum/job/proc/get_mail_color(mob/recipient) + return mail_color + +// Assistant + +/datum/job/intern + mail_goodies = list( + /obj/item/cell/device = 200, + /obj/item/cell = 175, + /obj/item/storage/belt/utility = 150, + /obj/item/cell/high = 125, + /obj/item/tool/wrench = 125, + /obj/item/tool/screwdriver = 125, + /obj/item/cell/device/hyper = 50, + /obj/item/cell/hyper = 50, + ) + mail_color = COMMS_COLOR_ENTERTAIN + +/datum/alt_title/intern_eng + mail_goodies = list( + /obj/item/cell/device = 200, + /obj/item/cell = 175, + /obj/item/storage/belt/utility = 150, + /obj/item/cell/high = 125, + /obj/item/tool/wrench = 125, + /obj/item/tool/screwdriver = 125, + /obj/item/geiger = 100 + ) + +/datum/alt_title/intern_med + mail_goodies = list( + /obj/item/reagent_containers/hypospray/autoinjector/burn = 200, + /obj/item/reagent_containers/hypospray/autoinjector/trauma = 200, + /obj/item/reagent_containers/hypospray/autoinjector/detox = 200, + /obj/item/stack/medical/ointment = 100, + /obj/item/stack/medical/bruise_pack = 100, + /obj/item/storage/pill_bottle/paracetamol = 100, + /obj/item/storage/pill_bottle/blood_regen = 50, + /obj/item/storage/pill_bottle/assorted = 50, + ) + +/datum/alt_title/intern_sci + mail_goodies = list( + /obj/item/cell/device = 200, + /obj/item/cell = 175, + /obj/item/storage/belt/utility = 150, + /obj/item/cell/high = 125, + /obj/item/tool/wrench = 125, + /obj/item/tool/screwdriver = 125, + /obj/item/cell/device/hyper = 50, + /obj/item/cell/hyper = 50, + ) + +/datum/alt_title/intern_sec + mail_goodies = list( + /obj/item/reagent_containers/food/snacks/donut/plain = 200, + /obj/item/poster/custom = 200, + /obj/item/ticket_printer = 200, + /obj/item/holowarrant = 200, + /obj/item/retail_scanner/security = 100, + /obj/item/taperoll/police = 100 + ) + +/datum/alt_title/intern_crg + mail_goodies = list( + /obj/item/wrapping_paper = 200, + /obj/item/form_printer = 200, + /obj/item/poster/custom = 200, + /obj/item/stack/material/wood{amount = 10} = 100, + /obj/item/stack/material/steel{amount = 10} = 100, + /obj/item/pickaxe = 100, + /obj/item/stack/marker_beacon = 100, + ) + +/datum/alt_title/intern_exp + mail_goodies = list( + /obj/item/storage/mre/menu2 = 800, + /obj/item/binoculars/spyglass = 150, + /obj/item/cell/device/hyper = 50, + ) + +/datum/alt_title/server + mail_goodies = list( + /obj/item/tray = 200, + /obj/item/material/kitchen/utensil/fork = 200, + /obj/item/material/knife/plastic = 200, + /obj/item/reagent_containers/food/snacks/tofu = 200, + /obj/item/reagent_containers/food/snacks/candy_corn = 200, + ) + +/datum/alt_title/assistant + +// Visitor + +/datum/job/assistant + +/datum/alt_title/guest + +/datum/alt_title/traveler + +// Cargo + +/datum/job/qm + mail_goodies = list( + /obj/item/stack/material/plasteel{amount = 10} = 125, + /obj/item/stack/material/marble{amount = 10} = 125, + /obj/item/stack/material/wood{amount = 10} = 125, + /obj/item/stack/material/steel{amount = 10} = 125, + /obj/item/stack/material/glass{amount = 10} = 125, + /obj/item/coin/silver = 100, + /obj/item/pen/fountain8 = 100, + /obj/item/stack/material/durasteel{amount = 5} = 75, + /obj/item/stack/material/diamond{amount = 3} = 75, + /obj/item/toy/plushie/borgplushie/drake/mine = 25, + ) + mail_color = COMMS_COLOR_SUPPLY + +/datum/job/cargo_tech + mail_goodies = list( + /obj/item/pizzavoucher = 375, + /obj/item/poster/custom = 200, + /obj/item/stack/material/steel{amount = 10} = 150, + /obj/item/stack/material/glass{amount = 10} = 150, + /obj/item/stack/material/wood{amount = 10} = 150, + /obj/item/coin/silver = 50 + ) + mail_color = COMMS_COLOR_SUPPLY + +/datum/alt_title/disposal_sorter + mail_goodies = list( + /obj/item/clothing/gloves/black = 300, + /obj/item/reagent_containers/spray/sterilizine = 300, + /obj/item/storage/bag/trash = 300, + /obj/item/coin/silver = 80, + /obj/item/storage/bag/trash/holding = 20 + ) + +/datum/alt_title/mailman + mail_goodies = list( + /obj/item/poster/custom = 300, + /obj/item/wrapping_paper = 300, + /obj/item/pizzavoucher = 300, + /obj/item/coin/silver = 100, + ) + +/datum/job/mining + mail_goodies = list( + /obj/item/plastique/seismic/locked = 150, + /obj/item/stack/marker_beacon/ten = 150, + /obj/item/pickaxe/diamond = 125, + /obj/item/perfect_tele/one_beacon = 125, + /obj/item/clothing/shoes/bhop = 125, + /obj/item/inducer = 125, + /obj/item/pickaxe/advdrill = 100, + /obj/item/storage/bag/ore/holding = 100 + ) + mail_color = COMMS_COLOR_SUPPLY + +/datum/alt_title/drill_tech + mail_goodies = list( + /obj/item/stack/marker_beacon/ten = 250, + /obj/item/perfect_tele/one_beacon = 125, + /obj/item/clothing/shoes/bhop = 125, + /obj/item/inducer = 125, + /obj/item/stock_parts/manipulator/nano = 50, + /obj/item/stock_parts/capacitor/adv = 50, + /obj/item/stock_parts/scanning_module/adv = 50, + /obj/item/stock_parts/micro_laser/high = 50, + /obj/item/stock_parts/matter_bin/super = 10, + /obj/item/stock_parts/manipulator/pico = 10, + /obj/item/stock_parts/capacitor/super = 10, + /obj/item/stock_parts/scanning_module/phasic = 10, + /obj/item/stock_parts/micro_laser/ultra = 10 + ) + +// Civilian + +/datum/job/bartender + mail_goodies = list( + /obj/item/reagent_containers/food/drinks/metaglass/metapint = 300, + /obj/item/reagent_containers/glass/bottle/nothing = 250, + /obj/item/reagent_containers/glass/bottle/gelatin = 250, + /obj/item/stack/material/uranium = 150, + /obj/item/reagent_containers/chem_disp_cartridge/nothing = 25, + /obj/item/reagent_containers/chem_disp_cartridge/gelatin = 25, + ) + mail_color = COMMS_COLOR_SERVICE + +/datum/alt_title/barista + mail_goodies = list( + /obj/item/reagent_containers/food/drinks/metaglass/metapint = 300, + /obj/item/reagent_containers/glass/bottle/gelatin = 225, + /obj/item/reagent_containers/food/drinks/smallmilk = 225, + /obj/item/reagent_containers/glass/bottle/cinnamonpowder = 100, + /obj/item/reagent_containers/food/drinks/teapot = 100, + /obj/item/reagent_containers/chem_disp_cartridge/gelatin = 50, + ) + +/datum/job/chef + mail_goodies = list( + /obj/item/reagent_containers/food/condiment/soysauce = 250, + /obj/item/reagent_containers/food/drinks/smallmilk = 250, + /obj/item/reagent_containers/glass/bottle/cakebatter = 200, + /obj/item/reagent_containers/food/snacks/cuttlefish = 200, + /obj/item/reagent_containers/glass/bottle/cinnamonpowder = 100 + ) + mail_color = COMMS_COLOR_SERVICE + +/datum/job/hydro + mail_goodies = list( + /obj/item/reagent_containers/glass/bottle/eznutrient = 200, + /obj/item/reagent_containers/glass/bottle/left4zed = 200, + /obj/item/reagent_containers/glass/bottle/robustharvest = 200, + /obj/item/reagent_containers/spray/plantbgone = 150, + /obj/item/reagent_containers/glass/bottle/diethylamine = 100, + /obj/item/gun/energy/floragun = 75, + /obj/item/grenade/chem_grenade/antiweed = 75 + ) + mail_color = COMMS_COLOR_SERVICE + +/datum/job/janitor + mail_goodies = list( + /obj/item/storage/box/lights/mixed = 200, + /obj/item/reagent_containers/spray/cleaner = 200, + /obj/item/lightreplacer = 150, + /obj/item/lightpainter = 150, + /obj/item/soap = 100, + /obj/item/grenade/chem_grenade/cleaner = 100, + /obj/item/reagent_containers/spray/chemsprayer/hosed = 50, + /obj/item/storage/bag/trash/holding = 25, + /obj/item/toy/plushie/borgplushie/drake/jani = 25, + ) + mail_color = COMMS_COLOR_SERVICE + +/datum/job/librarian + mail_goodies = list( + /obj/item/form_printer = 250, + /obj/item/book/manual/wizzoffguide = 100, + /obj/item/book/bundle/custom_library/fiction/ghostship = 100, + /obj/item/book/bundle/custom_library/reference/ThermodynamicReactionsandResearch = 100, + /obj/item/book/bundle/custom_library/nonfiction/riseandfallofpersianempire = 100, + /obj/item/book/bundle/custom_library/nonfiction/skrelliancastesystem = 100, + /obj/item/book/codex/lore/robutt = 95, + /obj/item/book/codex/lore/news = 95, + /obj/item/pen/fountain3 = 50, + /obj/item/reagent_containers/food/snacks/egg = 10 + ) + mail_color = COMMS_COLOR_SERVICE + +/datum/job/lawyer + mail_goodies = list( + /obj/item/pen/fountain8 = 800, + /obj/item/form_printer = 200, + ) + mail_color = COMMS_COLOR_SERVICE + +/datum/job/chaplain + mail_goodies = list( + /obj/item/storage/fancy/candle_box = 340, + /obj/item/storage/fancy/whitecandle_box = 330, + /obj/item/storage/fancy/blackcandle_box = 330 + ) + mail_color = COMMS_COLOR_SERVICE + +/datum/job/entertainer + // These need new goodes... + mail_goodies = list( + /obj/random/instrument = 600, + /obj/item/storage/pill_bottle/dice_nerd = 400, + ) + mail_color = COMMS_COLOR_SERVICE + +/datum/alt_title/clown + mail_goodies = list( + /obj/fruitspawner/banana = 200, + /obj/item/pen/crayon/rainbow = 200, + /obj/item/bikehorn = 200, + /obj/item/soap/rainbow_soap = 100, + /obj/item/reagent_containers/spray/waterflower = 100, + /obj/item/reagent_containers/glass/bottle/lube = 100, + /obj/item/reagent_containers/food/snacks/pie = 100 + ) + +/datum/alt_title/mime + mail_goodies = list( + /obj/item/reagent_containers/food/drinks/bottle/wine = 250, + /obj/item/reagent_containers/glass/bottle/nothing = 250, + /obj/item/reagent_containers/food/snacks/baguette = 200, + /obj/item/pen/crayon/mime = 200 + ) +/datum/job/entrepreneur // Same for these guys! What could they get? + mail_goodies = list( + /obj/item/reagent_containers/food/drinks/coffee = 1000, // For now, they'll get extra on coffee. + ) + mail_color = COMMS_COLOR_SERVICE + +/datum/alt_title/paranormal_investigator + mail_goodies = list( + /obj/item/storage/fancy/candle_box = 340, + /obj/item/storage/fancy/whitecandle_box = 330, + /obj/item/storage/fancy/blackcandle_box = 330 + ) + +// Command + +/datum/job/captain + mail_goodies = list( + /obj/item/reagent_containers/food/drinks/bottle/specialwhiskey = 250, + /obj/item/reagent_containers/food/drinks/bottle/champagne = 250, + /obj/item/storage/fancy/cigar/havana = 250, + /obj/item/form_printer = 200, + /obj/item/pen/fountain6 = 50 + ) + mail_color = COMMS_COLOR_COMMAND + +/datum/job/hop + mail_goodies = list( // Need to check what these could get... + /obj/item/pen/fountain6 = 650, + /obj/item/form_printer = 200, + /obj/item/toy/figure/corgi = 150 + ) + mail_color = COMMS_COLOR_COMMAND + +/datum/job/secretary + mail_goodies = list( + /obj/item/form_printer = 225, + /obj/item/toy/figure/cmo = 175, + /obj/item/toy/figure/ce = 175, + /obj/item/toy/figure/rd = 175, + /obj/item/toy/figure/hos = 150, + /obj/item/toy/figure/hop = 125, + /obj/item/toy/figure/captain = 50, + /obj/item/pen/fountain6 = 25 + ) + mail_color = COMMS_COLOR_COMMAND + +// Engineering + +/datum/job/chief_engineer + mail_goodies = list( + /obj/item/stack/material/steel{amount = 15} = 225, + /obj/item/stack/material/lead{amount = 10} = 175, + /obj/item/stack/material/glass/reinforced{amount = 10} = 150, + /obj/item/rcd_ammo = 150, + /obj/item/stack/material/plasteel{amount = 10} = 125, + /obj/item/stack/material/phoron{amount = 5} = 100, + /obj/item/pen/fountain6 = 50, + /obj/item/toy/plushie/borgplushie/drake/eng = 25, + ) + mail_color = COMMS_COLOR_COMMAND + +/datum/job/engineer + mail_goodies = list( + /obj/item/stack/material/steel{amount = 10} = 235, + /obj/item/stack/material/lead{amount = 10} = 235, + /obj/item/stack/material/glass/reinforced{amount = 10} = 235, + /obj/item/rcd_ammo = 155, + /obj/item/stack/material/plasteel{amount = 10} = 100, + /obj/item/tool/screwdriver/power = 10, + /obj/item/tool/wirecutters/power = 10, + /obj/item/weldingtool/experimental = 10, + /obj/item/tool/wrench/power = 10, + ) + mail_color = COMMS_COLOR_ENGINEER + +/datum/alt_title/electrician + mail_goodies = list( + /obj/item/storage/box/lights/mixed = 250, + /obj/item/stack/cable_coil = 250, + /obj/item/clothing/gloves/yellow = 200, + /obj/item/stack/cable_coil/heavyduty = 210, + /obj/item/tool/screwdriver/power = 10, + /obj/item/tool/wirecutters/power = 10, + /obj/item/weldingtool/experimental = 10, + /obj/item/tool/wrench/power = 10, + ) + +/datum/job/atmos + mail_goodies = list( + /obj/item/stack/material/steel{amount = 10} = 330, + /obj/item/analyzer = 300, + /obj/item/holosign_creator/combifan = 230, + /obj/item/pipe_dispenser = 130, + /obj/item/tool/screwdriver/power = 10, + /obj/item/tool/wirecutters/power = 10, + /obj/item/weldingtool/experimental = 10, + ) + mail_color = COMMS_COLOR_ENGINEER + +// Exploration + +/datum/job/pathfinder + mail_goodies = list( + /obj/item/binoculars/spyglass = 300, + /obj/item/cataloguer/advanced = 200, + /obj/item/storage/mre/menu2 = 150, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/brute = 100, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/burn = 100, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/toxin = 100, + /obj/item/cell/device/hyper = 100, + /obj/item/flashlight/slime = 50, + ) + mail_color = "#274d0a" + +/datum/job/pilot + mail_goodies = list( + /obj/item/storage/mre/menu2 = 400, + /obj/item/tank/air = 250, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/brute = 100, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/burn = 100, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/toxin = 100, + /obj/item/cell/device/hyper = 50, + ) + mail_color = "#274d0a" + +/datum/job/explorer + mail_goodies = list( + /obj/item/storage/mre/menu2 = 500, + /obj/item/binoculars/spyglass = 150, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/brute = 100, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/burn = 100, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/toxin = 100, + /obj/item/cell/device/hyper = 50, + ) + mail_color = "#274d0a" + +/datum/job/sar + mail_goodies = list( + /obj/item/storage/mre/menu2 = 500, + /obj/item/storage/pill_bottle/antitox = 100, + /obj/item/storage/pill_bottle/dexalin_plus = 100, + /obj/item/storage/pill_bottle/kelotane = 100, + /obj/item/storage/firstaid/adv = 75, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/brute = 25, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/burn = 25, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/toxin = 25, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/purity = 10, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/pain = 10, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/organ = 10, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/combat = 5, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/clotting = 5, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/healing_nanites = 5, + /obj/item/reagent_containers/hypospray/autoinjector/bonemed = 5 + ) + mail_color = "#274d0a" + +// Medical +/datum/job/cmo + mail_goodies = list( + /obj/item/healthanalyzer/advanced = 270, + /obj/item/reagent_containers/hypospray = 250, + /obj/item/reagent_containers/blood/OMinus = 250, + /obj/item/pen/fountain6 = 75, + /obj/item/surgical/scalpel/manager = 20, + /obj/item/surgical/circular_saw/manager = 20, + /obj/item/reagent_containers/hypospray/autoinjector/bonemed = 20, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/clotting = 20, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/organ = 20, + /obj/item/toy/plushie/borgplushie/medihound = 20, + /obj/item/reagent_containers/pill/healing_nanites = 15, + ) + mail_color = COMMS_COLOR_COMMAND + +/datum/job/doctor + mail_goodies = list( + /obj/item/reagent_containers/syringe/antiviral = 200, + /obj/item/reagent_containers/spray/sterilizine = 200, + /obj/item/storage/pill_bottle/tramadol = 125, + /obj/item/storage/pill_bottle/antitox = 125, + /obj/item/reagent_containers/blood/OMinus = 125, + /obj/item/healthanalyzer/improved = 150, + /* // These will stay uncommented until we see what to do about the chems + /obj/item/storage/pill_bottle/neotane = 10, + /obj/item/storage/pill_bottle/burncard = 10, + /obj/item/storage/pill_bottle/flamecure = 10, + /obj/item/storage/pill_bottle/purifyingagent = 10, + */ + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/clotting = 10 + ) + mail_color = COMMS_COLOR_MEDICAL + +/datum/alt_title/surgeon + mail_goodies = list( + /obj/item/reagent_containers/spray/sterilizine = 300, + /obj/item/healthanalyzer/improved = 170, + /obj/item/reagent_containers/blood/OMinus = 170, + /obj/item/stack/medical/advanced/bruise_pack = 150, + /obj/item/stack/medical/advanced/ointment = 150, + /obj/item/surgical/bone_clamp = 20, + /obj/item/surgical/scalpel/manager = 20, + /obj/item/surgical/circular_saw/manager = 20, + ) + +/datum/alt_title/virologist + mail_goodies = list( + /obj/item/storage/pill_bottle/spaceacillin = 150, + /obj/item/clothing/mask/surgical = 150, + /obj/item/clothing/gloves/sterile/latex = 150, + /obj/item/reagent_containers/glass/bottle/culture/cold = 150, + /obj/item/reagent_containers/glass/bottle/culture/flu = 150, + /obj/item/reagent_containers/blood/OMinus = 100, + ) + +/datum/job/chemist + mail_goodies = list( + /obj/item/storage/pill_bottle = 235, + /obj/item/reagent_containers/glass/beaker/large = 210, + /obj/item/reagent_containers/pill/hyronalin = 210, + /obj/item/reagent_containers/pill/carthatoline = 210, + /obj/item/stack/material/phoron{amount = 5} = 120, + /obj/item/reagent_containers/pill/healing_nanites = 15 + ) + mail_color = COMMS_COLOR_MEDICAL + +/datum/job/psychiatrist + mail_goodies = list( + /obj/item/toy/plushie/carp = 225, + /obj/item/toy/plushie/blue_fox = 225, + /obj/item/toy/plushie/orange_cat = 200, + /obj/item/toy/plushie/borgplushie/drake/jani = 200, + /obj/item/toy/plushie/shark = 75, + /obj/item/storage/pill_bottle/happy = 50, + /obj/item/storage/pill_bottle/citalopram = 50 + ) + mail_color = COMMS_COLOR_MEDICAL + +/datum/job/geneticist + mail_goodies = list( + /obj/item/reagent_containers/food/snacks/monkeycube = 600, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/toxin = 200, + /obj/item/reagent_containers/hypospray/autoinjector/biginjector/purity = 200, + ) + mail_color = COMMS_COLOR_MEDICAL + + +/datum/job/paramedic + mail_goodies = list( + /obj/item/stack/medical/bruise_pack = 200, + /obj/item/stack/medical/ointment = 200, + /obj/item/stack/medical/advanced/bruise_pack = 175, + /obj/item/stack/medical/advanced/ointment = 175, + /obj/item/reagent_containers/syringe/antiviral = 100, + /obj/item/storage/pill_bottle/tramadol = 100, + /* // Commented until we know what to do with the many chomp chems + /obj/item/storage/pill_bottle/neotane = 10, + /obj/item/storage/pill_bottle/burncard = 10, + /obj/item/storage/pill_bottle/flamecure = 10, + /obj/item/storage/pill_bottle/purifyingagent = 10, + */ + /obj/item/reagent_containers/pill/myelamine = 10 + ) + mail_color = COMMS_COLOR_MEDICAL + +// Science + +/datum/job/rd + mail_goodies = list( + /obj/item/stack/material/steel{amount = 15} = 300, + /obj/item/stack/material/plasteel{amount = 10} = 250, + /obj/item/cell/super = 155, + /obj/item/cell/hyper = 125, + /obj/item/pen/fountain6 = 75, + /obj/item/toy/plushie/borgplushie/drake/sci = 20, + /obj/item/stock_parts/matter_bin/hyper = 15, + /obj/item/stock_parts/manipulator/hyper = 15, + /obj/item/stock_parts/capacitor/hyper = 15, + /obj/item/stock_parts/scanning_module/hyper = 15, + /obj/item/stock_parts/micro_laser/hyper = 15 + ) + mail_color = COMMS_COLOR_COMMAND + +/datum/job/scientist + mail_goodies = list( + /obj/item/stack/material/steel{amount = 10} = 250, + /obj/item/stack/material/glass{amount = 10} = 200, + /obj/item/cell/super = 100, + /obj/item/cell/hyper = 100, + /obj/item/stack/material/plasteel{amount = 10} = 70, + /obj/item/stock_parts/matter_bin/adv = 45, + /obj/item/stock_parts/manipulator/nano = 45, + /obj/item/stock_parts/capacitor/adv = 45, + /obj/item/stock_parts/scanning_module/adv = 45, + /obj/item/stock_parts/micro_laser/high = 45, + /obj/item/stack/nanopaste/advanced = 30, + /obj/item/stock_parts/matter_bin/super = 5, + /obj/item/stock_parts/manipulator/pico = 5, + /obj/item/stock_parts/capacitor/super = 5, + /obj/item/stock_parts/scanning_module/phasic = 5, + /obj/item/stock_parts/micro_laser/ultra = 5 + ) + mail_color = COMMS_COLOR_SCIENCE + +/datum/job/xenobiologist + mail_goodies = list( + /obj/item/reagent_containers/food/snacks/monkeycube = 780, + /obj/item/clothing/head/helmet = 100, + /obj/item/melee/baton/slime = 100, + /obj/item/xenobio/monkey_gun = 20 + ) + mail_color = COMMS_COLOR_SCIENCE + +/datum/job/roboticist + mail_goodies = list( + /obj/item/trash/rkibble = 200, + /obj/item/stack/material/steel{amount = 10} = 150, + /obj/item/robotanalyzer = 125, + /obj/item/stack/nanopaste/advanced = 85, + /obj/item/kit/paint/ripley = 55, + /obj/item/kit/paint/gygax = 55, + /obj/item/kit/paint/durand = 55, + /obj/item/kit/paint/ripley/death = 45, + /obj/item/kit/paint/durand/seraph = 45, + /obj/item/kit/paint/durand/phazon = 45, + /obj/item/kit/paint/gygax/darkgygax = 30, + /obj/item/kit/paint/ripley/flames_red = 30, + /obj/item/kit/paint/gygax/recitence = 25, + /obj/item/kit/paint/ripley/flames_blue = 25, + /obj/item/tool/screwdriver/power = 10, + /obj/item/tool/wirecutters/power = 10, + /obj/item/weldingtool/experimental = 10, + ) + mail_color = COMMS_COLOR_SCIENCE + +/datum/job/xenobotanist + mail_goodies = list( + /obj/item/reagent_containers/glass/bottle/mutagen = 350, + /obj/item/reagent_containers/glass/bottle/diethylamine = 350, + /obj/item/reagent_containers/spray/plantbgone = 150, + /obj/item/gun/energy/floragun = 100, + /obj/item/grenade/chem_grenade/antiweed = 50 + ) + mail_color = COMMS_COLOR_SCIENCE + +// Security + +/datum/job/hos + mail_goodies = list( + /obj/item/reagent_containers/food/snacks/donut/homer = 200, + /obj/item/clothing/mask/smokable/cigarette/cigar/havana = 165, + /obj/item/grenade/concussion = 150, + /obj/item/grenade/chem_grenade/teargas = 125, + /obj/item/grenade/shooter/rubber = 75, + /obj/item/storage/box/handcuffs = 75, + /obj/item/pen/fountain6 = 50, + /obj/item/ammo_magazine/ammo_box/b12g/stunshell = 50, + /obj/item/ammo_magazine/m45 = 50, + /obj/item/ammo_magazine/m9mmt = 50, + /obj/item/toy/plushie/borgplushie/drake/sec = 10 + ) + mail_color = COMMS_COLOR_COMMAND + +/datum/job/warden + mail_goodies = list( + /obj/item/reagent_containers/food/snacks/donut/homer = 250, + /obj/item/clothing/mask/smokable/cigarette/cigar/havana = 165, + /obj/item/grenade/concussion = 150, + /obj/item/grenade/chem_grenade/teargas = 150, + /obj/item/grenade/shooter/rubber = 125, + /obj/item/storage/box/handcuffs = 100, + /obj/item/ammo_magazine/ammo_box/b12g/stunshell = 20, + /obj/item/ammo_magazine/m45 = 20, + /obj/item/ammo_magazine/m9mmt = 20, + ) + mail_color = COMMS_COLOR_SECURITY + +/datum/job/detective + mail_goodies = list( + /obj/item/storage/box/matches = 200, + /obj/item/storage/fancy/cigarettes = 100, + /obj/item/reagent_containers/food/drinks/bottle/whiskey = 100, + /obj/item/storage/fancy/cigarettes/dromedaryco = 75, + /obj/item/storage/fancy/cigarettes/killthroat = 75, + /obj/item/storage/fancy/cigarettes/luckystars = 75, + /obj/item/storage/fancy/cigarettes/jerichos = 75, + /obj/item/storage/fancy/cigarettes/menthols = 75, + /obj/item/storage/fancy/cigarettes/carcinomas = 75, + /obj/item/storage/fancy/cigarettes/professionals = 75, + /obj/item/storage/fancy/cigar/havana = 25, + /obj/item/flame/lighter/supermatter/syndismzippo = 20, + /obj/item/clothing/mask/smokable/cigarette/cigar = 10, + /obj/item/clothing/mask/smokable/cigarette/cigar/cohiba = 10, + /obj/item/clothing/mask/smokable/cigarette/cigar/havana = 10 + ) + mail_color = COMMS_COLOR_SECURITY + +/datum/job/officer + mail_goodies = list( + /obj/item/reagent_containers/food/snacks/donut/olive = 175, + /obj/item/reagent_containers/food/snacks/donut/homer/jelly = 155, + /obj/item/reagent_containers/food/snacks/donut/purple = 155, + /obj/item/reagent_containers/food/snacks/donut/plain = 155, + /obj/item/handcuffs = 75, + /obj/item/hailer = 75, + /obj/item/ammo_magazine/m9mmt/rubber = 50, + /obj/item/ammo_magazine/ammo_box/b12g/beanbag = 50, + /obj/item/ammo_magazine/ammo_box/b12g = 25, + /obj/item/ammo_magazine/ammo_box/b12g/pellet = 25, + /obj/item/ammo_magazine/m45/rubber = 25, + /obj/item/ammo_magazine/m45/flash = 25, + ) + mail_color = COMMS_COLOR_SECURITY diff --git a/code/game/objects/effects/decals/contraband.dm b/code/game/objects/effects/decals/contraband.dm index f3c7027f09f..cfe48296448 100644 --- a/code/game/objects/effects/decals/contraband.dm +++ b/code/game/objects/effects/decals/contraband.dm @@ -1,4 +1,4 @@ - +/* //########################## CONTRABAND ;3333333333333333333 -Agouri ################################################### /obj/item/contraband @@ -240,3 +240,31 @@ /obj/structure/sign/poster/custom roll_type = /obj/item/contraband/poster/custom +*/ +/obj/item/contraband/package + name = "contraband" + desc = "A tightly sealed package. Dare to look inside?" + icon = 'icons/obj/storage.dmi' + icon_state = "deliverycrate5" + item_state = "table_parts" + w_class = ITEMSIZE_HUGE + +/obj/item/contraband/package/attack_self(mob/user) + var/contraband = pick( + /obj/item/reagent_containers/glass/beaker/vial/macrocillin, + /obj/item/reagent_containers/glass/beaker/vial/microcillin, + /obj/item/gun/energy/sizegun, + /obj/item/clothing/mask/muzzle, + /obj/item/pda/clown, + /obj/item/pda/mime, + /obj/item/storage/fancy/cigar/havana, + /obj/item/card/emag_broken, + /obj/item/sleevemate, + /obj/item/disk/nifsoft/compliance, + /obj/item/seeds/ambrosiadeusseed, + /obj/item/seeds/ambrosiavulgarisseed, + /obj/item/bodysnatcher) + + user.put_in_hands(new contraband(user.loc)) + to_chat(user, span_notice("You unwrap the package.")) + qdel(src) diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index 266c0c5d89c..5a622223ab9 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -219,3 +219,76 @@ return 1 else return 0 + +// Light Painter. + +/obj/item/lightpainter + name = "light painter" + desc = "A device to configure the emission color of lighting fixtures. Use this device in-hand to set/reset the color. Use the device on a light fixture to assign the color." + icon = 'icons/obj/janitor.dmi' + icon_state = "lightreplacer0" + color = "#bbbbff" + slot_flags = SLOT_BELT + + matter = list(MAT_STEEL = 5000,MAT_GLASS = 1500) + + var/static/dcolor = "#e0eff0" + var/static/dnightcolor = "#efcc86" + //set color values. + var/setcolor = "#e0eff0" + var/setnightcolor = "#efcc86" + var/resetmode = 1 + + var/dimming = 0.7 // multiply value to dim lights from setcolor to nightcolor + + +/obj/item/lightpainter/New() + . = ..() + +/obj/item/lightpainter/examine(mob/user) + . = ..() + if(get_dist(user, src) <= 2) + if(resetmode) + . += "It is currently resetting light colors." + else + . += "It is currently coloring lights." + +/obj/item/lightpainter/attack_self(mob/user) + + if(!resetmode) + resetmode = 1 + to_chat(user, span_infoplain("Painter reset.")) + else + var/color_input = tgui_color_picker(user,"","Choose Light Color",setcolor) + if(color_input) + setcolor = sanitize_hexcolor(color_input) + var/list/setcolorRGB = hex2rgb(setcolor) + var/setcolorR = num2hex(setcolorRGB[1] * dimming, 2) + var/setcolorG = num2hex(setcolorRGB[2] * dimming, 2) + var/setcolorB = num2hex(setcolorRGB[3] * dimming, 2) + setnightcolor = addtext("#", setcolorR, setcolorG, setcolorB) + resetmode = 0 + to_chat(user, span_infoplain("Painter color set.")) + + +/obj/item/lightpainter/proc/ColorLight(var/obj/machinery/light/target, var/mob/living/U) + + src.add_fingerprint(U) + + if(resetmode) + to_chat(U, span_notice("You reset the color of the [target.get_fitting_name()].")) + target.brightness_color = dcolor + target.brightness_color_ns = dnightcolor + else + to_chat(U, span_notice("You set the color of the [target.get_fitting_name()].")) + + target.brightness_color = setcolor + target.brightness_color_ns = setnightcolor + + if(target.nightshift_enabled) + target.light_color = target.brightness_color_ns + else + target.light_color = target.brightness_color + + target.set_light(0) + target.update() diff --git a/code/game/objects/items/holosign_creator.dm b/code/game/objects/items/holosign_creator.dm new file mode 100644 index 00000000000..15663bc0058 --- /dev/null +++ b/code/game/objects/items/holosign_creator.dm @@ -0,0 +1,72 @@ +/obj/item/holosign_creator + name = "holographic sign projector" + desc = "A handy-dandy holographic projector that displays a janitorial sign." + icon = 'icons/obj/device.dmi' + icon_state = "signmaker" + item_state = "electronic" + force = 0 + w_class = 2 + throwforce = 0 + throw_speed = 3 + throw_range = 7 + var/list/signs = list() + var/max_signs = 10 + var/creation_time = 0 //time to create a holosign in deciseconds. + var/holosign_type = /obj/structure/holosign/wetsign + var/holocreator_busy = FALSE //to prevent placing multiple holo barriers at once + +/obj/item/holosign_creator/afterattack(atom/target, mob/user, clickchain_flags, list/params) + . = ..() + if(!check_allowed_items(target, 1)) + return + var/turf/T = get_turf(target) + var/obj/structure/holosign/H = locate(holosign_type) in T + if(H) + to_chat(user, span_notice("You use [src] to deactivate [H].")) + qdel(H) + else + if(holocreator_busy) + to_chat(user, span_notice("[src] is busy creating a hologram.")) + return + if(signs.len < max_signs) + playsound(src.loc, 'sound/machines/click.ogg', 20, 1) + if(creation_time) + holocreator_busy = TRUE + if(!do_after(user, creation_time, target = target)) + holocreator_busy = FALSE + return + holocreator_busy = FALSE + if(signs.len >= max_signs) + return + if(is_blocked_turf(T, TRUE)) //don't try to sneak dense stuff on our tile during the wait. + return + H = new holosign_type(get_turf(target), src) + to_chat(user, span_notice("You create \a [H] with [src].")) + else + to_chat(user, span_notice("[src] is projecting at max capacity!")) + +/obj/item/holosign_creator/attack_self(mob/user) + . = ..() + if(.) + return + if(signs.len) + for(var/H in signs) + qdel(H) + to_chat(user, span_notice("You clear all active holograms.")) + +/obj/item/holosign_creator/combifan + name = "ATMOS holo-combifan projector" + desc = "A holographic projector that creates holographic combi-fans that prevent changes in atmosphere and temperature conditions. Somehow." + icon_state = "signmaker_engi" + holosign_type = /obj/structure/holosign/barrier/combifan + creation_time = 0 + max_signs = 3 + +/obj/item/holosign_creator/medical + name = "Vey-Med barrier projector" + desc = "A holographic projector that creates Vey-Medical holobarriers. Useful during quarantines since they halt those with malicious diseases." + icon = 'icons/obj/device.dmi' + icon_state = "signmaker_med" + holosign_type = /obj/structure/holosign/barrier/medical + creation_time = 0 + max_signs = 6 diff --git a/code/game/objects/items/toys/target_toy.dm b/code/game/objects/items/toys/target_toy.dm new file mode 100644 index 00000000000..7b4d79aca35 --- /dev/null +++ b/code/game/objects/items/toys/target_toy.dm @@ -0,0 +1,12 @@ +/obj/item/storage/briefcase/target_toy + starts_with = list( + /obj/item/paper/target, + /obj/item/gun/projectile/revolver/toy/big_iron, + /obj/item/grenade/confetti = 2 + ) + +/obj/item/paper/target + name = "target notice" + +/obj/item/paper/target/New() + info = "Your target is " + span_bold("[random_name(pick(MALE,FEMALE))]") + ". Make sure they don't get out of there alive." diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index 4836cbe3376..1cd4f038474 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -766,3 +766,338 @@ CIGARETTE PACKETS ARE IN FANCY.DM name = "\improper badass Zippo lighter" desc = "An absolutely badass zippo lighter. Just look at that skull!" icon_state = "skullzippo" + +/obj/item/flame/lighter/supermatter + name = "Hardlight Supermatter Zippo" // Base SM Lighter + desc = "State of the Art Supermatter Lighter." + description_fluff = "A zippo style lighter with a tiny supermatter sliver held by a hardlight shield. When lighting a cigar, make sure to hover the tip near the sliver, not against it!" + icon_state = "SMzippo" + item_state = "SMzippo" + activation_sound = 'sound/items/zippo_on_alt.ogg' + deactivation_sound = 'sound/items/zippo_off.ogg' + +/obj/item/flame/lighter/supermatter/syndismzippo + name = "Phoron Supermatter Zippo" // Syndicate SM Lighter + desc = "State of the Art Supermatter Lighter." + description_fluff = "A red zippo style lighter with a tiny supermatter sliver held by a phoron field." + icon_state = "SyndiSMzippo" + item_state = "SyndiSMzippo" + activation_sound = 'sound/items/zippo_on_alt.ogg' + deactivation_sound = 'sound/items/zippo_off.ogg' + +/obj/item/flame/lighter/supermatter/expsmzippo + name = "Experimental SM Lighter" // Dangerous WIP (admin/event only ATM) + desc = "State of the Art Supermatter Lighter" + description_fluff = "A unique take originating from the zippo design, a shard of supermatter placed within lead-lined walls. Cautious, VERY DANGEROUS do NOT touch!" + icon_state = "ExpSMzippo" + item_state = "ExpSMzippo" + activation_sound = 'sound/items/button-open.ogg' + deactivation_sound = 'sound/items/button-close.ogg' + +// safe smzippo +/obj/item/flame/lighter/supermatter/attack_self(mob/living/user) + if(!base_state) + base_state = icon_state + if(!lit) + lit = 1 + icon_state = "[base_state]on" + item_state = "[base_state]on" + playsound(src, activation_sound, 75, 1) + if(prob(50)) + user.visible_message(span_rose("[user] safely activates the [src] with a push of a button!")) + else + if(prob(95)) + user.visible_message(span_notice("After a few attempts, [user] manages to excite the supermatter within the [src].")) + else // Just like the cheap lighter, this time you can shock/burn yourself a little on the hardlight shield + to_chat(user, span_warning("You hurt yourself on the shielding!")) + if (user.get_left_hand() == src) + user.apply_damage(1,SEARING,"l_hand") + user.apply_damage(2,ELECTROCUTE,"l_hand") + user.apply_damage(3,CLONE,"l_hand") + user.apply_damage(4,ELECTROMAG,"l_hand") + else + user.apply_damage(1,SEARING,"r_hand") + user.apply_damage(2,ELECTROCUTE,"r_hand") + user.apply_damage(3,CLONE,"r_hand") + user.apply_damage(4,ELECTROMAG,"r_hand") + user.visible_message(span_notice("After a few attempts, [user] manages to activate the [src], they however sting themselves on the shielding!")) + + set_light(2) + START_PROCESSING(SSobj, src) + else + lit = 0 + icon_state = "[base_state]" + item_state = "[base_state]" + playsound(src, deactivation_sound, 75, 1) + if(istype(src, /obj/item/flame/lighter/supermatter) ) + user.visible_message(span_rose("You hear a quiet click, as [user] shuts the [src] without even looking at what they're doing.")) + else + user.visible_message(span_notice("[user] quietly shuts the [src].")) + + set_light(0) + STOP_PROCESSING(SSobj, src) + return + + +/obj/item/flame/lighter/supermatter/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + if(!istype(M, /mob)) + return + + if(lit == 1) + M.IgniteMob() + add_attack_logs(user,M,"Lit on fire with [src]") + + if(istype(M.wear_mask, /obj/item/clothing/mask/smokable/cigarette) && user.zone_sel.selecting == O_MOUTH && lit) + var/obj/item/clothing/mask/smokable/cigarette/cig = M.wear_mask + if(M == user) + cig.attackby(src, user) + else + if(istype(src, /obj/item/flame/lighter/supermatter)) + cig.light(span_rose("[user] whips the [name] out and holds it for [M].")) + else + cig.light(span_notice("[user] holds the [name] out for [M], and lights the [cig.name].")) + else + ..() + +/obj/item/flame/lighter/supermatter/process() + var/turf/location = get_turf(src) + if(location) + location.hotspot_expose(700, 5) + return + +// syndicate smzippo +/obj/item/flame/lighter/supermatter/syndismzippo/attack_self(mob/living/user) + if(!base_state) + base_state = icon_state + if(!lit) + lit = 1 + icon_state = "[base_state]on" + item_state = "[base_state]on" + playsound(src, activation_sound, 75, 1) + if(prob(50)) + user.visible_message(span_rose("[user] safely activates the [src] with a push of a button!")) + else + if(prob(95)) + user.visible_message(span_notice("After a few attempts, [user] manages to excite the supermatter within the [src].")) + else // Just like with the cheap lighter, but this time you can hurt yourself on the heated phoron field + to_chat(user, span_warning("You singe yourself on the phoron shielding the excited supermatter!")) + if (user.get_left_hand() == src) + user.apply_damage(30,HALLOSS,"l_hand") + user.apply_effect(20,IRRADIATE) + user.apply_damage(5,BURN,"l_hand") + user.apply_damage(5,ELECTROCUTE,"l_hand") + else + user.apply_damage(30,HALLOSS,"r_hand") + user.apply_effect(20,IRRADIATE) + user.apply_damage(5,BURN,"r_hand") + user.apply_damage(5,ELECTROCUTE,"r_hand") + user.visible_message(span_notice("After a few attempts, [user] manages to activate the [src], they however burn themselves with the heated phoron field!")) + + set_light(2) + START_PROCESSING(SSobj, src) + else + lit = 0 + icon_state = "[base_state]" + item_state = "[base_state]" + playsound(src, deactivation_sound, 75, 1) + if(istype(src, /obj/item/flame/lighter/supermatter/syndismzippo) ) + user.visible_message(span_rose("You hear a quiet click, as [user] shuts the [src] without even looking at what they're doing.")) + else + user.visible_message(span_notice("[user] quietly shuts the [src].")) + + set_light(0) + STOP_PROCESSING(SSobj, src) + return + + +/obj/item/flame/lighter/supermatter/syndismzippo/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + if(!istype(M, /mob)) + return + + if(lit == 1) + M.IgniteMob() + add_attack_logs(user,M,"Lit on fire with [src]") + + if(istype(M.wear_mask, /obj/item/clothing/mask/smokable/cigarette) && user.zone_sel.selecting == O_MOUTH && lit) + var/obj/item/clothing/mask/smokable/cigarette/cig = M.wear_mask + if(M == user) + cig.attackby(src, user) + else + if(istype(src, /obj/item/flame/lighter/supermatter/syndismzippo)) + cig.light(span_rose("[user] whips the [name] out and holds it for [M].")) + else + cig.light(span_notice("[user] holds the [name] out for [M], and lights the [cig.name].")) + else + ..() + +/obj/item/flame/lighter/process() + var/turf/location = get_turf(src) + if(location) + location.hotspot_expose(700, 5) + return + +// Experimental smzippo +/obj/item/flame/lighter/supermatter/expsmzippo/attack_self(mob/living/user) + if (!base_state) + base_state = icon_state + if (!lit) + lit = 1 + icon_state = "[base_state]on" + item_state = "[base_state]on" + playsound(src, activation_sound, 75, 1) + var/i = rand(1, 100) + switch(i) + if(1 to 22) + to_chat(user, span_rose("[user] safely reveals the supermatter shard within the [src]!")) + user.visible_message(span_rose("You safely revealed the supermatter shard within the [src]!")) + if (user.get_left_hand() == src) + user.apply_damage(1, IRRADIATE, "l_hand") + else // Even using this safely will irradiate you a tiny tiny bit. + user.apply_damage(1, IRRADIATE, "r_hand") + if(23 to 33) + to_chat(user, span_warning("[user]'s hand slipped and they brush against the supermatter within [src]!")) + user.visible_message(span_notice("You accidentally grazed your hand across the supermatter!")) + if (user.get_left_hand() == src) + user.apply_damage(10, IRRADIATE, "l_hand") + user.apply_damage(20, BURN, "l_hand") + user.apply_damage(20, ELECTROCUTE, "l_hand") + user.apply_damage(50, AGONY, "l_hand") + else // One of the outcomes will burn and shock you, the pain is the worst part of this one though. + user.apply_damage(10, IRRADIATE, "r_hand") + user.apply_damage(20, BURN, "r_hand") + user.apply_damage(20, ELECTROCUTE, "r_hand") + user.apply_damage(50, AGONY, "r_hand") + if(34 to 44) + to_chat(user, span_warning("[user] burned themselves on the [src]!")) + user.visible_message(span_notice("You accidentally burn yourself on the [src]!")) + if (user.get_left_hand() == src) + user.apply_damage(30, IRRADIATE, "l_hand") + user.apply_damage(20, SEARING, "l_hand") + user.apply_damage(15, BURN, "l_hand") + else // One of the outcomes is pure burn and radiation. + user.apply_damage(30, IRRADIATE, "r_hand") + user.apply_damage(20, SEARING, "r_hand") + user.apply_damage(15, BURN, "r_hand") + if(45 to 55) + to_chat(user, span_warning("[user] fumbled the [src] and the supermatter let out sparks!")) + user.visible_message(span_notice("You fumble the [src], letting the supermatter spark as the case opens!")) + if (user.get_left_hand() == src) + user.apply_damage(1, ELECTROCUTE, "l_hand") + user.apply_damage(100, ELECTROMAG, "l_hand") + else // This one is mostly dangerous to synthetics and it will EMP you. But otherwise it's safe. + user.apply_damage(1, ELECTROCUTE, "r_hand") + user.apply_damage(100, ELECTROMAG, "r_hand") + if(56 to 66) + to_chat(user, span_warning("[user] struggles to open their [src], but when they do they get burned by the extreme heat within!")) + user.visible_message(span_notice("You struggle to get the case to open, and when it does the heat that pours out of the [src] burns!")) + if (user.get_left_hand() == src) + user.apply_damage(1, IRRADIATE, "l_hand") + user.apply_damage(1, BRUISE, "l_hand") + user.apply_damage(200, BURN, "l_hand") + user.drop_l_hand() + else // This will INSTA-DUST your hand that you're holding the item in, and then make you drop the lighter. + user.apply_damage(1, IRRADIATE, "r_hand") + user.apply_damage(1, BRUISE, "r_hand") + user.apply_damage(200, BURN, "r_hand") + user.drop_r_hand() + if(67 to 77) + to_chat(user, span_warning("Ouch! While pushing on the release to open the [src], [user]'s finger slipped right as the case opened, pressing their finger firm against the supermatter!")) + user.visible_message(span_notice("You accidentally pushed your finger against the supermatter!")) + if (user.get_left_hand() == src) + user.apply_damage(50, HALLOSS, "l_hand") + user.apply_damage(40, IRRADIATE, "l_hand") + user.apply_damage(30, BURN, "l_hand") + user.apply_damage(20, TOX, "l_hand") + user.apply_damage(10, ELECTROCUTE, "l_hand") + user.apply_effect(25, STUTTER) + user.apply_effect(15, SLUR) + user.apply_effect(5, STUN) + else // This one is VERY punishing, you get a ton of damage, a lot of pain, and a minor stun. Once the stun goes away you'll be stuttering for awhile as if in crit. + user.apply_damage(50, HALLOSS, "r_hand") + user.apply_damage(40, IRRADIATE, "r_hand") + user.apply_damage(30, BURN, "r_hand") + user.apply_damage(20, TOX, "r_hand") + user.apply_damage(10, ELECTROCUTE, "r_hand") + user.apply_effect(25, STUTTER) + user.apply_effect(15, SLUR) + user.apply_effect(5, STUN) + if(78 to 88) + to_chat(user, span_notice("[user] managed to pinch themselves on the case of their [src]... it could have been worse.")) + user.visible_message(span_notice("You manage to pinch yourself on the case!")) + if (user.get_left_hand() == src) + user.apply_damage(1, CLONE, "l_hand") + user.apply_damage(1, HALLOSS, "l_hand") + else // Aside from the base, this one isn't punishing outside of giving you genetic damage. + user.apply_damage(1, CLONE, "r_hand") + user.apply_damage(1, HALLOSS, "r_hand") + if(89 to 99) + to_chat(user, span_notice("[user] opened the [src] but forgot that you aren't supposed to look at supermatter!")) + user.visible_message(span_notice("You find yourself looking at the supermatter for longer than you should...")) + if (user.get_left_hand() == src) + user.apply_damage(15, HALLOSS, "l_hand") + user.apply_effect(5, WEAKEN) + user.apply_damage(15, IRRADIATE, "l_hand") + user.apply_effect(100, EYE_BLUR) + user.apply_effect(50, AGONY) + user.apply_damage(5, OXY) + user.eye_blurry = 10 + else // This one just blinds and blurs your screen, but otherwise doesn't actually risk harming you. Even the oxy damage heals on its own. + user.apply_damage(15, HALLOSS, "r_hand") + user.apply_effect(5, WEAKEN) + user.apply_damage(15, IRRADIATE, "l_hand") + user.apply_effect(100, EYE_BLUR) + user.apply_effect(50, AGONY) + user.apply_damage(15, OXY) + user.eye_blurry = 10 + if(100) // This is the part that makes it admin only for the moment, it spawns 500 rads from the carbon's position, and dusts the carbon instantly. It does also drop everything unlike the supermatter crystal though, so hopefully you won't lose any items if you fumble this badly! + to_chat(user, span_warning("OH NO! [user] almost dropped their live [src]! Thank goodness they caught it... by the glowing yellow crystal... oh.")) + user.visible_message(span_danger("You almost dropped your [src], thank goodness you caught it! By the glowing crystal within. You find your ears filled with unearthly ringing and your last thought is \"Oh, fuck.\"")) + user.drop_r_hand() // To ensure the lighter is dropped <3 + user.drop_l_hand() // To ensure the lighter is dropped <3 + for(var/obj/item/e in user) + user.drop_from_inventory(e) + log_and_message_admins("[user] dusted themselves and caused massive radiation with [src]!",user) + user.dust() + var/rads = 500 + SSradiation.radiate(src, rads) + + set_light(5) + START_PROCESSING(SSobj, src) + else + lit = 0 + icon_state = "[base_state]" + item_state = "[base_state]" + playsound(src, deactivation_sound, 75, 1) + if (istype(src, /obj/item/flame/lighter/supermatter/expsmzippo)) + user.visible_message(span_rose("You hear a quiet click, as [user] closes the [src].")) + else + user.visible_message(span_notice("[user] quietly shuts the [src].")) + + set_light(0) + STOP_PROCESSING(SSobj, src) + +/obj/item/flame/lighter/supermatter/expsmzippo/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + if (!istype(M, /mob)) + return + + if (lit == 1) + M.IgniteMob() + add_attack_logs(user, M, "Lit on fire with [src]") + + if (istype(M.wear_mask, /obj/item/clothing/mask/smokable/cigarette) && user.zone_sel.selecting == O_MOUTH && lit) + var/obj/item/clothing/mask/smokable/cigarette/cig = M.wear_mask + if (M == user) + cig.attackby(src, user) + else + if (istype(src, /obj/item/flame/lighter/supermatter/expsmzippo)) + cig.light(span_rose("[user] whips the [name] out and holds it for [M].")) + else + cig.light(span_notice("[user] holds the [name] out for [M], and lights the [cig.name].")) + else + ..() + +/obj/item/flame/lighter/supermatter/expsmzippo/process() + var/turf/location = get_turf(src) + if (location) + location.hotspot_expose(700, 5) + return diff --git a/code/game/objects/mail.dm b/code/game/objects/mail.dm new file mode 100644 index 00000000000..339ae5f5b33 --- /dev/null +++ b/code/game/objects/mail.dm @@ -0,0 +1,509 @@ +/obj/item/mail + name = "mail" + 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 = ITEMSIZE_SMALL + drop_sound = 'sound/items/drop/paper.ogg' + pickup_sound = 'sound/items/pickup/paper.ogg' + mouse_drag_pointer = MOUSE_ACTIVE_POINTER + // Destination tagging for the mail sorter. + var/sortTag = 0 + // Who this mail is for and who can open it. + var/datum/weakref/recipient + // How many goodies this mail contains. + var/goodie_count = 1 + // Goodies which can be given to anyone. + // Weight sum will be 1000 + var/list/generic_goodies = list( + /obj/item/spacecash/c50 = 75, + /obj/item/reagent_containers/food/drinks/cans/cola = 75, + /obj/item/reagent_containers/food/snacks/chips = 75, + /obj/item/reagent_containers/food/drinks/coffee = 75, + /obj/item/reagent_containers/food/drinks/tea = 75, + /obj/item/reagent_containers/food/drinks/glass2/coffeemug/nt = 50, + /obj/item/spacecash/c100 = 40, + /obj/item/spacecash/c200 = 25, + /obj/item/spacecash/c500 = 15, + /obj/item/spacecash/c1000 = 5, + /obj/item/reagent_containers/food/drinks/bluespace_coffee = 5 + ) + // 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 + // If the mail is actively being opened right now + var/opening = FALSE + // If the mail has been scanned with a mail scanner + var/scanned + // Does it have a colored envelope? + var/colored_envelope + +/obj/item/mail/container_resist(mob/living/M) + if(istype(M, /mob/living/voice)) return + M.forceMove(get_turf(src)) + to_chat(M, span_warning("You climb out of \the [src].")) + +/obj/item/mail/envelope + name = "envelope" + icon_state = "mail_large" + goodie_count = 2 + stamp_max = 2 + stamp_offset_y = 5 + +/obj/item/mail/Initialize() + . = ..() + RegisterSignal(src, COMSIG_MOVABLE_DISPOSING, PROC_REF(disposal_handling)) + + // Icons + // Add some random stamps. + if(stamped == TRUE) + var/stamp_count = rand(1, stamp_max) + for(var/i = 1, i <= stamp_count, i++) + stamps += list("stamp_[rand(2, 8)]") + +/obj/item/mail/blank + desc = "A blank envelope." + description_info = "An object can be placed into the envelope, click on it with an empty hand to seal it. Alt-Click to retrieve the items from inside before sealing." + stamped = FALSE + postmarked = FALSE + var/set_recipient = FALSE + var/set_content = FALSE + var/sealed = FALSE + var/list/mail_recipients + +/obj/item/mail/blank/attackby(obj/item/W, mob/user) + ..() + if(istype(W, /obj/item/pen) && sealed && !set_recipient) + if(setRecipient(user)) + set_recipient = TRUE + add_fingerprint(user) + return + + if(!set_content && !sealed) + if(!do_after(user, 1.5 SECONDS, target = user)) + set_content = FALSE + user.drop_item() + W.forceMove(src) + to_chat(user, "Placed the [W] into the [src]") + set_content = TRUE + description_info = "Click with an empty hand to seal it, or Alt-Click to retrieve the object out." + return + return + +/obj/item/mail/proc/setRecipient(mob/user) + var/list/recipients = list() + for(var/mob/living/player in player_list) + if(!player_is_antag(player.mind) && player.mind.show_in_directory) + recipients += player + + recipients = tgui_input_list(usr, "Choose recipient", "Recipients", recipients, recipients) + + if(recipients) + initialize_for_recipient(recipients, preset_goodies = TRUE) + return TRUE + +/obj/item/mail/blank/AltClick(mob/user) + if(sealed) + return + + for(var/obj/stuff as anything in contents) + if(isitem(stuff)) + user.put_in_hands(stuff) + else + stuff.forceMove(drop_location()) + set_content = FALSE + description_info = initial(description_info) + +/obj/item/mail/blank/ShiftClick(mob/user) + ..() + if(!sealed) + var/sender = tgui_input_text(user, "Write name", "Name", user.name) + if(sender) + desc = "A signed envelope, from [sender]." + +/obj/item/mail/blank/attack_self(mob/user) + if(!sealed) + if(!do_after(user, 1.5 SECONDS, target = user)) + sealed = FALSE + sealed = TRUE + description_info = "Shift Click to add the sender's name to the envelope, or attack with a pen to set a receiver." + return + . = ..() + +/obj/item/mail/update_icon() + . = ..() + cut_overlays() + if(colored_envelope) + var/image/envelope = image(icon, icon_state) + envelope.color = colored_envelope + add_overlay(envelope) + var/bonus_stamp_offset = 0 + for(var/stamp in stamps) + var/image/stamp_image = image( + 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(-4, 0), + 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 as obj, mob/user as mob) + . = ..() + // Destination tagging + if(istype(W, /obj/item/destTagger)) + var/obj/item/destTagger/O = W + if(O.currTag) + if(src.sortTag != O.currTag) + to_chat(user, span_notice("You have labeled the destination as [O.currTag].")) + src.sortTag = O.currTag + playsound(src, 'sound/machines/twobeep.ogg', 50, 1) + W.description_info = " It is labeled for [O.currTag]" + else + to_chat(user, span_notice("The mail is already labeled for [O.currTag].")) + else + to_chat(user, span_danger("You need to set a destination first!")) + return + +/obj/item/mail/attack_self(mob/user) + if(!unwrap(user)) + return FALSE + return after_unwrap(user) + +/obj/item/mail/proc/unwrap(mob/user) + if(recipient && user != recipient) + to_chat(user, span_danger("You can't open somebody's mail! That's illegal")) + return FALSE + + if(opening) + to_chat(user, span_danger("You are already opening that!")) + return FALSE + + opening = TRUE + if(!do_after(user, 1.5 SECONDS, target = user)) + opening = FALSE + return FALSE + return TRUE + +/obj/item/mail/proc/after_unwrap(mob/user) + user.temporarilyRemoveItemFromInventory(src, TRUE) + for(var/obj/stuff as anything in contents) + if(isitem(stuff)) + user.put_in_hands(stuff) + else + stuff.forceMove(drop_location()) + playsound(loc, 'sound/items/poster_ripped.ogg', 100, TRUE) + qdel(src) + +/obj/item/mail/proc/initialize_for_recipient(mob/new_recipient, var/preset_goodies = FALSE) + recipient = new_recipient + var/current_title = new_recipient.mind.role_alt_title ? new_recipient.mind.role_alt_title : new_recipient.mind.assigned_role + name = "[initial(name)] for [new_recipient.real_name] ([current_title])" + + var/datum/job/this_job = SSjob.name_occupations[new_recipient.job] + + var/list/goodies = generic_goodies + if(this_job) + colored_envelope = this_job.get_mail_color() + if(!preset_goodies) + var/list/job_goodies = this_job.get_mail_goodies(new_recipient, current_title) + if(LAZYLEN(job_goodies)) + if(this_job.get_mail_goodies()) + goodies = job_goodies + else + goodies += job_goodies + + if(!preset_goodies) + for(var/iterator in 1 to goodie_count) + var/target_good = pickweight(goodies) + var/atom/movable/target_atom = new target_good(src) + log_game("[key_name(new_recipient)] received [target_atom.name] in the mail ([target_good])") + + update_icon() + return TRUE + +/obj/item/mail/proc/disposal_handling(disposal_source, obj/structure/disposalholder/disposal_holder, obj/machinery/disposal/deliveryChute, hasmob) + SIGNAL_HANDLER + if(!hasmob) + disposal_holder.destinationTag = sortTag + +// Mail spawn for events +/datum/admins/proc/spawn_mail(var/object as text) + set name = "Spawn Mail" + set category = "Fun.Event Kit" + set desc = "Spawn mail for a specific player, with a specific item." + + if(!check_rights(R_SPAWN)) return + + var/list/types = typesof(/atom) + var/list/matches = new() + var/list/recipients = list() + + for(var/path in types) + if(findtext("[path]", object)) + matches += path + + if(matches.len==0) + return + var/chosen + if(matches.len==1) + chosen = matches[1] + else + chosen = tgui_input_list(usr, "Select an atom type", "Spawn Atom in Mail", matches) + if(!chosen) + return + + for(var/mob/living/player in player_list) + recipients += player + + recipients = tgui_input_list(usr, "Choose recipient", "Recipients", recipients, recipients) + + if(!recipients) + return + + var/shuttle_spawn = tgui_alert(usr, "Spawn mail at location or in the shuttle?", "Spawn mail", list("Location", "Shuttle")) + if(!shuttle_spawn) + return + if(shuttle_spawn == "Shuttle") + var/obj/item/mail/new_mail = new + new_mail.initialize_for_recipient(recipients, TRUE) + new chosen(new_mail) + SSmail.admin_mail += new_mail + log_and_message_admins("spawned [chosen] inside an envelope at the shuttle") + else + var/obj/item/mail/ground_mail = new /obj/item/mail(usr.loc) + ground_mail.initialize_for_recipient(recipients, TRUE) + new chosen(ground_mail) + log_and_message_admins("spawned [chosen] inside an envelope at ([usr.x],[usr.y],[usr.z])") + + feedback_add_details("admin_verb","SM") + +// Mail Crate +/obj/structure/closet/crate/mail + name = "mail crate" + desc = "An official mail crate from CentCom" + points_per_crate = 0 + closet_appearance = /decl/closet_appearance/crate/nanotrasen + +/obj/structure/closet/crate/mail/full/Initialize() + . = ..() + var/list/mail_recipients = list() + for(var/mob/living/carbon/human/alive in player_list) + if(alive.stat != DEAD && alive.client && alive.client.inactivity <= 10 MINUTES) + mail_recipients += alive + for(var/iterator in 1 to storage_capacity) + var/obj/item/mail/new_mail + if(prob(70)) + new_mail = new /obj/item/mail(src) + else + new_mail = new /obj/item/mail/envelope(src) + var/mob/living/carbon/human/mail_to + if(mail_to) + new_mail.initialize_for_recipient(mail_to) + mail_recipients -= mail_to + else + new_mail.junk_mail() + +// Mailbag +/obj/item/storage/bag/mail + name = "mail bag" + desc = "A bag for letters, envelopes and other postage." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "mailbag" + slot_flags = SLOT_BELT | SLOT_POCKET + w_class = ITEMSIZE_NORMAL + storage_slots = 31 + max_storage_space = 50 + max_w_class = ITEMSIZE_NORMAL + use_to_pickup = TRUE + allow_quick_gather = TRUE + can_hold = list( + /obj/item/mail, + /obj/item/smallDelivery, + /obj/item/paper, + /obj/item/stolenpackage, + /obj/item/contraband, + /obj/item/mail_scanner, + /obj/item/pen + ) + +// Mail Scanner +/obj/item/mail_scanner + name = "mail scanner" + desc = "Sponsored by the Intergalactic Mail Service, this device logs mail deliveries in exchance for financial compensation." + force = 0 + throwforce = 0 + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "mail_scanner" + slot_flags = SLOT_BELT + w_class = ITEMSIZE_SMALL + var/cargo_points = 5 + var/obj/item/mail/saved + +/obj/item/mail_scanner/examine(mob/user) + . = ..() + . += span_notice("Scan a letter to log it into the active database, then scan the person you wish to hand the letter to. Correctly scanning the recipient of the letter logged into the active database will add points to the supply budget.") + +/obj/item/mail_scanner/attack() + return + +/obj/item/mail_scanner/afterattack(atom/A, mob/user) + if(istype(A, /obj/item/mail)) + var/obj/item/mail/saved_mail = A + if(saved_mail.scanned) + to_chat(user, span_danger("This letter has already been scanned!")) + playsound(loc, 'sound/items/mail/maildenied.ogg', 50, TRUE) + return + to_chat(user, span_notice("Mail added to database")) + playsound(loc, 'sound/items/mail/mailscanned.ogg', 50, TRUE) + saved = A + return + if(isliving(A)) + var/mob/living/M = A + + if(!saved) + to_chat(user, span_danger("No logged mail!")) + playsound(loc, 'sound/items/mail/maildenied.ogg', 50, TRUE) + return + + var/mob/living/recipient = saved.recipient + + if(M.stat == DEAD) + to_chat(user, span_warning("Consent Verification failed: You can't deliver mail to a corpse!")) + playsound(loc, 'sound/items/mail/maildenied.ogg', 50, TRUE) + return + if(M.real_name != recipient.real_name) + to_chat(user, span_warning("Identity Verification failed: Target is not authorized recipient of this envelope!")) + playsound(loc, 'sound/items/mail/maildenied.ogg', 50, TRUE) + return + if(!M.client) + to_chat(user, span_warning("Consent Verification failed: The scanner does not accept orders from SSD crewmemmbers!")) + playsound(loc, 'sound/items/mail/maildenied.ogg', 50, TRUE) + return + + saved.scanned = TRUE + saved = null + + cargo_points = rand(5, 10) + to_chat(user, span_notice("Succesful delivery acknowledged! [cargo_points] points added to Supply.")) + playsound(loc, 'sound/items/mail/mailapproved.ogg', 50, TRUE) + SSsupply.points += cargo_points + +// JUNK MAIL STUFF + +/obj/item/mail/junkmail/Initialize() + . = ..() + junk_mail() + +/obj/item/mail/proc/junk_mail() + + 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/violent_video_games, + /obj/item/paper/pamphlet/radstorm, + /obj/item/paper/fluff/junkmail_redpill, + /obj/effect/decal/cleanable/ash, + /obj/item/paper/fluff/love_letter, + /obj/item/reagent_containers/food/snacks/donkpocket/berry, + /obj/item/reagent_containers/food/snacks/donkpocket/dankpocket, + /obj/item/reagent_containers/food/snacks/donkpocket/gondola, + /obj/item/reagent_containers/food/snacks/donkpocket/honk, + /obj/item/reagent_containers/food/snacks/donkpocket/pizza, + /obj/item/reagent_containers/food/snacks/donkpocket/spicy, + /obj/item/reagent_containers/food/snacks/donkpocket/teriyaki, + /obj/item/toy/figure, + /obj/item/contraband/package, + /obj/item/tool/screwdriver/sdriver, + /obj/item/storage/briefcase/target_toy + )) + + var/list/junk_names = list( + /obj/item/paper/pamphlet/gateway = "[initial(name)] for BRAVE adventurers", + /obj/item/paper/pamphlet/violent_video_games = "[initial(name)] for the truth about the arcade CentComm doesn't want to hear", + /obj/item/paper/pamphlet/radstorm = "[initial(name)] for the threats in space", + /obj/item/paper/fluff/junkmail_redpill = "[initial(name)] for those feeling tired working at Nanotrasen", + /obj/effect/decal/cleanable/ash = "[initial(name)] with INCREDIBLY IMPORTANT ARTIFACT- DELIVER TO SCIENCE DIVISION. HANDLE WITH CARE.", + /obj/item/paper/fluff/love_letter = "[initial(name)] for STUPID CARGO MAILMEN.", + /obj/item/reagent_containers/food/snacks/donkpocket/berry = "[initial(name)] with NEW BERRY-POCKET.", + /obj/item/reagent_containers/food/snacks/donkpocket/dankpocket = "[initial(name)] with NEW DANK-POCKET.", + /obj/item/reagent_containers/food/snacks/donkpocket/gondola = "[initial(name)] with NEW GONDOLA-POCKET.", + /obj/item/reagent_containers/food/snacks/donkpocket/honk = "[initial(name)] with NEW HONK-POCKET.", + /obj/item/reagent_containers/food/snacks/donkpocket/pizza = "[initial(name)] with NEW PIZZA-POCKET.", + /obj/item/reagent_containers/food/snacks/donkpocket/spicy = "[initial(name)] with NEW SPICY-POCKET.", + /obj/item/reagent_containers/food/snacks/donkpocket/teriyaki = "[initial(name)] with NEW TERIYAKI-POCKET.", + /obj/item/toy/figure = "[initial(name)] from DoN**K*oC", + /obj/item/contraband/package = "[pick("oddly shaped", "strangely wrapped", "weird", "bulging")] [initial(name)]", + /obj/item/tool/screwdriver/sdriver = "[initial(name)] for Proffesor Who", + /obj/item/storage/briefcase/target_toy = "[initial(name)] for SIMPATHY, SUCCESS, MANHATTAN, BELIEFS" + ) + + name = special_name ? junk_names[junk] : "important [initial(name)]" + + junk = new junk(src) + update_icon() + return TRUE + +/obj/item/paper/fluff/junkmail_generic/Initialize() + . = ..() + info = pick( + prob(5);"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?", + prob(5);"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!", + prob(5);"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.", + prob(5);"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!", + prob(5);"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", + prob(5);"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.", + prob(5);"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 :^()", + prob(5);"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", + prob(5);"hello :wave::wave: nanotrasens! fuck :point_left::ok_hand: the syndicate! they :older_woman: got ☄ me :heart_eyes::cold_sweat: questioning my :pregnant_woman: loyalty to nanotraben! so :ok_hand::100: please :tired_face: lets :no_entry::eyes: gather our :camera_with_flash::poop: energy :sunglasses: and :moneybag::symbols: QUICK. :astonished: send this :wastebasket::point_left: to :sweat_drops::pill: 10 :joy::joy: other loyal :100: nanotraysens to :sweat_drops::thinking: show we :dog: dont :person_gesturing_no::no_entry_sign: take :shopping_bags: nothing from :joy: the ✝ syndicate!! bless your :point_right_tone2: heart :heart_eyes::broken_heart:", + prob(5);"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", + prob(5);"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.", + prob(5);"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", + prob(5);"MESSAGE FROM CENTCOMM 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.", + prob(5);"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", + ) + +/obj/item/paper/fluff/junkmail_redpill + name = "smudged paper" + icon_state = "scrap" + +/obj/item/paper/fluff/junkmail_redpill/Initialize() + . = ..() + info = "You need to escape the simulation. Don't forget the numbers, they help you remember: '[rand(0,9)]*[rand(0,9)][rand(0,9)]...'" + +/obj/item/paper/fluff/love_letter + name = "love letter" + icon_state = "paper_words" + +/obj/item/paper/fluff/love_letter/Initialize() + . = ..() + info = "I HATE CARGO MAIL\n\"GRAA LEMME BREAK YOUR DOORS DOWN I GOTTA GIVE YOU MAIL\nREE YOU GOTTA GET YOUR MAIL I SORTED IT\nYOU'RE WASTIN YOUR TIME IF YOU DONT GET MAIL YOU NEED TO GET YOUR MAIL NOW\nWHY ARENT YO UGETTING YOUR MAIL RAAA\"" + +/obj/item/paper/fluff/junkmail_generic + name = "important document" + icon_state = "paper_words" diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm new file mode 100644 index 00000000000..8c006c0c690 --- /dev/null +++ b/code/game/objects/structures/holosign.dm @@ -0,0 +1,108 @@ +/obj/structure/holosign + name = "holo sign" + icon = 'icons/effects/effects.dmi' + anchored = TRUE + var/obj/item/holosign_creator/projector + var/health = 10 + explosion_resistance = 1 + +/obj/structure/holosign/Initialize(mapload, source_projector) + . = ..() + if(source_projector) + projector = source_projector + projector.signs += src +/* if(overlays) // Fucking god damnit why do we have to have an entire different subsystem for this shit from other codebases. + overlays.add_overlay(src, icon, icon_state, ABOVE_MOB_LAYER, plane, dir, alpha, RESET_ALPHA) //you see mobs under it, but you hit them like they are above it + alpha = 0 +*/ + +/obj/structure/holosign/Destroy() + if(projector) + projector.signs -= src + projector = null + return ..() + +/obj/structure/holosign/attack_hand(mob/user, list/params) + . = ..() + if(.) + return + user.setClickCooldown(user.get_attack_speed()) + user.do_attack_animation(src) + take_damage(5) + playsound(loc, 'sound/weapons/egloves.ogg', 80, 1) + +/obj/structure/holosign/attackby(obj/item/W as obj, mob/user as mob) + user.setClickCooldown(user.get_attack_speed(W)) + user.do_attack_animation(src) + playsound(loc, 'sound/weapons/egloves.ogg', 80, 1) + take_damage(W.force) + +/obj/structure/holosign/take_damage(var/damage) + health -= damage + spawn(1) healthcheck() + return 1 + +/obj/structure/holosign/proc/healthcheck() + if(health <= 0) + qdel(src) + +/obj/structure/holosign/wetsign + name = "wet floor sign" + desc = "The words flicker as if they mean nothing." + icon_state = "holosign" + +/obj/structure/holosign/barrier/combifan + name = "holo combifan" + desc = "A holographic barrier resembling a blue-accented tiny fan. Though it does not prevent solid objects from passing through, gas and temperature changes are kept out." + icon_state = "holo_firelock" + anchored = TRUE + density = FALSE + layer = ABOVE_TURF_LAYER + can_atmos_pass = ATMOS_PASS_NO + alpha = 150 + +/obj/structure/holosign/barrier/combifan/Destroy() + update_nearby_tiles() + return ..() + +/obj/structure/holosign/barrier/combifan/Initialize(mapload) + .=..() + update_nearby_tiles() + +/obj/structure/holosign/barrier/medical + name = "\improper Vey-Med holobarrier" + desc = "A holobarrier that uses biometrics to detect viruses. Denies passing to personnel with easily-detected, malicious viruses. Good for quarantines." + icon_state = "holo_medical" + alpha = 125 + var/buzzed = 0 + +/obj/structure/holosign/barrier/medical/CanPass(atom/movable/mover, border_dir) + . = ..() + if(mover.has_buckled_mobs()) + for(var/mob/living/L as anything in buckled_mobs) + if(ishuman(L)) + if(CheckHuman(L)) + return FALSE + if(ishuman(mover)) + return CheckHuman(mover) + return TRUE + +/obj/structure/holosign/barrier/medical/Bumped(atom/movable/AM) + . = ..() + if(ishuman(AM) && !CheckHuman(AM)) + if(buzzed < world.time) + playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 1) + buzzed = (world.time + 60) + + icon_state = "holo_medical-deny" + addtimer(VARSET_CALLBACK(src, icon_state, "holo_medical"), 10 SECONDS, TIMER_DELETE_ME) + +/obj/structure/holosign/barrier/medical/proc/CheckHuman(mob/living/carbon/human/H) + if(istype(H.get_species(), SPECIES_XENOCHIMERA)) + return FALSE + if(H.GetViruses()) + for(var/datum/disease/D in H.GetViruses()) + if(D.severity == NONTHREAT) + continue + return FALSE + return TRUE diff --git a/code/modules/admin/admin_verb_lists_vr.dm b/code/modules/admin/admin_verb_lists_vr.dm index 44dcdf75e77..564fed32465 100644 --- a/code/modules/admin/admin_verb_lists_vr.dm +++ b/code/modules/admin/admin_verb_lists_vr.dm @@ -183,6 +183,7 @@ var/list/admin_verbs_spawn = list( /datum/admins/proc/check_custom_items, /datum/admins/proc/spawn_plant, /datum/admins/proc/spawn_atom, //allows us to spawn instances, + /datum/admins/proc/spawn_mail, /client/proc/cmd_admin_droppod_spawn, /client/proc/respawn_character, /client/proc/spawn_character_mob, //VOREStation Add, diff --git a/code/modules/awaymissions/pamphlet.dm b/code/modules/awaymissions/pamphlet.dm index 5f05f3e99da..6ac224d1225 100644 --- a/code/modules/awaymissions/pamphlet.dm +++ b/code/modules/awaymissions/pamphlet.dm @@ -1,21 +1,29 @@ -/obj/item/paper/pamphlet - name = "pamphlet" - icon_state = "pamphlet" - info = span_bold("Welcome to the Gateway project...") + "
\ +/obj/item/paper/pamphlet/radstorm + name = "pamphlet - 'Radstorm Safety Measures and How to Not Become Monkey'" + info = "Has your station's preemptive radstorm safety alarm gone off and you don't see a nearby maintenance hatch to escape to? Never fear, for NT truly thinks of everything! \ + Several public-access shelters have been installed around the upper station with express purpose of protecting your fragile meaty bits from becoming the next medical disaster! \ + Please see subsection 4.3 V2-3 in your employee handbook for appropriate procedures to deal with excessive radiation damage if you do not make it to a shelter in time." + +/obj/item/paper/pamphlet/violent_video_games + name = "pamphlet - 'Violent Video Games and You'" + desc = "A pamphlet encouraging the reader to maintain a balanced lifestyle and take care of their mental health, while still enjoying video games in a healthy way. You probably don't need this..." + info = "They don't make you kill people. There, we said it. Now get back to work!" + +/obj/item/paper/pamphlet/gateway + info = "Welcome to the Nanotrasen Gateway project...
\ Congratulations! If you're reading this, you and your superiors have decided that you're \ ready to commit to a life spent colonising the rolling hills of far away worlds. You \ must be ready for a lifetime of adventure, a little bit of hard work, and an award \ - winning dental plan- but that's not all the Gateway project has to offer.
\ + winning dental plan- but that's not all the Nanotrasen Gateway project has to offer.
\
Because we care about you, we feel it is only fair to make sure you know the risks \ - before you commit to joining the Gateway project. All away destinations have \ - been fully scanned by a expeditionary team, and are certified to be 100% safe. \ + before you commit to joining the Nanotrasen Gateway project. All away destinations have \ + been fully scanned by a Nanotrasen expeditionary team, and are certified to be 100% safe. \ We've even left a case of space beer along with the basic materials you'll need to expand \ - the Project's operational area and start your new life.

\ + Nanotrasen's operational area and start your new life.

\ Gateway Operation Basics
\ - All approved Gateways operate on the same basic principals. They operate off \ - area equipment power as you would expect, but they also require a backup wire with at least \ - 128, 000 Watts of power running through it. Without this supply, it cannot safely function \ - and will reject all attempts at operation.

\ + All Nanotrasen approved Gateways operate on the same basic principals. They operate off \ + area equipment power as you would expect, and without this supply, it cannot safely function, \ + causinng it to reject all attempts at operation.

\ Once it is correctly setup, and once it has enough power to operate, the Gateway will begin \ searching for an output location. The amount of time this takes is variable, but the Gateway \ interface will give you an estimate accurate to the minute. Power loss will not interrupt the \ @@ -29,10 +37,6 @@ number of cases, the Gateway they have established may not be immediately obvious. \ Do not panic if you cannot locate the return Gateway. Begin colonisation of the destination. \

A New World
\ - As a participant in the Gateway Project, you will be on the frontiers of space. \ + As a participant in the Nanotrasen Gateway Project, you will be on the frontiers of space. \ Though complete safety is assured, participants are advised to prepare for inhospitable \ environs." - -//we don't want the silly text overlay! -/obj/item/paper/pamphlet/update_icon() - return diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index 7e538630256..e80186a767d 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -289,3 +289,8 @@ name = "quartermaster's beret" desc = "This headwear shows off your Cargonian leadership." icon_state = "beretqm" + +/obj/item/clothing/head/mailman2 + name = "mailman hat" + desc = "A hat used by the mailman to show who's the delivery person here." + icon_state = "mailman2" diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm index a81d32685b5..4066f1125ab 100644 --- a/code/modules/clothing/under/jobs/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian.dm @@ -211,3 +211,10 @@ name = "shaft miner's jumpsuit" icon_state = "miner" rolled_sleeves = 0 + +/obj/item/clothing/under/rank/mailman2 + name = "mailman's suit" + desc = "A good looking suit for the delivery person!" + icon_state = "mailman2" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + rolled_sleeves = 0 diff --git a/code/modules/food/glass/bottle.dm b/code/modules/food/glass/bottle.dm index 341a79c09b9..fe3b6d90ea7 100644 --- a/code/modules/food/glass/bottle.dm +++ b/code/modules/food/glass/bottle.dm @@ -176,3 +176,33 @@ icon = 'icons/obj/chemical.dmi' icon_state = "bottle-3" prefill = list(REAGENT_ID_BIOMASS = 60) + +/obj/item/reagent_containers/glass/bottle/cakebatter + name = "cake batter bottle" + desc = "A bottle of pre-made cake batter." + icon_state = "bottle-1" + prefill = list(REAGENT_ID_CAKEBATTER = 60) + +/obj/item/reagent_containers/glass/bottle/cinnamonpowder + name = "cinnamon powder bottle" + desc = "A bottle with expensive cinnamon powder." + icon_state = "bottle-1" + prefill = list(REAGENT_ID_CINNAMONPOWDER = 30) // Expensive! + +/obj/item/reagent_containers/glass/bottle/nothing + name = "empty bottle?" + desc = "An apparently empty bottle." + icon_state = "bottle-1" + prefill = list(REAGENT_ID_NOTHING = 60) + +/obj/item/reagent_containers/glass/bottle/gelatin + name = "gelatin bottle" + desc = "A bottle full of gelatin." + icon_state = "bottle-1" + prefill = list(REAGENT_ID_GELATIN = 60) + +/obj/item/reagent_containers/glass/bottle/lube + name = "lube bottle" + desc = "A bottle full of lube." + icon_state = "bottle-1" + prefill = list(REAGENT_ID_LUBE = 60) diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station.dm b/code/modules/mob/living/silicon/robot/robot_modules/station.dm index b11696eaaa1..eef7cdbe76a 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm @@ -345,7 +345,7 @@ var/global/list/robot_modules = list( src.modules += new /obj/item/surgical/bioregen/cyborg(src) //Surgeon Modules End src.modules += new /obj/item/inflatable_dispenser/robot(src) - //src.modules += new /obj/item/holosign_creator/medical(src) //Re-enable after Guti's PR. + src.modules += new /obj/item/holosign_creator/medical(src) var/obj/item/reagent_containers/spray/PS = new /obj/item/reagent_containers/spray(src) src.emag += PS PS.reagents.add_reagent(REAGENT_ID_PACID, 250) diff --git a/code/modules/reagents/machinery/dispenser/cartridge_presets.dm b/code/modules/reagents/machinery/dispenser/cartridge_presets.dm index 2668f932785..98fd2f9677b 100644 --- a/code/modules/reagents/machinery/dispenser/cartridge_presets.dm +++ b/code/modules/reagents/machinery/dispenser/cartridge_presets.dm @@ -251,3 +251,7 @@ spawn_reagent = REAGENT_ID_CRYOXADONE /obj/item/reagent_containers/chem_disp_cartridge/clonexadone spawn_reagent = REAGENT_ID_CLONEXADONE +/obj/item/reagent_containers/chem_disp_cartridge/gelatin + spawn_reagent = REAGENT_ID_GELATIN +/obj/item/reagent_containers/chem_disp_cartridge/nothing + spawn_reagent = REAGENT_ID_NOTHING diff --git a/code/modules/reagents/reagent_containers/bluespacecoffee.dm b/code/modules/reagents/reagent_containers/bluespacecoffee.dm new file mode 100644 index 00000000000..9a7202dd7ec --- /dev/null +++ b/code/modules/reagents/reagent_containers/bluespacecoffee.dm @@ -0,0 +1,17 @@ +/obj/item/reagent_containers/food/drinks/bluespace_coffee + name = "bluespace coffee" + desc = "Dreamt up in a strange feverish dream, this coffee cup seems to have been heavily modified with a variety of unlikely parts and wires, and never seems to run out of coffee. Truly the differance between madmen and genius is success." + icon = 'icons/obj/coffee.dmi' + icon_state = "bluespace_coffee" + center_of_mass_x = 15 + center_of_mass_y = 10 + volume = 50 + +/obj/item/reagent_containers/food/drinks/bluespace_coffee/Initialize() + ..() + reagents.add_reagent(REAGENT_ID_COFFEE, 50) + + //Infinite Coffee +/obj/item/reagent_containers/food/drinks/bluespace_coffee/attack(mob/M as mob, mob/user as mob, def_zone) + ..() + src.reagents.add_reagent(REAGENT_ID_COFFEE, 50) diff --git a/code/modules/reagents/reagents/food_drinks.dm b/code/modules/reagents/reagents/food_drinks.dm index 0dd5e8b3383..a6f9083814b 100644 --- a/code/modules/reagents/reagents/food_drinks.dm +++ b/code/modules/reagents/reagents/food_drinks.dm @@ -4988,3 +4988,23 @@ nutriment_factor = 2 glass_name = REAGENT_ID_KVASS glass_desc = "A hearty glass of Slavic brew." + +/datum/reagent/cinnamonpowder + name = REAGENT_CINNAMONPOWDER + id = REAGENT_ID_CINNAMONPOWDER + description = "Cinnamon, a spice made from tree bark, ground into a fine powder. Probably not a good idea to eat on its own!" + taste_description= "sweet spice with a hint of wood" + color = "#a96622" + + glass_name = REAGENT_ID_CINNAMONPOWDER + glass_desc = "A glass of ground cinnamon. Dare you take the challenge?" + +/datum/reagent/gelatin + name = REAGENT_GELATIN + id = REAGENT_ID_GELATIN + description = "It doesnt taste like anything." + taste_description = REAGENT_ID_NOTHING + color = "#aaabcf" + + glass_name = REAGENT_GELATIN + glass_desc = "It's like flavourless slime." diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 3cdb972e742..95c3910431f 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -646,6 +646,10 @@ var/mob/living/silicon/robot/drone/drone = AM src.destinationTag = drone.mail_destination + if(istype(AM, /obj/item/mail) && !hasmob) + var/obj/item/mail/T = AM + src.destinationTag = T.sortTag + // start the movement process // argument is the disposal unit the holder started in diff --git a/code/modules/shuttles/shuttle_supply.dm b/code/modules/shuttles/shuttle_supply.dm index 55ee7d83b46..46398bc01f4 100644 --- a/code/modules/shuttles/shuttle_supply.dm +++ b/code/modules/shuttles/shuttle_supply.dm @@ -38,6 +38,7 @@ return if (!at_station()) //at centcom + SSmail.create_mail() SSsupply.buy() //We pretend it's a long_jump by making the shuttle stay at centcom for the "in-transit" period. @@ -93,4 +94,3 @@ //returns the ETA in deciseconds /datum/shuttle/autodock/ferry/supply/proc/eta_deciseconds() return round(arrive_time - world.time) - \ No newline at end of file diff --git a/icons/inventory/head/item.dmi b/icons/inventory/head/item.dmi index b56402e145d..80c522418a9 100644 Binary files a/icons/inventory/head/item.dmi and b/icons/inventory/head/item.dmi differ diff --git a/icons/inventory/head/mob.dmi b/icons/inventory/head/mob.dmi index af3083f5f73..9e986603aa9 100644 Binary files a/icons/inventory/head/mob.dmi and b/icons/inventory/head/mob.dmi differ diff --git a/icons/inventory/uniform/item.dmi b/icons/inventory/uniform/item.dmi index 6fe8d7345b7..044c91078c6 100644 Binary files a/icons/inventory/uniform/item.dmi and b/icons/inventory/uniform/item.dmi differ diff --git a/icons/inventory/uniform/mob.dmi b/icons/inventory/uniform/mob.dmi index 6fa7b536104..9c8f5c9aada 100644 Binary files a/icons/inventory/uniform/mob.dmi and b/icons/inventory/uniform/mob.dmi differ diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi index 61365297d24..0bae43c3955 100644 Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ diff --git a/icons/obj/coffee.dmi b/icons/obj/coffee.dmi new file mode 100644 index 00000000000..dfcbadd5b30 Binary files /dev/null and b/icons/obj/coffee.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 2a817ae4e0e..423bfd14b8a 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/lighters.dmi b/icons/obj/lighters.dmi index 8356af7b48b..23d0e2b9c55 100644 Binary files a/icons/obj/lighters.dmi and b/icons/obj/lighters.dmi differ diff --git a/sound/items/button-close.ogg b/sound/items/button-close.ogg new file mode 100644 index 00000000000..4139ac6e840 Binary files /dev/null and b/sound/items/button-close.ogg differ diff --git a/sound/items/button-open.ogg b/sound/items/button-open.ogg new file mode 100644 index 00000000000..83bedcdd362 Binary files /dev/null and b/sound/items/button-open.ogg differ diff --git a/sound/items/mail/mailapproved.ogg b/sound/items/mail/mailapproved.ogg new file mode 100644 index 00000000000..2f3135bc3c2 Binary files /dev/null and b/sound/items/mail/mailapproved.ogg differ diff --git a/sound/items/mail/maildenied.ogg b/sound/items/mail/maildenied.ogg new file mode 100644 index 00000000000..d8cdd0c107f Binary files /dev/null and b/sound/items/mail/maildenied.ogg differ diff --git a/sound/items/mail/mailscanned.ogg b/sound/items/mail/mailscanned.ogg new file mode 100644 index 00000000000..b2514370ba1 Binary files /dev/null and b/sound/items/mail/mailscanned.ogg differ diff --git a/sound/items/zippo_on_alt.ogg b/sound/items/zippo_on_alt.ogg new file mode 100644 index 00000000000..cad742f1bfe Binary files /dev/null and b/sound/items/zippo_on_alt.ogg differ diff --git a/vorestation.dme b/vorestation.dme index 0a68266eef7..c4ef5d23c24 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -368,6 +368,7 @@ #include "code\controllers\subsystems\job.dm" #include "code\controllers\subsystems\lighting.dm" #include "code\controllers\subsystems\machines.dm" +#include "code\controllers\subsystems\mail.dm" #include "code\controllers\subsystems\mapping.dm" #include "code\controllers\subsystems\media_tracks.dm" #include "code\controllers\subsystems\mobs.dm" @@ -943,6 +944,7 @@ #include "code\game\jobs\job\department.dm" #include "code\game\jobs\job\engineering.dm" #include "code\game\jobs\job\job.dm" +#include "code\game\jobs\job\job_goodies.dm" #include "code\game\jobs\job\medical.dm" #include "code\game\jobs\job\offduty.dm" #include "code\game\jobs\job\science.dm" @@ -1234,6 +1236,7 @@ #include "code\game\objects\explosion_recursive.dm" #include "code\game\objects\items.dm" #include "code\game\objects\items_vr.dm" +#include "code\game\objects\mail.dm" #include "code\game\objects\micro_event.dm" #include "code\game\objects\micro_structures.dm" #include "code\game\objects\mob_spawner_vr.dm" @@ -1274,6 +1277,7 @@ #include "code\game\objects\effects\chem\foam_vr.dm" #include "code\game\objects\effects\chem\water.dm" #include "code\game\objects\effects\decals\cleanable.dm" +#include "code\game\objects\effects\decals\contraband.dm" #include "code\game\objects\effects\decals\crayon.dm" #include "code\game\objects\effects\decals\misc.dm" #include "code\game\objects\effects\decals\remains.dm" @@ -1322,6 +1326,7 @@ #include "code\game\objects\items\glassjar.dm" #include "code\game\objects\items\gunbox.dm" #include "code\game\objects\items\gunbox_vr.dm" +#include "code\game\objects\items\holosign_creator.dm" #include "code\game\objects\items\latexballoon.dm" #include "code\game\objects\items\leash.dm" #include "code\game\objects\items\lockpicks.dm" @@ -1425,6 +1430,7 @@ #include "code\game\objects\items\toys\balls_vr.dm" #include "code\game\objects\items\toys\godfigures.dm" #include "code\game\objects\items\toys\mech_toys.dm" +#include "code\game\objects\items\toys\target_toy.dm" #include "code\game\objects\items\toys\toys.dm" #include "code\game\objects\items\toys\toys_vr.dm" #include "code\game\objects\items\weapons\AI_modules.dm" @@ -1650,6 +1656,7 @@ #include "code\game\objects\structures\grille.dm" #include "code\game\objects\structures\handrail.dm" #include "code\game\objects\structures\holoplant.dm" +#include "code\game\objects\structures\holosign.dm" #include "code\game\objects\structures\inflatable.dm" #include "code\game\objects\structures\janicart.dm" #include "code\game\objects\structures\kitchen_foodcart_vr.dm" @@ -3989,6 +3996,7 @@ #include "code\modules\reagents\reagent_containers\_reagent_containers.dm" #include "code\modules\reagents\reagent_containers\blood_pack.dm" #include "code\modules\reagents\reagent_containers\blood_pack_vr.dm" +#include "code\modules\reagents\reagent_containers\bluespacecoffee.dm" #include "code\modules\reagents\reagent_containers\borghypo.dm" #include "code\modules\reagents\reagent_containers\dropper.dm" #include "code\modules\reagents\reagent_containers\glass.dm"