diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index ea3b9df4f54..3c541a308ff 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -305,6 +305,10 @@
/atom/proc/rpd_act()
return
+/atom/proc/rpd_blocksusage()
+ // Atoms that return TRUE prevent RPDs placing any kind of pipes on their turf.
+ return FALSE
+
/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked)
if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...).
addtimer(CALLBACK(src, .proc/hitby_react, AM), 2)
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index 270b2a99411..e84d0778ef3 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -140,6 +140,7 @@
//update the name and icon of the pipe item depending on the type
/obj/item/pipe/rpd_act(mob/user, obj/item/rpd/our_rpd)
+ . = TRUE
if(our_rpd.mode == RPD_ROTATE_MODE)
rotate()
else if(our_rpd.mode == RPD_FLIP_MODE)
@@ -147,7 +148,7 @@
else if(our_rpd.mode == RPD_DELETE_MODE)
our_rpd.delete_single_pipe(user, src)
else
- ..()
+ return ..()
/obj/item/pipe/proc/update(var/obj/machinery/atmospherics/make_from)
name = "[get_pipe_name(pipe_type, PIPETYPE_ATMOS)] fitting"
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index 6d79a65dcbd..f1e27be33fa 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -541,6 +541,8 @@
/obj/machinery/shieldwall/attack_hand(mob/user as mob)
return
+/obj/machinery/shieldwall/rpd_blocksusage()
+ return TRUE
/obj/machinery/shieldwall/process()
if(needs_power)
diff --git a/code/game/objects/items/weapons/rpd.dm b/code/game/objects/items/weapons/rpd.dm
index ffcb2e06785..c139155b57c 100644
--- a/code/game/objects/items/weapons/rpd.dm
+++ b/code/game/objects/items/weapons/rpd.dm
@@ -192,11 +192,27 @@ var/list/pipemenu = list(
return
if(world.time < lastused + spawndelay)
return
+
+
var/turf/T = get_turf(target)
- for(var/obj/machinery/shieldwall/S in T)
- to_chat(user, "[S] blocks access!")
- return
- target.rpd_act(user, src) //Handle RPD effects in separate procs
+ if(target != T)
+ // We only check the rpd_act of the target if it isn't the turf, because otherwise
+ // (A) blocked turfs can be acted on, and (B) unblocked turfs get acted on twice.
+ if(target.rpd_act(user, src) == TRUE)
+ // If the object we are clicking on has a valid RPD interaction for just that specific object, do that and nothing else.
+ // Example: clicking on a pipe with a RPD in rotate mode should rotate that pipe and ignore everything else on the tile.
+ return
+
+ // If we get this far, we have to check every object in the tile, to make sure that none of them block RPD usage on this tile.
+ // This is done by calling rpd_blocksusage on every /obj in the tile. If any block usage, fail at this point.
+
+ for(var/obj/O in T)
+ if(O.rpd_blocksusage() == TRUE)
+ to_chat(user, "[O] blocks the [src]!")
+ return
+
+ // If we get here, then we're effectively acting on the turf, probably placing a pipe.
+ T.rpd_act(user, src)
#undef RPD_COOLDOWN_TIME
#undef RPD_WALLBUILD_TIME
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index a7e57ce5a52..6c7094fbe9f 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -71,10 +71,6 @@
SSnanoui.close_uis(src)
return ..()
-/obj/rpd_act(mob/user, obj/item/rpd/our_rpd)
- var/turf/T = get_turf(src) //This preserves RPD behaviour on specific turfs
- T.rpd_act(user, our_rpd)
-
/obj/proc/process()
set waitfor = 0
processing_objects.Remove(src)
diff --git a/code/modules/recycling/disposal-construction.dm b/code/modules/recycling/disposal-construction.dm
index c7e276cae17..3bb3c237d07 100644
--- a/code/modules/recycling/disposal-construction.dm
+++ b/code/modules/recycling/disposal-construction.dm
@@ -258,6 +258,7 @@
return
/obj/structure/disposalconstruct/rpd_act(mob/user, obj/item/rpd/our_rpd)
+ . = TRUE
if(our_rpd.mode == RPD_ROTATE_MODE)
rotate()
else if(our_rpd.mode == RPD_FLIP_MODE)
@@ -265,4 +266,4 @@
else if(our_rpd.mode == RPD_DELETE_MODE)
our_rpd.delete_single_pipe(user, src)
else
- ..()
+ return ..()