From 1bff8f5da99d80451c7e49891561dbd91a46c01e Mon Sep 17 00:00:00 2001 From: CRUNCH <143041327+Fordoxia@users.noreply.github.com> Date: Mon, 6 Oct 2025 16:29:37 +0100 Subject: [PATCH] RPD attack chain migration (#30574) --- code/game/objects/items/rpd.dm | 89 ++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 36 deletions(-) diff --git a/code/game/objects/items/rpd.dm b/code/game/objects/items/rpd.dm index 01a00d3287d..85e24bf46d7 100644 --- a/code/game/objects/items/rpd.dm +++ b/code/game/objects/items/rpd.dm @@ -22,16 +22,26 @@ armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 100, ACID = 50) resistance_flags = FIRE_PROOF origin_tech = "engineering=4;materials=2" + new_attack_chain = TRUE var/datum/effect_system/spark_spread/spark_system var/lastused - var/iconrotation = 0 //Used to orient icons and pipes - var/mode = RPD_ATMOS_MODE //Disposals, atmospherics, etc. - var/pipe_category = RPD_ATMOS_PIPING //For TGUI menus, this is a subtype of pipes e.g. scrubbers pipes, devices - var/whatpipe = PIPE_SIMPLE_STRAIGHT //What kind of atmos pipe is it? - var/whatdpipe = PIPE_DISPOSALS_STRAIGHT //What kind of disposals pipe is it? + /// Used to orient icons and pipes. + var/iconrotation = 0 + /// Disposals, atmospherics, etc. + var/mode = RPD_ATMOS_MODE + /// For TGUI menus, this is a subtype of pipes e.g. scrubbers pipes, devices. + var/pipe_category = RPD_ATMOS_PIPING + /// What kind of atmos pipe are we trying to lay? + var/whatpipe = PIPE_SIMPLE_STRAIGHT + /// What kind of disposals pipe are we trying to lay? + var/whatdpipe = PIPE_DISPOSALS_STRAIGHT + /// What kind of transit tube are we trying to lay? var/whatttube = PIPE_TRANSIT_TUBE + /// Cooldown on RPD use. var/spawndelay = RPD_COOLDOWN_TIME + /// Time taken to drill a borehole before the pipe can be laid. var/walldelay = RPD_WALLBUILD_TIME + /// Can this RPD lay pipe on non-adjacent turfs? var/ranged = FALSE var/primary_sound = 'sound/machines/click.ogg' var/alt_sound = null @@ -209,7 +219,9 @@ return // TGUI stuff -/obj/item/rpd/attack_self__legacy__attackchain(mob/user) +/obj/item/rpd/activate_self(mob/user) + if(..()) + return ui_interact(user) /obj/item/rpd/ui_state(mob/user) @@ -303,24 +315,39 @@ else return //Either nothing was selected, or an invalid mode was selected to_chat(user, "You set [src]'s mode.") + +/obj/item/rpd/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(!ranged) + return NONE + + if(handle_atom_interaction(target, user, ranged)) + return ITEM_INTERACT_COMPLETE -/obj/item/rpd/afterattack__legacy__attackchain(atom/target, mob/user, proximity) - ..() + return NONE + +/obj/item/rpd/interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(handle_atom_interaction(target, user, ranged)) + return ITEM_INTERACT_COMPLETE + + return NONE + +/obj/item/rpd/proc/handle_atom_interaction(atom/target, mob/living/user, ranged) if(isstorage(target)) var/obj/item/storage/S = target if(!S.can_be_inserted(src, stop_messages = TRUE)) - return - if(loc != user) - return - if(!proximity && !ranged) - return + return ITEM_INTERACT_COMPLETE + return NONE + if(world.time < lastused + spawndelay) - return + return ITEM_INTERACT_COMPLETE + + // Use as melee weapon + if(user.a_intent == INTENT_HARM) + return NONE var/turf/T = get_turf(target) - if(!T) - return + return ITEM_INTERACT_COMPLETE if(target != T) // We only check the rpd_act of the target if it isn't the turf, because otherwise @@ -329,42 +356,32 @@ // 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. if(ranged) - user.Beam(T, icon_state="rped_upgrade", icon='icons/effects/effects.dmi', time=5) - return + user.Beam(T, icon_state = "rped_upgrade", icon = 'icons/effects/effects.dmi', time = 0.5 SECONDS) + return ITEM_INTERACT_COMPLETE // 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()) to_chat(user, "[O] blocks [src]!") - return + return ITEM_INTERACT_COMPLETE // 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(ranged) //woosh beam! 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)") + 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, "ERROR: \The [T] is out of [src]'s range!") - return + to_chat(user, "ERROR: \The [T] is out of [src]'s range!") + return ITEM_INTERACT_COMPLETE if(!(user in hearers(12, T))) // Checks if user can hear the target turf, cause viewers doesnt work for it. to_chat(user, "[src] needs full visibility to determine the dispensing location.") playsound(src, 'sound/machines/synth_no.ogg', 50, TRUE) - return + return ITEM_INTERACT_COMPLETE + 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__legacy__attackchain(obj/O, mob/living/user) - if(user.a_intent != INTENT_HARM) - if(istype(O, /obj/machinery/atmospherics/pipe)) - return - else if(istype(O, /obj/structure/disposalconstruct)) - return - else if(istype(O, /obj/structure/transit_tube_construction)) - return - - return ..() + return ITEM_INTERACT_COMPLETE #undef RPD_COOLDOWN_TIME #undef RPD_WALLBUILD_TIME