RPED Update (#22750)

RPEDS now work on most machinery via attackby() handler.

Part matching checks circuit-board requirements and the machine's
component_types which fixes the science telepad RPED compatability.

Alt-clicking an autolathe with an RPED now recycles the materials in the
autolathe.

Normal lmb activity is preserved on the autolathe.

Signed-off-by: mineymonkey <brandontanner63@outlook.com>
This commit is contained in:
mineymonkey
2026-08-02 01:24:58 +00:00
committed by GitHub
parent 7172d3dbe3
commit 9eb7413a75
6 changed files with 117 additions and 30 deletions
+39 -17
View File
@@ -370,6 +370,9 @@ Class Procs:
attack_hand(user)
/obj/structure/machinery/attackby(obj/item/attacking_item, mob/user)
if(default_part_replacement(user, attacking_item))
return TRUE
if(obj_flags & OBJ_FLAG_SIGNALER)
if(issignaler(attacking_item))
if(signaler)
@@ -488,23 +491,43 @@ Class Procs:
update_icon()
return TRUE
/obj/structure/machinery/proc/get_part_replacement_type(obj/item/part)
var/obj/item/circuitboard/board = locate(/obj/item/circuitboard) in component_parts
var/replacement_type
if(board?.req_components)
for(var/component_type in board.req_components)
var/board_part_type = ispath(component_type) ? component_type : text2path(component_type)
if(!ispath(board_part_type, /obj/item/stock_parts) && !ispath(board_part_type, /obj/item/reagent_containers/glass))
continue
if(istype(part, board_part_type) && (!replacement_type || ispath(board_part_type, replacement_type)))
replacement_type = board_part_type
if(replacement_type)
return replacement_type
for(var/component_type in component_types)
var/component_part_type = ispath(component_type) ? component_type : text2path(component_type)
if(!ispath(component_part_type, /obj/item/stock_parts) && !ispath(component_part_type, /obj/item/reagent_containers/glass))
continue
if(istype(part, component_part_type) && (!replacement_type || ispath(component_part_type, replacement_type)))
replacement_type = component_part_type
return replacement_type
/obj/structure/machinery/proc/default_part_replacement(var/mob/user, var/obj/item/storage/part_replacer/R)
if(!LAZYLEN(component_parts))
return FALSE
else if(istype(R))
var/parts_replaced = FALSE
if(panel_open)
var/obj/item/circuitboard/CB = locate(/obj/item/circuitboard) in component_parts
var/P
for(var/obj/item/reagent_containers/glass/G in component_parts)
for(var/D in CB.req_components)
var/T = text2path(D)
if(ispath(G.type, T))
P = T
break
var/replacement_type = get_part_replacement_type(G)
if(!replacement_type)
continue
for(var/obj/item/reagent_containers/glass/B in R.contents)
if(B.reagents && B.reagents.total_volume > 0) continue
if(istype(B, P) && istype(G, P))
if(istype(B, replacement_type))
if(B.volume > G.volume)
R.remove_from_storage(B, src)
R.handle_item_insertion(G, 1)
@@ -512,15 +535,14 @@ Class Procs:
component_parts += B
B.forceMove(src)
to_chat(user, SPAN_NOTICE("[G.name] replaced with [B.name]."))
parts_replaced = TRUE
break
for(var/obj/item/stock_parts/A in component_parts)
for(var/D in CB.req_components)
var/T = text2path(D)
if(ispath(A.type, T))
P = T
break
var/replacement_type = get_part_replacement_type(A)
if(!replacement_type)
continue
for(var/obj/item/stock_parts/B in R.contents)
if(istype(B, P) && istype(A, P))
if(istype(B, replacement_type))
if(B.rating > A.rating)
R.remove_from_storage(B, src)
R.handle_item_insertion(A, 1)
@@ -530,9 +552,9 @@ Class Procs:
to_chat(user, SPAN_NOTICE("[A.name] replaced with [B.name]."))
parts_replaced = TRUE
break
RefreshParts()
update_icon()
if(parts_replaced) //only play sound when RPED actually replaces parts
if(parts_replaced)
RefreshParts()
update_icon()
playsound(src, 'sound/items/rped.ogg', 40, TRUE)
return TRUE
else
+25
View File
@@ -188,6 +188,7 @@ ABSTRACT_TYPE(/obj/structure/machinery/fabricator)
return TRUE
if(default_deconstruction_crowbar(user, attacking_item))
return TRUE
if(default_part_replacement(user, attacking_item))
return TRUE
@@ -212,6 +213,30 @@ ABSTRACT_TYPE(/obj/structure/machinery/fabricator)
load_lathe(attacking_item, user)
return TRUE
/obj/structure/machinery/fabricator/autolathe/proc/recycle_rped_contents(obj/item/storage/part_replacer/R, mob/user)
var/recycled = 0
var/recyclable = 0
var/rejected = 0
for(var/obj/item/item in R.contents.Copy())
if(!item.matter || !item.recyclable)
continue
recyclable++
if(load_lathe(item, user, FALSE))
recycled++
else
rejected++
if(recycled)
to_chat(user, SPAN_NOTICE("You recycle [recycled] item\s from \the [R] into \the [src]."))
else if(!recyclable)
to_chat(user, SPAN_WARNING("\The [R] contains no recyclable materials for \the [src]."))
else
to_chat(user, SPAN_WARNING("\The [src] could not accept any recyclable contents from \the [R]."))
if(rejected)
to_chat(user, SPAN_WARNING("Some contents could not be accepted and remain in \the [R]."))
/obj/structure/machinery/fabricator/attack_hand(mob/user)
user.set_machine(src)
ui_interact(user)
+20 -13
View File
@@ -3,13 +3,14 @@
#define FILL_INCOMPLETELY "Fill Incompletely"
///Loads the lathe with materials
/obj/structure/machinery/fabricator/proc/load_lathe(obj/item/loading_item, mob/user)
/obj/structure/machinery/fabricator/proc/load_lathe(obj/item/loading_item, mob/user, show_messages = TRUE)
//Resources are being loaded.
var/obj/item/eating = loading_item
if(!eating.matter || !eating.recyclable)
to_chat(user, SPAN_WARNING("\The [eating] cannot be recycled by \the [src]."))
return
if(show_messages)
to_chat(user, SPAN_WARNING("\The [eating] cannot be recycled by \the [src]."))
return FALSE
var/list/fill_status = list() // Used to determine message in cases of multiple materials.
var/total_used = 0 // Amount of material used.
@@ -44,17 +45,21 @@
total_used += total_material
mass_per_sheet += eating.matter[material]
if(total_used <= 0 || mass_per_sheet <= 0)
if(fill_status[NO_SPACE])
to_chat(user, SPAN_WARNING("\The [src] is full of [english_list(fill_status[NO_SPACE])]. Please remove some material in order to insert more."))
else
to_chat(user, SPAN_WARNING("\The [src] cannot accept any materials from \the [eating]."))
return
if(total_used <= 0)
if(show_messages)
if(fill_status[NO_SPACE])
to_chat(user, SPAN_WARNING("\The [src] is full of [english_list(fill_status[NO_SPACE])]. Please remove some material in order to insert more."))
else
to_chat(user, SPAN_WARNING("\The [eating] contains no materials accepted by \the [src]."))
return FALSE
if(fill_status[FILL_COMPLETELY])
to_chat(user, SPAN_NOTICE("You fill \the [src] to capacity with [english_list(fill_status[FILL_COMPLETELY])][is_stack ? "." : " from \the [eating]."]"))
else if(fill_status[FILL_INCOMPLETELY])
to_chat(user, SPAN_NOTICE("You fill \the [src] with [english_list(fill_status[FILL_INCOMPLETELY])][is_stack ? "." : " from \the [eating]."]"))
if(show_messages)
if(fill_status[NO_SPACE])
to_chat(user, SPAN_WARNING("\The [src] could not accept [english_list(fill_status[NO_SPACE])] from \the [eating]."))
if(fill_status[FILL_COMPLETELY])
to_chat(user, SPAN_NOTICE("You fill \the [src] to capacity with [english_list(fill_status[FILL_COMPLETELY])][is_stack ? "." : " from \the [eating]."]"))
else if(fill_status[FILL_INCOMPLETELY])
to_chat(user, SPAN_NOTICE("You fill \the [src] with [english_list(fill_status[FILL_INCOMPLETELY])][is_stack ? "." : " from \the [eating]."]"))
// Plays metal insertion animation.
if(istype(eating, /obj/item/stack/material) && does_flick)
@@ -76,6 +81,8 @@
user.remove_from_mob(loading_item)
qdel(loading_item)
return TRUE
#undef NO_SPACE
#undef FILL_COMPLETELY
#undef FILL_INCOMPLETELY
@@ -4,6 +4,29 @@
icon = 'icons/obj/machinery/fabricators/autolathe.dmi'
icon_state = "autolathe"
/obj/structure/machinery/fabricator/autolathe/mechanics_hints(mob/user, distance, is_adjacent)
. = ..()
. += "Alt-click with a rapid part exchange device in your active hand to recycle its compatible contents."
/obj/structure/machinery/fabricator/autolathe/AltClick(mob/user)
. = ..()
if(use_check_and_message(user))
return
var/obj/item/storage/part_replacer/R = user.get_active_hand()
if(!istype(R))
return
if(fab_status_flags & FAB_BUSY)
to_chat(user, SPAN_NOTICE("\The [src] is busy. Please wait for the completion of the previous operation."))
return
if(stat || !is_functioning())
to_chat(user, SPAN_WARNING("\The [src] cannot accept materials in its current state."))
return
recycle_rped_contents(R, user)
/obj/structure/machinery/fabricator/autolathe/mounted
name = "\improper mounted autolathe"
density = FALSE
+3
View File
@@ -35,6 +35,9 @@
if(default_deconstruction_screwdriver(user, attacking_item))
return
if(default_part_replacement(user, attacking_item))
return
if(panel_open)
if(attacking_item.tool_behaviour == TOOL_MULTITOOL)
var/obj/item/multitool/M = attacking_item
@@ -0,0 +1,7 @@
author: Mineymonkey
delete-after: True
changes:
- bugfix: "Rapid part exchange devices can now upgrade stock parts in all compatible machinery, including science telepads."
- qol: "Alt-clicking an autolathe with a rapid part exchange device in your active hand now recycles its compatible contents, leaving rejected items inside."