diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index 8be56acbf3..ef15cfb26f 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -297,7 +297,7 @@ /obj/item/weapon/storage/part_replacer name = "rapid part exchange device" - desc = "Special mechanical module made to store, sort, and apply standard machine parts." + desc = "A special mechanical module made to store, sort, and apply standard machine parts." icon_state = "RPED" w_class = ITEMSIZE_HUGE can_hold = list(/obj/item/weapon/stock_parts) @@ -311,10 +311,11 @@ max_storage_space = 100 drop_sound = 'sound/items/drop/device.ogg' pickup_sound = 'sound/items/pickup/device.ogg' + var/panel_req = TRUE /obj/item/weapon/storage/part_replacer/adv name = "advanced rapid part exchange device" - desc = "Special mechanical module made to store, sort, and apply standard machine parts. This one has a greatly upgraded storage capacity" + desc = "A special mechanical module made to store, sort, and apply standard machine parts. This one has a greatly upgraded storage capacity." icon_state = "RPED" w_class = ITEMSIZE_HUGE can_hold = list(/obj/item/weapon/stock_parts) @@ -327,6 +328,31 @@ max_w_class = ITEMSIZE_NORMAL max_storage_space = 400 +/obj/item/weapon/storage/part_replacer/adv/discount_bluespace + name = "discount bluespace rapid part exchange device" + desc = "A special mechanical module made to store, sort, and apply standard machine parts. This one has a further increased storage capacity, \ + and the ability to work on machines with closed maintenance panels." + storage_slots = 400 + max_storage_space = 800 + panel_req = FALSE + +/obj/item/weapon/storage/part_replacer/drop_contents() // hacky-feeling tier-based drop system + hide_from(usr) + var/turf/T = get_turf(src) + var/lowest_rating = INFINITY // We want the lowest-part tier rating in the RPED so we only drop the lowest-tier parts. + /* + * Why not just use the stock part's rating variable? + * Future-proofing for a potential future where stock parts aren't the only thing that can fit in an RPED. + * see: /tg/ and /vg/'s RPEDs fitting power cells, beakers, etc. + */ + for(var/obj/item/B in contents) + if(B.rped_rating() < lowest_rating) + lowest_rating = B.rped_rating() + for(var/obj/item/B in contents) + if(B.rped_rating() > lowest_rating) + continue + remove_from_storage(B, T) + /obj/item/weapon/stock_parts name = "stock part" desc = "What?" @@ -342,6 +368,9 @@ src.pixel_y = rand(-5.0, 5) ..() +/obj/item/weapon/stock_parts/get_rating() + return rating + //Rank 1 /obj/item/weapon/stock_parts/console_screen diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index fe656d9e4a..a96ef4ed0a 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -327,7 +327,10 @@ Class Procs: return 0 if(!component_parts) return 0 - if(panel_open) + to_chat(user, "Following parts detected in [src]:") + for(var/obj/item/C in component_parts) + to_chat(user, " [C.name]") + if(panel_open || !R.panel_req) var/obj/item/weapon/circuitboard/CB = circuit var/P for(var/obj/item/weapon/stock_parts/A in component_parts) @@ -347,10 +350,6 @@ Class Procs: break update_icon() RefreshParts() - else - to_chat(user, "Following parts detected in the machine:") - for(var/var/obj/item/C in component_parts) //var/var/obj/item/C? - to_chat(user, " [C.name]") return 1 // Default behavior for wrenching down machines. Supports both delay and instant modes. diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index e90cf3aaea..6da2255e1b 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -942,3 +942,12 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. /obj/item/proc/openTip(location, control, params, user) openToolTip(user, src, params, title = name, content = desc) + +// These procs are for RPEDs and part ratings. The concept for this was borrowed from /vg/station. +// Gets the rating of the item, used in stuff like machine construction. +/obj/item/proc/get_rating() + return FALSE + +// Like the above, but used for RPED sorting of parts. +/obj/item/proc/rped_rating() + return get_rating() \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 4759b06667..64de9b68a2 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -523,9 +523,11 @@ if(((!(ishuman(usr) || isrobot(usr))) && (src.loc != usr)) || usr.stat || usr.restrained()) return + drop_contents() - var/turf/T = get_turf(src) +/obj/item/weapon/storage/proc/drop_contents() // why is this a proc? literally just for RPEDs hide_from(usr) + var/turf/T = get_turf(src) for(var/obj/item/I in contents) remove_from_storage(I, T) diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm index 78d8f9d323..005c0f07d1 100644 --- a/code/modules/research/destructive_analyzer.dm +++ b/code/modules/research/destructive_analyzer.dm @@ -15,6 +15,7 @@ Note: Must be placed within 3 tiles of the R&D Console use_power = USE_POWER_IDLE idle_power_usage = 30 active_power_usage = 2500 + var/rped_recycler_ready = TRUE /obj/machinery/r_n_d/destructive_analyzer/Initialize() . = ..() @@ -22,7 +23,7 @@ Note: Must be placed within 3 tiles of the R&D Console /obj/machinery/r_n_d/destructive_analyzer/RefreshParts() var/T = 0 - for(var/obj/item/weapon/stock_parts/S in src) + for(var/obj/item/weapon/stock_parts/S in component_parts) T += S.rating decon_mod = T * 0.1 @@ -76,3 +77,44 @@ Note: Must be placed within 3 tiles of the R&D Console busy = 0 return 1 return + +/obj/machinery/r_n_d/destructive_analyzer/MouseDrop_T(atom/dropping, mob/living/user) + if(istype(dropping, /obj/item/weapon/storage/part_replacer)) + var/obj/item/weapon/storage/part_replacer/replacer = dropping + replacer.hide_from(user) + if(!linked_console) + to_chat(user, "\The [src] must be linked to an R&D console first.") + return 0 + if(!linked_console.linked_lathe) + to_chat(user, "Link a protolathe to [src]'s R&D console first.") + return 0 + if(!rped_recycler_ready) + to_chat(user, "\The [src]'s stock parts recycler isn't ready yet.") + return 0 + var/obj/machinery/r_n_d/protolathe/lathe_to_fill = linked_console.linked_lathe + var/lowest_rating = INFINITY // We want the lowest-part tier rating in the RPED so we only recycle the lowest-tier parts. + for(var/obj/item/B in replacer.contents) + if(B.rped_rating() < lowest_rating) + lowest_rating = B.rped_rating() + if(lowest_rating == INFINITY) + to_chat(user, "Mass part deconstruction attempt canceled - no valid parts for recycling detected.") + return 0 + for(var/obj/item/B in replacer.contents) + if(B.rped_rating() > lowest_rating) + continue + if(lathe_to_fill && B.matter) // Sending salvaged materials to the lathe... + for(var/t in B.matter) + if(t in lathe_to_fill.materials) + lathe_to_fill.materials[t] += B.matter[t] * src.decon_mod + qdel(B) + playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) + rped_recycler_ready = FALSE + addtimer(CALLBACK(src, .proc/rped_ready), 5 SECONDS) + to_chat(user, "You deconstruct all the parts of rating [lowest_rating] in [replacer] with [src].") + return 1 + else + ..() + +/obj/machinery/r_n_d/destructive_analyzer/proc/rped_ready() + rped_recycler_ready = TRUE + playsound(get_turf(src), 'sound/machines/chime.ogg', 50, 1) \ No newline at end of file