BRPD Auto-wrenching (#26855)

* Modified the RPD auto-wrenching behaviour
* Removed tool requirement for auto-wrenching
* Allowed the BRPD to auto-wrench remotely
* Added a TGUI toggle for auto-wrenching

* Added a Line of Sight check for the BRPD
* Readded missing UI buttons

* Tweaked disposals construction
* Disposals objects can't be anchored if there's floor tiles
* Bins, chutes and outlets now need a constructed trunk to be anchored.

* Changed LoS check, added sounds, stopped station auto-wrench.

* Final touches for the RPD
* Added sounds when wrenching occurs

* tgui bundle

* Consolidated all RPD related sounds to the RPD code

* removed some redundant things I forgot about

* tguibundle

* span classes and tgui bundle

* Applying lewcc's suggestion

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: Toastical <vnndvp@gmail.com>

* applying lewcc's 2nd suggestion

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: Toastical <vnndvp@gmail.com>

* Applying contrabang's suggestions + added marks in pipe.dm

* typos n stuff

* tgui bundle

* Update code/modules/recycling/disposal-construction.dm

Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>

---------

Signed-off-by: Toastical <vnndvp@gmail.com>
Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
This commit is contained in:
Toastical
2024-11-03 13:47:20 +00:00
committed by GitHub
co-authored by Luc DGamerL
parent ba2c42280b
commit 08b74db517
7 changed files with 147 additions and 108 deletions
+6 -8
View File
@@ -1,5 +1,4 @@
//Atmospherics pipes
// MARK: Atmospherics pipes
#define PIPE_SIMPLE_STRAIGHT 0
#define PIPE_SIMPLE_BENT 1
#define PIPE_HE_STRAIGHT 2
@@ -41,8 +40,7 @@
#define PIPE_GAS_SENSOR 98
#define PIPE_METER 99
//Disposals pipes
// MARK: Disposals pipes
#define PIPE_DISPOSALS_STRAIGHT 100
#define PIPE_DISPOSALS_BENT 101
#define PIPE_DISPOSALS_JUNCTION_RIGHT 102
@@ -55,7 +53,7 @@
#define PIPE_DISPOSALS_SORT_RIGHT 109
#define PIPE_DISPOSALS_SORT_LEFT 110
// Transit tubes
// MARK: Transit tubes
#define PIPE_TRANSIT_POD 200
#define PIPE_TRANSIT_TUBE 201
#define PIPE_TRANSIT_TUBE_DIAGONAL 202
@@ -65,8 +63,7 @@
#define PIPE_TRANSIT_TUBE_TERMINUS_DISPENSER 206
#define PIPE_TRANSIT_TUBE_DISPENSER_STATION 207
//RPD stuff
// MARK: RPD stuff
#define RPD_ATMOS_MODE 1
#define RPD_DISPOSALS_MODE 2
#define RPD_ROTATE_MODE 3
@@ -84,8 +81,9 @@
#define PIPETYPE_DISPOSAL 2
#define PIPETYPE_TRANSIT 3
// Connection types
#define RPD_TOOL_SUCCESS (1<<1)
// MARK: Connection types
#define CONNECT_TYPE_NORMAL 1
#define CONNECT_TYPE_SUPPLY 2
#define CONNECT_TYPE_SCRUBBER 3
@@ -341,7 +341,6 @@
/obj/item/pipe/wrench_act(mob/user, obj/item/I)
. = TRUE
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
return
@@ -528,6 +527,7 @@
"<span class='notice'>You fasten [src].</span>",
"<span class='notice'>You hear a ratchet.</span>")
qdel(src) // remove the pipe item
. |= RPD_TOOL_SUCCESS
/obj/item/pipe_meter
name = "meter"
+29 -9
View File
@@ -39,6 +39,7 @@
var/ranged = FALSE
var/primary_sound = 'sound/machines/click.ogg'
var/alt_sound = null
var/auto_wrench_toggle = TRUE
//Lists of things
var/list/mainmenu = list(
@@ -114,8 +115,7 @@
else if(!iconrotation) //If user selected a rotation
P.dir = user.dir
to_chat(user, "<span class='notice'>[src] rapidly dispenses [P]!</span>")
if(istype(user.get_inactive_hand(), /obj/item/wrench) && (user.can_reach(P, user.get_inactive_hand())))
P.wrench_act(user, user.get_inactive_hand())
automatic_wrench_down(user, P)
activate_rpd(TRUE)
/obj/item/rpd/proc/create_disposals_pipe(mob/user, turf/T) //Make a disposals pipe / construct
@@ -127,8 +127,7 @@
if(!iconrotation && whatdpipe != PIPE_DISPOSALS_JUNCTION_RIGHT) //Disposals pipes are in the opposite direction to atmos pipes, so we need to flip them. Junctions don't have this quirk though
P.flip()
to_chat(user, "<span class='notice'>[src] rapidly dispenses [P]!</span>")
if(istype(user.get_inactive_hand(), /obj/item/wrench) && (user.can_reach(P, user.get_inactive_hand())))
P.attackby(user.get_inactive_hand(), user)
automatic_wrench_down(user, P)
activate_rpd(TRUE)
/obj/item/rpd/proc/create_transit_tube(mob/user, turf/dest)
@@ -144,8 +143,7 @@
S.dir = iconrotation ? iconrotation : user.dir
to_chat(user, "<span class='notice'>[src] rapidly dispenses [S]!</span>")
if(istype(user.get_inactive_hand(), /obj/item/wrench) && (user.can_reach(S, user.get_inactive_hand())))
S.wrench_act(user, user.get_inactive_hand())
automatic_wrench_down(user, S)
activate_rpd(TRUE)
/obj/item/rpd/proc/rotate_all_pipes(mob/user, turf/T) //Rotate all pipes on a turf
@@ -195,6 +193,22 @@
QDEL_NULL(P)
activate_rpd()
/**
* Automatically wrenches down an atmos device/pipe if the auto_wrench_toggle is TRUE.
* Arguments:
* * user - the user of the RPD.
* * target - the pipe/device/tube being placed by the RPD.
*/
/obj/item/rpd/proc/automatic_wrench_down(mob/living/user, obj/item/target)
if(!auto_wrench_toggle)
return
if(mode == RPD_TRANSIT_MODE)
if(target.screwdriver_act(user, src) & RPD_TOOL_SUCCESS)
playsound(src, 'sound/items/impactwrench.ogg', 50, TRUE)
return
if(target.wrench_act(user, src) & RPD_TOOL_SUCCESS)
playsound(src, 'sound/items/impactwrench.ogg', 50, TRUE)
return
// TGUI stuff
/obj/item/rpd/attack_self(mob/user)
@@ -228,6 +242,7 @@
data["whatdpipe"] = whatdpipe
data["whatpipe"] = whatpipe
data["whatttube"] = whatttube
data["auto_wrench_toggle"] = auto_wrench_toggle
return data
/obj/item/rpd/ui_act(action, list/params)
@@ -249,6 +264,8 @@
pipe_category = isnum(params[action]) ? params[action] : text2num(params[action])
if("mode")
mode = isnum(params[action]) ? params[action] : text2num(params[action])
if("auto_wrench_toggle")
auto_wrench_toggle = !auto_wrench_toggle
//RPD radial menu
/obj/item/rpd/proc/check_menu(mob/living/user)
@@ -325,14 +342,17 @@
// If we get here, then we're effectively acting on the turf, probably placing a pipe.
if(ranged) //woosh beam if bluespaced at a distance
if(get_dist(src, T) <= (user.client.maxview() + 2))\
user.Beam(T, icon_state = "rped_upgrade", icon = 'icons/effects/effects.dmi', time = 5)
else
if(get_dist(src, T) >= (user.client.maxview() + 2))
message_admins("\[EXPLOIT] [key_name_admin(user)] attempted to place pipes with a BRPD via a camera console. (Attempted range exploit)")
playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE)
to_chat(user, "<span class='notice'>ERROR: \The [T] is out of [src]'s range!</span>")
return
if(!(user in viewers(12, T))) // Checks if the user can see the target turf
to_chat(user, "<span class='warning'>[src] needs full visibility to determine the dispensing location.</span>")
playsound(src, 'sound/machines/synth_no.ogg', 50, TRUE)
return
user.Beam(T, icon_state = "rped_upgrade", icon = 'icons/effects/effects.dmi', time = 0.5 SECONDS)
T.rpd_act(user, src)
/obj/item/rpd/attack_obj(obj/O, mob/living/user)
@@ -9,6 +9,7 @@
var/installed_type = null
var/installed_type_flipped = null
var/flipped = FALSE
var/is_station = FALSE
/obj/structure/transit_tube_construction/proc/rotate()
setDir(turn(dir, -90))
@@ -43,20 +44,25 @@
. = TRUE
var/turf/T = get_turf(src)
if(!isfloorturf(T) && !isspaceturf(T))
to_chat(user, "<span class='notice'>You cannot install [src] here.</span>")
to_chat(user, "<span class='warning'>You cannot install [src] here.</span>")
return
for(var/obj/turf_contents in T)
// It's okay for tube parts to be installed over existing pods.
if(!istype(turf_contents, /obj/structure/transit_tube_pod) && turf_contents.density)
to_chat(user, "<span class='notice'>There is not enough space to install [src] here.</span>")
to_chat(user, "<span class='warning'>There is not enough space to install [src] here.</span>")
return
if(is_station && !user.can_reach(src))
to_chat(user, "<span class='warning'>[src] must be installed manually.</span>")
return
var/install_type = flipped ? installed_type_flipped : installed_type
var/atom/installed = new install_type(T)
installed.dir = dir
user.visible_message("<span class='notice'>[user] installs [src].</span>")
I.play_tool_sound(src, I.tool_volume)
qdel(src)
. |= RPD_TOOL_SUCCESS
/obj/structure/transit_tube_construction/wrench_act(mob/living/user, obj/item/I)
. = TRUE
@@ -93,7 +99,7 @@
qdel(src)
to_chat(user, "<span class='notice'>[src] can only be installed in a transit tube!</span>")
to_chat(user, "<span class='warning'>[src] can only be installed in a transit tube!</span>")
/obj/structure/transit_tube_construction/straight
installed_type = /obj/structure/transit_tube
@@ -121,14 +127,17 @@
installed_type = /obj/structure/transit_tube/station
base_icon_state = "transit_station"
icon_state = "transit_station"
is_station = TRUE
/obj/structure/transit_tube_construction/terminus/dispenser
installed_type = /obj/structure/transit_tube/station/dispenser/reverse
installed_type_flipped = /obj/structure/transit_tube/station/dispenser/reverse/flipped
base_icon_state = "transit_dispenser_terminus"
icon_state = "transit_dispenser_terminus"
is_station = TRUE
/obj/structure/transit_tube_construction/station/dispenser
installed_type = /obj/structure/transit_tube/station/dispenser
base_icon_state = "transit_dispenser_station"
icon_state = "transit_dispenser_station"
is_station = TRUE
+28 -25
View File
@@ -138,27 +138,31 @@
// weldingtool: convert to real pipe
/obj/structure/disposalconstruct/wrench_act(mob/living/user, obj/item/I)
. = TRUE
var/ispipe = is_pipe()
var/nicetype = get_nice_name()
if(anchored)
anchored = FALSE
if(ispipe)
level = 2
density = FALSE
else
density = TRUE
to_chat(user, "You detach the [nicetype] from the underfloor.")
var/turf/T = get_turf(src)
if(T.intact)
to_chat(user, "<span class='warning'>You can only attach the [nicetype] if the floor plating is removed.</span>")
return
if(ispipe)
anchored = !anchored
level = anchored ? 1 : 2
to_chat(user, anchored ? "<span class='notice'>You attach the [nicetype] to the underfloor.</span>" : "<span class='notice'>You detach the [nicetype] from the underfloor.</span>")
else
anchored = TRUE
if(ispipe)
level = 1 // We don't want disposal bins to disappear under the floors
density = FALSE
else
density = TRUE // We don't want disposal bins or outlets to go density 0
to_chat(user, "You attach the [nicetype] to the underfloor.")
var/obj/structure/disposalpipe/trunk/CT = locate() in T //For disposal bins, chutes, outlets.
if(!CT)
to_chat(user, "<span class='warning'>The [nicetype] requires a trunk underneath it in order to be anchored.</span>")
return
anchored = !anchored
density = anchored
to_chat(user, anchored ? "<span class='notice'>You attach the [nicetype] to the trunk.</span>" : "<span class='notice'>You detach the [nicetype] from the trunk.</span>")
I.play_tool_sound(src, I.tool_volume)
update()
return TRUE
. |= RPD_TOOL_SUCCESS
/obj/structure/disposalconstruct/proc/is_pipe()
switch(ptype)
@@ -186,18 +190,17 @@
/obj/structure/disposalconstruct/attackby(obj/item/I, mob/user, params)
var/nicetype = get_nice_name()
var/ispipe = is_pipe() // Indicates if we should change the level of this pipe
var/turf/T = get_turf(src)
add_fingerprint(user)
var/turf/T = src.loc
if(T.intact)
to_chat(user, "You can only attach the [nicetype] if the floor plating is removed.")
to_chat(user, "<span class='warning'>You can only attach the [nicetype] if the floor plating is removed.</span>")
return
if(ptype in list(PIPE_DISPOSALS_BIN, PIPE_DISPOSALS_OUTLET, PIPE_DISPOSALS_CHUTE)) // Disposal or outlet
var/obj/structure/disposalpipe/trunk/CP = locate() in T
if(!CP) // There's no trunk
to_chat(user, "The [nicetype] requires a trunk underneath it in order to work.")
to_chat(user, "<span class='warning'>The [nicetype] requires a trunk underneath it in order to work.</span>")
return
else
for(var/obj/structure/disposalpipe/CP in T)
@@ -207,15 +210,15 @@
if(istype(CP, /obj/structure/disposalpipe/broken))
pdir = CP.dir
if(pdir & dpdir)
to_chat(user, "There is already a [nicetype] at that location.")
to_chat(user, "<span class='warning'>There is already a [nicetype] at that location.</span>")
return
if(istype(I, /obj/item/weldingtool))
if(anchored)
if(I.tool_use_check(user, 0))
to_chat(user, "Welding the [nicetype] in place.")
to_chat(user, "<span class='notice'>You begin welding the [nicetype] in place.</span>")
if(I.use_tool(src, user, 20, volume = I.tool_volume))
to_chat(user, "The [nicetype] has been welded in place!")
to_chat(user, "<span class='notice'>You have welded the [nicetype] in place!</span>")
update() // TODO: Make this neat
if(ispipe) // Pipe
@@ -252,10 +255,10 @@
qdel(src)
return
else
to_chat(user, "You need more welding fuel to complete this task.")
to_chat(user, "<span class='warning'>You need more welding fuel to complete this task.</span>")
return
else
to_chat(user, "You need to attach it to the plating first!")
to_chat(user, "<span class='warning'>You need to attach it to the plating first!</span>")
return
/obj/structure/disposalconstruct/rpd_act(mob/user, obj/item/rpd/our_rpd)
+30 -21
View File
@@ -101,20 +101,11 @@ const AtmosPipeContent = (props, context) => {
<Section fill>
<Grid>
<Grid.Column>
<ActionButtons />
{pipelist
.filter((p) => p.pipe_type === 1 && p.pipe_id === whatpipe && p.orientations !== 1)
.map((p) => (
<Box key={p.pipe_id}>
<Box>
<Button
fluid
textAlign="center"
content="Orient automatically"
selected={iconrotation === 0}
onClick={() => act('iconrotation', { iconrotation: 0 })}
style={{ 'margin-bottom': '5px' }}
/>
</Box>
{p.bendy ? (
<>
<Grid>
@@ -234,7 +225,7 @@ const AtmosPipeContent = (props, context) => {
const DisposalPipeContent = (props, context) => {
const { act, data } = useBackend(context);
const { pipe_category, pipelist, whatdpipe, iconrotation } = data;
const { pipe_category, pipelist, whatdpipe, iconrotation, auto_wrench_toggle } = data;
return (
<Stack.Item grow>
@@ -266,20 +257,11 @@ const DisposalPipeContent = (props, context) => {
<Section fill>
<Grid>
<Grid.Column>
<ActionButtons />
{pipelist
.filter((p) => p.pipe_type === 2 && p.pipe_id === whatdpipe && p.orientations !== 1)
.map((p) => (
<Stack.Item key={p.pipe_id}>
<Box>
<Button
fluid
textAlign="center"
content="Orient automatically"
selected={iconrotation === 0}
onClick={() => act('iconrotation', { iconrotation: 0 })}
style={{ 'margin-bottom': '5px' }}
/>
</Box>
<Grid>
<Grid.Column>
<Button
@@ -341,6 +323,32 @@ const DisposalPipeContent = (props, context) => {
);
};
const ActionButtons = (props, context) => {
const { act, data } = useBackend(context);
const { iconrotation, auto_wrench_toggle } = data;
return (
<Stack mb={1} textAlign="center">
<Stack.Item basis="50%">
<Button
fluid
content="Auto-orientation"
selected={iconrotation === 0}
onClick={() => act('iconrotation', { iconrotation: 0 })}
/>
</Stack.Item>
<Stack.Item basis="50%">
<Button.Checkbox
fluid
checked={auto_wrench_toggle}
content="Auto-anchor"
onClick={() => act('auto_wrench_toggle')}
/>
</Stack.Item>
</Stack>
);
};
const RotatePipeContent = (props, context) => {
return (
<Stack.Item grow>
@@ -424,6 +432,7 @@ const TransitTubeContent = (props, context) => {
<Section fill>
<Grid>
<Grid.Column>
<ActionButtons />
{pipelist
.filter((p) => p.pipe_type === transit_pipe_type && p.pipe_id === whatttube && p.orientations !== 1)
.map((p) => (
File diff suppressed because one or more lines are too long