mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-19 12:05:59 +01:00
Adds a mail sorting unit to sort mail per department; some flatpack stuff (#88288)
Adds a mail sorting unit! The unit accepts mail, stores it and sorts it per department. It can also search for individual envelopes, change it's output tile and be VERY loud. At the meantime, this PR also adds two flatpack subtypes - flatpacker subtype and mail sorter subtype. The first one is intended to be used by mappers to have a flatpacker be accessible roundstart, and the second one is now sold at cargo wardrobes to make the mail sorter also available roundstart.
This commit is contained in:
@@ -477,3 +477,9 @@
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
#undef MAX_FLAT_PACKS
|
||||
|
||||
/obj/item/flatpack/flatpacker // a roundstart flatpacker is NICE you can gahdamn tell the time and everythin'
|
||||
board = /obj/item/circuitboard/machine/flatpacker
|
||||
|
||||
/obj/item/flatpack/mailsorter // to have a roundstart mail sorter at cargo
|
||||
board = /obj/item/circuitboard/machine/mailsorter
|
||||
|
||||
@@ -1466,6 +1466,16 @@
|
||||
/datum/stock_part/scanning_module = 1,
|
||||
/datum/stock_part/card_reader = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/mailsorter
|
||||
name = "Mail Sorter"
|
||||
greyscale_colors = CIRCUIT_COLOR_SUPPLY
|
||||
build_path = /obj/machinery/mailsorter
|
||||
req_components = list(
|
||||
/obj/item/stack/sheet/glass = 1,
|
||||
/datum/stock_part/matter_bin = 2,
|
||||
/datum/stock_part/scanning_module = 1)
|
||||
needs_anchored = TRUE
|
||||
|
||||
//Tram
|
||||
/obj/item/circuitboard/machine/crossing_signal
|
||||
name = "Crossing Signal"
|
||||
|
||||
@@ -1347,3 +1347,13 @@
|
||||
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ENGINEERING
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO
|
||||
|
||||
/datum/design/board/mailsorter
|
||||
name = "Mail Sorter"
|
||||
desc = "The circuit board for a mail sorting unit."
|
||||
id = "mailsorter"
|
||||
build_path = /obj/item/circuitboard/machine/mailsorter
|
||||
category = list(
|
||||
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_CARGO
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_ENGINEERING
|
||||
|
||||
@@ -155,6 +155,7 @@
|
||||
"manulathe",
|
||||
"manusorter",
|
||||
"manurouter",
|
||||
"mailsorter",
|
||||
)
|
||||
|
||||
/datum/techweb_node/energy_manipulation
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
#define STATE_SORTING "sorting"
|
||||
#define STATE_IDLE "idle"
|
||||
#define STATE_YES "yes"
|
||||
#define STATE_NO "no"
|
||||
#define MAIL_CAPACITY 100
|
||||
|
||||
/obj/machinery/mailsorter
|
||||
name = "mail sorter"
|
||||
desc = "A large mail sorting unit. Sorting mail since 1987!"
|
||||
icon = 'icons/obj/machines/mailsorter.dmi'
|
||||
icon_state = "mailsorter"
|
||||
base_icon_state = "mailsorter"
|
||||
layer = BELOW_OBJ_LAYER
|
||||
density = TRUE
|
||||
max_integrity = 300
|
||||
integrity_failure = 0.33
|
||||
req_access = list(ACCESS_CARGO)
|
||||
circuit = /obj/item/circuitboard/machine/mailsorter
|
||||
|
||||
var/light_mask = "mailsorter-light-mask"
|
||||
var/panel_type = "panel"
|
||||
|
||||
/// What the machine is currently doing. Can be "sorting", "idle", "yes", "no".
|
||||
var/currentstate = STATE_IDLE
|
||||
/// List of all mail that's inside the mailbox.
|
||||
var/list/mail_list = list()
|
||||
/// The direction in which the mail will be unloaded.
|
||||
var/output_dir = SOUTH
|
||||
/// List of the departments to sort the mail for.
|
||||
var/static/list/sorting_departments = list(
|
||||
DEPARTMENT_ENGINEERING,
|
||||
DEPARTMENT_SECURITY,
|
||||
DEPARTMENT_MEDICAL,
|
||||
DEPARTMENT_SCIENCE,
|
||||
DEPARTMENT_CARGO,
|
||||
DEPARTMENT_SERVICE,
|
||||
DEPARTMENT_COMMAND,
|
||||
)
|
||||
var/static/list/choices = list(
|
||||
"Eject" = icon('icons/hud/radial.dmi', "radial_eject"),
|
||||
"Dump" = icon('icons/hud/radial.dmi', "mail_dump"),
|
||||
"Sort" = icon('icons/hud/radial.dmi', "mail_sort"),
|
||||
)
|
||||
|
||||
/// Steps one tile in the `output_dir`. Returns `turf`.
|
||||
/obj/machinery/mailsorter/proc/get_unload_turf()
|
||||
return get_step(src, output_dir)
|
||||
|
||||
/obj/machinery/mailsorter/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
default_deconstruction_screwdriver(user, "[base_icon_state]-off", base_icon_state, tool)
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/machinery/mailsorter/crowbar_act(mob/living/user, obj/item/tool)
|
||||
default_deconstruction_crowbar(tool)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/machinery/mailsorter/examine(mob/user)
|
||||
. = ..()
|
||||
. += span_notice("There is[length(mail_list) < 100 ? " " : " no more "]space for <b>[length(mail_list) < 100 ? "[100 - length(mail_list)] " : ""]</b>envelope\s inside.")
|
||||
. += span_notice("There [length(mail_list) >= 2 ? "are" : "is"] <b>[length(mail_list) ? length(mail_list) : "no"]</b> envelope\s inside.")
|
||||
if(panel_open)
|
||||
. += span_notice("Alt-click to rotate the output direction.")
|
||||
|
||||
/obj/machinery/mailsorter/Destroy()
|
||||
drop_all_mail()
|
||||
. = ..()
|
||||
|
||||
/// Drops all enevlopes on the machine turf. Only occurs when the machine is broken.
|
||||
/obj/machinery/mailsorter/proc/drop_all_mail(damage_flag)
|
||||
if(!isturf(get_turf(src)))
|
||||
QDEL_LIST(mail_list)
|
||||
return
|
||||
for(var/obj/item/mail in mail_list)
|
||||
mail.forceMove(src)
|
||||
mail_list -= mail
|
||||
|
||||
/// Dumps all envelopes on the `unload_turf`.
|
||||
/obj/machinery/mailsorter/proc/dump_all_mail()
|
||||
if(!isturf(get_turf(src)))
|
||||
QDEL_LIST(mail_list)
|
||||
return
|
||||
var/turf/unload_turf = get_unload_turf()
|
||||
for(var/obj/item/mail in mail_list)
|
||||
mail.forceMove(unload_turf)
|
||||
mail.throw_at(unload_turf, 2, 3)
|
||||
mail_list -= mail
|
||||
|
||||
/// Validates whether the inserted item is acceptable.
|
||||
/obj/machinery/mailsorter/proc/accept_check(obj/item/weapon)
|
||||
var/static/list/accepted_items = list(
|
||||
/obj/item/mail,
|
||||
/obj/item/mail/envelope,
|
||||
/obj/item/mail/junkmail,
|
||||
/obj/item/mail/mail_strike,
|
||||
/obj/item/mail/traitor,
|
||||
/obj/item/paper,
|
||||
)
|
||||
return is_type_in_list(weapon, accepted_items)
|
||||
|
||||
/obj/machinery/mailsorter/interact(mob/user)
|
||||
if (!allowed(user))
|
||||
to_chat(user, span_warning("Access denied."))
|
||||
return
|
||||
if (currentstate != STATE_IDLE)
|
||||
return
|
||||
if (length(mail_list) == 0)
|
||||
to_chat(user, span_warning("There's no mail inside!"))
|
||||
return
|
||||
var/choice = show_radial_menu(
|
||||
user,
|
||||
src,
|
||||
choices,
|
||||
require_near = !HAS_SILICON_ACCESS(user),
|
||||
autopick_single_option = FALSE,
|
||||
)
|
||||
if (!choice)
|
||||
return
|
||||
switch (choice)
|
||||
if ("Eject")
|
||||
pick_mail(user)
|
||||
if ("Dump")
|
||||
playsound(src, 'sound/machines/buzz/buzz-sigh.ogg', 20, TRUE)
|
||||
to_chat(user, span_notice("[src] dumps [length(mail_list)] envelope\s on the floor."))
|
||||
dump_all_mail()
|
||||
if ("Sort")
|
||||
sort_mail(user)
|
||||
|
||||
/// Prompts the player to select a department to sort the mail for. Returns if `null`.
|
||||
/obj/machinery/mailsorter/proc/sort_mail(mob/user)
|
||||
var/sorting_dept = tgui_input_list(user, "Choose the department to sort mail for","Mail Sorting", sorting_departments)
|
||||
if (!sorting_dept)
|
||||
return
|
||||
currentstate = STATE_SORTING
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
playsound(src, 'sound/machines/mail_sort.ogg', 20, TRUE)
|
||||
addtimer(CALLBACK(src, PROC_REF(continue_sort), user, sorting_dept), 5 SECONDS)
|
||||
|
||||
/// Sorts the mail based on the picked department. Ejects the sorted envelopes onto the `unload_turf`.
|
||||
/obj/machinery/mailsorter/proc/continue_sort(mob/user, sorting_dept)
|
||||
var/list/sorted_mail = list()
|
||||
var/total_to_sort = length(mail_list)
|
||||
var/sorted = 0
|
||||
var/unable_to_sort = 0
|
||||
|
||||
for (var/obj/item/mail/some_mail in mail_list)
|
||||
if (!some_mail.recipient_ref)
|
||||
unable_to_sort ++
|
||||
continue
|
||||
var/datum/mind/some_recipient = some_mail.recipient_ref.resolve()
|
||||
if (some_recipient)
|
||||
var/datum/job/recipient_job = some_recipient.assigned_role
|
||||
var/datum/job_department/primary_department = recipient_job.departments_list?[1]
|
||||
var/datum/job_department/main_department = primary_department.department_name
|
||||
if (main_department == sorting_dept)
|
||||
sorted_mail.Add(some_mail)
|
||||
sorted ++
|
||||
else
|
||||
unable_to_sort ++
|
||||
if (length(sorted_mail) == 0)
|
||||
currentstate = STATE_NO
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
playsound(src, 'sound/machines/buzz/buzz-sigh.ogg', 20, TRUE)
|
||||
say("No mail for the following department: [sorting_dept].")
|
||||
else
|
||||
currentstate = STATE_YES
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
say("[sorted] envelope\s sorted successfully.")
|
||||
playsound(src, 'sound/machines/ping.ogg', 20, TRUE)
|
||||
to_chat(user, span_notice("[src] ejects [length(sorted_mail)] envelope\s."))
|
||||
var/turf/unload_turf = get_unload_turf()
|
||||
for (var/obj/item/mail/mail_in_list in sorted_mail)
|
||||
mail_in_list.forceMove(unload_turf)
|
||||
sorted_mail -= mail_in_list
|
||||
mail_list -= mail_in_list
|
||||
addtimer(CALLBACK(src, PROC_REF(check_sorted), unable_to_sort, total_to_sort), 1 SECONDS)
|
||||
|
||||
/// Informs the player of the amount of processed envelopes.
|
||||
/obj/machinery/mailsorter/proc/check_sorted(mob/user, unable_to_sort, total_to_sort)
|
||||
if (unable_to_sort > 0)
|
||||
playsound(src, 'sound/machines/buzz/buzz-sigh.ogg', 20, TRUE)
|
||||
say("Couldn't sort [unable_to_sort] envelope\s.")
|
||||
else
|
||||
playsound(src, 'sound/machines/ping.ogg', 20, TRUE)
|
||||
say("[total_to_sort] envelope\s processed.")
|
||||
addtimer(CALLBACK(src, PROC_REF(update_state_after_sorting)), 1 SECONDS)
|
||||
|
||||
/obj/machinery/mailsorter/proc/update_state_after_sorting()
|
||||
currentstate = STATE_IDLE
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/machinery/mailsorter/item_interaction(mob/user, obj/item/thingy, params)
|
||||
if (istype(thingy, /obj/item/storage/bag/mail))
|
||||
if (length(thingy.contents) < 1)
|
||||
to_chat(user, span_warning("The [thingy] is empty!"))
|
||||
return
|
||||
var/loaded = 0
|
||||
for (var/obj/item/mail in thingy.contents)
|
||||
if (!(mail.item_flags & ABSTRACT) && \
|
||||
!(mail.flags_1 & HOLOGRAM_1) && \
|
||||
accept_check(mail) \
|
||||
)
|
||||
if (length(mail_list) + 1 > MAIL_CAPACITY )
|
||||
to_chat(user, span_warning("There is no space for more mail in [src]!"))
|
||||
return FALSE
|
||||
else if (load(mail, user))
|
||||
loaded++
|
||||
mail_list += mail
|
||||
if(loaded)
|
||||
user.visible_message(span_notice("[user] loads \the [src] with \the [thingy]."), \
|
||||
span_notice("You load \the [src] with \the [thingy]."))
|
||||
if(length(thingy.contents))
|
||||
to_chat(user, span_warning("Some items are refused."))
|
||||
return TRUE
|
||||
else
|
||||
to_chat(user, span_warning("There is nothing in \the [thingy] to put in the [src]!"))
|
||||
return FALSE
|
||||
else if (istype(thingy, /obj/item/mail))
|
||||
if (length(mail_list) + 1 > MAIL_CAPACITY )
|
||||
to_chat(user, span_warning("There is no space for more mail in [src]!"))
|
||||
else
|
||||
thingy.forceMove(src)
|
||||
mail_list += thingy
|
||||
to_chat(user, span_notice("The [src] whizzles as it accepts the [thingy]."))
|
||||
|
||||
/// Prompts the user to select an anvelope from the list of all the envelopes inside.
|
||||
/obj/machinery/mailsorter/proc/pick_mail(mob/user)
|
||||
if(!length(mail_list))
|
||||
return
|
||||
var/obj/item/mail/mail_throw = tgui_input_list(user, "Choose the envelope to eject","Mail Sorting", mail_list)
|
||||
if(!mail_throw)
|
||||
return
|
||||
currentstate = STATE_SORTING
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
playsound(src, 'sound/machines/mail_sort.ogg', 20, TRUE)
|
||||
addtimer(CALLBACK(src, PROC_REF(pick_envelope), user, mail_throw), 50)
|
||||
|
||||
/// Ejects a single envelope the player has picked onto the `unload_turf`.
|
||||
/obj/machinery/mailsorter/proc/pick_envelope(mob/user, obj/item/mail/mail_throw)
|
||||
to_chat(user, span_notice("[src] reluctantly spits out [mail_throw]."))
|
||||
var/turf/unload_turf = get_unload_turf()
|
||||
mail_throw.forceMove(unload_turf)
|
||||
mail_throw.throw_at(unload_turf, 2, 3)
|
||||
mail_list -= mail_throw
|
||||
currentstate = STATE_IDLE
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
|
||||
/// Tries to load something into the machine.
|
||||
/obj/machinery/mailsorter/proc/load(obj/item/thingy, mob/user)
|
||||
if(ismob(thingy.loc))
|
||||
var/mob/owner = thingy.loc
|
||||
if(!owner.transferItemToLoc(thingy, src))
|
||||
to_chat(owner, span_warning("\the [thingy] is stuck to your hand, you cannot put it in \the [src]!"))
|
||||
return FALSE
|
||||
return TRUE
|
||||
else
|
||||
if(thingy.loc.atom_storage)
|
||||
return thingy.loc.atom_storage.attempt_remove(thingy, src, silent = TRUE)
|
||||
else
|
||||
thingy.forceMove(src)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mailsorter/click_alt(mob/living/user)
|
||||
if(!panel_open)
|
||||
return CLICK_ACTION_BLOCKING
|
||||
output_dir = turn(output_dir, -90)
|
||||
to_chat(user, span_notice("You change [src]'s I/O settings, setting the output to [dir2text(output_dir)]."))
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
return CLICK_ACTION_SUCCESS
|
||||
|
||||
|
||||
/obj/machinery/mailsorter/update_overlays()
|
||||
. = ..()
|
||||
if(!powered())
|
||||
return
|
||||
if(!(machine_stat & BROKEN))
|
||||
var/image/mail_output = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_[output_dir]")
|
||||
switch(output_dir)
|
||||
if(NORTH)
|
||||
mail_output.pixel_y = 32
|
||||
if(SOUTH)
|
||||
mail_output.pixel_y = -32
|
||||
if(EAST)
|
||||
mail_output.pixel_x = 32
|
||||
if(WEST)
|
||||
mail_output.pixel_x = -32
|
||||
mail_output.color = COLOR_CRAYON_ORANGE
|
||||
var/mutable_appearance/light_out = emissive_appearance(mail_output.icon, mail_output.icon_state, offset_spokesman = src, alpha = mail_output.alpha)
|
||||
light_out.pixel_y = mail_output.pixel_y
|
||||
light_out.pixel_x = mail_output.pixel_x
|
||||
. += mail_output
|
||||
. += light_out
|
||||
. += mutable_appearance(base_icon_state, currentstate)
|
||||
if(panel_open)
|
||||
. += panel_type
|
||||
if(light_mask && !(machine_stat & BROKEN))
|
||||
. += emissive_appearance(icon, light_mask, src)
|
||||
|
||||
/obj/machinery/mailsorter/update_icon_state()
|
||||
icon_state = "[base_icon_state][powered() ? null : "-off"]"
|
||||
if(machine_stat & BROKEN)
|
||||
icon_state = "[base_icon_state]-broken"
|
||||
return ..()
|
||||
|
||||
#undef STATE_SORTING
|
||||
#undef STATE_IDLE
|
||||
#undef STATE_YES
|
||||
#undef STATE_NO
|
||||
#undef MAIL_CAPACITY
|
||||
@@ -202,6 +202,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE)
|
||||
/obj/item/storage/bag/mail = 3,
|
||||
/obj/item/radio/headset/headset_cargo = 3,
|
||||
/obj/item/clothing/accessory/pocketprotector = 3,
|
||||
/obj/item/flatpack/mailsorter = 1,
|
||||
)
|
||||
premium = list(
|
||||
/obj/item/clothing/head/costume/mailman = 1,
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 114 KiB |
@@ -4,3 +4,5 @@ This is licensed under CC-BY 4.0, found at https://creativecommons.org/licenses/
|
||||
|
||||
shutter.ogg adapted from Joseph Sardin on BigSoundBank
|
||||
https://bigsoundbank.com/detail-2475-manual-roller-shutter-closing-out-2.html
|
||||
|
||||
mail_sort.ogg adapted from csigusz_foxoup ob Freesound https://freesound.org/people/csigusz_foxoup/sounds/711428/
|
||||
Binary file not shown.
@@ -6328,6 +6328,7 @@
|
||||
#include "code\modules\vending\liberation.dm"
|
||||
#include "code\modules\vending\liberation_toy.dm"
|
||||
#include "code\modules\vending\magivend.dm"
|
||||
#include "code\modules\vending\mail.dm"
|
||||
#include "code\modules\vending\medical.dm"
|
||||
#include "code\modules\vending\medical_wall.dm"
|
||||
#include "code\modules\vending\megaseed.dm"
|
||||
|
||||
Reference in New Issue
Block a user